@vizejs/composable 0.345.0 → 0.347.7
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/abort-signal.d.mts +96 -0
- package/dist/abort-signal.mjs +203 -0
- package/dist/async-resource.d.mts +97 -0
- package/dist/async-resource.mjs +99 -0
- package/dist/capability-BNpkvSy5.d.mts +93 -0
- package/dist/capability.d.mts +2 -0
- package/dist/capability.mjs +37 -0
- package/dist/catalog-CuWhR-0q.d.mts +506 -0
- package/dist/catalog-DOXTbk4r.mjs +529 -0
- package/dist/catalog.d.mts +2 -0
- package/dist/catalog.mjs +2 -0
- package/dist/disposal-scope.d.mts +93 -0
- package/dist/disposal-scope.mjs +119 -0
- package/dist/event-listener.d.mts +85 -0
- package/dist/event-listener.mjs +55 -0
- package/dist/index.d.mts +19 -786
- package/dist/index.mjs +19 -751
- package/dist/locale.d.mts +65 -0
- package/dist/locale.mjs +72 -0
- package/dist/media-query.d.mts +56 -0
- package/dist/media-query.mjs +56 -0
- package/dist/retry-async.d.mts +91 -0
- package/dist/retry-async.mjs +136 -0
- package/dist/retry-delay.d.mts +73 -0
- package/dist/retry-delay.mjs +50 -0
- package/dist/scope.d.mts +18 -0
- package/dist/scope.mjs +23 -0
- package/dist/timeout-scheduler.d.mts +18 -0
- package/dist/timeout-scheduler.mjs +1 -0
- package/dist/use-counter.d.mts +91 -0
- package/dist/use-counter.mjs +67 -0
- package/dist/use-debounced.d.mts +87 -0
- package/dist/use-debounced.mjs +98 -0
- package/dist/use-history.d.mts +105 -0
- package/dist/use-history.mjs +137 -0
- package/dist/use-previous.d.mts +43 -0
- package/dist/use-previous.mjs +11 -0
- package/dist/use-throttled.d.mts +107 -0
- package/dist/use-throttled.mjs +124 -0
- package/dist/use-toggle.d.mts +45 -0
- package/dist/use-toggle.mjs +34 -0
- package/package.json +91 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { tryOnScopeDispose } from "./scope.mjs";
|
|
2
|
+
//#region src/disposal-scope.ts
|
|
3
|
+
/** Stable error code reported when one or more owned cleanups fail. */
|
|
4
|
+
const DISPOSAL_ERROR_CODE = "VIZE_COMPOSE_DISPOSAL_FAILED";
|
|
5
|
+
/** Aggregate failure produced after every owned cleanup has been attempted. */
|
|
6
|
+
var DisposalError = class extends AggregateError {
|
|
7
|
+
/** Stable machine-readable error code. */
|
|
8
|
+
code = DISPOSAL_ERROR_CODE;
|
|
9
|
+
/**
|
|
10
|
+
* Create an aggregate disposal failure.
|
|
11
|
+
*
|
|
12
|
+
* Nested {@link DisposalError} instances are flattened by the scope before
|
|
13
|
+
* construction, so `errors` contains the original cleanup failures in
|
|
14
|
+
* execution order.
|
|
15
|
+
*
|
|
16
|
+
* @param errors Cleanup failures in deterministic execution order.
|
|
17
|
+
*/
|
|
18
|
+
constructor(errors) {
|
|
19
|
+
super(errors, `[${DISPOSAL_ERROR_CODE}] ${String(errors.length)} cleanup operation(s) failed.`);
|
|
20
|
+
this.name = "DisposalError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Create an explicit, deterministic cleanup owner.
|
|
25
|
+
*
|
|
26
|
+
* The owner is runtime-neutral and performs no browser-global access. By
|
|
27
|
+
* default it joins an active Vue reactive scope; when no scope exists, or
|
|
28
|
+
* `scope` is disabled, the caller must invoke `dispose()`. Cleanups are
|
|
29
|
+
* synchronous by contract so disposal completes before the owner releases
|
|
30
|
+
* its records.
|
|
31
|
+
*
|
|
32
|
+
* @param options Reactive-scope ownership behavior.
|
|
33
|
+
* @default options {}
|
|
34
|
+
* @returns A disposal owner with child-lifetime support.
|
|
35
|
+
*/
|
|
36
|
+
function createDisposalScope(options = {}) {
|
|
37
|
+
const owner = createOwner();
|
|
38
|
+
if (options.scope ?? true) tryOnScopeDispose(owner.dispose);
|
|
39
|
+
return owner;
|
|
40
|
+
}
|
|
41
|
+
function createOwner(onDispose) {
|
|
42
|
+
const records = [];
|
|
43
|
+
let disposed = false;
|
|
44
|
+
let size = 0;
|
|
45
|
+
const add = (cleanup) => {
|
|
46
|
+
if (disposed) {
|
|
47
|
+
try {
|
|
48
|
+
cleanup();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
throw new DisposalError(flattenDisposalError(error));
|
|
51
|
+
}
|
|
52
|
+
return inactiveRegistration();
|
|
53
|
+
}
|
|
54
|
+
const record = {
|
|
55
|
+
active: true,
|
|
56
|
+
cleanup
|
|
57
|
+
};
|
|
58
|
+
records.push(record);
|
|
59
|
+
size += 1;
|
|
60
|
+
return {
|
|
61
|
+
get active() {
|
|
62
|
+
return record.active;
|
|
63
|
+
},
|
|
64
|
+
unregister() {
|
|
65
|
+
if (!record.active) return false;
|
|
66
|
+
record.active = false;
|
|
67
|
+
size -= 1;
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
const dispose = () => {
|
|
73
|
+
if (disposed) return;
|
|
74
|
+
disposed = true;
|
|
75
|
+
onDispose?.();
|
|
76
|
+
const errors = [];
|
|
77
|
+
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
78
|
+
const record = records[index];
|
|
79
|
+
if (!record?.active) continue;
|
|
80
|
+
record.active = false;
|
|
81
|
+
size -= 1;
|
|
82
|
+
try {
|
|
83
|
+
record.cleanup();
|
|
84
|
+
} catch (error) {
|
|
85
|
+
errors.push(...flattenDisposalError(error));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
records.length = 0;
|
|
89
|
+
if (errors.length > 0) throw new DisposalError(errors);
|
|
90
|
+
};
|
|
91
|
+
const child = () => {
|
|
92
|
+
let parentRegistration;
|
|
93
|
+
const childOwner = createOwner(() => parentRegistration?.unregister());
|
|
94
|
+
parentRegistration = add(childOwner.dispose);
|
|
95
|
+
return childOwner;
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
get disposed() {
|
|
99
|
+
return disposed;
|
|
100
|
+
},
|
|
101
|
+
get size() {
|
|
102
|
+
return size;
|
|
103
|
+
},
|
|
104
|
+
add,
|
|
105
|
+
child,
|
|
106
|
+
dispose
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function inactiveRegistration() {
|
|
110
|
+
return {
|
|
111
|
+
active: false,
|
|
112
|
+
unregister: () => false
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function flattenDisposalError(error) {
|
|
116
|
+
return error instanceof DisposalError ? error.errors : [error];
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { DISPOSAL_ERROR_CODE, DisposalError, createDisposalScope };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { MaybeRefOrGetter, Ref } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/event-listener.d.ts
|
|
4
|
+
/** Options for {@link useEventListener}. */
|
|
5
|
+
interface UseEventListenerOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Invoke the listener during the capture phase.
|
|
8
|
+
*
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
readonly capture?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Stop listening after the first event.
|
|
14
|
+
*
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
readonly once?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Declare that the listener does not cancel the event's default action.
|
|
20
|
+
*
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
readonly passive?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Stop listening when this signal is aborted. An already-aborted signal
|
|
26
|
+
* prevents listening from ever starting.
|
|
27
|
+
*
|
|
28
|
+
* @default undefined
|
|
29
|
+
*/
|
|
30
|
+
readonly signal?: AbortSignal;
|
|
31
|
+
/**
|
|
32
|
+
* Start listening during composable creation.
|
|
33
|
+
*
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
readonly immediate?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Reactive target update timing.
|
|
39
|
+
*
|
|
40
|
+
* @default "pre"
|
|
41
|
+
*/
|
|
42
|
+
readonly flush?: "pre" | "post" | "sync";
|
|
43
|
+
}
|
|
44
|
+
/** Reactive controls returned by {@link useEventListener}. */
|
|
45
|
+
interface EventListenerControls {
|
|
46
|
+
/** Whether a concrete target currently owns the listener. */
|
|
47
|
+
readonly isListening: Readonly<Ref<boolean>>;
|
|
48
|
+
/**
|
|
49
|
+
* Begin listening.
|
|
50
|
+
*
|
|
51
|
+
* @returns Whether a new reactive watcher was started. `false` while the
|
|
52
|
+
* watcher is already active (including a null-target watcher with no
|
|
53
|
+
* listener attached), after the abort signal has fired, and after the
|
|
54
|
+
* owning reactive scope has been disposed.
|
|
55
|
+
*/
|
|
56
|
+
readonly start: () => boolean;
|
|
57
|
+
/** Stop listening. Repeated calls are safe. */
|
|
58
|
+
readonly stop: () => void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Attach an event listener to a reactive target and clean it up with the
|
|
62
|
+
* current reactive scope. Missing targets are valid during server rendering:
|
|
63
|
+
* a `null`/`undefined` target keeps the listener detached until a concrete
|
|
64
|
+
* target appears, so no browser globals are required.
|
|
65
|
+
*
|
|
66
|
+
* The listener is re-attached whenever the reactive target changes and is
|
|
67
|
+
* removed when the owning reactive scope stops, when
|
|
68
|
+
* {@link EventListenerControls.stop} is called, or when the abort signal
|
|
69
|
+
* fires. Outside an active scope, teardown ownership stays with the caller,
|
|
70
|
+
* who must call `stop` explicitly. Errors thrown by a custom target's
|
|
71
|
+
* add/remove methods propagate to the active watcher run.
|
|
72
|
+
*
|
|
73
|
+
* @param target Reactive event target.
|
|
74
|
+
* @param event Event name.
|
|
75
|
+
* @param listener Typed event listener.
|
|
76
|
+
* @param options Listener lifecycle and scheduling options.
|
|
77
|
+
* @default options {}
|
|
78
|
+
* @returns Controls to observe and change the listening state.
|
|
79
|
+
*/
|
|
80
|
+
declare function useEventListener<Key extends keyof WindowEventMap>(target: MaybeRefOrGetter<Window | null | undefined>, event: Key, listener: (event: WindowEventMap[Key]) => void, options?: UseEventListenerOptions): EventListenerControls;
|
|
81
|
+
declare function useEventListener<Key extends keyof DocumentEventMap>(target: MaybeRefOrGetter<Document | null | undefined>, event: Key, listener: (event: DocumentEventMap[Key]) => void, options?: UseEventListenerOptions): EventListenerControls;
|
|
82
|
+
declare function useEventListener<Key extends keyof HTMLElementEventMap>(target: MaybeRefOrGetter<HTMLElement | null | undefined>, event: Key, listener: (event: HTMLElementEventMap[Key]) => void, options?: UseEventListenerOptions): EventListenerControls;
|
|
83
|
+
declare function useEventListener(target: MaybeRefOrGetter<EventTarget | null | undefined>, event: string, listener: EventListener, options?: UseEventListenerOptions): EventListenerControls;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { EventListenerControls, UseEventListenerOptions, useEventListener };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { tryOnScopeDispose } from "./scope.mjs";
|
|
2
|
+
import { readonly, ref, toValue, watch } from "vue";
|
|
3
|
+
//#region src/event-listener.ts
|
|
4
|
+
function useEventListener(target, event, listener, options = {}) {
|
|
5
|
+
const { capture = false, once = false, passive = false, signal, immediate = true, flush = "pre" } = options;
|
|
6
|
+
const isListening = ref(false);
|
|
7
|
+
const eventOptions = {
|
|
8
|
+
capture,
|
|
9
|
+
passive,
|
|
10
|
+
...signal ? { signal } : {}
|
|
11
|
+
};
|
|
12
|
+
let disposed = false;
|
|
13
|
+
let stopWatch;
|
|
14
|
+
const stop = () => {
|
|
15
|
+
stopWatch?.stop();
|
|
16
|
+
stopWatch = void 0;
|
|
17
|
+
isListening.value = false;
|
|
18
|
+
};
|
|
19
|
+
const start = () => {
|
|
20
|
+
if (disposed || stopWatch || signal?.aborted) return false;
|
|
21
|
+
stopWatch = watch(() => toValue(target), (next, _previous, onCleanup) => {
|
|
22
|
+
isListening.value = false;
|
|
23
|
+
if (!next || signal?.aborted) return;
|
|
24
|
+
const invoke = (nativeEvent) => {
|
|
25
|
+
if (once) stop();
|
|
26
|
+
listener(nativeEvent);
|
|
27
|
+
};
|
|
28
|
+
const onAbort = () => stop();
|
|
29
|
+
next.addEventListener(event, invoke, eventOptions);
|
|
30
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
31
|
+
isListening.value = true;
|
|
32
|
+
onCleanup(() => {
|
|
33
|
+
next.removeEventListener(event, invoke, capture);
|
|
34
|
+
signal?.removeEventListener("abort", onAbort);
|
|
35
|
+
isListening.value = false;
|
|
36
|
+
});
|
|
37
|
+
}, {
|
|
38
|
+
flush,
|
|
39
|
+
immediate: true
|
|
40
|
+
});
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
tryOnScopeDispose(() => {
|
|
44
|
+
disposed = true;
|
|
45
|
+
stop();
|
|
46
|
+
});
|
|
47
|
+
if (immediate) start();
|
|
48
|
+
return {
|
|
49
|
+
isListening: readonly(isListening),
|
|
50
|
+
start,
|
|
51
|
+
stop
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { useEventListener };
|