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 CHANGED
@@ -178,7 +178,8 @@ function useActionsRegistry(options = {}) {
178
178
  registry[id] = {
179
179
  label: config.label,
180
180
  group: config.group,
181
- keywords: config.keywords
181
+ keywords: config.keywords,
182
+ hideFromModal: config.hideFromModal
182
183
  };
183
184
  }
184
185
  return registry;
@@ -298,7 +299,6 @@ function useOmnibarEndpointsRegistry() {
298
299
  const queryEndpoint = react.useCallback(async (endpointId, query, pagination, signal) => {
299
300
  const ep = endpointsRef.current.get(endpointId);
300
301
  if (!ep) return null;
301
- if (ep.config.enabled === false) return null;
302
302
  if (query.length < (ep.config.minQueryLength ?? 2)) return null;
303
303
  try {
304
304
  const response = await ep.config.fetch(query, signal, pagination);
@@ -325,7 +325,11 @@ function useOmnibarEndpointsRegistry() {
325
325
  }, []);
326
326
  const queryAll = react.useCallback(async (query, signal) => {
327
327
  const endpoints2 = Array.from(endpointsRef.current.values());
328
- const promises = endpoints2.filter((ep) => ep.config.enabled !== false).filter((ep) => query.length >= (ep.config.minQueryLength ?? 2)).map(async (ep) => {
328
+ const filteredByMinQuery = endpoints2.filter((ep) => {
329
+ const minLen = ep.config.minQueryLength ?? 2;
330
+ return query.length >= minLen;
331
+ });
332
+ const promises = filteredByMinQuery.map(async (ep) => {
329
333
  const pageSize = ep.config.pageSize ?? 10;
330
334
  const result = await queryEndpoint(ep.id, query, { offset: 0, limit: pageSize }, signal);
331
335
  return result ?? { endpointId: ep.id, entries: [] };
@@ -1733,18 +1737,36 @@ function useOmnibarEndpoint(id, config) {
1733
1737
  }
1734
1738
  const registryRef = react.useRef(registry);
1735
1739
  registryRef.current = registry;
1736
- const fetchRef = react.useRef(config.fetch);
1737
- fetchRef.current = config.fetch;
1740
+ const isSync = "filter" in config && config.filter !== void 0;
1741
+ const fetchFn = isSync ? void 0 : config.fetch;
1742
+ const filterFn = isSync ? config.filter : void 0;
1743
+ const fetchRef = react.useRef(fetchFn);
1744
+ fetchRef.current = fetchFn;
1745
+ const filterRef = react.useRef(filterFn);
1746
+ filterRef.current = filterFn;
1747
+ const isSyncRef = react.useRef(isSync);
1748
+ isSyncRef.current = isSync;
1738
1749
  const enabledRef = react.useRef(config.enabled ?? true);
1739
1750
  enabledRef.current = config.enabled ?? true;
1740
1751
  react.useEffect(() => {
1741
- registryRef.current.register(id, {
1742
- ...config,
1752
+ const asyncConfig = {
1753
+ group: config.group,
1754
+ priority: config.priority,
1755
+ minQueryLength: config.minQueryLength,
1756
+ enabled: config.enabled,
1757
+ pageSize: config.pageSize,
1758
+ pagination: config.pagination,
1759
+ isSync: isSyncRef.current,
1760
+ // Track sync endpoints to skip debouncing
1743
1761
  fetch: async (query, signal, pagination) => {
1744
1762
  if (!enabledRef.current) return { entries: [] };
1763
+ if (isSyncRef.current && filterRef.current) {
1764
+ return filterRef.current(query, pagination);
1765
+ }
1745
1766
  return fetchRef.current(query, signal, pagination);
1746
1767
  }
1747
- });
1768
+ };
1769
+ registryRef.current.register(id, asyncConfig);
1748
1770
  return () => {
1749
1771
  registryRef.current.unregister(id);
1750
1772
  };
@@ -1755,7 +1777,7 @@ function useOmnibarEndpoint(id, config) {
1755
1777
  config.minQueryLength,
1756
1778
  config.pageSize,
1757
1779
  config.pagination
1758
- // Note: we use refs for fetch and enabled, so they don't cause re-registration
1780
+ // Note: we use refs for fetch/filter and enabled, so they don't cause re-registration
1759
1781
  ]);
1760
1782
  }
1761
1783
  function useEventCallback(fn) {
@@ -2179,50 +2201,99 @@ function useOmnibar(options) {
2179
2201
  abortControllerRef.current.abort();
2180
2202
  abortControllerRef.current = null;
2181
2203
  }
2182
- if (!endpointsRegistry || !query.trim()) {
2204
+ if (!endpointsRegistry) {
2183
2205
  setEndpointStates(/* @__PURE__ */ new Map());
2184
2206
  return;
2185
2207
  }
2186
- setEndpointStates((prev) => {
2187
- const next = new Map(prev);
2188
- for (const [id] of endpointsRegistry.endpoints) {
2189
- next.set(id, { entries: [], offset: 0, isLoading: true });
2208
+ const syncEndpoints = [];
2209
+ const asyncEndpoints = [];
2210
+ for (const [id, ep] of endpointsRegistry.endpoints) {
2211
+ if (ep.config.isSync) {
2212
+ syncEndpoints.push(id);
2213
+ } else {
2214
+ asyncEndpoints.push(id);
2190
2215
  }
2191
- return next;
2192
- });
2193
- debounceTimerRef.current = setTimeout(async () => {
2194
- const controller = new AbortController();
2195
- abortControllerRef.current = controller;
2196
- try {
2197
- const endpointResults = await endpointsRegistry.queryAll(query, controller.signal);
2198
- if (controller.signal.aborted) return;
2199
- setEndpointStates(() => {
2200
- const next = /* @__PURE__ */ new Map();
2201
- for (const epResult of endpointResults) {
2202
- const ep = endpointsRegistry.endpoints.get(epResult.endpointId);
2203
- const pageSize = ep?.config.pageSize ?? 10;
2204
- next.set(epResult.endpointId, {
2205
- entries: epResult.entries,
2206
- offset: pageSize,
2207
- total: epResult.total,
2208
- hasMore: epResult.hasMore ?? (epResult.total !== void 0 ? epResult.entries.length < epResult.total : void 0),
2209
- isLoading: false
2210
- });
2211
- }
2212
- return next;
2213
- });
2214
- } catch (error) {
2215
- if (error instanceof Error && error.name === "AbortError") return;
2216
- console.error("Omnibar endpoint query failed:", error);
2216
+ }
2217
+ const updateEndpointState = (epResult) => {
2218
+ const ep = endpointsRegistry.endpoints.get(epResult.endpointId);
2219
+ const pageSize = ep?.config.pageSize ?? 10;
2220
+ return {
2221
+ entries: epResult.entries,
2222
+ offset: pageSize,
2223
+ total: epResult.total,
2224
+ hasMore: epResult.hasMore ?? (epResult.total !== void 0 ? epResult.entries.length < epResult.total : void 0),
2225
+ isLoading: false
2226
+ };
2227
+ };
2228
+ if (syncEndpoints.length > 0) {
2229
+ const syncController = new AbortController();
2230
+ Promise.all(
2231
+ syncEndpoints.map(
2232
+ (id) => endpointsRegistry.queryEndpoint(id, query, { offset: 0, limit: endpointsRegistry.endpoints.get(id)?.config.pageSize ?? 10 }, syncController.signal)
2233
+ )
2234
+ ).then((results2) => {
2235
+ if (syncController.signal.aborted) return;
2217
2236
  setEndpointStates((prev) => {
2218
2237
  const next = new Map(prev);
2219
- for (const [id, state] of next) {
2220
- next.set(id, { ...state, isLoading: false });
2238
+ for (const result of results2) {
2239
+ if (result) {
2240
+ next.set(result.endpointId, updateEndpointState(result));
2241
+ }
2221
2242
  }
2222
2243
  return next;
2223
2244
  });
2224
- }
2225
- }, debounceMs);
2245
+ });
2246
+ }
2247
+ if (asyncEndpoints.length > 0) {
2248
+ setEndpointStates((prev) => {
2249
+ const next = new Map(prev);
2250
+ for (const id of asyncEndpoints) {
2251
+ const existing = prev.get(id);
2252
+ next.set(id, {
2253
+ entries: existing?.entries ?? [],
2254
+ offset: existing?.offset ?? 0,
2255
+ total: existing?.total,
2256
+ hasMore: existing?.hasMore,
2257
+ isLoading: true
2258
+ });
2259
+ }
2260
+ return next;
2261
+ });
2262
+ debounceTimerRef.current = setTimeout(async () => {
2263
+ const controller = new AbortController();
2264
+ abortControllerRef.current = controller;
2265
+ try {
2266
+ const results2 = await Promise.all(
2267
+ asyncEndpoints.map(
2268
+ (id) => endpointsRegistry.queryEndpoint(id, query, { offset: 0, limit: endpointsRegistry.endpoints.get(id)?.config.pageSize ?? 10 }, controller.signal)
2269
+ )
2270
+ );
2271
+ if (controller.signal.aborted) return;
2272
+ setEndpointStates((prev) => {
2273
+ const next = new Map(prev);
2274
+ for (const result of results2) {
2275
+ if (result) {
2276
+ next.set(result.endpointId, updateEndpointState(result));
2277
+ }
2278
+ }
2279
+ return next;
2280
+ });
2281
+ } catch (error) {
2282
+ if (error instanceof Error && error.name === "AbortError") return;
2283
+ console.error("Omnibar endpoint query failed:", error);
2284
+ setEndpointStates((prev) => {
2285
+ const next = new Map(prev);
2286
+ for (const id of asyncEndpoints) {
2287
+ const state = next.get(id);
2288
+ if (state) {
2289
+ next.set(id, { ...state, isLoading: false });
2290
+ }
2291
+ }
2292
+ return next;
2293
+ });
2294
+ }
2295
+ }, debounceMs);
2296
+ }
2226
2297
  return () => {
2227
2298
  if (debounceTimerRef.current) {
2228
2299
  clearTimeout(debounceTimerRef.current);