1import type { EnvironmentId, PullRequestLinkedThreadsResult } from "@t3tools/contracts";
2
3export interface CommandPaletteLinkedThreads {
4 readonly environmentId: EnvironmentId;
5 readonly threads: PullRequestLinkedThreadsResult["threads"];
6}
7
8// Tiny event bus allowing components to programmatically open the command palette
9// without owning its React state.
10const COMMAND_PALETTE_OPEN_EVENT = "t3code:open-command-palette";
11
12export interface CommandPaletteOpenDetail {
13 readonly open?: "add-project" | "new-thread-in";
14 readonly query?: string;
15 readonly linkedThreads?: CommandPaletteLinkedThreads;
16}
17
18export function openCommandPalette(detail?: CommandPaletteOpenDetail): void {
19 window.dispatchEvent(
20 new CustomEvent(COMMAND_PALETTE_OPEN_EVENT, detail ? { detail } : undefined),
21 );
22}
23
24export function onOpenCommandPalette(
25 listener: (detail: CommandPaletteOpenDetail) => void,
26): () => void {
27 const handler = (event: Event) => {
28 listener((event as CustomEvent<CommandPaletteOpenDetail>).detail ?? {});
29 };
30 window.addEventListener(COMMAND_PALETTE_OPEN_EVENT, handler);
31 return () => window.removeEventListener(COMMAND_PALETTE_OPEN_EVENT, handler);
32}
33
34/** Read at event time so consumers do not subscribe to transient dialog state. */
35export function isCommandPaletteOpen(): boolean {
36 return (
37 typeof document !== "undefined" && document.querySelector("[data-command-palette]") !== null
38 );
39}