withId('counter:test') * ->withState(['count' => 0]) * ->create(); * * // Component with custom actions * $component = ComponentFactory::make() * ->withId('posts:manager') * ->withState(['posts' => []]) * ->withAction('addPost', function(string $title) { * $this->state['posts'][] = $title; * return ComponentData::fromArray($this->state); * }) * ->create(); * ``` */ final class ComponentFactory { private string $id = 'test:component'; private array $initialState = []; private array $actions = []; private ?string $template = null; private function __construct() { } /** * Create new factory instance */ public static function make(): self { return new self(); } /** * Set component ID */ public function withId(string $id): self { $this->id = $id; return $this; } /** * Set initial state * * @param array $state Initial state data */ public function withState(array $state): self { $this->initialState = $state; return $this; } /** * Add custom action * * @param string $name Action method name * @param callable $handler Action handler */ public function withAction(string $name, callable $handler): self { $this->actions[$name] = $handler; return $this; } /** * Set template name */ public function withTemplate(string $template): self { $this->template = $template; return $this; } /** * Create component instance */ public function create(): LiveComponentContract { $componentId = ComponentId::fromString($this->id); $initialState = $this->initialState; $actions = $this->actions; $template = $this->template ?? 'test-component'; return new class ($componentId, $initialState, $actions, $template) implements LiveComponentContract { private array $state; public function __construct( private ComponentId $id, array $initialState, private array $actions, private string $template ) { $this->state = $initialState; } public function getId(): ComponentId { return $this->id; } public function getData(): ComponentData { return ComponentData::fromArray($this->state); } public function getRenderData(): ComponentRenderData { return new ComponentRenderData($this->template, $this->state); } public function __call(string $method, array $arguments): mixed { if (isset($this->actions[$method])) { // Bind action to this component instance $action = $this->actions[$method]->bindTo($this, self::class); return $action(...$arguments); } throw new \BadMethodCallException("Method {$method} not found on test component"); } }; } /** * Create simple counter component * * Pre-configured counter with increment/decrement/reset actions. */ public static function counter(int $initialCount = 0): LiveComponentContract { return self::make() ->withId('counter:test') ->withState(['count' => $initialCount]) ->withAction('increment', function () { $this->state['count']++; return ComponentData::fromArray($this->state); }) ->withAction('decrement', function () { $this->state['count']--; return ComponentData::fromArray($this->state); }) ->withAction('reset', function () { $this->state['count'] = 0; return ComponentData::fromArray($this->state); }) ->create(); } /** * Create simple list component * * Pre-configured list with add/remove actions. * * @param array $initialItems Initial list items */ public static function list(array $initialItems = []): LiveComponentContract { return self::make() ->withId('list:test') ->withState(['items' => $initialItems]) ->withAction('addItem', function (string $item) { $this->state['items'][] = $item; return ComponentData::fromArray($this->state); }) ->withAction('removeItem', function (int $index) { array_splice($this->state['items'], $index, 1); return ComponentData::fromArray($this->state); }) ->withAction('clear', function () { $this->state['items'] = []; return ComponentData::fromArray($this->state); }) ->create(); } }