diff --git a/README.md b/README.md
index bc85e22..f9abdcd 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ This package provides a set of scaffolding commands to help you quickly set up c
in [Brave](https://github.com/yardinternet/brave):
```shell
+wp acorn scaffold:wp-events
wp acorn scaffold:knowledgebase
wp acorn scaffold:news
wp acorn scaffold:person
@@ -53,6 +54,14 @@ To create a child theme you can run the following command. This will create a ch
More information about child themes can be found in [Brave](https://github.com/yardinternet/brave)
and [Sage Child Theme Support](https://github.com/yardinternet/sage-child-theme-support)
+### Elasticsearch & Reactive Search
+
+```shell
+wp acorn scaffold:elasticsearch
+```
+
+After scaffolding, [follow these manual steps to complete the setup](docs/elasticsearch.md).
+
## About us
[](https://www.yard.nl/werken-bij/)
diff --git a/docs/elasticsearch.md b/docs/elasticsearch.md
new file mode 100644
index 0000000..afa9a0b
--- /dev/null
+++ b/docs/elasticsearch.md
@@ -0,0 +1,74 @@
+# Elasticsearch
+
+Use the WP Acorn scaffold command to get started:
+
+```shell
+wp acorn scaffold:elasticsearch
+```
+
+After scaffolding, follow these steps:
+
+## 1. Install dependencies
+
+Install the Yard Elasticsearch plugin and the Reactive Search npm package:
+
+```shell
+composer require plugin/yard-elasticsearch && pnpm install @yardinternet/reactive-search
+```
+
+## 2. Add the Elasticsearch `.env` variables
+
+Add the following variables to your `.env` and `.env.example` file:
+
+```env
+# Elasticsearch
+EP_HOST=
+ES_PUBLIC_URL=
+```
+
+## 3. Add Reactive Search entrypoint to Vite
+
+Update your `vite.config.js`:
+
+```js
+export default braveConfig( {
+ entryPoints: [
+ 'resources/scripts/reactive-search/reactive-search.jsx',
+ ],
+} );
+```
+
+## 4. Register the Elasticsearch Hook
+
+Add the `Elasticsearch.php` hook to your `hooks.php`:
+
+```php
+return [
+ 'elasticsearch' => \App\Hooks\Elasticsearch::class,
+];
+```
+
+## 5. Add the reactive search bar to the header
+
+Replace the current `@include('partials.header.search-bar')` of the search-bar with the following in the `header.blade.php`:
+
+```diff
+- @include('partials.header.search-bar')
+
++ @if (is_plugin_active('yard-elasticsearch/yard-elasticsearch.php'))
++ @include('partials.header.reactive-search-bar')
++ @else
++ @include('partials.header.search-bar')
++ @endif
+```
+
+## 6. Activate the Plugin & Configure Settings
+
+1. Activate the Yard Elasticsearch plugin in WordPress.
+2. Go to the settings page `/wp/wp-admin/admin.php?page=acf-options-yard-elastic`
+3. Configure the following settings:
+ - **Bronnen** (required)
+ - **Filters** (optional)
+ - **Veld weging** (required)
+
+Everything should now be set up and ready to use!
diff --git a/src/Console/ElasticsearchScaffoldCommand.php b/src/Console/ElasticsearchScaffoldCommand.php
new file mode 100644
index 0000000..862a8b3
--- /dev/null
+++ b/src/Console/ElasticsearchScaffoldCommand.php
@@ -0,0 +1,37 @@
+call('vendor:publish', [
+ '--provider' => 'Yard\\Brave\\Scaffold\\ScaffoldServiceProvider',
+ '--tag' => 'elasticsearch',
+ ]);
+ $this->info('You need to do some additional steps after running this scaffold. Please read the docs here:');
+ $this->line('https://github.com/yardinternet/brave-scaffold/blob/feat/elasticsearch/docs/elasticsearch.md');
+ }
+}
diff --git a/src/ScaffoldServiceProvider.php b/src/ScaffoldServiceProvider.php
index 138d367..af52a6b 100644
--- a/src/ScaffoldServiceProvider.php
+++ b/src/ScaffoldServiceProvider.php
@@ -7,6 +7,7 @@
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
use Yard\Brave\Scaffold\Console\ChildThemeScaffoldCommand;
+use Yard\Brave\Scaffold\Console\ElasticsearchScaffoldCommand;
use Yard\Brave\Scaffold\Console\EventScaffoldCommand;
use Yard\Brave\Scaffold\Console\KnowledgebaseScaffoldCommand;
use Yard\Brave\Scaffold\Console\NewsScaffoldCommand;
@@ -22,6 +23,7 @@ public function configurePackage(Package $package): void
->hasCommands(
[
ChildThemeScaffoldCommand::class,
+ ElasticsearchScaffoldCommand::class,
KnowledgebaseScaffoldCommand::class,
NewsScaffoldCommand::class,
PersonScaffoldCommand::class,
@@ -33,6 +35,21 @@ public function configurePackage(Package $package): void
public function bootingPackage(): void
{
+ $this->publishes([
+ __DIR__ . '/../stubs/app/Hooks/Elasticsearch.php' => app_path('Hooks/Elasticsearch.php'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/reactive-search.jsx' => resource_path('scripts/reactive-search/reactive-search.jsx'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/config/theme.js' => resource_path('scripts/reactive-search/config/theme.js'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/styles/autosuggest.css' => resource_path('scripts/reactive-search/styles/autosuggest.css'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/views/search-bar/search-bar.css' => resource_path('scripts/reactive-search/views/search-bar/search-bar.css'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/views/search-bar/SearchBar.jsx' => resource_path('scripts/reactive-search/views/search-bar/SearchBar.jsx'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/views/search-input/search-input.css' => resource_path('scripts/reactive-search/views/search-input/search-input.css'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/views/search-input/SearchInput.jsx' => resource_path('scripts/reactive-search/views/search-input/SearchInput.jsx'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/views/search-page/search-page.css' => resource_path('scripts/reactive-search/views/search-page/search-page.css'),
+ __DIR__ . '/../stubs/resources/scripts/reactive-search/views/search-page/SearchPage.jsx' => resource_path('scripts/reactive-search/views/search-page/SearchPage.jsx'),
+ __DIR__ . '/../stubs/resources/views/partials/header/reactive-search-bar.blade.php' => resource_path('views/partials/header/reactive-search-bar.blade.php'),
+ __DIR__ . '/../stubs/resources/views/reactive-search-page.blade.php' => resource_path('views/reactive-search-page.blade.php'),
+ ], 'elasticsearch');
+
$this->publishes([
__DIR__ . '/../stubs/View/Components/Card/News.php' => app_path('View/Components/Card/News.php'),
__DIR__ . '/../stubs/Data/NewsData.php' => app_path('Data/NewsData.php'),
diff --git a/stubs/app/Hooks/Elasticsearch.php b/stubs/app/Hooks/Elasticsearch.php
new file mode 100644
index 0000000..970ff58
--- /dev/null
+++ b/stubs/app/Hooks/Elasticsearch.php
@@ -0,0 +1,46 @@
+toHtml();
+ } catch (\Exception $e) {
+ // Fail silently if entrypoint is not found.
+ }
+ }
+
+ #[Filter('template_include')]
+ public function overrideSearchTemplate(string $template): string
+ {
+ if (! is_search() || is_admin()) {
+ return $template;
+ }
+
+ $override = get_theme_file_path('resources/views/reactive-search-page.blade.php');
+
+ if (file_exists($override)) {
+ return $override;
+ }
+
+ return $template;
+ }
+}
diff --git a/stubs/resources/scripts/reactive-search/config/theme.js b/stubs/resources/scripts/reactive-search/config/theme.js
new file mode 100644
index 0000000..d782eb8
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/config/theme.js
@@ -0,0 +1,11 @@
+export const theme = {
+ typography: {
+ fontFamily: 'inherit',
+ fontSize: 'inherit',
+ },
+ colors: {
+ primaryColor: '#3a0056', // @todo
+ borderColor: '#3a0056', // @todo
+ textColor: '#000',
+ },
+};
diff --git a/stubs/resources/scripts/reactive-search/reactive-search.jsx b/stubs/resources/scripts/reactive-search/reactive-search.jsx
new file mode 100644
index 0000000..8c78614
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/reactive-search.jsx
@@ -0,0 +1,34 @@
+/**
+ * Internal dependencies
+ */
+import SearchPage from './views/search-page/SearchPage.jsx';
+import SearchBar from './views/search-bar/SearchBar.jsx';
+import SearchInput from './views/search-input/SearchInput.jsx';
+
+/**
+ * WordPress dependencies
+ */
+import { createRoot } from '@wordpress/element';
+
+/**
+ * Styles
+ */
+import './styles/autosuggest.css';
+
+if ( document.getElementById( 'js-reactive-search-page' ) ) {
+ createRoot( document.getElementById( 'js-reactive-search-page' ) ).render(
+
+ );
+}
+
+if ( document.getElementById( 'js-reactive-search-bar' ) ) {
+ createRoot( document.getElementById( 'js-reactive-search-bar' ) ).render(
+
+ );
+}
+
+if ( document.getElementById( 'js-reactive-search-input' ) ) {
+ createRoot( document.getElementById( 'js-reactive-search-input' ) ).render(
+
+ );
+}
diff --git a/stubs/resources/scripts/reactive-search/styles/autosuggest.css b/stubs/resources/scripts/reactive-search/styles/autosuggest.css
new file mode 100644
index 0000000..60f1e55
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/styles/autosuggest.css
@@ -0,0 +1,56 @@
+@reference '@sage/styles/base/config.css';
+@reference '@sage/styles/base/utilities.css';
+
+.yrs-wrapper {
+ .yrs-autosuggest {
+ @apply z-100 shadow;
+ }
+
+ .yrs-autosuggest-item {
+ @apply border-gray-100;
+
+ &:last-child {
+ @apply font-bold;
+
+ .yrs-autosuggest-link {
+ @apply gap-x-4;
+ }
+ }
+
+ &.is-selected {
+ .yrs-autosuggest-link {
+ @apply text-primary bg-white;
+ animation: focus 0.1s linear both;
+ outline-color: -webkit-focus-ring-color;
+ outline-style: auto;
+ }
+ }
+ }
+
+ .yrs-autosuggest-link {
+ @apply py-2 no-underline;
+
+ &:hover,
+ &:focus {
+ @apply text-black;
+ }
+
+ @variant hocus {
+ @apply text-primary;
+ }
+
+ &:focus {
+ .trim {
+ @apply underline;
+ }
+ }
+
+ i {
+ @apply text-inherit!;
+ }
+ }
+
+ .yrs-autosuggest-link-label {
+ @apply text-xs whitespace-nowrap sm:pl-4;
+ }
+}
diff --git a/stubs/resources/scripts/reactive-search/views/search-bar/SearchBar.jsx b/stubs/resources/scripts/reactive-search/views/search-bar/SearchBar.jsx
new file mode 100644
index 0000000..03dc25d
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/views/search-bar/SearchBar.jsx
@@ -0,0 +1,43 @@
+/**
+ * External dependencies
+ */
+import {
+ Base,
+ SearchBar as ReactiveSearchBar,
+} from '@yardinternet/reactive-search';
+
+/**
+ * Internal dependencies
+ */
+import { theme } from '../../config/theme';
+import './search-bar.css';
+
+const SearchBar = () => {
+ if ( ! window.YS || ! window.YS.indices ) {
+ console.error( 'Error: Yard Elasticsearch indices has not been set.' ); // eslint-disable-line no-console
+ return <>>;
+ }
+
+ return (
+
+
+
+ );
+};
+
+export default SearchBar;
diff --git a/stubs/resources/scripts/reactive-search/views/search-bar/search-bar.css b/stubs/resources/scripts/reactive-search/views/search-bar/search-bar.css
new file mode 100644
index 0000000..5ba50f2
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/views/search-bar/search-bar.css
@@ -0,0 +1,68 @@
+@reference '@sage/styles/base/config.css';
+@reference '@sage/styles/base/utilities.css';
+
+.yrs-search-bar-container {
+ .yrs-search-bar-btn-open {
+ @apply lg:text-primary flex h-11.5 flex-col items-center justify-between rounded bg-white text-black transition-all lg:size-14 lg:min-w-14 lg:justify-center;
+
+ &::before {
+ @apply fontawesome pointer-events-none text-4xl leading-none transition md:text-2xl;
+ --fa-icon: '\f002';
+ --fa-weight: 400;
+ }
+
+ @variant hocus {
+ @apply text-primary;
+ }
+
+ .yrs-search-bar-btn-open-text {
+ @apply text-xs leading-none lg:sr-only;
+ }
+ }
+
+ .yrs-search-bar-inner {
+ @apply top-(--wp-admin-bar-height) h-(--combined-bar-height)! gap-x-2 sm:gap-x-4;
+ }
+
+ .yrs-datasearch-autosuggest {
+ @apply w-full max-w-xl;
+
+ > div {
+ @apply m-0;
+ }
+
+ .yrs-datasearch-autosuggest-input {
+ @apply border-primary ring-primary rounded-none border-0 border-b-2 bg-white shadow-none! md:py-4 md:pl-3 md:text-lg;
+ }
+
+ .input-group {
+ @apply shadow-none;
+ }
+ }
+
+ .yrs-search-bar-btn-submit,
+ .yrs-search-bar-btn-close {
+ @apply size-8 min-w-8 sm:text-lg xl:text-xl;
+
+ &::before {
+ @apply fontawesome transition;
+ --fa-icon: '\f002';
+ }
+
+ @variant hocus {
+ &::before {
+ @apply text-primary;
+ }
+ }
+ }
+
+ .yrs-search-bar-btn-submit-text,
+ .yrs-search-bar-btn-close-text {
+ @apply sr-only;
+ }
+
+ .yrs-search-bar-btn-close::before {
+ @apply fontawesome;
+ --fa-icon: '\f00d';
+ }
+}
diff --git a/stubs/resources/scripts/reactive-search/views/search-input/SearchInput.jsx b/stubs/resources/scripts/reactive-search/views/search-input/SearchInput.jsx
new file mode 100644
index 0000000..feb2c40
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/views/search-input/SearchInput.jsx
@@ -0,0 +1,43 @@
+/**
+ * External dependencies
+ */
+import {
+ Base,
+ SearchInput as ReactiveSearchInput,
+} from '@yardinternet/reactive-search';
+
+/**
+ * Internal dependencies
+ */
+import { theme } from '../../config/theme';
+import './search-input.css';
+
+const SearchInput = () => {
+ if ( ! window.YS || ! window.YS.indices ) {
+ console.error( 'Error: Yard Elasticsearch indices has not been set.' ); // eslint-disable-line no-console
+ return <>>;
+ }
+
+ return (
+
+
+
+ );
+};
+
+export default SearchInput;
diff --git a/stubs/resources/scripts/reactive-search/views/search-input/search-input.css b/stubs/resources/scripts/reactive-search/views/search-input/search-input.css
new file mode 100644
index 0000000..7f7841d
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/views/search-input/search-input.css
@@ -0,0 +1,64 @@
+@reference '@sage/styles/base/config.css';
+@reference '@sage/styles/base/utilities.css';
+
+:root {
+ --yrs-search-input-height: 60px;
+}
+
+.wp-block-yard-yrs-search-input {
+ @apply min-h-(--yrs-search-input-height) w-full;
+}
+
+.yrs-search-input-container {
+ @apply mx-auto w-full shadow;
+
+ &:has( .yrs-datasearch-autosuggest-input:focus ),
+ &:has( .yrs-datasearch-autosuggest-input:not( :placeholder-shown ) ) {
+ .yrs-search-input-label {
+ @apply -translate-y-4 text-xs leading-none;
+ }
+ }
+
+ .yrs-search-input-label {
+ @apply left-2 bg-white px-2 py-1;
+ }
+
+ .yrs-datasearch-autosuggest {
+ > div {
+ @apply m-0;
+ }
+
+ .input-group {
+ @apply shadow-none;
+
+ .yrs-datasearch-autosuggest-input {
+ @apply ring-primary focus:border-primary h-(--yrs-search-input-height) rounded-none py-3! pr-16! pl-4! shadow-none;
+
+ + div > div {
+ @apply p-0;
+
+ > div {
+ @apply max-w-full;
+ }
+ }
+ }
+
+ .yrs-search-bar-btn-submit {
+ @apply bg-primary absolute top-0 right-0 h-full w-18 text-2xl text-white transition;
+
+ &::before {
+ @apply fontawesome;
+ --fa-icon: '\f002';
+ }
+
+ @variant hocus {
+ @apply bg-primary-800;
+ }
+ }
+
+ .yrs-search-bar-btn-submit-text {
+ @apply sr-only;
+ }
+ }
+ }
+}
diff --git a/stubs/resources/scripts/reactive-search/views/search-page/SearchPage.jsx b/stubs/resources/scripts/reactive-search/views/search-page/SearchPage.jsx
new file mode 100644
index 0000000..5f25dcc
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/views/search-page/SearchPage.jsx
@@ -0,0 +1,43 @@
+/**
+ * External dependencies
+ */
+import {
+ Base,
+ SearchPage as ReactiveSearchPage,
+} from '@yardinternet/reactive-search';
+
+/**
+ * Internal dependencies
+ */
+import { theme } from '../../config/theme';
+import './search-page.css';
+
+const SearchPage = () => {
+ if ( ! window.YS || ! window.YS.indices ) {
+ console.error( 'Error: Yard Elasticsearch indices has not been set.' ); // eslint-disable-line no-console
+ return <>>;
+ }
+
+ return (
+
+
+
+ );
+};
+
+export default SearchPage;
diff --git a/stubs/resources/scripts/reactive-search/views/search-page/search-page.css b/stubs/resources/scripts/reactive-search/views/search-page/search-page.css
new file mode 100644
index 0000000..9b92bcd
--- /dev/null
+++ b/stubs/resources/scripts/reactive-search/views/search-page/search-page.css
@@ -0,0 +1,206 @@
+@reference '@sage/styles/base/config.css';
+@reference '@sage/styles/base/utilities.css';
+
+:root {
+ --yrs-datasearch-input-border-color: var( --color-gray-400 );
+ --yrs-datasearch-input-border-color-focus: var( --color-primary );
+ --yrs-datasearch-input-btn-color: var( --color-black );
+ --yrs-datasearch-input-btn-color-hover: var( --color-primary );
+ --yrs-datasearch-input-btn-bg: transparent;
+ --yrs-datasearch-input-btn-bg-hover: transparent;
+}
+
+.yrs-wrapper {
+ .yrs-heading {
+ @apply mb-8 lg:mb-12;
+ }
+
+ .yrs-row {
+ @apply gap-4 lg:grid-cols-12 lg:gap-8 xl:gap-10;
+
+ .yrs-column-1 {
+ @apply lg:col-span-4 xl:col-span-3;
+ }
+
+ .yrs-column-2 {
+ @apply lg:col-span-8 xl:col-span-9;
+ }
+ }
+
+ .yrs-datasearch-label,
+ .yrs-multidatalist-title {
+ @apply mb-2 block text-xl font-bold;
+ }
+
+ .yrs-datasearch-container {
+ @apply mb-8;
+ }
+
+ .yrs-datasearch {
+ > div {
+ @apply m-0;
+ }
+
+ .input-group {
+ @apply shadow-none;
+ }
+ }
+
+ .yrs-datasearch-input {
+ @apply rounded-theme h-13 border-x-0 border-t-0 border-b-2 border-(--yrs-datasearch-input-border-color) bg-white py-3 pr-10 text-base shadow-sm;
+
+ &:focus {
+ @apply border-(--yrs-datasearch-input-border-color-focus);
+ }
+
+ + div > div {
+ @apply min-w-11;
+
+ &:empty {
+ @apply hidden;
+ }
+ }
+ }
+
+ .yrs-datasearch-input-btn {
+ @apply h-full bg-(--yrs-datasearch-input-btn-bg) text-(--yrs-datasearch-input-btn-color);
+
+ &::before {
+ @apply fontawesome flex h-full w-12 items-center justify-center bg-transparent;
+ --fa-icon: '\f002';
+ }
+
+ @variant hocus {
+ &::before {
+ @apply bg-(--yrs-datasearch-input-btn-bg-hover) text-(--yrs-datasearch-input-btn-color-hover);
+ }
+ }
+
+ .yrs-datasearch-input-btn-text {
+ @apply sr-only;
+ }
+ }
+
+ .yrs-button-filters {
+ @apply is-button w-full lg:hidden;
+
+ &::before {
+ @apply fontawesome mr-2;
+ --fa-icon: '\f1de';
+ }
+ }
+
+ .yrs-filters-inner {
+ @apply mt-3;
+ }
+
+ .yrs-multidatalist-label {
+ @apply mt-0 mb-2 text-base!;
+
+ &::before {
+ @apply mr-3;
+ }
+
+ > span {
+ @apply flex items-center;
+ }
+
+ .yrs-multidatalist-count {
+ @apply text-sm;
+ }
+ }
+
+ .yrs-results {
+ @apply @container;
+ }
+
+ .yrs-results-info {
+ @apply text-primary mb-4 justify-end text-sm;
+ }
+
+ .yrs-results-list {
+ @apply grid gap-4 @xl:gap-6;
+ }
+
+ .yrs-card {
+ @apply rounded-theme relative bg-white shadow transition-all;
+
+ &:focus-within,
+ &:hover {
+ .yrs-card-body {
+ @apply border-primary;
+ }
+ }
+
+ .yrs-card-body {
+ @apply flex flex-col border-b-4 border-transparent p-(--card-padding) transition-all xl:p-8;
+ }
+
+ .yrs-card-title-link {
+ @apply a-linkable-area text-inherit! no-underline! focus:underline!;
+ }
+
+ .yrs-card-excerpt {
+ @apply mb-2 leading-snug sm:leading-relaxed;
+ }
+
+ .yrs-card-label {
+ @apply mt-3 w-fit rounded bg-gray-100 px-2 py-1 text-xs leading-normal! sm:text-sm;
+ }
+
+ .yrs-card-score {
+ @apply absolute right-6 bottom-6 hidden text-xs text-gray-700;
+
+ &:is( .logged-in .yrs-card-score ) {
+ @apply block;
+ }
+ }
+ }
+
+ .yrs-pagination-list {
+ @apply justify-end gap-x-2 gap-y-4;
+ }
+
+ .yrs-pagination-button {
+ @apply size-10 min-h-10 min-w-10 p-2 text-black no-underline transition-all;
+
+ &:not( .is-active ) {
+ @apply hover:bg-primary-100;
+ }
+
+ &.is-active {
+ @apply font-bold;
+ }
+ }
+
+ .yrs-pagination-button-prev {
+ @apply hover:bg-primary! border-primary text-primary mr-4 size-10 border text-[0px];
+
+ &::before {
+ @apply fontawesome text-base text-inherit;
+ --fa-icon: '\f053';
+ }
+
+ @variant hocus {
+ @apply bg-primary text-white;
+ }
+ }
+
+ .yrs-pagination-button-next {
+ @apply bg-primary ml-4 size-10 text-[0px] text-white;
+
+ &::before {
+ @apply fontawesome text-base;
+ --fa-icon: '\f054';
+ }
+
+ @variant hocus {
+ @apply bg-primary-700!;
+ filter: brightness( 1 );
+ }
+ }
+
+ .yrs-pagination-info {
+ @apply text-right text-sm;
+ }
+}
diff --git a/stubs/resources/views/partials/header/reactive-search-bar.blade.php b/stubs/resources/views/partials/header/reactive-search-bar.blade.php
new file mode 100644
index 0000000..53430e9
--- /dev/null
+++ b/stubs/resources/views/partials/header/reactive-search-bar.blade.php
@@ -0,0 +1,3 @@
+
diff --git a/stubs/resources/views/reactive-search-page.blade.php b/stubs/resources/views/reactive-search-page.blade.php
new file mode 100644
index 0000000..94479ea
--- /dev/null
+++ b/stubs/resources/views/reactive-search-page.blade.php
@@ -0,0 +1,3 @@
+
+
+