diff --git a/README.md b/README.md index b085d01..d039417 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,20 @@ $navigation->get()->name; $navigation->get('name', 'My menu title'); ``` +### Acorn Usage + +If you are using Navi alongside [Acorn](https://roots.io/acorn/) (e.g. Sage), you may generate a usable view component using Acorn's CLI: + +```sh +$ acorn make:navi +``` + +Once generated, you may use the [view component](https://laravel.com/docs/11.x/blade#components) in an existing view like so: + +```php + +``` + ### Accessing Page Objects If your menu item is linked to a page object (e.g. not a custom link) – you can retrieve the ID of the page using the `objectId` attribute. diff --git a/examples/sage/app/View/Composers/Navigation.php b/examples/sage/app/View/Composers/Navigation.php deleted file mode 100644 index 290249a..0000000 --- a/examples/sage/app/View/Composers/Navigation.php +++ /dev/null @@ -1,26 +0,0 @@ -toArray(); - } -} diff --git a/examples/sage/resources/views/components/navigation.blade.php b/examples/sage/resources/views/components/navigation.blade.php new file mode 100644 index 0000000..77fb182 --- /dev/null +++ b/examples/sage/resources/views/components/navigation.blade.php @@ -0,0 +1,39 @@ +@props([ + 'name' => null, + 'inactive' => 'hover:text-blue-500', + 'active' => 'text-blue-500', +]) + +@php($menu = Navi::build($name)) + +@if ($menu->isNotEmpty()) + +@endif diff --git a/examples/sage/resources/views/partials/navigation.blade.php b/examples/sage/resources/views/partials/navigation.blade.php deleted file mode 100644 index a69b4c1..0000000 --- a/examples/sage/resources/views/partials/navigation.blade.php +++ /dev/null @@ -1,23 +0,0 @@ -@if ($navigation) - -@endif diff --git a/src/Console/NaviMakeCommand.php b/src/Console/NaviMakeCommand.php new file mode 100644 index 0000000..85867e4 --- /dev/null +++ b/src/Console/NaviMakeCommand.php @@ -0,0 +1,165 @@ +argument('name'))); + + $this->components->info("Navi component is ready for use."); + } + + /** + * Build the class with the given name. + * + * @param string $name + * @return string + */ + protected function buildClass($name) + { + $contents = parent::buildClass($name); + + return str_replace( + '{{ default }}', + $this->option('default') ? Str::wrap($this->option('default'), "'") : 'null', + $contents, + ); + } + + /** + * Get the destination view path. + * + * @param string $name + * @return string + */ + protected function getPath($name) + { + $path = $this->viewPath( + str_replace('.', '/', 'components.'.$this->getView()).'.blade.php' + ); + + if (! $this->files->isDirectory(dirname($path))) { + $this->files->makeDirectory(dirname($path), 0777, true, true); + } + + return $path; + } + + /** + * Get the view name relative to the components directory. + * + * @return string + */ + protected function getView() + { + $name = str_replace('\\', '/', $this->argument('name')); + + return collect(explode('/', $name)) + ->map(fn ($part) => Str::kebab($part)) + ->implode('.'); + } + + /** + * Get the desired view name from the input. + * + * @return string + */ + protected function getNameInput() + { + $name = trim($this->argument('name')); + + $name = str_replace(['\\', '.'], '/', $this->argument('name')); + + return $name; + } + + /** + * Get the stub file for the generator. + * + * @return string + */ + protected function getStub() + { + return $this->resolveStubPath( + '/stubs/view.stub', + ); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Prompt for missing input arguments using the returned questions. + * + * @return array + */ + protected function promptForMissingArgumentsUsing() + { + return [ + 'name' => [ + 'What should the Navi component be named?', + 'E.g. Navigation', + ], + ]; + } + + /** + * Get the console command arguments. + * + * @return array + */ + protected function getOptions() + { + return [ + ['default', 'd', InputOption::VALUE_OPTIONAL, 'The default menu name'], + ['force', 'f', InputOption::VALUE_NONE, 'Create the view component even if the component already exists'], + ]; + } +} diff --git a/src/Console/stubs/view.stub b/src/Console/stubs/view.stub new file mode 100644 index 0000000..0ce446b --- /dev/null +++ b/src/Console/stubs/view.stub @@ -0,0 +1,39 @@ +@props([ + 'name' => {{ default }}, + 'inactive' => 'hover:text-blue-500', + 'active' => 'text-blue-500', +]) + +@php($menu = Navi::build($name)) + +@if ($menu->isNotEmpty()) +
    + @foreach ($menu->all() as $item) +
  • classes, + $inactive => ! $item->active, + $active => $item->active, + ])> + + {{ $item->label }} + + + @if ($item->children) +
      + @foreach ($item->children as $child) +
    • classes, + $inactive => ! $child->active, + $active => $child->active, + ])> + + {{ $child->label }} + +
    • + @endforeach +
    + @endif +
  • + @endforeach +
+@endif diff --git a/src/Navi.php b/src/Navi.php index 6769861..30ec5d9 100644 --- a/src/Navi.php +++ b/src/Navi.php @@ -14,6 +14,11 @@ class Navi */ protected array $items = []; + /** + * The default menu. + */ + protected string $default = 'primary_navigation'; + /** * Create a new Navi instance. */ @@ -35,8 +40,10 @@ public static function make(array $items = []): self /** * Build the navigation menu items. */ - public function build(string $menu = 'primary_navigation'): self + public function build(mixed $menu = null): self { + $menu = $menu ?? $this->default; + if (is_string($menu)) { $locations = get_nav_menu_locations(); diff --git a/src/Providers/NaviServiceProvider.php b/src/Providers/NaviServiceProvider.php index f012cdc..08b2ce1 100644 --- a/src/Providers/NaviServiceProvider.php +++ b/src/Providers/NaviServiceProvider.php @@ -3,6 +3,7 @@ namespace Log1x\Navi\Providers; use Illuminate\Support\ServiceProvider; +use Log1x\Navi\Console\NaviMakeCommand; use Log1x\Navi\Navi; class NaviServiceProvider extends ServiceProvider @@ -16,4 +17,18 @@ public function register() { $this->app->bind('navi', fn () => Navi::make()); } + + /** + * Bootstrap any application services. + * + * @return void + */ + public function boot() + { + if ($this->app->runningInConsole()) { + $this->commands([ + NaviMakeCommand::class, + ]); + } + } }