您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

panel-shift-dropdown.blade.php 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. @php
  2. $items = filament()->getUserMenuItems();
  3. $logoutItem = $items['logout'] ?? null;
  4. $currentTenant = filament()->getTenant();
  5. $currentTenantName = $currentTenant ? filament()->getTenantName($currentTenant) : null;
  6. $navigation = $component->getNavigation();
  7. $hasDisplayAndAccessibility = $component->hasDisplayAndAccessibility();
  8. $hasCompanySettings = $component->hasCompanySettings();
  9. $hasLogoutItem = $component->hasLogoutItem();
  10. $panels = $component->getNavigationAsHierarchyArray();
  11. @endphp
  12. <div x-data="panelShiftDropdown" x-on:click.outside="closeDropdown">
  13. <div x-on:click="toggleDropdown" class="flex cursor-pointer">
  14. <button
  15. type="button"
  16. class="fi-tenant-menu-trigger group flex w-full items-center justify-center gap-x-3 rounded-lg p-2 text-sm font-medium outline-none transition duration-75 hover:bg-gray-100 focus-visible:bg-gray-100 dark:hover:bg-white/5 dark:focus-visible:bg-white/5"
  17. >
  18. <x-filament-panels::avatar.tenant
  19. :tenant="$currentTenant"
  20. class="shrink-0"
  21. />
  22. <span class="grid justify-items-start text-start">
  23. @if ($currentTenant instanceof \Filament\Models\Contracts\HasCurrentTenantLabel)
  24. <span class="text-xs text-gray-500 dark:text-gray-400">
  25. {{ $currentTenant->getCurrentTenantLabel() }}
  26. </span>
  27. @endif
  28. <span class="text-gray-950 dark:text-white">
  29. {{ $currentTenantName }}
  30. </span>
  31. </span>
  32. <x-filament::icon
  33. icon="heroicon-m-chevron-down"
  34. class="h-5 w-5 transition duration-75 text-gray-400 group-hover:text-gray-500 group-focus-visible:text-gray-500 dark:text-gray-500 dark:group-hover:text-gray-400 dark:group-focus-visible:text-gray-400"
  35. x-bind:class="{ 'rotate-180': open }"
  36. />
  37. </button>
  38. </div>
  39. <div x-show="open"
  40. class="flex flex-col transition duration-200 ease-in-out grow shrink mt-4 absolute z-10 w-screen max-w-[360px] end-8 rounded-lg bg-white shadow-lg ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10 overflow-hidden">
  41. @foreach($panels as $panelId => $panel)
  42. <x-panel-shift-dropdown.panel :panel-id="$panelId">
  43. @if($panelId !== 'main' && isset($panel['label']))
  44. <x-panel-shift-dropdown.subpanel-header :label="$panel['label']" :panel-id="$panelId"/>
  45. @endif
  46. @if($panel['renderItems'])
  47. @foreach($panel['items'] as $item)
  48. <x-panel-shift-dropdown.content-handler :item="$item"/>
  49. @endforeach
  50. @endif
  51. @if($panelId === 'company-settings')
  52. <x-panel-shift-dropdown.company-settings :current-tenant="$currentTenant"
  53. icon="heroicon-m-building-office-2"/>
  54. @endif
  55. @if($panelId === 'company-switcher')
  56. <x-panel-shift-dropdown.company-switcher :current-tenant="$currentTenant"
  57. icon="heroicon-m-adjustments-horizontal"/>
  58. @endif
  59. @if($panelId === 'display-and-accessibility')
  60. <x-panel-shift-dropdown.display-accessibility icon="heroicon-s-moon"/>
  61. @endif
  62. @if($panelId === 'main' && $hasLogoutItem)
  63. <x-panel-shift-dropdown.item
  64. tag="form"
  65. method="post"
  66. :action="$logoutItem?->getUrl() ?? filament()->getLogoutUrl()"
  67. :label="$logoutItem?->getLabel() ?? __('filament-panels::layout.actions.logout.label')"
  68. :icon="$logoutItem?->getIcon() ?? \Filament\Support\Facades\FilamentIcon::resolve('panels::user-menu.logout-button') ?? 'heroicon-m-arrow-left-on-rectangle'"
  69. />
  70. @endif
  71. </x-panel-shift-dropdown.panel>
  72. @endforeach
  73. </div>
  74. </div>
  75. <script>
  76. document.addEventListener('alpine:init', () => {
  77. Alpine.data('panelShiftDropdown', () => ({
  78. open: false,
  79. navigationStack: ['main'],
  80. theme: localStorage.getItem('theme') || '{{ filament()->getDefaultThemeMode()->value }}',
  81. themeLabels: {
  82. light: 'Off',
  83. dark: 'On',
  84. system: 'System',
  85. },
  86. toggleDropdown() {
  87. this.open = !this.open;
  88. },
  89. closeDropdown() {
  90. this.open = false;
  91. },
  92. setActiveMenu(menu) {
  93. this.transitionPanel(menu, 'forward');
  94. },
  95. focusMenuItem(menuItemRef) {
  96. this.$nextTick(() => {
  97. setTimeout(() => {
  98. this.$refs[menuItemRef]?.focus();
  99. }, 200);
  100. });
  101. },
  102. focusBackButton(backButtonRef) {
  103. this.$nextTick(() => {
  104. setTimeout(() => {
  105. this.$refs[backButtonRef]?.focus();
  106. }, 200);
  107. });
  108. },
  109. goBack() {
  110. if (this.open && this.navigationStack.length > 1) {
  111. this.transitionPanel(this.navigationStack.at(-2), 'back');
  112. }
  113. },
  114. currentActiveMenu() {
  115. return this.navigationStack.at(-1);
  116. },
  117. transitionPanel(target, direction) {
  118. const currentPanel = this.$refs[this.currentActiveMenu()];
  119. const targetPanel = this.$refs[target];
  120. const translateX = direction === 'forward' ? '-100%' : '100%';
  121. currentPanel.style.transform = `translateX(${translateX})`;
  122. setTimeout(() => {
  123. currentPanel.classList.add('hide');
  124. targetPanel.classList.remove('hide');
  125. targetPanel.style.transform = 'translateX(0)';
  126. if (direction === 'forward') {
  127. this.navigationStack.push(target);
  128. } else {
  129. this.navigationStack.pop();
  130. }
  131. }, 200);
  132. },
  133. setTheme(newTheme) {
  134. this.theme = newTheme;
  135. },
  136. init() {
  137. this.$watch('theme', (value) => {
  138. this.$dispatch('theme-changed', value);
  139. });
  140. this.$watch('open', (value) => {
  141. if (value) {
  142. if (this.navigationStack.length === 1) {
  143. const mainPanel = this.$refs.main;
  144. mainPanel.classList.remove('hide');
  145. mainPanel.style.transform = 'translateX(0)';
  146. }
  147. } else {
  148. if (this.currentActiveMenu() !== 'main') {
  149. this.setActiveMenu('main');
  150. }
  151. }
  152. });
  153. },
  154. getThemeLabel(value) {
  155. return this.themeLabels[value] || value;
  156. },
  157. }));
  158. });
  159. </script>