npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@react-agendfy/core

v1.1.25

Published

Core library for React Agendfy — a flexible calendar and scheduling system for React applications.

Readme

React Agendfy Calendar Component

@react-agendfy/core

React Agendfy is a flexible and customizable calendar component for React applications. It supports various calendar views, drag and drop event management, recurring events, resource filtering, and now with enhanced timezone support and notification functionalities.

Table of Contents

  1. Features
  2. Installation
  3. Usage
  4. Configuration Options (Config Prop)
  5. Events Object Structure
  6. Resources Object Structure
  7. Email Adapter
  8. Localization (i18n)
  9. Calendar Export (ICS Format)
  10. Plugin Support
  11. How to Create a Plugin
  12. Contributing
  13. License

Features

  • Multiple Calendar Views: Supports month, week, day, and list views.
  • Drag & Drop Event Management: Easily move and resize events within the calendar.
  • Recurring Events: Handles events that repeat daily, weekly, monthly, etc., using RRule.
  • Event Resizing: Adjust event durations directly on the calendar (week and day views).
  • Resource Filtering: Filter events by assigned resources.
  • Timezone Support: Comprehensive timezone handling using @date-fns/tz.
  • Event Notifications (Alerts): Configure alerts to remind users of upcoming events.
  • Customizable Configuration: Extensive config prop to tailor the calendar's appearance and behavior.
  • Localization: Basic localization for text elements.
  • Extensible Plugin Architecture: Add new views, themes, data sources, export formats, and more.
  • Resource Display: Visually represent event resources.
  • Tooltips: Informative tooltips for events.
  • Business Hours: Highlight business hours in the calendar view.
  • Event Click and Slot Click Handlers: Callbacks for user interactions.

Installation

npm install @react-agendfy/core

or

yarn add @react-agendfy/core

Ensure you have installed all peer dependencies listed in the peerDependencies section of the package.json.

Usage

Basic Usage

Import the Calendar component and necessary dependencies into your React component: Import the Calendar component and, if needed, the CalendarEvent type.

 import React, { useMemo, useRef, useState, useEffect, useCallback, FC } from 'react';
import { format } from 'date-fns';
import Calendar, { CalendarEvent } from './View/Calendar';
import { ToastProvider } from './Components/Toast/Toast';
import { EmailAdapter } from './types/notification';
 
export class ExampleEmailAdapter implements EmailAdapter {
  async sendEmail(subject: string, body: string, recipient?: string): Promise<void> {
    console.log(`Sending email to ${recipient}: ${subject} - ${body}`);
    return Promise.resolve();
  }
}
import React, { useState } from 'react';
import Calendar, { CalendarEvent } from '@react-agendfy/core';
// Importe os estilos CSS do core
import '@react-agendfy/core/dist/index.css';

const resources = [
  { id: "r1", name: "Conference Room", type: "room" },
  { id: "r2", name: "John Silva", type: "person" },
  { id: "r3", name: "Projector", type: "equipment" },
  { id: "r4", name: "Holidays", type: "equipment" }
];

const initialEvents = [
  { id: "11", title: "March End Report Deadline", start: "2025-03-31T00:00:00.000Z", end: "2025-10-31T23:59:59.000Z", color: "#f44336", isAllDay: true, isMultiDay: true },
  { id: "12", title: "Daily Standup Meeting", start: "2025-10-23T10:00:00.000Z", end: "2025-10-23T10:30:00.000Z", color: "#2196f3", isAllDay: false, isMultiDay: false },
  { id: "13", title: "Annual Planning Session (2026 Budget)", start: "2025-12-15T00:00:00.000Z", end: "2025-12-17T23:59:59.000Z", color: "#673ab7", isAllDay: true, isMultiDay: true },
  { id: "14", title: "Q4 Performance Review", start: "2025-11-05T14:00:00.000Z", end: "2025-11-05T17:00:00.000Z", color: "#4caf50", isAllDay: false, isMultiDay: false },
  { id: "15", title: "Company Holiday Break", start: "2026-01-01T00:00:00.000Z", end: "2026-01-10T23:59:59.000Z", color: "#ffc107", isAllDay: true, isMultiDay: true },
  { id: "16", title: "Project Alpha Code Freeze", start: "2026-02-14T00:00:00.000Z", end: "2026-02-14T23:59:59.000Z", color: "#ff9800", isAllDay: true, isMultiDay: false },
  { id: "17", title: "Technical Workshop - New Framework", start: "2025-11-10T00:00:00.000Z", end: "2025-11-10T23:59:59.000Z", color: "#009688", isAllDay: true, isMultiDay: false },
  { id: "18", title: "Team Lunch Celebration", start: "2025-11-20T12:30:00.000Z", end: "2025-11-20T13:30:00.000Z", color: "#e91e63", isAllDay: false, isMultiDay: false },
  { id: "19", title: "Mandatory Security Training", start: "2026-03-01T00:00:00.000Z", end: "2026-03-01T23:59:59.000Z", color: "#3f51b5", isAllDay: true, isMultiDay: false }
  { 
    id: "1", 
    title: "Team Meeting", 
    start: "2025-10-23T10:00:00.000Z", 
    end: "2025-10-23T10:30:00.000Z", 
    color: "#2196f3" 
  },
];

