# useCustomCommand - Exemplos Práticos

> 🎯 **Comandos temporários que existem apenas enquanto o componente está montado**

O `useCustomCommand` é o hook principal para criar comandos contextuais que aparecem automaticamente no Command Palette (Ctrl+Shift+P) e desaparecem quando o componente é desmontado.

## 📋 Índice

1. [Modal com Comandos](#modal-com-comandos)
2. [Editor de Texto](#editor-de-texto)
3. [Formulário com Ações](#formulário-com-ações)
4. [Lista com Ações Contextuais](#lista-com-ações-contextuais)
5. [Player de Mídia](#player-de-mídia)
6. [Dashboard com Widgets](#dashboard-com-widgets)
7. [Tabela de Dados](#tabela-de-dados)
8. [Integração com Rotas](#integração-com-rotas)

---

## Modal com Comandos

```tsx
import { useState } from "react";
import { useCustomCommand } from "@darksnow-ui/commander";

function UserProfileModal({ user, isOpen, onClose }) {
  const [isEditing, setIsEditing] = useState(false);
  const [formData, setFormData] = useState(user);

  // Comando para fechar o modal (ESC)
  useCustomCommand({
    key: `modal:close:${user.id}`,
    label: "Fechar Modal",
    icon: "❌",
    shortcut: "escape",
    handle: async () => {
      onClose();
    },
  });

  // Comando para editar/salvar
  const saveCommand = useCustomCommand({
    key: `user:save:${user.id}`,
    label: isEditing ? "Salvar Alterações" : "Editar Perfil",
    icon: isEditing ? "💾" : "✏️",
    shortcut: isEditing ? "ctrl+s" : "ctrl+e",
    category: "user",
    when: () => isOpen, // Só disponível quando modal está aberto
    handle: async () => {
      if (isEditing) {
        await api.updateUser(user.id, formData);
        setIsEditing(false);
        toast.success("Perfil atualizado!");
      } else {
        setIsEditing(true);
      }
    },
  });

  // Comando para deletar usuário
  useCustomCommand({
    key: `user:delete:${user.id}`,
    label: "Deletar Usuário",
    icon: "🗑️",
    category: "user",
    tags: ["danger", "delete"],
    priority: -1, // Baixa prioridade na busca
    when: () => isOpen && user.role !== "admin",
    handle: async () => {
      if (confirm("Tem certeza?")) {
        await api.deleteUser(user.id);
        onClose();
      }
    },
  });

  // Comando para enviar mensagem
  useCustomCommand({
    key: `user:message:${user.id}`,
    label: `Enviar mensagem para ${user.name}`,
    icon: "💬",
    shortcut: "ctrl+m",
    category: "communication",
    handle: async () => {
      openMessageComposer(user);
    },
  });

  if (!isOpen) return null;

  return <Modal onClose={onClose}>{/* UI do modal */}</Modal>;
}
```

---

## Editor de Texto

```tsx
import { useCustomCommand, useAction } from "@darksnow-ui/commander";

function RichTextEditor({ documentId, initialContent, onSave }) {
  const [content, setContent] = useState(initialContent);
  const [isDirty, setIsDirty] = useState(false);
  const [selectedText, setSelectedText] = useState("");
  const [undoStack, setUndoStack] = useState([]);
  const [redoStack, setRedoStack] = useState([]);

  // Comando de salvar
  const saveCommand = useCustomCommand({
    key: `doc:save:${documentId}`,
    label: "Salvar Documento",
    icon: "💾",
    shortcut: "ctrl+s",
    category: "file",
    when: () => isDirty, // Só aparece quando há mudanças
    handle: async () => {
      const result = await onSave(content);
      setIsDirty(false);
      return result;
    },
  });

  // Comandos de formatação
  useCustomCommand({
    key: `format:bold:${documentId}`,
    label: "Negrito",
    icon: "🅱️",
    shortcut: "ctrl+b",
    category: "format",
    when: () => selectedText.length > 0,
    handle: async () => {
      document.execCommand("bold");
    },
  });

  useCustomCommand({
    key: `format:italic:${documentId}`,
    label: "Itálico",
    icon: "𝐼",
    shortcut: "ctrl+i",
    category: "format",
    when: () => selectedText.length > 0,
    handle: async () => {
      document.execCommand("italic");
    },
  });

  // Comandos de edição
  useAction(
    `edit:undo:${documentId}`,
    "Desfazer",
    () => {
      if (undoStack.length > 0) {
        const previous = undoStack[undoStack.length - 1];
        setRedoStack([...redoStack, content]);
        setContent(previous);
        setUndoStack(undoStack.slice(0, -1));
      }
    },
    {
      shortcut: "ctrl+z",
      icon: "↩️",
      when: () => undoStack.length > 0,
    },
  );

  useAction(
    `edit:redo:${documentId}`,
    "Refazer",
    () => {
      if (redoStack.length > 0) {
        const next = redoStack[redoStack.length - 1];
        setUndoStack([...undoStack, content]);
        setContent(next);
        setRedoStack(redoStack.slice(0, -1));
      }
    },
    {
      shortcut: "ctrl+y",
      icon: "↪️",
      when: () => redoStack.length > 0,
    },
  );

  // Comandos avançados
  useCustomCommand({
    key: `edit:find:${documentId}`,
    label: "Buscar e Substituir",
    icon: "🔍",
    shortcut: "ctrl+f",
    category: "edit",
    handle: async () => {
      const searchTerm = prompt("Buscar por:");
      if (searchTerm) {
        const replaceTerm = prompt("Substituir por:");
        if (replaceTerm !== null) {
          const newContent = content.replaceAll(searchTerm, replaceTerm);
          setContent(newContent);
          setIsDirty(true);
          return { replaced: content.split(searchTerm).length - 1 };
        }
      }
    },
  });

  // Comando de exportação
  useCustomCommand({
    key: `export:pdf:${documentId}`,
    label: "Exportar como PDF",
    icon: "📄",
    shortcut: "ctrl+shift+e",
    category: "file",
    tags: ["export", "pdf", "download"],
    handle: async () => {
      const blob = await generatePDF(content);
      downloadBlob(blob, `document-${documentId}.pdf`);
    },
  });

  return (
    <div className="editor">
      <div className="toolbar">
        <button onClick={() => saveCommand.invoke()}>
          Salvar {isDirty && "*"}
        </button>
      </div>
      <textarea
        value={content}
        onChange={(e) => {
          setContent(e.target.value);
          setIsDirty(true);
          setUndoStack([...undoStack, content].slice(-50)); // Max 50 undos
        }}
        onSelect={(e) => {
          const target = e.target as HTMLTextAreaElement;
          setSelectedText(
            target.value.substring(target.selectionStart, target.selectionEnd),
          );
        }}
      />
    </div>
  );
}
```

---

## Formulário com Ações

```tsx
import { useCustomCommand, useToggleCommand } from "@darksnow-ui/commander";

function ContactForm() {
  const [formData, setFormData] = useState({
    name: "",
    email: "",
    message: "",
  });
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [autoSave, setAutoSave] = useState(true);

  // Toggle de auto-save
  useToggleCommand("form:autosave", "Auto-save", autoSave, setAutoSave, {
    icon: autoSave ? "✅" : "❌",
    category: "settings",
  });

  // Comando para limpar formulário
  useCustomCommand({
    key: "form:clear",
    label: "Limpar Formulário",
    icon: "🧹",
    shortcut: "ctrl+shift+delete",
    category: "form",
    when: () => Object.values(formData).some((v) => v !== ""),
    handle: async () => {
      if (confirm("Limpar todos os campos?")) {
        setFormData({ name: "", email: "", message: "" });
      }
    },
  });

  // Comando para preencher com dados de teste
  useCustomCommand({
    key: "form:fill-test",
    label: "Preencher com Dados de Teste",
    icon: "🧪",
    category: "debug",
    tags: ["test", "development"],
    when: () => process.env.NODE_ENV === "development",
    handle: async () => {
      setFormData({
        name: "João Silva",
        email: "joao@example.com",
        message: "Mensagem de teste para desenvolvimento",
      });
    },
  });

  // Comando para enviar
  const submitCommand = useCustomCommand({
    key: "form:submit",
    label: "Enviar Formulário",
    icon: "📤",
    shortcut: "ctrl+enter",
    category: "form",
    when: () =>
      formData.name && formData.email && formData.message && !isSubmitting,
    handle: async () => {
      setIsSubmitting(true);
      try {
        await api.submitContact(formData);
        toast.success("Mensagem enviada!");
        setFormData({ name: "", email: "", message: "" });
      } catch (error) {
        toast.error("Erro ao enviar");
      } finally {
        setIsSubmitting(false);
      }
    },
  });

  // Auto-save com debounce
  useEffect(() => {
    if (!autoSave) return;

    const timer = setTimeout(() => {
      if (Object.values(formData).some((v) => v !== "")) {
        localStorage.setItem("contact-form-draft", JSON.stringify(formData));
      }
    }, 1000);

    return () => clearTimeout(timer);
  }, [formData, autoSave]);

  return (
    <form
      onSubmit={(e) => {
        e.preventDefault();
        submitCommand.invoke();
      }}
    >
      {/* Campos do formulário */}
    </form>
  );
}
```

---

## Lista com Ações Contextuais

```tsx
import {
  useContextualCommands,
  useCustomCommand,
} from "@darksnow-ui/commander";

function TaskList({ projectId }) {
  const [tasks, setTasks] = useState([]);
  const [selectedTasks, setSelectedTasks] = useState([]);
  const [filter, setFilter] = useState("all");

  // Comandos para cada task individual
  useContextualCommands(tasks, (task) => ({
    key: `task:toggle:${task.id}`,
    label: task.completed
      ? `Reabrir: ${task.title}`
      : `Completar: ${task.title}`,
    icon: task.completed ? "↩️" : "✅",
    category: "task",
    tags: ["task", task.priority],
    priority: task.priority === "high" ? 10 : 5,
    handle: async () => {
      await api.updateTask(task.id, { completed: !task.completed });
      setTasks(
        tasks.map((t) =>
          t.id === task.id ? { ...t, completed: !t.completed } : t,
        ),
      );
    },
  }));

  // Comandos para seleção múltipla
  useCustomCommand({
    key: "tasks:select-all",
    label: "Selecionar Todas",
    icon: "☑️",
    shortcut: "ctrl+a",
    category: "selection",
    when: () => tasks.length > 0,
    handle: async () => {
      setSelectedTasks(tasks.map((t) => t.id));
    },
  });

  useCustomCommand({
    key: "tasks:complete-selected",
    label: `Completar ${selectedTasks.length} tarefas`,
    icon: "✅",
    category: "bulk",
    when: () => selectedTasks.length > 0,
    handle: async () => {
      await api.bulkUpdate(selectedTasks, { completed: true });
      setTasks(
        tasks.map((t) =>
          selectedTasks.includes(t.id) ? { ...t, completed: true } : t,
        ),
      );
      setSelectedTasks([]);
    },
  });

  // Comandos de filtro
  useCustomCommand({
    key: "filter:active",
    label: "Mostrar Apenas Ativas",
    icon: "🔵",
    shortcut: "alt+1",
    category: "view",
    when: () => filter !== "active",
    handle: async () => setFilter("active"),
  });

  useCustomCommand({
    key: "filter:completed",
    label: "Mostrar Apenas Completas",
    icon: "🟢",
    shortcut: "alt+2",
    category: "view",
    when: () => filter !== "completed",
    handle: async () => setFilter("completed"),
  });

  // Comando para adicionar nova task
  useCustomCommand({
    key: "task:add",
    label: "Nova Tarefa",
    icon: "➕",
    shortcut: "ctrl+n",
    category: "task",
    handle: async () => {
      const title = prompt("Título da tarefa:");
      if (title) {
        const newTask = await api.createTask({ projectId, title });
        setTasks([...tasks, newTask]);
      }
    },
  });

  const filteredTasks = tasks.filter((task) => {
    if (filter === "active") return !task.completed;
    if (filter === "completed") return task.completed;
    return true;
  });

  return (
    <div>
      <div className="filters">
        <button onClick={() => setFilter("all")}>Todas</button>
        <button onClick={() => setFilter("active")}>Ativas</button>
        <button onClick={() => setFilter("completed")}>Completas</button>
      </div>

      {filteredTasks.map((task) => (
        <TaskItem
          key={task.id}
          task={task}
          isSelected={selectedTasks.includes(task.id)}
          onToggleSelect={() => {
            setSelectedTasks(
              selectedTasks.includes(task.id)
                ? selectedTasks.filter((id) => id !== task.id)
                : [...selectedTasks, task.id],
            );
          }}
        />
      ))}
    </div>
  );
}
```

---

## Player de Mídia

```tsx
import { useCustomCommand, useAction } from "@darksnow-ui/commander";

function VideoPlayer({ video }) {
  const videoRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [volume, setVolume] = useState(1);
  const [playbackRate, setPlaybackRate] = useState(1);
  const [currentTime, setCurrentTime] = useState(0);

  // Play/Pause
  useCustomCommand({
    key: `video:playpause:${video.id}`,
    label: isPlaying ? "Pausar" : "Reproduzir",
    icon: isPlaying ? "⏸️" : "▶️",
    shortcut: "space",
    category: "playback",
    handle: async () => {
      if (isPlaying) {
        videoRef.current?.pause();
      } else {
        videoRef.current?.play();
      }
      setIsPlaying(!isPlaying);
    },
  });

  // Controles de velocidade
  const speeds = [0.5, 0.75, 1, 1.25, 1.5, 2];
  speeds.forEach((speed) => {
    useAction(
      `video:speed:${speed}:${video.id}`,
      `Velocidade ${speed}x`,
      () => {
        if (videoRef.current) {
          videoRef.current.playbackRate = speed;
          setPlaybackRate(speed);
        }
      },
      {
        category: "playback",
        icon: "⚡",
        when: () => playbackRate !== speed,
      },
    );
  });

  // Volume
  useCustomCommand({
    key: `video:mute:${video.id}`,
    label: volume > 0 ? "Silenciar" : "Ativar Som",
    icon: volume > 0 ? "🔇" : "🔊",
    shortcut: "m",
    category: "audio",
    handle: async () => {
      if (videoRef.current) {
        const newVolume = volume > 0 ? 0 : 1;
        videoRef.current.volume = newVolume;
        setVolume(newVolume);
      }
    },
  });

  // Navegação
  useAction(
    `video:skip-forward:${video.id}`,
    "Avançar 10s",
    () => {
      if (videoRef.current) {
        videoRef.current.currentTime += 10;
      }
    },
    {
      shortcut: "right",
      icon: "⏩",
      category: "navigation",
    },
  );

  useAction(
    `video:skip-backward:${video.id}`,
    "Voltar 10s",
    () => {
      if (videoRef.current) {
        videoRef.current.currentTime -= 10;
      }
    },
    {
      shortcut: "left",
      icon: "⏪",
      category: "navigation",
    },
  );

  // Fullscreen
  useCustomCommand({
    key: `video:fullscreen:${video.id}`,
    label: "Tela Cheia",
    icon: "🖥️",
    shortcut: "f",
    category: "view",
    handle: async () => {
      if (videoRef.current) {
        if (document.fullscreenElement) {
          document.exitFullscreen();
        } else {
          videoRef.current.requestFullscreen();
        }
      }
    },
  });

  // Screenshot
  useCustomCommand({
    key: `video:screenshot:${video.id}`,
    label: "Capturar Tela",
    icon: "📸",
    shortcut: "s",
    category: "tools",
    handle: async () => {
      const canvas = document.createElement("canvas");
      canvas.width = videoRef.current.videoWidth;
      canvas.height = videoRef.current.videoHeight;
      const ctx = canvas.getContext("2d");
      ctx.drawImage(videoRef.current, 0, 0);

      canvas.toBlob((blob) => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `screenshot-${video.id}-${Date.now()}.png`;
        a.click();
      });
    },
  });

  return (
    <div className="video-player">
      <video
        ref={videoRef}
        src={video.url}
        onTimeUpdate={(e) => setCurrentTime(e.currentTarget.currentTime)}
      />
      {/* Controles do player */}
    </div>
  );
}
```

---

## Dashboard com Widgets

```tsx
import { useCustomCommand, useModalCommand } from "@darksnow-ui/commander";

function Dashboard() {
  const [widgets, setWidgets] = useState([]);
  const [layout, setLayout] = useState("grid");
  const [refreshInterval, setRefreshInterval] = useState(30000);

  // Comando para adicionar widget
  const addWidgetCommand = useModalCommand(
    "dashboard:add-widget",
    "Adicionar Widget",
    async () => {
      const widgetType = await showWidgetPicker();
      if (widgetType) {
        const newWidget = await createWidget(widgetType);
        setWidgets([...widgets, newWidget]);
        return newWidget;
      }
    },
    {
      icon: "➕",
      shortcut: "ctrl+shift+w",
      category: "dashboard",
    },
  );

  // Comandos para cada widget
  widgets.forEach((widget) => {
    // Refresh individual
    useCustomCommand({
      key: `widget:refresh:${widget.id}`,
      label: `Atualizar: ${widget.title}`,
      icon: "🔄",
      category: "widget",
      tags: ["refresh", widget.type],
      handle: async () => {
        await widget.refresh();
        toast.success(`${widget.title} atualizado`);
      },
    });

    // Configurar widget
    useModalCommand(
      `widget:config:${widget.id}`,
      `Configurar: ${widget.title}`,
      async () => {
        const config = await showWidgetConfig(widget);
        if (config) {
          await updateWidget(widget.id, config);
          setWidgets(
            widgets.map((w) => (w.id === widget.id ? { ...w, ...config } : w)),
          );
        }
      },
      {
        icon: "⚙️",
        category: "widget",
      },
    );

    // Remover widget
    useCustomCommand({
      key: `widget:remove:${widget.id}`,
      label: `Remover: ${widget.title}`,
      icon: "🗑️",
      category: "widget",
      priority: -1,
      handle: async () => {
        if (confirm(`Remover ${widget.title}?`)) {
          setWidgets(widgets.filter((w) => w.id !== widget.id));
        }
      },
    });
  });

  // Comandos de layout
  useCustomCommand({
    key: "dashboard:layout:grid",
    label: "Layout em Grade",
    icon: "⚏",
    category: "view",
    when: () => layout !== "grid",
    handle: async () => setLayout("grid"),
  });

  useCustomCommand({
    key: "dashboard:layout:list",
    label: "Layout em Lista",
    icon: "☰",
    category: "view",
    when: () => layout !== "list",
    handle: async () => setLayout("list"),
  });

  // Refresh global
  useCustomCommand({
    key: "dashboard:refresh-all",
    label: "Atualizar Todos os Widgets",
    icon: "🔄",
    shortcut: "ctrl+r",
    category: "dashboard",
    handle: async () => {
      await Promise.all(widgets.map((w) => w.refresh()));
      toast.success("Dashboard atualizado");
    },
  });

  // Auto-refresh toggle
  useToggleCommand(
    "dashboard:auto-refresh",
    "Auto-refresh",
    refreshInterval > 0,
    (enabled) => setRefreshInterval(enabled ? 30000 : 0),
    {
      category: "settings",
      icon: "⏱️",
    },
  );

  // Exportar dashboard
  useCustomCommand({
    key: "dashboard:export",
    label: "Exportar Dashboard",
    icon: "📊",
    shortcut: "ctrl+e",
    category: "dashboard",
    tags: ["export", "download"],
    handle: async () => {
      const format = await showExportOptions();
      if (format) {
        const data = await exportDashboard(widgets, format);
        downloadFile(data, `dashboard-${Date.now()}.${format}`);
      }
    },
  });

  return (
    <div className={`dashboard layout-${layout}`}>
      <button onClick={() => addWidgetCommand.invoke()}>Add Widget</button>

      {widgets.map((widget) => (
        <Widget key={widget.id} {...widget} />
      ))}
    </div>
  );
}
```

---

## Tabela de Dados

```tsx
import {
  useCustomCommand,
  useContextualCommands,
} from "@darksnow-ui/commander";

function DataTable({ data, columns, onUpdate }) {
  const [selectedRows, setSelectedRows] = useState([]);
  const [sortConfig, setSortConfig] = useState(null);
  const [filters, setFilters] = useState({});
  const [editingCell, setEditingCell] = useState(null);

  // Comandos para linhas selecionadas
  useCustomCommand({
    key: "table:export-selected",
    label: `Exportar ${selectedRows.length} linhas`,
    icon: "📥",
    shortcut: "ctrl+shift+e",
    category: "table",
    when: () => selectedRows.length > 0,
    handle: async () => {
      const selectedData = data.filter((row) => selectedRows.includes(row.id));
      const csv = convertToCSV(selectedData);
      downloadFile(csv, "export.csv");
    },
  });

  useCustomCommand({
    key: "table:delete-selected",
    label: `Deletar ${selectedRows.length} linhas`,
    icon: "🗑️",
    shortcut: "delete",
    category: "table",
    when: () => selectedRows.length > 0,
    priority: -1,
    handle: async () => {
      if (confirm(`Deletar ${selectedRows.length} linhas?`)) {
        await onUpdate("delete", selectedRows);
        setSelectedRows([]);
      }
    },
  });

  // Comandos de ordenação para cada coluna
  columns.forEach((column) => {
    if (column.sortable) {
      useCustomCommand({
        key: `sort:${column.key}:asc`,
        label: `Ordenar por ${column.label} (A-Z)`,
        icon: "⬆️",
        category: "sort",
        when: () =>
          sortConfig?.key !== column.key || sortConfig?.direction !== "asc",
        handle: async () => {
          setSortConfig({ key: column.key, direction: "asc" });
        },
      });

      useCustomCommand({
        key: `sort:${column.key}:desc`,
        label: `Ordenar por ${column.label} (Z-A)`,
        icon: "⬇️",
        category: "sort",
        when: () =>
          sortConfig?.key !== column.key || sortConfig?.direction !== "desc",
        handle: async () => {
          setSortConfig({ key: column.key, direction: "desc" });
        },
      });
    }
  });

  // Comandos contextuais para cada linha
  useContextualCommands(data, (row) => ({
    key: `row:edit:${row.id}`,
    label: `Editar: ${row.name || row.title || row.id}`,
    icon: "✏️",
    category: "row",
    handle: async () => {
      const updatedRow = await showRowEditor(row);
      if (updatedRow) {
        await onUpdate("update", row.id, updatedRow);
      }
    },
  }));

  // Comandos de filtro
  useCustomCommand({
    key: "table:clear-filters",
    label: "Limpar Filtros",
    icon: "🧹",
    category: "filter",
    when: () => Object.keys(filters).length > 0,
    handle: async () => {
      setFilters({});
    },
  });

  // Comando de busca global
  useCustomCommand({
    key: "table:search",
    label: "Buscar na Tabela",
    icon: "🔍",
    shortcut: "ctrl+f",
    category: "table",
    handle: async () => {
      const searchTerm = prompt("Buscar por:");
      if (searchTerm) {
        setFilters({ ...filters, global: searchTerm });
      }
    },
  });

  // Copiar dados selecionados
  useCustomCommand({
    key: "table:copy-selected",
    label: "Copiar Seleção",
    icon: "📋",
    shortcut: "ctrl+c",
    category: "table",
    when: () => selectedRows.length > 0,
    handle: async () => {
      const selectedData = data.filter((row) => selectedRows.includes(row.id));
      const text = selectedData
        .map((row) => columns.map((col) => row[col.key]).join("\t"))
        .join("\n");

      await navigator.clipboard.writeText(text);
      toast.success("Copiado para área de transferência");
    },
  });

  const sortedAndFilteredData = useMemo(() => {
    let result = [...data];

    // Apply filters
    Object.entries(filters).forEach(([key, value]) => {
      if (key === "global") {
        result = result.filter((row) =>
          Object.values(row).some((v) =>
            String(v).toLowerCase().includes(value.toLowerCase()),
          ),
        );
      } else {
        result = result.filter((row) =>
          String(row[key]).toLowerCase().includes(value.toLowerCase()),
        );
      }
    });

    // Apply sorting
    if (sortConfig) {
      result.sort((a, b) => {
        const aVal = a[sortConfig.key];
        const bVal = b[sortConfig.key];

        if (sortConfig.direction === "asc") {
          return aVal > bVal ? 1 : -1;
        } else {
          return aVal < bVal ? 1 : -1;
        }
      });
    }

    return result;
  }, [data, filters, sortConfig]);

  return (
    <div className="data-table">
      <table>
        <thead>
          <tr>
            {columns.map((column) => (
              <th key={column.key}>
                {column.label}
                {column.sortable && (
                  <button
                    onClick={() => {
                      const newDir =
                        sortConfig?.key === column.key &&
                        sortConfig?.direction === "asc"
                          ? "desc"
                          : "asc";
                      setSortConfig({ key: column.key, direction: newDir });
                    }}
                  >
                    {sortConfig?.key === column.key
                      ? sortConfig.direction === "asc"
                        ? "⬆️"
                        : "⬇️"
                      : "↕️"}
                  </button>
                )}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {sortedAndFilteredData.map((row) => (
            <tr
              key={row.id}
              className={selectedRows.includes(row.id) ? "selected" : ""}
              onClick={() => {
                setSelectedRows(
                  selectedRows.includes(row.id)
                    ? selectedRows.filter((id) => id !== row.id)
                    : [...selectedRows, row.id],
                );
              }}
            >
              {columns.map((column) => (
                <td key={column.key}>{row[column.key]}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
```

---

## Integração com Rotas

```tsx
import { useNavigationCommand, useCustomCommand } from "@darksnow-ui/commander";
import { useRouter, useParams } from "next/router";

function ProductPage() {
  const router = useRouter();
  const { productId } = useParams();
  const [product, setProduct] = useState(null);
  const [relatedProducts, setRelatedProducts] = useState([]);

  // Navegação entre produtos
  useNavigationCommand(
    "nav:products",
    "Voltar para Produtos",
    "/products",
    router.push,
    {
      icon: "🏪",
      shortcut: "alt+p",
    },
  );

  // Navegação para produtos relacionados
  relatedProducts.forEach((related) => {
    useNavigationCommand(
      `nav:product:${related.id}`,
      `Ver: ${related.name}`,
      `/products/${related.id}`,
      router.push,
      {
        icon: "🔗",
        category: "related",
        tags: ["product", related.category],
      },
    );
  });

  // Ações do produto
  useCustomCommand({
    key: `product:share:${productId}`,
    label: "Compartilhar Produto",
    icon: "🔗",
    shortcut: "ctrl+shift+s",
    category: "product",
    handle: async () => {
      const url = `${window.location.origin}/products/${productId}`;

      if (navigator.share) {
        await navigator.share({
          title: product.name,
          text: product.description,
          url,
        });
      } else {
        await navigator.clipboard.writeText(url);
        toast.success("Link copiado!");
      }
    },
  });

  // Adicionar ao carrinho
  const addToCartCommand = useCustomCommand({
    key: `product:cart:${productId}`,
    label: "Adicionar ao Carrinho",
    icon: "🛒",
    shortcut: "ctrl+enter",
    category: "product",
    priority: 10,
    when: () => product?.inStock,
    handle: async () => {
      await addToCart(productId);
      toast.success("Adicionado ao carrinho!");
    },
  });

  // Admin commands
  const isAdmin = useIsAdmin();

  useCustomCommand({
    key: `product:edit:${productId}`,
    label: "Editar Produto",
    icon: "✏️",
    category: "admin",
    when: () => isAdmin,
    handle: async () => {
      router.push(`/admin/products/${productId}/edit`);
    },
  });

  useCustomCommand({
    key: `product:analytics:${productId}`,
    label: "Ver Analytics",
    icon: "📊",
    category: "admin",
    when: () => isAdmin,
    handle: async () => {
      const analytics = await fetchProductAnalytics(productId);
      showAnalyticsModal(analytics);
    },
  });

  return (
    <div>
      {/* UI do produto */}
      <button onClick={() => addToCartCommand.invoke()}>
        Adicionar ao Carrinho
      </button>
    </div>
  );
}
```

---

## 💡 Dicas e Melhores Práticas

### 1. **Use IDs únicos nas keys**

```tsx
// ✅ Bom - ID único por instância
useCustomCommand({
  key: `modal:save:${modalId}`,
  // ...
});

// ❌ Evite - Pode causar conflitos
useCustomCommand({
  key: "modal:save",
  // ...
});
```

### 2. **Aproveite a função `when`**

```tsx
// Comando só aparece quando relevante
useCustomCommand({
  key: "form:submit",
  label: "Enviar",
  when: () => isFormValid && !isSubmitting,
  handle: async () => {
    /* ... */
  },
});
```

### 3. **Use categorias para organização**

```tsx
// Agrupe comandos relacionados
category: "file"; // Operações de arquivo
category: "edit"; // Edição
category: "view"; // Visualização
category: "tools"; // Ferramentas
category: "debug"; // Desenvolvimento
```

### 4. **Retorne valores úteis**

```tsx
// Retorne informações sobre a operação
handle: async () => {
  const result = await saveFile();
  return {
    success: true,
    fileSize: result.size,
    savedAt: new Date(),
  };
};
```

### 5. **Use os hooks especializados**

```tsx
// Para ações simples
useAction("toggle:sidebar", "Toggle Sidebar", () => {
  setSidebarOpen(!sidebarOpen);
});

// Para toggles
useToggleCommand("dark:mode", "Dark Mode", isDark, setIsDark);

// Para modais
useModalCommand("user:edit", "Edit User", async () => {
  return await showUserEditModal();
});
```

### 6. **Integre com o estado do componente**

```tsx
// Comandos que refletem o estado atual
const [filter, setFilter] = useState("all")[
  ("all", "active", "completed")
].forEach((filterType) => {
  useCustomCommand({
    key: `filter:${filterType}`,
    label: `Show ${filterType}`,
    when: () => filter !== filterType,
    handle: async () => setFilter(filterType),
  });
});
```

---

## 🎯 Conclusão

O `useCustomCommand` transforma qualquer componente em uma interface poderosa e acessível. Os comandos aparecem automaticamente no Command Palette, permitindo que usuários avançados naveguem e controlem sua aplicação com eficiência.

**Lembre-se**: Os comandos são temporários e existem apenas enquanto o componente está montado, garantindo que o Command Palette sempre reflita o contexto atual da aplicação.
