$options Key-value pairs for options */ public function __construct( public string $name, public array $options, public ?string $selected = null, public ?string $label = null, public ?string $id = null, public ?string $placeholder = null, public bool $required = false, public bool $disabled = false, public bool $multiple = false, public ?string $errorMessage = null, public HtmlAttributes $additionalAttributes = new HtmlAttributes() ) { $this->tag = new HtmlTag(TagName::DIV); $this->attributes = HtmlAttributes::empty()->withClass('form-group'); $this->content = $this->buildContent(); } public static function create( string $name, array $options, ?string $label = null ): self { return new self(name: $name, options: $options, label: $label); } public function withSelected(string $selected): self { return new self( name: $this->name, options: $this->options, selected: $selected, label: $this->label, id: $this->id, placeholder: $this->placeholder, required: $this->required, disabled: $this->disabled, multiple: $this->multiple, errorMessage: $this->errorMessage, additionalAttributes: $this->additionalAttributes ); } public function withRequired(bool $required = true): self { return new self( name: $this->name, options: $this->options, selected: $this->selected, label: $this->label, id: $this->id, placeholder: $this->placeholder, required: $required, disabled: $this->disabled, multiple: $this->multiple, errorMessage: $this->errorMessage, additionalAttributes: $this->additionalAttributes ); } public function withMultiple(bool $multiple = true): self { return new self( name: $this->name, options: $this->options, selected: $this->selected, label: $this->label, id: $this->id, placeholder: $this->placeholder, required: $this->required, disabled: $this->disabled, multiple: $multiple, errorMessage: $this->errorMessage, additionalAttributes: $this->additionalAttributes ); } public function withError(string $errorMessage): self { return new self( name: $this->name, options: $this->options, selected: $this->selected, label: $this->label, id: $this->id, placeholder: $this->placeholder, required: $this->required, disabled: $this->disabled, multiple: $this->multiple, errorMessage: $errorMessage, additionalAttributes: $this->additionalAttributes ); } private function buildContent(): string { $selectId = $this->id ?? "select-{$this->name}"; $attributes = HtmlAttributes::empty() ->withName($this->name) ->withId($selectId) ->withClass('form-select'); if ($this->required) { $attributes = $attributes->withRequired(); } if ($this->disabled) { $attributes = $attributes->withDisabled(); } if ($this->multiple) { $attributes = $attributes->with('multiple', 'multiple'); } if ($this->errorMessage !== null) { $attributes = $attributes ->withClass('form-select--error') ->with('aria-invalid', 'true') ->with('aria-describedby', "{$selectId}-error"); } // Merge additional attributes foreach ($this->additionalAttributes->attributes as $name => $value) { $attributes = $attributes->with($name, $value); } // Build options $optionElements = []; if ($this->placeholder !== null) { $optionElements[] = StandardHtmlElement::create( TagName::OPTION, HtmlAttributes::empty() ->withValue('') ->withDisabled() ->withSelected(), $this->placeholder ); } foreach ($this->options as $value => $text) { $optionAttrs = HtmlAttributes::empty()->withValue($value); if ($this->selected !== null && $value === $this->selected) { $optionAttrs = $optionAttrs->withSelected(); } $optionElements[] = StandardHtmlElement::create( TagName::OPTION, $optionAttrs, $text ); } $selectContent = implode('', array_map('strval', $optionElements)); $elements = []; // Label if ($this->label !== null) { $labelAttrs = HtmlAttributes::empty() ->withClass('form-label') ->with('for', $selectId); if ($this->required) { $labelAttrs = $labelAttrs->withClass('form-label--required'); } $elements[] = StandardHtmlElement::create( TagName::LABEL, $labelAttrs, $this->label ); } // Select $elements[] = StandardHtmlElement::create( TagName::SELECT, $attributes, $selectContent ); // Error message if ($this->errorMessage !== null) { $elements[] = StandardHtmlElement::create( TagName::SPAN, HtmlAttributes::empty() ->withClass('form-error') ->withId("{$selectId}-error") ->with('role', 'alert'), $this->errorMessage ); } return implode('', array_map('strval', $elements)); } public function __toString(): string { return (string) StandardHtmlElement::create( $this->tag->name, $this->attributes, $this->content ); } }