Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fila Calendar Laravel Package

asmit/fila-calendar

A Filament calendar package for Laravel that adds calendar views and event management to your admin panel. It integrates with Filament resources so you can schedule, display, and manage events with minimal setup, ideal for dashboards and scheduling workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

asmit/fila-calendar adds an always-visible inline calendar to Filament forms and infolists. Unlike Filament's stock DatePicker (a popover trigger), the calendar grid is rendered directly in the form, which makes it a good fit for booking screens, availability editors, and scheduling admin panels where seeing the month at a glance matters.

Install and register

composer require asmit/fila-calendar

The package ships a service provider that registers its Blade views. There is usually nothing to publish for a first run. If you need to restyle the grid:

php artisan vendor:publish --tag=fila-calendar-views
php artisan vendor:publish --tag=fila-calendar-config   # if a config file is offered

If the package ships compiled JS/CSS, run Filament's asset command after install and after every upgrade (php artisan filament:assets, or php artisan filament:upgrade on older Filament versions).

First use case: a single-date form field

use Asmit\FilaCalendar\Forms\Components\CalendarField;

CalendarField::make('starts_on')
    ->label('Start date')
    ->mode('single')
    ->minDate(now())
    ->required();

First use case: a read-only calendar in an infolist

use Asmit\FilaCalendar\Infolists\Components\CalendarEntry;

CalendarEntry::make('availability')
    ->mode('range');

The exact class names and namespaces follow the package's convention but can shift between releases. Check src/ or the README of the installed version before wiring it into a resource — the mode API is the part most likely to change.

Where to look first

  1. The README's mode table — single, range, and multi-range return different state shapes, and that difference drives everything else.
  2. The published Blade view — it tells you whether the grid is Alpine-driven or a JS library wrapper, which determines how state syncs with Livewire.
  3. The service provider — for view namespace, config merge, and asset registration.
  4. composer.json — for the supported Filament major version. With a September 2026 release, expect Filament v4 support; verify before dropping it into a v3 panel.

Implementation Patterns

Mode drives your column type

Mode Persisted shape Column
single string (Y-m-d) date
range ['start' => ..., 'end' => ...] json
multi-range [['start' => ..., 'end' => ...], ...] json

Cast JSON columns to array in the model so the field hydrates cleanly on edit:

protected $casts = [
    'availability' => 'array',
];

Booking / scheduling form

Pair the calendar with reactive state so the rest of the form responds to what the user clicks:

CalendarField::make('slot_range')
    ->mode('range')
    ->live()
    ->afterStateUpdated(function (?array $state, Set $set) {
        $set('duration_days', $state
            ? Carbon::parse($state['start'])->diffInDays(Carbon::parse($state['end'])) + 1
            : null);
    })
    ->required();

Availability / blackout editor

Multi-range is the strongest use case: an admin paints several windows on one month and saves them as a JSON array. Normalize before persisting so you never store half-open ranges:

->mutateDehydratedStateUsing(fn (?array $state) => collect($state)
    ->filter(fn ($r) => filled($r['start'] ?? null) && filled($r['end'] ?? null))
    ->sortBy('start')
    ->values()
    ->all())

Pairing with table columns

There is no first-class table column in the package. Render a summary with a TextColumn:

TextColumn::make('availability')
    ->formatStateUsing(fn ($state) => collect($state)
        ->map(fn ($r) => "{$r['start']} → {$r['end']}")
        ->join(', '))
    ->wrap();

Using it as a filter

Reuse the form field inside a ->form() schema on a Filter, but constrain it to a form-friendly mode (single or range) and add explicit query logic in ->query() — the field supplies state, not filtering.

Theming to match the panel

Because the grid is inline, it inherits less of Filament's chrome than a popover. Publish the view and swap hard-coded colors for Filament's CSS custom properties (--primary-500, --gray-100, etc.) so light/dark mode and panel color changes propagate.

Livewire testing

State is a plain array/string on the component, so standard Filament test helpers work:

livewire(CreateBooking::class)
    ->fillForm(['slot_range' => ['start' => '2026-10-01', 'end' => '2026-10-05']])
    ->call('create')
    ->assertHasNoFormErrors();

Gotchas and Tips

State shape is not uniform across modes. This is the single biggest source of bugs. A single field yields a string; range yields an associative array; multi-range yields a list of arrays. Code that "just works" in single mode (e.g. Carbon::parse($state)) will fatal in range mode. Branch on mode or normalize in a custom cast.

required() on an array field is weaker than you expect. An empty multi-range often arrives as [], which passes required. Add ->rule('array|min:1'), and validate each range's endpoints separately.

Timezone drift. The calendar grid is rendered client-side, so date arithmetic can pick up the browser timezone while your validation rules use config('app.timezone'). Pick one storage convention (store Y-m-d strings, not datetimes) and stick to it; if the package exposes a timezone setter, verify it actually reaches the JS layer.

Empty vs. null on edit. Hydrating a JSON column that is null sometimes yields [] and sometimes null depending on the cast. Guard both in any formatStateUsing or afterStateUpdated callback.

Asset and view caching after upgrades. With a small, fast-moving package, a stale compiled view is a common "my CSS change did nothing" cause. After upgrading: php artisan view:clear && php artisan filament:assets.

No built-in table column or filter. Budget time for the TextColumn formatter and filter query yourself; don't assume parity with DatePicker's table/filter surface.

Maturity risk. Six stars, zero dependents, and a single-maintainer release cadence. Pin the version in composer.json ("asmit/fila-calendar": "^1.0" rather than *), read the release notes before bumping, and wrap the field in your own thin factory class if you use it in more than a handful of places — that gives you one place to patch if the mode API changes or the package goes quiet.

Extension points. Prefer ->extraAttributes() and a published Blade view over forking. The Alpine component is the fragile part; avoid depending on internal method names in your own JS. If you need click-through behavior the package doesn't expose, handle it via ->afterStateUpdated() on the Livewire side rather than reaching into the grid's JavaScript.

Debugging tip. When clicks don't update the form, drop a ->live() plus dump($state) into afterStateUpdated(). If $state never changes, the issue is the JS-to-Livewire bridge (asset version, caching, or a Filament version mismatch), not your schema. If $state updates but the saved record is wrong, the problem is dehydration — check mutateDehydratedStateUsing and your model cast.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core