morphbox
Version:
Docker-based AI sandbox for development with Claude integration
407 lines (404 loc) • 39 kB
JavaScript
import { c as create_ssr_component, v as validate_component, o as onDestroy, d as add_attribute, e as escape, f as each, g as get_store_value } from './ssr-Bi8A3Ffq.js';
import { t as tick, p as panelStore } from './registry-kTtxA5oL.js';
import { d as derived, w as writable } from './index-6zo8caE3.js';
function fuzzyScore(query, text) {
if (!query) return 1;
const queryLower = query.toLowerCase();
const textLower = text.toLowerCase();
if (textLower === queryLower) return 100;
if (textLower.includes(queryLower)) return 80;
let score = 0;
let queryIndex = 0;
let lastMatchIndex = -1;
for (let i = 0; i < textLower.length && queryIndex < queryLower.length; i++) {
if (textLower[i] === queryLower[queryIndex]) {
score += 1;
if (i === lastMatchIndex + 1) {
score += 5;
}
if (i === 0 || textLower[i - 1] === " ") {
score += 10;
}
lastMatchIndex = i;
queryIndex++;
}
}
return queryIndex === queryLower.length ? score : 0;
}
function createCommandStore() {
const { subscribe, set, update } = writable({
commands: /* @__PURE__ */ new Map(),
recentCommands: [],
isVisible: false
});
const loadRecentCommands = () => {
try {
const saved = localStorage.getItem("command-palette-recent");
if (saved) {
const parsed = JSON.parse(saved);
return parsed.map((cmd) => ({
...cmd,
executedAt: new Date(cmd.executedAt)
}));
}
} catch (error) {
console.error("Failed to load recent commands:", error);
}
return [];
};
const saveRecentCommands = (recentCommands2) => {
try {
localStorage.setItem("command-palette-recent", JSON.stringify(recentCommands2));
} catch (error) {
console.error("Failed to save recent commands:", error);
}
};
return {
subscribe,
// Register a command
register: (command) => {
update((state) => {
state.commands.set(command.id, command);
return state;
});
},
// Unregister a command
unregister: (commandId) => {
update((state) => {
state.commands.delete(commandId);
return state;
});
},
// Search commands with fuzzy matching
search: (query) => {
const state = get_store_value({ subscribe });
const commands2 = Array.from(state.commands.values());
if (!query.trim()) {
const recentCommandIds = new Set(state.recentCommands.map((rc) => rc.commandId));
const recentCommands2 = commands2.filter((cmd) => recentCommandIds.has(cmd.id));
const otherCommands = commands2.filter((cmd) => !recentCommandIds.has(cmd.id));
recentCommands2.sort((a, b) => {
const aRecent = state.recentCommands.find((rc) => rc.commandId === a.id);
const bRecent = state.recentCommands.find((rc) => rc.commandId === b.id);
if (aRecent.count !== bRecent.count) {
return bRecent.count - aRecent.count;
}
return bRecent.executedAt.getTime() - aRecent.executedAt.getTime();
});
return [...recentCommands2, ...otherCommands];
}
const scoredCommands = commands2.map((command) => {
const titleScore = fuzzyScore(query, command.title);
const descScore = fuzzyScore(query, command.description);
const categoryScore = fuzzyScore(query, command.category);
const keywordScore = Math.max(...command.keywords.map((k) => fuzzyScore(query, k)), 0);
const maxScore = Math.max(titleScore, descScore, categoryScore, keywordScore);
return {
command,
score: maxScore
};
}).filter((item) => item.score > 0).sort((a, b) => {
if (a.score !== b.score) {
return b.score - a.score;
}
const aRecent = state.recentCommands.find((rc) => rc.commandId === a.command.id);
const bRecent = state.recentCommands.find((rc) => rc.commandId === b.command.id);
if (aRecent && !bRecent) return -1;
if (!aRecent && bRecent) return 1;
if (aRecent && bRecent) {
return bRecent.executedAt.getTime() - aRecent.executedAt.getTime();
}
return a.command.title.localeCompare(b.command.title);
});
return scoredCommands.map((item) => item.command);
},
// Execute a command
execute: async (commandId) => {
const state = get_store_value({ subscribe });
const command = state.commands.get(commandId);
if (!command || command.disabled) return;
try {
await command.action();
update((currentState) => {
const now = /* @__PURE__ */ new Date();
const existingIndex = currentState.recentCommands.findIndex((rc) => rc.commandId === commandId);
if (existingIndex >= 0) {
currentState.recentCommands[existingIndex].executedAt = now;
currentState.recentCommands[existingIndex].count += 1;
} else {
currentState.recentCommands.push({
commandId,
executedAt: now,
count: 1
});
}
currentState.recentCommands.sort((a, b) => b.executedAt.getTime() - a.executedAt.getTime());
if (currentState.recentCommands.length > 50) {
currentState.recentCommands = currentState.recentCommands.slice(0, 50);
}
saveRecentCommands(currentState.recentCommands);
return currentState;
});
} catch (error) {
console.error(`Failed to execute command ${commandId}:`, error);
}
},
// Show/hide command palette
show: () => {
update((state) => ({ ...state, isVisible: true }));
},
hide: () => {
update((state) => ({ ...state, isVisible: false }));
},
toggle: () => {
update((state) => ({ ...state, isVisible: !state.isVisible }));
},
// Clear recent commands
clearRecentCommands: () => {
update((state) => {
state.recentCommands = [];
saveRecentCommands([]);
return state;
});
},
// Initialize with default commands
initializeDefaults: () => {
const defaultCommands = [
// Panel management commands
{
id: "panel.create.terminal",
title: "Create Terminal Panel",
description: "Create a new terminal panel",
category: "Panel",
keywords: ["terminal", "console", "shell", "create", "new"],
action: () => panelStore.addPanel("terminal"),
icon: "💻"
},
{
id: "panel.create.fileExplorer",
title: "Create File Explorer Panel",
description: "Create a new file explorer panel",
category: "Panel",
keywords: ["file", "explorer", "browser", "create", "new"],
action: () => panelStore.addPanel("fileExplorer"),
icon: "📁"
},
{
id: "panel.create.editor",
title: "Create Code Editor Panel",
description: "Create a new code editor panel",
category: "Panel",
keywords: ["editor", "code", "text", "create", "new"],
action: () => panelStore.addPanel("editor"),
icon: "📝"
},
{
id: "panel.create.settings",
title: "Create Settings Panel",
description: "Create a new settings panel",
category: "Panel",
keywords: ["settings", "preferences", "config", "create", "new"],
action: () => panelStore.addPanel("settings"),
icon: "⚙️"
},
{
id: "panel.closeAll",
title: "Close All Panels",
description: "Close all non-persistent panels",
category: "Panel",
keywords: ["close", "all", "panels", "clear"],
action: () => panelStore.clearPanels(),
icon: "❌"
},
// Layout commands
{
id: "layout.floating",
title: "Set Floating Layout",
description: "Set panel layout to floating mode",
category: "Layout",
keywords: ["layout", "floating", "free", "mode"],
action: () => panelStore.setLayout("floating"),
icon: "🪟"
},
{
id: "layout.grid",
title: "Set Grid Layout",
description: "Set panel layout to grid mode",
category: "Layout",
keywords: ["layout", "grid", "organized", "mode"],
action: () => panelStore.setLayout("grid"),
icon: "⊞"
},
{
id: "layout.split",
title: "Set Split Layout",
description: "Set panel layout to split mode",
category: "Layout",
keywords: ["layout", "split", "pane", "mode"],
action: () => panelStore.setLayout("split"),
icon: "⊟"
},
{
id: "layout.tabs",
title: "Set Tab Layout",
description: "Set panel layout to tabs mode",
category: "Layout",
keywords: ["layout", "tabs", "tabbed", "mode"],
action: () => panelStore.setLayout("tabs"),
icon: "📑"
},
// Configuration commands
{
id: "config.save",
title: "Save Configuration",
description: "Save current panel configuration",
category: "Configuration",
keywords: ["save", "config", "configuration", "persist"],
action: () => panelStore.saveConfiguration(),
icon: "💾"
},
{
id: "config.load",
title: "Load Configuration",
description: "Load saved panel configuration",
category: "Configuration",
keywords: ["load", "config", "configuration", "restore"],
action: () => panelStore.loadConfiguration(),
icon: "📥"
},
{
id: "config.clear",
title: "Clear Panel State",
description: "Clear all panels and reset to default terminal",
category: "Configuration",
keywords: ["clear", "reset", "panels", "state", "default"],
action: () => panelStore.clearState(),
icon: "🔄"
},
// Help commands
{
id: "help.commands",
title: "Show All Commands",
description: "Display all available commands",
category: "Help",
keywords: ["help", "commands", "list", "show"],
action: () => console.log("All commands displayed in palette"),
icon: "❓"
},
{
id: "help.shortcuts",
title: "Show Keyboard Shortcuts",
description: "Display keyboard shortcuts reference",
category: "Help",
keywords: ["help", "shortcuts", "keyboard", "hotkeys"],
action: () => alert("Ctrl+Shift+P: Open Command Palette\nEsc: Close Command Palette\nArrow Keys: Navigate\nEnter: Execute"),
icon: "⌨️"
}
];
defaultCommands.forEach((command) => {
update((state) => {
state.commands.set(command.id, command);
return state;
});
});
update((state) => {
state.recentCommands = loadRecentCommands();
return state;
});
}
};
}
const commands = createCommandStore();
derived(
commands,
($commands) => Array.from($commands.commands.values()).filter((cmd) => !cmd.disabled)
);
derived(
commands,
($commands) => {
const grouped = {};
Array.from($commands.commands.values()).forEach((command) => {
if (!grouped[command.category]) grouped[command.category] = [];
grouped[command.category].push(command);
});
return grouped;
}
);
derived(
commands,
($commands) => $commands.recentCommands
);
const isCommandPaletteVisible = derived(
commands,
($commands) => $commands.isVisible
);
if (typeof window !== "undefined") {
commands.initializeDefaults();
}
const css = {
code: ".command-palette-overlay.svelte-lc0xhx{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0, 0, 0, 0.5);backdrop-filter:blur(4px);display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;z-index:9999;animation:svelte-lc0xhx-fadeIn 0.15s ease-out}.command-palette-modal.svelte-lc0xhx{background:white;border-radius:12px;box-shadow:0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04),\n 0 0 0 1px rgba(0, 0, 0, 0.05);width:90%;max-width:640px;max-height:70vh;display:flex;flex-direction:column;animation:svelte-lc0xhx-slideDown 0.15s ease-out;overflow:hidden}@media(prefers-color-scheme: dark){.command-palette-modal.svelte-lc0xhx{background:#1f2937;color:#f9fafb;box-shadow:0 20px 25px -5px rgba(0, 0, 0, 0.3),\n 0 10px 10px -5px rgba(0, 0, 0, 0.2),\n 0 0 0 1px rgba(255, 255, 255, 0.1)}}.search-container.svelte-lc0xhx{display:flex;align-items:center;padding:16px;border-bottom:1px solid #e5e7eb;position:relative}@media(prefers-color-scheme: dark){.search-container.svelte-lc0xhx{border-bottom-color:#374151}}.search-icon.svelte-lc0xhx{color:#6b7280;margin-right:12px;flex-shrink:0}.search-input.svelte-lc0xhx{flex:1;border:none;outline:none;font-size:16px;background:transparent;color:inherit}.search-input.svelte-lc0xhx::placeholder{color:#9ca3af}.shortcut-hint.svelte-lc0xhx{color:#6b7280;font-size:12px;margin-left:12px;flex-shrink:0}.command-results.svelte-lc0xhx{flex:1;overflow-y:auto;min-height:0}.no-results.svelte-lc0xhx{padding:32px;text-align:center;color:#6b7280;font-style:italic}.results-list.svelte-lc0xhx{padding:8px 0}.command-item.svelte-lc0xhx{width:100%;text-align:left;border:none;background:none;padding:12px 16px;cursor:pointer;transition:background-color 0.1s ease;display:block;color:inherit}.command-item.svelte-lc0xhx:hover,.command-item.selected.svelte-lc0xhx{background:#f3f4f6}@media(prefers-color-scheme: dark){.command-item.svelte-lc0xhx:hover,.command-item.selected.svelte-lc0xhx{background:#374151}}.command-item.svelte-lc0xhx:disabled{opacity:0.5;cursor:not-allowed}.command-content.svelte-lc0xhx{width:100%}.command-main.svelte-lc0xhx{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px}.command-icon-title.svelte-lc0xhx{display:flex;align-items:center;gap:8px}.command-icon.svelte-lc0xhx{font-size:16px;line-height:1}.command-title.svelte-lc0xhx{font-weight:500;font-size:14px}.command-shortcut.svelte-lc0xhx{font-size:12px;color:#6b7280;font-family:monospace;background:#f3f4f6;padding:2px 6px;border-radius:4px}@media(prefers-color-scheme: dark){.command-shortcut.svelte-lc0xhx{background:#4b5563;color:#d1d5db}}.command-meta.svelte-lc0xhx{display:flex;align-items:center;justify-content:space-between;font-size:12px}.command-description.svelte-lc0xhx{color:#6b7280;flex:1;margin-right:8px}.command-category.svelte-lc0xhx{font-weight:500;font-size:11px;text-transform:uppercase;letter-spacing:0.5px;opacity:0.8}.command-footer.svelte-lc0xhx{padding:12px 16px;border-top:1px solid #e5e7eb;background:#f9fafb}@media(prefers-color-scheme: dark){.command-footer.svelte-lc0xhx{border-top-color:#374151;background:#111827}}.navigation-hints.svelte-lc0xhx{display:flex;gap:16px;font-size:11px;color:#6b7280}kbd.svelte-lc0xhx{background:#e5e7eb;border:1px solid #d1d5db;border-radius:3px;padding:1px 4px;font-size:10px;font-family:monospace;margin:0 1px}@media(prefers-color-scheme: dark){kbd.svelte-lc0xhx{background:#374151;border-color:#4b5563;color:#d1d5db}}.command-palette-modal mark{background:#fef3c7;color:#92400e;padding:0 2px;border-radius:2px}@media(prefers-color-scheme: dark){.command-palette-modal mark{background:#451a03;color:#fbbf24}}@keyframes svelte-lc0xhx-fadeIn{from{opacity:0}to{opacity:1}}@keyframes svelte-lc0xhx-slideDown{from{opacity:0;transform:translateY(-20px) scale(0.95)}to{opacity:1;transform:translateY(0) scale(1)}}.command-results.svelte-lc0xhx::-webkit-scrollbar{width:6px}.command-results.svelte-lc0xhx::-webkit-scrollbar-track{background:transparent}.command-results.svelte-lc0xhx::-webkit-scrollbar-thumb{background:#d1d5db;border-radius:3px}@media(prefers-color-scheme: dark){.command-results.svelte-lc0xhx::-webkit-scrollbar-thumb{background:#4b5563}}.command-results.svelte-lc0xhx::-webkit-scrollbar-thumb:hover{background:#9ca3af}@media(prefers-color-scheme: dark){.command-results.svelte-lc0xhx::-webkit-scrollbar-thumb:hover{background:#6b7280}}",
map: '{"version":3,"file":"CommandPalette.svelte","sources":["CommandPalette.svelte"],"sourcesContent":["<script lang=\\"ts\\">import { onMount, onDestroy, tick } from \\"svelte\\";\\nimport { commands, isCommandPaletteVisible } from \\"$lib/stores/commands\\";\\nimport { clickOutside } from \\"$lib/components/actions/clickOutside\\";\\nlet searchQuery = \\"\\";\\nlet searchInput;\\nlet commandResults = [];\\nlet selectedIndex = 0;\\nlet isVisible = false;\\nconst unsubscribeVisible = isCommandPaletteVisible.subscribe((visible) => {\\n isVisible = visible;\\n if (visible) {\\n searchQuery = \\"\\";\\n selectedIndex = 0;\\n searchCommands();\\n tick().then(() => {\\n searchInput?.focus();\\n });\\n }\\n});\\nfunction handleGlobalKeydown(event) {\\n if ((event.ctrlKey || event.metaKey) && event.shiftKey && event.key === \\"P\\") {\\n event.preventDefault();\\n commands.toggle();\\n }\\n}\\nfunction handleKeydown(event) {\\n if (!isVisible) return;\\n switch (event.key) {\\n case \\"Escape\\":\\n event.preventDefault();\\n commands.hide();\\n break;\\n case \\"ArrowDown\\":\\n event.preventDefault();\\n selectedIndex = Math.min(selectedIndex + 1, commandResults.length - 1);\\n scrollToSelected();\\n break;\\n case \\"ArrowUp\\":\\n event.preventDefault();\\n selectedIndex = Math.max(selectedIndex - 1, 0);\\n scrollToSelected();\\n break;\\n case \\"Enter\\":\\n event.preventDefault();\\n if (commandResults[selectedIndex]) {\\n executeCommand(commandResults[selectedIndex]);\\n }\\n break;\\n case \\"Tab\\":\\n event.preventDefault();\\n break;\\n }\\n}\\nfunction searchCommands() {\\n commandResults = commands.search(searchQuery);\\n selectedIndex = Math.min(selectedIndex, Math.max(0, commandResults.length - 1));\\n}\\nasync function executeCommand(command) {\\n commands.hide();\\n await commands.execute(command.id);\\n}\\nfunction scrollToSelected() {\\n tick().then(() => {\\n const selectedElement = document.querySelector(\\".command-item.selected\\");\\n if (selectedElement) {\\n selectedElement.scrollIntoView({ block: \\"nearest\\", behavior: \\"smooth\\" });\\n }\\n });\\n}\\nfunction handleClickOutside() {\\n commands.hide();\\n}\\nfunction handleMouseEnter(index) {\\n selectedIndex = index;\\n}\\nfunction formatShortcut(shortcut) {\\n if (!shortcut) return \\"\\";\\n return shortcut.replace(/Ctrl/g, \\"\\\\u2303\\").replace(/Cmd/g, \\"\\\\u2318\\").replace(/Alt/g, \\"\\\\u2325\\").replace(/Shift/g, \\"\\\\u21E7\\").replace(/\\\\+/g, \\" \\");\\n}\\nfunction getCategoryColor(category) {\\n const colors = {\\n \\"Panel\\": \\"rgb(59, 130, 246)\\",\\n // blue\\n \\"Layout\\": \\"rgb(34, 197, 94)\\",\\n // green\\n \\"Configuration\\": \\"rgb(168, 85, 247)\\",\\n // purple\\n \\"Help\\": \\"rgb(251, 146, 60)\\",\\n // orange\\n \\"File\\": \\"rgb(236, 72, 153)\\",\\n // pink\\n \\"Navigation\\": \\"rgb(14, 165, 233)\\"\\n // sky\\n };\\n return colors[category] || \\"rgb(107, 114, 128)\\";\\n}\\nfunction highlightMatch(text, query) {\\n if (!query.trim()) return text;\\n const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\\\\]\\\\\\\\]/g, \\"\\\\\\\\$&\\")})`, \\"gi\\");\\n return text.replace(regex, \\"<mark>$1</mark>\\");\\n}\\nonMount(() => {\\n document.addEventListener(\\"keydown\\", handleGlobalKeydown);\\n document.addEventListener(\\"keydown\\", handleKeydown);\\n return () => {\\n document.removeEventListener(\\"keydown\\", handleGlobalKeydown);\\n document.removeEventListener(\\"keydown\\", handleKeydown);\\n };\\n});\\nonDestroy(() => {\\n unsubscribeVisible();\\n});\\n$: if (searchQuery !== void 0) {\\n searchCommands();\\n}\\n<\/script>\\n\\n<!-- Command Palette Modal -->\\n{#if isVisible}\\n <div class=\\"command-palette-overlay\\" role=\\"dialog\\" aria-modal=\\"true\\" aria-label=\\"Command Palette\\">\\n <div \\n class=\\"command-palette-modal\\"\\n use:clickOutside={handleClickOutside}\\n >\\n <!-- Search Input -->\\n <div class=\\"search-container\\">\\n <div class=\\"search-icon\\">\\n <svg width=\\"16\\" height=\\"16\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"currentColor\\" stroke-width=\\"2\\">\\n <circle cx=\\"11\\" cy=\\"11\\" r=\\"8\\"></circle>\\n <path d=\\"m21 21-4.35-4.35\\"></path>\\n </svg>\\n </div>\\n <input\\n bind:this={searchInput}\\n bind:value={searchQuery}\\n placeholder=\\"Type a command or search...\\"\\n class=\\"search-input\\"\\n type=\\"text\\"\\n autocomplete=\\"off\\"\\n spellcheck=\\"false\\"\\n />\\n <div class=\\"shortcut-hint\\">\\n <kbd>Esc</kbd> to close\\n </div>\\n </div>\\n\\n <!-- Command Results -->\\n <div class=\\"command-results\\">\\n {#if commandResults.length === 0}\\n <div class=\\"no-results\\">\\n {#if searchQuery.trim()}\\n No commands found for \\"<em>{searchQuery}</em>\\"\\n {:else}\\n No commands available\\n {/if}\\n </div>\\n {:else}\\n <div class=\\"results-list\\">\\n {#each commandResults as command, index}\\n <button\\n class=\\"command-item {index === selectedIndex ? \'selected\' : \'\'}\\"\\n on:click={() => executeCommand(command)}\\n on:mouseenter={() => handleMouseEnter(index)}\\n disabled={command.disabled}\\n >\\n <div class=\\"command-content\\">\\n <div class=\\"command-main\\">\\n <div class=\\"command-icon-title\\">\\n {#if command.icon}\\n <span class=\\"command-icon\\">{command.icon}</span>\\n {/if}\\n <span class=\\"command-title\\">\\n {@html highlightMatch(command.title, searchQuery)}\\n </span>\\n </div>\\n {#if command.shortcut}\\n <span class=\\"command-shortcut\\">{formatShortcut(command.shortcut)}</span>\\n {/if}\\n </div>\\n <div class=\\"command-meta\\">\\n <span class=\\"command-description\\">\\n {@html highlightMatch(command.description, searchQuery)}\\n </span>\\n <span \\n class=\\"command-category\\"\\n style=\\"color: {getCategoryColor(command.category)}\\"\\n >\\n {command.category}\\n </span>\\n </div>\\n </div>\\n </button>\\n {/each}\\n </div>\\n {/if}\\n </div>\\n\\n <!-- Footer -->\\n <div class=\\"command-footer\\">\\n <div class=\\"navigation-hints\\">\\n <span><kbd>↑</kbd><kbd>↓</kbd> to navigate</span>\\n <span><kbd>Enter</kbd> to execute</span>\\n <span><kbd>Esc</kbd> to close</span>\\n </div>\\n </div>\\n </div>\\n </div>\\n{/if}\\n\\n<style>\\n .command-palette-overlay {\\n position: fixed;\\n top: 0;\\n left: 0;\\n right: 0;\\n bottom: 0;\\n background: rgba(0, 0, 0, 0.5);\\n backdrop-filter: blur(4px);\\n display: flex;\\n align-items: flex-start;\\n justify-content: center;\\n padding-top: 10vh;\\n z-index: 9999;\\n animation: fadeIn 0.15s ease-out;\\n }\\n\\n .command-palette-modal {\\n background: white;\\n border-radius: 12px;\\n box-shadow: \\n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\\n 0 10px 10px -5px rgba(0, 0, 0, 0.04),\\n 0 0 0 1px rgba(0, 0, 0, 0.05);\\n width: 90%;\\n max-width: 640px;\\n max-height: 70vh;\\n display: flex;\\n flex-direction: column;\\n animation: slideDown 0.15s ease-out;\\n overflow: hidden;\\n }\\n\\n /* Dark theme support */\\n @media (prefers-color-scheme: dark) {\\n .command-palette-modal {\\n background: #1f2937;\\n color: #f9fafb;\\n box-shadow: \\n 0 20px 25px -5px rgba(0, 0, 0, 0.3),\\n 0 10px 10px -5px rgba(0, 0, 0, 0.2),\\n 0 0 0 1px rgba(255, 255, 255, 0.1);\\n }\\n }\\n\\n .search-container {\\n display: flex;\\n align-items: center;\\n padding: 16px;\\n border-bottom: 1px solid #e5e7eb;\\n position: relative;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n .search-container {\\n border-bottom-color: #374151;\\n }\\n }\\n\\n .search-icon {\\n color: #6b7280;\\n margin-right: 12px;\\n flex-shrink: 0;\\n }\\n\\n .search-input {\\n flex: 1;\\n border: none;\\n outline: none;\\n font-size: 16px;\\n background: transparent;\\n color: inherit;\\n }\\n\\n .search-input::placeholder {\\n color: #9ca3af;\\n }\\n\\n .shortcut-hint {\\n color: #6b7280;\\n font-size: 12px;\\n margin-left: 12px;\\n flex-shrink: 0;\\n }\\n\\n .command-results {\\n flex: 1;\\n overflow-y: auto;\\n min-height: 0;\\n }\\n\\n .no-results {\\n padding: 32px;\\n text-align: center;\\n color: #6b7280;\\n font-style: italic;\\n }\\n\\n .results-list {\\n padding: 8px 0;\\n }\\n\\n .command-item {\\n width: 100%;\\n text-align: left;\\n border: none;\\n background: none;\\n padding: 12px 16px;\\n cursor: pointer;\\n transition: background-color 0.1s ease;\\n display: block;\\n color: inherit;\\n }\\n\\n .command-item:hover,\\n .command-item.selected {\\n background: #f3f4f6;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n .command-item:hover,\\n .command-item.selected {\\n background: #374151;\\n }\\n }\\n\\n .command-item:disabled {\\n opacity: 0.5;\\n cursor: not-allowed;\\n }\\n\\n .command-content {\\n width: 100%;\\n }\\n\\n .command-main {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n margin-bottom: 4px;\\n }\\n\\n .command-icon-title {\\n display: flex;\\n align-items: center;\\n gap: 8px;\\n }\\n\\n .command-icon {\\n font-size: 16px;\\n line-height: 1;\\n }\\n\\n .command-title {\\n font-weight: 500;\\n font-size: 14px;\\n }\\n\\n .command-shortcut {\\n font-size: 12px;\\n color: #6b7280;\\n font-family: monospace;\\n background: #f3f4f6;\\n padding: 2px 6px;\\n border-radius: 4px;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n .command-shortcut {\\n background: #4b5563;\\n color: #d1d5db;\\n }\\n }\\n\\n .command-meta {\\n display: flex;\\n align-items: center;\\n justify-content: space-between;\\n font-size: 12px;\\n }\\n\\n .command-description {\\n color: #6b7280;\\n flex: 1;\\n margin-right: 8px;\\n }\\n\\n .command-category {\\n font-weight: 500;\\n font-size: 11px;\\n text-transform: uppercase;\\n letter-spacing: 0.5px;\\n opacity: 0.8;\\n }\\n\\n .command-footer {\\n padding: 12px 16px;\\n border-top: 1px solid #e5e7eb;\\n background: #f9fafb;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n .command-footer {\\n border-top-color: #374151;\\n background: #111827;\\n }\\n }\\n\\n .navigation-hints {\\n display: flex;\\n gap: 16px;\\n font-size: 11px;\\n color: #6b7280;\\n }\\n\\n kbd {\\n background: #e5e7eb;\\n border: 1px solid #d1d5db;\\n border-radius: 3px;\\n padding: 1px 4px;\\n font-size: 10px;\\n font-family: monospace;\\n margin: 0 1px;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n kbd {\\n background: #374151;\\n border-color: #4b5563;\\n color: #d1d5db;\\n }\\n }\\n\\n /* Highlight marks in search results */\\n :global(.command-palette-modal mark) {\\n background: #fef3c7;\\n color: #92400e;\\n padding: 0 2px;\\n border-radius: 2px;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n :global(.command-palette-modal mark) {\\n background: #451a03;\\n color: #fbbf24;\\n }\\n }\\n\\n /* Animations */\\n @keyframes fadeIn {\\n from {\\n opacity: 0;\\n }\\n to {\\n opacity: 1;\\n }\\n }\\n\\n @keyframes slideDown {\\n from {\\n opacity: 0;\\n transform: translateY(-20px) scale(0.95);\\n }\\n to {\\n opacity: 1;\\n transform: translateY(0) scale(1);\\n }\\n }\\n\\n /* Scrollbar styling */\\n .command-results::-webkit-scrollbar {\\n width: 6px;\\n }\\n\\n .command-results::-webkit-scrollbar-track {\\n background: transparent;\\n }\\n\\n .command-results::-webkit-scrollbar-thumb {\\n background: #d1d5db;\\n border-radius: 3px;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n .command-results::-webkit-scrollbar-thumb {\\n background: #4b5563;\\n }\\n }\\n\\n .command-results::-webkit-scrollbar-thumb:hover {\\n background: #9ca3af;\\n }\\n\\n @media (prefers-color-scheme: dark) {\\n .command-results::-webkit-scrollbar-thumb:hover {\\n background: #6b7280;\\n }\\n }\\n</style>"],"names":[],"mappings":"AAkNE,sCAAyB,CACvB,QAAQ,CAAE,KAAK,CACf,GAAG,CAAE,CAAC,CACN,IAAI,CAAE,CAAC,CACP,KAAK,CAAE,CAAC,CACR,MAAM,CAAE,CAAC,CACT,UAAU,CAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAC9B,eAAe,CAAE,KAAK,GAAG,CAAC,CAC1B,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,UAAU,CACvB,eAAe,CAAE,MAAM,CACvB,WAAW,CAAE,IAAI,CACjB,OAAO,CAAE,IAAI,CACb,SAAS,CAAE,oBAAM,CAAC,KAAK,CAAC,QAC1B,CAEA,oCAAuB,CACrB,UAAU,CAAE,KAAK,CACjB,aAAa,CAAE,IAAI,CACnB,UAAU,CACR,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACzC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAC/B,KAAK,CAAE,GAAG,CACV,SAAS,CAAE,KAAK,CAChB,UAAU,CAAE,IAAI,CAChB,OAAO,CAAE,IAAI,CACb,cAAc,CAAE,MAAM,CACtB,SAAS,CAAE,uBAAS,CAAC,KAAK,CAAC,QAAQ,CACnC,QAAQ,CAAE,MACZ,CAGA,MAAO,uBAAuB,IAAI,CAAE,CAClC,oCAAuB,CACrB,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,OAAO,CACd,UAAU,CACR,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC3C,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CACrC,CACF,CAEA,+BAAkB,CAChB,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,MAAM,CACnB,OAAO,CAAE,IAAI,CACb,aAAa,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAChC,QAAQ,CAAE,QACZ,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,+BAAkB,CAChB,mBAAmB,CAAE,OACvB,CACF,CAEA,0BAAa,CACX,KAAK,CAAE,OAAO,CACd,YAAY,CAAE,IAAI,CAClB,WAAW,CAAE,CACf,CAEA,2BAAc,CACZ,IAAI,CAAE,CAAC,CACP,MAAM,CAAE,IAAI,CACZ,OAAO,CAAE,IAAI,CACb,SAAS,CAAE,IAAI,CACf,UAAU,CAAE,WAAW,CACvB,KAAK,CAAE,OACT,CAEA,2BAAa,aAAc,CACzB,KAAK,CAAE,OACT,CAEA,4BAAe,CACb,KAAK,CAAE,OAAO,CACd,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,IAAI,CACjB,WAAW,CAAE,CACf,CAEA,8BAAiB,CACf,IAAI,CAAE,CAAC,CACP,UAAU,CAAE,IAAI,CAChB,UAAU,CAAE,CACd,CAEA,yBAAY,CACV,OAAO,CAAE,IAAI,CACb,UAAU,CAAE,MAAM,CAClB,KAAK,CAAE,OAAO,CACd,UAAU,CAAE,MACd,CAEA,2BAAc,CACZ,OAAO,CAAE,GAAG,CAAC,CACf,CAEA,2BAAc,CACZ,KAAK,CAAE,IAAI,CACX,UAAU,CAAE,IAAI,CAChB,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,IAAI,CAChB,OAAO,CAAE,IAAI,CAAC,IAAI,CAClB,MAAM,CAAE,OAAO,CACf,UAAU,CAAE,gBAAgB,CAAC,IAAI,CAAC,IAAI,CACtC,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,OACT,CAEA,2BAAa,MAAM,CACnB,aAAa,uBAAU,CACrB,UAAU,CAAE,OACd,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,2BAAa,MAAM,CACnB,aAAa,uBAAU,CACrB,UAAU,CAAE,OACd,CACF,CAEA,2BAAa,SAAU,CACrB,OAAO,CAAE,GAAG,CACZ,MAAM,CAAE,WACV,CAEA,8BAAiB,CACf,KAAK,CAAE,IACT,CAEA,2BAAc,CACZ,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,MAAM,CACnB,eAAe,CAAE,aAAa,CAC9B,aAAa,CAAE,GACjB,CAEA,iCAAoB,CAClB,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,MAAM,CACnB,GAAG,CAAE,GACP,CAEA,2BAAc,CACZ,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,CACf,CAEA,4BAAe,CACb,WAAW,CAAE,GAAG,CAChB,SAAS,CAAE,IACb,CAEA,+BAAkB,CAChB,SAAS,CAAE,IAAI,CACf,KAAK,CAAE,OAAO,CACd,WAAW,CAAE,SAAS,CACtB,UAAU,CAAE,OAAO,CACnB,OAAO,CAAE,GAAG,CAAC,GAAG,CAChB,aAAa,CAAE,GACjB,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,+BAAkB,CAChB,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,OACT,CACF,CAEA,2BAAc,CACZ,OAAO,CAAE,IAAI,CACb,WAAW,CAAE,MAAM,CACnB,eAAe,CAAE,aAAa,CAC9B,SAAS,CAAE,IACb,CAEA,kCAAqB,CACnB,KAAK,CAAE,OAAO,CACd,IAAI,CAAE,CAAC,CACP,YAAY,CAAE,GAChB,CAEA,+BAAkB,CAChB,WAAW,CAAE,GAAG,CAChB,SAAS,CAAE,IAAI,CACf,cAAc,CAAE,SAAS,CACzB,cAAc,CAAE,KAAK,CACrB,OAAO,CAAE,GACX,CAEA,6BAAgB,CACd,OAAO,CAAE,IAAI,CAAC,IAAI,CAClB,UAAU,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAC7B,UAAU,CAAE,OACd,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,6BAAgB,CACd,gBAAgB,CAAE,OAAO,CACzB,UAAU,CAAE,OACd,CACF,CAEA,+BAAkB,CAChB,OAAO,CAAE,IAAI,CACb,GAAG,CAAE,IAAI,CACT,SAAS,CAAE,IAAI,CACf,KAAK,CAAE,OACT,CAEA,iBAAI,CACF,UAAU,CAAE,OAAO,CACnB,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CACzB,aAAa,CAAE,GAAG,CAClB,OAAO,CAAE,GAAG,CAAC,GAAG,CAChB,SAAS,CAAE,IAAI,CACf,WAAW,CAAE,SAAS,CACtB,MAAM,CAAE,CAAC,CAAC,GACZ,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,iBAAI,CACF,UAAU,CAAE,OAAO,CACnB,YAAY,CAAE,OAAO,CACrB,KAAK,CAAE,OACT,CACF,CAGQ,2BAA6B,CACnC,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,OAAO,CACd,OAAO,CAAE,CAAC,CAAC,GAAG,CACd,aAAa,CAAE,GACjB,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAC1B,2BAA6B,CACnC,UAAU,CAAE,OAAO,CACnB,KAAK,CAAE,OACT,CACF,CAGA,WAAW,oBAAO,CAChB,IAAK,CACH,OAAO,CAAE,CACX,CACA,EAAG,CACD,OAAO,CAAE,CACX,CACF,CAEA,WAAW,uBAAU,CACnB,IAAK,CACH,OAAO,CAAE,CAAC,CACV,SAAS,CAAE,WAAW,KAAK,CAAC,CAAC,MAAM,IAAI,CACzC,CACA,EAAG,CACD,OAAO,CAAE,CAAC,CACV,SAAS,CAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAClC,CACF,CAGA,8BAAgB,mBAAoB,CAClC,KAAK,CAAE,GACT,CAEA,8BAAgB,yBAA0B,CACxC,UAAU,CAAE,WACd,CAEA,8BAAgB,yBAA0B,CACxC,UAAU,CAAE,OAAO,CACnB,aAAa,CAAE,GACjB,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,8BAAgB,yBAA0B,CACxC,UAAU,CAAE,OACd,CACF,CAEA,8BAAgB,yBAAyB,MAAO,CAC9C,UAAU,CAAE,OACd,CAEA,MAAO,uBAAuB,IAAI,CAAE,CAClC,8BAAgB,yBAAyB,MAAO,CAC9C,UAAU,CAAE,OACd,CACF"}'
};
function formatShortcut(shortcut) {
if (!shortcut) return "";
return shortcut.replace(/Ctrl/g, "⌃").replace(/Cmd/g, "⌘").replace(/Alt/g, "⌥").replace(/Shift/g, "⇧").replace(/\+/g, " ");
}
function getCategoryColor(category) {
const colors = {
"Panel": "rgb(59, 130, 246)",
// blue
"Layout": "rgb(34, 197, 94)",
// green
"Configuration": "rgb(168, 85, 247)",
// purple
"Help": "rgb(251, 146, 60)",
// orange
"File": "rgb(236, 72, 153)",
// pink
"Navigation": "rgb(14, 165, 233)"
};
return colors[category] || "rgb(107, 114, 128)";
}
function highlightMatch(text, query) {
if (!query.trim()) return text;
const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`, "gi");
return text.replace(regex, "<mark>$1</mark>");
}
const CommandPalette = create_ssr_component(($$result, $$props, $$bindings, slots) => {
let searchQuery = "";
let searchInput;
let commandResults = [];
let selectedIndex = 0;
let isVisible = false;
const unsubscribeVisible = isCommandPaletteVisible.subscribe((visible) => {
isVisible = visible;
if (visible) {
searchQuery = "";
selectedIndex = 0;
searchCommands();
tick().then(() => {
});
}
});
function searchCommands() {
commandResults = commands.search(searchQuery);
selectedIndex = Math.min(selectedIndex, Math.max(0, commandResults.length - 1));
}
onDestroy(() => {
unsubscribeVisible();
});
$$result.css.add(css);
{
if (searchQuery !== void 0) {
searchCommands();
}
}
return ` ${isVisible ? `<div class="command-palette-overlay svelte-lc0xhx" role="dialog" aria-modal="true" aria-label="Command Palette"><div class="command-palette-modal svelte-lc0xhx"> <div class="search-container svelte-lc0xhx"><div class="search-icon svelte-lc0xhx" data-svelte-h="svelte-5dl7sz"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.35-4.35"></path></svg></div> <input placeholder="Type a command or search..." class="search-input svelte-lc0xhx" type="text" autocomplete="off" spellcheck="false"${add_attribute("this", searchInput, 0)}${add_attribute("value", searchQuery, 0)}> <div class="shortcut-hint svelte-lc0xhx" data-svelte-h="svelte-bpshni"><kbd class="svelte-lc0xhx">Esc</kbd> to close</div></div> <div class="command-results svelte-lc0xhx">${commandResults.length === 0 ? `<div class="no-results svelte-lc0xhx">${searchQuery.trim() ? `No commands found for "<em>${escape(searchQuery)}</em>"` : `No commands available`}</div>` : `<div class="results-list svelte-lc0xhx">${each(commandResults, (command, index) => {
return `<button class="${"command-item " + escape(index === selectedIndex ? "selected" : "", true) + " svelte-lc0xhx"}" ${command.disabled ? "disabled" : ""}><div class="command-content svelte-lc0xhx"><div class="command-main svelte-lc0xhx"><div class="command-icon-title svelte-lc0xhx">${command.icon ? `<span class="command-icon svelte-lc0xhx">${escape(command.icon)}</span>` : ``} <span class="command-title svelte-lc0xhx"><!-- HTML_TAG_START -->${highlightMatch(command.title, searchQuery)}<!-- HTML_TAG_END --> </span></div> ${command.shortcut ? `<span class="command-shortcut svelte-lc0xhx">${escape(formatShortcut(command.shortcut))}</span>` : ``}</div> <div class="command-meta svelte-lc0xhx"><span class="command-description svelte-lc0xhx"><!-- HTML_TAG_START -->${highlightMatch(command.description, searchQuery)}<!-- HTML_TAG_END --></span> <span class="command-category svelte-lc0xhx" style="${"color: " + escape(getCategoryColor(command.category), true)}">${escape(command.category)}</span> </div></div> </button>`;
})}</div>`}</div> <div class="command-footer svelte-lc0xhx" data-svelte-h="svelte-ycu39a"><div class="navigation-hints svelte-lc0xhx"><span><kbd class="svelte-lc0xhx">↑</kbd><kbd class="svelte-lc0xhx">↓</kbd> to navigate</span> <span><kbd class="svelte-lc0xhx">Enter</kbd> to execute</span> <span><kbd class="svelte-lc0xhx">Esc</kbd> to close</span></div></div></div></div>` : ``}`;
});
const Layout = create_ssr_component(($$result, $$props, $$bindings, slots) => {
return `${slots.default ? slots.default({}) : ``} ${validate_component(CommandPalette, "CommandPalette").$$render($$result, {}, {}, {})}`;
});
export { Layout as default };
//# sourceMappingURL=_layout.svelte-3A9hROSO.js.map