use-kbd 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -260,11 +260,9 @@ interface EndpointResponse {
260
260
  */
261
261
  type EndpointPaginationMode = 'scroll' | 'buttons' | 'none';
262
262
  /**
263
- * Configuration for a remote omnibar endpoint
263
+ * Base configuration shared by async and sync endpoints
264
264
  */
265
- interface OmnibarEndpointConfig {
266
- /** Fetch function that returns entries for a query */
267
- fetch: (query: string, signal: AbortSignal, pagination: EndpointPagination) => Promise<EndpointResponse>;
265
+ interface OmnibarEndpointConfigBase {
268
266
  /** Default group for entries from this endpoint */
269
267
  group?: string;
270
268
  /** Priority for result ordering (higher = shown first, default: 0, local actions: 100) */
@@ -278,6 +276,30 @@ interface OmnibarEndpointConfig {
278
276
  /** Pagination mode (default: 'none') */
279
277
  pagination?: EndpointPaginationMode;
280
278
  }
279
+ /**
280
+ * Configuration for an async omnibar endpoint (remote API calls)
281
+ */
282
+ interface OmnibarEndpointAsyncConfig extends OmnibarEndpointConfigBase {
283
+ /** Async fetch function for remote data sources */
284
+ fetch: (query: string, signal: AbortSignal, pagination: EndpointPagination) => Promise<EndpointResponse>;
285
+ filter?: never;
286
+ /** Internal: true if this was originally a sync endpoint (skip debouncing) */
287
+ isSync?: boolean;
288
+ }
289
+ /**
290
+ * Configuration for a sync omnibar endpoint (in-memory filtering)
291
+ *
292
+ * Sync endpoints skip debouncing for instant results.
293
+ */
294
+ interface OmnibarEndpointSyncConfig extends OmnibarEndpointConfigBase {
295
+ /** Sync filter function for in-memory data sources */
296
+ filter: (query: string, pagination: EndpointPagination) => EndpointResponse;
297
+ fetch?: never;
298
+ }
299
+ /**
300
+ * Configuration for an omnibar endpoint (async or sync)
301
+ */
302
+ type OmnibarEndpointConfig = OmnibarEndpointAsyncConfig | OmnibarEndpointSyncConfig;
281
303
 
282
304
  /**
283
305
  * Hotkey definition - maps key combinations/sequences to action names
@@ -393,7 +415,8 @@ declare function useEditableHotkeys(defaults: HotkeyMap, handlers: HandlerMap, o
393
415
 
394
416
  interface RegisteredEndpoint {
395
417
  id: string;
396
- config: OmnibarEndpointConfig;
418
+ /** Internal config is always async (useOmnibarEndpoint normalizes sync endpoints) */
419
+ config: OmnibarEndpointAsyncConfig;
397
420
  registeredAt: number;
398
421
  }
399
422
  /**
@@ -410,7 +433,7 @@ interface EndpointQueryResult {
410
433
  }
411
434
  interface OmnibarEndpointsRegistryValue {
412
435
  /** Register an endpoint. Called by useOmnibarEndpoint on mount. */
413
- register: (id: string, config: OmnibarEndpointConfig) => void;
436
+ register: (id: string, config: OmnibarEndpointAsyncConfig) => void;
414
437
  /** Unregister an endpoint. Called by useOmnibarEndpoint on unmount. */
415
438
  unregister: (id: string) => void;
416
439
  /** Currently registered endpoints */
@@ -1388,39 +1411,50 @@ declare function useHotkeysContext(): HotkeysContextValue;
1388
1411
  declare function useMaybeHotkeysContext(): HotkeysContextValue | null;
1389
1412
 
1390
1413
  /**
1391
- * Register a remote omnibar endpoint.
1414
+ * Register an omnibar endpoint for dynamic search results.
1415
+ *
1416
+ * Supports both async (remote API) and sync (in-memory) endpoints:
1417
+ * - Use `fetch` for async operations that need AbortSignal support
1418
+ * - Use `filter` for sync in-memory filtering (skips debouncing for instant results)
1392
1419
  *
1393
1420
  * Endpoints are automatically unregistered when the component unmounts,
1394
1421
  * making this ideal for colocating search providers with their data context.
1395
1422
  *
1396
- * @example
1423
+ * @example Async endpoint (remote API)
1397
1424
  * ```tsx
1398
- * function UsersPage() {
1399
- * const navigate = useNavigate()
1400
- *
1401
- * useOmnibarEndpoint('users', {
1402
- * fetch: async (query, signal, pagination) => {
1403
- * const res = await fetch(`/api/users?q=${query}&offset=${pagination.offset}&limit=${pagination.limit}`, { signal })
1404
- * const { users, total } = await res.json()
1405
- * return {
1406
- * entries: users.map(u => ({
1407
- * id: `user:${u.id}`,
1408
- * label: u.name,
1409
- * description: u.email,
1410
- * handler: () => navigate(`/users/${u.id}`),
1411
- * })),
1412
- * total,
1413
- * hasMore: pagination.offset + users.length < total,
1414
- * }
1415
- * },
1416
- * group: 'Users',
1417
- * priority: 10,
1418
- * pageSize: 10,
1419
- * pagination: 'scroll',
1420
- * })
1425
+ * useOmnibarEndpoint('users', {
1426
+ * fetch: async (query, signal, pagination) => {
1427
+ * const res = await fetch(`/api/users?q=${query}`, { signal })
1428
+ * const { users, total } = await res.json()
1429
+ * return {
1430
+ * entries: users.map(u => ({
1431
+ * id: `user:${u.id}`,
1432
+ * label: u.name,
1433
+ * handler: () => navigate(`/users/${u.id}`),
1434
+ * })),
1435
+ * total,
1436
+ * hasMore: pagination.offset + users.length < total,
1437
+ * }
1438
+ * },
1439
+ * group: 'Users',
1440
+ * })
1441
+ * ```
1421
1442
  *
1422
- * return <UsersList />
1423
- * }
1443
+ * @example Sync endpoint (in-memory filtering)
1444
+ * ```tsx
1445
+ * useOmnibarEndpoint('stations', {
1446
+ * filter: (query, pagination) => {
1447
+ * const matches = stations.filter(s => s.name.includes(query))
1448
+ * return {
1449
+ * entries: matches.slice(pagination.offset, pagination.offset + pagination.limit)
1450
+ * .map(s => ({ id: s.id, label: s.name, handler: () => select(s) })),
1451
+ * total: matches.length,
1452
+ * hasMore: pagination.offset + pagination.limit < matches.length,
1453
+ * }
1454
+ * },
1455
+ * group: 'Stations',
1456
+ * minQueryLength: 0,
1457
+ * })
1424
1458
  * ```
1425
1459
  */
1426
1460
  declare function useOmnibarEndpoint(id: string, config: OmnibarEndpointConfig): void;
@@ -1631,4 +1665,4 @@ declare const ACTION_MODAL = "__hotkeys:modal";
1631
1665
  declare const ACTION_OMNIBAR = "__hotkeys:omnibar";
1632
1666
  declare const ACTION_LOOKUP = "__hotkeys:lookup";
1633
1667
 
1634
- export { ACTION_LOOKUP, ACTION_MODAL, ACTION_OMNIBAR, type ActionConfig, type ActionDefinition, type ActionHandler, type ActionRegistry, type ActionSearchResult, ActionsRegistryContext, type ActionsRegistryValue, Alt, Backspace, type BindingInfo, Command, Ctrl, DEFAULT_SEQUENCE_TIMEOUT, DIGITS_PLACEHOLDER, DIGIT_PLACEHOLDER, Down, type EndpointPagination, type EndpointPaginationInfo, type EndpointPaginationMode, type EndpointQueryResult, type EndpointResponse, Enter, type FuzzyMatchResult, type GroupRenderer, type GroupRendererProps, type HandlerMap, type HotkeyHandler, type HotkeyMap, type HotkeySequence, type HotkeysConfig, type HotkeysContextValue, HotkeysProvider, type HotkeysProviderProps, Kbd, KbdLookup, KbdModal, KbdOmnibar, type KbdProps, Kbds, Key, type KeyCombination, type KeyCombinationDisplay, type KeyConflict, type KeyIconProps, type KeyIconType, type KeySeq, KeybindingEditor, type KeybindingEditorProps, type KeybindingEditorRenderProps, Left, LookupModal, ModifierIcon, type ModifierIconProps, type ModifierType, type Modifiers, Omnibar, type OmnibarActionEntry, type OmnibarEndpointConfig, OmnibarEndpointsRegistryContext, type OmnibarEndpointsRegistryValue, type OmnibarEntry, type OmnibarEntryBase, type OmnibarLinkEntry, type OmnibarProps, type OmnibarRenderProps, Option, type RecordHotkeyOptions, type RecordHotkeyResult, type RegisteredAction, type RegisteredEndpoint, type RemoteOmnibarResult, Right, type SeqElem, type SeqElemState, type SeqMatchState, type SequenceCompletion, SequenceModal, Shift, type ShortcutGroup, ShortcutsModal, type ShortcutsModalProps, type ShortcutsModalRenderProps, type TooltipComponent, type TooltipProps, type TwoColumnConfig, type TwoColumnRow, Up, type UseEditableHotkeysOptions, type UseEditableHotkeysResult, type UseHotkeysOptions, type UseHotkeysResult, type UseOmnibarOptions, type UseOmnibarResult, countPlaceholders, createTwoColumnRenderer, extractCaptures, findConflicts, formatBinding, formatCombination, formatKeyForDisplay, formatKeySeq, fuzzyMatch, getActionBindings, getConflictsArray, getKeyIcon, getModifierIcon, getSequenceCompletions, hasConflicts, hasDigitPlaceholders, hotkeySequenceToKeySeq, isDigitPlaceholder, isMac, isModifierKey, isPlaceholderSentinel, isSequence, isShiftedSymbol, keySeqToHotkeySequence, normalizeKey, parseHotkeyString, parseKeySeq, searchActions, useAction, useActions, useActionsRegistry, useEditableHotkeys, useHotkeys, useHotkeysContext, useMaybeHotkeysContext, useOmnibar, useOmnibarEndpoint, useOmnibarEndpointsRegistry, useRecordHotkey };
1668
+ export { ACTION_LOOKUP, ACTION_MODAL, ACTION_OMNIBAR, type ActionConfig, type ActionDefinition, type ActionHandler, type ActionRegistry, type ActionSearchResult, ActionsRegistryContext, type ActionsRegistryValue, Alt, Backspace, type BindingInfo, Command, Ctrl, DEFAULT_SEQUENCE_TIMEOUT, DIGITS_PLACEHOLDER, DIGIT_PLACEHOLDER, Down, type EndpointPagination, type EndpointPaginationInfo, type EndpointPaginationMode, type EndpointQueryResult, type EndpointResponse, Enter, type FuzzyMatchResult, type GroupRenderer, type GroupRendererProps, type HandlerMap, type HotkeyHandler, type HotkeyMap, type HotkeySequence, type HotkeysConfig, type HotkeysContextValue, HotkeysProvider, type HotkeysProviderProps, Kbd, KbdLookup, KbdModal, KbdOmnibar, type KbdProps, Kbds, Key, type KeyCombination, type KeyCombinationDisplay, type KeyConflict, type KeyIconProps, type KeyIconType, type KeySeq, KeybindingEditor, type KeybindingEditorProps, type KeybindingEditorRenderProps, Left, LookupModal, ModifierIcon, type ModifierIconProps, type ModifierType, type Modifiers, Omnibar, type OmnibarActionEntry, type OmnibarEndpointAsyncConfig, type OmnibarEndpointConfig, type OmnibarEndpointConfigBase, type OmnibarEndpointSyncConfig, OmnibarEndpointsRegistryContext, type OmnibarEndpointsRegistryValue, type OmnibarEntry, type OmnibarEntryBase, type OmnibarLinkEntry, type OmnibarProps, type OmnibarRenderProps, Option, type RecordHotkeyOptions, type RecordHotkeyResult, type RegisteredAction, type RegisteredEndpoint, type RemoteOmnibarResult, Right, type SeqElem, type SeqElemState, type SeqMatchState, type SequenceCompletion, SequenceModal, Shift, type ShortcutGroup, ShortcutsModal, type ShortcutsModalProps, type ShortcutsModalRenderProps, type TooltipComponent, type TooltipProps, type TwoColumnConfig, type TwoColumnRow, Up, type UseEditableHotkeysOptions, type UseEditableHotkeysResult, type UseHotkeysOptions, type UseHotkeysResult, type UseOmnibarOptions, type UseOmnibarResult, countPlaceholders, createTwoColumnRenderer, extractCaptures, findConflicts, formatBinding, formatCombination, formatKeyForDisplay, formatKeySeq, fuzzyMatch, getActionBindings, getConflictsArray, getKeyIcon, getModifierIcon, getSequenceCompletions, hasConflicts, hasDigitPlaceholders, hotkeySequenceToKeySeq, isDigitPlaceholder, isMac, isModifierKey, isPlaceholderSentinel, isSequence, isShiftedSymbol, keySeqToHotkeySequence, normalizeKey, parseHotkeyString, parseKeySeq, searchActions, useAction, useActions, useActionsRegistry, useEditableHotkeys, useHotkeys, useHotkeysContext, useMaybeHotkeysContext, useOmnibar, useOmnibarEndpoint, useOmnibarEndpointsRegistry, useRecordHotkey };
package/dist/index.d.ts CHANGED
@@ -260,11 +260,9 @@ interface EndpointResponse {
260
260
  */
261
261
  type EndpointPaginationMode = 'scroll' | 'buttons' | 'none';
262
262
  /**
263
- * Configuration for a remote omnibar endpoint
263
+ * Base configuration shared by async and sync endpoints
264
264
  */
265
- interface OmnibarEndpointConfig {
266
- /** Fetch function that returns entries for a query */
267
- fetch: (query: string, signal: AbortSignal, pagination: EndpointPagination) => Promise<EndpointResponse>;
265
+ interface OmnibarEndpointConfigBase {
268
266
  /** Default group for entries from this endpoint */
269
267
  group?: string;
270
268
  /** Priority for result ordering (higher = shown first, default: 0, local actions: 100) */
@@ -278,6 +276,30 @@ interface OmnibarEndpointConfig {
278
276
  /** Pagination mode (default: 'none') */
279
277
  pagination?: EndpointPaginationMode;
280
278
  }
279
+ /**
280
+ * Configuration for an async omnibar endpoint (remote API calls)
281
+ */
282
+ interface OmnibarEndpointAsyncConfig extends OmnibarEndpointConfigBase {
283
+ /** Async fetch function for remote data sources */
284
+ fetch: (query: string, signal: AbortSignal, pagination: EndpointPagination) => Promise<EndpointResponse>;
285
+ filter?: never;
286
+ /** Internal: true if this was originally a sync endpoint (skip debouncing) */
287
+ isSync?: boolean;
288
+ }
289
+ /**
290
+ * Configuration for a sync omnibar endpoint (in-memory filtering)
291
+ *
292
+ * Sync endpoints skip debouncing for instant results.
293
+ */
294
+ interface OmnibarEndpointSyncConfig extends OmnibarEndpointConfigBase {
295
+ /** Sync filter function for in-memory data sources */
296
+ filter: (query: string, pagination: EndpointPagination) => EndpointResponse;
297
+ fetch?: never;
298
+ }
299
+ /**
300
+ * Configuration for an omnibar endpoint (async or sync)
301
+ */
302
+ type OmnibarEndpointConfig = OmnibarEndpointAsyncConfig | OmnibarEndpointSyncConfig;
281
303
 
282
304
  /**
283
305
  * Hotkey definition - maps key combinations/sequences to action names
@@ -393,7 +415,8 @@ declare function useEditableHotkeys(defaults: HotkeyMap, handlers: HandlerMap, o
393
415
 
394
416
  interface RegisteredEndpoint {
395
417
  id: string;
396
- config: OmnibarEndpointConfig;
418
+ /** Internal config is always async (useOmnibarEndpoint normalizes sync endpoints) */
419
+ config: OmnibarEndpointAsyncConfig;
397
420
  registeredAt: number;
398
421
  }
399
422
  /**
@@ -410,7 +433,7 @@ interface EndpointQueryResult {
410
433
  }
411
434
  interface OmnibarEndpointsRegistryValue {
412
435
  /** Register an endpoint. Called by useOmnibarEndpoint on mount. */
413
- register: (id: string, config: OmnibarEndpointConfig) => void;
436
+ register: (id: string, config: OmnibarEndpointAsyncConfig) => void;
414
437
  /** Unregister an endpoint. Called by useOmnibarEndpoint on unmount. */
415
438
  unregister: (id: string) => void;
416
439
  /** Currently registered endpoints */
@@ -1388,39 +1411,50 @@ declare function useHotkeysContext(): HotkeysContextValue;
1388
1411
  declare function useMaybeHotkeysContext(): HotkeysContextValue | null;
1389
1412
 
1390
1413
  /**
1391
- * Register a remote omnibar endpoint.
1414
+ * Register an omnibar endpoint for dynamic search results.
1415
+ *
1416
+ * Supports both async (remote API) and sync (in-memory) endpoints:
1417
+ * - Use `fetch` for async operations that need AbortSignal support
1418
+ * - Use `filter` for sync in-memory filtering (skips debouncing for instant results)
1392
1419
  *
1393
1420
  * Endpoints are automatically unregistered when the component unmounts,
1394
1421
  * making this ideal for colocating search providers with their data context.
1395
1422
  *
1396
- * @example
1423
+ * @example Async endpoint (remote API)
1397
1424
  * ```tsx
1398
- * function UsersPage() {
1399
- * const navigate = useNavigate()
1400
- *
1401
- * useOmnibarEndpoint('users', {
1402
- * fetch: async (query, signal, pagination) => {
1403
- * const res = await fetch(`/api/users?q=${query}&offset=${pagination.offset}&limit=${pagination.limit}`, { signal })
1404
- * const { users, total } = await res.json()
1405
- * return {
1406
- * entries: users.map(u => ({
1407
- * id: `user:${u.id}`,
1408
- * label: u.name,
1409
- * description: u.email,
1410
- * handler: () => navigate(`/users/${u.id}`),
1411
- * })),
1412
- * total,
1413
- * hasMore: pagination.offset + users.length < total,
1414
- * }
1415
- * },
1416
- * group: 'Users',
1417
- * priority: 10,
1418
- * pageSize: 10,
1419
- * pagination: 'scroll',
1420
- * })
1425
+ * useOmnibarEndpoint('users', {
1426
+ * fetch: async (query, signal, pagination) => {
1427
+ * const res = await fetch(`/api/users?q=${query}`, { signal })
1428
+ * const { users, total } = await res.json()
1429
+ * return {
1430
+ * entries: users.map(u => ({
1431
+ * id: `user:${u.id}`,
1432
+ * label: u.name,
1433
+ * handler: () => navigate(`/users/${u.id}`),
1434
+ * })),
1435
+ * total,
1436
+ * hasMore: pagination.offset + users.length < total,
1437
+ * }
1438
+ * },
1439
+ * group: 'Users',
1440
+ * })
1441
+ * ```
1421
1442
  *
1422
- * return <UsersList />
1423
- * }
1443
+ * @example Sync endpoint (in-memory filtering)
1444
+ * ```tsx
1445
+ * useOmnibarEndpoint('stations', {
1446
+ * filter: (query, pagination) => {
1447
+ * const matches = stations.filter(s => s.name.includes(query))
1448
+ * return {
1449
+ * entries: matches.slice(pagination.offset, pagination.offset + pagination.limit)
1450
+ * .map(s => ({ id: s.id, label: s.name, handler: () => select(s) })),
1451
+ * total: matches.length,
1452
+ * hasMore: pagination.offset + pagination.limit < matches.length,
1453
+ * }
1454
+ * },
1455
+ * group: 'Stations',
1456
+ * minQueryLength: 0,
1457
+ * })
1424
1458
  * ```
1425
1459
  */
1426
1460
  declare function useOmnibarEndpoint(id: string, config: OmnibarEndpointConfig): void;
@@ -1631,4 +1665,4 @@ declare const ACTION_MODAL = "__hotkeys:modal";
1631
1665
  declare const ACTION_OMNIBAR = "__hotkeys:omnibar";
1632
1666
  declare const ACTION_LOOKUP = "__hotkeys:lookup";
1633
1667
 
1634
- export { ACTION_LOOKUP, ACTION_MODAL, ACTION_OMNIBAR, type ActionConfig, type ActionDefinition, type ActionHandler, type ActionRegistry, type ActionSearchResult, ActionsRegistryContext, type ActionsRegistryValue, Alt, Backspace, type BindingInfo, Command, Ctrl, DEFAULT_SEQUENCE_TIMEOUT, DIGITS_PLACEHOLDER, DIGIT_PLACEHOLDER, Down, type EndpointPagination, type EndpointPaginationInfo, type EndpointPaginationMode, type EndpointQueryResult, type EndpointResponse, Enter, type FuzzyMatchResult, type GroupRenderer, type GroupRendererProps, type HandlerMap, type HotkeyHandler, type HotkeyMap, type HotkeySequence, type HotkeysConfig, type HotkeysContextValue, HotkeysProvider, type HotkeysProviderProps, Kbd, KbdLookup, KbdModal, KbdOmnibar, type KbdProps, Kbds, Key, type KeyCombination, type KeyCombinationDisplay, type KeyConflict, type KeyIconProps, type KeyIconType, type KeySeq, KeybindingEditor, type KeybindingEditorProps, type KeybindingEditorRenderProps, Left, LookupModal, ModifierIcon, type ModifierIconProps, type ModifierType, type Modifiers, Omnibar, type OmnibarActionEntry, type OmnibarEndpointConfig, OmnibarEndpointsRegistryContext, type OmnibarEndpointsRegistryValue, type OmnibarEntry, type OmnibarEntryBase, type OmnibarLinkEntry, type OmnibarProps, type OmnibarRenderProps, Option, type RecordHotkeyOptions, type RecordHotkeyResult, type RegisteredAction, type RegisteredEndpoint, type RemoteOmnibarResult, Right, type SeqElem, type SeqElemState, type SeqMatchState, type SequenceCompletion, SequenceModal, Shift, type ShortcutGroup, ShortcutsModal, type ShortcutsModalProps, type ShortcutsModalRenderProps, type TooltipComponent, type TooltipProps, type TwoColumnConfig, type TwoColumnRow, Up, type UseEditableHotkeysOptions, type UseEditableHotkeysResult, type UseHotkeysOptions, type UseHotkeysResult, type UseOmnibarOptions, type UseOmnibarResult, countPlaceholders, createTwoColumnRenderer, extractCaptures, findConflicts, formatBinding, formatCombination, formatKeyForDisplay, formatKeySeq, fuzzyMatch, getActionBindings, getConflictsArray, getKeyIcon, getModifierIcon, getSequenceCompletions, hasConflicts, hasDigitPlaceholders, hotkeySequenceToKeySeq, isDigitPlaceholder, isMac, isModifierKey, isPlaceholderSentinel, isSequence, isShiftedSymbol, keySeqToHotkeySequence, normalizeKey, parseHotkeyString, parseKeySeq, searchActions, useAction, useActions, useActionsRegistry, useEditableHotkeys, useHotkeys, useHotkeysContext, useMaybeHotkeysContext, useOmnibar, useOmnibarEndpoint, useOmnibarEndpointsRegistry, useRecordHotkey };
1668
+ export { ACTION_LOOKUP, ACTION_MODAL, ACTION_OMNIBAR, type ActionConfig, type ActionDefinition, type ActionHandler, type ActionRegistry, type ActionSearchResult, ActionsRegistryContext, type ActionsRegistryValue, Alt, Backspace, type BindingInfo, Command, Ctrl, DEFAULT_SEQUENCE_TIMEOUT, DIGITS_PLACEHOLDER, DIGIT_PLACEHOLDER, Down, type EndpointPagination, type EndpointPaginationInfo, type EndpointPaginationMode, type EndpointQueryResult, type EndpointResponse, Enter, type FuzzyMatchResult, type GroupRenderer, type GroupRendererProps, type HandlerMap, type HotkeyHandler, type HotkeyMap, type HotkeySequence, type HotkeysConfig, type HotkeysContextValue, HotkeysProvider, type HotkeysProviderProps, Kbd, KbdLookup, KbdModal, KbdOmnibar, type KbdProps, Kbds, Key, type KeyCombination, type KeyCombinationDisplay, type KeyConflict, type KeyIconProps, type KeyIconType, type KeySeq, KeybindingEditor, type KeybindingEditorProps, type KeybindingEditorRenderProps, Left, LookupModal, ModifierIcon, type ModifierIconProps, type ModifierType, type Modifiers, Omnibar, type OmnibarActionEntry, type OmnibarEndpointAsyncConfig, type OmnibarEndpointConfig, type OmnibarEndpointConfigBase, type OmnibarEndpointSyncConfig, OmnibarEndpointsRegistryContext, type OmnibarEndpointsRegistryValue, type OmnibarEntry, type OmnibarEntryBase, type OmnibarLinkEntry, type OmnibarProps, type OmnibarRenderProps, Option, type RecordHotkeyOptions, type RecordHotkeyResult, type RegisteredAction, type RegisteredEndpoint, type RemoteOmnibarResult, Right, type SeqElem, type SeqElemState, type SeqMatchState, type SequenceCompletion, SequenceModal, Shift, type ShortcutGroup, ShortcutsModal, type ShortcutsModalProps, type ShortcutsModalRenderProps, type TooltipComponent, type TooltipProps, type TwoColumnConfig, type TwoColumnRow, Up, type UseEditableHotkeysOptions, type UseEditableHotkeysResult, type UseHotkeysOptions, type UseHotkeysResult, type UseOmnibarOptions, type UseOmnibarResult, countPlaceholders, createTwoColumnRenderer, extractCaptures, findConflicts, formatBinding, formatCombination, formatKeyForDisplay, formatKeySeq, fuzzyMatch, getActionBindings, getConflictsArray, getKeyIcon, getModifierIcon, getSequenceCompletions, hasConflicts, hasDigitPlaceholders, hotkeySequenceToKeySeq, isDigitPlaceholder, isMac, isModifierKey, isPlaceholderSentinel, isSequence, isShiftedSymbol, keySeqToHotkeySequence, normalizeKey, parseHotkeyString, parseKeySeq, searchActions, useAction, useActions, useActionsRegistry, useEditableHotkeys, useHotkeys, useHotkeysContext, useMaybeHotkeysContext, useOmnibar, useOmnibarEndpoint, useOmnibarEndpointsRegistry, useRecordHotkey };
package/dist/index.js CHANGED
@@ -176,7 +176,8 @@ function useActionsRegistry(options = {}) {
176
176
  registry[id] = {
177
177
  label: config.label,
178
178
  group: config.group,
179
- keywords: config.keywords
179
+ keywords: config.keywords,
180
+ hideFromModal: config.hideFromModal
180
181
  };
181
182
  }
182
183
  return registry;
@@ -296,7 +297,6 @@ function useOmnibarEndpointsRegistry() {
296
297
  const queryEndpoint = useCallback(async (endpointId, query, pagination, signal) => {
297
298
  const ep = endpointsRef.current.get(endpointId);
298
299
  if (!ep) return null;
299
- if (ep.config.enabled === false) return null;
300
300
  if (query.length < (ep.config.minQueryLength ?? 2)) return null;
301
301
  try {
302
302
  const response = await ep.config.fetch(query, signal, pagination);
@@ -323,7 +323,11 @@ function useOmnibarEndpointsRegistry() {
323
323
  }, []);
324
324
  const queryAll = useCallback(async (query, signal) => {
325
325
  const endpoints2 = Array.from(endpointsRef.current.values());
326
- const promises = endpoints2.filter((ep) => ep.config.enabled !== false).filter((ep) => query.length >= (ep.config.minQueryLength ?? 2)).map(async (ep) => {
326
+ const filteredByMinQuery = endpoints2.filter((ep) => {
327
+ const minLen = ep.config.minQueryLength ?? 2;
328
+ return query.length >= minLen;
329
+ });
330
+ const promises = filteredByMinQuery.map(async (ep) => {
327
331
  const pageSize = ep.config.pageSize ?? 10;
328
332
  const result = await queryEndpoint(ep.id, query, { offset: 0, limit: pageSize }, signal);
329
333
  return result ?? { endpointId: ep.id, entries: [] };
@@ -1731,18 +1735,36 @@ function useOmnibarEndpoint(id, config) {
1731
1735
  }
1732
1736
  const registryRef = useRef(registry);
1733
1737
  registryRef.current = registry;
1734
- const fetchRef = useRef(config.fetch);
1735
- fetchRef.current = config.fetch;
1738
+ const isSync = "filter" in config && config.filter !== void 0;
1739
+ const fetchFn = isSync ? void 0 : config.fetch;
1740
+ const filterFn = isSync ? config.filter : void 0;
1741
+ const fetchRef = useRef(fetchFn);
1742
+ fetchRef.current = fetchFn;
1743
+ const filterRef = useRef(filterFn);
1744
+ filterRef.current = filterFn;
1745
+ const isSyncRef = useRef(isSync);
1746
+ isSyncRef.current = isSync;
1736
1747
  const enabledRef = useRef(config.enabled ?? true);
1737
1748
  enabledRef.current = config.enabled ?? true;
1738
1749
  useEffect(() => {
1739
- registryRef.current.register(id, {
1740
- ...config,
1750
+ const asyncConfig = {
1751
+ group: config.group,
1752
+ priority: config.priority,
1753
+ minQueryLength: config.minQueryLength,
1754
+ enabled: config.enabled,
1755
+ pageSize: config.pageSize,
1756
+ pagination: config.pagination,
1757
+ isSync: isSyncRef.current,
1758
+ // Track sync endpoints to skip debouncing
1741
1759
  fetch: async (query, signal, pagination) => {
1742
1760
  if (!enabledRef.current) return { entries: [] };
1761
+ if (isSyncRef.current && filterRef.current) {
1762
+ return filterRef.current(query, pagination);
1763
+ }
1743
1764
  return fetchRef.current(query, signal, pagination);
1744
1765
  }
1745
- });
1766
+ };
1767
+ registryRef.current.register(id, asyncConfig);
1746
1768
  return () => {
1747
1769
  registryRef.current.unregister(id);
1748
1770
  };
@@ -1753,7 +1775,7 @@ function useOmnibarEndpoint(id, config) {
1753
1775
  config.minQueryLength,
1754
1776
  config.pageSize,
1755
1777
  config.pagination
1756
- // Note: we use refs for fetch and enabled, so they don't cause re-registration
1778
+ // Note: we use refs for fetch/filter and enabled, so they don't cause re-registration
1757
1779
  ]);
1758
1780
  }
1759
1781
  function useEventCallback(fn) {
@@ -2177,50 +2199,99 @@ function useOmnibar(options) {
2177
2199
  abortControllerRef.current.abort();
2178
2200
  abortControllerRef.current = null;
2179
2201
  }
2180
- if (!endpointsRegistry || !query.trim()) {
2202
+ if (!endpointsRegistry) {
2181
2203
  setEndpointStates(/* @__PURE__ */ new Map());
2182
2204
  return;
2183
2205
  }
2184
- setEndpointStates((prev) => {
2185
- const next = new Map(prev);
2186
- for (const [id] of endpointsRegistry.endpoints) {
2187
- next.set(id, { entries: [], offset: 0, isLoading: true });
2206
+ const syncEndpoints = [];
2207
+ const asyncEndpoints = [];
2208
+ for (const [id, ep] of endpointsRegistry.endpoints) {
2209
+ if (ep.config.isSync) {
2210
+ syncEndpoints.push(id);
2211
+ } else {
2212
+ asyncEndpoints.push(id);
2188
2213
  }
2189
- return next;
2190
- });
2191
- debounceTimerRef.current = setTimeout(async () => {
2192
- const controller = new AbortController();
2193
- abortControllerRef.current = controller;
2194
- try {
2195
- const endpointResults = await endpointsRegistry.queryAll(query, controller.signal);
2196
- if (controller.signal.aborted) return;
2197
- setEndpointStates(() => {
2198
- const next = /* @__PURE__ */ new Map();
2199
- for (const epResult of endpointResults) {
2200
- const ep = endpointsRegistry.endpoints.get(epResult.endpointId);
2201
- const pageSize = ep?.config.pageSize ?? 10;
2202
- next.set(epResult.endpointId, {
2203
- entries: epResult.entries,
2204
- offset: pageSize,
2205
- total: epResult.total,
2206
- hasMore: epResult.hasMore ?? (epResult.total !== void 0 ? epResult.entries.length < epResult.total : void 0),
2207
- isLoading: false
2208
- });
2209
- }
2210
- return next;
2211
- });
2212
- } catch (error) {
2213
- if (error instanceof Error && error.name === "AbortError") return;
2214
- console.error("Omnibar endpoint query failed:", error);
2214
+ }
2215
+ const updateEndpointState = (epResult) => {
2216
+ const ep = endpointsRegistry.endpoints.get(epResult.endpointId);
2217
+ const pageSize = ep?.config.pageSize ?? 10;
2218
+ return {
2219
+ entries: epResult.entries,
2220
+ offset: pageSize,
2221
+ total: epResult.total,
2222
+ hasMore: epResult.hasMore ?? (epResult.total !== void 0 ? epResult.entries.length < epResult.total : void 0),
2223
+ isLoading: false
2224
+ };
2225
+ };
2226
+ if (syncEndpoints.length > 0) {
2227
+ const syncController = new AbortController();
2228
+ Promise.all(
2229
+ syncEndpoints.map(
2230
+ (id) => endpointsRegistry.queryEndpoint(id, query, { offset: 0, limit: endpointsRegistry.endpoints.get(id)?.config.pageSize ?? 10 }, syncController.signal)
2231
+ )
2232
+ ).then((results2) => {
2233
+ if (syncController.signal.aborted) return;
2215
2234
  setEndpointStates((prev) => {
2216
2235
  const next = new Map(prev);
2217
- for (const [id, state] of next) {
2218
- next.set(id, { ...state, isLoading: false });
2236
+ for (const result of results2) {
2237
+ if (result) {
2238
+ next.set(result.endpointId, updateEndpointState(result));
2239
+ }
2219
2240
  }
2220
2241
  return next;
2221
2242
  });
2222
- }
2223
- }, debounceMs);
2243
+ });
2244
+ }
2245
+ if (asyncEndpoints.length > 0) {
2246
+ setEndpointStates((prev) => {
2247
+ const next = new Map(prev);
2248
+ for (const id of asyncEndpoints) {
2249
+ const existing = prev.get(id);
2250
+ next.set(id, {
2251
+ entries: existing?.entries ?? [],
2252
+ offset: existing?.offset ?? 0,
2253
+ total: existing?.total,
2254
+ hasMore: existing?.hasMore,
2255
+ isLoading: true
2256
+ });
2257
+ }
2258
+ return next;
2259
+ });
2260
+ debounceTimerRef.current = setTimeout(async () => {
2261
+ const controller = new AbortController();
2262
+ abortControllerRef.current = controller;
2263
+ try {
2264
+ const results2 = await Promise.all(
2265
+ asyncEndpoints.map(
2266
+ (id) => endpointsRegistry.queryEndpoint(id, query, { offset: 0, limit: endpointsRegistry.endpoints.get(id)?.config.pageSize ?? 10 }, controller.signal)
2267
+ )
2268
+ );
2269
+ if (controller.signal.aborted) return;
2270
+ setEndpointStates((prev) => {
2271
+ const next = new Map(prev);
2272
+ for (const result of results2) {
2273
+ if (result) {
2274
+ next.set(result.endpointId, updateEndpointState(result));
2275
+ }
2276
+ }
2277
+ return next;
2278
+ });
2279
+ } catch (error) {
2280
+ if (error instanceof Error && error.name === "AbortError") return;
2281
+ console.error("Omnibar endpoint query failed:", error);
2282
+ setEndpointStates((prev) => {
2283
+ const next = new Map(prev);
2284
+ for (const id of asyncEndpoints) {
2285
+ const state = next.get(id);
2286
+ if (state) {
2287
+ next.set(id, { ...state, isLoading: false });
2288
+ }
2289
+ }
2290
+ return next;
2291
+ });
2292
+ }
2293
+ }, debounceMs);
2294
+ }
2224
2295
  return () => {
2225
2296
  if (debounceTimerRef.current) {
2226
2297
  clearTimeout(debounceTimerRef.current);