import * as React from "react"; export type CommandPaletteItem = { id: string; label: React.ReactNode; /** * Decorative glyph before the label — a folder, a file, an emoji (gh#1159). Sized like a menu * row's icon (`--menu-icon-size`) and hidden from assistive tech: the label is the name. */ icon?: React.ReactNode; searchValue?: string; meta?: React.ReactNode; disabled?: boolean; }; export type CommandPaletteGroup = { id: string; label: React.ReactNode; items: CommandPaletteItem[]; }; export type CommandPaletteLabels = { open: string; title: string; description: string; placeholder: string; empty: React.ReactNode; loading?: React.ReactNode; move?: React.ReactNode; select?: React.ReactNode; close?: React.ReactNode; }; /** * Recent queries the CONSUMER keeps (gh#1249). The palette only renders them — it never reads or * writes `localStorage` or any other store, and it renders `items` exactly as given (de-duplicate * and cap them before passing them in). */ export type CommandPaletteRecent = { /** Most recent first. Duplicates are rendered as given. */ items: string[]; /** A recent query was chosen. The palette closes, like any other selection. */ onSelect: (query: string) => void; /** The trailing "Clear recent searches" row was chosen. The palette stays open. */ onClear: () => void; /** Group heading. Default: `t("dataEntry.commandPalette.recent")`. */ label?: React.ReactNode; }; /** The modifier keys held while an item was chosen (gh#1126). */ export type CommandPaletteSelectModifiers = { metaKey: boolean; ctrlKey: boolean; shiftKey: boolean; altKey: boolean; }; export type CommandPaletteProps = { groups: CommandPaletteGroup[]; labels: CommandPaletteLabels; /** * Fires with the chosen item and the modifier keys held while choosing it (gh#1126) — Enter or a * click with ⌘/Ctrl/Shift/Alt — so a host can "open in split" or "open in a new tab". */ onSelect: (item: CommandPaletteItem, modifiers: CommandPaletteSelectModifiers) => void; open?: boolean; defaultOpen?: boolean; onOpenChange?: (open: boolean) => void; /** * Controlled search-box query. Pairs with `onSearchChange`; leave it out for the uncontrolled * palette (seeded by `defaultSearch`). */ search?: string; /** Initial uncontrolled query, and the value the palette resets to when it closes. Default `""`. */ defaultSearch?: string; /** * Fires on every keystroke with the current query — the seam a server-backed group needs to run * search-as-you-type. Also fires with `defaultSearch` when the palette closes. */ onSearchChange?: (query: string) => void; /** * Whether the palette filters `groups` itself (cmdk's client-side fuzzy match). Set `false` when * the QUERY is answered by a server and `groups` already holds the matches — otherwise every row * is scored a second time against the same string and late-arriving matches are dropped. */ shouldFilter?: boolean; loading?: boolean; error?: React.ReactNode; /** * The control that opens the palette. * * `undefined` (omitted) — the default outline Button with the ⌘K hint. * `null` — **NO trigger at all**, for a palette driven purely by `shortcut`. * * The two are deliberately NOT the same, and that is the whole point of gh#778: the previous * `trigger ?? ` collapsed them, so `null` — the spelling every consumer reaches for — * silently rendered the very Button it was asked to remove. The only working spelling was * `trigger={<>}`, which is a hack that renders an empty fragment into the trigger slot. * * A keyboard-only palette is a NORMAL shape: `shortcut` already binds ⌘K/Ctrl+K and handles * `event.isComposing` (i.e. every keystroke of a Japanese IME) and focus restore, so it is a * better handler than a consumer's own. A topbar with no width to spare should be able to say so. */ trigger?: React.ReactNode; /** * The global shortcut that toggles the palette (gh#1126). `true` (default) is ⌘K / Ctrl+K; * `false` binds none; a combo string — `"mod+o"`, `"mod+p"`, `"mod+shift+p"` — binds that, so two * palettes (a quick switcher and a command palette) can live side by side. `mod` is ⌘ on Apple * and Ctrl elsewhere — never both, so Ctrl+O keeps its editing meaning on a Mac; `shift` and * `alt` must match exactly, so `mod+p` and * `mod+shift+p` are different shortcuts. Never fires during IME composition. */ shortcut?: boolean | string; /** * Recent queries (gh#1249), shown as the FIRST group only while the query is empty, with a * trailing "Clear recent searches" row. Storage stays with the consumer. */ recent?: CommandPaletteRecent; }; /** * Unchanged. - **`shouldFilter={false}` (server-side)** — the PALETTE owns it, derived * synchronously from props: the empty node renders when `groups` carries no items, and never while * `loading` or `error` is set. cmdk's own empty node cannot be trusted here, because it is driven * by a scheduled count of the items that have REGISTERED in the DOM, not by what the consumer * knows — so an async group that populates a frame late flips it on and off and any assertion over * it races. Reading `groups` instead makes "did we render the empty state?" a pure function of the * props at that render, which is what a contract test can assert. */ export declare function CommandPalette({ groups, labels, onSelect, open: controlledOpen, defaultOpen, onOpenChange, search: controlledSearch, defaultSearch, onSearchChange, shouldFilter, loading, error, trigger, shortcut, recent, }: CommandPaletteProps): React.JSX.Element;