import { DecafContextType } from '@decafhub/decaf-react'; import { DecafMenuItem } from '../types'; /** * A single entry shown in the command palette. * * Each item must define exactly one of `to`, `href`, or `onSelect` to be * actionable. When more than one is set, precedence is `to` > `href` > * `onSelect`. Items with none of them are silently dropped during render. * * The palette searches over `label`, `to`, `href`, `group`, and `keywords` * (case-insensitive substring match). `icon` is rendered but not searched. */ export interface CommandPaletteItem { /** * Display text shown in the row and matched by the search query. * * Always a plain string. Menu items whose `label` is JSX (e.g. * `Portfolios`) are converted to text by recursively walking * the element tree and concatenating its string children — sufficient for * typical icon-and-text or styled-text labels. */ label: string; /** * Internal route. When the user selects the item, the palette closes and * navigates with React Router (`useNavigate`). Use this for in-app pages. * * Mutually exclusive with `href` and `onSelect`. If multiple are set, `to` * wins. */ to?: string; /** * URL navigated to on selection. The palette closes first, then: * - same-origin paths (e.g. `/webapps/foo/production/`) trigger a full-page * navigation in the same tab — typical "switch to sibling webapp" flow; * - cross-origin URLs open in a new tab with `noopener,noreferrer`. * * If you specifically need a new tab for a same-origin URL, use `onSelect` * and call `window.open` yourself. * * Mutually exclusive with `to` and `onSelect`. If both `href` and * `onSelect` are set, `href` wins. */ href?: string; /** * Arbitrary action invoked on selection. The palette closes *before* the * handler runs, so slow handlers don't leave the modal frozen. Errors are * not caught — they propagate to the consumer's error boundary / antd * notification setup. * * Use for things like "refresh cache", "toggle theme", "open feedback * dialog" — anything that isn't a navigation. * * Mutually exclusive with `to` and `href`; only invoked when both are * absent. */ onSelect?: () => void; /** * Category hint rendered next to the label, e.g. "Admin", "Reports". Also * included in the search haystack. * * Items derived from the menu tree get this automatically: a parent that * has only `children` (no `to`/`href`) acts as a pure header, and its * label propagates as the `group` of its descendants. The deepest pure * header wins. */ group?: string; /** * Optional icon rendered to the left of the label. Any React node — most * commonly an `@ant-design/icons` element. Inherited from the menu item * when the palette item is menu-derived. */ icon?: React.ReactNode; /** * Extra search aliases that are matched by the query but never rendered. * * Useful for synonyms users might type — e.g. an item labelled * "Refresh data" might carry `keywords: ['reload', 'invalidate', 'flush']` * so any of those terms surface the same row. */ keywords?: string[]; } /** * Configuration for the command palette feature, passed via * `DecafWebappProps.commandPalette`. * * The final palette list is built in three steps, in order: * * 1. **Defaults**: every actionable node in `buildMenuItems(context)` is * flattened into a `CommandPaletteItem`. Pure-header parents propagate * their label as the `group` of their descendants. * 2. **Append**: `extraItems` is concatenated after the defaults. This is * the right place to add a few static entries (docs, status, etc.). * 3. **Transform**: `buildItems(merged, context)` runs last and may * filter, reorder, or replace the list entirely. Skip this prop if the * defaults + `extraItems` are enough. * * Both fields are optional. Omit the whole `commandPalette` prop (or pass * `undefined`) to get the default palette derived from the menu only. Pass * `false` on `DecafWebappProps.commandPalette` to disable the feature * entirely (no header indicator, no global hotkey, no modal). */ export interface CommandPaletteOptions { /** * Items appended to the menu-derived defaults. * * The recommended way to add a small number of static entries (links to * external docs, shortcut actions, etc.) without having to spread the * default items yourself. These items are appended *before* `buildItems` * runs, so a `buildItems` transform sees them too. * * @example * extraItems: [ * { label: 'Open docs', href: 'https://docs.example.com', group: 'Help' }, * { label: 'Refresh data', group: 'Actions', onSelect: () => qc.invalidateQueries() }, * ] */ extraItems?: CommandPaletteItem[]; /** * Final transform applied to the merged list of `defaults + extraItems`. * * Use when you need full control: privilege-based filtering, reordering, * deduplication, replacing the list entirely. Receives the merged items * and the live `DecafContextType` so the transform can branch on the * authenticated user, tenant, etc. * * Returning `[]` produces an empty palette (the feature stays enabled and * the modal still opens, but shows "No results"). Returning a brand-new * array silently discards the defaults — useful, but easy to do by * accident; prefer `extraItems` when you only want to *add* entries. * * @example * buildItems: (items, ctx) => * ctx.me.privileged ? items : items.filter((i) => !i.to?.startsWith('/admin')) */ buildItems?: (items: CommandPaletteItem[], context: DecafContextType) => CommandPaletteItem[]; } /** * Walk a menu tree and yield a flat list of palette items. * * A node is selectable when it has `to` or `href`. A node that has only * `children` acts as a group header — its label propagates as `group` * to descendants that don't already carry one. The deepest ancestor wins. */ export declare function flattenMenu(items: DecafMenuItem[]): CommandPaletteItem[]; //# sourceMappingURL=CommandPalette.utils.d.ts.map