@fluixi/reactive 1.0.0-alpha.100
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/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/cdn/reactive.cjs +2803 -0
- package/dist/cdn/reactive.d.ts +11 -0
- package/dist/cdn/reactive.d.ts.map +1 -0
- package/dist/cdn/reactive.global.js +2 -0
- package/dist/cdn/reactive.js +10 -0
- package/dist/cdn/reactive.mjs +2787 -0
- package/dist/cdn/signal.cjs +299 -0
- package/dist/cdn/signal.d.ts +19 -0
- package/dist/cdn/signal.d.ts.map +1 -0
- package/dist/cdn/signal.global.js +2 -0
- package/dist/cdn/signal.js +18 -0
- package/dist/cdn/signal.mjs +276 -0
- package/dist/index.cjs +2803 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +2787 -0
- package/dist/lib/index.cjs +2804 -0
- package/dist/lib/index.d.ts +8 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.mjs +2789 -0
- package/dist/lib/observable/index.cjs +386 -0
- package/dist/lib/observable/index.d.ts +4 -0
- package/dist/lib/observable/index.d.ts.map +1 -0
- package/dist/lib/observable/index.js +3 -0
- package/dist/lib/observable/index.mjs +364 -0
- package/dist/lib/observable/observable.cjs +384 -0
- package/dist/lib/observable/observable.d.ts +246 -0
- package/dist/lib/observable/observable.d.ts.map +1 -0
- package/dist/lib/observable/observable.js +268 -0
- package/dist/lib/observable/observable.mjs +361 -0
- package/dist/lib/observable/subscription.cjs +180 -0
- package/dist/lib/observable/subscription.d.ts +58 -0
- package/dist/lib/observable/subscription.d.ts.map +1 -0
- package/dist/lib/observable/subscription.js +177 -0
- package/dist/lib/observable/subscription.mjs +157 -0
- package/dist/lib/observable/types.cjs +18 -0
- package/dist/lib/observable/types.d.ts +44 -0
- package/dist/lib/observable/types.d.ts.map +1 -0
- package/dist/lib/observable/types.js +1 -0
- package/dist/lib/observable/types.mjs +0 -0
- package/dist/lib/predicates.cjs +44 -0
- package/dist/lib/predicates.d.ts +37 -0
- package/dist/lib/predicates.d.ts.map +1 -0
- package/dist/lib/predicates.js +62 -0
- package/dist/lib/predicates.mjs +23 -0
- package/dist/lib/signal/api.cjs +592 -0
- package/dist/lib/signal/api.d.ts +227 -0
- package/dist/lib/signal/api.d.ts.map +1 -0
- package/dist/lib/signal/api.js +228 -0
- package/dist/lib/signal/api.mjs +569 -0
- package/dist/lib/signal/cached-resource.cjs +726 -0
- package/dist/lib/signal/cached-resource.d.ts +86 -0
- package/dist/lib/signal/cached-resource.d.ts.map +1 -0
- package/dist/lib/signal/cached-resource.js +250 -0
- package/dist/lib/signal/cached-resource.mjs +704 -0
- package/dist/lib/signal/graph/children.cjs +326 -0
- package/dist/lib/signal/graph/children.d.ts +2 -0
- package/dist/lib/signal/graph/children.d.ts.map +1 -0
- package/dist/lib/signal/graph/children.js +30 -0
- package/dist/lib/signal/graph/children.mjs +303 -0
- package/dist/lib/signal/graph/compat.cjs +590 -0
- package/dist/lib/signal/graph/compat.d.ts +66 -0
- package/dist/lib/signal/graph/compat.d.ts.map +1 -0
- package/dist/lib/signal/graph/compat.js +197 -0
- package/dist/lib/signal/graph/compat.mjs +568 -0
- package/dist/lib/signal/graph/core.cjs +295 -0
- package/dist/lib/signal/graph/core.d.ts +99 -0
- package/dist/lib/signal/graph/core.d.ts.map +1 -0
- package/dist/lib/signal/graph/core.js +268 -0
- package/dist/lib/signal/graph/core.mjs +273 -0
- package/dist/lib/signal/graph/debounced.cjs +680 -0
- package/dist/lib/signal/graph/debounced.d.ts +67 -0
- package/dist/lib/signal/graph/debounced.d.ts.map +1 -0
- package/dist/lib/signal/graph/debounced.js +92 -0
- package/dist/lib/signal/graph/debounced.mjs +657 -0
- package/dist/lib/signal/graph/derived.cjs +508 -0
- package/dist/lib/signal/graph/derived.d.ts +14 -0
- package/dist/lib/signal/graph/derived.d.ts.map +1 -0
- package/dist/lib/signal/graph/derived.js +65 -0
- package/dist/lib/signal/graph/derived.mjs +485 -0
- package/dist/lib/signal/graph/detect.cjs +66 -0
- package/dist/lib/signal/graph/detect.d.ts +17 -0
- package/dist/lib/signal/graph/detect.d.ts.map +1 -0
- package/dist/lib/signal/graph/detect.js +39 -0
- package/dist/lib/signal/graph/detect.mjs +45 -0
- package/dist/lib/signal/graph/error-boundary.cjs +313 -0
- package/dist/lib/signal/graph/error-boundary.d.ts +16 -0
- package/dist/lib/signal/graph/error-boundary.d.ts.map +1 -0
- package/dist/lib/signal/graph/error-boundary.js +34 -0
- package/dist/lib/signal/graph/error-boundary.mjs +290 -0
- package/dist/lib/signal/graph/index.cjs +305 -0
- package/dist/lib/signal/graph/index.d.ts +22 -0
- package/dist/lib/signal/graph/index.d.ts.map +1 -0
- package/dist/lib/signal/graph/index.js +21 -0
- package/dist/lib/signal/graph/index.mjs +283 -0
- package/dist/lib/signal/graph/observe.cjs +198 -0
- package/dist/lib/signal/graph/observe.d.ts +185 -0
- package/dist/lib/signal/graph/observe.d.ts.map +1 -0
- package/dist/lib/signal/graph/observe.js +198 -0
- package/dist/lib/signal/graph/observe.mjs +175 -0
- package/dist/lib/signal/graph/resource.cjs +632 -0
- package/dist/lib/signal/graph/resource.d.ts +39 -0
- package/dist/lib/signal/graph/resource.d.ts.map +1 -0
- package/dist/lib/signal/graph/resource.js +165 -0
- package/dist/lib/signal/graph/resource.mjs +609 -0
- package/dist/lib/signal/graph/runtime.cjs +522 -0
- package/dist/lib/signal/graph/runtime.d.ts +80 -0
- package/dist/lib/signal/graph/runtime.d.ts.map +1 -0
- package/dist/lib/signal/graph/runtime.js +358 -0
- package/dist/lib/signal/graph/runtime.mjs +499 -0
- package/dist/lib/signal/graph/signal-next.cjs +1249 -0
- package/dist/lib/signal/graph/signal-next.d.ts +38 -0
- package/dist/lib/signal/graph/signal-next.d.ts.map +1 -0
- package/dist/lib/signal/graph/signal-next.js +44 -0
- package/dist/lib/signal/graph/signal-next.mjs +1227 -0
- package/dist/lib/signal/graph/ssr-hooks.cjs +89 -0
- package/dist/lib/signal/graph/ssr-hooks.d.ts +51 -0
- package/dist/lib/signal/graph/ssr-hooks.d.ts.map +1 -0
- package/dist/lib/signal/graph/ssr-hooks.js +80 -0
- package/dist/lib/signal/graph/ssr-hooks.mjs +68 -0
- package/dist/lib/signal/graph/state.cjs +72 -0
- package/dist/lib/signal/graph/state.d.ts +76 -0
- package/dist/lib/signal/graph/state.d.ts.map +1 -0
- package/dist/lib/signal/graph/state.js +99 -0
- package/dist/lib/signal/graph/state.mjs +49 -0
- package/dist/lib/signal/graph/suspense.cjs +313 -0
- package/dist/lib/signal/graph/suspense.d.ts +13 -0
- package/dist/lib/signal/graph/suspense.d.ts.map +1 -0
- package/dist/lib/signal/graph/suspense.js +36 -0
- package/dist/lib/signal/graph/suspense.mjs +290 -0
- package/dist/lib/signal/index-legacy.cjs +2582 -0
- package/dist/lib/signal/index-legacy.d.ts +12 -0
- package/dist/lib/signal/index-legacy.d.ts.map +1 -0
- package/dist/lib/signal/index-legacy.js +11 -0
- package/dist/lib/signal/index-legacy.mjs +2560 -0
- package/dist/lib/signal/index.cjs +1350 -0
- package/dist/lib/signal/index.d.ts +19 -0
- package/dist/lib/signal/index.d.ts.map +1 -0
- package/dist/lib/signal/index.js +19 -0
- package/dist/lib/signal/index.mjs +1328 -0
- package/dist/lib/signal/list.cjs +561 -0
- package/dist/lib/signal/list.d.ts +39 -0
- package/dist/lib/signal/list.d.ts.map +1 -0
- package/dist/lib/signal/list.js +172 -0
- package/dist/lib/signal/list.mjs +538 -0
- package/dist/lib/signal/resource-api.cjs +638 -0
- package/dist/lib/signal/resource-api.d.ts +19 -0
- package/dist/lib/signal/resource-api.d.ts.map +1 -0
- package/dist/lib/signal/resource-api.js +27 -0
- package/dist/lib/signal/resource-api.mjs +615 -0
- package/dist/lib/signal/signal.cjs +2035 -0
- package/dist/lib/signal/signal.d.ts +303 -0
- package/dist/lib/signal/signal.d.ts.map +1 -0
- package/dist/lib/signal/signal.js +1233 -0
- package/dist/lib/signal/signal.mjs +2012 -0
- package/dist/lib/signal/types.cjs +38 -0
- package/dist/lib/signal/types.d.ts +133 -0
- package/dist/lib/signal/types.d.ts.map +1 -0
- package/dist/lib/signal/types.js +38 -0
- package/dist/lib/signal/types.mjs +17 -0
- package/dist/lib/signal/utilities.cjs +1024 -0
- package/dist/lib/signal/utilities.d.ts +247 -0
- package/dist/lib/signal/utilities.d.ts.map +1 -0
- package/dist/lib/signal/utilities.js +346 -0
- package/dist/lib/signal/utilities.mjs +1002 -0
- package/dist/lib/store/api.cjs +662 -0
- package/dist/lib/store/api.d.ts +40 -0
- package/dist/lib/store/api.d.ts.map +1 -0
- package/dist/lib/store/api.js +63 -0
- package/dist/lib/store/api.mjs +646 -0
- package/dist/lib/store/index.cjs +741 -0
- package/dist/lib/store/index.d.ts +16 -0
- package/dist/lib/store/index.d.ts.map +1 -0
- package/dist/lib/store/index.js +13 -0
- package/dist/lib/store/index.mjs +726 -0
- package/dist/lib/store/setter.types.cjs +18 -0
- package/dist/lib/store/setter.types.d.ts +131 -0
- package/dist/lib/store/setter.types.d.ts.map +1 -0
- package/dist/lib/store/setter.types.js +65 -0
- package/dist/lib/store/setter.types.mjs +0 -0
- package/dist/lib/store/store.cjs +708 -0
- package/dist/lib/store/store.d.ts +142 -0
- package/dist/lib/store/store.d.ts.map +1 -0
- package/dist/lib/store/store.js +812 -0
- package/dist/lib/store/store.mjs +694 -0
- package/dist/lib/store/types.cjs +18 -0
- package/dist/lib/store/types.d.ts +57 -0
- package/dist/lib/store/types.d.ts.map +1 -0
- package/dist/lib/store/types.js +1 -0
- package/dist/lib/store/types.mjs +0 -0
- package/dist/lib/store/utils.cjs +43 -0
- package/dist/lib/store/utils.d.ts +13 -0
- package/dist/lib/store/utils.d.ts.map +1 -0
- package/dist/lib/store/utils.js +29 -0
- package/dist/lib/store/utils.mjs +22 -0
- package/dist/lib/subject.cjs +450 -0
- package/dist/lib/subject.d.ts +14 -0
- package/dist/lib/subject.d.ts.map +1 -0
- package/dist/lib/subject.js +81 -0
- package/dist/lib/subject.mjs +427 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/version.generated.cjs +27 -0
- package/dist/version.generated.d.ts +3 -0
- package/dist/version.generated.d.ts.map +1 -0
- package/dist/version.generated.js +3 -0
- package/dist/version.generated.mjs +7 -0
- package/package.json +115 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Accessor, Setter } from './compat.js';
|
|
2
|
+
import type { ResourceFetcherInfo, ResourceReturn } from './resource.js';
|
|
3
|
+
/** Controls beyond reading and writing the value. */
|
|
4
|
+
export interface DebounceControls<T> {
|
|
5
|
+
/** The value as written, before the delay: bind a controlled input to this. */
|
|
6
|
+
immediate: Accessor<T>;
|
|
7
|
+
/** True while a write is waiting to settle. Distinct from a request in flight. */
|
|
8
|
+
pending: Accessor<boolean>;
|
|
9
|
+
/** Settle now, dropping the remaining delay. Returns the value that settled. */
|
|
10
|
+
flush: () => T;
|
|
11
|
+
/** Discard a pending write; the settled value keeps its last value. */
|
|
12
|
+
cancel: () => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A signal whose settled value trails writes by `delay`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const [query, setQuery, { immediate, pending, flush }] = createDebouncedSignal('', 300);
|
|
20
|
+
*
|
|
21
|
+
* // the input never lags: it binds the immediate value
|
|
22
|
+
* <input value={immediate()} onInput={(e) => setQuery(e.currentTarget.value)}
|
|
23
|
+
* onKeyDown={(e) => e.key === 'Enter' && flush()} />
|
|
24
|
+
*
|
|
25
|
+
* // work keys off the settled value
|
|
26
|
+
* createEffect(() => search(query()));
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function createDebouncedSignal<T>(initial: T, delay?: number): [Accessor<T>, Setter<T>, DebounceControls<T>];
|
|
30
|
+
export interface DebouncedResourceOptions<T> {
|
|
31
|
+
/** Delay before a change reaches the fetcher. Defaults to 300ms. */
|
|
32
|
+
delay?: number;
|
|
33
|
+
/** Seed value, so the resource has something to read before the first fetch. */
|
|
34
|
+
initialValue?: T;
|
|
35
|
+
/**
|
|
36
|
+
* Whether a settled query should be fetched at all. Defaults to rejecting
|
|
37
|
+
* `undefined`, `null` and `''`, an empty search box shouldn't hit the network.
|
|
38
|
+
*/
|
|
39
|
+
shouldFetch?: (query: unknown) => boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface DebouncedResourceControls<S> extends DebounceControls<S> {
|
|
42
|
+
/** The settled query the resource is fetching for. */
|
|
43
|
+
query: Accessor<S>;
|
|
44
|
+
setQuery: Setter<S>;
|
|
45
|
+
refetch: (info?: unknown) => unknown;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A resource driven by a debounced query: search-as-you-type, as one primitive.
|
|
49
|
+
*
|
|
50
|
+
* Two waiting states exist and they are not the same thing: `pending` is "the user
|
|
51
|
+
* is still typing", `resource.loading` is "a request is in flight". A UI that
|
|
52
|
+
* conflates them either flickers on every keystroke or looks frozen while typing.
|
|
53
|
+
*
|
|
54
|
+
* An empty query doesn't fetch, so a cleared search box doesn't hit the network.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* const [results, { setQuery, immediate, pending, flush }] =
|
|
59
|
+
* createDebouncedResource('', (q) => api.search(q));
|
|
60
|
+
*
|
|
61
|
+
* <input value={immediate()} onInput={(e) => setQuery(e.currentTarget.value)} />
|
|
62
|
+
* <Show when={pending()}>typing...</Show>
|
|
63
|
+
* <Show when={results.loading}>searching...</Show>
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function createDebouncedResource<T, S>(initial: S, fetcher: (query: S, info: ResourceFetcherInfo<T>) => T | Promise<T>, options?: DebouncedResourceOptions<T>): [ResourceReturn<T>[0], DebouncedResourceControls<S>];
|
|
67
|
+
//# sourceMappingURL=debounced.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debounced.d.ts","sourceRoot":"","sources":["../../../../src/lib/signal/graph/debounced.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEzE,qDAAqD;AACrD,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,+EAA+E;IAC/E,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvB,kFAAkF;IAClF,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC3B,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC,CAAC;IACf,uEAAuE;IACvE,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EACrC,OAAO,EAAE,CAAC,EACV,KAAK,SAAM,GACV,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAqC/C;AAED,MAAM,WAAW,wBAAwB,CAAC,CAAC;IACzC,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;IACvE,sDAAsD;IACtD,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;CACtC;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAC1C,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACnE,OAAO,GAAE,wBAAwB,CAAC,CAAC,CAAM,GACxC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAetD"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debounced reactive values.
|
|
3
|
+
*
|
|
4
|
+
* The shape that matters: a debounced input has TWO values, not one. The
|
|
5
|
+
* immediate value is what the user is typing and what a controlled input must be
|
|
6
|
+
* bound to; the settled value is what a query should run on. Collapsing them into
|
|
7
|
+
* a single delayed signal makes a controlled input lag behind the keyboard, which
|
|
8
|
+
* is why this exposes both rather than only the settled one.
|
|
9
|
+
*
|
|
10
|
+
* `flush` and `cancel` are part of the primitive, not extras: a search box needs
|
|
11
|
+
* "submit now" on Enter, and navigating away needs to drop a pending write instead
|
|
12
|
+
* of firing it into a disposed scope.
|
|
13
|
+
*/
|
|
14
|
+
import { createSignal, onCleanup, untrack } from './compat.js';
|
|
15
|
+
import { createResource } from './resource.js';
|
|
16
|
+
/**
|
|
17
|
+
* A signal whose settled value trails writes by `delay`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const [query, setQuery, { immediate, pending, flush }] = createDebouncedSignal('', 300);
|
|
22
|
+
*
|
|
23
|
+
* // the input never lags: it binds the immediate value
|
|
24
|
+
* <input value={immediate()} onInput={(e) => setQuery(e.currentTarget.value)}
|
|
25
|
+
* onKeyDown={(e) => e.key === 'Enter' && flush()} />
|
|
26
|
+
*
|
|
27
|
+
* // work keys off the settled value
|
|
28
|
+
* createEffect(() => search(query()));
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function createDebouncedSignal(initial, delay = 300) {
|
|
32
|
+
const [immediate, setImmediate] = createSignal(initial);
|
|
33
|
+
const [settled, setSettled] = createSignal(initial);
|
|
34
|
+
const [pending, setPending] = createSignal(false);
|
|
35
|
+
let timer;
|
|
36
|
+
const clear = () => {
|
|
37
|
+
if (timer === undefined)
|
|
38
|
+
return;
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
timer = undefined;
|
|
41
|
+
};
|
|
42
|
+
const settle = () => {
|
|
43
|
+
clear();
|
|
44
|
+
// untrack, settling is a write, and must not subscribe whoever triggered it.
|
|
45
|
+
const value = untrack(immediate);
|
|
46
|
+
setSettled(() => value);
|
|
47
|
+
setPending(false);
|
|
48
|
+
return value;
|
|
49
|
+
};
|
|
50
|
+
const set = ((value) => {
|
|
51
|
+
const next = typeof value === 'function' ? value(untrack(immediate)) : value;
|
|
52
|
+
setImmediate(() => next);
|
|
53
|
+
setPending(true);
|
|
54
|
+
clear();
|
|
55
|
+
timer = setTimeout(settle, delay);
|
|
56
|
+
return next;
|
|
57
|
+
});
|
|
58
|
+
// A pending write into a disposed scope is a write nobody asked for.
|
|
59
|
+
onCleanup(clear);
|
|
60
|
+
return [settled, set, { immediate, pending, flush: settle, cancel: () => { clear(); setPending(false); } }];
|
|
61
|
+
}
|
|
62
|
+
function meaningful(query) {
|
|
63
|
+
return query !== undefined && query !== null && query !== '';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* A resource driven by a debounced query: search-as-you-type, as one primitive.
|
|
67
|
+
*
|
|
68
|
+
* Two waiting states exist and they are not the same thing: `pending` is "the user
|
|
69
|
+
* is still typing", `resource.loading` is "a request is in flight". A UI that
|
|
70
|
+
* conflates them either flickers on every keystroke or looks frozen while typing.
|
|
71
|
+
*
|
|
72
|
+
* An empty query doesn't fetch, so a cleared search box doesn't hit the network.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const [results, { setQuery, immediate, pending, flush }] =
|
|
77
|
+
* createDebouncedResource('', (q) => api.search(q));
|
|
78
|
+
*
|
|
79
|
+
* <input value={immediate()} onInput={(e) => setQuery(e.currentTarget.value)} />
|
|
80
|
+
* <Show when={pending()}>typing...</Show>
|
|
81
|
+
* <Show when={results.loading}>searching...</Show>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function createDebouncedResource(initial, fetcher, options = {}) {
|
|
85
|
+
const { delay = 300, initialValue, shouldFetch = meaningful } = options;
|
|
86
|
+
const [query, setQuery, controls] = createDebouncedSignal(initial, delay);
|
|
87
|
+
// createResource treats a falsy source as "don't fetch", which is exactly the
|
|
88
|
+
// empty-query case, so the predicate rides on the source rather than the fetcher.
|
|
89
|
+
const source = () => (shouldFetch(query()) ? query() : false);
|
|
90
|
+
const [resource, { refetch }] = createResource(source, fetcher, initialValue === undefined ? {} : { initialValue });
|
|
91
|
+
return [resource, { ...controls, query, setQuery, refetch }];
|
|
92
|
+
}
|