{"id":24488034,"url":"https://github.com/stillat/dagger","last_synced_at":"2025-04-05T05:02:24.258Z","repository":{"id":273309667,"uuid":"919276521","full_name":"Stillat/dagger","owner":"Stillat","description":"A robust component authoring library for Laravel Blade.","archived":false,"fork":false,"pushed_at":"2025-02-27T01:31:29.000Z","size":249,"stargazers_count":144,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T05:01:47.167Z","etag":null,"topics":["blade","laravel","laravel-package"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Stillat.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"johnathonkoster"}},"created_at":"2025-01-20T05:08:14.000Z","updated_at":"2025-04-02T07:19:38.000Z","dependencies_parsed_at":"2025-01-20T06:25:09.399Z","dependency_job_id":"cd368d46-5d27-41fc-9903-1f9eefa7c6f8","html_url":"https://github.com/Stillat/dagger","commit_stats":null,"previous_names":["stillat/dagger"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Fdagger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Fdagger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Fdagger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Fdagger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Stillat","download_url":"https://codeload.github.com/Stillat/dagger/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289409,"owners_count":20914464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blade","laravel","laravel-package"],"created_at":"2025-01-21T16:18:08.757Z","updated_at":"2025-04-05T05:02:24.237Z","avatar_url":"https://github.com/Stillat.png","language":"PHP","funding_links":["https://github.com/sponsors/johnathonkoster"],"categories":[],"sub_categories":[],"readme":"# Dagger Components for Laravel Blade\n\nDagger is a component authoring library for Laravel's Blade templating engine. Dagger components are heavily inspired by Laravel's [anonymous components](https://laravel.com/docs/blade#anonymous-components). Dagger's differentiating features are its compiler and expanded capabilities.\n\nThe Dagger compiler works hard to inline your component's code, perform various optimizations, as well as enable powerful new features, such as the [Attribute Cache](#attribute-cache), [Attribute Forwarding](#attribute-forwarding), and [Slot Forwarding](#slot-forwarding). The end result is a powerful, performant component authoring library with a familiar syntax.\n\nThe main visual difference when working with Dagger components is the use of the `\u003cc-` prefix instead of `\u003cx-`, this is to help differentiate them from Blade components and make interoperability easier:\n\n```blade\n\u003c!-- /resources/dagger/views/alert.blade.php --\u003e\n\n@props(['type' =\u003e 'info', 'message'])\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message }}\n\u003c/div\u003e\n```\n\n```blade\n\u003c!-- /resources/views/layout.blade.php --\u003e\n\n\u003cc-alert type=\"error\" :message=\"$message\" class=\"mb-4\"/\u003e\n```\n\n- [Frequently Asked Questions](#frequently-asked-questions)\n- [Installation](#installation)\n- [Dagger Component View Paths](#dagger-component-view-paths)\n  - [Index Components](#index-components)\n  - [Moving Dagger Component Views](#moving-dagger-component-views)\n- [Component Syntax and the Component Builder](#component-syntax-and-the-component-builder)\n  - [Slots](#slots)\n    - [Named/Scoped Slots](#namedscoped-slots)\n  - [Custom PHP When Using the Component Function](#custom-php-when-using-the-component-function)\n  - [Calling Component Builder Methods](#calling-component-builder-methods)\n  - [Renaming the Component Variable](#renaming-the-component-variable)\n- [Data Properties/Attributes](#data-properties--attributes)\n- [Notes on Conditional aware and props Directives](#notes-on-conditional-aware-and-props-directives)\n- [Accessing Parent Data](#accessing-parent-data)\n  - [Using the aware Directive](#using-the-aware-directive)\n  - [Using the aware Builder Method](#using-the-aware-builder-method)\n  - [Accessing Arbitrary Parent Data](#accessing-arbitrary-parent-data)\n  - [Aware Variables and Attributes](#aware-variables-and-attributes)\n- [Property Validation](#property-validation)\n  - [Shorthand Validation Rules](#shorthand-validation-rules)\n- [Compiler Attributes](#compiler-attributes)\n  - [Escaping Compiler Attributes](#escaping-compiler-attributes)\n- [Caching Components](#caching-components)\n  - [Dynamic Cache Keys](#dynamic-cache-keys)\n  - [Specifying the Cache Store](#specifying-the-cache-store)\n  - [Stale While Revalidate/Flexible Caching](#stale-while-revalidate-flexible-cache)\n- [Component Name](#component-name)\n- [Component Depth](#component-depth)\n- [Attribute Forwarding](#attribute-forwarding)\n  - [Nested Attribute Forwarding](#nested-attribute-forwarding)\n  - [Variable Bindings and Attribute Forwarding](#variable-bindings-and-attribute-forwarding)\n- [Slot Forwarding](#slot-forwarding)\n  - [Nested Slot Forwarding](#nested-slot-forwarding)\n- [Output Trimming](#output-trimming)\n- [Stencils](#stencils)\n  - [Rendering Default Stencil Content](#rendering-default-stencil-content)\n  - [Additional Notes on Stencils](#additional-notes-on-stencils)\n- [Mixins](#mixins)\n  - [Mixin Methods](#mixin-methods)\n  - [Accessing the Component Instance Inside Mixins](#accessing-the-component-instance-inside-mixins)\n  - [Additional Notes on Mixins](#additional-notes-on-mixins)\n- [Attribute Cache](#attribute-cache)\n  - [Slot Variables and the Attribute Cache](#slot-variables-and-the-attribute-cache)\n  - [Considerations](#considerations)\n- [Static Template Optimizations](#static-template-optimizations)\n- [Dynamic Components](#dynamic-components)\n- [Custom Component Paths and Namespaces](#custom-component-paths-and-namespaces)\n  - [Blade Component Prefix](#blade-component-prefix)\n- [Compile Time Rendering](#compile-time-rendering)\n  - [Disabling Compile Time Rendering on a Component](#disabling-compile-time-rendering-on-a-component)\n  - [Enabling/Disabling Optimizations on Classes or Methods](#enablingdisabling-optimizations-on-classes-or-methods)\n  - [Notes on Compile Time Rendering](#notes-on-compile-time-rendering)\n- [The View Manifest](#the-view-manifest)\n- [License](#license)\n\n## Frequently Asked Questions\n\n- [How does the Dagger compiler differ from Laravel's component compiler?](#how-does-the-dagger-compiler-differ-from-laravels-component-compiler)\n- [Is an additional build step required?](#is-an-additional-build-step-required)\n- [Are class-based components supported?](#are-class-based-components-supported)\n- [Will this magically make my existing Blade components faster?](#will-this-magically-make-my-existing-blade-components-faster)\n- [Can I use regular Blade components with Dagger components?](#can-i-use-regular-blade-components-with-dagger-components)\n- [Why are there JSON files in my compiled view folder?](#why-are-there-json-files-in-my-compiled-view-folder)\n- [Are circular component hierarchies supported?](#are-circular-component-hierarchies-supported)\n- [Why build all of this?](#why-build-all-of-this)\n\n### How does the Dagger compiler differ from Laravel's component compiler?\n\nThe Dagger compiler is a multi-stage compiler that recursively parses and compiles a component's template ahead of time. Components compiled with the Dagger compiler will become *part of the view's* compiled output. Because of this, Laravel's related view events will *not* be fired when Dagger components are loaded.\n\n### Is an additional build step required?\n\nAn additional build step is *not* required. Dagger components will be compiled the first time you load your views. [Dynamic Components](#dynamic-components) will be compiled automatically the first time they are encountered.\n\n### Are class-based components supported?\n\nDagger only supports anonymous components, and there are no plans to support class-based components at this time. However, you may use [Mixins](#mixins) to gain back some of the benefits of class-based components when authoring Dagger components.\n\n### Will this magically make my existing Blade components faster?\n\nNo. The Dagger compiler only interacts with components using one of the registered component prefixes (`\u003cc-`, by default). While great care has been taken to support Laravel's features, such as `@props`, `@aware`, slots, etc., certain features, such as the attribute cache, may subtly change the behavior of components if they were not designed with these features in mind.\n\nConverting existing anonymous components to Dagger components is a relatively painless process, however.\n\n### Can I use regular Blade components with Dagger components?\n\nYes. You may use both Blade and Dagger components within the same project.\n\nDagger components are also interopable with Blade components, and will add themselves to Laravel's component stack, making it seamless to use both. Because of this, you can use features such as `@props` and `@aware` between Dagger and Blade components like normal.\n\n### Why are there JSON files in my compiled view folder?\n\nThis is due to the View Manifest. The Dagger compiler and runtime will store which component files were used to create the final output in a JSON file, which is later used for cache-invalidation. The Dagger compiler inlines component templates, which prevents typical file-based cache invalidation from working; the View Manifest solves that problem.\n\n### Why build all of this?\n\nBecause I wanted to.\n\nBut more specifically, I am working on a number of projects that involve *a lot* of components and wanted to reduce the amount of overhead. Additionally, I also wanted to explore what could be done with a more advanced/involved compilation step to support features like Attribute Forwarding, Slot Forwarding, and the Attribute Cache.\n\n## Installation\n\nDagger requires at *least* Laravel version 11.9 and PHP 8.2.\n\nTo install Dagger, you may run the following:\n\n```bash\ncomposer require stillat/dagger\n```\n\nAfterwards you can run the following Artisan command to scaffold the required paths if you'd like to build Dagger components within your application:\n\n```bash\nphp artisan dagger:install\n```\n\nAfter running the `dagger:install` command, you will find new directories within your application's resources directory:\n\n```text\nresources/\n  dagger/\n    views/\n```\n\n## Dagger Component View Paths\n\nThe views for Dagger components will live in `resources/dagger/views/` instead of `resources/views/components`. This is to help differentiate them from Blade's anonymous components. The rules for Dagger component paths are the same as those for Blade's anonymous components.\n\nIf you had defined a component at `resources/dagger/views/alert.blade.php`, you may render it like so:\n\n```blade\n\u003cc-alert /\u003e\n```\n\nLike with Blade's anonymous components, you may use the `.` character to indicate if a component is contained within a sub-directory. For a component defined at `resources/dagger/views/inputs/button.blade.php`, you may render it like so:\n\n```blade\n\u003cc-inputs.button /\u003e\n```\n\n### Index Components\n\nDagger components follow the same rules as Laravel's [Anonymous Index Components](https://laravel.com/docs/blade#anonymous-index-components), allowing you to group components into their own self-contained directories.\n\nAssuming the following component directory structure:\n\n```text\n/resources/dagger/views/accordion.blade.php\n/resources/dagger/views/accordion/item.blade.php\n```\n\nYou could render the accordion component and the nested item like so:\n\n```blade\n\u003cc-accordion\u003e\n    \u003cc-accordion.item\u003e\n        ...\n    \u003c/c-accordion.item\u003e\n\u003c/c-accordion\u003e\n```\n\nIf you'd prefer to not have the \"root\" view be located within the `/resources/dagger/views/` directory, you may create a file with the same name as the component within the component's directory:\n\n```text\n/resources/dagger/views/accordion/accordion.blade.php\n/resources/dagger/views/accordion/item.blade.php\n```\n\nAlternatively, you may also create a view named `index` within the component's directory:\n\n```text\n/resources/dagger/views/accordion/index.blade.php\n/resources/dagger/views/accordion/item.blade.php\n```\n\n### Moving Dagger Component Views\n\nWhile it is *strongly discouraged* to move Dagger components into Laravel's `resources/views/components` directory, it is technically possible, and you are free to do what you want in your own project. If you'd like to move the Dagger component path, you may add the following to your applications service provider:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Dagger\\Facades\\Compiler;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot(): void\n    {\n        Compiler::registerComponentPath(\n            'c',\n            resource_path('views/components')\n        );\n    }\n}\n```\n\nWhile you *can* do this, it will be difficult to tell Dagger and Blade components apart when they are commingled.\n\n## Component Syntax and the Component Builder\n\nThe syntax for Dagger components is very similar to Blade components. Instead of `\u003cx-`, you would use `\u003cc-`:\n\n```blade\n\u003cc-alert /\u003e\n```\n\nThe Dagger compiler supports Blade's `@props` and `@aware` directives, but also provides a new functional approach to defining components. When using the functional approach, the *first* thing within your component definition *must* be a PHP block, where the component is defined.\n\nThe following component definitions would produce identical output.\n\nUsing the component builder:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()-\u003eprops(['type' =\u003e 'info', 'message']);\n@endphp\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message }}\n\u003c/div\u003e\n```\n\nUsing Blade directives:\n\n```blade\n@props(['type' =\u003e 'info', 'message'])\n \n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message }}\n\u003c/div\u003e\n```\n\n### Slots\n\nDagger slots behave the same as Blade's component slots. Default slot content is specified between component tag pairs. Assuming the following component definition:\n\n```blade\n\u003c!-- /resources/dagger/views/item.blade.php --\u003e\n\n\u003cdiv {{ $attributes }}\u003e\n    {{ $slot }}\n\u003c/div\u003e\n```\n\nSlot content may be specified like so:\n\n```blade\n\u003cc-button class=\"bg-red-500 text-white\"\u003e\n    The Slot Content\n\u003c/c-button\u003e\n```\n\n#### Named/Scoped Slots\n\nDagger components also support named or *scoped* slots. Accessing scoped slots is done through the `$slots` variable, which is different from Blade components. This is done to help prevent collisions with variables that may have the same name as desireable slot names.\n\n\nAssuming the following component definition:\n\n```blade\n\u003c!-- /resources/dagger/views/panel.blade.php --\u003e\n\u003cdiv {{ $slots-\u003eheader-\u003eattributes }}\u003e\n    {{ $slots-\u003eheader }}\n\u003c/div\u003e\n\n{{ $slot }}\n\n\u003cdiv {{ $slots-\u003efooter-\u003eattributes }}\u003e\n    {{ $slots-\u003efooter }}\n\u003c/div\u003e\n```\n\nYou may specify content for each slot like so:\n\n```blade\n\u003cc-docs.namedslot\u003e\n    \u003cc-slot:header class=\"header classes here\"\u003e\n        Header Content\n    \u003c/c-slot:header\u003e\n    \n    \u003cc-slot:footer class=\"header classes here\"\u003e\n        Footer Content\n    \u003c/c-slot:footer\u003e\n    \n    Default Slot Content\n\u003c/c-docs.namedslot\u003e\n```\n\n### Custom PHP When Using the Component Function\n\nWhen using the functional syntax, it is important to note that PHP code that appears *before* the `component()` call may be removed from the compiled output. You can use this space to perform logic at compile time or set variables.\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\n// Danger zone.\n$myCustomVariable = 'the value';\n\ncomponent()-\u003eprops(['type' =\u003e 'info', 'message']);\n\n// Safe zone.\n@endphp\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message ?? $myCustomVariable }}\n\u003c/div\u003e\n```\n\nTo be safe, any custom PHP code you'd like to execute should appear after the `component()` call:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()-\u003eprops(['type' =\u003e 'info', 'message']);\n\n$myCustomVariable = 'the value';\n@endphp\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message ?? $myCustomVariable }}\n\u003c/div\u003e\n```\n\nThis does not apply to `use` statements and variable assignments. Any custom PHP code that appears before the `component()` call will be executed at *compile* time, however.\n\n### Calling Component Builder Methods\n\nWhen using the `component()` builder function, you should only call the `component()` function *once*. Do not make repeated calls to it:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()-\u003eprops(['type' =\u003e 'info', 'message']);\ncomponent()-\u003eaware(['message']); ❌\n@endphp\n\n...\n```\n\nInstead, always chain the builder methods:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()-\u003eprops(['type' =\u003e 'info', 'message'])\n    -\u003eaware(['message']); ✅\n@endphp\n\n...\n```\n\n### Renaming the Component Variable\n\nIf you'd like to rename the automatic `$component` variable within your component's definition, you may simply assign the results of the `component()` function to a variable:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\n$theAlert = component()-\u003eprops(['type' =\u003e 'info', 'message']);\n@endphp\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$theAlert-\u003etype]) }}\u003e\n    {{ $theAlert-\u003emessage }}\n\u003c/div\u003e\n```\n\n\u003e [!NOTE]\n\u003e The component instance will still be accessible via the `$component` variable inside slots, even if it has been renamed within the component itself. This is intentional to provide a consistent experience for component consumers.\n\n## Data Properties / Attributes\n\nTo ease development, and provide a familiar starting place, the Dagger compiler supports Blade's `@props` directive to help differentiate between which data is a *property* of the component, and what data should be placed inside the component's [attribute bag](https://laravel.com/docs/blade#component-attributes).\n\n```blade\n\u003c!-- /resources/dagger/views/alert.blade.php --\u003e\n\n@props(['type' =\u003e 'info', 'message'])\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message }}\n\u003c/div\u003e\n```\n\nGiven the component above, we may render it like so:\n\n```blade\n\u003cc-alert type=\"error\" :message=\"$message\" class=\"mb-4\"/\u003e\n```\n\nWe can also use the `props` component builder method to achieve the same results:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()-\u003eprops(['type' =\u003e 'info', 'message']);\n@endphp\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message }}\n\u003c/div\u003e\n```\n\n## Notes on Conditional aware and props Directives\n\nBoth the `@aware` and `@props` directives are supported by the Dagger compiler. However, because the compiler needs to know about their values ahead of time, conditional use of these directives is *not* supported in Dagger components.\n\nYou **must not** have Dagger component templates like the following:\n\n```blade\n@if ($someCondition)\n    @props(['title'])\n@else\n    @props(['title', 'somethingElse'])\n    @aware(['title'])\n@endif\n\n```\n\n## Accessing Parent Data\n\nYou have multiple options for accessing parent data from within a child component.\n\n- Using the aware directive\n- Using the aware Builder Method\n- Accessing Arbitrary Parent Data\n\n### Using the aware Directive\n\nThe most familiar option will be to use Blade's `@aware` directive.\n\nAssuming we had a menu component with a parent `\u003cc-menu\u003e` and a child `\u003cc-menu.item\u003e` component:\n\n```blade\n\u003cc-menu color=\"purple\"\u003e\n    \u003cc-menu.item\u003e...\u003c/c-menu.item\u003e\n    \u003cc-menu.item\u003e...\u003c/c-menu.item\u003e\n\u003c/c-menu\u003e\n```\n\nThe `\u003cc-menu\u003e` component may have an implementation like the following:\n\n```blade\n\u003c!-- /resources/dagger/views/menu/index.blade.php --\u003e\n \n@props([\n    'color' =\u003e 'gray'\n])\n \n\u003cul {{ $attributes-\u003emerge(['class' =\u003e 'bg-'.$color.'-200']) }}\u003e\n    {{ $slot }}\n\u003c/ul\u003e\n```\n\nBecause the `color` prop was passed into the parent (`\u003cc-menu\u003e`), it won't be immediately available inside `\u003cc-menu.item\u003e`. We can use the `@aware` directive to make that variable available inside `\u003cc-menu.item\u003e` as well:\n\n```blade\n\u003c!-- /resources/dagger/views/menu/item.blade.php --\u003e\n\n@aware([\n    'color' =\u003e 'gray'\n])\n\n\u003cli {{ $attributes-\u003emerge(['class' =\u003e 'text-'.$color.'-800']) }}\u003e\n    {{ $slot }}\n\u003c/li\u003e\n```\n\n### Using the aware Builder Method\n\nAlternatively, we may also use the `aware` builder method to specify variables that should be passed to our child component:\n\n```blade\n\u003c!-- /resources/dagger/views/menu/item.blade.php --\u003e\n\n@php\n    Stillat\\Dagger\\component()-\u003eaware(['color' =\u003e 'gray']);\n@endphp\n\n\u003cli {{ $attributes-\u003emerge(['class' =\u003e 'text-'.$color.'-800']) }}\u003e\n    {{ $slot }}\n\u003c/li\u003e\n```\n\n### Accessing Arbitrary Parent Data\n\nWe can also access the parent component instance directly using the `parent()` method:\n\n```blade\n\u003c!-- /resources/dagger/views/menu/item.blade.php --\u003e\n\n\u003cli {{ $attributes-\u003emerge(['class' =\u003e 'text-'.$component-\u003eparent()-\u003ecolor.'-800']) }}\u003e\n    {{ $slot }}\n\u003c/li\u003e\n```\n\nIf you are in a deeply nested component, you may access parent instances on parent instances:\n\n```blade\n{{ $component-\u003eparent()-\u003eparent()-\u003esomeValue }}\n```\n\nYou may also supply the name of the parent component you'd like to retrieve data from. Doing so will return access to the *nearest* parent instance with that name:\n\n```blade\n{{ $component-\u003eparent('nav')-\u003esomeValue }}\n```\n\n### Aware Variables and Attributes\n\nAware variables will automatically be added to the component's props list, preventing them from appearing in the attribute bag.\n\n```blade\n\u003c!-- /resources/dagger/views/menu/index.blade.php --\u003e\n@props(['color'])\n\n\u003cul\u003e\n  {{ $slot}}\n\u003c/ul\u003e\n```\n\n```blade\n\u003c!-- /resources/dagger/views/menu/item.blade.php --\u003e\n@aware(['color']) // \"color\" will be automatically added to the component's props.\n\n\u003cli {{ $attributes }}\u003e{{ $slot }}\u003c/li\u003e\n```\n\n## Property Validation\n\nYou may use Laravel's [validation](https://laravel.com/docs/validation) features to validate the *props* of your Dagger components. To do this, you may use the `validateProps` builder method to specify the prop and validation rules you'd like to enforce. As an example, the following would ensure that a `title` property was supplied to the `button` component:\n\n```blade\n\u003c!-- /resources/dagger/views/button.blade.php --\u003e\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()\n    -\u003eprops(['title'])\n    -\u003evalidateProps([\n        'title' =\u003e 'required',\n    ]);\n@endphp\n\n{{ $title }}\n```\n\nThe following would not trigger a validation error:\n\n```blade\n\u003cc-button title=\"The Title\" /\u003e\n```\n\nwhile the following would:\n\n```blade\n\u003cc-button /\u003e\n```\n\nThe following data sources are also considered when validating components:\n\n- Data made available via. the `aware` builder method or directive\n- Data provided by mixins\n\n### Shorthand Validation Rules\n\nIf you are using only string-based validation rules, you can skip the additional method call and specify them on the props directly. To do this, separate the prop name from the rules using the `|` character:\n\n```blade\n\u003c!-- /resources/dagger/views/button.blade.php --\u003e\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()\n    -\u003eprops(['title|required']);\n@endphp\n\n{{ $title }}\n```\n\nYou can still specify default prop values when adding shorthand validation rules:\n\n```blade\n@php\nuse function Stillat\\Dagger\\component;\n\ncomponent()\n    -\u003eprops([\n        'size|numeric|min:1|max:5' =\u003e 3,\n    ]);\n@endphp\n\nThe Size: {{ $size }}\n```\n\n## Compiler Attributes\n\nThe Dagger compiler introduces the concept of \"compiler attributes\", which have special meaning to the compiler. The most common of these is the `#id` attribute, which may be used to name a nested component:\n\n```blade\n\u003c!-- /resources/dagger/views/component.blade.php --\u003e\n\n\u003cc-nested.component #id=\"theNestedComponentName\" /\u003e\n```\n\nCompiler attribute values **must** be static and **cannot** contain PHP expressions or reference variables.\n\n### Escaping Compiler Attributes\n\nIf you need to output an attribute beginning with `#`, you may escape compiler attributes by prefixing it with another `#` character:\n\n```blade\n\u003c!-- /resources/dagger/views/component.blade.php --\u003e\n\n\u003cc-nested.component ##id=\"the-escaped-id-attribute\" /\u003e\n```\n\nIn general, you should avoid using props or attributes beginning with `#` as they are likely to be further developed upon and made available as an extension point, or may conflict with forwarded attributes. The following list of compiler attributes are currently in use, or are reserved for future internal use:\n\n- `#id`\n- `#name`\n- `#compiler`\n- `#style`\n- `#def`\n- `#group`\n- `#styledef`\n- `#classdef`\n- `#cache`\n- `#precompile`\n\n## Caching Components\n\nYou may cache the output of any Dagger component using the `#cache` compiler attribute. This attribute utilizes Laravel's [Cache](https://laravel.com/docs/cache) feature, and provides ways to customize cache keys, expirations, and the cache store.\n\nFor example, imagine we had a report component that we'd like to cache:\n\n```blade\n\u003c!-- /resources/dagger/views/report.blade.php --\u003e\n\n@php\n    // Some expensive report logic.\n@endphp\n```\n\nInstead of manually capturing output, or adding caching in other locations, we can simply cache the output of our component call like so:\n\n```blade\n\u003cc-report #cache=\"the-cache-key\" /\u003e\n```\n\nNow, the output of the component will be cached forever using the `the-cache-key` string as the cache key.\n\nWe may also specify a different time-to-live by specifying the number of seconds the cached output is valid:\n\n```blade\n\u003cc-report #cache.300=\"the-cache-key\" /\u003e\n```\n\nYou may also use a shorthand notation to calculate the time-to-live in seconds. For example, if we'd like to have the cache expire ten minutes from the time the component was first rendered we could use the value `10m`:\n\n```blade\n\u003cc-report\n    #cache.10m=\"the-cache-key\"\n/\u003e\n```\n\nAlternatively, we could also have the cache expire in 1 hour, 15 minutes, and 32 seconds:\n\n```blade\n\u003cc-report\n    #cache=1h15m32s=\"the-cache-key\"\n/\u003e\n```\n\nThe total number of seconds is calculated dynamically by adding the desired \"date parts\" to the current time and *then* calculating the number of seconds to use.\n\nThe following table lists the possible suffixes that may be used:\n\n| Suffix | Description | Example |\n|---|---|---|\n| y | Year | 1y |\n| mo | Month | 1mo |\n| w | Week | 1w |\n| d | Day | 2d |\n| h | Hour | 1h |\n| m | Minute | 30m |\n| s | Seconds | 15s |\n\n### Dynamic Cache Keys\n\nYou may create dynamic cache keys by prefixing the `#cache` attribute with the `:` character:\n\n```blade\n\u003cc-profile\n    :$user\n    :#cache.forever=\"'user-profile'.$user-\u003eid\"\n/\u003e\n```\n\n### Specifying the Cache Store\n\nYou may use a specific cache store by providing the desired cache store's name as the final modifier to the `#cache` attribute.\n\nThe following examples would cache the output for 30 seconds on different cache stores:\n\n```blade\n\u003cc-first_component #cache.300.array=\"first-key\" /\u003e\n\n\u003cc-second_component #cache.300.file=\"second-key\" /\u003e\n```\n\n### Stale While Revalidate (Flexible Cache)\n\nYou may leverage Laravel's [stale-while-revalidate pattern implementation](https://laravel.com/docs/11.x/cache#swr) using the `flexible` cache modifier. This modifier accepts two values: the number of seconds the cache is considered fresh, and the second value determines how long the cached contents can be served as stale before recalculation is necessary.\n\n```blade\n\u003cc-report\n    #cache.flexible:5:10=\"the-cache-key\"\n/\u003e\n```\n\n## Component Name\n\nYou may access the name of the current component through the `name` property on the component instance:\n\n```blade\n\u003c!-- /resources/dagger/views/button.blade.php --\u003e\n\n{{-- Displays \"button\" --}}\n{{ $component-\u003ename }}\n```\n\n## Component Depth\n\nYou may get the current depth of the current component using the `depth` property on the component instance:\n\n```blade\n\n{{ $component-\u003edepth }}\n```\n\nEach time a component is nested, the depth is increased by one. Depth is also incremented when the parent component is a Blade component.\n\n## Attribute Forwarding\n\nAttribute forwarding is a powerful feature that allows you to set and override props and attributes on *nested* components. For this to work, nested components must have an identifier, which is set using the `#id` compiler attribute.\n\nImagine we have the following simple toolbar component:\n\n```blade\n\u003c!-- /resources/dagger/views/toolbar.blade.php --\u003e\n\n\u003cdiv\u003e\n    \u003cc-docs.button #id=\"saveButton\" text=\"The Save Button\" /\u003e\n    \u003cc-docs.button #id=\"cancelButton\" text=\"The Cancel Button\" /\u003e\n\u003c/div\u003e\n```\n\nand the following button component:\n\n```blade\n\u003c!-- /resources/dagger/views/button.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()\n        -\u003eprops(['text'])\n        -\u003etrimOutput();\n@endphp\n\n\u003cbutton {{ $attributes }}\u003e{{ $text }}\u003c/button\u003e\n\n```\n\nIf we were to render the following template:\n\n```blade\n\u003cc-toolbar /\u003e\n```\n\nwe would receive output similar to the following:\n\n```html\n\u003cdiv\u003e\n    \u003cbutton\u003eThe Save Button\u003c/button\u003e\n    \u003cbutton\u003eThe Cancel Button\u003c/button\u003e\n\u003c/div\u003e\n```\n\nIf we wanted to allow consumers of the `toolbar` component to modify both the cancel and save buttons, we historically would have to create dedicated props on the parent and pass the values to each child component or define extra slots and pass in our nested components. However, because each of the nested button components has an `#id`, we can use attribute forwarding to set props and attributes on the nested components.\n\nIf we adjusted our *template* to the following:\n\n```blade\n\u003cc-toolbar\n    #saveButton:text=\"A New Save Button\"\n    #saveButton:class=\"mr-0\"\n    #cancelButton:text=\"A New Cancel Button\"\n    #cancelButton:style=\"display:none\"\n/\u003e\n```\n\nwe would now get output similar to the following:\n\n```html\n\u003cdiv\u003e\n    \u003cbutton class=\"mr-0\"\u003eA New Save Button\u003c/button\u003e\n    \u003cbutton style=\"display:none\"\u003eA New Cancel Button\u003c/button\u003e\n\u003c/div\u003e\n```\n\nWhen using attribute forwarding we specify the `#id` of the nested component followed by the `:` character, and then the name of the prop or attribute to update.\n\n### Nested Attribute Forwarding\n\nAttributes and props can be forwarded to nested components. To do so, we separate each nested component name with the `.` character. Imagine we had the following components:\n\n```blade\n\u003c!-- /resources/dagger/views/nested_one.blade.php --\u003e\n\u003cc-nested_two #id=\"nestedTwo\" /\u003e\n```\n\n```blade\n\u003c!-- /resources/dagger/views/nested_two.blade.php --\u003e\n\u003cc-nested_three #id=\"nestedThree\" /\u003e\n```\n\n```blade\n\u003c!-- /resources/dagger/views/nested_three.blade.php --\u003e\n@props(['title'])\n\n{{ $title }}\n```\n\nWe can set the `title` prop on the nested `\u003cc-nested_three\u003e` component from the template using attribute forwarding like so:\n\n```blade\n\u003cc-nested_one\n    #nestedTwo.nestedThree:title=\"The Nested Title\"\n/\u003e\n```\n\n### Variable Bindings and Attribute Forwarding\n\nYou may pass in variable references when using attribute forwarding by prefixing the forwarded attribute with the `:` character:\n\n```blade\n\u003cc-nested_one\n    :#nestedTwo.nestedThree:title=\"$title\"\n/\u003e\n```\n\n## Slot Forwarding\n\nWe may specify slot contents on *nested* components. To do so, the nested components must have an identifier specified using the `#id` compiler attribute. Imagine we have the following components:\n\n```blade\n\u003c!-- /resources/dagger/views/root.blade.php --\u003e\n\u003cc-nested_one #id=\"componentOne\" /\u003e\n```\n\n```blade\n\u003c!-- /resources/dagger/views/nested_one.blade.php --\u003e\n\n\u003cdiv {{ $slots-\u003eheader-\u003eattributes }}\u003e\n    {{ $slots-\u003eheader }}\n\u003c/div\u003e\n\n{{ $slot }}\n\n\u003cdiv {{ $slots-\u003efooter-\u003eattributes }}\u003e\n    {{ $slots-\u003efooter }}\n\u003c/div\u003e\n```\n\nWe could specify the slot contents on the nested `componentOne` within our template using slot forwarding:\n\n```blade\n\u003cc-root\u003e\n    \u003cc-slot:componentOne.header class=\"header classes here\"\u003e\n        Nested Header Content\n    \u003c/c-slot:componentOne.header\u003e\n    \n    \u003cc-slot:componentOne.footer class=\"footer classes here\"\u003e\n        Nested Footer Content\n    \u003c/c-slot:componentOne.footer\u003e\n\n    \u003cc-slot:componentOne.default\u003e\n        Nested Default Content\n    \u003c/c-slot:componentOne.default\u003e\n\u003c/c-root\u003e\n```\n\nWe do not use the `#` symbol when referencing nested slots, and instead separate the nested path using the `.` character. You will also notice that we were able to specify the *default* slot content using the `.default` name.\n\n### Nested Slot Forwarding\n\nWe may also set the contents of deeply nested components. To do so, we continue to add the names of nested components, separated by the `.` character. Consider the following components:\n\n```blade\n\u003c!-- /resources/dagger/views/root.blade.php --\u003e\n\u003cc-nested_one #id=\"componentOne\" /\u003e\n```\n\n```blade\n\u003c!-- /resources/dagger/views/nested_one.blade.php --\u003e\n\u003cc-nested_two #id=\"componentTwo\" /\u003e\n```\n\n```blade\n\u003c!-- /resources/dagger/views/nested_two.blade.php --\u003e\n\n\u003cdiv {{ $slots-\u003eheader-\u003eattributes }}\u003e\n    {{ $slots-\u003eheader }}\n\u003c/div\u003e\n\n{{ $slot }}\n\n\u003cdiv {{ $slots-\u003efooter-\u003eattributes }}\u003e\n    {{ $slots-\u003efooter }}\n\u003c/div\u003e\n```\n\nwe could set the nested slot contents like so:\n\n```blade\n\u003cc-root\u003e\n    \u003cc-slot:componentOne.componentTwo.header class=\"header classes here\"\u003e\n        Nested Header Content\n    \u003c/c-slot:componentOne.componentTwo.header\u003e\n    \n    \u003cc-slot:componentOne.componentTwo.footer class=\"footer classes here\"\u003e\n        Nested Footer Content\n    \u003c/c-slot:componentOne.componentTwo.footer\u003e\n\n    \u003cc-slot:componentOne.componentTwo.default\u003e\n        Nested Default Content\n    \u003c/c-slot:componentOne.componentTwo.default\u003e\n\u003c/c-root\u003e\n```\n\n## Output Trimming\n\nThere are times you may wish to trim the output of a component before it is rendered on the client. Instead of manually capturing output, or carefully ensuring that each component file does not contain a final newline, you can instead use the `trimOutput` builder method:\n\n```blade\n@php\n    \\Stillat\\Dagger\\component()\n        -\u003eprops(['name'])\n        -\u003etrimOutput();\n@endphp\n\n\n\n{{ $name }}\n\n\n\n\n```\n\nThe Dagger compile will now trim the output of the component before adding it to the rest of the response.\n\n\u003e [!NOTE]\n\u003e Any leading content, such as HTML comments, before the first `@php ... @endphp` block will be considered content when trimming component output.\n\n## Stencils\n\nStencils allow consumers of components to override named sections of a component *without* having to publish the component's views. They are similar to slots, but work in a very different way. Slots are a runtime feature, where content is evaluated within the consumer's variable scope and the results are injected in the component as a variable. Stencils, on the other hand, are a *compile time* substitution and become part of the component's compiled output.\n\nStencils, by themselves, simply create a \"named\" section of a component's template that the compiler can replace. These regions are created using the special `\u003cc-stencil\u003e` component. Imagine we had the following list component:\n\n```blade\n\u003c!-- /resources/dagger/views/list/index.blade.php --\u003e\n@props(['items'])\n\n\u003cul\u003e\n    @foreach ($items as $item)\n        \u003cc-stencil:list_item\u003e\n            \u003cli\u003e{{ $item }}\u003c/li\u003e\n        \u003c/c-stencil:list_item\u003e\n    @endforeach\n\u003c/ul\u003e\n```\n\nIf we were to render the component like so:\n\n```blade\n\u003cc-list\n    :items=\"['Alice', 'Bob', 'Charlie']\"\n/\u003e\n```\n\nOur output would resemble the following:\n\n```html\n\u003cul\u003e\n    \u003cli\u003eAlice\u003c/li\u003e\n    \u003cli\u003eBob\u003c/li\u003e\n    \u003cli\u003eCharlie\u003c/li\u003e\n\u003c/ul\u003e\n```\n\nHowever, because the component defined a `list_item` stencil, we can replace that section of the component's template entirely:\n\n```blade\n\u003cc-docs.list :items=\"['Alice', 'Bob', 'Charlie']\"\u003e\n    \u003cc-stencil:list_item\u003e\n        \u003cli class=\"mt-2\"\u003e{{ Str::upper($item) }}\u003c/li\u003e\n    \u003c/c-stencil:list_item\u003e\n\u003c/c-docs.list\u003e\n```\n\nRendering the new template would produce output similar to the following:\n\n```html\n\u003cul\u003e\n    \u003cli class=\"mt-2\"\u003eALICE\u003c/li\u003e\n    \u003cli class=\"mt-2\"\u003eBOB\u003c/li\u003e\n    \u003cli class=\"mt-2\"\u003eCHARLIE\u003c/li\u003e\n\u003c/ul\u003e\n```\n\n### Rendering Default Stencil Content\n\nThere may be times where you'd like to change a stencil's template, but conditionally render the original. Building on the list example above, we can accomplish this by using a special `default` modifier provided by the stencil component:\n\n```blade\n\u003cc-docs.list :items=\"['Alice', 'Bob', 'Charlie']\"\u003e\n    \u003cc-stencil:list_item\u003e\n        @if ($item === 'Alice')\n            \u003cli data-something=\"special-for-alice\"\u003e{{ $item }}\u003c/li\u003e\n        @else\n            \u003cc-stencil:list_item.default /\u003e\n        @endif\n    \u003c/c-stencil:list_item\u003e\n\u003c/c-docs.list\u003e\n```\n\nRendering this template would now produce the following output:\n\n```html\n\u003cul\u003e\n    \u003cli data-something=\"special-for-alice\"\u003eAlice\u003c/li\u003e\n    \u003cli\u003eBob\u003c/li\u003e\n    \u003cli\u003eCharlie\u003c/li\u003e\n\u003c/ul\u003e\n```\n\n### Additional Notes on Stencils\n\nA few things to remember when using stencils:\n\n- Stencils do *not* have access to the consumer's scope\n- Stencil templates become part of the component's compiled output and have access to the component's internal scope\n- Default stencil templates can be injected using the `\u003cc-stencil:stencil_name.default /\u003e` component, where `stencil_name` is the name of the stencil\n- Stencils, by themselves, have no additional overhead once compiled\n\n## Mixins\n\nMixins provide a way to inject data and common behaviors into components. Mixins are specified by calling the `mixin` component builder method and supplying either a single class name, or multiple mixin class names.\n\nMixin classes may define a `data` method, which should return an array of key/value pairs. Imagine we had the following mixin class providing common theme data:\n\n```php\n\u003c?php\n\nnamespace App\\Mixins;\n\nclass ThemeData\n{\n    public function data(): array\n    {\n        return [\n            'background' =\u003e 'bg-indigo-500',\n        ];\n    }\n}\n```\n\nWe could include this mixin in our component like so:\n\n```blade\n\u003c!-- /resources/dagger/views/mixin.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()-\u003emixin([\n        \\App\\Mixins\\ThemeData::class,\n    ])-\u003eprops(['background']);\n@endphp\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e $background]) }}\u003e\n    ...\n\u003c/div\u003e\n\n```\n\nData returned by mixins will be injected as variables, like regular props. Prop values will override any values provided by a mixin:\n\n```blade\n\u003cc-mixin background=\"bg-blue-500\" /\u003e\n```\n\nA mixin's `data` method will be invoked *last* when registering the mixin with the component.\n\n### Mixin Methods\n\nPublic methods defined within a mixin will be injected as variables within the component's view:\n\n```php\n\u003c?php\n\nnamespace App\\Mixins;\n\nclass ProfileMixin\n{\n    public function sayHello(string $name): string\n    {\n        return \"Hello, {$name}.\";\n    }\n}\n```\n\n```blade\n\u003c!-- /resources/dagger/views/profile.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()-\u003emixin([\n        \\App\\Mixins\\ProfileMixin::class,\n    ])-\u003eprops(['name']);\n@endphp\n\n\u003cdiv\u003e\n    {{ $sayHello($name) }}\n\u003c/div\u003e\n\n```\n\nIf you prefer not to use variables as methods, you may also access mixin methods on the `$component` instance. This is also helpful if you have props that share the same name as methods:\n\n```blade\n\u003c!-- /resources/dagger/views/profile.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()-\u003emixin([\n        \\App\\Mixins\\ProfileMixin::class,\n    ])-\u003eprops(['name']);\n@endphp\n\n\u003cdiv\u003e\n    {{ $component-\u003esayHello($name) }}\n\u003c/div\u003e\n\n```\n\n### Accessing the Component Instance Inside Mixins\n\nYou can gain access to the `$component` instance within a mixin class by defining a `withComponent` method that accepts the component as its only argument. The `withComponent` method will be invoked *first* if it exists:\n\n```php\n\u003c?php\n\nnamespace App\\Mixins;\n\nuse Illuminate\\Support\\Str;\nuse Stillat\\Dagger\\Runtime\\Component;\n\nclass ComponentMixin\n{\n    protected ?Component $component = null;\n\n    public function withComponent(Component $component): void\n    {\n        $this-\u003ecomponent = $component;\n    }\n\n    public function data(): array\n    {\n        return [\n            'name_upper' =\u003e Str::upper($this-\u003ecomponent-\u003ename),\n        ];\n    }\n}\n```\n\n```blade\n\u003c!-- /resources/dagger/views/component.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()-\u003emixin([\n        \\App\\Mixins\\ComponentMixin::class,\n    ]);\n@endphp\n\n\u003cdiv\u003e\n    {{ $name_upper }}\n\u003c/div\u003e\n\n```\n\n### Additional Notes on Mixins\n\n* Mixin instances are resolved from the service container *each* time a component is used\n* The `withComponent` method is always called first, if present\n* The `data` method is always called last, if present\n* Data provided to mixins via. `data` methods will *not* become part of the `$attributes`, even if they are not listed in the props\n* Public methods defined within a mixin will be made available as variables within the component\n  * The `withComponent` and `data` methods will *not* be made available\n\n## Attribute Cache\n\nThe Dagger compiler and runtime provide an opt-in feature called the attribute cache. This cache mechanism is able to cache the results of components, while still allowing for dynamic slot substition. The attribute cache may be used to prevent re-rendering components when the same attributes are supplied to it, helping to improve performance for heavy, large, or complicated components.\n\nTo use the attribute cache simply call the `cache` component builder method:\n\n```blade\n\u003c!-- /resources/dagger/views/cached.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()\n        -\u003eprops(['title'])\n        -\u003ecache();\n@endphp\n\n{{ $title }}\n```\n\nAssuming the following template, the `\u003cc-cached /\u003e` component internals would only be evaulated once because the attributes and props remain the same across both renderings:\n\n```blade\n\u003cc-cached title=\"The Title\" /\u003e\n\u003cc-cached title=\"The Title\" /\u003e\n```\n\nHowever, the `\u003cc-cached /\u003e` component would be evaluated *twice* in the following template:\n\n```blade\n\u003cc-cached title=\"The Title\" /\u003e\n\u003cc-cached title=\"The Title\" /\u003e\n\n\u003cc-cached title=\"The Second Title\" /\u003e\n\u003cc-cached title=\"The Second Title\" /\u003e\n```\n\nAny attributes supplied on named/scoped slots will also be added to the internal cache key. All instances of a component will share the same internal attribute cache.\n\n### Slot Variables and the Attribute Cache\n\nComponents with slots are still able to take advantage of the attribute cache. Internally, the Dagger compiler will perform string substition on the cached component output. Because of this behavior, you should avoid performing operations on the *results* of slots when enabling the attribute cache:\n\n```blade\n@php\n    \\Stillat\\Dagger\\component()\n        -\u003eprops(['title'])\n        -\u003ecache();\n@endphp\n\n{{ Str::upper($slot) }} // ❌ Don't change the output of slots when using the attribute cache.\n```\n\n### Considerations\n\nThe attribute cache is a powerful feature that can help to improve performance for heavily re-used components, but there are some things to keep in mind before deciding to use it. Any custom PHP code or dynamic behavior within your component will only be evaluated for each unique rendering of the component.\n\nConsider the following component:\n\n```blade\n\u003c!-- /resources/dagger/views/time.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()\n        -\u003ecache();\n@endphp\n\n{{ time() }}\n```\n\nThe results of the `time()` function call would be the same for all of the following renders, since it was cached:\n\n```blade\n\u003cc-time /\u003e\n\u003cc-time /\u003e\n\u003cc-time /\u003e\n```\n\nIf you're component's internal execution needs to remain dynamic you *should not* use the attribute cache. Because the Dagger compiler inlines components, performance should remain relatively stable in these scenarios, even for heavily-used components.\n\n## Static Template Optimizations\n\nIf a component's template does *not* contain any PHP code after compilation, the Dagger compiler will **not** output any component infrastructure for that component. Instead, it will simply inline the static component's content in the view's compiled output. Dagger maintains a \"view manifest\" which tracks components like this, allowing things like hot reloading and cache busting to continue functioning.\n\nImagine we had a footer component that contained static HTML contents:\n\n```html\n\u003c!-- /resources/dagger/views/footer.blade.php --\u003e\n\u003cfooter\u003e\n    ...\n\u003c/footer\u003e\n```\n\nRendering the `\u003cc-footer /\u003e` component would not output any additional PHP code in the final, compiled output.\n\n## Dynamic Components\n\nIf you need to render dynamic Dagger components, you may use the `dynamic-component` component to render a component based on a runtime value or variable:\n\n```blade\n// $componentName = \"button\";\n\n\u003cc-dynamic-component :component=\"$componentName\" class=\"mt-4\" /\u003e\n```\n\nYou may also supply slot content to dynamic components:\n\n```blade\n\u003cc-dynamic-component :component=\"$componentName\"\u003e\n    The Slot Contents\n\u003c/c-dynamic-component\u003e\n```\n\nDynamic components will be compiled and cached, taking into account any slots, forwarded attributes, or forwarded slots. Dynamic Dagger components can also take advantage of the Attribute Cache.\n\nYou may use any of the following aliases to render dynamic components:\n\n```blade\n\u003cc-delegate-component :$component /\u003e\n\u003cc-dynamic-component :$component /\u003e\n\u003cc-proxy :$component /\u003e\n```\n\nAll three aliases share the same internal behavior.\n\n## Custom Component Paths and Namespaces\n\nIf you are writing a component library, you may wish to register your own component namespace and not have to rely on the `\u003cc-` prefix. You may do this within your package's service provider by providing your desired namespace and the path to your component's views:\n\n```php\n\u003c?php\n\nnamespace Your\\Package\\Namespace;\n\nuse Illuminate\\Support\\ServiceProvider as IlluminateServiceProvider;\nuse Stillat\\Dagger\\Facades\\Compiler;\n\nclass ServiceProvider extends IlluminateServiceProvider\n{\n    public function boot(): void\n    {\n        Compiler::registerComponentPath(\n            'lenz',\n            __DIR__.'./../path/to/component/views'\n        );\n    }\n}\n```\n\nThe first argument is the component prefix or namespace that will be used for your components, and the second argument is the path to the component's views. In the previous example, we supplied `lenz` as the prefix, which means consumers of the components can now write the following, assuming the component views exist:\n\n```blade\n\u003clenz:button class=\"mt-4\" /\u003e\n\u003clenz-button class=\"mt-4\" /\u003e\n```\n\nCustom components can leverage all features of the Dagger compiler using their custom prefix.\n\n### Blade Component Prefix\n\nYou are **not** allowed to register the prefix `x` with the Dagger compiler; attempting to do so will raise an `InvalidArgumentException`.\n\n## Compile Time Rendering\n\nThe Dagger compiler contains a subsystem known as the Compile Time Renderer, or CTR. This checks to see if all the props on a component are resolvable at runtime; if so, it may elect to compile the component at runtime and insert the pre-rendered results into Blade's compiled output.\n\nThis feature has a number of internal safe guards, and here are a few of the things that will internally disable this feature:\n\n- Dynamic/interpolated variable references\n- Using Mixins\n- Most static method calls\n- Referencing PHP's [superglobals](https://php.net/superglobals), such as `$_GET` or `$_POST`\n- Using debugging-related functions in a component, such as `dd`, `dump`, `var_dump`, etc.\n- Calling functions such as `time`, `now`, or `date`\n- Enabling the Attribute Cache on a component\n- Components with slots\n\nImagine we have the following alert component:\n\n```blade\n\u003c!-- /resources/dagger/views/alert.blade.php --\u003e\n\n@props(['type' =\u003e 'info', 'message'])\n\n\u003cdiv {{ $attributes-\u003emerge(['class' =\u003e 'alert alert-'.$type]) }}\u003e\n    {{ $message }}\n\u003c/div\u003e\n```\n\nIf we were to call the alert component like so:\n\n```blade\n\u003cc-alert message=\"My awesome message\" /\u003e\n```\n\nThe compiler would detect that all props are resolvable, and the following would be emitted in the compiled Blade output:\n\n```html\n\u003cdiv class=\"alert alert-info\"\u003e\n    The awesome message\n\u003c/div\u003e\n```\n\nHowever, if we were to call our component like so, the compiler would not attempt to render the component at compile time:\n\n```blade\n\u003cc-alert :$message /\u003e\n```\n\n### Disabling Compile Time Rendering on a Component\n\nThe CTR system should be transparent from a component author's point-of-view, however, if the rare event that you need to disable compiler optimizations, you may do so using the `compiler` helper method:\n\n```blade\n\u003c!-- /resources/dagger/views/the_component.blade.php --\u003e\n@php\n    \\Stillat\\Dagger\\component()\n        -\u003eprops(['title'])\n        -\u003ecompiler(\n            allowOptimizations: false\n        );\n@endphp\n\n{{ $title }}\n```\n\nIf you find yourself disabling optimizations on a component, please open a discussion or an issue with details on which behaviors led to that decision.\n\n### Enabling/Disabling Optimizations on Classes or Methods\n\nThe CTR system will aggressively disable itself whenever it detects static method calls within component templates. You may choose to mark these methods as safe using the `EnableOptimization` attribute:\n\n```php\n\u003c?php\n\nnamespace App;\n\nuse Stillat\\Dagger\\Compiler\\EnableOptimization;\n\nclass MyAwesomeClass\n{\n\n    #[EnableOptimization]\n    public static function myHelper()\n    {\n\n    }\n\n}\n```\n\nYou may also mark an entire class as safe for optimizations by applying the attribute to the class instead:\n\n```php\n\u003c?php\n\nnamespace App;\n\nuse Stillat\\Dagger\\Compiler\\EnableOptimization;\n\n#[EnableOptimization]\nclass MyAwesomeClass\n{\n\n    public static function myHelper()\n    {\n\n    }\n\n}\n```\n\nIf you'd like to *disable* optimizations on a class or method explicitly, you may use the `DisableOptimization` attribute instead.\n\nThe following example would enable optimizations on the entire class but disable it on a specific method:\n\n```php\n\u003c?php\n\nnamespace App;\n\nuse Stillat\\Dagger\\Compiler\\DisableOptimization;\nuse Stillat\\Dagger\\Compiler\\EnableOptimization;\n\n#[EnableOptimization]\nclass MyAwesomeClass\n{\n\n    public static function methodOne()\n    {\n        // Optimization allowed.\n    }\n\n    #[DisableOptimization]\n    public static function methodTwo()\n    {\n        // Optimization not allowed.\n    }\n\n}\n```\n\n### Notes on Compile Time Rendering\n\n- You should *never* attempt to force a component to render at compile time, outside of applying the `EnableOptimization` or `DisableOptimization` attributes to your own helper methods\n- If an exception is raised while rendering a component at compile time, CTR will be disabled for that component and the compiler will revert to normal behavior\n\n## The View Manifest\n\nYou may have noticed JSON files being written to your compiled view folder. These files are created by Dagger's \"view manifest\", which tracks dependencies of compiled views.\n\nBecause the Dagger compiler inlines component views into one larger compiled file, as well as optimizes static templates, the Dagger runtime uses these JSON files to help with cache invalidation.\n\n## License\n\nDagger is free software, released under the MIT license. Please see [LICENSE.md](LICENSE.md) for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstillat%2Fdagger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstillat%2Fdagger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstillat%2Fdagger/lists"}