vernsg/nusa-filament

Ready-to-use Filament 4 components for creasi/laravel-nusa Indonesian administrative regions.

Maintainers

Package info

github.com/VernSG/nusa-filament

Homepage

Issues

pkg:composer/vernsg/nusa-filament

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

v0.1.3 2026-05-30 06:34 UTC

This package is auto-updated.

Last update: 2026-05-30 06:58:35 UTC


README

CI Latest Version on Packagist Total Downloads License

Nusa Filament provides Filament 4 components for working with Indonesian administrative regions in Laravel applications. It is powered by creasi/laravel-nusa, which supplies the underlying region data and lookup support.

Use this package to add cascading Provinsi -> Kabupaten/Kota -> Kecamatan -> Desa/Kelurahan selects to Filament forms. It also includes postal code autofill, table columns, filters, infolist entries, and validation rules for applications that store Indonesian address data.

Preview

Nusa Filament address form preview

Child regions are displayed as soon as a parent region is selected. Remote search remains available for filtering larger option lists.

Features

  • Form components: cascading province, regency, district, and village selects, available individually or as a complete address group with sensible default field names.
  • Dependent options: child regions are loaded immediately after their parent region is selected, with remote search for larger option lists.
  • Postal code autofill: the postal code field can be filled automatically from the selected village.
  • Display components: table columns and infolist entries resolve stored region codes to readable names.
  • Table filtering: a dependent location filter supports province, regency, district, and village fields.
  • Validation: Laravel validation rules check individual region codes and address hierarchy consistency.
  • Configuration: field names, labels, search limit, native select behavior, and dropdown position can be customized.

Requirements

Package Version PHP Laravel Filament
^0.1 ^8.2 ^11.0 | ^12.0 ^4.0

The PHP sqlite3 extension is also required. Laravel Nusa stores its administrative region dataset in SQLite, so the extension must be enabled in the application that installs this package.

Installation

Install the package with Composer:

composer require vernsg/nusa-filament

Laravel package auto-discovery registers the service provider automatically.

Publish the configuration file if you need to customize field names, labels, the search limit, native select behavior, or dropdown position:

php artisan vendor:publish --tag=nusa-filament-config

The published configuration file will be available at:

config/nusa-filament.php

Usage

Quick Start

Add NusaAddress to a Filament resource form to render a complete Indonesian address block.

<?php

namespace App\Filament\Resources\Customers\Schemas;

use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;
use Vernsg\NusaFilament\Forms\Components\NusaAddress;

class CustomerForm
{
    public static function configure(Schema $schema): Schema
    {
        return $schema
            ->components([
                TextInput::make('name')
                    ->required(),

                NusaAddress::make(),
            ]);
    }
}

The component renders these fields:

Alamat
Provinsi
Kabupaten/Kota
Kecamatan
Desa/Kelurahan
Kode Pos

By default, values are stored in these model attributes:

address_line
province_code
regency_code
district_code
village_code
postal_code

Ensure that your model table contains matching nullable columns before saving the form.

Database Columns

The package stores administrative region codes, not region names. Use the provided table columns and infolist entries to display readable region names.

Example migration:

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('customers', function (Blueprint $table): void {
    $table->text('address_line')->nullable();
    $table->string('province_code')->nullable();
    $table->string('regency_code')->nullable();
    $table->string('district_code')->nullable();
    $table->string('village_code')->nullable();
    $table->string('postal_code', 10)->nullable();
});

Dependent Select Behavior

The address selects are reactive and dependent by default:

  • Selecting a province loads its regencies.
  • Selecting a regency loads its districts.
  • Selecting a district loads its villages.
  • Selecting a village can automatically fill the postal code field.

Options are available immediately after a parent region is selected. For example, after selecting a province, the regency dropdown displays the matching regencies without requiring the user to type first.

Remote search remains enabled for filtering larger option lists.

Naming Convention

The package uses English names in its PHP API while displaying Indonesian labels by default:

Indonesian Label Component / API Term
Provinsi Province
Kabupaten/Kota Regency
Kecamatan District
Desa/Kelurahan Village

Form Components

Full Address Group

use Vernsg\NusaFilament\Forms\Components\NusaAddress;

NusaAddress::make();

Customize field names when your model uses different columns:

NusaAddress::make()
    ->addressLine('shipping_address')
    ->province('shipping_province_code')
    ->regency('shipping_regency_code')
    ->district('shipping_district_code')
    ->village('shipping_village_code')
    ->postalCode('shipping_postal_code');

Hide optional fields:

NusaAddress::make()
    ->withoutAddressLine()
    ->withoutPostalCode();

Individual Selects

