diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 47e0e14ef..3e7b55aec 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -6,6 +6,8 @@ 0, 'name', 'base_view', + 'layout.wrapper', + 'layout.outside_filters', 'header.view', 'header.layout.container', 'header.layout.sub_container', @@ -19,22 +21,17 @@ 'header.search_box.icon_close_wrapper', 'header.search_box.icon_close', 'header.search_box.icon_search', - 'table.view', - 'table.view_header', - 'table.view_row', - 'table.view_cols', - 'table.view_th_empty', - 'table.view_inline_filters', - 'table.view_checkbox_all', - 'table.view_checkbox_row', - 'table.view_radio_row', 'table.layout.container', 'table.layout.table', 'table.layout.thead', 'table.layout.tr', 'table.layout.th', + 'table.layout.th_actions', 'table.layout.tbody', 'table.layout.td', + 'table.layout.td_actions', + 'table.body.tr.responsive', + 'table.body.tr.responsive_toggle_icon', 'table.checkbox.th', 'table.checkbox.base', 'table.checkbox.label', @@ -43,6 +40,7 @@ 'table.radio.base', 'table.radio.label', 'table.radio.input', + 'cols.div', 'footer.view', 'footer.layout.container', 'footer.layout.select', @@ -68,11 +66,26 @@ 'filter.input_text.select', 'filter.input_text.input', 'filter.input', + 'filter.flyout.view', + 'filter.flyout.overlay', + 'filter.flyout.panel', + 'filter.flyout.panel_left', + 'filter.flyout.panel_right', + 'filter.flyout.header', + 'filter.flyout.title', + 'filter.flyout.close', + 'filter.flyout.body', + 'filter.flyout.footer', + 'filter.flyout.clear_all', 'editable.view', 'editable.clickable', 'editable.input', 'editable.error', - 'toggleable.view' + 'toggleable.color_on', + 'toggleable.color_off', + 'toggleable.color_on_dark', + 'toggleable.color_off_dark', + 'toggleable.knob_on' ); expectedArguments( @@ -80,6 +93,8 @@ 0, 'name', 'base_view', + 'layout.wrapper', + 'layout.outside_filters', 'header.view', 'header.layout.container', 'header.layout.sub_container', @@ -93,22 +108,17 @@ 'header.search_box.icon_close_wrapper', 'header.search_box.icon_close', 'header.search_box.icon_search', - 'table.view', - 'table.view_header', - 'table.view_row', - 'table.view_cols', - 'table.view_th_empty', - 'table.view_inline_filters', - 'table.view_checkbox_all', - 'table.view_checkbox_row', - 'table.view_radio_row', 'table.layout.container', 'table.layout.table', 'table.layout.thead', 'table.layout.tr', 'table.layout.th', + 'table.layout.th_actions', 'table.layout.tbody', 'table.layout.td', + 'table.layout.td_actions', + 'table.body.tr.responsive', + 'table.body.tr.responsive_toggle_icon', 'table.checkbox.th', 'table.checkbox.base', 'table.checkbox.label', @@ -117,6 +127,7 @@ 'table.radio.base', 'table.radio.label', 'table.radio.input', + 'cols.div', 'footer.view', 'footer.layout.container', 'footer.layout.select', @@ -142,11 +153,26 @@ 'filter.input_text.select', 'filter.input_text.input', 'filter.input', + 'filter.flyout.view', + 'filter.flyout.overlay', + 'filter.flyout.panel', + 'filter.flyout.panel_left', + 'filter.flyout.panel_right', + 'filter.flyout.header', + 'filter.flyout.title', + 'filter.flyout.close', + 'filter.flyout.body', + 'filter.flyout.footer', + 'filter.flyout.clear_all', 'editable.view', 'editable.clickable', 'editable.input', 'editable.error', - 'toggleable.view' + 'toggleable.color_on', + 'toggleable.color_off', + 'toggleable.color_on_dark', + 'toggleable.color_off_dark', + 'toggleable.knob_on' ); expectedArguments( @@ -155,6 +181,7 @@ 'editable', 'filter.boolean', 'filter.date_picker', + 'filter.flyout', 'filter.input_text', 'filter.multi_select', 'filter.number', @@ -162,9 +189,7 @@ 'footer', 'footer.pagination', 'header', - 'header.batch-exporting', 'header.enabled-filters', - 'header.export', 'header.filters', 'header.loading', 'header.message-soft-deletes', @@ -174,7 +199,6 @@ 'header.soft-deletes', 'header.toggle-columns', 'pagination', - 'table', 'table.checkbox-all', 'table.checkbox-row', 'table.cols', @@ -197,6 +221,7 @@ 'editable', 'filter.boolean', 'filter.date_picker', + 'filter.flyout', 'filter.input_text', 'filter.multi_select', 'filter.number', @@ -204,9 +229,7 @@ 'footer', 'footer.pagination', 'header', - 'header.batch-exporting', 'header.enabled-filters', - 'header.export', 'header.filters', 'header.loading', 'header.message-soft-deletes', @@ -216,7 +239,6 @@ 'header.soft-deletes', 'header.toggle-columns', 'pagination', - 'table', 'table.checkbox-all', 'table.checkbox-row', 'table.cols', diff --git a/resources/boost/skills/powergrid-theme/REFERENCE.md b/resources/boost/skills/powergrid-theme/REFERENCE.md index 2f2be1853..e3fadb4d9 100644 --- a/resources/boost/skills/powergrid-theme/REFERENCE.md +++ b/resources/boost/skills/powergrid-theme/REFERENCE.md @@ -28,6 +28,7 @@ Companion to `SKILL.md`. Everything here is verified against the v7 source in | `src/Themes/Components/Footer.php` | `view()`, `layout()`, `pagination(Closure\|array\|string)`. | | `src/Themes/Components/Pagination.php` | Holds the pagination `view`; usually set via the string form. | | `src/Themes/Components/Filter.php` | Fluent filter builder (used by DaisyUI/Flux `filter()`). | +| `src/Themes/Components/Flyout.php` | Classes for the filter drawer, via `Filter::flyout(Closure)`. `view`, `overlay`, `panel`, `panelLeft`, `panelRight`, `header`, `title`, `close`, `body`, `footer`, `clearAll`. | | `src/Themes/Components/Component.php` | Generic sub-component (used in `filter()` array form, `editable()`, `toggleable()`). | | `src/Themes/Components/HasProperties.php` | Shared trait. `toArray()` snake_cases keys and prefixes `view*` values with `baseView`. | | `src/Support/ThemeManager.php` | `ThemeManager::theme($key, $default)` and `::view($alias)` — read `app('powergrid.theme')`. | @@ -177,6 +178,19 @@ public function filter(): array 'input' => '...input classes...', ], 'input' => '...generic filter input classes...', + 'flyout' => [ + 'view' => 'livewire-powergrid::components.themes.tailwind.filter-flyout', + 'overlay' => '...backdrop classes...', + 'panel' => '...classes shared by both drawer sides...', + 'panel_left' => '...anchoring classes when position is left...', + 'panel_right' => '...anchoring classes when position is right...', + 'header' => '...drawer header row...', + 'title' => '...drawer title...', + 'close' => '...close button...', + 'body' => '...scrollable filter area...', + 'footer' => '...drawer footer...', + 'clear_all' => '...clear all filters button...', + ], ], ]; } @@ -187,6 +201,24 @@ public function filter(): array It is equivalent — pick whichever you find clearer, and copy the exact form from `src/Themes/DaisyUI.php` if you want the fluent version. +### `filter.flyout` — the drawer + +`filter.flyout.*` styles the drawer used when `config('livewire-powergrid.filter')` +is `flyout`. Its blade lives at +`resources/views/components/themes/tailwind/filter-flyout.blade.php` and is shared +by every theme through `parentTheme`, so a theme normally overrides the classes +only, not `view`. Use the fluent `->flyout(fn (Components\Flyout $flyout) => ...)` +setter (`Components\Flyout`) or the plain array form above. + +Two constraints the drawer markup relies on: + +- `panel` must position the drawer itself (`fixed inset-y-0`) and set a stacking + context above `overlay`. `panel_left` / `panel_right` add only the edge + anchoring, because the blade picks one of the two based on the configured + position and pairs it with a matching slide-in transform. +- `panel` should be full width on small screens and constrained above the `sm` + breakpoint (`w-full max-w-full sm:w-96 sm:max-w-[90vw]`). + Because a subclass with `parentTheme = Tailwind::class` inherits Tailwind's `filter()` wholesale, you only need to override `filter()` when your framework's inputs need different classes or views. diff --git a/resources/boost/skills/powergrid-theme/SKILL.md b/resources/boost/skills/powergrid-theme/SKILL.md index 14b6ea1ed..c783f0610 100644 --- a/resources/boost/skills/powergrid-theme/SKILL.md +++ b/resources/boost/skills/powergrid-theme/SKILL.md @@ -213,6 +213,7 @@ public function template(): ?Theme - **Pagination is a string.** `->pagination('pagination')` — `Footer::pagination()` accepts `Closure|array|string`; all three shipped themes use the string alias. - **CSS classes live in `->layout(Closure)`.** Direct string properties on `Header`/`Table`/`Footer` are for view aliases only. - **`filter()`, `editable()`, `toggleable()` are separate methods**, not part of `struct()`. They are merged into `resolveTokens()` automatically. +- **The filter drawer is styled, not rebuilt.** `filter.flyout.*` (set with `->flyout(fn (Components\Flyout $f) => ...)`) drives the drawer used when `config('livewire-powergrid.filter')` is `flyout`. Its blade is shared by every theme through `parentTheme`, so override the classes and leave `view` alone. `panel` must carry the positioning (`fixed inset-y-0`) and stay above `overlay`; `panel_left`/`panel_right` add only the edge anchoring. - **`toggleable()` fills color tokens, not a view.** It sets `colorOn`/`colorOff`/`colorOnDark`/`colorOffDark`/`knobOn`; the shipped Toggleable blade reads them via `theme('toggleable.color_on')` etc. Do not give it a `->view()`. - **Feature views are auto-resolved.** export, toggle-columns, soft-deletes, etc. resolve via `baseView + alias` (then the `parentTheme` chain, then `components.structure.*`). Do not declare them in `struct()`. - **View aliases**: a value without `::` is prefixed with `baseView + '.'`. Use a fully-qualified `livewire-powergrid::...` path only to point at another theme's view. diff --git a/resources/config/livewire-powergrid.php b/resources/config/livewire-powergrid.php index 5cc19311e..98275ef8c 100644 --- a/resources/config/livewire-powergrid.php +++ b/resources/config/livewire-powergrid.php @@ -76,15 +76,36 @@ | Filters |-------------------------------------------------------------------------- | - | PowerGrid supports inline and outside filters. + | PowerGrid supports inline, outside and flyout filters. | 'inline': Filters data inside the table. | 'outside': Filters data outside the table. + | 'flyout': Filters data in a drawer sliding in from the side. | 'null' | */ 'filter' => 'inline', + /* + |-------------------------------------------------------------------------- + | Filter Flyout + |-------------------------------------------------------------------------- + | + | Settings for the drawer used when 'filter' is set to 'flyout'. + | 'position': which edge the drawer slides in from ('left' or 'right'). + | 'close_on_escape': close the drawer when the Escape key is pressed. + | 'close_on_click_outside': close the drawer when its backdrop is clicked. + | + | Override these per table by calling config() in the table's boot() method. + | + */ + + 'filter_flyout' => [ + 'position' => 'right', + 'close_on_escape' => true, + 'close_on_click_outside' => true, + ], + /* |-------------------------------------------------------------------------- | Filters Attributes diff --git a/resources/lang/ar/datatable.php b/resources/lang/ar/datatable.php index 47860a618..a770ec75a 100644 --- a/resources/lang/ar/datatable.php +++ b/resources/lang/ar/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'تصفية', 'clear_all_filters' => 'مسح الكل', + 'close' => 'إغلاق', ], 'labels' => [ 'action' => 'العمليات', diff --git a/resources/lang/bn_BD/datatable.php b/resources/lang/bn_BD/datatable.php index fe9760650..1ab175203 100644 --- a/resources/lang/bn_BD/datatable.php +++ b/resources/lang/bn_BD/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'ফিল্টার', 'clear_all_filters' => 'সব ফিল্টার মুছুন', + 'close' => 'বন্ধ করুন', ], 'labels' => [ 'action' => 'কার্যসমূহ', diff --git a/resources/lang/ca/datatable.php b/resources/lang/ca/datatable.php index 35006236f..4ee75ca07 100644 --- a/resources/lang/ca/datatable.php +++ b/resources/lang/ca/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtre', 'clear_all_filters' => 'Clear all', + 'close' => 'Tanca', ], 'labels' => [ 'action' => 'Accions', diff --git a/resources/lang/cs/datatable.php b/resources/lang/cs/datatable.php index 97ca9f1cf..0d20c650f 100644 --- a/resources/lang/cs/datatable.php +++ b/resources/lang/cs/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtrovat', 'clear_all_filters' => 'Vymazat vše', + 'close' => 'Zavřít', ], 'labels' => [ 'action' => 'Akce', diff --git a/resources/lang/de/datatable.php b/resources/lang/de/datatable.php index 74c282002..b78e9d3ae 100644 --- a/resources/lang/de/datatable.php +++ b/resources/lang/de/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Aktionen', 'clear_all_filters' => 'Alle löschen', + 'close' => 'Schließen', ], 'labels' => [ 'action' => 'Aktionen', diff --git a/resources/lang/en/datatable.php b/resources/lang/en/datatable.php index 08320af24..20189306e 100644 --- a/resources/lang/en/datatable.php +++ b/resources/lang/en/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filter', 'clear_all_filters' => 'Clear all', + 'close' => 'Close', ], 'labels' => [ 'action' => 'Actions', diff --git a/resources/lang/es/datatable.php b/resources/lang/es/datatable.php index 61aa81547..c34fb1cdd 100644 --- a/resources/lang/es/datatable.php +++ b/resources/lang/es/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtrar', 'clear_all_filters' => 'Limpiar todo', + 'close' => 'Cerrar', ], 'labels' => [ 'action' => 'Acción', diff --git a/resources/lang/fa/datatable.php b/resources/lang/fa/datatable.php index cf7b17c5b..5bb9a937c 100644 --- a/resources/lang/fa/datatable.php +++ b/resources/lang/fa/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'فیلتر', 'clear_all_filters' => 'حذف همه', + 'close' => 'بستن', ], 'labels' => [ 'action' => 'اقدام ها', diff --git a/resources/lang/fr/datatable.php b/resources/lang/fr/datatable.php index 7ad2e6b71..5e19eb9c2 100644 --- a/resources/lang/fr/datatable.php +++ b/resources/lang/fr/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtrer', 'clear_all_filters' => 'Enlever tous les filtres', + 'close' => 'Fermer', ], 'labels' => [ 'action' => 'Actions', diff --git a/resources/lang/id/datatable.php b/resources/lang/id/datatable.php index 6770d3eed..e652b6540 100644 --- a/resources/lang/id/datatable.php +++ b/resources/lang/id/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filter', 'clear_all_filters' => 'Hapus semua', + 'close' => 'Tutup', ], 'labels' => [ 'action' => 'Aksi', diff --git a/resources/lang/it/datatable.php b/resources/lang/it/datatable.php index af1ee3de4..f2f302efc 100644 --- a/resources/lang/it/datatable.php +++ b/resources/lang/it/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtra', 'clear_all_filters' => 'Svuota filtri', + 'close' => 'Chiudi', ], 'labels' => [ 'action' => 'Azioni', diff --git a/resources/lang/ms_MY/datatable.php b/resources/lang/ms_MY/datatable.php index b3750967b..56248792f 100644 --- a/resources/lang/ms_MY/datatable.php +++ b/resources/lang/ms_MY/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Carian', 'clear_all_filters' => 'Clear all', + 'close' => 'Tutup', ], 'labels' => [ 'action' => 'Action', diff --git a/resources/lang/nl/datatable.php b/resources/lang/nl/datatable.php index 94a74c024..bd6360e76 100644 --- a/resources/lang/nl/datatable.php +++ b/resources/lang/nl/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filter', 'clear_all_filters' => 'Wis alle filters', + 'close' => 'Sluiten', ], 'labels' => [ 'action' => 'Acties', diff --git a/resources/lang/pl/datatable.php b/resources/lang/pl/datatable.php index 4aa46812c..dbde0350f 100644 --- a/resources/lang/pl/datatable.php +++ b/resources/lang/pl/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtry', 'clear_all_filters' => 'Wyczyść wszystkie filtry', + 'close' => 'Zamknij', ], 'labels' => [ 'action' => 'Akcje', diff --git a/resources/lang/pt/datatable.php b/resources/lang/pt/datatable.php index 87b4bf52c..e83f252cd 100644 --- a/resources/lang/pt/datatable.php +++ b/resources/lang/pt/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtrar', 'clear_all_filters' => 'Limpar Todos', + 'close' => 'Fechar', ], 'labels' => [ 'action' => 'Ações', diff --git a/resources/lang/pt_BR/datatable.php b/resources/lang/pt_BR/datatable.php index 3d25eaa8f..0779b572d 100644 --- a/resources/lang/pt_BR/datatable.php +++ b/resources/lang/pt_BR/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtrar', 'clear_all_filters' => 'Limpar Todos', + 'close' => 'Fechar', ], 'labels' => [ 'action' => 'Ações', diff --git a/resources/lang/ru/datatable.php b/resources/lang/ru/datatable.php index 59bdcd1fd..e3f520aaf 100644 --- a/resources/lang/ru/datatable.php +++ b/resources/lang/ru/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Фильтр', 'clear_all_filters' => 'Очистить все', + 'close' => 'Закрыть', ], 'labels' => [ 'action' => 'Действия', diff --git a/resources/lang/tr/datatable.php b/resources/lang/tr/datatable.php index e5651536e..1da0a7231 100644 --- a/resources/lang/tr/datatable.php +++ b/resources/lang/tr/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Filtre', 'clear_all_filters' => 'Tümünü Temizle', + 'close' => 'Kapat', ], 'labels' => [ 'action' => 'İşlemler', diff --git a/resources/lang/uk/datatable.php b/resources/lang/uk/datatable.php index ea6523b19..4d4818186 100644 --- a/resources/lang/uk/datatable.php +++ b/resources/lang/uk/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'Фильтр', 'clear_all_filters' => 'Очистити все', + 'close' => 'Закрити', ], 'labels' => [ 'action' => 'Дія', diff --git a/resources/lang/yr/datatable.php b/resources/lang/yr/datatable.php index 983f736dd..2c3645554 100644 --- a/resources/lang/yr/datatable.php +++ b/resources/lang/yr/datatable.php @@ -4,6 +4,7 @@ 'buttons' => [ 'filter' => 'àlẹmọ', 'clear_all_filters' => 'Clear all', + 'close' => 'Tì', ], 'labels' => [ 'action' => 'Awọn Igbese', diff --git a/resources/views/components/structure/table.blade.php b/resources/views/components/structure/table.blade.php index fb278e348..7cef17f7d 100644 --- a/resources/views/components/structure/table.blade.php +++ b/resources/views/components/structure/table.blade.php @@ -24,13 +24,13 @@ class="pg-table-wrapper {{ theme('layout.wrapper') }}" '__partial' => $this, ]) - @if (config('livewire-powergrid.filter') === 'outside' && ! $this->filterBuilderHidesDefaultFilters()) + @if ($this->usesFilterPanel() && ! $this->filterBuilderHidesDefaultFilters()) @php $filtersFromColumns = collect($columns) ->filter(fn($column) => filled(data_get($column, 'filters'))); @endphp - @include(theme_view('filter'), [ + @include(theme_view($this->filterPanelView()), [ '__partial' => $this, 'tableName' => $tableName, 'filtersFromColumns' => $filtersFromColumns, diff --git a/resources/views/components/themes/daisyui/header.blade.php b/resources/views/components/themes/daisyui/header.blade.php index 08e5037cf..2caa7dc5f 100644 --- a/resources/views/components/themes/daisyui/header.blade.php +++ b/resources/views/components/themes/daisyui/header.blade.php @@ -10,7 +10,7 @@ @includeIf(theme_view('header.toggle-columns')) @includeIf(theme_view('header.soft-deletes')) - @if (config('livewire-powergrid.filter') == 'outside' && count($this->filters()) > 0 && ! $this->filterBuilderHidesDefaultFilters()) + @if ($this->usesFilterPanel() && count($this->filters()) > 0 && ! $this->filterBuilderHidesDefaultFilters()) @includeIf(theme_view('header.filters')) @endif diff --git a/resources/views/components/themes/flux/header.blade.php b/resources/views/components/themes/flux/header.blade.php index efb15b2e8..7e9ff9638 100644 --- a/resources/views/components/themes/flux/header.blade.php +++ b/resources/views/components/themes/flux/header.blade.php @@ -8,7 +8,7 @@ {!! $this->renderPluginZone('header') !!} @includeIf(theme_view('header.toggle-columns')) @includeIf(theme_view('header.soft-deletes')) - @if (config('livewire-powergrid.filter') == 'outside' && count($this->filters()) > 0 && ! $this->filterBuilderHidesDefaultFilters()) + @if ($this->usesFilterPanel() && count($this->filters()) > 0 && ! $this->filterBuilderHidesDefaultFilters()) @includeIf(theme_view('header.filters')) @endif diff --git a/resources/views/components/themes/tailwind/filter-flyout.blade.php b/resources/views/components/themes/tailwind/filter-flyout.blade.php new file mode 100644 index 000000000..b2fe3de21 --- /dev/null +++ b/resources/views/components/themes/tailwind/filter-flyout.blade.php @@ -0,0 +1,106 @@ +@props([ + 'theme' => null, + 'tableName' => null, + 'filtersFromColumns' => null, + '__partial' => null, +]) + +@php + $__partial = $__partial ?? (isset($this) ? $this : null); + $tableName = $tableName ?? $__partial->tableName; + + $flyout = $__partial->filterFlyoutOptions(); + $isLeft = $flyout['position'] === 'left'; + + // Alpine needs the off-screen class up front, so the side decides both the + // anchoring classes and the direction the panel slides in from. + $panelSide = $isLeft ? theme('filter.flyout.panel_left') : theme('filter.flyout.panel_right'); + $panelOffscreen = $isLeft ? '-translate-x-full' : 'translate-x-full'; +@endphp + +