mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
Cmd/Ctrl+K or the search control at the end of the top bar opens a combobox over a client-side index built from the lists the navigation already renders: pages, Insights pages, every Settings section and card (deep-linked by a new anchor prop on SettingsCardHeader), the Appearance sub-pages, module switches and a few actions. Entries follow the module map, the Coach capability, the admin role and a shared record's grant; inside somebody else's record no cards, switches or backup are offered. Ranking is prefix, then word start, then substring, then a small edit distance, then subsequence, with a short multilingual synonym list. The empty state shows recent places (per account, in localStorage) and the main actions. The palette is its own lazily loaded chunk; the top bar shows a search field where it has room and a magnifier otherwise. The module switch mutation moves into a shared hook used by the Modules hub and the palette.
43 lines
1.1 KiB
TypeScript
43 lines
1.1 KiB
TypeScript
"use client";
|
|
|
|
import { useSyncExternalStore } from "react";
|
|
|
|
/**
|
|
* Whether the command palette is open, reachable from anywhere: the top-bar
|
|
* button, Cmd/Ctrl+K in the shortcut handler, and the palette itself. The
|
|
* palette's code is a separate chunk (`command-palette.lazy.tsx`); this file
|
|
* is the few lines every page carries.
|
|
*/
|
|
let open = false;
|
|
const listeners = new Set<() => void>();
|
|
|
|
export function setCommandPaletteOpen(next: boolean): void {
|
|
if (open === next) return;
|
|
open = next;
|
|
for (const listener of listeners) listener();
|
|
}
|
|
|
|
export function openCommandPalette(): void {
|
|
setCommandPaletteOpen(true);
|
|
}
|
|
|
|
function subscribe(listener: () => void): () => void {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
}
|
|
|
|
export function useCommandPaletteOpen(): boolean {
|
|
return useSyncExternalStore(
|
|
subscribe,
|
|
() => open,
|
|
() => false,
|
|
);
|
|
}
|
|
|
|
/** Start loading the palette's chunk ahead of the click (hover, focus). */
|
|
export function preloadCommandPalette(): void {
|
|
void import("./command-palette").catch(() => {
|
|
// The click loads it again and reports a failure there.
|
|
});
|
|
}
|