daikazu/filament-size-visualizer-field
Adds an interactive visual preview to size inputs in Filament forms, so users can see dimensions, font sizes, or spacing as they edit instead of guessing from a number. Drop it into any resource or form to replace plain numeric fields with a clearer, WYSIWYG-style size control.
This package ships a Filament form component that renders an interactive size visualizer (product silhouette, coin, size circle, pattern square) over a snapping grid using fabric.js. v2 is a hard jump forward: PHP 8.3+, Laravel 13, Filament v5, Tailwind v4 only. If you are on Laravel 10/11/12 or Filament v3, stay on 1.x — there is no compatibility shim.
Install and wire it up:
composer require <vendor>/<package>:^2.0
php artisan vendor:publish --tag="<package>-assets" # compiled CSS/JS
php artisan filament:assets
Confirm your panel is on Filament v5 and your app build is on the Tailwind v4 toolchain (@tailwindcss/cli) before adding the field — v2 removed tailwind.config.js and postcss.config.js, so any custom theme tokens must move to CSS-first @theme blocks in your app stylesheet, or the component's utility classes will resolve differently than the rest of your panel.
First use case — a product/size picker on a jewelry or furniture resource form:
use Vendor\Package\Forms\Components\SizeVisualizer;
public static function form(Form $form): Form
{
return $form->schema([
SizeVisualizer::make('size')
->productImage('images/ring.png')
->coin(true) // reference coin for real-world scale
->patternSquare(true), // texture/pattern preview
]);
}
Where to look first: the published config (object defaults, image disk, grid step), then the field class itself for the fluent setters. The resize-size-visualizer and dispose-size-visualizer browser events are now documented — those are your extension hooks.
Bind to Livewire state via entangle. The component reads its value from an Alpine-entangled Livewire property. Keep the state path scalar (an int/float size), not an object — v2 coerces the entangled value before geometry math, but strings like "52" are safer than nested arrays:
SizeVisualizer::make('size')
->live() // pushes changes back on interaction
->afterStateUpdated(fn ($state, Set $set) => $set('price', Price::for((int) $state))),
Drive animations from state, not from DOM surgery. v2 splits rendering into a static grid layer and an animated object layer, with ease-out transitions on the product, coin, size circle, and pattern square while the grid snaps to each step. That means you should change the value and let the component animate — never try to reach into the canvas to move objects yourself, because wire:ignore protects fabric's DOM and your mutations will be invisible to Livewire's diff.
Toggle reference objects reactively. The coin and pattern square are meant to be toggled. Expose them as form toggles bound to the same schema and let the component react:
Toggle::make('show_coin')->live()->default(true),
SizeVisualizer::make('size')->coin(fn (Get $get) => $get('show_coin')),
React to layout changes with the documented events. Because the canvas is wire:ignored, resizing a container or opening a modal needs an explicit nudge. Dispatch the documented event instead of remounting:
// after a sidebar collapse, tab switch, or modal resize
window.dispatchEvent(new CustomEvent('resize-size-visualizer'));
Use dispose-size-visualizer in the same spirit when you build custom Alpine wrappers around the field — it tears down fabric's canvas and listeners; the component already manages its own window listeners via Alpine so SPA navigation doesn't leak.
Use it in modals and repeaters with care. Filament action modals mount the schema fresh, so the component initialises cleanly; repeaters re-render rows, which is exactly the case wire:ignore was added for. If you nest it in a repeater, give each row a distinct state path so entangle targets don't collide.
dynamicObjectSize() and getDynamicObjectSize() are gone. They were never wired to rendering, so callers saw no visual change — but any code calling them now fatals. Grep for both names before bumping.tailwind.config.js with a content array covering vendor views, your component styles may purge out. Move to CSS-first config and ensure the package's views are in the @source globs.setDimensions() assumptions — this is the most likely place for a hand-rolled image tweak to break.wire:ignore. If you still see a blank canvas, you are either on a stale published asset bundle (php artisan filament:assets / hard refresh) or you removed the x-load directive in a custom view — v2 relies on it to actually load the component.null, an empty string, or an array to a size field will silently compute nonsense rather than throw — validate with ->numeric()->required() on the Filament side.How can I help you explore Laravel packages today?