242 lines
6.7 KiB
PHP
242 lines
6.7 KiB
PHP
@php
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
$sidebar = config('admin-sidebar');
|
|
$menuItems = [];
|
|
|
|
function extractRoutes($items, &$menuItems, $group = '') {
|
|
foreach ($items as $item) {
|
|
if (isset($item['type']) && $item['type'] === 'group' && isset($item['children'])) {
|
|
extractRoutes($item['children'], $menuItems, $item['title']);
|
|
} elseif (isset($item['route'])) {
|
|
$menuItems[] = [
|
|
'title' => $item['title'],
|
|
'route' => $item['route'],
|
|
'params' => $item['params'] ?? [],
|
|
'group' => $group,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
extractRoutes($sidebar, $menuItems);
|
|
|
|
$validMenuItems = collect($menuItems)->filter(fn($item) => Route::has($item['route']))->values();
|
|
@endphp
|
|
|
|
<div id="command-palette-container" style="display: none;">
|
|
<div class="command-palette-backdrop" id="cmdk-backdrop"></div>
|
|
<div class="command-palette-wrapper" id="cmdk-wrapper">
|
|
<div class="cmdk">
|
|
<input type="text" class="cmdk-input" placeholder="Search pages..." id="cmdk-input">
|
|
<div class="cmdk-list" id="cmdk-list">
|
|
@forelse($validMenuItems as $item)
|
|
<a href="{{ route($item['route'], $item['params']) }}"
|
|
class="cmdk-item"
|
|
data-value="{{ strtolower($item['title']) }}">
|
|
<span>{{ $item['title'] }}</span>
|
|
@if($item['group'])
|
|
<span class="cmdk-group">{{ $item['group'] }}</span>
|
|
@endif
|
|
</a>
|
|
@empty
|
|
<div class="cmdk-empty">No pages found</div>
|
|
@endforelse
|
|
<div class="cmdk-empty-state" id="cmdk-empty" style="display: none;">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-box"><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/></svg>
|
|
<span>No results found</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@push('custom-scripts')
|
|
<script>
|
|
(function() {
|
|
var container = document.getElementById('command-palette-container');
|
|
var backdrop = document.getElementById('cmdk-backdrop');
|
|
var wrapper = document.getElementById('cmdk-wrapper');
|
|
var input = document.getElementById('cmdk-input');
|
|
var searchInput = document.getElementById('navbarForm');
|
|
var cmdkItems = document.querySelectorAll('.cmdk-item');
|
|
var cmdkEmpty = document.getElementById('cmdk-empty');
|
|
var cmdkList = document.getElementById('cmdk-list');
|
|
|
|
function showPalette() {
|
|
container.style.display = 'block';
|
|
input.value = searchInput ? searchInput.value : '';
|
|
input.focus();
|
|
cmdkItems.forEach(function(item) {
|
|
item.style.display = '';
|
|
});
|
|
if (cmdkEmpty) cmdkEmpty.style.display = 'none';
|
|
}
|
|
|
|
function hidePalette() {
|
|
container.style.display = 'none';
|
|
if (searchInput) searchInput.blur();
|
|
}
|
|
|
|
function filterItems(query) {
|
|
var visibleCount = 0;
|
|
cmdkItems.forEach(function(item) {
|
|
var value = item.dataset.value || item.textContent.toLowerCase();
|
|
var matches = query === '' || value.includes(query);
|
|
item.style.display = matches ? '' : 'none';
|
|
if (matches) visibleCount++;
|
|
});
|
|
if (cmdkEmpty) {
|
|
cmdkEmpty.style.display = visibleCount === 0 ? 'flex' : 'none';
|
|
}
|
|
}
|
|
|
|
function hidePalette() {
|
|
container.style.display = 'none';
|
|
if (searchInput) searchInput.blur();
|
|
}
|
|
|
|
if (searchInput) {
|
|
searchInput.addEventListener('focus', showPalette);
|
|
searchInput.addEventListener('input', function(e) {
|
|
if (container.style.display === 'none') {
|
|
showPalette();
|
|
}
|
|
filterItems(e.target.value.toLowerCase());
|
|
});
|
|
}
|
|
|
|
input.addEventListener('input', function(e) {
|
|
filterItems(e.target.value.toLowerCase());
|
|
});
|
|
|
|
document.addEventListener('keydown', function(e) {
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
|
e.preventDefault();
|
|
showPalette();
|
|
}
|
|
if (e.key === 'Escape' && container.style.display === 'block') {
|
|
hidePalette();
|
|
}
|
|
});
|
|
|
|
if (backdrop) {
|
|
backdrop.addEventListener('click', hidePalette);
|
|
}
|
|
})();
|
|
</script>
|
|
|
|
<style>
|
|
#command-palette-container {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: 9999;
|
|
}
|
|
|
|
.command-palette-backdrop {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
.command-palette-wrapper {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%);
|
|
width: 100%;
|
|
max-width: 700px;
|
|
padding: 0 20px;
|
|
}
|
|
|
|
.cmdk {
|
|
background: var(--bs-body-bg, #fff);
|
|
border-radius: 12px;
|
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
overflow: hidden;
|
|
border: 1px solid var(--bs-border-color, #e2e8f0);
|
|
}
|
|
|
|
.cmdk-input {
|
|
width: 100%;
|
|
padding: 16px;
|
|
font-size: 1.125rem;
|
|
border: none;
|
|
border-bottom: 1px solid var(--bs-border-color, #e2e8f0);
|
|
background: transparent;
|
|
outline: none;
|
|
color: var(--bs-body-color, #1e293b);
|
|
}
|
|
|
|
.cmdk-list {
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
padding: 8px;
|
|
}
|
|
|
|
.cmdk-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 12px 16px;
|
|
border-radius: 8px;
|
|
text-decoration: none;
|
|
color: var(--bs-body-color, #1e293b);
|
|
cursor: pointer;
|
|
transition: background 0.15s;
|
|
}
|
|
|
|
.cmdk-item:hover {
|
|
background: var(--bs-tertiary-bg, #f1f5f9);
|
|
}
|
|
|
|
.cmdk-group {
|
|
font-size: 0.75rem;
|
|
color: var(--bs-secondary-color, #64748b);
|
|
}
|
|
|
|
.cmdk-empty {
|
|
padding: 24px;
|
|
text-align: center;
|
|
color: var(--bs-secondary-color, #64748b);
|
|
}
|
|
|
|
.cmdk-empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 32px;
|
|
color: var(--bs-secondary-color, #64748b);
|
|
}
|
|
|
|
.cmdk-empty-state svg {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
[data-bs-theme="dark"] .cmdk {
|
|
background: #1e293b;
|
|
border-color: #334155;
|
|
}
|
|
|
|
[data-bs-theme="dark"] .cmdk-input {
|
|
color: #f8fafc;
|
|
}
|
|
|
|
[data-bs-theme="dark"] .cmdk-item {
|
|
color: #f8fafc;
|
|
}
|
|
|
|
[data-bs-theme="dark"] .cmdk-item:hover {
|
|
background: #334155;
|
|
}
|
|
</style>
|
|
@endpush
|