feat: add resources and view components
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
@php
|
||||
$pageComponent = static::isSimple() ? 'filament-panels::page.simple' : 'filament-panels::page';
|
||||
@endphp
|
||||
|
||||
<x-dynamic-component :component="$pageComponent">
|
||||
{{ $this->content }}
|
||||
</x-dynamic-component>
|
||||
@@ -0,0 +1,18 @@
|
||||
@props([
|
||||
'tenant' => filament()->getTenant(),
|
||||
])
|
||||
|
||||
@php
|
||||
$src = filament()->getTenantAvatarUrl($tenant);
|
||||
$alt = __('filament-panels::layout.avatar.alt', ['name' => filament()->getTenantName($tenant)]);
|
||||
@endphp
|
||||
|
||||
<x-filament::avatar
|
||||
:circular="false"
|
||||
:src="$src"
|
||||
:alt="$alt"
|
||||
:attributes="
|
||||
\Filament\Support\prepare_inherited_attributes($attributes)
|
||||
->class(['fi-tenant-avatar'])
|
||||
"
|
||||
/>
|
||||
@@ -0,0 +1,17 @@
|
||||
@props([
|
||||
'user' => filament()->auth()->user(),
|
||||
])
|
||||
|
||||
@php
|
||||
$src = filament()->getUserAvatarUrl($user);
|
||||
$alt = __('filament-panels::layout.avatar.alt', ['name' => filament()->getUserName($user)]);
|
||||
@endphp
|
||||
|
||||
<x-filament::avatar
|
||||
:src="$src"
|
||||
:alt="$alt"
|
||||
:attributes="
|
||||
\Filament\Support\prepare_inherited_attributes($attributes)
|
||||
->class(['fi-user-avatar'])
|
||||
"
|
||||
/>
|
||||
@@ -0,0 +1,54 @@
|
||||
@props([
|
||||
'actions' => [],
|
||||
'actionsAlignment' => null,
|
||||
'breadcrumbs' => [],
|
||||
'heading' => null,
|
||||
'subheading' => null,
|
||||
])
|
||||
|
||||
<header
|
||||
{{
|
||||
$attributes->class([
|
||||
'fi-header',
|
||||
'fi-header-has-breadcrumbs' => $breadcrumbs,
|
||||
])
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
@if ($breadcrumbs)
|
||||
<x-filament::breadcrumbs :breadcrumbs="$breadcrumbs" />
|
||||
@endif
|
||||
|
||||
@if (filled($heading))
|
||||
<h1 class="fi-header-heading">
|
||||
{{ $heading }}
|
||||
</h1>
|
||||
@endif
|
||||
|
||||
@if (filled($subheading))
|
||||
<p class="fi-header-subheading">
|
||||
{{ $subheading }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@php
|
||||
$beforeActions = \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_HEADER_ACTIONS_BEFORE, scopes: $this->getRenderHookScopes());
|
||||
$afterActions = \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_HEADER_ACTIONS_AFTER, scopes: $this->getRenderHookScopes());
|
||||
@endphp
|
||||
|
||||
@if (filled($beforeActions) || $actions || filled($afterActions))
|
||||
<div class="fi-header-actions-ctn">
|
||||
{{ $beforeActions }}
|
||||
|
||||
@if ($actions)
|
||||
<x-filament::actions
|
||||
:actions="$actions"
|
||||
:alignment="$actionsAlignment"
|
||||
/>
|
||||
@endif
|
||||
|
||||
{{ $afterActions }}
|
||||
</div>
|
||||
@endif
|
||||
</header>
|
||||
@@ -0,0 +1,23 @@
|
||||
@props([
|
||||
'heading' => null,
|
||||
'logo' => true,
|
||||
'subheading' => null,
|
||||
])
|
||||
|
||||
<header class="fi-simple-header">
|
||||
@if ($logo)
|
||||
<x-filament-panels::logo />
|
||||
@endif
|
||||
|
||||
@if (filled($heading))
|
||||
<h1 class="fi-simple-header-heading">
|
||||
{{ $heading }}
|
||||
</h1>
|
||||
@endif
|
||||
|
||||
@if (filled($subheading))
|
||||
<p class="fi-simple-header-subheading">
|
||||
{{ $subheading }}
|
||||
</p>
|
||||
@endif
|
||||
</header>
|
||||
@@ -0,0 +1,167 @@
|
||||
@props([
|
||||
'livewire' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$renderHookScopes = $livewire?->getRenderHookScopes();
|
||||
@endphp
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
lang="{{ str_replace('_', '-', app()->getLocale()) }}"
|
||||
dir="{{ __('filament-panels::layout.direction') ?? 'ltr' }}"
|
||||
@class([
|
||||
'fi',
|
||||
'dark' => filament()->hasDarkMode() && filament()->hasDarkModeForced(),
|
||||
])
|
||||
>
|
||||
<head>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::HEAD_START, scopes: $renderHookScopes) }}
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
@if ($favicon = filament()->getFavicon())
|
||||
<link rel="icon" href="{{ $favicon }}" />
|
||||
@endif
|
||||
|
||||
@php
|
||||
$title = trim(strip_tags($livewire?->getTitle() ?? ''));
|
||||
$brandName = trim(strip_tags(filament()->getBrandName()));
|
||||
@endphp
|
||||
|
||||
<title>
|
||||
{{ filled($title) ? $title : null }}
|
||||
{{ filled($brandName) && filled($title) ? ' - ' : null }}
|
||||
{{ filled($brandName) ? $brandName : null }}
|
||||
</title>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::STYLES_BEFORE, scopes: $renderHookScopes) }}
|
||||
|
||||
<style>
|
||||
[x-cloak=''],
|
||||
[x-cloak='x-cloak'],
|
||||
[x-cloak='1'] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
[x-cloak='inline-flex'] {
|
||||
display: inline-flex !important;
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
[x-cloak='-lg'] {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
[x-cloak='lg'] {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@filamentStyles
|
||||
|
||||
{{ filament()->getTheme()->getHtml() }}
|
||||
{{ filament()->getFontPreloadHtml() }}
|
||||
{{ filament()->getMonoFontPreloadHtml() }}
|
||||
{{ filament()->getSerifFontPreloadHtml() }}
|
||||
{{ filament()->getFontHtml() }}
|
||||
{{ filament()->getMonoFontHtml() }}
|
||||
{{ filament()->getSerifFontHtml() }}
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--font-family: '{!! filament()->getFontFamily() !!}';
|
||||
--mono-font-family: '{!! filament()->getMonoFontFamily() !!}';
|
||||
--serif-font-family: '{!! filament()->getSerifFontFamily() !!}';
|
||||
--sidebar-width: {{ filament()->getSidebarWidth() }};
|
||||
--collapsed-sidebar-width: {{ filament()->getCollapsedSidebarWidth() }};
|
||||
--default-theme-mode: {{ filament()->getDefaultThemeMode()->value }};
|
||||
}
|
||||
|
||||
html.fi {
|
||||
--livewire-progress-bar-color: var(--primary-500);
|
||||
}
|
||||
</style>
|
||||
|
||||
@stack('styles')
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::STYLES_AFTER, scopes: $renderHookScopes) }}
|
||||
|
||||
@if (! filament()->hasDarkMode())
|
||||
<script>
|
||||
localStorage.setItem('theme', 'light')
|
||||
</script>
|
||||
@elseif (filament()->hasDarkModeForced())
|
||||
<script>
|
||||
localStorage.setItem('theme', 'dark')
|
||||
</script>
|
||||
@else
|
||||
<script>
|
||||
const loadDarkMode = () => {
|
||||
window.theme = localStorage.getItem('theme') ?? @js(filament()->getDefaultThemeMode()->value)
|
||||
|
||||
if (
|
||||
window.theme === 'dark' ||
|
||||
(window.theme === 'system' &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)')
|
||||
.matches)
|
||||
) {
|
||||
document.documentElement.classList.add('dark')
|
||||
}
|
||||
}
|
||||
|
||||
loadDarkMode()
|
||||
|
||||
document.addEventListener('livewire:navigated', loadDarkMode)
|
||||
</script>
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::HEAD_END, scopes: $renderHookScopes) }}
|
||||
</head>
|
||||
|
||||
<body
|
||||
{{
|
||||
$attributes
|
||||
->merge($livewire?->getExtraBodyAttributes() ?? [], escape: false)
|
||||
->class([
|
||||
'fi-body',
|
||||
'fi-panel-' . filament()->getId(),
|
||||
])
|
||||
}}
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::BODY_START, scopes: $renderHookScopes) }}
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
@livewire(Filament\Livewire\Notifications::class)
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SCRIPTS_BEFORE, scopes: $renderHookScopes) }}
|
||||
|
||||
@filamentScripts(withCore: true)
|
||||
|
||||
@if (filament()->hasBroadcasting() && config('filament.broadcasting.echo'))
|
||||
<script data-navigate-once>
|
||||
window.Echo = new window.EchoFactory(@js(config('filament.broadcasting.echo')))
|
||||
|
||||
window.dispatchEvent(new CustomEvent('EchoLoaded'))
|
||||
</script>
|
||||
@endif
|
||||
|
||||
@if (filament()->hasDarkMode() && (! filament()->hasDarkModeForced()))
|
||||
<script>
|
||||
loadDarkMode()
|
||||
</script>
|
||||
@endif
|
||||
|
||||
@stack('scripts')
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SCRIPTS_AFTER, scopes: $renderHookScopes) }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::BODY_END, scopes: $renderHookScopes) }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,119 @@
|
||||
@php
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
$livewire ??= null;
|
||||
|
||||
$hasTopbar = filament()->hasTopbar();
|
||||
$isSidebarCollapsibleOnDesktop = filament()->isSidebarCollapsibleOnDesktop();
|
||||
$isSidebarFullyCollapsibleOnDesktop = filament()->isSidebarFullyCollapsibleOnDesktop();
|
||||
$hasTopNavigation = filament()->hasTopNavigation();
|
||||
$hasNavigation = filament()->hasNavigation();
|
||||
$renderHookScopes = $livewire?->getRenderHookScopes();
|
||||
$maxContentWidth ??= (filament()->getMaxContentWidth() ?? Width::SevenExtraLarge);
|
||||
|
||||
if (is_string($maxContentWidth)) {
|
||||
$maxContentWidth = Width::tryFrom($maxContentWidth) ?? $maxContentWidth;
|
||||
}
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::layout.base
|
||||
:livewire="$livewire"
|
||||
@class([
|
||||
'fi-body-has-navigation' => $hasNavigation,
|
||||
'fi-body-has-sidebar-collapsible-on-desktop' => $isSidebarCollapsibleOnDesktop,
|
||||
'fi-body-has-sidebar-fully-collapsible-on-desktop' => $isSidebarFullyCollapsibleOnDesktop,
|
||||
'fi-body-has-topbar' => $hasTopbar,
|
||||
'fi-body-has-top-navigation' => $hasTopNavigation,
|
||||
])
|
||||
>
|
||||
@if ($hasTopbar)
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_BEFORE, scopes: $renderHookScopes) }}
|
||||
|
||||
@livewire(filament()->getTopbarLivewireComponent())
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_AFTER, scopes: $renderHookScopes) }}
|
||||
@elseif ($hasNavigation)
|
||||
<div
|
||||
@if ($isSidebarFullyCollapsibleOnDesktop)
|
||||
x-data="{}"
|
||||
x-bind:class="{ 'lg:fi-hidden': $store.sidebar.isOpen }"
|
||||
@endif
|
||||
@class([
|
||||
'fi-layout-sidebar-toggle-btn-ctn',
|
||||
'lg:fi-hidden' => ! $isSidebarFullyCollapsibleOnDesktop,
|
||||
])
|
||||
>
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::OutlinedBars3"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.expand.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.open()"
|
||||
class="fi-layout-sidebar-toggle-btn"
|
||||
/>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="fi-layout">
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::LAYOUT_START, scopes: $renderHookScopes) }}
|
||||
|
||||
@if ($hasNavigation)
|
||||
<div
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.close()"
|
||||
x-show="$store.sidebar.isOpen"
|
||||
x-transition.opacity.300ms
|
||||
class="fi-sidebar-close-overlay"
|
||||
></div>
|
||||
|
||||
@livewire(filament()->getSidebarLivewireComponent())
|
||||
@endif
|
||||
|
||||
<div
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
x-data="{}"
|
||||
x-bind:class="{
|
||||
'fi-main-ctn-sidebar-open': $store.sidebar.isOpen,
|
||||
}"
|
||||
x-bind:style="'display: flex; opacity:1;'"
|
||||
{{-- Mimics `x-cloak`, as using `x-cloak` causes visual issues with chart widgets --}}
|
||||
@elseif ($isSidebarFullyCollapsibleOnDesktop)
|
||||
x-data="{}"
|
||||
x-bind:class="{
|
||||
'fi-main-ctn-sidebar-open': $store.sidebar.isOpen,
|
||||
}"
|
||||
x-bind:style="'display: flex; opacity:1;'"
|
||||
{{-- Mimics `x-cloak`, as using `x-cloak` causes visual issues with chart widgets --}}
|
||||
@elseif (! ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop || $hasTopNavigation || (! $hasNavigation)))
|
||||
x-data="{}"
|
||||
x-bind:style="'display: flex; opacity:1;'" {{-- Mimics `x-cloak`, as using `x-cloak` causes visual issues with chart widgets --}}
|
||||
@endif
|
||||
class="fi-main-ctn"
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_BEFORE, scopes: $renderHookScopes) }}
|
||||
|
||||
<main
|
||||
@class([
|
||||
'fi-main',
|
||||
($maxContentWidth instanceof Width) ? "fi-width-{$maxContentWidth->value}" : $maxContentWidth,
|
||||
])
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_START, scopes: $renderHookScopes) }}
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_END, scopes: $renderHookScopes) }}
|
||||
</main>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::CONTENT_AFTER, scopes: $renderHookScopes) }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::FOOTER, scopes: $renderHookScopes) }}
|
||||
</div>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::LAYOUT_END, scopes: $renderHookScopes) }}
|
||||
</div>
|
||||
</x-filament-panels::layout.base>
|
||||
@@ -0,0 +1,54 @@
|
||||
@php
|
||||
use Filament\Support\Enums\Width;
|
||||
|
||||
$livewire ??= null;
|
||||
|
||||
$renderHookScopes = $livewire?->getRenderHookScopes();
|
||||
$maxContentWidth ??= (filament()->getSimplePageMaxContentWidth() ?? Width::Large);
|
||||
|
||||
if (is_string($maxContentWidth)) {
|
||||
$maxContentWidth = Width::tryFrom($maxContentWidth) ?? $maxContentWidth;
|
||||
}
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::layout.base :livewire="$livewire">
|
||||
@props([
|
||||
'after' => null,
|
||||
'heading' => null,
|
||||
'subheading' => null,
|
||||
])
|
||||
|
||||
<div class="fi-simple-layout">
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIMPLE_LAYOUT_START, scopes: $renderHookScopes) }}
|
||||
|
||||
@if (($hasTopbar ?? true) && filament()->auth()->check())
|
||||
<div class="fi-simple-layout-header">
|
||||
@if (filament()->hasDatabaseNotifications())
|
||||
@livewire(filament()->getDatabaseNotificationsLivewireComponent(), [
|
||||
'lazy' => filament()->hasLazyLoadedDatabaseNotifications(),
|
||||
'position' => \Filament\Enums\DatabaseNotificationsPosition::Topbar,
|
||||
])
|
||||
@endif
|
||||
|
||||
@if (filament()->hasUserMenu())
|
||||
@livewire(Filament\Livewire\SimpleUserMenu::class)
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="fi-simple-main-ctn">
|
||||
<main
|
||||
@class([
|
||||
'fi-simple-main',
|
||||
($maxContentWidth instanceof Width) ? "fi-width-{$maxContentWidth->value}" : $maxContentWidth,
|
||||
])
|
||||
>
|
||||
{{ $slot }}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::FOOTER, scopes: $renderHookScopes) }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIMPLE_LAYOUT_END, scopes: $renderHookScopes) }}
|
||||
</div>
|
||||
</x-filament-panels::layout.base>
|
||||
@@ -0,0 +1,55 @@
|
||||
@php
|
||||
$brandName = filament()->getBrandName();
|
||||
$brandLogo = filament()->getBrandLogo();
|
||||
$brandLogoHeight = filament()->getBrandLogoHeight() ?? '1.5rem';
|
||||
$darkModeBrandLogo = filament()->getDarkModeBrandLogo();
|
||||
$hasDarkModeBrandLogo = filled($darkModeBrandLogo);
|
||||
|
||||
$getLogoClasses = fn (bool $isDarkMode): string => \Illuminate\Support\Arr::toCssClasses([
|
||||
'fi-logo',
|
||||
'fi-logo-light' => $hasDarkModeBrandLogo && (! $isDarkMode),
|
||||
'fi-logo-dark' => $isDarkMode,
|
||||
]);
|
||||
|
||||
$logoStyles = "height: {$brandLogoHeight}";
|
||||
@endphp
|
||||
|
||||
@capture($content, $logo, $isDarkMode = false)
|
||||
@if ($logo instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<div
|
||||
{{
|
||||
$attributes
|
||||
->class([$getLogoClasses($isDarkMode)])
|
||||
->style([$logoStyles])
|
||||
}}
|
||||
>
|
||||
{{ $logo }}
|
||||
</div>
|
||||
@elseif (filled($logo))
|
||||
<img
|
||||
alt="{{ __('filament-panels::layout.logo.alt', ['name' => $brandName]) }}"
|
||||
src="{{ $logo }}"
|
||||
{{
|
||||
$attributes
|
||||
->class([$getLogoClasses($isDarkMode)])
|
||||
->style([$logoStyles])
|
||||
}}
|
||||
/>
|
||||
@else
|
||||
<div
|
||||
{{
|
||||
$attributes->class([
|
||||
$getLogoClasses($isDarkMode),
|
||||
])
|
||||
}}
|
||||
>
|
||||
{{ $brandName }}
|
||||
</div>
|
||||
@endif
|
||||
@endcapture
|
||||
|
||||
{{ $content($brandLogo) }}
|
||||
|
||||
@if ($hasDarkModeBrandLogo)
|
||||
{{ $content($darkModeBrandLogo, isDarkMode: true) }}
|
||||
@endif
|
||||
@@ -0,0 +1,179 @@
|
||||
@props([
|
||||
'fullHeight' => false,
|
||||
])
|
||||
|
||||
@php
|
||||
use Filament\Pages\Enums\SubNavigationPosition;
|
||||
|
||||
$subNavigation = $this->getCachedSubNavigation();
|
||||
$subNavigationPosition = $this->getSubNavigationPosition();
|
||||
$widgetData = $this->getWidgetData();
|
||||
@endphp
|
||||
|
||||
<div
|
||||
{{
|
||||
$attributes->class([
|
||||
'fi-page',
|
||||
'fi-height-full' => $fullHeight,
|
||||
'fi-page-has-sub-navigation' => $subNavigation,
|
||||
"fi-page-has-sub-navigation-{$subNavigationPosition->value}" => $subNavigation,
|
||||
...$this->getPageClasses(),
|
||||
])
|
||||
}}
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_START, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
<div class="fi-page-header-main-ctn">
|
||||
@if ($subNavigation)
|
||||
<div
|
||||
class="fi-page-main-sub-navigation-mobile-menu-render-hook-ctn"
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_MOBILE_MENU_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
</div>
|
||||
|
||||
<x-filament-panels::page.sub-navigation.mobile-menu
|
||||
:navigation="$subNavigation"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="fi-page-main-sub-navigation-mobile-menu-render-hook-ctn"
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_MOBILE_MENU_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($header = $this->getHeader())
|
||||
{{ $header }}
|
||||
@else
|
||||
@php
|
||||
$heading = $this->getHeading();
|
||||
$headerActions = $this->getCachedHeaderActions();
|
||||
$headerActionsAlignment = $this->getHeaderActionsAlignment();
|
||||
$breadcrumbs = filament()->hasBreadcrumbs() ? $this->getBreadcrumbs() : [];
|
||||
$subheading = $this->getSubheading();
|
||||
@endphp
|
||||
|
||||
@if (filled($headerActions) || $breadcrumbs || filled($heading) || filled($subheading))
|
||||
<x-filament-panels::header
|
||||
:actions="$headerActions"
|
||||
:actions-alignment="$headerActionsAlignment"
|
||||
:breadcrumbs="$breadcrumbs"
|
||||
:heading="$heading"
|
||||
:subheading="$subheading"
|
||||
>
|
||||
@if ($heading instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<x-slot name="heading">
|
||||
{{ $heading }}
|
||||
</x-slot>
|
||||
@endif
|
||||
|
||||
@if ($subheading instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<x-slot name="subheading">
|
||||
{{ $subheading }}
|
||||
</x-slot>
|
||||
@endif
|
||||
</x-filament-panels::header>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
<div class="fi-page-main">
|
||||
@if ($subNavigation)
|
||||
@if ($subNavigationPosition === SubNavigationPosition::Start)
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_START_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
<x-filament-panels::page.sub-navigation.sidebar
|
||||
:navigation="$subNavigation"
|
||||
/>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_START_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
@endif
|
||||
|
||||
@if ($subNavigationPosition === SubNavigationPosition::Top)
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_TOP_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
<x-filament-panels::page.sub-navigation.tabs
|
||||
:navigation="$subNavigation"
|
||||
/>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_TOP_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
@endif
|
||||
@endif
|
||||
|
||||
<div class="fi-page-content">
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_HEADER_WIDGETS_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
{{ $this->headerWidgets }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_HEADER_WIDGETS_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_FOOTER_WIDGETS_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
{{ $this->footerWidgets }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_FOOTER_WIDGETS_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
</div>
|
||||
|
||||
@if ($subNavigation && $subNavigationPosition === SubNavigationPosition::End)
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_END_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
<x-filament-panels::page.sub-navigation.sidebar
|
||||
:navigation="$subNavigation"
|
||||
/>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_END_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($footer = $this->getFooter())
|
||||
{{ $footer }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if (! ($this instanceof \Filament\Tables\Contracts\HasTable))
|
||||
<x-filament-actions::modals />
|
||||
@elseif ($this->isTableLoaded() && filled($this->defaultTableAction))
|
||||
<div
|
||||
wire:init="mountAction(@js($this->defaultTableAction) , @if (filled($this->defaultTableActionArguments)) @js($this->defaultTableActionArguments) @else {} @endif , @js(['table' => true, 'recordKey' => $this->defaultTableActionRecord]))"
|
||||
></div>
|
||||
@endif
|
||||
|
||||
@if (filled($this->defaultAction))
|
||||
<div
|
||||
wire:init="mountAction(@js($this->defaultAction) @if (filled($this->defaultActionArguments) || filled($this->defaultActionContext)) , @if (filled($this->defaultActionArguments)) @js($this->defaultActionArguments) @else {} @endif @endif @if (filled($this->defaultActionContext)) , @js($this->defaultActionContext) @endif)"
|
||||
></div>
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_END, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
@if (method_exists($this, 'hasUnsavedDataChangesAlert') && $this->hasUnsavedDataChangesAlert())
|
||||
@if (\Filament\Support\Facades\FilamentView::hasSpaMode())
|
||||
@script
|
||||
<script>
|
||||
setUpSpaModeUnsavedDataChangesAlert({
|
||||
body: @js(__('filament-panels::unsaved-changes-alert.body')),
|
||||
resolveLivewireComponentUsing: () => @this,
|
||||
$wire,
|
||||
})
|
||||
</script>
|
||||
@endscript
|
||||
@else
|
||||
@script
|
||||
<script>
|
||||
setUpUnsavedDataChangesAlert({ $wire })
|
||||
</script>
|
||||
@endscript
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@if (! app()->hasDebugModeEnabled())
|
||||
@script
|
||||
<script>
|
||||
window.filamentErrorNotifications = @js($this->hasErrorNotifications() ? $this->getErrorNotifications() : null)
|
||||
</script>
|
||||
@endscript
|
||||
@endif
|
||||
|
||||
<x-filament-panels::unsaved-action-changes-alert />
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
@props([
|
||||
'heading' => null,
|
||||
'subheading' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$heading ??= $this->getHeading();
|
||||
$subheading ??= $this->getSubHeading();
|
||||
$hasLogo = $this->hasLogo();
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class(['fi-simple-page']) }}>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIMPLE_PAGE_START, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
<div class="fi-simple-page-content">
|
||||
@if (filled($heading) || $hasLogo || filled($subheading))
|
||||
<x-filament-panels::header.simple
|
||||
:heading="$heading"
|
||||
:logo="$hasLogo"
|
||||
:subheading="$subheading"
|
||||
/>
|
||||
@endif
|
||||
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
@if (! $this instanceof \Filament\Tables\Contracts\HasTable)
|
||||
<x-filament-actions::modals />
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIMPLE_PAGE_END, scopes: $this->getRenderHookScopes()) }}
|
||||
</div>
|
||||
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
@props([
|
||||
'navigation',
|
||||
])
|
||||
|
||||
<x-filament::dropdown
|
||||
placement="bottom-start"
|
||||
width="xs"
|
||||
:attributes="
|
||||
\Filament\Support\prepare_inherited_attributes($attributes)
|
||||
->class(['fi-page-sub-navigation-dropdown'])
|
||||
"
|
||||
>
|
||||
<x-slot name="trigger">
|
||||
@php
|
||||
$activeItem = null;
|
||||
|
||||
foreach ($navigation as $navigationGroup) {
|
||||
foreach ($navigationGroup->getItems() as $navigationItem) {
|
||||
foreach ([$navigationItem, ...$navigationItem->getChildItems()] as $navigationItemChild) {
|
||||
if ($navigationItemChild->isActive()) {
|
||||
$activeItem = $navigationItemChild;
|
||||
|
||||
break 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
<x-filament::button
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::ChevronDown"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::SUB_NAVIGATION_MOBILE_MENU_BUTTON"
|
||||
icon-position="after"
|
||||
>
|
||||
{{ $activeItem?->getLabel() }}
|
||||
</x-filament::button>
|
||||
</x-slot>
|
||||
|
||||
@foreach ($navigation as $navigationGroup)
|
||||
@if (filled($navigationGroupLabel = $navigationGroup->getLabel()))
|
||||
<x-filament::dropdown.header>
|
||||
{{ $navigationGroupLabel }}
|
||||
</x-filament::dropdown.header>
|
||||
@endif
|
||||
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($navigationGroup->getItems() as $navigationItem)
|
||||
@foreach ([$navigationItem, ...$navigationItem->getChildItems()] as $navigationItemChild)
|
||||
@php
|
||||
$navigationItemBadge = $navigationItem->getBadge();
|
||||
$navigationItemBadgeColor = $navigationItem->getBadgeColor();
|
||||
$navigationItemIcon = $navigationItem->isActive() ? ($navigationItem->getActiveIcon() ?? $navigationItem->getIcon()) : $navigationItem->getIcon();
|
||||
$navigationItemUrl = $navigationItem->getUrl();
|
||||
$shouldNavigationItemOpenUrlInNewTab = $navigationItem->shouldOpenUrlInNewTab();
|
||||
$navigationItemExtraAttributes = $navigationItemChild->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament::dropdown.list.item
|
||||
:badge="$navigationItemBadge"
|
||||
:badge-color="$navigationItemBadgeColor"
|
||||
:href="$navigationItemUrl"
|
||||
:icon="$navigationItemIcon"
|
||||
tag="a"
|
||||
:target="$shouldNavigationItemOpenUrlInNewTab ? '_blank' : null"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($navigationItemExtraAttributes)"
|
||||
>
|
||||
{{ $navigationItemChild->getLabel() }}
|
||||
</x-filament::dropdown.list.item>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endforeach
|
||||
</x-filament::dropdown>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
@props([
|
||||
'navigation',
|
||||
])
|
||||
|
||||
<div
|
||||
{{ $attributes->class(['fi-page-sub-navigation-sidebar-ctn']) }}
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_SIDEBAR_BEFORE, scopes: $this->getRenderHookScopes()) }}
|
||||
|
||||
<ul class="fi-page-sub-navigation-sidebar">
|
||||
@foreach ($navigation as $navigationGroup)
|
||||
@php
|
||||
$isNavigationGroupActive = $navigationGroup->isActive();
|
||||
$isNavigationGroupCollapsible = $navigationGroup->isCollapsible();
|
||||
$navigationGroupIcon = $navigationGroup->getIcon();
|
||||
$navigationGroupItems = $navigationGroup->getItems();
|
||||
$navigationGroupLabel = $navigationGroup->getLabel();
|
||||
$navigationGroupExtraSidebarAttributeBag = $navigationGroup->getExtraSidebarAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::sidebar.group
|
||||
:active="$isNavigationGroupActive"
|
||||
:collapsible="$isNavigationGroupCollapsible"
|
||||
:icon="$navigationGroupIcon"
|
||||
:items="$navigationGroupItems"
|
||||
:label="$navigationGroupLabel"
|
||||
:sidebar-collapsible="false"
|
||||
sub-navigation
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($navigationGroupExtraSidebarAttributeBag)"
|
||||
/>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_SUB_NAVIGATION_SIDEBAR_AFTER, scopes: $this->getRenderHookScopes()) }}
|
||||
</div>
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
@props([
|
||||
'navigation',
|
||||
])
|
||||
|
||||
<x-filament::tabs
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($attributes)->class(['fi-page-sub-navigation-tabs'])"
|
||||
>
|
||||
@foreach ($navigation as $navigationGroup)
|
||||
@php
|
||||
$navigationGroupLabel = $navigationGroup->getLabel();
|
||||
$isNavigationGroupActive = $navigationGroup->isActive();
|
||||
$navigationGroupIcon = $navigationGroup->getIcon();
|
||||
@endphp
|
||||
|
||||
@if ($navigationGroupLabel)
|
||||
<x-filament::dropdown placement="bottom-start">
|
||||
<x-slot name="trigger">
|
||||
<x-filament::tabs.item
|
||||
:active="$isNavigationGroupActive"
|
||||
:icon="$navigationGroupIcon"
|
||||
>
|
||||
{{ $navigationGroupLabel }}
|
||||
</x-filament::tabs.item>
|
||||
</x-slot>
|
||||
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($navigationGroup->getItems() as $navigationItem)
|
||||
@php
|
||||
$navigationItemBadge = $navigationItem->getBadge();
|
||||
$navigationItemBadgeColor = $navigationItem->getBadgeColor();
|
||||
$navigationItemBadgeTooltip = $navigationItem->getBadgeTooltip();
|
||||
$navigationItemIcon = $navigationItem->isActive() ? ($navigationItem->getActiveIcon() ?? $navigationItem->getIcon()) : $navigationItem->getIcon();
|
||||
$navigationItemUrl = $navigationItem->getUrl();
|
||||
$shouldNavigationItemOpenUrlInNewTab = $navigationItem->shouldOpenUrlInNewTab();
|
||||
$navigationItemExtraAttributes = $navigationItem->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament::dropdown.list.item
|
||||
:badge="$navigationItemBadge"
|
||||
:badge-color="$navigationItemBadgeColor"
|
||||
:badge-tooltip="$navigationItemBadgeTooltip"
|
||||
:href="$navigationItemUrl"
|
||||
:icon="$navigationItemIcon"
|
||||
tag="a"
|
||||
:target="$shouldNavigationItemOpenUrlInNewTab ? '_blank' : null"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($navigationItemExtraAttributes)"
|
||||
>
|
||||
{{ $navigationItem->getLabel() }}
|
||||
|
||||
@if ($navigationItemIcon instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<x-slot name="icon">
|
||||
{{ $navigationItemIcon }}
|
||||
</x-slot>
|
||||
@endif
|
||||
</x-filament::dropdown.list.item>
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
</x-filament::dropdown>
|
||||
@else
|
||||
@foreach ($navigationGroup->getItems() as $navigationItem)
|
||||
@php
|
||||
$isNavigationItemActive = $navigationItem->isActive();
|
||||
$navigationItemBadge = $navigationItem->getBadge();
|
||||
$navigationItemBadgeColor = $navigationItem->getBadgeColor();
|
||||
$navigationItemBadgeTooltip = $navigationItem->getBadgeTooltip();
|
||||
$navigationItemIcon = $navigationItem->isActive() ? ($navigationItem->getActiveIcon() ?? $navigationItem->getIcon()) : $navigationItem->getIcon();
|
||||
$navigationItemUrl = $navigationItem->getUrl();
|
||||
$shouldNavigationItemOpenUrlInNewTab = $navigationItem->shouldOpenUrlInNewTab();
|
||||
$navigationItemExtraAttributes = $navigationItem->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament::tabs.item
|
||||
:active="$isNavigationItemActive"
|
||||
:badge="$navigationItemBadge"
|
||||
:badge-color="$navigationItemBadgeColor"
|
||||
:badge-tooltip="$navigationItemBadgeTooltip"
|
||||
:href="$navigationItemUrl"
|
||||
:icon="$navigationItemIcon"
|
||||
tag="a"
|
||||
:target="$shouldNavigationItemOpenUrlInNewTab ? '_blank' : null"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($navigationItemExtraAttributes)"
|
||||
>
|
||||
{{ $navigationItem->getLabel() }}
|
||||
|
||||
@if ($navigationItemIcon instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<x-slot name="icon">
|
||||
{{ $navigationItemIcon }}
|
||||
</x-slot>
|
||||
@endif
|
||||
</x-filament::tabs.item>
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
</x-filament::tabs>
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
@php
|
||||
$isSidebarCollapsibleOnDesktop = filament()->isSidebarCollapsibleOnDesktop();
|
||||
@endphp
|
||||
|
||||
<button class="fi-sidebar-database-notifications-btn">
|
||||
{{ \Filament\Support\generate_icon_html(\Filament\Support\Icons\Heroicon::OutlinedBell, alias: \Filament\View\PanelsIconAlias::SIDEBAR_OPEN_DATABASE_NOTIFICATIONS_BUTTON, size: \Filament\Support\Enums\IconSize::Large) }}
|
||||
|
||||
<span
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
x-transition:enter="fi-transition-enter"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:enter-end="fi-transition-enter-end"
|
||||
@endif
|
||||
class="fi-sidebar-database-notifications-btn-label"
|
||||
>
|
||||
{{ __('filament-panels::layout.actions.open_database_notifications.label') }}
|
||||
</span>
|
||||
|
||||
@if ($unreadNotificationsCount)
|
||||
<span
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
x-transition:enter="fi-transition-enter"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:enter-end="fi-transition-enter-end"
|
||||
@endif
|
||||
class="fi-sidebar-database-notifications-btn-badge-ctn"
|
||||
>
|
||||
<x-filament::badge>
|
||||
{{ $unreadNotificationsCount }}
|
||||
</x-filament::badge>
|
||||
</span>
|
||||
@endif
|
||||
</button>
|
||||
@@ -0,0 +1,228 @@
|
||||
@props([
|
||||
'active' => false,
|
||||
'collapsible' => true,
|
||||
'icon' => null,
|
||||
'items' => [],
|
||||
'label' => null,
|
||||
'sidebarCollapsible' => true,
|
||||
'subNavigation' => false,
|
||||
])
|
||||
|
||||
@php
|
||||
$sidebarCollapsible = $sidebarCollapsible && filament()->isSidebarCollapsibleOnDesktop();
|
||||
$hasDropdown = filled($label) && filled($icon) && $sidebarCollapsible;
|
||||
@endphp
|
||||
|
||||
<li
|
||||
x-data="{ label: @js($subNavigation ? "sub_navigation_{$label}" : $label) }"
|
||||
data-group-label="{{ $subNavigation ? "sub_navigation_{$label}" : $label }}"
|
||||
x-bind:class="{ 'fi-collapsed': $store.sidebar.groupIsCollapsed(label) }"
|
||||
{{
|
||||
$attributes->class([
|
||||
'fi-sidebar-group',
|
||||
'fi-active' => $active,
|
||||
'fi-collapsible' => $collapsible,
|
||||
])
|
||||
}}
|
||||
>
|
||||
@if ($label)
|
||||
<div
|
||||
@if ($collapsible)
|
||||
x-on:click="$store.sidebar.toggleCollapsedGroup(label)"
|
||||
@endif
|
||||
@if ($sidebarCollapsible)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
x-transition:enter="fi-transition-enter"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:enter-end="fi-transition-enter-end"
|
||||
@endif
|
||||
class="fi-sidebar-group-btn"
|
||||
>
|
||||
@if ($icon)
|
||||
{{ \Filament\Support\generate_icon_html($icon, size: \Filament\Support\Enums\IconSize::Large) }}
|
||||
@endif
|
||||
|
||||
<span class="fi-sidebar-group-label">
|
||||
{{ $label }}
|
||||
</span>
|
||||
|
||||
@if ($collapsible)
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::ChevronUp"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::SIDEBAR_GROUP_COLLAPSE_BUTTON"
|
||||
:label="$label"
|
||||
x-bind:aria-expanded="! $store.sidebar.groupIsCollapsed(label)"
|
||||
x-on:click.stop="$store.sidebar.toggleCollapsedGroup(label)"
|
||||
class="fi-sidebar-group-collapse-btn"
|
||||
/>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($hasDropdown)
|
||||
<x-filament::dropdown
|
||||
:placement="(__('filament-panels::layout.direction') === 'rtl') ? 'left-start' : 'right-start'"
|
||||
x-show="! $store.sidebar.isOpen"
|
||||
>
|
||||
<x-slot name="trigger">
|
||||
<button
|
||||
x-data="{ tooltip: false }"
|
||||
x-effect="
|
||||
tooltip = $store.sidebar.isOpen
|
||||
? false
|
||||
: {
|
||||
content: @js($label),
|
||||
placement: document.dir === 'rtl' ? 'left' : 'right',
|
||||
theme: $store.theme,
|
||||
}
|
||||
"
|
||||
x-tooltip.html="tooltip"
|
||||
class="fi-sidebar-group-dropdown-trigger-btn"
|
||||
>
|
||||
{{ \Filament\Support\generate_icon_html($icon, size: \Filament\Support\Enums\IconSize::Large) }}
|
||||
</button>
|
||||
</x-slot>
|
||||
|
||||
@php
|
||||
$lists = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($childItems = $item->getChildItems()) {
|
||||
$lists[] = [
|
||||
$item,
|
||||
...$childItems,
|
||||
];
|
||||
$lists[] = [];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($lists)) {
|
||||
$lists[] = [$item];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$lists[count($lists) - 1][] = $item;
|
||||
}
|
||||
|
||||
if (empty($lists[count($lists) - 1])) {
|
||||
array_pop($lists);
|
||||
}
|
||||
@endphp
|
||||
|
||||
@if (filled($label))
|
||||
<x-filament::dropdown.header>
|
||||
{{ $label }}
|
||||
</x-filament::dropdown.header>
|
||||
@endif
|
||||
|
||||
@foreach ($lists as $list)
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($list as $item)
|
||||
@php
|
||||
$itemIsActive = $item->isActive();
|
||||
$itemBadge = $item->getBadge();
|
||||
$itemBadgeColor = $item->getBadgeColor();
|
||||
$itemBadgeTooltip = $item->getBadgeTooltip();
|
||||
$itemUrl = $item->getUrl();
|
||||
$itemIcon = $itemIsActive ? ($item->getActiveIcon() ?? $item->getIcon()) : $item->getIcon();
|
||||
$shouldItemOpenUrlInNewTab = $item->shouldOpenUrlInNewTab();
|
||||
$itemExtraAttributes = $item->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament::dropdown.list.item
|
||||
:badge="$itemBadge"
|
||||
:badge-color="$itemBadgeColor"
|
||||
:badge-tooltip="$itemBadgeTooltip"
|
||||
:color="$itemIsActive ? 'primary' : 'gray'"
|
||||
:href="$itemUrl"
|
||||
:icon="$itemIcon"
|
||||
tag="a"
|
||||
:target="$shouldItemOpenUrlInNewTab ? '_blank' : null"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($itemExtraAttributes)"
|
||||
>
|
||||
{{ $item->getLabel() }}
|
||||
</x-filament::dropdown.list.item>
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endforeach
|
||||
</x-filament::dropdown>
|
||||
@endif
|
||||
|
||||
<ul
|
||||
@if (filled($label))
|
||||
@if ($sidebarCollapsible)
|
||||
x-show="$store.sidebar.isOpen ? ! $store.sidebar.groupIsCollapsed(label) : ! @js($hasDropdown)"
|
||||
@else
|
||||
x-show="! $store.sidebar.groupIsCollapsed(label)"
|
||||
@endif
|
||||
x-collapse.duration.200ms
|
||||
@endif
|
||||
@if ($sidebarCollapsible)
|
||||
x-transition:enter="fi-transition-enter"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:enter-end="fi-transition-enter-end"
|
||||
@endif
|
||||
class="fi-sidebar-group-items"
|
||||
>
|
||||
@foreach ($items as $item)
|
||||
@php
|
||||
$isItemChildItemsActive = $item->isChildItemsActive();
|
||||
$isItemActive = (! $isItemChildItemsActive) && $item->isActive();
|
||||
$itemActiveIcon = $item->getActiveIcon();
|
||||
$itemBadge = $item->getBadge();
|
||||
$itemBadgeColor = $item->getBadgeColor();
|
||||
$itemBadgeTooltip = $item->getBadgeTooltip();
|
||||
$itemChildItems = $item->getChildItems();
|
||||
$itemIcon = $item->getIcon();
|
||||
$shouldItemOpenUrlInNewTab = $item->shouldOpenUrlInNewTab();
|
||||
$itemUrl = $item->getUrl();
|
||||
$itemExtraAttributes = $item->getExtraAttributeBag();
|
||||
|
||||
if ($icon) {
|
||||
if ($hasDropdown || (blank($itemIcon) && blank($itemActiveIcon))) {
|
||||
$itemIcon = null;
|
||||
$itemActiveIcon = null;
|
||||
} else {
|
||||
throw new \Exception('Navigation group [' . $label . '] has an icon but one or more of its items also have icons. Either the group or its items can have icons, but not both. This is to ensure a proper user experience.');
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::sidebar.item
|
||||
:active="$isItemActive"
|
||||
:active-child-items="$isItemChildItemsActive"
|
||||
:active-icon="$itemActiveIcon"
|
||||
:badge="$itemBadge"
|
||||
:badge-color="$itemBadgeColor"
|
||||
:badge-tooltip="$itemBadgeTooltip"
|
||||
:child-items="$itemChildItems"
|
||||
:first="$loop->first"
|
||||
:grouped="filled($label)"
|
||||
:icon="$itemIcon"
|
||||
:last="$loop->last"
|
||||
:should-open-url-in-new-tab="$shouldItemOpenUrlInNewTab"
|
||||
:sidebar-collapsible="$sidebarCollapsible"
|
||||
:sub-navigation="$subNavigation"
|
||||
:url="$itemUrl"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($itemExtraAttributes)"
|
||||
>
|
||||
{{ $item->getLabel() }}
|
||||
|
||||
@if ($itemIcon instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<x-slot name="icon">
|
||||
{{ $itemIcon }}
|
||||
</x-slot>
|
||||
@endif
|
||||
|
||||
@if ($itemActiveIcon instanceof \Illuminate\Contracts\Support\Htmlable)
|
||||
<x-slot name="activeIcon">
|
||||
{{ $itemActiveIcon }}
|
||||
</x-slot>
|
||||
@endif
|
||||
</x-filament-panels::sidebar.item>
|
||||
@endforeach
|
||||
</ul>
|
||||
</li>
|
||||
@@ -0,0 +1,153 @@
|
||||
@props([
|
||||
'active' => false,
|
||||
'activeChildItems' => false,
|
||||
'activeIcon' => null,
|
||||
'badge' => null,
|
||||
'badgeColor' => null,
|
||||
'badgeTooltip' => null,
|
||||
'childItems' => [],
|
||||
'first' => false,
|
||||
'grouped' => false,
|
||||
'icon' => null,
|
||||
'last' => false,
|
||||
'shouldOpenUrlInNewTab' => false,
|
||||
'sidebarCollapsible' => true,
|
||||
'subGrouped' => false,
|
||||
'subNavigation' => false,
|
||||
'url',
|
||||
])
|
||||
|
||||
@php
|
||||
$sidebarCollapsible = $sidebarCollapsible && filament()->isSidebarCollapsibleOnDesktop();
|
||||
@endphp
|
||||
|
||||
<li
|
||||
{{
|
||||
$attributes->class([
|
||||
'fi-sidebar-item',
|
||||
'fi-active' => $active,
|
||||
'fi-sidebar-item-has-active-child-items' => $activeChildItems,
|
||||
'fi-sidebar-item-has-url' => filled($url),
|
||||
])
|
||||
}}
|
||||
>
|
||||
<a
|
||||
{{ \Filament\Support\generate_href_html($url, $shouldOpenUrlInNewTab) }}
|
||||
x-on:click="window.matchMedia(`(max-width: 1024px)`).matches && $store.sidebar.close()"
|
||||
@if ($sidebarCollapsible && (! $subNavigation))
|
||||
x-data="{ tooltip: false }"
|
||||
x-effect="
|
||||
tooltip = $store.sidebar.isOpen
|
||||
? false
|
||||
: {
|
||||
content: @js($slot->toHtml()),
|
||||
placement: document.dir === 'rtl' ? 'left' : 'right',
|
||||
theme: $store.theme,
|
||||
}
|
||||
"
|
||||
x-tooltip.html="tooltip"
|
||||
@endif
|
||||
class="fi-sidebar-item-btn"
|
||||
>
|
||||
@if (filled($icon) && ((! $subGrouped) || ($sidebarCollapsible && (! $subNavigation))))
|
||||
{{
|
||||
\Filament\Support\generate_icon_html(($active && $activeIcon) ? $activeIcon : $icon, attributes: (new \Illuminate\View\ComponentAttributeBag([
|
||||
'x-show' => ($subGrouped && $sidebarCollapsible) ? '! $store.sidebar.isOpen' : false,
|
||||
]))->class(['fi-sidebar-item-icon']), size: \Filament\Support\Enums\IconSize::Large)
|
||||
}}
|
||||
@endif
|
||||
|
||||
@if ((blank($icon) && $grouped) || $subGrouped)
|
||||
<div
|
||||
@if (filled($icon) && $subGrouped && $sidebarCollapsible && (! $subNavigation))
|
||||
x-show="$store.sidebar.isOpen"
|
||||
@endif
|
||||
class="fi-sidebar-item-grouped-border"
|
||||
>
|
||||
@if (! $first)
|
||||
<div
|
||||
class="fi-sidebar-item-grouped-border-part-not-first"
|
||||
></div>
|
||||
@endif
|
||||
|
||||
@if (! $last)
|
||||
<div
|
||||
class="fi-sidebar-item-grouped-border-part-not-last"
|
||||
></div>
|
||||
@endif
|
||||
|
||||
<div class="fi-sidebar-item-grouped-border-part"></div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<span
|
||||
@if ($sidebarCollapsible && (! $subNavigation))
|
||||
x-show="$store.sidebar.isOpen"
|
||||
x-transition:enter="fi-transition-enter"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:enter-end="fi-transition-enter-end"
|
||||
@endif
|
||||
class="fi-sidebar-item-label"
|
||||
>
|
||||
{{ $slot }}
|
||||
</span>
|
||||
|
||||
@if (filled($badge))
|
||||
<span
|
||||
@if ($sidebarCollapsible && (! $subNavigation))
|
||||
x-show="$store.sidebar.isOpen"
|
||||
x-transition:enter="fi-transition-enter"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:enter-end="fi-transition-enter-end"
|
||||
@endif
|
||||
class="fi-sidebar-item-badge-ctn"
|
||||
>
|
||||
<x-filament::badge
|
||||
:color="$badgeColor"
|
||||
:tooltip="$badgeTooltip"
|
||||
>
|
||||
{{ $badge }}
|
||||
</x-filament::badge>
|
||||
</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
@if (($active || $activeChildItems) && $childItems)
|
||||
<ul class="fi-sidebar-sub-group-items">
|
||||
@foreach ($childItems as $childItem)
|
||||
@php
|
||||
$isChildItemChildItemsActive = $childItem->isChildItemsActive();
|
||||
$isChildActive = (! $isChildItemChildItemsActive) && $childItem->isActive();
|
||||
$childItemActiveIcon = $childItem->getActiveIcon();
|
||||
$childItemBadge = $childItem->getBadge();
|
||||
$childItemBadgeColor = $childItem->getBadgeColor();
|
||||
$childItemBadgeTooltip = $childItem->getBadgeTooltip();
|
||||
$childItemIcon = $childItem->getIcon();
|
||||
$shouldChildItemOpenUrlInNewTab = $childItem->shouldOpenUrlInNewTab();
|
||||
$childItemUrl = $childItem->getUrl();
|
||||
$childItemExtraAttributes = $childItem->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::sidebar.item
|
||||
:active="$isChildActive"
|
||||
:active-child-items="$isChildItemChildItemsActive"
|
||||
:active-icon="$childItemActiveIcon"
|
||||
:badge="$childItemBadge"
|
||||
:badge-color="$childItemBadgeColor"
|
||||
:badge-tooltip="$childItemBadgeTooltip"
|
||||
:first="$loop->first"
|
||||
grouped
|
||||
:icon="$childItemIcon"
|
||||
:last="$loop->last"
|
||||
:should-open-url-in-new-tab="$shouldChildItemOpenUrlInNewTab"
|
||||
sub-grouped
|
||||
:sub-navigation="$subNavigation"
|
||||
:url="$childItemUrl"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($childItemExtraAttributes)"
|
||||
>
|
||||
{{ $childItem->getLabel() }}
|
||||
</x-filament-panels::sidebar.item>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</li>
|
||||
@@ -0,0 +1,152 @@
|
||||
@props([
|
||||
'teleport' => false,
|
||||
])
|
||||
|
||||
@php
|
||||
use Filament\Actions\Action;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
$currentTenant = filament()->getTenant();
|
||||
$currentTenantName = filament()->getTenantName($currentTenant);
|
||||
|
||||
$items = $this->getTenantMenuItems();
|
||||
|
||||
$canSwitchTenants = filament()->hasTenantSwitcher() && filled($tenants = array_filter(
|
||||
filament()->getUserTenants(filament()->auth()->user()),
|
||||
fn (\Illuminate\Database\Eloquent\Model $tenant): bool => ! $tenant->is($currentTenant),
|
||||
));
|
||||
|
||||
$isSearchable = $canSwitchTenants && (filament()->isTenantMenuSearchable() ?? (count($tenants) >= 10));
|
||||
|
||||
$itemsBeforeAndAfterTenantSwitcher = collect($items)
|
||||
->groupBy(fn (Action $item): bool => $canSwitchTenants && ($item->getSort() < 0), preserveKeys: true)
|
||||
->all();
|
||||
$itemsBeforeTenantSwitcher = $itemsBeforeAndAfterTenantSwitcher[true] ?? collect();
|
||||
$itemsAfterTenantSwitcher = $itemsBeforeAndAfterTenantSwitcher[false] ?? collect();
|
||||
|
||||
$isSidebarCollapsibleOnDesktop = filament()->isSidebarCollapsibleOnDesktop();
|
||||
@endphp
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TENANT_MENU_BEFORE) }}
|
||||
|
||||
<x-filament::dropdown
|
||||
placement="bottom-start"
|
||||
size
|
||||
:teleport="$teleport"
|
||||
:attributes="
|
||||
\Filament\Support\prepare_inherited_attributes($attributes)
|
||||
->class(['fi-tenant-menu'])
|
||||
"
|
||||
>
|
||||
<x-slot name="trigger">
|
||||
<button
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
x-data="{ tooltip: false }"
|
||||
x-effect="
|
||||
tooltip = $store.sidebar.isOpen
|
||||
? false
|
||||
: {
|
||||
content: @js($currentTenantName),
|
||||
placement: document.dir === 'rtl' ? 'left' : 'right',
|
||||
theme: $store.theme,
|
||||
}
|
||||
"
|
||||
x-tooltip.html="tooltip"
|
||||
@endif
|
||||
type="button"
|
||||
class="fi-tenant-menu-trigger"
|
||||
>
|
||||
<x-filament-panels::avatar.tenant
|
||||
:tenant="$currentTenant"
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
<span
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
@endif
|
||||
class="fi-tenant-menu-trigger-text"
|
||||
>
|
||||
@if ($currentTenant instanceof \Filament\Models\Contracts\HasCurrentTenantLabel)
|
||||
<span class="fi-tenant-menu-trigger-current-tenant-label">
|
||||
{{ $currentTenant->getCurrentTenantLabel() }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
<span class="fi-tenant-menu-trigger-tenant-name">
|
||||
{{ $currentTenantName }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
{{
|
||||
\Filament\Support\generate_icon_html(\Filament\Support\Icons\Heroicon::ChevronDown, alias: \Filament\View\PanelsIconAlias::TENANT_MENU_TOGGLE_BUTTON, attributes: new \Illuminate\View\ComponentAttributeBag([
|
||||
'x-show' => $isSidebarCollapsibleOnDesktop ? '$store.sidebar.isOpen' : null,
|
||||
]))
|
||||
}}
|
||||
</button>
|
||||
</x-slot>
|
||||
|
||||
@if ($itemsBeforeTenantSwitcher->isNotEmpty())
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($itemsBeforeTenantSwitcher as $item)
|
||||
{{ $item }}
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endif
|
||||
|
||||
@if ($canSwitchTenants)
|
||||
<div x-data="{ search: '' }">
|
||||
<x-filament::dropdown.list>
|
||||
@if ($isSearchable)
|
||||
<div x-id="['input']">
|
||||
<label x-bind:for="$id('input')" class="fi-sr-only">
|
||||
{{ __('filament-panels::layout.tenant_menu.search_field.label') }}
|
||||
</label>
|
||||
|
||||
<x-filament::input
|
||||
x-bind:id="$id('input')"
|
||||
x-model="search"
|
||||
placeholder="{{ __('filament-panels::layout.tenant_menu.search_field.placeholder') }}"
|
||||
type="search"
|
||||
/>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@foreach ($tenants as $tenant)
|
||||
@php
|
||||
$tenantImage = filament()->getTenantAvatarUrl($tenant);
|
||||
$tenantName = filament()->getTenantName($tenant);
|
||||
$tenantUrl = filament()->getUrl($tenant);
|
||||
@endphp
|
||||
|
||||
<div
|
||||
x-show="
|
||||
search === '' ||
|
||||
@js($tenantName).replace(/ /g, '')
|
||||
.toLowerCase()
|
||||
.includes(search.replace(/ /g, '').toLowerCase())
|
||||
"
|
||||
>
|
||||
<x-filament::dropdown.list.item
|
||||
:href="$tenantUrl"
|
||||
:image="$tenantImage"
|
||||
tag="a"
|
||||
>
|
||||
{{ $tenantName }}
|
||||
</x-filament::dropdown.list.item>
|
||||
</div>
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($itemsAfterTenantSwitcher->isNotEmpty())
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($itemsAfterTenantSwitcher as $item)
|
||||
{{ $item }}
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endif
|
||||
</x-filament::dropdown>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TENANT_MENU_AFTER) }}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
@props([
|
||||
'icon',
|
||||
'theme',
|
||||
])
|
||||
|
||||
@php
|
||||
$label = __("filament-panels::layout.actions.theme_switcher.{$theme}.label");
|
||||
@endphp
|
||||
|
||||
<button
|
||||
aria-label="{{ $label }}"
|
||||
type="button"
|
||||
x-on:click="(theme = @js($theme)) && close()"
|
||||
x-tooltip="{
|
||||
content: @js($label),
|
||||
theme: $store.theme,
|
||||
}"
|
||||
x-bind:class="{ 'fi-active': theme === @js($theme) }"
|
||||
class="fi-theme-switcher-btn"
|
||||
>
|
||||
{{
|
||||
\Filament\Support\generate_icon_html($icon, alias: match ($theme) {
|
||||
'light' => \Filament\View\PanelsIconAlias::THEME_SWITCHER_LIGHT_BUTTON,
|
||||
'dark' => \Filament\View\PanelsIconAlias::THEME_SWITCHER_DARK_BUTTON,
|
||||
'system' => \Filament\View\PanelsIconAlias::THEME_SWITCHER_SYSTEM_BUTTON,
|
||||
})
|
||||
}}
|
||||
</button>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<div
|
||||
x-data="{ theme: null }"
|
||||
x-init="
|
||||
$watch('theme', () => {
|
||||
$dispatch('theme-changed', theme)
|
||||
})
|
||||
|
||||
theme = localStorage.getItem('theme') || @js(filament()->getDefaultThemeMode()->value)
|
||||
"
|
||||
class="fi-theme-switcher"
|
||||
>
|
||||
<x-filament-panels::theme-switcher.button
|
||||
:icon="\Filament\Support\Icons\Heroicon::Sun"
|
||||
theme="light"
|
||||
/>
|
||||
|
||||
<x-filament-panels::theme-switcher.button
|
||||
:icon="\Filament\Support\Icons\Heroicon::Moon"
|
||||
theme="dark"
|
||||
/>
|
||||
|
||||
<x-filament-panels::theme-switcher.button
|
||||
:icon="\Filament\Support\Icons\Heroicon::ComputerDesktop"
|
||||
theme="system"
|
||||
/>
|
||||
</div>
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
<x-filament::icon-button
|
||||
:badge="$unreadNotificationsCount ?: null"
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::OutlinedBell"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::TOPBAR_OPEN_DATABASE_NOTIFICATIONS_BUTTON"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.open_database_notifications.label')"
|
||||
class="fi-topbar-database-notifications-btn"
|
||||
/>
|
||||
@@ -0,0 +1,54 @@
|
||||
@props([
|
||||
'active' => false,
|
||||
'activeIcon' => null,
|
||||
'badge' => null,
|
||||
'badgeColor' => null,
|
||||
'badgeTooltip' => null,
|
||||
'icon' => null,
|
||||
'shouldOpenUrlInNewTab' => false,
|
||||
'url' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$tag = $url ? 'a' : 'button';
|
||||
@endphp
|
||||
|
||||
<li
|
||||
{{
|
||||
$attributes->class([
|
||||
'fi-topbar-item',
|
||||
'fi-active' => $active,
|
||||
])
|
||||
}}
|
||||
>
|
||||
<{{ $tag }}
|
||||
@if ($url)
|
||||
{{ \Filament\Support\generate_href_html($url, $shouldOpenUrlInNewTab) }}
|
||||
@else
|
||||
type="button"
|
||||
@endif
|
||||
class="fi-topbar-item-btn"
|
||||
>
|
||||
@if ($icon || $activeIcon)
|
||||
{{ \Filament\Support\generate_icon_html(($active && $activeIcon) ? $activeIcon : $icon, attributes: (new \Illuminate\View\ComponentAttributeBag)->class(['fi-topbar-item-icon'])) }}
|
||||
@endif
|
||||
|
||||
<span class="fi-topbar-item-label">
|
||||
{{ $slot }}
|
||||
</span>
|
||||
|
||||
@if (filled($badge))
|
||||
<x-filament::badge
|
||||
:color="$badgeColor"
|
||||
size="sm"
|
||||
:tooltip="$badgeTooltip"
|
||||
>
|
||||
{{ $badge }}
|
||||
</x-filament::badge>
|
||||
@endif
|
||||
|
||||
@if (! $url)
|
||||
{{ \Filament\Support\generate_icon_html(\Filament\Support\Icons\Heroicon::ChevronDown, alias: \Filament\View\PanelsIconAlias::TOPBAR_GROUP_TOGGLE_BUTTON, attributes: (new \Illuminate\View\ComponentAttributeBag)->class(['fi-topbar-group-toggle-icon'])) }}
|
||||
@endif
|
||||
</{{ $tag }}>
|
||||
</li>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
@if (filament()->hasUnsavedChangesAlerts())
|
||||
@script
|
||||
<script>
|
||||
setUpUnsavedActionChangesAlert({
|
||||
resolveLivewireComponentUsing: () => @this,
|
||||
$wire,
|
||||
})
|
||||
</script>
|
||||
@endscript
|
||||
@endif
|
||||
@@ -0,0 +1,135 @@
|
||||
@props([
|
||||
'position' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Enums\UserMenuPosition;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
$user = filament()->auth()->user();
|
||||
|
||||
$items = $this->getUserMenuItems();
|
||||
|
||||
$itemsBeforeAndAfterThemeSwitcher = collect($items)
|
||||
->groupBy(fn (Action $item): bool => $item->getSort() < 0, preserveKeys: true)
|
||||
->all();
|
||||
$itemsBeforeThemeSwitcher = $itemsBeforeAndAfterThemeSwitcher[true] ?? collect();
|
||||
$itemsAfterThemeSwitcher = $itemsBeforeAndAfterThemeSwitcher[false] ?? collect();
|
||||
|
||||
$hasProfileHeader = $itemsBeforeThemeSwitcher->has('profile') &&
|
||||
blank(($item = Arr::first($itemsBeforeThemeSwitcher))->getUrl()) &&
|
||||
(! $item->hasAction());
|
||||
|
||||
if ($itemsBeforeThemeSwitcher->has('profile')) {
|
||||
$itemsBeforeThemeSwitcher = $itemsBeforeThemeSwitcher->prepend($itemsBeforeThemeSwitcher->pull('profile'), 'profile');
|
||||
}
|
||||
|
||||
$position ??= filament()->getUserMenuPosition();
|
||||
|
||||
$isSidebarCollapsibleOnDesktop = filament()->isSidebarCollapsibleOnDesktop();
|
||||
@endphp
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_BEFORE) }}
|
||||
|
||||
<x-filament::dropdown
|
||||
:placement="($position === UserMenuPosition::Topbar) ? 'bottom-end' : 'top-end'"
|
||||
:teleport="$position === UserMenuPosition::Topbar"
|
||||
:attributes="
|
||||
\Filament\Support\prepare_inherited_attributes($attributes)
|
||||
->class(['fi-user-menu'])
|
||||
"
|
||||
>
|
||||
<x-slot name="trigger">
|
||||
@if ($position === UserMenuPosition::Topbar)
|
||||
<button
|
||||
aria-label="{{ __('filament-panels::layout.actions.open_user_menu.label') }}"
|
||||
type="button"
|
||||
class="fi-user-menu-trigger"
|
||||
>
|
||||
<x-filament-panels::avatar.user :user="$user" loading="lazy" />
|
||||
</button>
|
||||
@else
|
||||
<button
|
||||
aria-label="{{ __('filament-panels::layout.actions.open_user_menu.label') }}"
|
||||
type="button"
|
||||
class="fi-user-menu-trigger"
|
||||
>
|
||||
<x-filament-panels::avatar.user :user="$user" loading="lazy" />
|
||||
|
||||
<span
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
@endif
|
||||
class="fi-user-menu-trigger-text"
|
||||
>
|
||||
{{ filament()->getUserName($user) }}
|
||||
</span>
|
||||
|
||||
{{
|
||||
\Filament\Support\generate_icon_html(\Filament\Support\Icons\Heroicon::ChevronUp, alias: \Filament\View\PanelsIconAlias::USER_MENU_TOGGLE_BUTTON, attributes: new \Illuminate\View\ComponentAttributeBag([
|
||||
'x-show' => $isSidebarCollapsibleOnDesktop ? '$store.sidebar.isOpen' : null,
|
||||
]))
|
||||
}}
|
||||
</button>
|
||||
@endif
|
||||
</x-slot>
|
||||
|
||||
@if ($hasProfileHeader)
|
||||
@php
|
||||
$item = $itemsBeforeThemeSwitcher['profile'];
|
||||
$itemColor = $item->getColor();
|
||||
$itemIcon = $item->getIcon();
|
||||
|
||||
unset($itemsBeforeThemeSwitcher['profile']);
|
||||
@endphp
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_PROFILE_BEFORE) }}
|
||||
|
||||
<x-filament::dropdown.header :color="$itemColor" :icon="$itemIcon">
|
||||
{{ $item->getLabel() }}
|
||||
</x-filament::dropdown.header>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_PROFILE_AFTER) }}
|
||||
@endif
|
||||
|
||||
@if ($itemsBeforeThemeSwitcher->isNotEmpty())
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($itemsBeforeThemeSwitcher as $key => $item)
|
||||
@if ($key === 'profile')
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_PROFILE_BEFORE) }}
|
||||
|
||||
{{ $item }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_PROFILE_AFTER) }}
|
||||
@else
|
||||
{{ $item }}
|
||||
@endif
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endif
|
||||
|
||||
@if (filament()->hasDarkMode() && (! filament()->hasDarkModeForced()))
|
||||
<x-filament::dropdown.list>
|
||||
<x-filament-panels::theme-switcher />
|
||||
</x-filament::dropdown.list>
|
||||
@endif
|
||||
|
||||
@if ($itemsAfterThemeSwitcher->isNotEmpty())
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($itemsAfterThemeSwitcher as $key => $item)
|
||||
@if ($key === 'profile')
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_PROFILE_BEFORE) }}
|
||||
|
||||
{{ $item }}
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_PROFILE_AFTER) }}
|
||||
@else
|
||||
{{ $item }}
|
||||
@endif
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endif
|
||||
</x-filament::dropdown>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::USER_MENU_AFTER) }}
|
||||
@@ -0,0 +1,153 @@
|
||||
@php
|
||||
$debounce = filament()->getGlobalSearchDebounce();
|
||||
$keyBindings = filament()->getGlobalSearchKeyBindings();
|
||||
$suffix = filament()->getGlobalSearchFieldSuffix();
|
||||
@endphp
|
||||
|
||||
<div class="fi-global-search-ctn">
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::GLOBAL_SEARCH_START) }}
|
||||
|
||||
<div
|
||||
x-on:focus-first-global-search-result.stop="$el.querySelector('.fi-global-search-result-link')?.focus()"
|
||||
class="fi-global-search"
|
||||
>
|
||||
<div x-id="['input']" class="fi-global-search-field">
|
||||
<label x-bind:for="$id('input')" class="fi-sr-only">
|
||||
{{ __('filament-panels::global-search.field.label') }}
|
||||
</label>
|
||||
|
||||
<x-filament::input.wrapper
|
||||
:prefix-icon="\Filament\Support\Icons\Heroicon::MagnifyingGlass"
|
||||
:prefix-icon-alias="\Filament\View\PanelsIconAlias::GLOBAL_SEARCH_FIELD"
|
||||
inline-prefix
|
||||
:suffix="$suffix"
|
||||
inline-suffix
|
||||
wire:target="search"
|
||||
>
|
||||
<input
|
||||
autocomplete="off"
|
||||
maxlength="1000"
|
||||
placeholder="{{ __('filament-panels::global-search.field.placeholder') }}"
|
||||
type="search"
|
||||
wire:key="global-search.field.input"
|
||||
x-bind:id="$id('input')"
|
||||
x-on:keydown.down.prevent.stop="$dispatch('focus-first-global-search-result')"
|
||||
wire:model.live.debounce.{{ $debounce }}="search"
|
||||
x-mousetrap.global.{{ collect($keyBindings)->map(fn (string $keyBinding): string => str_replace('+', '-', $keyBinding))->implode('.') }}="document.getElementById($id('input'))?.focus()"
|
||||
class="fi-input fi-input-has-inline-prefix"
|
||||
/>
|
||||
</x-filament::input.wrapper>
|
||||
</div>
|
||||
|
||||
@if ($results !== null)
|
||||
<div
|
||||
x-data="{
|
||||
isOpen: false,
|
||||
|
||||
open(event) {
|
||||
this.isOpen = true
|
||||
},
|
||||
|
||||
close(event) {
|
||||
this.isOpen = false
|
||||
},
|
||||
}"
|
||||
x-init="$nextTick(() => open())"
|
||||
x-on:click.away="close()"
|
||||
x-on:keydown.escape.window="close()"
|
||||
x-on:keydown.up.prevent="$focus.wrap().previous()"
|
||||
x-on:keydown.down.prevent="$focus.wrap().next()"
|
||||
x-on:open-global-search-results.window="$nextTick(() => open())"
|
||||
x-show="isOpen"
|
||||
x-transition:enter-start="fi-transition-enter-start"
|
||||
x-transition:leave-end="fi-transition-leave-end"
|
||||
class="fi-global-search-results-ctn"
|
||||
>
|
||||
@if ($results->getCategories()->isEmpty())
|
||||
<p class="fi-global-search-no-results-message">
|
||||
{{ __('filament-panels::global-search.no_results_message') }}
|
||||
</p>
|
||||
@else
|
||||
<ul class="fi-global-search-results">
|
||||
@foreach ($results->getCategories() as $group => $groupedResults)
|
||||
<li class="fi-global-search-result-group">
|
||||
<h3
|
||||
class="fi-global-search-result-group-header"
|
||||
>
|
||||
{{ $group }}
|
||||
</h3>
|
||||
|
||||
<ul
|
||||
class="fi-global-search-result-group-results"
|
||||
>
|
||||
@foreach ($groupedResults as $result)
|
||||
@php
|
||||
$resultVisibleActions = $result->getVisibleActions();
|
||||
@endphp
|
||||
|
||||
<li
|
||||
@class([
|
||||
'fi-global-search-result',
|
||||
'fi-global-search-result-has-actions' => $resultVisibleActions,
|
||||
])
|
||||
>
|
||||
<a
|
||||
{{ \Filament\Support\generate_href_html($result->url) }}
|
||||
x-on:click="close()"
|
||||
class="fi-global-search-result-link"
|
||||
>
|
||||
<h4
|
||||
class="fi-global-search-result-heading"
|
||||
>
|
||||
{{ $result->title }}
|
||||
</h4>
|
||||
|
||||
@if ($result->details)
|
||||
<dl
|
||||
class="fi-global-search-result-details"
|
||||
>
|
||||
@foreach ($result->details as $label => $value)
|
||||
<div
|
||||
class="fi-global-search-result-detail"
|
||||
>
|
||||
@if ($isAssoc ??= \Illuminate\Support\Arr::isAssoc($result->details))
|
||||
<dt
|
||||
class="fi-global-search-result-detail-label"
|
||||
>
|
||||
{{ $label }}:
|
||||
</dt>
|
||||
@endif
|
||||
|
||||
<dd
|
||||
class="fi-global-search-result-detail-value"
|
||||
>
|
||||
{{ $value }}
|
||||
</dd>
|
||||
</div>
|
||||
@endforeach
|
||||
</dl>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
@if ($resultVisibleActions)
|
||||
<div
|
||||
class="fi-global-search-result-actions"
|
||||
>
|
||||
@foreach ($resultVisibleActions as $action)
|
||||
{{ $action }}
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::GLOBAL_SEARCH_END) }}
|
||||
</div>
|
||||
@@ -0,0 +1,203 @@
|
||||
<div>
|
||||
@php
|
||||
$navigation = filament()->getNavigation();
|
||||
$isRtl = __('filament-panels::layout.direction') === 'rtl';
|
||||
$isSidebarCollapsibleOnDesktop = filament()->isSidebarCollapsibleOnDesktop();
|
||||
$isSidebarFullyCollapsibleOnDesktop = filament()->isSidebarFullyCollapsibleOnDesktop();
|
||||
$hasNavigation = filament()->hasNavigation();
|
||||
$hasTopbar = filament()->hasTopbar();
|
||||
@endphp
|
||||
|
||||
{{-- format-ignore-start --}}
|
||||
<aside
|
||||
x-data="{}"
|
||||
@if ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop)
|
||||
x-cloak
|
||||
@else
|
||||
x-cloak="-lg"
|
||||
@endif
|
||||
x-bind:class="{ 'fi-sidebar-open': $store.sidebar.isOpen }"
|
||||
class="fi-sidebar fi-main-sidebar"
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIDEBAR_START) }}
|
||||
|
||||
<div class="fi-sidebar-header-ctn">
|
||||
<header
|
||||
class="fi-sidebar-header"
|
||||
>
|
||||
@if ((! $hasTopbar) && $isSidebarCollapsibleOnDesktop)
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="$isRtl ? \Filament\Support\Icons\Heroicon::OutlinedChevronLeft : \Filament\Support\Icons\Heroicon::OutlinedChevronRight"
|
||||
{{-- @deprecated Use `PanelsIconAlias::SIDEBAR_EXPAND_BUTTON_RTL` instead of `PanelsIconAlias::SIDEBAR_EXPAND_BUTTON` for RTL. --}}
|
||||
:icon-alias="
|
||||
$isRtl
|
||||
? [
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON_RTL,
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON,
|
||||
]
|
||||
: \Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON
|
||||
"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.expand.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.open()"
|
||||
x-show="! $store.sidebar.isOpen"
|
||||
class="fi-sidebar-open-collapse-sidebar-btn"
|
||||
/>
|
||||
@endif
|
||||
|
||||
@if ((! $hasTopbar) && ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop))
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="$isRtl ? \Filament\Support\Icons\Heroicon::OutlinedChevronRight : \Filament\Support\Icons\Heroicon::OutlinedChevronLeft"
|
||||
{{-- @deprecated Use `PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON_RTL` instead of `PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON` for RTL. --}}
|
||||
:icon-alias="
|
||||
$isRtl
|
||||
? [
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON_RTL,
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON,
|
||||
]
|
||||
: \Filament\View\PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON
|
||||
"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.collapse.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.close()"
|
||||
x-show="$store.sidebar.isOpen"
|
||||
class="fi-sidebar-close-collapse-sidebar-btn"
|
||||
/>
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIDEBAR_LOGO_BEFORE) }}
|
||||
|
||||
<div
|
||||
@if ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
@endif
|
||||
class="fi-sidebar-header-logo-ctn"
|
||||
>
|
||||
@if ($homeUrl = filament()->getHomeUrl())
|
||||
<a {{ \Filament\Support\generate_href_html($homeUrl) }}>
|
||||
<x-filament-panels::logo />
|
||||
</a>
|
||||
@else
|
||||
<x-filament-panels::logo />
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIDEBAR_LOGO_AFTER) }}
|
||||
</header>
|
||||
</div>
|
||||
|
||||
@if (filament()->hasTenancy() && filament()->hasTenantMenu())
|
||||
<x-filament-panels::tenant-menu />
|
||||
@endif
|
||||
|
||||
@if (filament()->isGlobalSearchEnabled() && filament()->getGlobalSearchPosition() === \Filament\Enums\GlobalSearchPosition::Sidebar)
|
||||
<div
|
||||
@if ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop)
|
||||
x-show="$store.sidebar.isOpen"
|
||||
@endif
|
||||
>
|
||||
@livewire(Filament\Livewire\GlobalSearch::class)
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<nav class="fi-sidebar-nav">
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIDEBAR_NAV_START) }}
|
||||
|
||||
<ul class="fi-sidebar-nav-groups">
|
||||
@foreach ($navigation as $group)
|
||||
@php
|
||||
$isGroupActive = $group->isActive();
|
||||
$isGroupCollapsible = $group->isCollapsible();
|
||||
$groupIcon = $group->getIcon();
|
||||
$groupItems = $group->getItems();
|
||||
$groupLabel = $group->getLabel();
|
||||
$groupExtraSidebarAttributeBag = $group->getExtraSidebarAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::sidebar.group
|
||||
:active="$isGroupActive"
|
||||
:collapsible="$isGroupCollapsible"
|
||||
:icon="$groupIcon"
|
||||
:items="$groupItems"
|
||||
:label="$groupLabel"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($groupExtraSidebarAttributeBag)"
|
||||
/>
|
||||
@endforeach
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
var collapsedGroups = JSON.parse(
|
||||
localStorage.getItem('collapsedGroups'),
|
||||
)
|
||||
|
||||
if (collapsedGroups === null || collapsedGroups === 'null') {
|
||||
localStorage.setItem(
|
||||
'collapsedGroups',
|
||||
JSON.stringify(@js(
|
||||
collect($navigation)
|
||||
->filter(fn (\Filament\Navigation\NavigationGroup $group): bool => $group->isCollapsed())
|
||||
->map(fn (\Filament\Navigation\NavigationGroup $group): string => $group->getLabel())
|
||||
->values()
|
||||
->all()
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
collapsedGroups = JSON.parse(
|
||||
localStorage.getItem('collapsedGroups'),
|
||||
)
|
||||
|
||||
document
|
||||
.querySelectorAll('.fi-sidebar-group')
|
||||
.forEach((group) => {
|
||||
if (
|
||||
!collapsedGroups.includes(group.dataset.groupLabel)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// Alpine.js loads too slow, so attempt to hide a
|
||||
// collapsed sidebar group earlier.
|
||||
group.querySelector(
|
||||
'.fi-sidebar-group-items',
|
||||
).style.display = 'none'
|
||||
group.classList.add('fi-collapsed')
|
||||
})
|
||||
</script>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIDEBAR_NAV_END) }}
|
||||
</nav>
|
||||
|
||||
@php
|
||||
$isAuthenticated = filament()->auth()->check();
|
||||
$hasDatabaseNotificationsInSidebar = filament()->hasDatabaseNotifications() && filament()->getDatabaseNotificationsPosition() === \Filament\Enums\DatabaseNotificationsPosition::Sidebar;
|
||||
$hasUserMenuInSidebar = filament()->hasUserMenu() && filament()->getUserMenuPosition() === \Filament\Enums\UserMenuPosition::Sidebar;
|
||||
$shouldRenderFooter = $isAuthenticated && ($hasDatabaseNotificationsInSidebar || $hasUserMenuInSidebar);
|
||||
@endphp
|
||||
|
||||
@if ($shouldRenderFooter)
|
||||
<div class="fi-sidebar-footer">
|
||||
@if ($hasDatabaseNotificationsInSidebar)
|
||||
@livewire(filament()->getDatabaseNotificationsLivewireComponent(), [
|
||||
'lazy' => filament()->hasLazyLoadedDatabaseNotifications(),
|
||||
])
|
||||
@endif
|
||||
|
||||
@if ($hasUserMenuInSidebar)
|
||||
<x-filament-panels::user-menu />
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::SIDEBAR_FOOTER) }}
|
||||
</aside>
|
||||
{{-- format-ignore-end --}}
|
||||
|
||||
<x-filament-actions::modals />
|
||||
</div>
|
||||
@@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<div class="fi-simple-user-menu-ctn">
|
||||
<x-filament-panels::user-menu
|
||||
:position="\Filament\Enums\UserMenuPosition::Topbar"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<x-filament-actions::modals />
|
||||
</div>
|
||||
@@ -0,0 +1,269 @@
|
||||
<div class="fi-topbar-ctn">
|
||||
@php
|
||||
$isRtl = __('filament-panels::layout.direction') === 'rtl';
|
||||
$isSidebarCollapsibleOnDesktop = filament()->isSidebarCollapsibleOnDesktop();
|
||||
$isSidebarFullyCollapsibleOnDesktop = filament()->isSidebarFullyCollapsibleOnDesktop();
|
||||
$hasTopNavigation = filament()->hasTopNavigation();
|
||||
$hasNavigation = filament()->hasNavigation();
|
||||
$hasTenancy = filament()->hasTenancy();
|
||||
@endphp
|
||||
|
||||
<nav class="fi-topbar">
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_START) }}
|
||||
|
||||
@if ($hasNavigation)
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::OutlinedBars3"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::TOPBAR_OPEN_SIDEBAR_BUTTON"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.expand.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.open()"
|
||||
x-show="! $store.sidebar.isOpen"
|
||||
class="fi-topbar-open-sidebar-btn"
|
||||
/>
|
||||
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::OutlinedXMark"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::TOPBAR_CLOSE_SIDEBAR_BUTTON"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.collapse.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.close()"
|
||||
x-show="$store.sidebar.isOpen"
|
||||
class="fi-topbar-close-sidebar-btn"
|
||||
/>
|
||||
@endif
|
||||
|
||||
<div class="fi-topbar-start">
|
||||
@if ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop)
|
||||
<div
|
||||
x-show="$store.sidebar.isOpen || @js($isSidebarCollapsibleOnDesktop)"
|
||||
class="fi-topbar-collapse-sidebar-btn-ctn"
|
||||
>
|
||||
@if ($isSidebarCollapsibleOnDesktop)
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="$isRtl ? \Filament\Support\Icons\Heroicon::OutlinedChevronLeft : \Filament\Support\Icons\Heroicon::OutlinedChevronRight"
|
||||
{{-- @deprecated Use `PanelsIconAlias::SIDEBAR_EXPAND_BUTTON_RTL` instead of `PanelsIconAlias::SIDEBAR_EXPAND_BUTTON` for RTL. --}}
|
||||
:icon-alias="
|
||||
$isRtl
|
||||
? [
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON_RTL,
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON,
|
||||
]
|
||||
: \Filament\View\PanelsIconAlias::SIDEBAR_EXPAND_BUTTON
|
||||
"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.expand.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.open()"
|
||||
x-show="! $store.sidebar.isOpen"
|
||||
class="fi-topbar-open-collapse-sidebar-btn"
|
||||
/>
|
||||
@endif
|
||||
|
||||
@if ($isSidebarCollapsibleOnDesktop || $isSidebarFullyCollapsibleOnDesktop)
|
||||
<x-filament::icon-button
|
||||
color="gray"
|
||||
:icon="$isRtl ? \Filament\Support\Icons\Heroicon::OutlinedChevronRight : \Filament\Support\Icons\Heroicon::OutlinedChevronLeft"
|
||||
{{-- @deprecated Use `PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON_RTL` instead of `PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON` for RTL. --}}
|
||||
:icon-alias="
|
||||
$isRtl
|
||||
? [
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON_RTL,
|
||||
\Filament\View\PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON,
|
||||
]
|
||||
: \Filament\View\PanelsIconAlias::SIDEBAR_COLLAPSE_BUTTON
|
||||
"
|
||||
icon-size="lg"
|
||||
:label="__('filament-panels::layout.actions.sidebar.collapse.label')"
|
||||
x-cloak
|
||||
x-data="{}"
|
||||
x-on:click="$store.sidebar.close()"
|
||||
x-show="$store.sidebar.isOpen"
|
||||
class="fi-topbar-close-collapse-sidebar-btn"
|
||||
/>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_LOGO_BEFORE) }}
|
||||
|
||||
@if ($homeUrl = filament()->getHomeUrl())
|
||||
<a {{ \Filament\Support\generate_href_html($homeUrl) }}>
|
||||
<x-filament-panels::logo />
|
||||
</a>
|
||||
@else
|
||||
<x-filament-panels::logo />
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_LOGO_AFTER) }}
|
||||
</div>
|
||||
|
||||
@if ($hasTopNavigation || (! $hasNavigation))
|
||||
@if ($hasTenancy && filament()->hasTenantMenu())
|
||||
<x-filament-panels::tenant-menu teleport />
|
||||
@endif
|
||||
|
||||
@if ($hasNavigation)
|
||||
@php
|
||||
$navigation = filament()->getNavigation();
|
||||
@endphp
|
||||
|
||||
<ul class="fi-topbar-nav-groups">
|
||||
@foreach ($navigation as $group)
|
||||
@php
|
||||
$groupLabel = $group->getLabel();
|
||||
$groupExtraTopbarAttributeBag = $group->getExtraTopbarAttributeBag();
|
||||
$isGroupActive = $group->isActive();
|
||||
$groupIcon = $group->getIcon();
|
||||
@endphp
|
||||
|
||||
@if ($groupLabel)
|
||||
<x-filament::dropdown
|
||||
placement="bottom-start"
|
||||
teleport
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($groupExtraTopbarAttributeBag)"
|
||||
>
|
||||
<x-slot name="trigger">
|
||||
<x-filament-panels::topbar.item
|
||||
:active="$isGroupActive"
|
||||
:icon="$groupIcon"
|
||||
>
|
||||
{{ $groupLabel }}
|
||||
</x-filament-panels::topbar.item>
|
||||
</x-slot>
|
||||
|
||||
@php
|
||||
$lists = [];
|
||||
|
||||
foreach ($group->getItems() as $item) {
|
||||
if ($childItems = $item->getChildItems()) {
|
||||
$lists[] = [
|
||||
$item,
|
||||
...$childItems,
|
||||
];
|
||||
$lists[] = [];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($lists)) {
|
||||
$lists[] = [$item];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$lists[count($lists) - 1][] = $item;
|
||||
}
|
||||
|
||||
if (empty($lists[count($lists) - 1])) {
|
||||
array_pop($lists);
|
||||
}
|
||||
@endphp
|
||||
|
||||
@foreach ($lists as $list)
|
||||
<x-filament::dropdown.list>
|
||||
@foreach ($list as $item)
|
||||
@php
|
||||
$isItemActive = $item->isActive();
|
||||
$itemBadge = $item->getBadge();
|
||||
$itemBadgeColor = $item->getBadgeColor();
|
||||
$itemBadgeTooltip = $item->getBadgeTooltip();
|
||||
$itemUrl = $item->getUrl();
|
||||
$itemIcon = $isItemActive ? ($item->getActiveIcon() ?? $item->getIcon()) : $item->getIcon();
|
||||
$shouldItemOpenUrlInNewTab = $item->shouldOpenUrlInNewTab();
|
||||
$itemExtraAttributes = $item->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament::dropdown.list.item
|
||||
:badge="$itemBadge"
|
||||
:badge-color="$itemBadgeColor"
|
||||
:badge-tooltip="$itemBadgeTooltip"
|
||||
:color="$isItemActive ? 'primary' : 'gray'"
|
||||
:href="$itemUrl"
|
||||
:icon="$itemIcon"
|
||||
tag="a"
|
||||
:target="$shouldItemOpenUrlInNewTab ? '_blank' : null"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($itemExtraAttributes)"
|
||||
>
|
||||
{{ $item->getLabel() }}
|
||||
</x-filament::dropdown.list.item>
|
||||
@endforeach
|
||||
</x-filament::dropdown.list>
|
||||
@endforeach
|
||||
</x-filament::dropdown>
|
||||
@else
|
||||
@foreach ($group->getItems() as $item)
|
||||
@php
|
||||
$isItemActive = $item->isActive();
|
||||
$itemActiveIcon = $item->getActiveIcon();
|
||||
$itemBadge = $item->getBadge();
|
||||
$itemBadgeColor = $item->getBadgeColor();
|
||||
$itemBadgeTooltip = $item->getBadgeTooltip();
|
||||
$itemIcon = $item->getIcon();
|
||||
$shouldItemOpenUrlInNewTab = $item->shouldOpenUrlInNewTab();
|
||||
$itemUrl = $item->getUrl();
|
||||
$itemExtraAttributes = $item->getExtraAttributeBag();
|
||||
@endphp
|
||||
|
||||
<x-filament-panels::topbar.item
|
||||
:active="$isItemActive"
|
||||
:active-icon="$itemActiveIcon"
|
||||
:badge="$itemBadge"
|
||||
:badge-color="$itemBadgeColor"
|
||||
:badge-tooltip="$itemBadgeTooltip"
|
||||
:icon="$itemIcon"
|
||||
:should-open-url-in-new-tab="$shouldItemOpenUrlInNewTab"
|
||||
:url="$itemUrl"
|
||||
:attributes="\Filament\Support\prepare_inherited_attributes($itemExtraAttributes)"
|
||||
>
|
||||
{{ $item->getLabel() }}
|
||||
</x-filament-panels::topbar.item>
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
<div
|
||||
@if ($hasTenancy)
|
||||
x-persist="topbar.end.panel-{{ filament()->getId() }}.tenant-{{ filament()->getTenant()?->getKey() }}"
|
||||
@else
|
||||
x-persist="topbar.end.panel-{{ filament()->getId() }}"
|
||||
@endif
|
||||
class="fi-topbar-end"
|
||||
>
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::GLOBAL_SEARCH_BEFORE) }}
|
||||
|
||||
@if (filament()->isGlobalSearchEnabled() && filament()->getGlobalSearchPosition() === \Filament\Enums\GlobalSearchPosition::Topbar)
|
||||
@livewire(Filament\Livewire\GlobalSearch::class)
|
||||
@endif
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::GLOBAL_SEARCH_AFTER) }}
|
||||
|
||||
@if (filament()->auth()->check())
|
||||
@if (filament()->hasDatabaseNotifications() && filament()->getDatabaseNotificationsPosition() === \Filament\Enums\DatabaseNotificationsPosition::Topbar)
|
||||
@livewire(filament()->getDatabaseNotificationsLivewireComponent(), [
|
||||
'lazy' => filament()->hasLazyLoadedDatabaseNotifications(),
|
||||
])
|
||||
@endif
|
||||
|
||||
@if (filament()->hasUserMenu() && filament()->getUserMenuPosition() === \Filament\Enums\UserMenuPosition::Topbar)
|
||||
<x-filament-panels::user-menu />
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_END) }}
|
||||
</nav>
|
||||
|
||||
<x-filament-actions::modals />
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<x-filament-panels::page>
|
||||
{{ $this->content }}
|
||||
</x-filament-panels::page>
|
||||
@@ -0,0 +1,3 @@
|
||||
<x-filament-panels::page.simple>
|
||||
{{ $this->content }}
|
||||
</x-filament-panels::page.simple>
|
||||
@@ -0,0 +1,5 @@
|
||||
<div class="fi-resource-relation-manager">
|
||||
{{ $this->content }}
|
||||
|
||||
<x-filament-panels::unsaved-action-changes-alert />
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
@php
|
||||
$user = filament()->auth()->user();
|
||||
@endphp
|
||||
|
||||
<x-filament-widgets::widget class="fi-account-widget">
|
||||
<x-filament::section>
|
||||
<x-filament-panels::avatar.user
|
||||
size="lg"
|
||||
:user="$user"
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
<div class="fi-account-widget-main">
|
||||
<h2 class="fi-account-widget-heading">
|
||||
{{ __('filament-panels::widgets/account-widget.welcome', ['app' => config('app.name')]) }}
|
||||
</h2>
|
||||
|
||||
<p class="fi-account-widget-user-name">
|
||||
{{ filament()->getUserName($user) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form
|
||||
action="{{ filament()->getLogoutUrl() }}"
|
||||
method="post"
|
||||
class="fi-account-widget-logout-form"
|
||||
>
|
||||
@csrf
|
||||
|
||||
<x-filament::button
|
||||
color="gray"
|
||||
:icon="\Filament\Support\Icons\Heroicon::ArrowLeftEndOnRectangle"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::WIDGETS_ACCOUNT_LOGOUT_BUTTON"
|
||||
labeled-from="sm"
|
||||
tag="button"
|
||||
type="submit"
|
||||
>
|
||||
{{ __('filament-panels::widgets/account-widget.actions.logout.label') }}
|
||||
</x-filament::button>
|
||||
</form>
|
||||
</x-filament::section>
|
||||
</x-filament-widgets::widget>
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
<x-filament-widgets::widget class="fi-filament-info-widget">
|
||||
<x-filament::section>
|
||||
<div class="fi-filament-info-widget-main">
|
||||
<a
|
||||
href="https://filamentphp.com"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<svg
|
||||
aria-label="Filament"
|
||||
fill="currentColor"
|
||||
role="img"
|
||||
viewBox="0 0 1988.74 399.55"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="fi-filament-info-widget-logo"
|
||||
>
|
||||
<path
|
||||
d="M115.85,138.9v-20.22c0-31.15,10.38-54.64,41.53-54.64h27.87V.1h-27.87C85.79.1,48.64,44.36,48.64,118.68v20.22H0v53.55h48.64v201.63h67.21v-201.63h82.19v-53.55h-82.19Z"
|
||||
/>
|
||||
<rect x="382.68" y=".11" width="66.67" height="393.98" />
|
||||
<path
|
||||
d="M628.22,335.07c-36.62,0-70.49-27.87-70.49-68.85s33.88-68.86,70.49-68.86,69.94,24.59,69.94,68.86-33.88,68.85-69.94,68.85M698.16,170.59c-18.57-28.42-56.28-37.16-79.23-37.16-67.21,0-130.06,50.82-130.06,132.79s62.84,132.79,130.06,132.79c25.14,0,62.84-11.48,79.23-37.71v32.79h66.67v-255.2h-66.67v31.7Z"
|
||||
/>
|
||||
<path
|
||||
d="M1116.15,133.44c-20.22,0-56.28,6.01-80.33,48.09-14.21-31.16-40.98-45.36-81.42-47.55-24.04,0-59.01,11.48-73.22,42.63v-37.7h-66.67v255.19h66.67v-136.07c0-43.71,26.23-59.56,53.55-59.56s46.45,19.68,47,55.19v140.44h66.66v-136.07c0-38.79,21.86-59.56,51.92-59.56,27.32,0,48.09,20.22,48.09,56.83v138.8h66.12v-145.9c0-74.87-36.61-114.75-98.36-114.75"
|
||||
/>
|
||||
<path
|
||||
d="M1314.33,243.27c4.92-34.43,32.23-54.1,67.21-54.1,32.78,0,59.01,19.12,63.93,54.1h-131.14ZM1380.99,133.44c-72.68,0-132.24,51.91-132.24,132.24s59.56,133.87,132.24,133.87c46.99,0,96.17-18.03,119.12-61.74-16.39-8.75-34.97-18.58-50.82-27.32-12.02,21.86-38.25,32.78-63.93,32.78-37.71,0-66.12-20.76-70.49-54.64h194.53c.55-6.01,1.09-16.4,1.09-22.95,0-80.33-56.83-132.24-129.51-132.24"
|
||||
/>
|
||||
<path
|
||||
d="M1698.38,133.44c-29.51,0-61.75,15.84-75.96,43.17v-37.7h-66.66v255.19h66.66v-136.07c0-44.26,25.69-59.56,55.74-59.56s48.64,19.68,48.64,56.83v138.8h66.66v-150.82c0-72.13-35.51-109.84-95.08-109.84"
|
||||
/>
|
||||
<polygon
|
||||
points="1868.52 41.64 1868.52 138.9 1822.07 138.9 1822.07 192.45 1868.52 192.45 1868.52 394.09 1934.64 394.09 1934.64 192.45 1988.74 192.45 1988.74 138.9 1934.64 138.9 1934.64 41.64 1868.52 41.64"
|
||||
/>
|
||||
<path
|
||||
d="M277.05,80.43c22.95,0,42.07-17.49,42.07-40.44S300,.11,277.05.11s-43.17,17.48-43.17,39.89,19.67,40.44,43.17,40.44"
|
||||
/>
|
||||
<path
|
||||
d="M323.62,164.94l-40.54-24.73,2.36-20.71-42.93,1.25.26,1.6c.38,2.33.06,5.14-.29,8.12-.71,6.12-1.52,13.07,4.08,17.83,1.93,1.64,8.35,5.31,15.14,9.19,4.29,2.45,9.81,5.6,12.53,7.37-1.73.58-4.17.44-6.56.31-1.56-.09-3.15-.19-4.59-.07l-2.06.14c-6.77.44-13.01.91-14.89,1.8-3.26,1.55-4.26,8.19-3.8,13.71.23,2.77,1.22,9.52,5.54,12.25l26.35,15.94-27.62,2.43-.53.15c-2.69,1.35-3.09,6.74-3.08,9.83,0,5.09,1.15,12.03,4.67,15.03l27.31,16.82c-1.02.02-2.05.06-3.07.08-8.85.23-18.02.46-26.14,2.81l-.44.22c-2.03,1.52-2.19,11.99-.76,17.93.85,3.58,2.3,5.87,4.09,6.72l26.38,15.93-26.59,2.44-.49.13c-5.61,2.66-3.51,17.42-2.07,21.75l.23.7,30.04,19.34-26.51,1.8c-1.81.09-2.69,1.08-3.38,1.99-2.17,2.88-2.03,13.55-1.59,29.49.23,7.83.43,15.22-.06,18.24l-.36,2.25h38.49l.21-23.88,45.27-4.62.38-.04.3-.21c1.94-1.39,2.28-6.6,2.3-9.58.02-2.34-.14-10.21-3-13.37l-28.81-18.02,28.71-2.66.31-.23c2.37-1.76,2.67-12.39,1.09-18.54-.98-3.82-2.63-6.25-4.65-7.1l-26.3-15.92c2.59-.14,5.31-.21,8.12-.28,6.36-.16,12.94-.33,18.45-1.47,1.94-.41,3.34-2.03,4.12-4.84,1.6-5.69.46-15.62-2.22-19.32-1.28-1.76-7.11-5.22-20.58-12.82-3.97-2.24-7.74-4.37-9.73-5.6,2.12-.09,4.84-.12,7.66-.14,11.65-.11,20.1-.36,22.78-2.58,2.23-1.86,2.89-12.01,1.22-18.4-.91-3.44-2.42-5.68-4.31-6.56l-26.32-15.92,26.83-2.23.53-.15c3.22-1.62,3.79-9.61,3.39-14.27-.27-3.21-1.26-8.94-4.89-11.31"
|
||||
/>
|
||||
<path
|
||||
d="M279.71,0c-23.51,0-43.2,17.5-43.2,39.92s19.69,40.46,43.2,40.46,42.11-17.5,42.11-40.46S302.68,0,279.71,0"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<p class="fi-filament-info-widget-version">
|
||||
{{ \Composer\InstalledVersions::getPrettyVersion('filament/filament') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="fi-filament-info-widget-links">
|
||||
<x-filament::link
|
||||
color="gray"
|
||||
href="https://filamentphp.com/docs"
|
||||
:icon="\Filament\Support\Icons\Heroicon::BookOpen"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::WIDGETS_FILAMENT_INFO_OPEN_DOCUMENTATION_BUTTON"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{{ __('filament-panels::widgets/filament-info-widget.actions.open_documentation.label') }}
|
||||
</x-filament::link>
|
||||
|
||||
<x-filament::link
|
||||
color="gray"
|
||||
href="https://github.com/filamentphp/filament"
|
||||
:icon-alias="\Filament\View\PanelsIconAlias::WIDGETS_FILAMENT_INFO_OPEN_GITHUB_BUTTON"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<x-slot name="icon">
|
||||
<svg viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
|
||||
/>
|
||||
</svg>
|
||||
</x-slot>
|
||||
|
||||
{{ __('filament-panels::widgets/filament-info-widget.actions.open_github.label') }}
|
||||
</x-filament::link>
|
||||
</div>
|
||||
</x-filament::section>
|
||||
</x-filament-widgets::widget>
|
||||
Reference in New Issue
Block a user