Use the individual components to place fields manually:

use Vernsg\NusaFilament\Forms\Components\DistrictSelect;
use Vernsg\NusaFilament\Forms\Components\ProvinceSelect;
use Vernsg\NusaFilament\Forms\Components\RegencySelect;
use Vernsg\NusaFilament\Forms\Components\VillageSelect;

ProvinceSelect::make('province_code');

RegencySelect::make('regency_code')
    ->provinceField('province_code');

DistrictSelect::make('district_code')
    ->regencyField('regency_code');

VillageSelect::make('village_code')
    ->districtField('district_code')
    ->fillPostalCode('postal_code');

Table Components

Display readable region names from stored codes:

use Vernsg\NusaFilament\Tables\Columns\DistrictColumn;
use Vernsg\NusaFilament\Tables\Columns\ProvinceColumn;
use Vernsg\NusaFilament\Tables\Columns\RegencyColumn;
use Vernsg\NusaFilament\Tables\Columns\VillageColumn;

return $table
    ->columns([
        ProvinceColumn::make('province_code'),
        RegencyColumn::make('regency_code'),
        DistrictColumn::make('district_code'),
        VillageColumn::make('village_code'),
    ]);

Add a dependent location filter:

use Vernsg\NusaFilament\Tables\Filters\NusaLocationFilter;

return $table
    ->filters([
        NusaLocationFilter::make('location'),
    ]);

Customize filter field names:

NusaLocationFilter::make('shipping_location')
    ->provinceField('shipping_province_code')
    ->regencyField('shipping_regency_code')
    ->districtField('shipping_district_code')
    ->villageField('shipping_village_code');

Infolist Components

Display a complete address entry:

use Vernsg\NusaFilament\Infolists\Components\NusaAddressEntry;

NusaAddressEntry::make();

Or display individual entries:

use Vernsg\NusaFilament\Infolists\Components\DistrictEntry;
use Vernsg\NusaFilament\Infolists\Components\ProvinceEntry;
use Vernsg\NusaFilament\Infolists\Components\RegencyEntry;
use Vernsg\NusaFilament\Infolists\Components\VillageEntry;

ProvinceEntry::make('province_code');
RegencyEntry::make('regency_code');
DistrictEntry::make('district_code');
VillageEntry::make('village_code');

Validation

Use the provided rules to validate individual region codes and confirm that the selected address hierarchy is consistent:

use Vernsg\NusaFilament\Rules\NusaRules;

[
    'province_code' => ['required', NusaRules::province()],
    'regency_code' => ['required', NusaRules::regency()],
    'district_code' => ['required', NusaRules::district()],
    'village_code' => [
        'required',
        NusaRules::village(),
        NusaRules::addressHierarchy(),
    ],
]

addressHierarchy() validates that:

  • the regency belongs to the selected province;
  • the district belongs to the selected regency;
  • the village belongs to the selected district.

Configuration

Publish the configuration file:

php artisan vendor:publish --tag=nusa-filament-config

Available options:

return [
    'fields' => [
        'province' => 'province_code',
        'regency' => 'regency_code',
        'district' => 'district_code',
        'village' => 'village_code',
        'postal_code' => 'postal_code',
        'address_line' => 'address_line',
    ],

    'labels' => [
        'province' => 'Provinsi',
        'regency' => 'Kabupaten/Kota',
        'district' => 'Kecamatan',
        'village' => 'Desa/Kelurahan',
        'postal_code' => 'Kode Pos',
        'address_line' => 'Alamat',
    ],

    'search_limit' => 50,

    'native' => false,

    'select_position' => 'bottom',
];

select_position defaults to bottom so region dropdowns do not flip upward and cover previous fields on long forms. Set it to null to use Filament's default auto-placement behavior.

Relationship to Laravel Nusa

This package does not replace Laravel Nusa. It uses creasi/laravel-nusa as its data and region lookup layer, then adds Filament-specific components around it.

It can be used as:

  • a ready-to-install Filament integration for Laravel applications;
  • a concrete example of how Laravel Nusa can power admin panel address forms;
  • a small reference implementation for dependent Indonesian region selects.

Development

Install dependencies:

composer install

Run the test suite:

composer test

Run static analysis:

composer analyse

Check code style:

composer format:test

Fix code style:

composer format

Changelog

Please see CHANGELOG.md for notable changes.

Contributing

Please see CONTRIBUTING.md for contribution guidelines.

Security

Please see SECURITY.md for the security policy.

Credits

  • creasi/laravel-nusa for the Indonesian administrative region data and underlying region support.
  • Filament for the application panel and component framework.

License

The MIT License. Please see LICENSE.md for details.