From b299a26c6c33ecb0b97aee9670025c094d7ad3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20M?= Date: Fri, 12 Jul 2024 12:49:20 +0200 Subject: [PATCH] feat: html (#9) --- README.md | 31 ++--- composer.json | 6 +- config/wireuse.php | 43 +++--- phpstan.neon.dist | 3 +- .../css/presets/tailwind.config.preset.js | 12 +- resources/views/actions/button.blade.php | 38 ------ resources/views/actions/icon.blade.php | 29 ---- resources/views/actions/link.blade.php | 39 ------ resources/views/auth/login.blade.php | 17 --- resources/views/auth/logout.blade.php | 3 - resources/views/auth/register.blade.php | 3 - .../views/components/forms/checkbox.blade.php | 15 --- .../views/components/forms/input.blade.php | 57 -------- .../views/components/forms/select.blade.php | 67 --------- .../components/layout/container.blade.php | 16 --- .../views/components/layout/join.blade.php | 18 --- .../components/navigation/navbar.blade.php | 32 ----- resources/views/navigation/tabs.blade.php | 39 ------ src/Actions/Components/Button.php | 14 -- src/Actions/Components/Icon.php | 44 ------ src/Actions/Components/Link.php | 55 -------- src/Actions/Concerns/WithAction.php | 12 -- src/Actions/Support/Action.php | 100 -------------- src/Auth/Controllers/LoginController.php | 53 -------- src/Auth/Controllers/LogoutController.php | 35 ----- src/Auth/Controllers/RegisterController.php | 39 ------ src/Auth/Forms/LoginForm.php | 45 ------- src/Auth/Forms/RegisterForm.php | 67 --------- src/Facades/WireUse.php | 1 - src/Forms/Concerns/WithValidation.php | 5 + src/Forms/Support/Form.php | 4 +- src/Layout/Concerns/WithScroll.php | 75 +++++++++++ src/Navigation/Components/Tabs.php | 24 ---- src/Navigation/Concerns/WithTabs.php | 37 ----- src/Support/Blade/Bladeable.php | 5 +- .../Blade/Concerns/WithBladeMacros.php | 77 +++++++++++ src/Support/Components/Component.php | 26 ---- .../Components/Concerns/HasComponent.php | 35 ----- src/Support/Components/Concerns/HasIcon.php | 40 ------ src/Support/Components/Concerns/HasLabel.php | 23 ---- .../Components/Concerns/HasLivewire.php | 42 ------ src/Support/Components/Concerns/HasName.php | 23 ---- src/Support/Components/Concerns/HasNodes.php | 55 -------- .../Components/Concerns/HasRequest.php | 35 ----- .../Components/Concerns/HasRouting.php | 62 --------- src/Support/Components/Concerns/HasState.php | 35 ----- .../Components/Concerns/HasVisibility.php | 35 ----- src/Support/Discover/ComponentScout.php | 33 ++--- src/Support/Html/Elements/Icon.php | 15 +++ src/Support/Html/Elements/Validate.php | 20 +++ src/Support/Html/Mixins/BaseElementMixin.php | 49 +++++++ src/Support/Html/Mixins/HtmlExtendedMixin.php | 53 ++++++++ src/Support/Html/Mixins/ImgElementMixin.php | 24 ++++ src/Support/Html/Mixins/LinkElementMixin.php | 32 +++++ .../ActionObjects/ActionObjectSynth.php | 37 ----- .../ActionObjects/SupportActionObjects.php | 15 --- src/Views/Support/Component.php | 2 - src/WireUse.php | 20 +-- src/WireUseServiceProvider.php | 127 +----------------- tailwind.config.js | 3 +- tests/src/Support/BladeDirectiveTest.php | 12 -- tests/src/TestClasses/BladeComponent.php | 12 +- 62 files changed, 435 insertions(+), 1590 deletions(-) delete mode 100644 resources/views/actions/button.blade.php delete mode 100644 resources/views/actions/icon.blade.php delete mode 100644 resources/views/actions/link.blade.php delete mode 100644 resources/views/auth/login.blade.php delete mode 100644 resources/views/auth/logout.blade.php delete mode 100644 resources/views/auth/register.blade.php delete mode 100644 resources/views/components/forms/checkbox.blade.php delete mode 100644 resources/views/components/forms/input.blade.php delete mode 100644 resources/views/components/forms/select.blade.php delete mode 100644 resources/views/components/layout/container.blade.php delete mode 100644 resources/views/components/layout/join.blade.php delete mode 100644 resources/views/components/navigation/navbar.blade.php delete mode 100644 resources/views/navigation/tabs.blade.php delete mode 100644 src/Actions/Components/Button.php delete mode 100644 src/Actions/Components/Icon.php delete mode 100644 src/Actions/Components/Link.php delete mode 100644 src/Actions/Concerns/WithAction.php delete mode 100644 src/Actions/Support/Action.php delete mode 100644 src/Auth/Controllers/LoginController.php delete mode 100644 src/Auth/Controllers/LogoutController.php delete mode 100644 src/Auth/Controllers/RegisterController.php delete mode 100644 src/Auth/Forms/LoginForm.php delete mode 100644 src/Auth/Forms/RegisterForm.php create mode 100644 src/Layout/Concerns/WithScroll.php delete mode 100644 src/Navigation/Components/Tabs.php delete mode 100644 src/Navigation/Concerns/WithTabs.php create mode 100644 src/Support/Blade/Concerns/WithBladeMacros.php delete mode 100644 src/Support/Components/Component.php delete mode 100644 src/Support/Components/Concerns/HasComponent.php delete mode 100644 src/Support/Components/Concerns/HasIcon.php delete mode 100644 src/Support/Components/Concerns/HasLabel.php delete mode 100644 src/Support/Components/Concerns/HasLivewire.php delete mode 100644 src/Support/Components/Concerns/HasName.php delete mode 100644 src/Support/Components/Concerns/HasNodes.php delete mode 100644 src/Support/Components/Concerns/HasRequest.php delete mode 100644 src/Support/Components/Concerns/HasRouting.php delete mode 100644 src/Support/Components/Concerns/HasState.php delete mode 100644 src/Support/Components/Concerns/HasVisibility.php create mode 100644 src/Support/Html/Elements/Icon.php create mode 100644 src/Support/Html/Elements/Validate.php create mode 100644 src/Support/Html/Mixins/BaseElementMixin.php create mode 100644 src/Support/Html/Mixins/HtmlExtendedMixin.php create mode 100644 src/Support/Html/Mixins/ImgElementMixin.php create mode 100644 src/Support/Html/Mixins/LinkElementMixin.php delete mode 100644 src/Support/Livewire/ActionObjects/ActionObjectSynth.php delete mode 100644 src/Support/Livewire/ActionObjects/SupportActionObjects.php delete mode 100644 tests/src/Support/BladeDirectiveTest.php diff --git a/README.md b/README.md index 8ab6f4a9..477db32c 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,9 @@ [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/foxws/wireuse/fix-php-code-style-issues.yml?branch=3.x&label=code%20style&style=flat-square)](https://github.com/foxws/wireuse/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3A3.x) [![Total Downloads](https://img.shields.io/packagist/dt/foxws/wireuse.svg?style=flat-square)](https://packagist.org/packages/foxws/wireuse) -This packages offers a collection of useful [Livewire](https://livewire.laravel.com/) utilities and components. :) +This packages offers a collection of useful [Livewire](https://livewire.laravel.com/) utilities and components. -It is made to assemble your Livewire and Blade components yourself, rather than extending from an existing framework or baseset. - -It shares the same idea as [VueUse](https://vueuse.org/), but for Laravel Livewire. - -If you have a suggestion, idea or feedback, please feel free to send a PR or create a discussion. :) - -## Documentation - -You will find full documentation on the dedicated [documentation](https://foxws.nl/projects/wireuse) site. - -> NOTE: The documentation is far from complete, see [discussion](https://github.com/foxws/wireuse/discussions/3) for progress and ideas. +The full documentation and more information about WireUse, is on our dedicated [documentation](https://foxws.nl/projects/wireuse) website. ## Installation @@ -27,17 +17,24 @@ You can install the package via composer: composer require foxws/wireuse ``` -You can publish the config file with: +Optionally, you can publish the config file with: ```bash php artisan vendor:publish --tag="wireuse-config" ``` -Optionally, you can publish the views using: +## Usage -```bash -php artisan vendor:publish --tag="wireuse-views" -``` +This is a selection of the available features: + +- [Property Synthesizers](https://foxws.nl/posts/wireuse/property-synthesizers) - Force usage of model route-keys, instead of model ids. +- [Components](https://foxws.nl/posts/wireuse/components) - Components like `Page` and useful traits. +- [HTML](https://foxws.nl/posts/wireuse/laravel-html) - Extends Spatie's [laravel-html](https://spatie.be/docs/laravel-html/v3/introduction) to generate HTML using a clean, simple and easy to read API. +- [State Objects](https://foxws.nl/posts/wireuse/state-objects) - State objects are based on states that you find, for example, in a VueJS Store. +- [Forms](https://foxws.nl/posts/wireuse/forms) - Traits and extensions for [Livewire Forms](https://livewire.laravel.com/docs/forms). +- [Structure Scout](https://foxws.nl/posts/wireuse/structure-scout) - Supported by [spatie/php-structure-discoverer](https://github.com/spatie/php-structure-discoverer) package, it provides a scout to discover and register components, which also offers benefits such as caching. + +Please checkout our [documentation](https://foxws.nl/projects/wireuse) for more information. ## Testing diff --git a/composer.json b/composer.json index 49fd2080..222ab4d2 100644 --- a/composer.json +++ b/composer.json @@ -18,14 +18,16 @@ ], "require": { "php": "^8.2", - "artesaos/seotools": "^1.3", "illuminate/contracts": "^10.0|^11.0", "illuminate/support": "^10.0|^11.0", "illuminate/view": "^10.0|^11.0", "laravel/scout": "^10.0|^11.0", "livewire/livewire": "^3.4", "spatie/laravel-package-tools": "^1.16.3", - "spatie/php-structure-discoverer": "^2.1" + "spatie/php-structure-discoverer": "^2.1", + "spatie/laravel-html": "^3.10", + "artesaos/seotools": "^1.3", + "blade-ui-kit/blade-icons": "^1.6.0" }, "require-dev": { "larastan/larastan": "^2.9", diff --git a/config/wireuse.php b/config/wireuse.php index 510ab2ee..f1b3477b 100644 --- a/config/wireuse.php +++ b/config/wireuse.php @@ -1,36 +1,33 @@ true, +return [ /* |-------------------------------------------------------------------------- - | Components + | Laravel HTML |-------------------------------------------------------------------------- | - | This controls components registration. + | This extends Laravel HTML. | - */ - - 'register_components' => true, - - /* - |-------------------------------------------------------------------------- - | Views - |-------------------------------------------------------------------------- - | - | This controls views registration. + | @doc https://spatie.be/docs/laravel-html/v3 | */ - 'view_prefix' => 'wireuse', + 'html' => [ + 'mixins' => [ + Html::class => HtmlExtendedMixin::class, + BaseElement::class => BaseElementMixin::class, + Elements\A::class => LinkElementMixin::class, + Elements\Img::class => ImgElementMixin::class, + ], + ], + ]; diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 9aaa7902..71aca4ee 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,7 +10,6 @@ parameters: tmpDir: build/phpstan checkOctaneCompatibility: true checkModelProperties: true - checkMissingIterableValueType: false ignoreErrors: - '#Unsafe usage of new static#' - - '#^Access to an undefined property Foxws\\WireUse\\Actions\\Support\\Action\:\:\$\w+\.$#' + - '#Call to an undefined method [a-zA-Z0-9\\_]+::wireModel\(\)#' diff --git a/resources/css/presets/tailwind.config.preset.js b/resources/css/presets/tailwind.config.preset.js index 7ee46872..46d65e0e 100644 --- a/resources/css/presets/tailwind.config.preset.js +++ b/resources/css/presets/tailwind.config.preset.js @@ -4,17 +4,23 @@ import typography from '@tailwindcss/typography'; /** @type {import('tailwindcss').Config} */ export default { - content: ['./resources/**/*.blade.php', './app/View/**/*.php', './src/**/*.php', './vendor/foxws/wireuse/**/*.php', './vendor/foxws/wireuse/**/*.blade.php'], + content: ['./resources/**/*.blade.php', './src/**/*.php'], plugins: [forms, typography], theme: { extend: { colors: { - primary: colors.slate, + base: colors.white, + primary: colors.pink, + secondary: colors.gray, + error: colors.red, }, container: { center: true, padding: '2rem', - } + }, + safelist: [ + 'text-error-500', + ], } } }; diff --git a/resources/views/actions/button.blade.php b/resources/views/actions/button.blade.php deleted file mode 100644 index 6439db4e..00000000 --- a/resources/views/actions/button.blade.php +++ /dev/null @@ -1,38 +0,0 @@ - diff --git a/resources/views/actions/icon.blade.php b/resources/views/actions/icon.blade.php deleted file mode 100644 index 8abee8fa..00000000 --- a/resources/views/actions/icon.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -
cssClass([ - 'layer' => 'inline-flex items-center justify-center', - 'icon' => 'size-6 sm:size-7', - ]) - ->classMerge([ - 'layer', - ]) -}}> - @if ($iconName() && $action->hasState()) - - - @if ($hasActiveIcon()) - - @endif - @elseif ($iconName()) - - @endif -
diff --git a/resources/views/actions/link.blade.php b/resources/views/actions/link.blade.php deleted file mode 100644 index 5f7d8d1c..00000000 --- a/resources/views/actions/link.blade.php +++ /dev/null @@ -1,39 +0,0 @@ -cssClass([ - 'layer' => 'inline-flex shrink-0 cursor-pointer items-center justify-center', - 'label' => 'text-inherit', - 'button' => 'py-1.5 px-3 gap-1 border border-primary-500 no-underline', - 'active' => 'text-primary-400 hover:text-primary-300', - 'inactive' => 'text-secondary-400 hover:text-primary-400', - 'icon' => 'size-6 text-secondary-400', - ]) - ->mergeAttributes($action->getComponentAttributes()) - ->classMerge([ - 'layer', - 'button' => $isButton(), - 'active' => $isCurrent(), - 'inactive' => ! $isCurrent(), - ]) - ->merge([ - 'wire:navigate' => $navigate(), - 'href' => $url(), - 'aria-label' => $label(), - ]) -}}> - @if ($slot->isEmpty()) - @if ($action->hasIcon()) - - @endif - - @if ($action->hasLabel()) - - {{ $label() }} - - @endif - @else - {{ $slot }} - @endif - diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php deleted file mode 100644 index c5db6b0e..00000000 --- a/resources/views/auth/login.blade.php +++ /dev/null @@ -1,17 +0,0 @@ -
- - - - - @foreach ($actions as $action) - - @endforeach - diff --git a/resources/views/auth/logout.blade.php b/resources/views/auth/logout.blade.php deleted file mode 100644 index 9a277598..00000000 --- a/resources/views/auth/logout.blade.php +++ /dev/null @@ -1,3 +0,0 @@ -
- {{-- redirecting --}} -
diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php deleted file mode 100644 index 33515c48..00000000 --- a/resources/views/auth/register.blade.php +++ /dev/null @@ -1,3 +0,0 @@ -
- {{-- TODO --}} -
diff --git a/resources/views/components/forms/checkbox.blade.php b/resources/views/components/forms/checkbox.blade.php deleted file mode 100644 index 25f85175..00000000 --- a/resources/views/components/forms/checkbox.blade.php +++ /dev/null @@ -1,15 +0,0 @@ -cssClass([ - 'layer' => 'peer shrink-0', - 'error' => 'border-red-500', - ]) - ->classMerge([ - 'layer', - 'error' => $errors->has($wireModel()), - ]) - ->merge([ - 'wire:key' => $wireKey(), - 'id' => $wireKey(), - 'type' => 'checkbox', - ]) -}}> diff --git a/resources/views/components/forms/input.blade.php b/resources/views/components/forms/input.blade.php deleted file mode 100644 index c1addaf1..00000000 --- a/resources/views/components/forms/input.blade.php +++ /dev/null @@ -1,57 +0,0 @@ -@props([ - 'prepend' => null, - 'append' => null, - 'label' => null, - 'hint' => null, -]) - -
cssClass([ - 'layer' => 'flex flex-col gap-1.5 w-full', - 'input' => 'px-3 h-10 w-full text-base bg-secondary-800/90 border-secondary-500/50 focus:none focus:ring-0', - 'label' => 'flex items-center', - 'error' => '!border-red-500', - 'hint' => 'py-3 text-xs', - 'message' => 'text-red-500 text-sm', - ]) - ->classMerge([ - 'layer', - ]) - ->only('class') -}}> - @if ($label) - - @endif - -
- {{ $prepend }} - - classMerge([ - 'input', - 'error' => $errors->has($attributes->wireKey()), - ]) - ->merge([ - ...['id' => $attributes->wireKey(), 'type' => 'text'], - ...$attributes->whereStartsWith('wire:model') - ]) - }} /> - - {{ $append }} -
- - @if ($hint) -

