PHPackages                             adultdate/filament-calendar - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. adultdate/filament-calendar

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

adultdate/filament-calendar
===========================

Adds support for vkurko/calendar to Filament PHP.

2.1.1(5mo ago)00MITPHPPHP ^8.1|^8.2

Since Jul 15Pushed 4mo agoCompare

[ Source](https://github.com/adultdate/filament-calendar)[ Packagist](https://packagist.org/packages/adultdate/filament-calendar)[ Docs](https://github.com/GuavaCZ/calendar)[ GitHub Sponsors](https://github.com/GuavaCZ)[ RSS](/packages/adultdate-filament-calendar/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (14)Versions (38)Used By (0)

[![filament-calendar Banner](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/banner.jpg)](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/banner.jpg)

Adds support for vkurko/filament-calendar to Filament PHP.
==========================================================

[](#adds-support-for-vkurkofilament-calendar-to-filament-php)

[![Latest Version on Packagist](https://camo.githubusercontent.com/f91078a4ce175fc3959cfbc402c5b419ca06ee6f3105add4b8193c2610e3fe67/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6164756c74646174652f63616c656e6461722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/adultdate/calendar)[![GitHub Tests Action Status](https://camo.githubusercontent.com/78a79d8699dfce31abff577956a82b5746af9af777d2a3d30ca213a51046e223/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6164756c74646174652f66696c616d656e742d63616c656e6461722f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/GuavaCZ/filament-calendar/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/63d57ff185a01170eb9d344020ce6123cd0d55bb623ab0d223d952b67f39e376/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6164756c74646174652f66696c616d656e742d63616c656e6461722f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/GuavaCZ/filament-calendar/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/c8d74292ca879e38916299c7d07e88d71d39efb1b3457fe85743c95a56e2542b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6164756c74646174652f66696c616d656e742d63616c656e6461722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/adultdate/filament-calendar)

Note

You are viewing the documentation for adultdate/filament-calendar v2, which supports only filament v4. For filament v3, please check adultdate/filament-calendar v1 here.

This package adds support for [vkurko/filament-calendar](https://github.com/vkurko/filament-calendar) (free, open-source alternative to FullCalendar) to your FilamentPHP panels.

It allows you to create a widget with a filament-calendar with support for **multiple** models and even resources you can group your events into. For example, you could have lessons (events) that are held in different rooms (resources).

Showcase
--------

[](#showcase)

[![Showcase 01](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/showcase_01.png)](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/showcase_01.png)[![Showcase 02](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/showcase_02.png)](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/showcase_02.png)

    Screen.Recording.2025-08-18.at.18.39.38.mov        Screen.Recording.2024-07-15.at.9.31.47.mp4    [![Resources Screenshot 01](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/resources_screenshot_01.png)](https://github.com/GuavaCZ/filament-calendar/raw/main/docs/images/resources_screenshot_01.png)

    context\_menu\_preview.mp4        context\_menu\_preview\_2.mp4        no\_events\_context\_menu.mp4    Support us
----------

[](#support-us)

Your support is key to the continual advancement of our plugin. We appreciate every user who has contributed to our journey so far.

While our plugin is available for all to use, if you are utilizing it for commercial purposes and believe it adds significant value to your business, we kindly ask you to consider supporting us through GitHub Sponsors. This sponsorship will assist us in continuous development and maintenance to keep our plugin robust and up-to-date. Any amount you contribute will greatly help towards reaching our goals. Join us in making this plugin even better and driving further innovation.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require adultdate/filament-calendar
```

Make sure to publish the package assets using:

```
php artisan filament:assets
```

Finally, make sure you have a **custom filament theme** (read [here](https://filamentphp.com/docs/4.x/styling/overview#creating-a-custom-theme) how to create one) and add the following to your **theme.css** file:

This ensures that the CSS is properly built:

```
@source '../../../../vendor/adultdate/filament-calendar/resources/**/*';
```

This is optional but highly recommended as it will apply styles to better fit with the (default) filament theme:

```
@import '../../../../vendor/adultdate/filament-calendar/resources/css/theme.css';
```

The paths might be a little bit different if your theme.css is located in a non-standard path. Adjust accordingly.

Usage
-----

[](#usage)

Creating the filament-calendar Widget
=====================================

[](#creating-the-filament-calendar-widget)

First you need to create a custom widget and extend the `CalendarWidget` class. Make sure to remove the `view` property from the generated widget class!

Either use the artisan command or simply create an empty class and extend `CalendarWidget`:

```
php artisan make:filament-widget
```

The widget class should look like this:

```
use \Guava\Calendar\Filament\CalendarWidget;

class MyCalendarWidget extends CalendarWidget
{
}
```

Add the widget like a regular widget to any filament page you like, such as your `Dashboard`.

Congrats! You now have a working filament-calendar in filament!

Customizing the filament-calendar view
--------------------------------------

[](#customizing-the-filament-calendar-view)

By default, we show the `DayGridMonth` view. You can customize the view by overriding the `calendarView` property on the widget class:

```
use Guava\Calendar\Enums\CalendarViewType;

protected CalendarViewType $calendarView = CalendarViewType::ResourceTimeGridWeek;
```

The `CalendarViewType` enum contains all available views that you can use.

Adding events
-------------

[](#adding-events)

You have probably noticed that your filament-calendar is still empty.

To add events, override the `getEvents` method, described in more detail below.

```
protected function getEvents(FetchInfo $info): Collection | array | Builder {}
```

FetchInfo is a ValueObject we provide which type hints all parameters that are made available to you. This helps you scope the query to only retrieve models which are visible in the view.

To learn more about FetchInfo and other Value Objects, please refer to the Value Object documentation.

There are two distinct ways on how to provide Events to the filament-calendar. Which way you use depends on your personal preference and the source of your events.

### 1. From Eloquent

[](#1-from-eloquent)

Important

Make sure that the Model class implements `Eventable`. Without it we are not able to map your model into a filament-calendar event.

For more information, please refer to the [Calendar Events section](#filament-calendar-events).

In the majority of cases, you will most likely want to display your eloquent models as events inside the filament-calendar.

The easiest way to do that is to just return your Eloquent Query, and we will handle the rest.

```
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Guava\Calendar\ValueObjects\FetchInfo;

protected function getEvents(FetchInfo $info): Collection | array | Builder
{
    // The simplest way:
    return Foo::query();

    // You probably want to query only visible events:
    return Foo::query()
        ->whereDate('ends_at', '>=', $info->start)
        ->whereDate('starts_at', 'styles([
    'color: red' => true,            // Applies the style if the condition (true) is met
    'background-color' => '#ffff00', // Directly applies the background color
    'font-size: 12px'                // Always applies this font size
]);
```

##### Usage Notes:

[](#usage-notes)

- The first format ('color: red' =&gt; true) is useful for conditional styling based on dynamic conditions. For instance, changing the text color based on an filament-calendar's type or status.
- The second format ('background-color' =&gt; '#ffff00') is straightforward for applying styles where the values do not depend on conditions.
- The third format ('font-size: 12px') is used when the style does not require any condition and is always applied to the filament-calendar. This flexibility allows you to easily customize the appearance of events based on dynamic conditions or predefined settings.

#### Customizing Event Classes

[](#customizing-event-classes)

Following the same pattern as with the styles property, it is possible to inject custom classes into the Event element using the `classNames` or `classes` property.

Here's how you can use it:

```
CalendarEvent::make()->classNames([
    'class-1',
    'class-2' => true  // Applies the class if the condition (true) is met
]);
```

##### Usage Notes:

[](#usage-notes-1)

- The second format ('class-2' =&gt; true) is useful for conditional classes based on dynamic conditions.

#### Customizing the display

[](#customizing-the-display)

By default, events are rendered as `blocks`. This is when the display is set to `auto`, which it is by default. You can also change the filament-calendar to be rendered as a background filament-calendar, which then fills the whole date cell. To do so, you can set `display` to `background` on the filament-calendar:

This doesn't always work though, it only works on all day events and in specific views. If the `background` filament-calendar is unsupported, the filament-calendar will not be rendered at all.

```
CalendarEvent::make()
->display('background') // or 'auto'
->displayAuto() // short-hand for ->display('auto')
->displayBackground(); // short-hand for ->display('background')
```

#### Setting the action on click

[](#setting-the-action-on-click)

This sets the action that should be mounted when the filament-calendar is clicked. It can be any name of a filament action you defined in your widget, such as `edit` or `view`.

By default, all `CalendarWidget` classes already include a `view` and `edit` action.

```
CalendarEvent::make()->action('edit');
```

#### Set the model and record key

[](#set-the-model-and-record-key)

To mount the action with the correct record, we need to pass the model type and primary key of the record.

The model is also required if you want to display multiple types of events and have each be rendered differently (see customizing filament-calendar content).

```
$record = MyModel::find(1);
// 1. variant
CalendarEvent::make($record);

// 2. variant
CalendarEvent::make()
    ->model($record::class)
    ->key($record->getKey());
```

#### Linking to resources

[](#linking-to-resources)

If you use resources in your filament-calendar, you need to tell your events which resource(s) they belong to.

To do this, pass an array of resource IDs to the event:

```
use Guava\Calendar\ValueObjects\CalendarEvent;
CalendarEvent::make()
    ->resourceId('foo') // Pass a single resource ID, you can repeat this call multiple times
    ->resourceIds(['bar', 'baz']); // Pass multiple resource IDs at once
```

#### Passing custom data

[](#passing-custom-data)

You can pass any custom data to the event that you wish:

```
CalendarEvent::make()
->extendedProp('foo', 'bar')
// or
->extendedProps(['baz' => 'qux', 'quux' => 'corge']);
```

Adding Resources
----------------

[](#adding-resources)

If you configure your filament-calendar to use a `resource` view, you will need to also define which resources to display in the filament-calendar.

Similarly to events, There are two distinct ways on how to provide Resources to the filament-calendar.

### 1. From Eloquent

[](#1-from-eloquent-1)

Important

Make sure that the Model class implements `Resourceable`. Without it, we are not able to map your model into a filament-calendar resource.

For more information, please refer to the [Calendar Resources section](#filament-calendar-resources).

In the majority of cases, you will most likely want to display your eloquent models as resources inside the filament-calendar.

The easiest way to do that is to just return your Eloquent Query, and we will handle the rest.

```
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

public function getResources(): Collection | array| Builder
{
    return [
        Bar::query()
    ];
}
```

### 2. From Array/Collection

[](#2-from-arraycollection-1)

Sometimes, however, you might want to display resources from an API or an array.

To do that, you can return an array or collection of `CalendarResource` objects directly.

```
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Guava\Calendar\ValueObjects\CalendarResource;
use Guava\Calendar\ValueObjects\FetchInfo;

protected function getResources(): Collection | array | Builder
{
    return [
        CalendarResource::make('baz') // This has to be unique ID
            ->title('My resource'),
    ];
}
```

### Link events to resources

[](#link-events-to-resources)

Now we successfully display resources in the filament-calendar, but we still need to add the events to their corresponding resource.

To do this, update your `CalendarEvent` objects (either directly in the `getEvents` method or in your classes implementing `Eventable`, depending on which approach you chose) and include the resource IDs it belongs to.

Please refer to the [Calendar Event: linking to resources section](#linking-to-resources) to learn how to do it.

Calendar Resources
------------------

[](#calendar-resources)

As seen above, the filament-calendar expects `CalendarResource` objects, which are configurable ValueObjects that help you build the required filament-calendar object.

For this purpose, we have a `Resourceable` interface which you can add to **any class** that you want to be able to display as a resource in your calendars.

In most cases, you will add this interface to your **eloquent models**, but you are not limited to it. Feel free to add it to any class you want.

Here is an example:

```
use Guava\Calendar\Contracts\Resourceable;
use Guava\Calendar\ValueObjects\CalendarResource;

class Bar extends Model implements Resourceable
{
    // ...

    // This is where you map your model into a filament-calendar resource object
    public function toCalendarResource(): CalendarResource
    {
        return CalendarResource::make('my-unique-id')
            ->title($this->name);
    }
}
```

### Configuration

[](#configuration-1)

The `CalendarResource` takes all available options like the underlying filament-calendar package, for more info [read here](https://github.com/vkurko/filament-calendar?tab=readme-ov-file#resource-object).

Below is a list of available methods on the filament-calendar object:

#### Setting the title

[](#setting-the-title-1)

Sets the title of the resource that is rendered in the filament-calendar.

```
CalendarResource::make()->title('My resource');
```

#### Setting the event background color

[](#setting-the-event-background-color)

Sets the default background color of the resource's events

```
CalendarResource::make()->eventBackgroundColor('#FF0000');
```

#### Setting the event text color

[](#setting-the-event-text-color)

Sets the default text color of the resource's events

```
CalendarResource::make()->eventTextColor('#FFFFFF');
```

#### Passing custom data

[](#passing-custom-data-1)

You can pass any custom data to the resource that you wish:

```
CalendarResource::make()
    ->extendedProp('foo', 'bar')
    // or
    ->extendedProps(['baz' => 'qux', 'quux' => 'corge']);
```

Available Methods
-----------------

[](#available-methods)

The filament-calendar widget class itself contains a few useful methods.

### Refresh events

[](#refresh-events)

If you need to trigger a refresh of the events in the filament-calendar, you can call `refreshRecords()` on the widget.

```
$this->refreshRecords();
```

### Refresh resources

[](#refresh-resources)

If you need to trigger a refresh of the resources in the filament-calendar, you can call `refreshResources()` on the widget.

```
$this->refreshResources();
```

### Set Option

[](#set-option)

To change any filament-calendar option during runtime, you can use the `setOption()` method on the widget.

For example, to programmatically change the date, you can use:

```
$this->setOption('date', today()->addDay()->toIso8601String());
```

Customization
-------------

[](#customization)

Now that we know how to create a working filament-calendar widget, we can learn how to customize the filament-calendar to our liking.

The filament-calendar widget contains a bunch of properties and methods that you can override in order to customize the widget.

In this section we will go through each of these options.

### Calendar view

[](#calendar-view)

The filament-calendar comes with a variety of views. You can the filament-calendar view per widget by overriding the `calendarView` property:

```
use Guava\Calendar\Enums\CalendarViewType;

protected CalendarViewType $calendarView = CalendarViewType::ListWeek;
```

Check the `CalendarViewType` enum for a list of available views.

### Locale

[](#locale)

By default, the filament-calendar will use your app's locale.

The underlying filament-calendar package doesn't support locales as a combination of language and region/country code, so locales such as `fr_CA` or `en_US` become invalid.

We attempt to resolve this by only using the first language part of the locale. If you still run into any issues with the localization, you can override the filament-calendar's locale manually using the `locale` property:

```
protected ?string $locale = 'en';
```

### First Day

[](#first-day)

By default, the filament-calendar will use `Monday` as the first day.

You can customize this by overriding the `firstDay` property:

```
use Carbon\WeekDay;

protected WeekDay $firstDay = WeekDay::Sunday;
```

### Day Max Events

[](#day-max-events)

Determines the maximum number of stacked event levels for a given day in the dayGrid view.

If there are too many events, a link like +2 more is displayed.

Currently, only a boolean value is supported. When set to true, it limits the number of events to the height of the day cell. When set to false (default) there is no limit.

```
protected bool $dayMaxEvents = true;
```

### Use Filament Timezone

[](#use-filament-timezone)

Caution

While we still recommend setting this property to true, it **does** come with some potential side effects that you need to keep in mind. Keep reading to learn more.

The underlying Event Calendar does **not support** working with timezones. Thus, everything the user sees in their filament-calendar is rendered in their **local browser time**.

This can cause confusion when adding interactivity to your filament-calendar (such as editing events or creating events using filament modals), because filament will display the time **not** in the user's local browser time, but in the **app's timezone** (as configured in config/app.php).

However, as of Filament v4, a `FilamentTimezone` can be configured which will make Filament automatically convert between the Apps timezone setting and your filament timezone. This allows you to store users preferred timezone and convert it back and forth when displaying it to the user, for example via a DatePicker.

To learn more about the `FilamentTimezone` setting, please refer to the [Filament documentation](https://filamentphp.com/docs/4.x/forms/date-time-picker#timezones).

If you want your filament-calendar to use the same timezone as configured via `FilamentTimezone`, you can use the `useFilamentTimezone` property to do so:

```
protected bool $useFilamentTimezone = true;
```

To achieve this, we intercept dates sent from / to the filament-calendar and override the timezone with the filament's timezone.

However, please keep in mind that this currently comes with a few side effects, as we are not able to override all dates / times used internally by the filament-calendar.

For example, if you enable the `now indicator`, it will still use the user's local browser time. We are trying to find a solution to fix this.

### Heading

[](#heading)

By default, the Heading displays the content of the `translations.heading` key (by default, it just says `Calendar`).

You can customize the heading of your filament-calendar widget by overriding the `$heading` property or `getHeading` method:

```
// Setting to null will disable the heading completely
protected string | HtmlString | bool | null $heading = null;

// Or to render HTML, you can override the method directly and return a HtmlString
public function getHeading(): string|HtmlString
{
    return  new HtmlString('some html');
}
```

Interactivity
-------------

[](#interactivity)

By now you should have a perfectly fine and working filament-calendar. However, it is still very static - you can view your events, but there is no way to interact with them.

The filament-calendar supports many ways to interact with, which will be described below individually.

### Actions

[](#actions)

Caution

Actions have no default authorization. This means, anyone can use any action.

Please check the [Authorization section](#authorization) to learn how to authorize actions.

Before you read about the different ways to add interactions to your filament-calendar, you need to understand how actions in the filament-calendar work.

Actions used within the Calendar context need the `CalendarAction` trait to work properly.

We provide a few drop-in replacements of the regular Filament actions that already implement everything necessary:

- CreateAction
- ViewAction
- EditAction
- DeleteAction

Whenever you want to use one of these actions, **make sure** you use the actions from our package. All they do is extend the regular filament action and add a few important setUp calls.

So, instead of using `Filament\Actions\CreateAction` you would use `Guava\Calendar\Filament\Actions\CreateAction`.

#### Defining actions

[](#defining-actions)

Every action you use in the filament-calendar should be defined as a public method in the widget class, just as usual when adding an [Action to a Livewire component](https://filamentphp.com/docs/4.x/components/action#adding-the-action) in filament.

`View`, `Edit` and `Delete` actions are already present for you. You do not need to add them anymore.

For create actions, you still need to create them, since for each model a different create action needs to be added. There is a helper method available for you to help with this.

For example, to add a `createFooAction` (where `Foo` is a model in your app), you would add this method:

```
use Guava\Calendar\Filament\Actions\CreateAction;

public function createFooAction(): CreateAction
{
    // You can use our helper method
    return $this->createAction(Foo::class);

    // Or you can add it manually, both variants are equivalent:
    return CreateAction::make('createFoo')
        ->model(Foo::class);
}
```

Both variants are equal, and it's just up to your personal preference which one you want to use.

#### Mounting actions

[](#mounting-actions)

whenever you want to mount an action programmatically within a filament-calendar context, such as in the `onDateClick` method (more on this later), you can use the `mountAction` method.

```
public function onDateClick(DateClickInfo $info) {
    $this->mountAction('createFoo');
}
```

In the background, we pass a few more arguments to the mount method. Thanks to that, you can type hint the contextual info in your actions:

```
use Guava\Calendar\Enums\Context;
use Guava\Calendar\Contracts\ContextualInfo;
use Guava\Calendar\ValueObjects\DateClickInfo;
use Guava\Calendar\ValueObjects\DateSelectInfo;

public function createFooAction(): CreateAction
{
    return $this->createAction(Foo::class)
        ->mountUsing(function (?ContextualInfo $info) {
            // You can now access contextual info from the filament-calendar using the $info argument
            if ($info instanceof DateClickInfo) {
                // do something on date click
            }

            // Both comparison checks are equal, but instanceof is better for IDE help
            if ($info->getContext() === Context::DateSelect) {
                // do something on date select
            }
        })
        // You could also type hint each contextual info directly:
        ->mountUsing(fn(?DateClickInfo $dateClick, ?DateSelectInfo $dateSelect))
    ;
}
```

#### Accessing context information

[](#accessing-context-information)

As seen above, we provide various contextual information for you when using filament-calendar actions:

ParameterDescriptionContextThe current context enum or null if not in filament-calendar contextDateClickInfoIf in the DateClick context, it will contain the DateClickInfo, otherwise nullDateSelectInfoIf in the DateSelect context, it will contain the DateSelectInfo, otherwise nullEventClickInfoIf in the EventClick context, it will contain the EventClickInfo, otherwise nullNoEventsClickInfoIf in the NoEventsClick context, it will contain the NoEventsClickInfo, otherwise nullYou simply need to type hint the parameter correctly and it will be injected for you if available.

These are not only limited to `mountUsing`, almost all action methods will have access to these.

For example, to conditionally hide an action in the DateClick context:

```
use Guava\Calendar\Enums\Context;

$this->createAction(Foo::class)
    ->hidden(function (?ContextualInfo $info) {
        return $info->getContext() === Context::DateClick;
    });
```

### Schemas

[](#schemas)

The `create`, `view` and `edit` actions should work out of the box and use the correct schemas.

We attempt to guess your Resource and reuse the appropriate schema: `Create` and `Edit` actions will use your **Form Schema**, while `View` actions will reuse your **Infolist Schema** or fall-back to the **Form Schema** if no Infolist is present.

But sometimes, you might want to customize the Schema that will be used in your Calendar Modals.

You have a few options available:

- Stick to auto discovery, in which case you are ready to go :-),
- if your filament-calendar works with a single model only or you reuse the same schema for multiple models, you can implement the `schema` or `defaultSchema` method,
- or you can implement a schema per model

#### Implementing a default schema

[](#implementing-a-default-schema)

If you only work with a single model, or you want to share the same schema across multiple models, you can implement the `schema` or `defaultSchema` method (both are equivalent) in your filament-calendar widget:

```
public function defaultSchema(Schema $schema): Schema
{
    return $schema->components([
        // ...
    ]);
}
```

#### Implementing a schema for a specific model

[](#implementing-a-schema-for-a-specific-model)

If you need to set a specific schema for a model, you have two options:

- Define a method with any name you want and add the `#[CalendarSchema()]` attribute,
- or define a method in the format `camelCaseModelNameSchema`, such as `fooBarSchema`

```
// Variant 1
public function fooBarSchema(Schema $schema): Schema
{
    return $schema->components([
        // ...
    ]);
}

// Variant 2
use Guava\Calendar\Attributes\CalendarSchema;

#[CalendarSchema(FooBar::class)]
public function baz(Schema $schema): Schema
{
    return $schema->components([
        // ...
    ]);
}
```

### Date Click

[](#date-click)

A date click event is triggered when a date cell is clicked in the filament-calendar.

To handle date clicks, first enable them by overriding the `dateClickEnabled` property:

```
protected bool $dateClickEnabled = true;
```

Now date clicks are enabled and a request will be sent to livewire each time a date cell is clicked.

But by default, nothing happens, and each date click will be silently ignored.

You can now choose to either:

- implement your own logic
- or use our context menu feature

#### Implementing your own logic

[](#implementing-your-own-logic)

If you want to take full control over what happens when a date cell is clicked, override the `onDateClick` method and implement your own custom logic:

```
use Guava\Calendar\ValueObjects\DateClickInfo;

protected function onDateClick(DateClickInfo $info): void
{
    // Validate the data and handle the event
    // For example, you might want to mount a create action
    $this->mountAction('createFoo');
}
```

#### Using the context menu feature

[](#using-the-context-menu-feature)

Another option is to use our context menu feature. When enabled, a context menu will be rendered at your mouse cursor when you click a date cell, which you can populate with actions.

To use the context menu feature, all you need to do is implement the `getDateClickContextMenuActions` method:

```
protected function getDateClickContextMenuActions(): array
{
    return [
        $this->createFooAction(),
        $this->createBarAction(),
        // Any other action you want
    ];
}
```

The context menu has a higher priority, so if it returns a non-empty array, it will always take precedence over your custom handler.

### Date Select

[](#date-select)

Similarly, a date select event is triggered when a date cell is dragged to create a selection in the filament-calendar.

To handle date selects, first enable them by overriding the `dateSelectEnabled` property:

```
protected bool $dateSelectEnabled = true;
```

Now date selects are enabled and a request will be sent to livewire each time a date selection is made.

But by default, nothing happens, and each date select will be silently ignored.

You can now choose to either:

- implement your own logic
- or use our context menu feature

#### Implementing your own logic

[](#implementing-your-own-logic-1)

If you want to take full control over what happens when a date selection is made, override the `onDateSelect` method and implement your own custom logic:

```
use Guava\Calendar\ValueObjects\DateSelectInfo;

protected function onDateSelect(DateSelectInfo $info): void
{
    // Validate the data and handle the event
    // For example, you might want to mount a create action
    $this->mountAction('createFoo');
}
```

#### Using the context menu feature

[](#using-the-context-menu-feature-1)

Another option is to use our context menu feature. When enabled, a context menu will be rendered at your mouse cursor when you complete your date selection, which you can populate with actions.

To use the context menu feature, all you need to do is implement the `getDateSelectContextMenuActions` method:

```
protected function getDateSelectContextMenuActions(): array
{
    return [
        $this->createFooAction(),
        $this->createBarAction(),
        // Any other action you want
    ];
}
```

The context menu has a higher priority, so if it returns a non-empty array, it will always take precedence over your custom handler.

### Event Click

[](#event-click)

An event click event is triggered when an event is clicked in the filament-calendar.

To handle event clicks, first enable them by overriding the `eventClickEnabled` property:

```
protected bool $eventClickEnabled = true;
```

Now event clicks are enabled and a request will be sent to livewire each time an event is clicked.

By default, a view action will be mounted with prefilled information about the event.

You can set the default click action by overriding the `defaultEventClickAction` property of the widget. This simply needs to be the name of an action that you can freely define in your widget, like regular Filament actions:

```
protected ?string $defaultEventClickAction = 'edit'; // view and edit actions are provided by us, but you can choose any action you want, even your own custom ones
```

You can now choose to either:

- keep the default behavior,
- implement your own logic
- or use our context menu feature

#### Implementing your own logic

[](#implementing-your-own-logic-2)

If you want to take full control over what happens when an event is clicked, override the `onEventClick` method and implement your own custom logic:

```
use Illuminate\Database\Eloquent\Model;
use Guava\Calendar\ValueObjects\EventClickInfo;

protected function onEventClick(EventClickInfo $info, Model $event, ?string $action = null): void
{
    // Validate the data and handle the event click
    // $event contains the clicked event record
    // you can also access it via $info->record
}
```

#### Using the context menu feature

[](#using-the-context-menu-feature-2)

Another option is to use our context menu feature. When enabled, a context menu will be rendered at your mouse cursor when you click an event, which you can populate with actions.

To use the context menu feature, all you need to do is implement the `getEventClickContextMenuActions` method:

```
protected function getEventClickContextMenuActions(): array
{
    return [
        $this->viewAction(),
        $this->editAction(),
        $this->deleteAction(),
    ];
}
```

The context menu has a higher priority, so if it returns a non-empty array, it will always take precedence over your custom handler.

### No Events Click

[](#no-events-click)

Note

This has affect only in list views.

A no events click event is triggered when a list view has no events to display and the filament-calendar content was clicked.

To handle no events clicks, first enable them by overriding the `noEventsClickEnabled` property:

```
protected bool $noEventsClickEnabled = true;
```

Now no events clicks are enabled and a request will be sent to livewire each time a click is made.

But by default, nothing happens, and each click will be silently ignored.

You can now choose to either:

- implement your own logic
- or use our context menu feature

#### Implementing your own logic

[](#implementing-your-own-logic-3)

If you want to take full control over what happens when a click is made, override the `onNoEventsClick` method and implement your own custom logic:

```
use Guava\Calendar\ValueObjects\NoEventsClickInfo;

protected function onNoEventsClick(NoEventsClickInfo $info): void
{
    // Validate the data and handle the event
    // For example, you might want to mount a create action
    $this->mountAction('createFoo');
}
```

#### Using the context menu feature

[](#using-the-context-menu-feature-3)

Another option is to use our context menu feature. When enabled, a context menu will be rendered at your mouse cursor when you click, which you can populate with actions.

To use the context menu feature, all you need to do is implement the `getNoEventsClickContextMenuActions` method:

```
protected function getNoEventsClickContextMenuActions(): array
{
    return [
        $this->createFooAction(),
        $this->createBarAction(),
        // Any other action you want
    ];
}
```

The context menu has a higher priority, so if it returns a non-empty array, it will always take precedence over your custom handler.

### Event Resize

[](#event-resize)

Callback function that is triggered when you finish resizing an event in your filament-calendar.

To handle the callback, first enable it by overriding the `eventResizeEnabled` property:

```
protected bool $eventResizeEnabled = true;
```

Now it is enabled and a request will be sent to livewire after you complete the resize of an event.

#### Implementing your own logic

[](#implementing-your-own-logic-4)

Important

Notice that unlike the other callbacks, this callback returns a boolean value.

This is used to control whether the event resize should be reverted visually on the frontend or not.

To handle the callback, override the `onEventResize` method and implement your own custom logic:

```
use Illuminate\Database\Eloquent\Model;
use Guava\Calendar\ValueObjects\EventResizeInfo;

protected function onEventResize(EventResizeInfo $info, Model $event): void
{
    // Validate the data and handle the event
    // Most likely you will want to update the event with the new start /end dates to persist the resize in the database
}
```

### Event Drag &amp; Drop

[](#event-drag--drop)

Callback function that is triggered when you finish dragging and drop an event to a date cell in your filament-calendar.

To handle the callback, first enable it by overriding the `eventDragEnabled` property:

```
protected bool $eventDragEnabled = true;
```

Now it is enabled and a request will be sent to livewire after you drop the event to a date cell in the filament-calendar.

#### Implementing your own logic

[](#implementing-your-own-logic-5)

Important

Notice that unlike the other callbacks, this callback returns a boolean value.

This is used to control whether the event should be reverted visually to it's original position on the frontend or not.

To handle the callback, override the `onEventDrop` method and implement your own custom logic:

```
use Illuminate\Database\Eloquent\Model;
use Guava\Calendar\ValueObjects\EventDropInfo;

protected function onEventDrop(EventDropInfo $info, Model $event): bool
{
     // Access the updated dates using getter methods
    $newStart = $info->event->getStart();
    $newEnd = $info->event->getEnd();
      // Update the event with the new start/end dates to persist the drag & drop
    $event->update([
        'start_time' => $newStart,
        'end_time' => $newEnd,
    ]);
     // Return true to accept the drop and keep the event in the new position
    return true;

}
```

### Dates Set

[](#dates-set)

When the date range of the filament-calendar was originally set or changed by clicking the previous/next buttons, changing the view, manipulating the current date via the API, etc. a Dates Set event is triggered.

To handle the Dates Set callback, first enable it by overriding the `datesSetEnabled` property:

```
protected bool $datesSetEnabled = true;
```

Now it is enabled and a request will be sent to livewire each time the filament-calendar date range is changed (or initially set).

#### Implementing your own logic

[](#implementing-your-own-logic-6)

To handle the callback, override the `onDatesSet` method and implement your own custom logic:

```
use Guava\Calendar\ValueObjects\DatesSetInfo;

protected function onDatesSet(DatesSetInfo $info): void
{
    // Validate the data and handle the event
    // For example, you might want to store the date range in a cookie or session
    // to remember the date range across page refreshes
}
```

### View Did Mount

[](#view-did-mount)

Callback function that is triggered right after the view has been added to the DOM.

To handle the callback, first enable it by overriding the `viewDidMountEnabled` property:

```
protected bool $viewDidMountEnabled = true;
```

Now it is enabled and a request will be sent to livewire right after the filament-calendar view has been added to the DOM.

#### Implementing your own logic

[](#implementing-your-own-logic-7)

To handle the callback, override the `onViewDidMount` method and implement your own custom logic:

```
use Guava\Calendar\ValueObjects\ViewDidMountInfo;

protected function onViewDidMount(ViewDidMountInfo $info): void
{
    // Validate the data and handle the event
    // For example, you might want to store the date range in a cookie or session
    // to remember the date range across page refreshes
}
```

Custom Event Content
--------------------

[](#custom-event-content)

By default, we use the default view from the filament-calendar package. However, you are able to use your own content.

To keep things performant, the blade view is rendered **once** on the server and then re-used for every event. Thus, you **cannot** access the filament-calendar event data from the server side via Blade or Laravel, or do any server-side operations.

However, each event is wrapped in an alpine component, which exposes the event data that you can freely use using [AlpineJS](https://alpinejs.dev/).

If you only have one type of events or events that render the same way, you can simply return a view or a HtmlString from the `defaultEventContent` or `eventContent` method:

```
use Illuminate\Support\HtmlString;

protected function eventContent(): HtmlString|string
{
    // return a blade view
    return view('filament-calendar.event');

    // return a HtmlString
    return new HtmlString('My event');
}
```

Example of the `filament-calendar.event` view blade file:

```

```

If you want to render events differently based on their model type, you can implement an Event Content method for each model, by using the `CalendarEventContent` attribute or by using a specific naming convention for the method - `camelCaseModelNameEventContent` such as `fooEventContent` (where Foo is your model):

```
use Illuminate\Support\HtmlString;
use Guava\Calendar\Attributes\CalendarEventContent;

// Variant 1.
#[CalendarEventContent(Foo::class)]
protected function eventContentForFoo(): HtmlString|string
{
    return view('filament-calendar.foo-model-event');
}

// Variant 2.
protected function barEventContent(): HtmlString|string
{
    return view('filament-calendar.bar-model-event');
}
```

Both variants are equal, it's up to your personal preference which one you want to use.

Custom Resource Label Content
-----------------------------

[](#custom-resource-label-content)

By default, we use the default view from the filament-calendar package. However, you are able to use your own content.

To keep things performant, the blade view is rendered **once** on the server and then re-used for every resource. Thus, you **cannot** access the filament-calendar resource data from the server side via Blade or Laravel, or do any server-side operations.

However, each resource is wrapped in an alpine component, which exposes the resource data that you can freely use using [AlpineJS](https://alpinejs.dev/).

If you only have one type of resources or resources that render the same way, you can simply return a view or a HtmlString from the `defaultResourceLabelContent` or `resourceLabelContent` method:

```
use Illuminate\Support\HtmlString;

protected function resourceLabelContent(): HtmlString|string
{
    // return a blade view
    return view('filament-calendar.resource');

    // return a HtmlString
    return new HtmlString('My resource');
}
```

Example of the `filament-calendar.resource` view blade file:

```

```

If you want to render resources differently based on their model type, you can implement a Resource Label Content method for each model, by using the `CalendarResourceLabelContent` attribute or by using a specific naming convention for the method - `camelCaseModelNameResourceLabelContent` such as `fooResourceLabelContent` (where Foo is your model):

```
use Illuminate\Support\HtmlString;
use Guava\Calendar\Attributes\CalendarResourceLabelContent;

// Variant 1.
#[CalendarResourceLabel(Foo::class)]
protected function resourceLabelContentForFoo(): HtmlString|string
{
    return view('filament-calendar.foo-model-resource');
}

// Variant 2.
protected function barResourceLabelContent(): HtmlString|string
{
    return view('filament-calendar.bar-model-resource');
}
```

Both variants are equal, it's up to your personal preference which one you want to use.

Authorization
-------------

[](#authorization)

By default, everyone can use all actions! The package does not handle authorization, this is your responsibility.

Since we use regular filament actions, adding authorizations is a breeze.

For example to add authorization to the createTaskAction:

```
use Guava\Calendar\Filament\Actions\CreateAction;

public function createFooAction(): CreateAction
{
    return $this->createAction(Foo::class)
        ->authorize('create', Foo::class)
        // At this point, it will authorize against the FooPolicy
        //
        // However, you might want to give the user some feedback:
        ->authorizationNotification()
        // Now it will send a notification with the response message from your policy
        //
        // For context menu actions, you can instead use:
        ->authorizationTooltip()
        // which will disable the action and show a tooltip with the response message
    ;
}
```

For detailed information, please follow the default filament documentation on how to add [authorization to actions](https://filamentphp.com/docs/4.x/actions/overview#authorization).

Utility Classes
---------------

[](#utility-classes)

We provide various helper and utility classes to provide you with type hints for various arguments that are being passed from the filament-calendar to your widget.

### CalendarViewType

[](#calendarviewtype)

This enum contains all available filament-calendar views that you can use in your filament-calendar widget.

### FetchInfo

[](#fetchinfo)

When the filament-calendar retrieves events, it provides you with a `FetchInfo` object which contains information about the current filament-calendar view.

Use this to query only models that are visible in the current view.

PropertyDescriptionstartStart date of the range the filament-calendar needs events for. Events before this date are not visible in the filament-calendar.endEnd date of the range the filament-calendar needs events for. Events after this date are not visible in the filament-calendar.Troubleshooting
---------------

[](#troubleshooting)

### Context menu actions don't work

[](#context-menu-actions-dont-work)

If you encounter issues with the context menu, make sure that the name of the action is unique across the whole widget. If there is another action with the same name, it might be mounted instead of the one you want.

### Record vs Event record

[](#record-vs-event-record)

When working with resource widgets, `$record` is the record of the currently opened resource record, whereas `$eventRecord` is the record of the filament-calendar event (during filament-calendar actions, context menus, etc.).

Security measures
-----------------

[](#security-measures)

Keep in mind that a lot of the data in this package comes from the client side JavaScript and could be tampered with. Always validate the data on the server side and never trust the data from the client side.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Lukas Frey](https://github.com/GuavaCZ)
- [All Contributors](../../contributors)
- Spatie - Our package skeleton is a modified version of [Spatie's Package Skeleton](https://github.com/spatie/package-skeleton-laravel)
- [vkurko/filament-calendar](https://github.com/vkurko/filament-calendar) - free, open-source alternative to FullCalendar
- [saade/filament-fullcalendar](https://github.com/saade/filament-fullcalendar) - heavy inspiration for this package

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance73

Regular maintenance activity

Popularity0

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 80.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~16 days

Recently: every ~28 days

Total

33

Last Release

155d ago

Major Versions

1.14.2 → 2.0.0-beta.12025-06-11

### Community

Maintainers

![](https://www.gravatar.com/avatar/cd883f243eac90139be92ab7cf99608411f09b2be1a64cd1b58cf6920362e473?d=identicon)[adultdate](/maintainers/adultdate)

---

Top Contributors

[![lukas-frey](https://avatars.githubusercontent.com/u/10926334?v=4)](https://github.com/lukas-frey "lukas-frey (131 commits)")[![mwagena](https://avatars.githubusercontent.com/u/1246801?v=4)](https://github.com/mwagena "mwagena (8 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![p3dro-docplanner](https://avatars.githubusercontent.com/u/60880234?v=4)](https://github.com/p3dro-docplanner "p3dro-docplanner (4 commits)")[![adultdate](https://avatars.githubusercontent.com/u/10224381?v=4)](https://github.com/adultdate "adultdate (3 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (2 commits)")[![hammadzafar05](https://avatars.githubusercontent.com/u/75698921?v=4)](https://github.com/hammadzafar05 "hammadzafar05 (2 commits)")[![sparksp](https://avatars.githubusercontent.com/u/243893?v=4)](https://github.com/sparksp "sparksp (1 commits)")[![yanntyb](https://avatars.githubusercontent.com/u/69966391?v=4)](https://github.com/yanntyb "yanntyb (1 commits)")[![ibrahem-kamal](https://avatars.githubusercontent.com/u/38753243?v=4)](https://github.com/ibrahem-kamal "ibrahem-kamal (1 commits)")[![Kepsondiaz](https://avatars.githubusercontent.com/u/67605105?v=4)](https://github.com/Kepsondiaz "Kepsondiaz (1 commits)")[![michaelnjuguna](https://avatars.githubusercontent.com/u/74660393?v=4)](https://github.com/michaelnjuguna "michaelnjuguna (1 commits)")[![paulhennell](https://avatars.githubusercontent.com/u/4799852?v=4)](https://github.com/paulhennell "paulhennell (1 commits)")[![pauloffb](https://avatars.githubusercontent.com/u/3179361?v=4)](https://github.com/pauloffb "pauloffb (1 commits)")[![sawirricardo](https://avatars.githubusercontent.com/u/37329575?v=4)](https://github.com/sawirricardo "sawirricardo (1 commits)")

---

Tags

laravelcalendarGuava

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/adultdate-filament-calendar/health.svg)

```
[![Health](https://phpackages.com/badges/adultdate-filament-calendar/health.svg)](https://phpackages.com/packages/adultdate-filament-calendar)
```

###  Alternatives

[guava/calendar

Adds support for vkurko/calendar to Filament PHP.

298241.0k3](/packages/guava-calendar)[pboivin/filament-peek

Full-screen page preview modal for Filament

253319.6k12](/packages/pboivin-filament-peek)[dotswan/filament-map-picker

Easily pick and retrieve geo-coordinates using a map-based interface in your Filament applications.

124139.3k2](/packages/dotswan-filament-map-picker)[creagia/filament-code-field

A Filamentphp input field to edit or view code data.

58289.3k3](/packages/creagia-filament-code-field)[swisnl/filament-backgrounds

Beautiful backgrounds for Filament auth pages

54149.2k6](/packages/swisnl-filament-backgrounds)[hydrat/filament-table-layout-toggle

Filament plugin adding a toggle button to tables, allowing user to switch between Grid and Table layouts.

6292.3k1](/packages/hydrat-filament-table-layout-toggle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
