/** * Core type definitions for the command palette. */ import type { CSSProperties, ReactNode } from "react"; import type { AppIcon } from "@/components/icon"; export type { AppIcon } from "@/components/icon"; // ============================================================================= // PALETTE ITEM // ============================================================================= /** * A searchable/selectable entry of the palette. * * Items are plain data: the host app builds the list (commands, documents, * contacts, navigation targets…) and hands it to . */ export interface PaletteItem { /** Unique id. Also used for usage tracking. */ id: string; /** Main label. */ title: string; /** Secondary text, searchable (not displayed in the compact rows). */ description?: string; /** Icon displayed at the left of the row. */ icon?: ReactNode; /** Keyboard shortcut hint displayed at the right (e.g. ["⌘", "P"]). */ shortcut?: string[]; /** Extra search terms. */ keywords?: string[]; /** * Direct action executed on Enter when no ActionProvider overrides it. * Return false to keep the palette open. */ execute?: () => void | false | Promise; /** * Category id used for filter tabs and result grouping. * Must match a CategoryDefinition id (or "all"). */ filterCategory: string; /** * Rank tier inside the item's category, lowest first (default 0). It beats * the relevance score, which still orders items of the same tier — e.g. * issues in progress before open ones before closed ones. */ searchTier?: number; /** * Typed exactly (case-insensitive), any of these puts the item before every * tier of its category — e.g. an issue identifier. */ exactKeywords?: string[]; /** * Shown only as a search result: an empty query in the "all" view leaves it * out, while its own category tab still lists it. For personal content that * would crowd the default list, such as notebook tasks. */ searchOnly?: boolean; /** * Entity type used to route the item to ActionProviders. * Falls back to filterCategory when omitted. */ entityType?: string; /** Dimmed context text displayed next to the title (e.g. "Project › Module"). */ contextLabel?: string; /** * Small icon rendered LEFT of the right-aligned context text — e.g. the * project orb of the project a ticket belongs to. */ contextIcon?: ReactNode; /** Small type label displayed at the right of the row (e.g. "Task"). */ typeLabel?: string; /** Colored status dot displayed before the title. */ statusDot?: "success" | "muted" | "warning" | "danger"; /** Extra class and style on the title, e.g. an objective's name in its color (MIN-785). */ titleClassName?: string; titleStyle?: CSSProperties; /** Optional context id — items matching SearchContext.currentContextId get boosted. */ contextId?: string; /** Optional sub-context id — items matching SearchContext.currentSubContextId get boosted. */ subContextId?: string; /** Arbitrary host data, available to ActionProviders. */ data?: unknown; /** Optional destination represented by the item. */ href?: string; } // ============================================================================= // CATEGORIES // ============================================================================= /** * A filter tab / result group of the palette. * The "all" category is built in. */ export interface CategoryDefinition { /** Category id, referenced by PaletteItem.filterCategory. */ id: string; /** Tab + group header label. */ label: string; /** Tab icon — Hugeicons data or a React SVG component. */ icon?: AppIcon; /** * Base score bonus applied to items of this category when searching. * Lets you keep e.g. commands above raw data in mixed results. */ searchBoost?: number; /** Search input placeholder when this tab is active. */ placeholder?: string; } // ============================================================================= // VIEW EXTENSION // ============================================================================= /** API handed to custom views (e.g. an AI chat view). */ export interface PaletteViewApi { /** Query captured when the view was entered (e.g. via Tab). */ initialQuery: string; /** Return to the search view. */ backToSearch: () => void; /** Close the palette entirely. */ closePalette: () => void; } /** A pluggable custom view. */ export type PaletteViewRenderer = (api: PaletteViewApi) => ReactNode;