Stimulus v PHP striktněji

Martk
Člen | 652
+
+1
-

Pravděpodobně už jste zaslechli, že existuje něco jako Stimulus (https://stimulus.hotwired.dev/). Používám ho velmi často a už se mi nechtělo psát x data atributů, neustále chodit do javascript souborů abych zjistil co je povinné jakého typu, zjišťoval kde je typo nebo mě tracy neupozornilo, že controller vlastně nechce string, ale int, nemusím myslet jak se píše data-action, data-target apod.

Proto jsem vytvořil generátor, který promění javascript controller na PHP type-safe controller a rozhodl jsem se o něj podělit, protože to umí dost šikovných věcí. PHP controllery generuje přes komentáře, má to tu výhodu, že mě to donutí psát typesafe anotace v js, takže win-win.

Mějme například ui/dropdown_controller.js

/**
 * @controller
 *
 * @property {Number[]} offsetValue { number: int }
 * @property {Boolean} hasOffsetValue
 * @property {String} placementValue
 * @property {Boolean} hasPlacementValue
 *
 * @property {HTMLElement} toggleTarget
 */
export default class extends StimulusController {

	static targets = ['toggle'];

	static values = {
		placement: String,
		offset: Array,
	};

	/**
	 * @var {Dropdown}
	 */
	#dropdown;

	connect() {
		this.toggleTarget.dataset.bsToggle = 'dropdown';

		this.#dropdown = new Dropdown(this.toggleTarget, {
			popperConfig: (config) => {
				config.placement = this.hasPlacementValue ? this.placementValue : 'bottom-end';
				if (this.hasOffsetValue) {
					config.modifiers[1].options.offset = this.offsetValue;
				}

				return config;
			},
		});
	}

	/**
	 * @action
	 */
	hide() {
		this.#dropdown.hide();
	}

	disconnect() {
		this.#dropdown.dispose();
	}
}

Tohle vygeneruje tento PHP kód:

<?php declare(strict_types = 1);

/**
 * NOTE: This class is auto generated by file: ui/dropdown_controller.js
 * Do not edit the class manually
 */

namespace Stimulus\UI;

use WebChemistry\Stimulus\Type\StimulusAction;
use WebChemistry\Stimulus\Type\StimulusController;
use WebChemistry\Stimulus\Type\StimulusTarget;

abstract class DropdownController
{

	final public const identifier = 'ui--dropdown';

	/**
	 * @param array<int> $offsetValue
	 */
	public static function construct(?array $offsetValue = null, ?string $placementValue = null): StimulusController
	{
		return new StimulusController(self::identifier, [
			'offsetValue' => $offsetValue,
			'placementValue' => $placementValue,
		], []);
	}

	public static function hideAction(): StimulusAction
	{
		return new StimulusAction(self::identifier, 'hide', []);
	}

	public static function toggleTarget(): StimulusTarget
	{
		return new StimulusTarget(self::identifier, 'toggleTarget');
	}

}

A použití je příjemnější a striktnější:

<div
	n:stimulus="
		Stimulus\UI\DropdownController::construct(offsetValue: [15, 15]),
		Stimulus\UI\DropdownController::toggleTarget(),
		Stimulus\UI\DropdownController::hideAction()->event('click'),
	"
></div>

Chceme použít ve formulářích nebo jinde v PHP?

$form->getElementPrototype()
		->addAttributes(HtmlRenderer::toArray(DropdownController::construct()));

Už jen čekám až @mesour vydá latte pro a budu moci plně využít s InlayParameterHints, našeptávání parametrů, refactoring. Pak ještě statická analýza v latte a bude to bomba.

Github: https://github.com/…try/stimulus
Packagist: webchemistry/stimulus