### Development Setup Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Install dependencies and build the JavaScript assets for development. Run the test suite using Pest. ```bash composer install npm install npm run build # rebuild dist/components/autocomplete.js after editing resources/js vendor/bin/pest # run the test suite ``` -------------------------------- ### Install Dependencies and Run Tests Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/README.md Installs project dependencies using Composer and npm, builds frontend assets, and executes the test suite. ```bash composer install npm install npm run build # rebuild dist/ assets after editing resources/js or resources/css vendor/bin/pest # run the test suite ``` -------------------------------- ### Install Filament TextInput Autocomplete Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/README.md Install the package using Composer. This command adds the plugin to your project dependencies. ```bash composer require giacomomasseron/filament-textinput-autocomplete ``` -------------------------------- ### Install Package and Publish Assets Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/AGENTS.md Install the package using Composer and publish Filament assets. Re-run `php artisan filament:assets` if suggestions are unstyled or the dropdown does not open. ```bash composer require giacomomasseron/filament-textinput-autocomplete php artisan filament:assets # required — publishes the Alpine component + CSS. Re-run on deploy. ``` -------------------------------- ### Publish Filament Assets Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/README.md After installation, publish Filament's assets to ensure the plugin's stylesheet is served correctly. This command should be run on each deployment. ```bash php artisan filament:assets ``` -------------------------------- ### Test Case Setup Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Extends Orchestra's TestCase and defines the package providers necessary for testing the Filament v5 components and the custom service provider. ```php toBeInstanceOf(AutocompleteInput::class) ->and($field->getName())->toBe('country'); }); ``` -------------------------------- ### Blade View for Autocomplete Component Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/specs/2026-06-12-filament-textinput-autocomplete-design.md Example of how to load and initialize the autocomplete component in a Blade view using Alpine.js directives. The component's source is dynamically fetched. ```blade
``` -------------------------------- ### Call Validation in search Method Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md This snippet demonstrates calling validateConfiguration() at the start of the search() method to enforce valid configuration before executing search logic. ```php public function search(string $search): { $this->validateConfiguration(); if ($this->getSearchResultsUsing === null) { // ...unchanged... ``` -------------------------------- ### Test Static Options Preparation Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md These tests verify that the `getOptionsForJs` method correctly handles static options, ensuring they are mapped to the expected format including value, label, HTML, and searchable keys. ```php getOptionsForJs())->toBe([]); }); it('maps options to value, label, html and searchable keys', function () { $field = AutocompleteInput::make('q') ->options([ ['value' => 1, 'label' => 'Spain', 'description' => 'Country'], ]) ->searchKeys(['label', 'description']) ->itemView(fn (array $item) => "{$item['label']}"); expect($field->getOptionsForJs())->toBe([ [ 'value' => 1, 'label' => 'Spain', 'html' => 'Spain', 'keys' => ['spain', 'country'], ], ]); }); ``` -------------------------------- ### Import AutocompleteInput Component Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/AGENTS.md Import the AutocompleteInput component from the correct namespace. Ensure the namespace matches the package's structure. ```php use GiacomoMasseroni\TextInputAutocomplete\Forms\Components\AutocompleteInput; ``` -------------------------------- ### Implement Server Search Method Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Implement the Livewire-exposed `search` method in the AutocompleteInput component, including error handling and result mapping. ```php #[ExposedLivewireMethod] #[Renderless] public function search(string $search): array { if ($this->getSearchResultsUsing === null) { return ['results' => [], 'error' => null]; } try { $raw = $this->evaluate($this->getSearchResultsUsing, ['search' => $search]) ?? []; } catch (\Throwable $e) { return ['results' => [], 'error' => $e->getMessage()]; } $results = array_map( fn (array $item) => $this->mapItem($item), array_slice(array_values($raw), 0, $this->getMaxResults()), ); return ['results' => $results, 'error' => null]; } ``` -------------------------------- ### Service Provider Implementation Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md A minimal service provider for the package, extending Spatie's PackageServiceProvider and configuring the package name and views. ```php name('filament-textinput-autocomplete') ->hasViews('filament-textinput-autocomplete'); } } ``` -------------------------------- ### Configure AutocompleteInput with Server-Side Search Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/AGENTS.md Use `getSearchResultsUsing()` for server-side search over Livewire. Configure minimum characters to trigger search with `minChars()` and debounce time with `searchDebounce()`. ```php use Illuminate\Support\Facades\Http; AutocompleteInput::make('repo') ->getSearchResultsUsing(function (string $search) { $items = Http::get('https://api.github.com/search/repositories', ['q' => $search]) ->json('items', []); return collect($items) ->map(fn (array $r) => ['value' => $r['id'], 'label' => $r['full_name']]) ->all(); }) ->minChars(2) ->searchDebounce(300); ``` -------------------------------- ### Implement Static Option Mapping Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Implement the `getOptionsForJs` and `mapItem` methods in `AutocompleteInput.php` to prepare static options for the Alpine.js component. This involves mapping each item to its value, label, HTML representation, and searchable keys. ```php public function getOptionsForJs(): array { $options = $this->getOptions() ?? []; return array_map(fn (array $item) => $this->mapItem($item), $options); } protected function mapItem(array $item): array { $searchable = array_map( fn (string $key) => mb_strtolower((string) ($item[$key] ?? '')), $this->getSearchKeys(), ); return [ 'value' => $item[$this->getOptionValue()] ?? null, 'label' => (string) ($item[$this->getOptionLabel()] ?? ''), 'html' => $this->renderItem($item), 'keys' => array_values($searchable), ]; } ``` -------------------------------- ### Git commit for build tooling Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Stages and commits package.json, the build script, and the compiled asset after setting up esbuild. ```bash git add package.json bin/build.js dist/components/autocomplete.js git commit -m "build: add esbuild tooling and compiled Alpine asset" ``` -------------------------------- ### Commit Documentation Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Stage and commit the updated README.md file. ```bash git add README.md git commit -m "docs: add README with installation and usage" ``` -------------------------------- ### Add Livewire Exposed Imports Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Add necessary imports for Livewire 3 attributes to expose the search method. ```php use Filament\Support\Components\Attributes\ExposedLivewireMethod; use Livewire\Attributes\Renderless; ``` -------------------------------- ### esbuild build script Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Uses esbuild to bundle, minify, and format the autocomplete JavaScript entry point into an ESM module for the browser. ```javascript import * as esbuild from 'esbuild'; await esbuild.build({ entryPoints: ['resources/js/autocomplete.js'], outfile: 'dist/components/autocomplete.js', bundle: true, minify: true, format: 'esm', platform: 'browser', }); console.log('Built dist/components/autocomplete.js'); ``` -------------------------------- ### Smoke Test for Package Bootstrapping Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md A simple Pest test to verify that the package's service provider class exists and can be loaded. ```php toBeTrue(); }); ``` -------------------------------- ### Usage: Server Search with Livewire Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Configure the AutocompleteInput to fetch search results from a server endpoint using Livewire. Specify the minimum characters required to trigger a search (`minChars`) and the debounce time in milliseconds (`searchDebounce`). The `itemView` can reference a Blade view for rendering suggestions. ```php use Illuminate\Support\Facades\Http; AutocompleteInput::make('repo') ->getSearchResultsUsing(function (string $search) { return Http::get('https://api.github.com/search/repositories', ['q' => $search]) ->json('items', []) ? collect(Http::get('https://api.github.com/search/repositories', ['q' => $search])->json('items')) ->map(fn ($r) => ['value' => $r['id'], 'label' => $r['full_name']]) ->all() : []; }) ->itemView('filament.autocomplete.repo') // a Blade view receiving $item ->minChars(2) ->searchDebounce(300); ``` -------------------------------- ### Git commit for service provider and tests Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Stages and commits changes to the service provider, render test, and Livewire test fixture. ```bash git add src/TextInputAutocompleteServiceProvider.php tests/Feature/RendersFieldTest.php tests/Fixtures/AutocompleteTestComponent.php git commit -m "feat: register Alpine asset and verify field rendering" ``` -------------------------------- ### Git Commit Command Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Command to stage and commit the initial package scaffolding files. ```bash git add composer.json phpunit.xml tests/ src/TextInputAutocompleteServiceProvider.php git commit -m "chore: scaffold package, test harness, and service provider" ``` -------------------------------- ### Autocomplete Input with Static Options Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/README.md Configure an AutocompleteInput component with a predefined list of options. These options are filtered client-side. The `searchKeys` method specifies which fields to search within, and `itemView` customizes how each item is displayed. ```php use GiacomoMasseroni\TextInputAutocomplete\Forms\Components\AutocompleteInput; AutocompleteInput::make('country') ->options([ ['value' => 'es', 'label' => 'Spain', 'description' => 'Country'], ['value' => 'fr', 'label' => 'France', 'description' => 'Country'], ]) ->searchKeys(['label', 'description']) ->itemView(fn (array $item) => "{$item['label']} — {$item['description']}"); ``` -------------------------------- ### Commit AutocompleteInput Skeleton Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Shows the Git commands to stage and commit the initial AutocompleteInput class and its test file. ```bash git add src/Forms/Components/AutocompleteInput.php tests/Unit/AutocompleteInputTest.php git commit -m "feat: add AutocompleteInput field class skeleton" ``` -------------------------------- ### Commit Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Command to stage and commit the implemented `renderItem` method, associated tests, and configuration changes. ```bash git add src/Forms/Components/AutocompleteInput.php tests/Unit/RenderItemTest.php tests/views/item.blade.php tests/TestCase.php git commit -m "feat: resolve itemView to HTML (closure, view, template, default)" ``` -------------------------------- ### Test Search Keys Configuration Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Checks the functionality for setting and retrieving search keys, including the default value and custom configurations. This ensures the field can be configured to search specific properties. ```php it('stores search keys with a sensible default', function () { $field = AutocompleteInput::make('country'); expect($field->getSearchKeys())->toBe(['label']); $field->searchKeys(['label', 'description']); expect($field->getSearchKeys())->toBe(['label', 'description']); }); ``` -------------------------------- ### package.json for esbuild build Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Defines project name, private status, module type, build script, and esbuild as a dev dependency. ```json { "name": "filament-textinput-autocomplete", "private": true, "type": "module", "scripts": { "build": "node bin/build.js" }, "devDependencies": { "esbuild": "^0.23.0" } } ``` -------------------------------- ### Test Server Search Configuration Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Checks the boolean flag that indicates whether server-side search is configured for the AutocompleteInput. This is crucial for performance with large datasets. ```php it('reports whether server search is configured', function () { $field = AutocompleteInput::make('country'); expect($field->hasServerSearch())->toBeFalse(); $field->getSearchResultsUsing(fn (string $search) => []); expect($field->hasServerSearch())->toBeTrue(); }); ``` -------------------------------- ### Test Option Label and Value Key Configuration Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Ensures that the component correctly handles custom keys for option labels and values, overriding the default 'label' and 'value'. This allows flexibility in data structure. ```php it('stores option label and value keys with defaults', function () { $field = AutocompleteInput::make('country'); expect($field->getOptionLabel())->toBe('label') ->and($field->getOptionValue())->toBe('value'); $field->optionLabel('name')->optionValue('id'); expect($field->getOptionLabel())->toBe('name') ->and($field->getOptionValue())->toBe('id'); }); ``` -------------------------------- ### Package Layout Structure Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/specs/2026-06-12-filament-textinput-autocomplete-design.md Overview of the directory structure for the Filament TextInput Autocomplete package, including source files, resources, build outputs, and tests. ```plaintext composer.json src/ TextInputAutocompleteServiceProvider.php Forms/Components/AutocompleteInput.php resources/ views/forms/components/autocomplete-input.blade.php js/autocomplete.js dist/components/autocomplete.js # esbuild output (committed for composer installs) package.json bin/build.js # esbuild config tests/ TestCase.php Unit/AutocompleteInputTest.php docs/superpowers/specs/2026-06-12-filament-textinput-autocomplete-design.md ``` -------------------------------- ### Test: Item Rendering with Template String Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Tests rendering an item using a template string. Tokens like {label} and {type} within the string should be replaced with corresponding item attributes. ```php it('renders a template string by replacing tokens', function () { $field = AutocompleteInput::make('q') ->itemView('
{label} — {type}
'); expect(callRenderItem($field, ['label' => 'Spain', 'type' => 'Country'])) ->toBe('
Spain — Country
'); }); ``` -------------------------------- ### Implement Configuration Validation Method Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md This method, validateConfiguration(), checks for invalid combinations of options and search callbacks, and ensures maxResults is at least 1. It should be added to the AutocompleteInput class. ```php protected function validateConfiguration(): void { if ($this->options !== null && $this->getSearchResultsUsing !== null) { throw new \InvalidArgumentException( 'AutocompleteInput cannot use both static options() and getSearchResultsUsing(); choose one source.', ); } if ($this->getMaxResults() < 1) { throw new \InvalidArgumentException('AutocompleteInput maxResults() must be at least 1.'); } } ``` -------------------------------- ### Composer Package Configuration Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Defines the package name, description, dependencies, autoloading, and extra Laravel configuration for the Filament TextInput Autocomplete package. ```json { "name": "giacomo/filament-textinput-autocomplete", "description": "A Filament v5 TextInput field with autocomplete (static + server search).", "type": "library", "license": "MIT", "require": { "php": "^8.2", "filament/filament": "^5.0", "spatie/laravel-package-tools": "^1.16" }, "require-dev": { "orchestra/testbench": "^10.0", "pestphp/pest": "^3.0", "pestphp/pest-plugin-laravel": "^3.0" }, "autoload": { "psr-4": { "Giacomo\TextInputAutocomplete\": "src/" } }, "autoload-dev": { "psr-4": { "Giacomo\TextInputAutocomplete\Tests\": "tests/" } }, "extra": { "laravel": { "providers": [ "Giacomo\TextInputAutocomplete\TextInputAutocompleteServiceProvider" ] } }, "config": { "allow-plugins": { "pestphp/pest-plugin": true, "php-http/discovery": true }, "sort-packages": true }, "minimum-stability": "stable", "prefer-stable": true } ``` -------------------------------- ### Autocomplete Input with Server Search Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/README.md Implement server-side search for AutocompleteInput using Livewire. The `getSearchResultsUsing` method defines a callback that fetches data, potentially from an external API like GitHub. `minChars` sets the minimum input length to trigger a search, and `searchDebounce` controls the delay before the search request is sent. ```php use GiacomoMasseroni\TextInputAutocomplete\Forms\Components\AutocompleteInput; use Illuminate\Support\Facades\Http; AutocompleteInput::make('repo') ->getSearchResultsUsing(function (string $search) { $items = Http::get('https://api.github.com/search/repositories', [ 'q' => $search, ])->json('items', []); return collect($items) ->map(fn (array $repo) => [ 'value' => $repo['id'], 'label' => $repo['full_name'], ]) ->all(); }) ->itemView('filament.autocomplete.repo') // a Blade view that receives $item ->minChars(2) ->searchDebounce(300); ``` -------------------------------- ### Test Server Search Method Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Write failing tests for the server search method, covering mapped results, error handling, and the absence of a configured search. ```php maxResults(2) ->itemView(fn (array $item) => "{$item['label']}") ->getSearchResultsUsing(fn (string $search) => [ ['value' => 1, 'label' => $search . '-a'], ['value' => 2, 'label' => $search . '-b'], ['value' => 3, 'label' => $search . '-c'], ]); $out = $field->search('x'); expect($out['error'])->toBeNull() ->and($out['results'])->toHaveCount(2) ->and($out['results'][0])->toMatchArray([ 'value' => 1, 'label' => 'x-a', 'html' => 'x-a', ]); }); it('returns an error and empty results when the closure throws', function () { $field = AutocompleteInput::make('q') ->getSearchResultsUsing(function (string $search) { throw new RuntimeException('boom'); }); $out = $field->search('x'); expect($out['results'])->toBe([]) ->and($out['error'])->toBe('boom'); }); it('returns empty results without server search configured', function () { $out = AutocompleteInput::make('q')->search('x'); expect($out['results'])->toBe([])->and($out['error'])->toBeNull(); }); ``` -------------------------------- ### Call Validation in getOptionsForJs Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md This snippet shows how to call the validateConfiguration() method at the beginning of the getOptionsForJs() method to ensure configuration is valid before proceeding. ```php public function getOptionsForJs(): array { $this->validateConfiguration(); $options = $this->getOptions() ?? []; // ...unchanged... ``` -------------------------------- ### PHPUnit Configuration Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md XML configuration for PHPUnit, specifying the bootstrap file, test suite directory, and source inclusion for code coverage. ```xml tests src ``` -------------------------------- ### Commit Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Commit the implemented server search method and passing tests. ```bash git add src/Forms/Components/AutocompleteInput.php tests/Unit/SearchMethodTest.php git commit -m "feat: add Livewire-exposed server search method" ``` -------------------------------- ### Registering Autocomplete Component Asset Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/specs/2026-06-12-filament-textinput-autocomplete-design.md Register the JavaScript component for the autocomplete input using FilamentAsset. This should be done within the package's boot method. ```php FilamentAsset::register([ AlpineComponent::make('autocomplete', __DIR__ . '/../dist/components/autocomplete.js'), ], package: 'giacomo/filament-textinput-autocomplete'); ``` -------------------------------- ### Basic AutocompleteInput Class Skeleton Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Provides the minimal PHP class structure for the AutocompleteInput component, extending Filament's base Field class. This is necessary for the component to be recognized. ```php getMinChars())->toBe(1) ->and($field->getSearchDebounce())->toBe(300) ->and($field->getMaxResults())->toBe(10); $field->minChars(3)->searchDebounce(500)->maxResults(5); expect($field->getMinChars())->toBe(3) ->and($field->getSearchDebounce())->toBe(500) ->and($field->getMaxResults())->toBe(5); }); ``` -------------------------------- ### Registering Alpine Component Asset in Service Provider Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Registers the 'autocomplete' Alpine component using FilamentAsset in the service provider's packageBooted method. ```php name('filament-textinput-autocomplete') ->hasViews('filament-textinput-autocomplete'); } public function packageBooted(): void { FilamentAsset::register([ AlpineComponent::make('autocomplete', __DIR__ . '/../dist/components/autocomplete.js'), ], package: static::$assetPackageName); } } ``` -------------------------------- ### AutocompleteInput API Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/specs/2026-06-12-filament-textinput-autocomplete-design.md This snippet outlines the available methods for configuring the AutocompleteInput field, including setting data sources, search parameters, and display options. ```APIDOC ## AutocompleteInput API This section details the configuration options for the `AutocompleteInput` component. ### Methods - **`make(string $name)`**: Creates a new instance of the AutocompleteInput. - **`options(array | Closure $options)`**: Sets the data source for static client-side mode. Accepts an array of options or a Closure that returns an array. - **`searchKeys(array $keys)`**: Specifies the item keys to be matched against the search query in static mode. - **`getSearchResultsUsing(Closure $callback)`**: Configures server mode. The provided Closure receives a string `$search` and should return search results. - **`itemView(string | Closure $view)`**: Defines how individual items are rendered. Accepts a string representing a Blade view name, a Closure that returns raw HTML, or a template string. - **`optionLabel(string $key)`**: Specifies the item key whose value will be displayed in the input field after an item is selected. - **`optionValue(string $key)`**: Specifies the item key whose value will be stored as the form state. - **`minChars(int $min)`**: Sets the minimum number of characters a user must type before a search is triggered. - **`searchDebounce(int $milliseconds)`**: Sets the delay in milliseconds before triggering a search after the user stops typing. - **`maxResults(int $max)`**: Limits the maximum number of results displayed. - **`placeholder(string $placeholder)`**: Sets the placeholder text for the input field. - **`noResultsMessage(string $message)`**: Sets the message to display when no search results are found. - **`loadingMessage(string $message)`**: Sets the message to display while search results are being loaded. - **`afterSelected(Closure $callback)`**: An optional callback that is executed after an item is selected. It receives the selected item as an argument. ### `itemView` Resolution - **`Closure`**: The Closure is called with the item (`$item`), and its return value is treated as raw HTML. - **`string` matching a Blade view**: If the string matches an existing Blade view (`view()->exists($value)`), it will be rendered with `['item' => $item]` passed to the view. - **Other `string`**: Treated as a template string. `{key}` tokens are replaced with item attributes, and the remaining markup is passed through as HTML. **Default `itemView`**: Renders the `optionLabel` as escaped text. ### Mode Resolution - **Server Mode**: Activated if `getSearchResultsUsing` is set. - **Static Mode**: Activated if `options` is set and `getSearchResultsUsing` is not. - **Configuration Error**: Setting both `getSearchResultsUsing` and `options` will result in an error. ``` -------------------------------- ### Test Message Configuration for AutocompleteInput Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Verifies the ability to customize messages displayed by the AutocompleteInput, such as 'No results found' and 'Loading...'. This allows for localized or branded messaging. ```php it('stores messages with defaults', function () { $field = AutocompleteInput::make('country'); expect($field->getNoResultsMessage())->toBe('No results found') ->and($field->getLoadingMessage())->toBe('Loading...'); $field->noResultsMessage('Nothing')->loadingMessage('Wait'); expect($field->getNoResultsMessage())->toBe('Nothing') ->and($field->getLoadingMessage())->toBe('Wait'); }); ``` -------------------------------- ### Test: Item Rendering with Closure Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Tests rendering an item using a closure provided to `itemView`. The closure is expected to return raw HTML, which should not be escaped. ```php it('renders a closure as raw html', function () { $field = AutocompleteInput::make('q') ->itemView(fn (array $item) => "{$item['label']}"); expect(callRenderItem($field, ['label' => 'Spain']))->toBe('Spain'); }); ``` -------------------------------- ### Commit Git Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Stage and commit the new AutocompleteInput component and its tests. This command adds the modified files to the Git staging area and then commits them with a descriptive message. ```bash git add src/Forms/Components/AutocompleteInput.php tests/Unit/AutocompleteInputTest.php git commit -m "feat: add AutocompleteInput configuration API" ``` -------------------------------- ### Test: Item Rendering with Blade View Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Tests rendering an item using a registered Blade view. The view should receive the item data and render it, including specific HTML attributes. ```php it('renders a matching blade view with the item', function () { $field = AutocompleteInput::make('q')->itemView('test-fixtures::item'); $html = callRenderItem($field, ['label' => 'Spain']); expect(trim($html))->toContain('class="fixture"')->toContain('Spain'); }); ``` -------------------------------- ### Implement `renderItem` Method Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md The core implementation of the `renderItem` method in `AutocompleteInput.php`. It handles resolution logic for closures, Blade views, template strings, and default rendering, including HTML escaping. ```php protected function renderItem(array $item): string { $itemView = $this->itemView; if ($itemView instanceof \Closure) { return (string) $this->evaluate($itemView, ['item' => $item]); } if (is_string($itemView)) { if (view()->exists($itemView)) { return view($itemView, ['item' => $item])->render(); } return preg_replace_callback( '/\{(\w+)\}/', fn (array $m) => e($item[$m[1]] ?? ''), $itemView, ); } return e($item[$this->getOptionLabel()] ?? ''); } ``` -------------------------------- ### Test Static Options for AutocompleteInput Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Verifies that the AutocompleteInput field can correctly store and retrieve a static array of options. This test ensures the basic functionality of setting options. ```php it('stores static options', function () { $options = [['value' => 1, 'label' => 'Spain']]; $field = AutocompleteInput::make('country')->options($options); expect($field->getOptions())->toBe($options); }); ``` -------------------------------- ### Commit Git Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Stage and commit the newly added Alpine.js autocomplete component source file to your Git repository. ```bash git add resources/js/autocomplete.js git commit -m "feat: add Alpine autocomplete component source" ``` -------------------------------- ### Livewire Test Fixture for Filament Forms Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md A Livewire component fixture used for testing Filament form components, implementing HasForms and InteractsWithForms traits. ```php field = $field; $this->form->fill(); } public function form(Schema $schema): Schema { return $schema ->components([$this->field]) ->statePath('data'); } public function render() { return <<<'BLADE'
{{ $this->form }}
BLADE; } } ``` -------------------------------- ### Commit Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Commit the implemented code and tests for preparing static options for the AutocompleteInput component. ```bash git add src/Forms/Components/AutocompleteInput.php tests/Unit/PrepareOptionsTest.php git commit -m "feat: prepare static options for the Alpine component" ``` -------------------------------- ### Test Invalid Configuration: Both Sources Set Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md This test verifies that an InvalidArgumentException is thrown when both static options and a server-side search callback are provided to the AutocompleteInput. ```php options([['value' => 1, 'label' => 'A']]) ->getSearchResultsUsing(fn (string $s) => []); $field->getOptionsForJs(); })->throws(InvalidArgumentException::class, 'both'); ``` -------------------------------- ### Commit Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md This bash command stages and commits the modified AutocompleteInput.php and ValidationTest.php files with a descriptive commit message. ```bash git add src/Forms/Components/AutocompleteInput.php tests/Unit/ValidationTest.php git commit -m "feat: validate AutocompleteInput configuration" ``` -------------------------------- ### AutocompleteInput Field API Configuration Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/specs/2026-06-12-filament-textinput-autocomplete-design.md Configure the AutocompleteInput component by setting options, search keys, custom search logic, item views, and display/value keys. It also allows for controlling search behavior like minimum characters, debounce time, and maximum results. ```php AutocompleteInput::make('field') ->options(array | Closure) // static client-side source ->searchKeys(['label', 'description']) // item keys matched in static mode ->getSearchResultsUsing(Closure) // server mode; receives string $search ->itemView(string | Closure) // view name | raw-HTML closure | string template ->optionLabel('label') // item key shown in the input on select ->optionValue('value') // item key stored as form state ->minChars(1) ->searchDebounce(300) ->maxResults(10) ->placeholder('...') ->noResultsMessage('No results found') ->loadingMessage('Loading...') ->afterSelected(Closure); ``` -------------------------------- ### Pest Test Bootstrap Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Configures Pest to use the custom TestCase for all tests within the tests directory. ```php in(__DIR__); ``` -------------------------------- ### Register Fixture View Directory in TestCase Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Adds a custom namespace for fixture views to the Laravel application environment. This is necessary for Filament to locate and render custom Blade views for item rendering. ```php protected function defineEnvironment($app): void { $app['view']->addNamespace('test-fixtures', __DIR__ . '/views'); } ``` -------------------------------- ### Filament Form Component Render Test Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Tests that the AutocompleteInput component renders correctly within a Filament Livewire schema, asserting the presence of a specific CSS class. ```php AutocompleteInput::make('country') ->options([['value' => 1, 'label' => 'Spain']]), ]) ->assertOk() ->assertSee('fi-ac-wrapper', escape: false); }); ``` -------------------------------- ### Test: Default Item Rendering (Escaped Label) Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Tests the default behavior of `renderItem` where it escapes the 'label' attribute of the item. This ensures basic security against XSS attacks. ```php it('renders the escaped label by default', function () { $field = AutocompleteInput::make('q'); $html = callRenderItem($field, ['label' => 'A & B']); expect($html)->toBe('A & B'); }); ``` -------------------------------- ### Commit Autocomplete View Changes Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Stages and commits the newly created Blade view file for the autocomplete input component to the Git repository. ```bash git add resources/views/forms/components/autocomplete-input.blade.php git commit -m "feat: add autocomplete field blade view" ``` -------------------------------- ### AutocompleteInput Component Class Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md Defines the AutocompleteInput component for Filament, including properties for options, search keys, and various display messages. Use this class to extend Filament's form capabilities with autocomplete functionality. ```php options = $options; return $this; } public function searchKeys(array | Closure $keys): static { $this->searchKeys = $keys; return $this; } public function getSearchResultsUsing(Closure $callback): static { $this->getSearchResultsUsing = $callback; return $this; } public function itemView(string | Closure $view): static { $this->itemView = $view; return $this; } public function optionLabel(string | Closure $key): static { $this->optionLabel = $key; return $this; } public function optionValue(string | Closure $key): static { $this->optionValue = $key; return $this; } public function minChars(int | Closure $count): static { $this->minChars = $count; return $this; } public function searchDebounce(int | Closure $ms): static { $this->searchDebounce = $ms; return $this; } public function maxResults(int | Closure $count): static { $this->maxResults = $count; return $this; } public function noResultsMessage(string | Closure $message): static { $this->noResultsMessage = $message; return $this; } public function loadingMessage(string | Closure $message): static { $this->loadingMessage = $message; return $this; } public function afterSelected(Closure $callback): static { $this->afterSelected = $callback; return $this; } public function getOptions(): ?array { return $this->evaluate($this->options); } public function getSearchKeys(): array { return $this->evaluate($this->searchKeys); } public function hasServerSearch(): bool { return $this->getSearchResultsUsing !== null; } public function getOptionLabel(): string { return $this->evaluate($this->optionLabel); } public function getOptionValue(): string { return $this->evaluate($this->optionValue); } public function getMinChars(): int { return $this->evaluate($this->minChars); } public function getSearchDebounce(): int { return $this->evaluate($this->searchDebounce); } public function getMaxResults(): int { return $this->evaluate($this->maxResults); } public function getNoResultsMessage(): string { return $this->evaluate($this->noResultsMessage); } public function getLoadingMessage(): string { return $this->evaluate($this->loadingMessage); } } ``` -------------------------------- ### Helper Function for Reflection Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md A helper function to access the protected `renderItem` method of the AutocompleteInput component using PHP Reflection. This is used in tests to invoke the method. ```php setAccessible(true); return $method->invoke($field, $item); } ``` -------------------------------- ### Fixture Blade View for Item Rendering Source: https://github.com/giacomomasseron/filament-textinput-autocomplete/blob/main/docs/superpowers/plans/2026-06-12-filament-textinput-autocomplete.md A simple Blade view used as a fixture to test custom item rendering. It displays the 'label' attribute of the item within a span with a specific class. ```blade {{ $item['label'] }} ```