Single Directory Trait
The SingleDirectoryObjectListTrait trait can be used with ObjectListTrait to replicate behaviour similar to SDC, where component PHP code and assets (CSS and JavaScript) files are colocated, and then organised by component specific directories.
namespace Drupal\my_module\Pinto;
use Pinto\List\ObjectListTrait;
use Drupal\pinto\List\SingleDirectoryObjectListTrait;
enum MyComponents: string implements ObjectListInterface {
use ObjectListTrait;
use SingleDirectoryObjectListTrait;
public function directory(): string {
return '/a/directory/with/shared/resources';
}
}Example
Here, a design system module for a site has a list with references to all components.
The
#[Definition]attribute references components in a different module.The single directory trait resolves the PHP class, template, and assets (JS and CSS) to the same directory where the PHP component is located, using PHP reflection.
The
templateName()method is overridden to customize the template file name. Since only one HTML file in a directory is used, the file name is normalized totemplate.html.twig. Otherwise, the enum name would be used, in this case:mycomponent.html.twig.
modules
├─ my_ds
│ └─ src
│ └─ Pinto
│ └─ MyComponents.php
└─ my_components
└─ src
└─ Components
└─ MyComponent
├─ MyComponent.php
├─ template.html.twig
├─ styles.css
└─ script.js// my_ds/src/Pinto/MyComponents.php
namespace Drupal\my_ds\Pinto;
use Drupal\my_components\Components\MyComponent\MyComponent;
use Drupal\pinto\List\SingleDirectoryObjectListTrait;
use Pinto\Attribute\ObjectType\Slots;
use Pinto\List\ObjectListTrait;
#[Slots(bindPromotedProperties: true)]
enum MyComponents implements ObjectListInterface {
use ObjectListTrait;
use SingleDirectoryObjectListTrait;
#[Definition(MyComponent::class)]
case MyComponent;
public function templateName(): string {
// Customise Twig file name to template.html.twig.
return 'template';
}
public function directory(): string {
return '/the/directory/containing/the/component/class/';
}
}// my_components/src/Components/MyComponent/MyComponent.php
namespace Drupal\my_components\Components\MyComponent;
use \Pinto\Attribute\Asset\Css;
use \Pinto\Attribute\Asset\Js;
#[Js('script.js')]
#[Css('styles.css')]
final readonly class MyComponent {
public function __construct(
public readonly string $title,
) {}
}<!-- my_components/src/Components/MyComponent/template.html.twig -->
<div class="my-component">
{{ title }}
</div>/* my_components/src/Components/MyComponent/script.js */
console.log('Hello World!');/* my_components/src/Components/MyComponent/styles.css */
.my-component {
border: 2px solid orange;
}