function App() {
  const calendarRef = useRef<HTMLDivElement>(null);
  const [events, setEvents] = useState<CalendarEvent[]>(() => {
    const storedEvents = localStorage.getItem('calendarEvents');
    return storedEvents ? JSON.parse(storedEvents) : initialEvents;
  });
  const [filteredResources, setFilteredResources] = useState<string[]>([]);
  const [events, setEvents] = useState<CalendarEvent[]>(initialEvents);

  const defaultConfig = {
    timeZone: 'Africa/Lagos',
    defaultView: "week",
    slotDuration: 15,
    slotLabelFormat: "HH:mm",
    slotMin: "08:00",
    slotMax: "23:59",
    lang: 'en',
    today: 'Today',
    monthView: 'Month',
    weekView: 'Week',
    dayView: 'Day',
    listView: 'List',
    all_day: 'All Day',
    clear_filter: 'Clear Filters',
    filter_resources: 'Filter Resources',
    businessHours: {
      enabled: true,
      intervals: [
        { daysOfWeek: [1, 2, 3, 4, 5], startTime: "09:00", endTime: "17:00" }
      ]
    },
    alerts: { enabled: true, thresholdMinutes: 15 },
    export: true,
    calendar_export: 'Export'
  };

  const config = useMemo(() => defaultConfig, []);

  useEffect(() => {
    localStorage.setItem('calendarEvents', JSON.stringify(events));
  }, [events]);

  const handleEventUpdate = useCallback((updatedEvent: CalendarEvent) => {
    console.log("Updated event:", updatedEvent);
    setEvents(prev => prev.map(e => e.id === updatedEvent.id ? updatedEvent : e));
  }, []);

  const handleResizedUpdate = useCallback((updatedEvent: CalendarEvent) => {
    console.log("Resized event:", updatedEvent);
    setEvents(prev => prev.map(e => e.id === updatedEvent.id ? updatedEvent : e));
  }, []);

  const handleEventClick = useCallback((event: CalendarEvent) => {
  const handleEventClick = (event: CalendarEvent) => {
    console.log("Clicked event:", event);
  }, []);

  const handleDayClick = useCallback((dayDate: Date) => {
    console.log("Clicked day:", dayDate);
    alert(`Clicked day: ${format(dayDate, 'dd/MM/yyyy')}`);
  }, []);

  const handleSlotClick = useCallback((slotTime: Date) => {
    console.log("Clicked slot:", slotTime);
    alert(`Clicked slot: ${format(slotTime, 'HH:mm dd/MM/yyyy')}. You can add a new event here.`);
  }, []);

  const handleResourceFilterChange = useCallback((selectedResources: string[]) => {
    setFilteredResources(selectedResources);
  }, []);

  const myEmailAdapter: EmailAdapter = {
    sendEmail: async (subject, body, recipient) => {
      console.log("Sending email:", { subject, body, recipient });
      return Promise.resolve();
    },
  };

  const MyLeftHeaderPlugin: React.FC = () => <button className="react-agenfy-btn">Plugin</button>;

  interface SearchPluginProps {
    onSearch?: (term: string, results: CalendarEvent[]) => void;
    events?: CalendarEvent[];
    className?: string;
  }
  const MyRightHeaderPlugin: React.FC<SearchPluginProps> = ({ onSearch, events = [] }) => {
    const [q, setQ] = useState('');
    useEffect(() => {
      const term = q.trim().toLowerCase();
      const results = term.length === 0 ? [] : events.filter(e => (e.title || '').toLowerCase().includes(term));
      onSearch?.(q, results);
    }, [q, events, onSearch]);

    return (
      <input
        type="search"
        value={q}
        onChange={(e) => setQ(e.target.value)}
        placeholder="Search..."
        className="react-agenfy-search-input"
        aria-label="Search events"
  return (
    <div style={{ height: '100vh' }}>
      <Calendar
        events={events}
        onEventClick={handleEventClick}
      />
    );
  };

  interface CustomViewProps {
    events: CalendarEvent[];
    currentDate: Date;
    config: any;
    onEventClick: (event: CalendarEvent) => void;
  }
  const MyCustomViewComponent: React.FC<CustomViewProps> = ({ events }) => {
    return <div>My Custom View! ({events.length} events)</div>;
  };

  return (
    <ToastProvider>
      <div className="">
        <Calendar
          events={events}
          config={{ ...config }}
          onEventUpdate={handleEventUpdate}
          onEventClick={handleEventClick}
          onDayClick={handleDayClick}
          onSlotClick={handleSlotClick}
          resources={resources}
          onEventResize={handleResizedUpdate}
          filteredResources={filteredResources}
          onResourceFilterChange={handleResourceFilterChange}
          theme="dark"
          emailAdapter={new ExampleEmailAdapter()}
          emailConfig={{ defaultRecipient: "[email protected]" }}
          plugins={[
            darkThemePlugin,
            { location: 'left', type: 'filter', component: MyLeftHeaderPlugin, key: 'left' },
            { location: 'right', type: 'search', component: MyRightHeaderPlugin, props: { className: 'search-input' }, key: 'right' },
            { type: 'view', viewName: 'custom view', component: MyCustomViewComponent, key: 'custom-view-key' },
            { type: 'view', viewName: 'notes', component: MyCustomView, key: 'custom-nota-key' },
           ]}
        />
      </div>
    </ToastProvider>
    </div>
  );
}

const darkThemePlugin = {
  type: 'theme',
  themeName: 'dark',
  key: 'dark-theme',
  cssVariables: {
    '--color-bg-white': '#1A202C',
    '--color-bg-gray-50': '#2D3748',
    '--color-bg-gray-100': '#4A5568',
    '--color-border': '#4A5568',
    '--color-border-gray-300': '#2D3748',
    '--color-text-gray-800': '#FFFFFF',
    '--color-text-gray-700': '#F7FAFC',
    '--color-text-gray-500': '#E2E8F0',
    '--btn-bg': '#4A5568',
    '--btn-hover-bg': '#718096',
  }
};

const MyCustomView: FC<CustomViewProps> = ({ events, currentDate, config, onEventClick }) => (
  <div>hello </div>
);

export default App;

Calendar Views

React Agendfy supports four main calendar views, configurable via the defaultView option in the config prop:

  • Month View: Displays a traditional month grid. Set defaultView: "month".
  • Week View: Shows a weekly agenda with time slots. Set defaultView: "week".
  • Day View: Focuses on a single day's schedule with time slots. Set defaultView: "day".
  • List View: Presents events in a list format, grouped by day for the current month. Set defaultView: "list".

Users can navigate between views using the view selector in the calendar header.

Event Handling

  • onEventClick(event: Event): Callback function triggered when an event is clicked. Provides the event object as a parameter.
  • onEventUpdate(updatedEvent: Event): Callback function for when an event is dragged and dropped to a new time slot or resized. It is crucial to update your event state with the updatedEvent provided.
  • onEventResize(resizedEvent: Event): Callback function when an event is resized (Week and Day views only). Update your event state with the resizedEvent.
  • onDateRangeSelect({ start: string, end: string, isMultiDay: boolean }): Callback triggered when a user selects a date range by clicking and dragging on the calendar grid (Month and Week views). Useful for creating new events.

Drag and Drop

  • Enable Drag and Drop: Drag and drop functionality is enabled by default when you provide the onEventUpdate and onEventResize callbacks.
  • Moving Events: Drag events to different time slots in week and day views to reschedule them. The onEventUpdate callback is triggered after a successful drag and drop operation.
  • Resizing Events: Resize events vertically in week and day views by dragging the bottom border of the event. The onEventResize callback is triggered upon resizing completion.

Recurring Events

React Agendfy supports recurring events using the RRule standard. Define recurrence rules in your event objects using the recurrence property.

{
    id: "4",
    title: "Daily Standup",
    start: "2025-03-01T10:00:00.000Z",
    end: "2025-03-01T12:15:00.000Z",
    color: "#4caf50",
    recurrence: "FREQ=WEEKLY;INTERVAL=1;COUNT=10", // Example: Weekly for 10 occurrences
    isAllDay: false,
    isMultiDay: false,
},

The expandRecurringEvents utility function (exported from the library) can be used to expand recurring events into individual event instances for a given date range.

Resource Filtering

  • Resource Definition: Define resources as an array of objects with id, name, and type properties. Pass this array to the resources prop of the Calendar component.
  • Event Resources: Assign resources to events using the resources property of the event object.
  • Filtering Interface: The calendar provides a built-in UI to filter events by resource type.
  • onResourceFilterChange(selectedResources: string[]): Callback function that is called when the resource filter changes, providing an array of selected resource IDs.
  • filteredResources: string[]: Prop to control the resource filter externally. Pass an array of resource IDs to filter events displayed on the calendar.

Time Zones

React Agendfy is timezone-aware, leveraging the @date-fns/tz library.

  • Configuration: Set the timezone property in the config prop to your desired timezone (e.g., 'America/Sao_Paulo', 'UTC', 'Africa/Luanda'). Default timezone is 'UTC'.

  • TZDate: Internally, the component uses TZDate objects from @date-fns/tz to handle dates and times, ensuring all calculations and displays are timezone-consistent.

  • Event Dates: Event start and end properties should be provided in ISO 8601 format (e.g., "2025-07-20T10:00:00.000Z"). While the component processes dates internally as TZDate objects with the configured timezone, it's recommended to store and manage event dates in UTC or a consistent timezone format to avoid ambiguity.

  • Example Config:

    const config = useMemo(() => ({
        timezone: 'Africa/Luanda', // Example: Set timezone to Luanda
        // ... other configurations
    }), []);

    By configuring the timezone, the calendar will display times and perform date calculations according to the specified timezone, ensuring accurate representation for users in different time zones.

Notifications (Alerts)

React Agendfy allows you to configure notifications or alerts for events using the alertBefore property in the event object. To enable email notifications, you need to implement and provide an EmailAdapter to the Calendar component.

  • alertBefore Property: In your event object, add alertBefore property to specify a reminder in minutes before the event starts.

    {
        id: "6",
        title: "Team Lunch",
        start: "2025-03-05T14:00:00.000Z",
        end: "2025-03-05T15:00:00.000Z",
        color: "#ffc107",
        isAllDay": false,
        isMultiDay": false,
        alertBefore: 15, // Alert 15 minutes before event start
    }
  • EmailAdapter Interface: Define an adapter object that conforms to the EmailAdapter interface:

    interface EmailAdapter {
        sendEmail: (subject: string, body: string, recipient: string) => Promise<void>;
    }
  • Implementing EmailAdapter: Create an object that implements the EmailAdapter interface with your email sending logic. Example using console.log for demonstration:

    const myEmailAdapter = {
        sendEmail: async (subject, body, recipient) => {
            console.log("Sending email:", { subject, body, recipient });
            // Implement your actual email sending logic here (e.g., using an API, SMTP, etc.)
            return Promise.resolve();
        },
    };
  • emailAdapter Prop: Pass your implemented EmailAdapter to the Calendar component via the emailAdapter prop:

    <Calendar
        // ...other props
        emailAdapter={myEmailAdapter}
    />
  • emailConfig Prop: Configure email settings using the emailConfig prop:

    <Calendar
        // ...other props
        emailAdapter={myEmailAdapter}
        emailConfig={{ defaultRecipient: "[email address removed]" }} // Default recipient for notifications
    />
    • defaultRecipient: (Optional) A default email address to be used if the event or user does not specify a recipient.

Notification Behavior:

  • When an event with alertBefore is created or updated, and the current time approaches the alert time, the calendar component (specifically with a backend implementation for processing alerts) will trigger the sendEmail method of the provided EmailAdapter.
  • The email will be sent to the specified recipient (if available in event.recipient or using emailConfig.defaultRecipient as fallback).
  • The email subject and body are automatically generated by the calendar component, including event details.
  • Note: The current component provides the front-end configuration and email sending interface. You will need to implement the backend logic that periodically checks for events nearing their alert times and triggers the notification sending mechanism. This backend logic is outside the scope of this React component.

Configuration Options (Config Prop)

The config prop is a JavaScript object that allows you to customize various aspects of the calendar. Below are the available configuration options:

| Option | Type | Default Value | Description | | ------------------ | ------- | ----------------- | --------------------------------------------------------------------------- | | timezone | string| 'UTC' | Sets the timezone for the calendar. Uses IANA timezone names (e.g., 'America/Sao_Paulo', 'Africa/Luanda'). | | defaultView | string| 'week' | Initial calendar view to display ('month', 'week', 'day', 'list'). | | slotDuration | number| 30 | Duration of time slots in minutes (Day and Week views). | | slotLabelFormat | string| 'HH:mm' | Format for time slot labels (uses date-fns format strings). | | slotMin | string| '00:00' | Start time for the Day and Week views. | | slotMax | string| '23:59' | End time for the Day and Week views. | | lang | string| 'en' | Language code for localization (currently supports basic text elements). | | today | string| 'Today' | Text for the "Today" button. | | monthView | string| 'Month' | Text for the Month view button. | | weekView | string| 'Week' | Text for the Week view button. | | dayView | string| 'Day' | Text for the Day view button. | | listView | string| 'List' | Text for the List view button. | | all_day | string| 'All Day' | Text for "All Day" events. | | clear_filter | string| 'Clear Filters' | Text for the "Clear Filters" button in resource filter. | | filter_resources | string| 'Filter' | Text for the "Filter" button in resource filter. | | businessHours | object| undefined | Configuration object for business hours highlighting (see below). |

Business Hours Configuration (businessHours in config)

To highlight business hours in the week and day views, use the businessHours config option. It accepts an object with the following structure:

businessHours: {
    enabled: boolean; // Enables or disables the feature
    intervals: {
        daysOfWeek: number[]; // Array of days (0=Sun, 1=Mon, ..., 6=Sat)
        startTime: string;    // Start time in "HH:mm" format
        endTime: string;      // End time in "HH:mm" format
    }[];
}

Example:

const config = useMemo(() => ({
    timezone: 'UTC',
    defaultView: "week",
    slotDuration: 30,
    businessHours: {
        start: 9, // 9 AM
        end: 18,  // 6 PM
        daysOfWeek: [1, 2, 3, 4, 5], // Monday to Friday (optional, defaults to all days if omitted)
    },
    // ... other configurations
}), []);

Events Object Structure

The events prop expects an array of event objects. Each event object should have the following properties:

| Property | Type | Required | Description | | -------------------- | ------------------ | -------- | ------------------------------------------------------------------------------------------------- | | id | string | number| Yes | Unique identifier for the event. | | title | string | Yes | Title of the event, displayed on the calendar. | | start | string | Yes | Start date and time of the event in ISO 8601 format (e.g., "2025-07-20T10:00:00.000Z"). | | end | string | Yes | End date and time of the event in ISO 8601 format (e.g., "2025-07-20T12:00:00.000Z"). | | color | string | No | Background color for the event (e.g., "#3490dc", "red"). | | isAllDay | boolean | No | Indicates if the event is an all-day event. Default is false. | | isMultiDay | boolean | No | Indicates if the event spans multiple days. Default is false. | | recurrence | string | No | RRule string for recurring events. | | resources | array | No | Array of resource objects assigned to the event (see Resources Object Structure). | | alertBefore | number | No | Reminder time in minutes before the event start (for email notifications, requires EmailAdapter). | | [key: string] | any | No | Allows adding any other custom properties to the event object. |

Resources Object Structure

The resources prop in the main Calendar component expects an array of resource objects. The resources property in the event object also uses the same structure. Each resource object should have:

| Property | Type | Required | Description | | ---------- | -------- | -------- | --------------------------------------------------- | | id | string | Yes | Unique identifier for the resource. | | name | string | Yes | Display name of the resource. | | type | string | Yes | Type or category of the resource (e.g., "room", "person", "equipment"). | | [key: string]| any | No | Allows adding any other custom properties. |

Email Adapter

To enable email notifications, you need to provide an EmailAdapter object to the emailAdapter prop of the Calendar component.

Interface:

interface EmailAdapter {
    sendEmail: (subject: string, body: string, recipient: string) => Promise<void>;
}

Implementation Example:

const myEmailAdapter = {
    sendEmail: async (subject, body, recipient) => {
        console.log("Sending email:", { subject, body, recipient });
        // Implement your email sending logic here
        return Promise.resolve();
    },
};

Pass this adapter to the Calendar component:

<Calendar
    // ...other props
    emailAdapter={myEmailAdapter}
/>

Localization (i18n)

Basic localization is supported for calendar text elements via the config prop. You can customize text for buttons and labels by setting the following properties in the config object to your desired language:

  • today
  • monthView
  • weekView
  • dayView
  • listView
  • all_day
  • clear_filter
  • filter_resources
  • lang: Set the lang property to a language code (e.g., 'pt' for Portuguese, 'en' for English) to apply basic localization. Currently, only text element translations need to be manually provided in the config.

Example (Portuguese Localization):

const config = useMemo(() => ({
    timezone: 'UTC',
    lang: 'pt',
    defaultView: "week",
    slotDuration: 30,
    today: 'Hoje',
    monthView: 'Mês',
    weekView: 'Semana',
    dayView: 'Dia',
    listView: 'Lista',
    all_day: 'Dia Inteiro',
    clear_filter: 'Limpar Filtro',
    filter_resources: 'Filtrar Recursos',
}), []);

Calendar Export (ICS Format)

The calendar component also includes built-in support for exporting calendar events in the widely compatible ICS (iCalendar) format. This feature allows users to easily download their calendar data and import it into other calendar applications such as Google Calendar, Outlook Calendar, Apple Calendar, and more. The export functionality can typically be triggered via a button or option in the calendar header.

Plugin Support

The calendar component also includes built-in support for exporting calendar events in the widely compatible ICS (iCalendar) format. This feature allows users to easily download their calendar data and import it into other calendar applications such as Google Calendar, Outlook Calendar, Apple Calendar, and more. The export functionality can typically be triggered via a button or option in the calendar header.

By default, the button for exporting the calendar is enabled (export: true in the configuration). You can customize the text displayed on this button by changing the value of the calendar_export attribute in the calendar's configuration object. For example, setting calendar_export: "Download Calendar" would change the button's text to "Download Calendar".

Plugin Types

Here are the available plugin types:

1. ViewPlugin

Adds a new custom view to the calendar.

  • type: 'view'
  • viewName: string: A unique name for the view (e.g., 'gantt').
  • component: FC<any>: The React component that renders the view.
  • props?: { label?: string }: The label for the view's button in the header.

Example:

{
  type: 'view',
  viewName: 'my-agenda',
  component: MyAgendaViewComponent,
  key: 'agenda-plugin',
  props: { label: 'My Agenda' }
}

2. HeaderControlPlugin

Adds UI controls (like filters or search bars) to the calendar header.

  • type: 'filter' | 'search'
  • location: 'header': Specifies integration into the header.
  • component: FC<any>: The React component for the control. It receives callbacks like onFilterChange or onSearch.

Example:

{
  type: 'search',
  location: 'header',
  component: MySearchComponent,
  key: 'search-plugin'
}

3. DataSourcePlugin

Integrates external data sources to fetch events.

  • type: 'data-source'
  • fetchEvents: (startDate, endDate, config) => Promise<EventProps[]>: An async function to load events.

4. EventRenderingPlugin

Customizes the rendering of individual event components.

  • type: 'event-rendering'
  • component: FC<any>: The component to render an event.

5. InteractionPlugin

Adds custom interaction logic, such as a different drag-and-drop implementation.

  • type: 'interaction'
  • viewName: string: The view to which this interaction applies (e.g., 'week').
  • component: FC<any>: A wrapper component that provides the interaction context.

6. ThemePlugin

Applies custom visual themes by dynamically injecting CSS variables.

  • type: 'theme'
  • themeName: string: A unique name for the theme (e.g., 'dark').
  • cssVariables: Record<string, string>: An object of CSS variables to apply.

How to use:

  1. Define a ThemePlugin with your custom colors.
  2. Pass the plugin to the <Calendar> component.
  3. Activate the theme by setting the theme prop on <Calendar> to the themeName you defined.

Example:

// 1. Define the dark theme plugin
const darkThemePlugin = {
  type: 'theme',
  themeName: 'dark',
  key: 'dark-theme',
  cssVariables: {
    '--color-bg-white': '#1A202C',           // Fundo principal (ex: cinza escuro)
    '--color-bg-gray-50': '#2D3748',         // Fundo secundário (ex: para cabeçalhos de tabela)
    '--color-bg-gray-100': '#4A5568',        // Fundo de elementos menores (ex: contador de eventos)
    '--color-border': '#4A5568',             // Cor da borda principal
    '--color-border-gray-300': '#2D3748',    // Cor da borda para elementos como all-day-column
    '--color-text-gray-800': '#FFFFFF',     // Texto principal (branco)
    '--color-text-gray-700': '#F7FAFC',     // Texto secundário (quase branco)
    '--color-text-gray-500': '#E2E8F0',     // Texto terciário (cinza claro)
    '--btn-bg': '#4A5568',                   // Fundo do botão
    '--btn-hover-bg': '#718096',             // Fundo do botão em hover
  }
};

// 2. Pass it to the Calendar
<Calendar
  plugins={[darkThemePlugin]}
  theme="dark" // 3. Activate the theme
  // ... other props
/>

7. ExportPlugin

Adds new formats for exporting events.

  • type: 'export'
  • formatName: string: The internal name of the format (e.g., 'pdf').
  • label: string: The label for the export menu item.
  • exportFunction: (events, config) => string | Promise<string>: A function that returns the file content.
  • mimeType: string: The file's MIME type.
  • fileExtension: string: The file's extension.

8. CustomFilterPlugin

Applies custom event filtering logic that can be controlled by UI components anywhere in the application.

  • type: 'custom-filter'
  • filterName: string: A unique name for the filter.
  • applyFilter: (events, config, filterValue) => EventProps[]: A function that applies the filter logic.
  • component?: FC<any>: An optional UI component to control the filter's value.

Plugin Structure

Plugins are passed to the Calendar component via the plugins prop as an array of objects. Each plugin object should have at least a type property and may include other properties depending on the plugin type:

  • type: (Required) A string indicating the type of the plugin (e.g., 'header', 'view', 'filter', 'search', 'dataSource').
  • location: (For header plugins) A string specifying the location in the header: 'left' or 'right'.
  • viewName: (For view plugins) A unique string identifying the custom view.
  • component: (Optional) A React component (functional or class) that renders the plugin's UI or functionality. For dataSource plugins, this might handle configuration or initialization.
  • props: (Optional) An object containing additional props that will be passed down to the plugin's component.
  • key: (Optional) A unique key for the plugin, useful for React's rendering optimization.

Usage

To use plugins, define them in an array and pass them to the plugins prop of the <Calendar> component.

import Calendar from '@react-agendfy/core';
import { CalendarPlugin } from '@react-agendfy/core/dist/types'; // Adjust path as needed

// 1. Define a custom view component
const MyAgendaView = ({ events }) => <div>{events.length} events in my agenda.</div>;

// 2. Define an export function
const exportToExcel = async (events) => { /* ... logic ... */ return 'excel-data'; };

const App = () => {
  const myPlugins: CalendarPlugin[] = [
    {
      type: 'view',
      viewName: 'my-agenda',
      component: MyAgendaView,
      key: 'my-agenda-plugin',
      props: { label: 'My Agenda' }
    },
    {
      type: 'export',
      formatName: 'excel',
      label: 'Export to Excel',
      exportFunction: exportToExcel,
      mimeType: 'application/vnd.ms-excel',
      fileExtension: 'xls',
      key: 'excel-export-plugin'
    }
  ];

  return (
    <Calendar
      // ... other Calendar props
      events={...}
      plugins={myPlugins}
    />
  );
};

Contributing

Contributions are welcome! Please see the CONTRIBUTING.md file for guidelines on how to contribute to this project.

License

MIT