c7644ade69
@robonen/vue (toolkit): migrate to eslint flat config + composite tsconfig; fix composable + test type errors (writable computed returns, null guards, overload-compatible signatures, typed test helpers) — all type-level.
61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import { nextTick, watch } from 'vue';
|
|
import type { WatchCallback, WatchHandle, WatchOptions, WatchSource } from 'vue';
|
|
|
|
type Truthy<T> = T extends false | null | undefined | 0 | '' ? never : T;
|
|
|
|
export interface WheneverOptions<Immediate = boolean> extends WatchOptions<Immediate> {
|
|
/**
|
|
* Only trigger the callback once when the source becomes truthy.
|
|
*
|
|
* Overrides the `once` option inherited from `WatchOptions`.
|
|
*
|
|
* @default false
|
|
*/
|
|
once?: boolean;
|
|
}
|
|
|
|
/**
|
|
* @name whenever
|
|
* @category Reactivity
|
|
* @description Shorthand for watching a source to be truthy. Behaves like `watch`, but the callback only fires when the resolved value is truthy.
|
|
*
|
|
* @param {WatchSource<T>} source The reactive source to watch
|
|
* @param {WatchCallback} cb Invoked with the truthy value, previous value, and `onCleanup`
|
|
* @param {WheneverOptions} [options] Watch options (`immediate`, `deep`, `flush`, `once`)
|
|
* @returns {WatchHandle} A handle to stop watching
|
|
*
|
|
* @example
|
|
* const ready = ref(false);
|
|
* whenever(ready, () => console.log('ready!'));
|
|
*
|
|
* @example
|
|
* whenever(() => count.value > 5, () => console.log('over five'), { once: true });
|
|
*
|
|
* @since 0.0.15
|
|
*/
|
|
export function whenever<T>(source: WatchSource<T>, cb: WatchCallback<Truthy<T>, T | undefined>, options?: WheneverOptions<true>): WatchHandle;
|
|
export function whenever<T>(source: WatchSource<T>, cb: WatchCallback<Truthy<T>, T>, options?: WheneverOptions<false>): WatchHandle;
|
|
export function whenever<T>(
|
|
source: WatchSource<T>,
|
|
cb: WatchCallback<Truthy<T>, T | undefined>,
|
|
options?: WheneverOptions,
|
|
): WatchHandle {
|
|
const stop = watch(
|
|
source,
|
|
(value, oldValue, onCleanup) => {
|
|
if (value) {
|
|
if (options?.once)
|
|
nextTick(() => stop());
|
|
|
|
cb(value as Truthy<T>, oldValue, onCleanup);
|
|
}
|
|
},
|
|
{
|
|
...options,
|
|
once: false,
|
|
} as WatchOptions,
|
|
);
|
|
|
|
return stop;
|
|
}
|