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.cjs +115 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -34
- package/dist/index.d.ts +68 -34
- package/dist/index.js +115 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -260,11 +260,9 @@ interface EndpointResponse {
|
|
|
260
260
|
*/
|
|
261
261
|
type EndpointPaginationMode = 'scroll' | 'buttons' | 'none';
|
|
262
262
|
/**
|
|
263
|
-
*
|
|
263
|
+
* Base configuration shared by async and sync endpoints
|
|
264
264
|
*/
|
|
265
|
-
interface
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
1403
|
-
*
|
|
1404
|
-
*
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1413
|
-
*
|
|
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
|
-
*
|
|
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
|
-
*
|
|
263
|
+
* Base configuration shared by async and sync endpoints
|
|
264
264
|
*/
|
|
265
|
-
interface
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
*
|
|
1401
|
-
*
|
|
1402
|
-
*
|
|
1403
|
-
*
|
|
1404
|
-
*
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1409
|
-
*
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1413
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
|
1735
|
-
|
|
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
|
-
|
|
1740
|
-
|
|
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
|
|
2202
|
+
if (!endpointsRegistry) {
|
|
2181
2203
|
setEndpointStates(/* @__PURE__ */ new Map());
|
|
2182
2204
|
return;
|
|
2183
2205
|
}
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
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
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
const
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
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
|
|
2218
|
-
|
|
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
|
-
}
|
|
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);
|