{{ $hint }}

- @endif - - @error($attributes->wireKey()) -

- {{ $message }} -

- @enderror -
diff --git a/resources/views/components/forms/select.blade.php b/resources/views/components/forms/select.blade.php deleted file mode 100644 index 2bee6523..00000000 --- a/resources/views/components/forms/select.blade.php +++ /dev/null @@ -1,67 +0,0 @@ -@props([ - 'prepend' => null, - 'append' => null, - 'label' => null, - 'hint' => null, - 'placeholder' => null, - 'options' => null, -]) - -
cssClass([ - 'layer' => 'flex flex-col gap-1.5 w-full', - 'input' => 'px-3 h-10 w-full text-base bg-secondary-800/90 border-secondary-500/50 focus:border-secondary-500 focus:border-2 focus:ring-0', - 'label' => 'flex items-center', - 'error' => '!border-red-500', - 'hint' => 'py-3 text-xs', - 'message' => 'text-red-500 text-sm', - ]) - ->classMerge([ - 'layer', - ]) - ->only('class') -}}> - @if ($label) - - @endif - -
- {{ $prepend }} - - - - {{ $append }} -
- - @if ($hint) -

{{ $hint }}

- @endif - - @error($attributes->wireKey()) -

- {{ $message }} -

- @enderror -
diff --git a/resources/views/components/layout/container.blade.php b/resources/views/components/layout/container.blade.php deleted file mode 100644 index bca3885b..00000000 --- a/resources/views/components/layout/container.blade.php +++ /dev/null @@ -1,16 +0,0 @@ -@props([ - 'fluid' => false, -]) - -
cssClass([ - 'layer' => 'container', - 'width' => 'w-full max-w-4xl xl:max-w-5xl', - ]) - ->classMerge([ - 'layer', - 'width' => ! $fluid, - ]); -}}> - {{ $slot }} -
diff --git a/resources/views/components/layout/join.blade.php b/resources/views/components/layout/join.blade.php deleted file mode 100644 index 0deea7d3..00000000 --- a/resources/views/components/layout/join.blade.php +++ /dev/null @@ -1,18 +0,0 @@ -@props([ - 'vertical' => false, -]) - -
cssClass([ - 'layer' => 'flex items-center', - 'horizontal' => 'flex-row flex-wrap sm:flex-nowrap', - 'vertical' => 'flex-col', - ]) - ->classMerge([ - 'layer', - 'horizontal' => ! $vertical, - 'vertical' => $vertical, - ]) -}}> - {{ $slot }} -
diff --git a/resources/views/components/navigation/navbar.blade.php b/resources/views/components/navigation/navbar.blade.php deleted file mode 100644 index 6ebf1bea..00000000 --- a/resources/views/components/navigation/navbar.blade.php +++ /dev/null @@ -1,32 +0,0 @@ -@props([ - 'start' => null, - 'end' => null, -]) - - diff --git a/resources/views/navigation/tabs.blade.php b/resources/views/navigation/tabs.blade.php deleted file mode 100644 index 3dde89a0..00000000 --- a/resources/views/navigation/tabs.blade.php +++ /dev/null @@ -1,39 +0,0 @@ -@php - $current = $this->getPropertyValue($wireModel()) -@endphp - - diff --git a/src/Actions/Components/Button.php b/src/Actions/Components/Button.php deleted file mode 100644 index aa6da9fc..00000000 --- a/src/Actions/Components/Button.php +++ /dev/null @@ -1,14 +0,0 @@ -isCurrent()) { - return $this->action->getActiveIcon(); - } - - return $this->action->getIcon(); - } - - public function isCurrent(): bool - { - if ($this->active === $this->action->getName()) { - return true; - } - - return $this->action->routeIs() || $this->action->fullUrlIs(); - } - - public function hasActiveIcon(): bool - { - return $this->action->getActiveIcon() !== $this->iconName(); - } -} diff --git a/src/Actions/Components/Link.php b/src/Actions/Components/Link.php deleted file mode 100644 index 7cb7f892..00000000 --- a/src/Actions/Components/Link.php +++ /dev/null @@ -1,55 +0,0 @@ -action->getLabel() ?: $this->action->getName(); - } - - public function url(): ?string - { - return $this->action->getRoute() ?: $this->action->getUrl(); - } - - public function navigate(): bool - { - if ($this->action->getWireNavigate() === false) { - return false; - } - - return $this->action->routeExist() || $this->action->isAppUrl(); - } - - public function isCurrent(): bool - { - if ($this->active === $this->action->getName()) { - return true; - } - - return $this->action->routeIs() || $this->action->fullUrlIs(); - } - - public function isButton(): bool - { - return boolval($this->button); - } -} diff --git a/src/Actions/Concerns/WithAction.php b/src/Actions/Concerns/WithAction.php deleted file mode 100644 index bcf58712..00000000 --- a/src/Actions/Concerns/WithAction.php +++ /dev/null @@ -1,12 +0,0 @@ -container = $container; - - $this->name = $name; - } - - public static function make(?string $name = null, ?array $attributes = null): static - { - return app(static::class, compact('name', 'attributes')); - } - - public function add(string $name, ?Closure $callback = null, ?array $attributes = null): self - { - $node = new Action($this, $name); - - if ($callback instanceof Closure) { - $callback($node); - } - - if ($attributes) { - $node->attributes($attributes); - } - - $this->addNode($node); - - return $this; - } - - public function addIf(string $name, mixed $condition = false, ?Closure $callback = null, ?array $attributes = null): self - { - if (value($condition)) { - $this->add($name, $callback, $attributes); - } - - return $this; - } - - public function getContainer(): mixed - { - return $this->value('container'); - } - - public function getContainers(): array - { - if (! $this->container) { - return []; - } - - return array_merge($this->container->getContainers(), [$this->container]); - } - - public function getDepth(): int - { - if (! $this->container) { - return 0; - } - - return count($this->container->getContainers()); - } - - public function toArray(): array - { - return [ - 'name' => $this->name, - 'container' => $this->container, - 'attributes' => $this->attributes, - ]; - } -} diff --git a/src/Auth/Controllers/LoginController.php b/src/Auth/Controllers/LoginController.php deleted file mode 100644 index ef70e9bf..00000000 --- a/src/Auth/Controllers/LoginController.php +++ /dev/null @@ -1,53 +0,0 @@ -redirectIntended(); - } - } - - public function mount(): void - { - $this->seo()->setTitle(__('Login')); - $this->seo()->setDescription(__('Login to Account')); - } - - public function render(): View - { - return view('wireuse::auth.login')->with([ - 'actions' => $this->actions(), - ]); - } - - public function submit(): void - { - $this->form->submit(); - - $this->redirectIntended(); - } - - protected function actions(): array - { - return [ - Action::make('submit') - ->label(__('Login')) - ->componentAttributes([ - 'type' => 'submit', - ]), - ]; - } -} diff --git a/src/Auth/Controllers/LogoutController.php b/src/Auth/Controllers/LogoutController.php deleted file mode 100644 index 9b1591e3..00000000 --- a/src/Auth/Controllers/LogoutController.php +++ /dev/null @@ -1,35 +0,0 @@ -seo()->setTitle(__('Logout')); - $this->seo()->setDescription(__('Account Logout')); - - $this->submit(); - } - - public function render(): View - { - return view('wireuse::auth.logout'); - } - - public function submit(): void - { - auth()->logout(); - - request()->session()->invalidate(); - - request()->session()->regenerateToken(); - - $this->redirect('/'); - } -} diff --git a/src/Auth/Controllers/RegisterController.php b/src/Auth/Controllers/RegisterController.php deleted file mode 100644 index e1101abd..00000000 --- a/src/Auth/Controllers/RegisterController.php +++ /dev/null @@ -1,39 +0,0 @@ -redirectIntended(); - } - } - - public function mount(): void - { - $this->seo()->setTitle(__('Register')); - $this->seo()->setDescription(__('Sign up')); - } - - public function render(): View - { - return view('wireuse::auth.register'); - } - - public function submit(): void - { - $this->form->submit(); - - $this->redirect('/'); - } -} diff --git a/src/Auth/Forms/LoginForm.php b/src/Auth/Forms/LoginForm.php deleted file mode 100644 index c890bd54..00000000 --- a/src/Auth/Forms/LoginForm.php +++ /dev/null @@ -1,45 +0,0 @@ - 'required|email', - 'remember' => 'nullable|boolean', - 'password' => [ - 'required', - Password::defaults(), - ], - ]; - } - - protected function handle(): void - { - if (! Auth::attempt($this->only('email', 'password'), $this->remember)) { - $this->addError('email', __('These credentials do not match our records')); - - return; - } - - session()->regenerate(); - } -} diff --git a/src/Auth/Forms/RegisterForm.php b/src/Auth/Forms/RegisterForm.php deleted file mode 100644 index 42bfdd90..00000000 --- a/src/Auth/Forms/RegisterForm.php +++ /dev/null @@ -1,67 +0,0 @@ - 'required|email|unique:users', - 'password' => [ - 'required', - 'confirmed', - Password::defaults(), - ], - 'password_confirmation' => [ - 'required', - Password::defaults(), - ], - ]; - } - - protected function handle(): void - { - $user = $this->getUserModel()::create( - $this->getUserData() - ); - - request()->session()->regenerate(); - - auth()->login($user); - - event(new Registered($user)); - } - - protected function getUserModel(): User - { - return app(config('auth.providers.users.model')); - } - - protected function getUserData(): array - { - $data = $this->only('email', 'password'); - - $data['password'] = Hash::make($data['password']); - - return $data; - } -} diff --git a/src/Facades/WireUse.php b/src/Facades/WireUse.php index a60103ab..5eeb741f 100644 --- a/src/Facades/WireUse.php +++ b/src/Facades/WireUse.php @@ -7,7 +7,6 @@ /** * @see \Foxws\WireUse\WireUse * - * @method static void routes() * @method static void registerComponents(string $name, string $namespace, string $prefix, ?Closure $callback = null) * @method static void registerLivewireComponents(string $name, string $namespace, string $prefix, ?Closure $callback = null) * @method static Stringable componentName(DiscoveredClass $class, string $namespace, string $prefix) diff --git a/src/Forms/Concerns/WithValidation.php b/src/Forms/Concerns/WithValidation.php index fcc53f33..a249d357 100644 --- a/src/Forms/Concerns/WithValidation.php +++ b/src/Forms/Concerns/WithValidation.php @@ -20,6 +20,11 @@ public function check(): void ); } + public function hasMessages(): bool + { + return $this->getErrorBag()->isNotEmpty(); + } + protected static function isRecoverable(): bool { return static::$recoverable; diff --git a/src/Forms/Support/Form.php b/src/Forms/Support/Form.php index d42568fb..21f5769a 100644 --- a/src/Forms/Support/Form.php +++ b/src/Forms/Support/Form.php @@ -62,9 +62,9 @@ public function fill($values) return parent::fill($values); } - public function get(string $property, mixed $default = null): mixed + public function get(string $key, mixed $default = null): mixed { - return $this->getPropertyValue($property) ?: $default; + return $this->getPropertyValue($key) ?: $default; } public function has(...$properties): bool diff --git a/src/Layout/Concerns/WithScroll.php b/src/Layout/Concerns/WithScroll.php new file mode 100644 index 00000000..c6e2959a --- /dev/null +++ b/src/Layout/Concerns/WithScroll.php @@ -0,0 +1,75 @@ +models)) { + $range = range(1, $this->getScrollLimit()); + + foreach ($range as $page) { + $this->mergePageItems($this->getPageItems($page)->all()); + + Sleep::for(100)->milliseconds(); + } + } + } + + #[Computed] + public function items(): array + { + return $this->models; + } + + public function fetch(): void + { + $this->nextPage(); + + $this->mergePageItems( + $this->getPageItems()->all() + ); + } + + public function clear(): void + { + $this->reset('models'); + + unset($this->items); + + $this->resetPage(); + } + + protected function getPageItems(?int $page = null): LengthAwarePaginator + { + $page ??= $this->getPage(); + + return $this->getQuery() + ->paginate(perPage: 16, page: $page); + } + + protected function mergePageItems(array $models = []): void + { + $this->models = array_merge_recursive($this->models, $models); + } + + protected function getScrollLimit(?int $page = null): int + { + $page ??= $this->getPage() ?? 1; + + return Number::clamp($page, 1, 32); + } +} diff --git a/src/Navigation/Components/Tabs.php b/src/Navigation/Components/Tabs.php deleted file mode 100644 index 8c987413..00000000 --- a/src/Navigation/Components/Tabs.php +++ /dev/null @@ -1,24 +0,0 @@ -getPropertyValue( - $this->getTabPath() - ); - - return $this->filterTabs($key)->first(); - } - - protected function tabs(): array - { - return []; - } - - protected function getTabPath(): string - { - return 'tab'; - } - - protected function filterTabs(string $key): mixed - { - return collect($this->tabs()) - ->where(function (mixed $item) use ($key) { - if ($item instanceof Action && $item->getName() === $key) { - return $item; - } - }); - } -} diff --git a/src/Support/Blade/Bladeable.php b/src/Support/Blade/Bladeable.php index 66795b47..19da34da 100644 --- a/src/Support/Blade/Bladeable.php +++ b/src/Support/Blade/Bladeable.php @@ -12,7 +12,7 @@ public static function classMerged(ComponentAttributeBag $attributeBag, ?array $ $values ??= static::classAttributes($attributeBag); return collect($values) - ->map(function (mixed $value, int|string $key) use ($attributeBag) { + ->map(function (mixed $value = null, int|string $key) use ($attributeBag) { if (is_bool($value) && $value === false) { return; } @@ -27,8 +27,7 @@ public static function classMerged(ComponentAttributeBag $attributeBag, ?array $ public static function classAttributes(ComponentAttributeBag $attributeBag): Collection { - return str($attributeBag->whereStartsWith('class:')) - ->matchAll('/class:(.*?)\=/s'); + return str($attributeBag->whereStartsWith('class:'))->matchAll('/class:(.*?)\=/s'); } public static function classKeys(...$keys): Collection diff --git a/src/Support/Blade/Concerns/WithBladeMacros.php b/src/Support/Blade/Concerns/WithBladeMacros.php new file mode 100644 index 00000000..dfb74970 --- /dev/null +++ b/src/Support/Blade/Concerns/WithBladeMacros.php @@ -0,0 +1,77 @@ + $value) { + $key = Bladeable::classKeys($key)->first(); + + /** @var ComponentAttributeBag $this */ + if (! $this->has($key)) { + $this->offsetSet($key, $value); + } + } + + return $this; + }); + + ComponentAttributeBag::macro('classMerge', function (?array $values = null): mixed { + /** @var ComponentAttributeBag $this */ + $classes = Bladeable::classMerged($this, $values) + ->merge($this->get('class')) + ->join(' '); + + $this->offsetSet('class', $classes); + + return $this + ->withoutClass(); + }); + + ComponentAttributeBag::macro('withoutClass', function (): mixed { + /** @var ComponentAttributeBag $this */ + return $this + ->whereDoesntStartWith('class:'); + }); + + ComponentAttributeBag::macro('withoutWireModel', function (): mixed { + /** @var ComponentAttributeBag $this */ + return $this + ->whereDoesntStartWith('wire:model'); + }); + + ComponentAttributeBag::macro('mergeAttributes', function (array $values = []): mixed { + foreach ($values as $key => $value) { + /** @var ComponentAttributeBag $this */ + $this->offsetSet($key, $value); + } + + return $this; + }); + + ComponentAttributeBag::macro('classFor', function (string $key, string $default = ''): mixed { + /** @var ComponentAttributeBag $this */ + $class = Bladeable::classKeys($key)->first(); + + return $this->get($class, $default); + }); + + ComponentAttributeBag::macro('wireModel', function (): mixed { + /** @var ComponentAttributeBag $this */ + return $this->whereStartsWith('wire:model')->first(); + }); + + ComponentAttributeBag::macro('wireKey', function (): mixed { + /** @var ComponentAttributeBag $this */ + return $this->wireModel() ?: $this->first('id') ?: $this->first('name'); + }); + + return $this; + } +} diff --git a/src/Support/Components/Component.php b/src/Support/Components/Component.php deleted file mode 100644 index 70b2eace..00000000 --- a/src/Support/Components/Component.php +++ /dev/null @@ -1,26 +0,0 @@ - $value) { - $this->attributes[$key] = $value; - } - - return $this; - } -} diff --git a/src/Support/Components/Concerns/HasComponent.php b/src/Support/Components/Concerns/HasComponent.php deleted file mode 100644 index 81adafea..00000000 --- a/src/Support/Components/Concerns/HasComponent.php +++ /dev/null @@ -1,35 +0,0 @@ -component = $component; - - return $this; - } - - public function componentAttributes(?array $attributes = null): static - { - $this->componentAttributes = $attributes; - - return $this; - } - - public function getComponent(): ?string - { - return $this->value('component'); - } - - public function hasComponent(): bool - { - return $this->offsetExists('component'); - } - - public function getComponentAttributes(): array - { - return $this->value('componentAttributes', []); - } -} diff --git a/src/Support/Components/Concerns/HasIcon.php b/src/Support/Components/Concerns/HasIcon.php deleted file mode 100644 index c183eaff..00000000 --- a/src/Support/Components/Concerns/HasIcon.php +++ /dev/null @@ -1,40 +0,0 @@ -icon = $icon; - - return $this; - } - - public function iconActive(?string $icon = null): static - { - $this->iconActive = $icon; - - return $this; - } - - public function getIcon(): ?string - { - return $this->value('icon'); - } - - public function hasIcon(): bool - { - return $this->offsetExists('icon'); - } - - public function getActiveIcon(): ?string - { - return $this->value('iconActive', $this->getIcon()); - } - - public function hasActiveIcon(): bool - { - return $this->offsetExists('iconActive'); - } -} diff --git a/src/Support/Components/Concerns/HasLabel.php b/src/Support/Components/Concerns/HasLabel.php deleted file mode 100644 index 52c2fc19..00000000 --- a/src/Support/Components/Concerns/HasLabel.php +++ /dev/null @@ -1,23 +0,0 @@ -label = $label; - - return $this; - } - - public function getLabel(): ?string - { - return $this->value('label'); - } - - public function hasLabel(): bool - { - return $this->offsetExists('label'); - } -} diff --git a/src/Support/Components/Concerns/HasLivewire.php b/src/Support/Components/Concerns/HasLivewire.php deleted file mode 100644 index 84f8ab4e..00000000 --- a/src/Support/Components/Concerns/HasLivewire.php +++ /dev/null @@ -1,42 +0,0 @@ -wireModel = $value; - - $this->wireModifier = $modifier; - - return $this; - } - - public function wireNavigate(?bool $value = true): static - { - $this->wireNavigate = $value; - - return $this; - } - - public function getWireModel(): ?string - { - return $this->value('wireModel'); - } - - public function hasWireModel(): bool - { - return $this->offsetExists('wireModel'); - } - - public function getWireModifier(): ?string - { - return $this->value('wireModifier'); - } - - public function getWireNavigate(): ?bool - { - return $this->value('wireNavigate'); - } -} diff --git a/src/Support/Components/Concerns/HasName.php b/src/Support/Components/Concerns/HasName.php deleted file mode 100644 index 69898466..00000000 --- a/src/Support/Components/Concerns/HasName.php +++ /dev/null @@ -1,23 +0,0 @@ -name = $name; - - return $this; - } - - public function getName(): ?string - { - return $this->value('name'); - } - - public function hasName(): bool - { - return $this->offsetExists('name'); - } -} diff --git a/src/Support/Components/Concerns/HasNodes.php b/src/Support/Components/Concerns/HasNodes.php deleted file mode 100644 index 17bafe3a..00000000 --- a/src/Support/Components/Concerns/HasNodes.php +++ /dev/null @@ -1,55 +0,0 @@ -nodes; - } - - public function getNode(string $key): mixed - { - return null; - } - - public function fillNodes(array $nodes = []): self - { - $this->validateNodes($nodes); - - $this->nodes = $nodes; - - return $this; - } - - public function addNode(mixed $node = null): self - { - $this->validateNode($node); - - $this->nodes[] = value($node, $this->getNodeArgs()); - - return $this; - } - - protected function validateNode(mixed $node = null): void - { - // - } - - protected function validateNodes(array $nodes = []): void - { - collect($nodes) - ->each(fn (mixed $node) => $this->validateNode($node)); - } - - protected function getNodeArgs(): array - { - return []; - } -} diff --git a/src/Support/Components/Concerns/HasRequest.php b/src/Support/Components/Concerns/HasRequest.php deleted file mode 100644 index bd5a8d40..00000000 --- a/src/Support/Components/Concerns/HasRequest.php +++ /dev/null @@ -1,35 +0,0 @@ -url = $url; - - return $this; - } - - public function getUrl(): ?string - { - return $this->value('url'); - } - - public function hasUrl(): bool - { - return $this->offsetExists('url'); - } - - public function isAppUrl(): bool - { - $url = str($this->value('url', ''))->trim(); - - return $url->is('/') || $url->startsWith(config('app.url')); - } - - public function fullUrlIs(): bool - { - return ($url = $this->getUrl()) && request()->fullUrlIs($url); - } -} diff --git a/src/Support/Components/Concerns/HasRouting.php b/src/Support/Components/Concerns/HasRouting.php deleted file mode 100644 index e0e4fd94..00000000 --- a/src/Support/Components/Concerns/HasRouting.php +++ /dev/null @@ -1,62 +0,0 @@ -route = $route; - - $this->routeParameters = $parameters; - - $this->routeAbsolute = $absolute; - - return $this; - } - - public function getRoute(): ?string - { - if (! $this->getRouteName()) { - return null; - } - - return route( - $this->getRouteName(), - $this->getRouteParameters(), - $this->getRouteAbsolute(), - ); - } - - public function hasRoute(): bool - { - return $this->offsetExists('route'); - } - - public function getRouteName(): ?string - { - return $this->value('route'); - } - - public function getRouteParameters(): mixed - { - return $this->value('routeParameters', []); - } - - public function getRouteAbsolute(): bool - { - return $this->value('routeAbsolute', true); - } - - public function routeIs(): bool - { - return ($route = $this->getRouteName()) && request()->routeIs($route); - } - - public function routeExist(): bool - { - return ($route = $this->getRouteName()) && Route::has($route); - } -} diff --git a/src/Support/Components/Concerns/HasState.php b/src/Support/Components/Concerns/HasState.php deleted file mode 100644 index d509bcc4..00000000 --- a/src/Support/Components/Concerns/HasState.php +++ /dev/null @@ -1,35 +0,0 @@ -state = $state; - - return $this; - } - - public function default(mixed $default = null): static - { - $this->default = $default; - - return $this; - } - - public function getState(): mixed - { - return $this->value('state'); - } - - public function hasState(): bool - { - return $this->offsetExists('state'); - } - - public function getDefault(): mixed - { - return $this->value('default'); - } -} diff --git a/src/Support/Components/Concerns/HasVisibility.php b/src/Support/Components/Concerns/HasVisibility.php deleted file mode 100644 index bbd9da24..00000000 --- a/src/Support/Components/Concerns/HasVisibility.php +++ /dev/null @@ -1,35 +0,0 @@ -visible = $visible; - - return $this; - } - - public function hidden(?bool $hidden = true): static - { - $this->hidden = $hidden; - - return $this; - } - - public function getVisible(): ?bool - { - return $this->value('visible'); - } - - public function hasVisible(): bool - { - return $this->offsetExists('visible'); - } - - public function getHidden(): ?bool - { - return $this->value('hidden'); - } -} diff --git a/src/Support/Discover/ComponentScout.php b/src/Support/Discover/ComponentScout.php index 681ee8e9..9dc90322 100644 --- a/src/Support/Discover/ComponentScout.php +++ b/src/Support/Discover/ComponentScout.php @@ -3,7 +3,7 @@ namespace Foxws\WireUse\Support\Discover; use Illuminate\View\Component; -use Spatie\StructureDiscoverer\Cache\FileDiscoverCacheDriver; +use Spatie\StructureDiscoverer\Cache\LaravelDiscoverCacheDriver; use Spatie\StructureDiscoverer\Discover; use Spatie\StructureDiscoverer\StructureScout; @@ -13,6 +13,8 @@ class ComponentScout extends StructureScout public ?string $prefix = null; + public ?string $store = null; + protected function definition(): Discover { return Discover::in($this->path) @@ -21,18 +23,6 @@ protected function definition(): Discover ->full(); } - public function identifier(): string - { - return $this->prefix ?? static::class; - } - - public function cacheDriver(): FileDiscoverCacheDriver - { - return new FileDiscoverCacheDriver( - $this->cacheDirectory() - ); - } - public function prefix(string $prefix): static { $this->prefix = trim($prefix, '-'); @@ -47,8 +37,21 @@ public function path(string $path): static return $this; } - protected function cacheDirectory(): string + public function identifier(): string + { + return $this->prefix ?? static::class; + } + + public function cacheStore(): ?string { - return realpath(config('wireuse.cache-path', storage_path('framework/cache'))); + return $this->store ?? config('structure-discoverer.cache.store'); + } + + public function cacheDriver(): LaravelDiscoverCacheDriver + { + return new LaravelDiscoverCacheDriver( + prefix: $this->identifier(), + store: $this->cacheStore(), + ); } } diff --git a/src/Support/Html/Elements/Icon.php b/src/Support/Html/Elements/Icon.php new file mode 100644 index 00000000..45bf3c68 --- /dev/null +++ b/src/Support/Html/Elements/Icon.php @@ -0,0 +1,15 @@ +html(svg($name, $class)->toHtml()); + } +} diff --git a/src/Support/Html/Elements/Validate.php b/src/Support/Html/Elements/Validate.php new file mode 100644 index 00000000..f1d188d2 --- /dev/null +++ b/src/Support/Html/Elements/Validate.php @@ -0,0 +1,20 @@ +addChild($message, Span::create() + ->class('text-error-500') + ->text($message) + ); + } +} diff --git a/src/Support/Html/Mixins/BaseElementMixin.php b/src/Support/Html/Mixins/BaseElementMixin.php new file mode 100644 index 00000000..d60c0273 --- /dev/null +++ b/src/Support/Html/Mixins/BaseElementMixin.php @@ -0,0 +1,49 @@ +attribute('crossorigin', $value); + }; + } + + public function ignore(): mixed + { + return function (?bool $self = false): BaseElement { + /** @var BaseElement $this */ + return $self + ? $this->attribute('wire:ignore.self') + : $this->attribute('wire:ignore'); + }; + } + + public function wireKey(): mixed + { + return function (?string $value = null): BaseElement { + /** @var BaseElement $this */ + return $this->attribute('wire:key', $value); + }; + } + + public function wireModel(): mixed + { + return function (string $key, ?string $modifiers = null): BaseElement { + /** @var BaseElement $this */ + $directive = str('wire:model') + ->when($modifiers, fn (Stringable $str) => $str->append(".{$modifiers}")) + ->squish(); + + return $this + ->attribute($directive->value(), $key) + ->attribute('id', $key); + }; + } +} diff --git a/src/Support/Html/Mixins/HtmlExtendedMixin.php b/src/Support/Html/Mixins/HtmlExtendedMixin.php new file mode 100644 index 00000000..ff224d45 --- /dev/null +++ b/src/Support/Html/Mixins/HtmlExtendedMixin.php @@ -0,0 +1,53 @@ +form = $form; + + return Form::create() + ->attributeIf($action, 'wire:submit', $action); + }; + } + + public function closeWireForm(): mixed + { + return function (): Form { + $this->form = null; + + return Form::create()->close(); + }; + } + + public function icon(): mixed + { + return function (): Icon { + return Icon::create(); + }; + } + + public function validate(): mixed + { + return function (string $field, ?string $message = null): Validate { + $messageBag = $this->form?->getErrorBag(); + + $hasMessage = $messageBag?->has($field); + + return Validate::create() + ->classUnless($hasMessage, 'hidden') + ->classIfNotNull($hasMessage, 'block py-1 text-sm') + ->messageIf($hasMessage, $message ?? $messageBag->first($field)); + }; + } +} diff --git a/src/Support/Html/Mixins/ImgElementMixin.php b/src/Support/Html/Mixins/ImgElementMixin.php new file mode 100644 index 00000000..4f015840 --- /dev/null +++ b/src/Support/Html/Mixins/ImgElementMixin.php @@ -0,0 +1,24 @@ +attribute('srcset', $value); + }; + } + + public function loading(): mixed + { + return function (?string $value = 'lazy') { + /** @var Img $this */ + return $this->attribute('loading', $value); + }; + } +} diff --git a/src/Support/Html/Mixins/LinkElementMixin.php b/src/Support/Html/Mixins/LinkElementMixin.php new file mode 100644 index 00000000..201331b2 --- /dev/null +++ b/src/Support/Html/Mixins/LinkElementMixin.php @@ -0,0 +1,32 @@ +navigate() + ->href($href) + ->class([ + 'link', + 'link-active' => request()->routeIs($route, "{$route}.*") || request()->fullUrlIs($href), + ]); + }; + } + + public function navigate(): mixed + { + return function (): A { + /** @var A $this */ + return $this->attribute('wire:navigate'); + }; + } +} diff --git a/src/Support/Livewire/ActionObjects/ActionObjectSynth.php b/src/Support/Livewire/ActionObjects/ActionObjectSynth.php deleted file mode 100644 index b48256d5..00000000 --- a/src/Support/Livewire/ActionObjects/ActionObjectSynth.php +++ /dev/null @@ -1,37 +0,0 @@ -toArray(), []]; - } - - public function hydrate($value) - { - $action = new Action($value['container'], $value['name']); - - $action->attributes($this->getAttributes($value)); - - return $action; - } - - protected function getAttributes(array $values): array - { - return collect($values) - ->except('container', 'name') - ->toArray(); - } -} diff --git a/src/Support/Livewire/ActionObjects/SupportActionObjects.php b/src/Support/Livewire/ActionObjects/SupportActionObjects.php deleted file mode 100644 index c2e97897..00000000 --- a/src/Support/Livewire/ActionObjects/SupportActionObjects.php +++ /dev/null @@ -1,15 +0,0 @@ -propertySynthesizer( - ActionObjectSynth::class - ); - } -} diff --git a/src/Views/Support/Component.php b/src/Views/Support/Component.php index 779264bf..ef5c8234 100644 --- a/src/Views/Support/Component.php +++ b/src/Views/Support/Component.php @@ -3,7 +3,6 @@ namespace Foxws\WireUse\Views\Support; use Foxws\WireUse\Views\Concerns\WithHash; -use Foxws\WireUse\Views\Concerns\WithLayout; use Foxws\WireUse\Views\Concerns\WithLivewire; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Tappable; @@ -14,6 +13,5 @@ abstract class Component extends BaseComponent use Conditionable; use Tappable; use WithHash; - use WithLayout; use WithLivewire; } diff --git a/src/WireUse.php b/src/WireUse.php index d817f5c2..30ab0fb7 100755 --- a/src/WireUse.php +++ b/src/WireUse.php @@ -2,28 +2,16 @@ namespace Foxws\WireUse; -use Foxws\WireUse\Auth\Controllers\LoginController; -use Foxws\WireUse\Auth\Controllers\LogoutController; -use Foxws\WireUse\Auth\Controllers\RegisterController; use Foxws\WireUse\Support\Discover\ComponentScout; use Foxws\WireUse\Support\Discover\LivewireScout; use Illuminate\Support\Facades\Blade; -use Illuminate\Support\Facades\Route; use Illuminate\Support\Stringable; use Livewire\Livewire; +use Livewire\LivewireManager; use Spatie\StructureDiscoverer\Data\DiscoveredStructure; class WireUse { - public static function routes(): void - { - Route::name('auth.')->group(function () { - Route::get('/login', LoginController::class)->middleware('guest')->name('login'); - Route::get('/register', RegisterController::class)->middleware('guest')->name('register'); - Route::post('/logout', LogoutController::class)->name('logout'); - }); - } - public static function registerComponents( string $path, string $namespace = 'App\\', @@ -56,7 +44,11 @@ public static function registerLivewireComponents( ->each(function (DiscoveredStructure $class) use ($namespace, $prefix) { $name = static::componentName($class, $namespace, $prefix); - Livewire::component($name->value(), $class->getFcqn()); + $fcqn = $class->getFcqn(); + + if (app(LivewireManager::class)->isDiscoverable($fcqn)) { + Livewire::component($name->value(), $fcqn); + } }); } diff --git a/src/WireUseServiceProvider.php b/src/WireUseServiceProvider.php index bbc056c2..0afc1e25 100644 --- a/src/WireUseServiceProvider.php +++ b/src/WireUseServiceProvider.php @@ -2,9 +2,6 @@ namespace Foxws\WireUse; -use Foxws\WireUse\Support\Blade\Bladeable; -use Illuminate\Support\Facades\Blade; -use Illuminate\View\ComponentAttributeBag; use Spatie\LaravelPackageTools\Commands\InstallCommand; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; @@ -23,25 +20,16 @@ public function configurePackage(Package $package): void }); } - public function packageRegistered() - { - $this->app->singleton(Bladeable::class); - } - public function bootingPackage(): void { $this ->registerFeatures() - ->registerBladeMacros() - ->registerAnonymousComponent() - ->registerComponents() - ->registerLivewire(); + ->registerMixins(); } protected function registerFeatures(): static { foreach ([ - \Foxws\WireUse\Support\Livewire\ActionObjects\SupportActionObjects::class, \Foxws\WireUse\Support\Livewire\StateObjects\SupportStateObjects::class, ] as $feature) { app('livewire')->componentHook($feature); @@ -50,119 +38,12 @@ protected function registerFeatures(): static return $this; } - protected function registerBladeMacros(): static - { - if (config('wireuse.register_macros') === false) { - return $this; - } - - ComponentAttributeBag::macro('cssClass', function (array $values = []): mixed { - foreach ($values as $key => $value) { - $key = app(Bladeable::class)::classKeys($key)->first(); - - /** @var ComponentAttributeBag $this */ - if (! $this->has($key)) { - $this->offsetSet($key, $value); - } - } - - return $this; - }); - - ComponentAttributeBag::macro('classMerge', function (?array $values = null): mixed { - /** @var ComponentAttributeBag $this */ - $classes = app(Bladeable::class)::classMerged($this, $values) - ->merge($this->get('class')) - ->join(' '); - - $this->offsetSet('class', $classes); - - return $this - ->withoutClass(); - }); - - ComponentAttributeBag::macro('withoutClass', function (): mixed { - /** @var ComponentAttributeBag $this */ - return $this - ->whereDoesntStartWith('class:'); - }); - - ComponentAttributeBag::macro('withoutWireModel', function (): mixed { - /** @var ComponentAttributeBag $this */ - return $this - ->whereDoesntStartWith('wire:model'); - }); - - ComponentAttributeBag::macro('mergeAttributes', function (array $values = []): mixed { - foreach ($values as $key => $value) { - /** @var ComponentAttributeBag $this */ - $this->offsetSet($key, $value); - } - - return $this; - }); - - ComponentAttributeBag::macro('classFor', function (string $key, string $default = ''): mixed { - /** @var ComponentAttributeBag $this */ - $class = app(Bladeable::class)::classKeys($key)->first(); - - return $this->get($class, $default); - }); - - ComponentAttributeBag::macro('wireModel', function (): mixed { - /** @var ComponentAttributeBag $this */ - return $this->whereStartsWith('wire:model')->first(); - }); - - ComponentAttributeBag::macro('wireKey', function (): mixed { - /** @var ComponentAttributeBag $this */ - return $this->wireModel() ?: $this->first('id') ?: $this->first('name'); - }); - - return $this; - } - - protected function registerAnonymousComponent(): static - { - if (config('wireuse.register_components') === false) { - return $this; - } - - Blade::anonymousComponentPath( - path: __DIR__.'/../resources/views/components', - prefix: 'wireuse' - ); - - return $this; - } - - protected function registerComponents(): static + protected function registerMixins(): static { - if (config('wireuse.register_components') === false) { - return $this; + foreach (config('wireuse.html.mixins', []) as $element => $mixin) { + $element::mixin(new $mixin); } - WireUse::registerComponents( - path: __DIR__, - namespace: 'Foxws\\WireUse\\', - prefix: config('wireuse.view_prefix'), - ); - - return $this; - } - - protected function registerLivewire(): static - { - if (config('wireuse.register_components') === false) { - return $this; - } - - WireUse::registerLivewireComponents( - path: __DIR__, - namespace: 'Foxws\\WireUse\\', - prefix: config('wireuse.view_prefix'), - ); - return $this; } } diff --git a/tailwind.config.js b/tailwind.config.js index 73fd597f..ff72f7af 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -5,6 +5,7 @@ import theme from './resources/css/presets/tailwind.config.preset'; /** @type {import('tailwindcss').Config} */ export default { presets: [theme], - content: ['./resources/**/*.blade.php'], + relative: true, + content: ['./resources/**/*.blade.php', './src/**/*.php'], plugins: [forms, typography], }; diff --git a/tests/src/Support/BladeDirectiveTest.php b/tests/src/Support/BladeDirectiveTest.php deleted file mode 100644 index 66a74f5e..00000000 --- a/tests/src/Support/BladeDirectiveTest.php +++ /dev/null @@ -1,12 +0,0 @@ -')) - ->toContain('class="flex flex-nowrap bg-gray-300 opacity-50"') - ->toMatchSnapshot(); -}); diff --git a/tests/src/TestClasses/BladeComponent.php b/tests/src/TestClasses/BladeComponent.php index 9d85f866..9666d43e 100644 --- a/tests/src/TestClasses/BladeComponent.php +++ b/tests/src/TestClasses/BladeComponent.php @@ -9,15 +9,9 @@ class BladeComponent extends Component public function render(): string { return <<<'blade' -
cssClass([ - 'layer' => 'flex flex-nowrap', - 'color' => 'bg-gray-300 opacity-50', - ]) - ->classMerge() - }}> - {{-- wow, such great content here --}} -
+ {{ html()->div()->class('text-center')->open() }} + {{-- wow, such great article content here --}} + {{ html()->div()->close() }} blade; } }