Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

panel-shift-dropdown.blade.php 7.6KB

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