@vizejs/composable 0.345.0 → 0.350.2

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.
Files changed (42) hide show
  1. package/dist/abort-signal.d.mts +96 -0
  2. package/dist/abort-signal.mjs +203 -0
  3. package/dist/async-resource.d.mts +97 -0
  4. package/dist/async-resource.mjs +99 -0
  5. package/dist/capability-Ptkjr_sD.d.mts +93 -0
  6. package/dist/capability.d.mts +2 -0
  7. package/dist/capability.mjs +37 -0
  8. package/dist/catalog-BQMC1CcY.d.mts +506 -0
  9. package/dist/catalog-CYHr82Jz.mjs +529 -0
  10. package/dist/catalog.d.mts +2 -0
  11. package/dist/catalog.mjs +2 -0
  12. package/dist/disposal-scope.d.mts +93 -0
  13. package/dist/disposal-scope.mjs +119 -0
  14. package/dist/event-listener.d.mts +85 -0
  15. package/dist/event-listener.mjs +55 -0
  16. package/dist/index.d.mts +19 -786
  17. package/dist/index.mjs +19 -751
  18. package/dist/locale.d.mts +65 -0
  19. package/dist/locale.mjs +72 -0
  20. package/dist/media-query.d.mts +56 -0
  21. package/dist/media-query.mjs +56 -0
  22. package/dist/retry-async.d.mts +91 -0
  23. package/dist/retry-async.mjs +136 -0
  24. package/dist/retry-delay.d.mts +73 -0
  25. package/dist/retry-delay.mjs +50 -0
  26. package/dist/scope.d.mts +18 -0
  27. package/dist/scope.mjs +23 -0
  28. package/dist/timeout-scheduler.d.mts +18 -0
  29. package/dist/timeout-scheduler.mjs +1 -0
  30. package/dist/use-counter.d.mts +91 -0
  31. package/dist/use-counter.mjs +67 -0
  32. package/dist/use-debounced.d.mts +87 -0
  33. package/dist/use-debounced.mjs +98 -0
  34. package/dist/use-history.d.mts +105 -0
  35. package/dist/use-history.mjs +137 -0
  36. package/dist/use-previous.d.mts +43 -0
  37. package/dist/use-previous.mjs +11 -0
  38. package/dist/use-throttled.d.mts +107 -0
  39. package/dist/use-throttled.mjs +124 -0
  40. package/dist/use-toggle.d.mts +45 -0
  41. package/dist/use-toggle.mjs +34 -0
  42. package/package.json +92 -2
@@ -0,0 +1,96 @@
1
+ import { TimeoutScheduler } from "./timeout-scheduler.mjs";
2
+
3
+ //#region src/abort-signal.d.ts
4
+ /**
5
+ * Create a signal that aborts when the first input signal aborts.
6
+ *
7
+ * The standard `AbortSignal.any()` implementation is used when available.
8
+ * Older runtimes receive an equivalent listener-based implementation that
9
+ * removes every retained listener as soon as the result aborts. The first
10
+ * already-aborted input wins in iteration order, and its exact reason is
11
+ * forwarded. An empty iterable returns a fresh signal that never aborts.
12
+ *
13
+ * This function reads runtime constructors only when called and is safe to
14
+ * import during server rendering. Materializing the iterable happens before
15
+ * listeners are attached, so an iterable that throws cannot leak a partial
16
+ * subscription. If a non-standard signal throws while registering, listeners
17
+ * already attached to earlier inputs are released before the error propagates.
18
+ *
19
+ * @param signals Abort signals to compose; consumed exactly once.
20
+ * @returns A new first-abort-wins signal.
21
+ */
22
+ declare function anyAbortSignal(signals: Iterable<AbortSignal>): AbortSignal;
23
+ /** Options for {@link timeoutAbortSignal}. */
24
+ interface TimeoutAbortSignalOptions {
25
+ /**
26
+ * Abort the returned signal early when this parent aborts.
27
+ *
28
+ * @default undefined
29
+ */
30
+ readonly signal?: AbortSignal;
31
+ /**
32
+ * Reason used when the timeout elapses. Parent cancellation always forwards
33
+ * the parent's reason instead.
34
+ *
35
+ * @default DOMException("The operation timed out.", "TimeoutError")
36
+ */
37
+ readonly reason?: unknown;
38
+ /**
39
+ * Deterministic or host-specific single-shot timer implementation. Supplying
40
+ * a scheduler selects the compatibility implementation.
41
+ *
42
+ * @default globalThis timer functions
43
+ */
44
+ readonly scheduler?: TimeoutScheduler;
45
+ }
46
+ /** Options for {@link deadlineAbortSignal}. */
47
+ interface DeadlineAbortSignalOptions extends TimeoutAbortSignalOptions {
48
+ /**
49
+ * Clock returning Unix epoch milliseconds.
50
+ *
51
+ * @default Date.now
52
+ */
53
+ readonly now?: () => number;
54
+ }
55
+ /**
56
+ * Create a signal that aborts after a portable, non-negative delay.
57
+ *
58
+ * The native `AbortSignal.timeout()` implementation is used when available
59
+ * and neither a custom scheduler nor a custom reason is supplied. Older
60
+ * runtimes use the same owned-timer path as injected schedulers. Parent
61
+ * cancellation is composed with first-reason-wins semantics. Compatibility
62
+ * scheduling owns exactly one timer and removes its parent listener whenever
63
+ * either source aborts. A zero delay remains asynchronous.
64
+ *
65
+ * The delay must be an integer from `0` through `2_147_483_647`; this common
66
+ * signed 32-bit timer ceiling avoids host-specific clamping. The function
67
+ * accesses timers and abort constructors only when called and is safe to
68
+ * import during server rendering.
69
+ *
70
+ * @param delayMs Delay in milliseconds.
71
+ * @param options Parent signal, timeout reason, and scheduler.
72
+ * @default options {}
73
+ * @throws {RangeError} Tagged `VIZE_COMPOSE_ABORT_TIMEOUT_INVALID_DELAY` when
74
+ * the delay is fractional, negative, non-finite, or exceeds the portable
75
+ * timer ceiling.
76
+ * @returns A new timeout or parent-cancelled signal.
77
+ */
78
+ declare function timeoutAbortSignal(delayMs: number, options?: TimeoutAbortSignalOptions): AbortSignal;
79
+ /**
80
+ * Create a timeout signal from an absolute Unix-epoch deadline.
81
+ *
82
+ * Fractional positive differences are rounded up so cancellation never occurs
83
+ * before the requested deadline. Past deadlines become an asynchronous
84
+ * zero-delay timeout. `Date` and numeric deadlines are both accepted.
85
+ *
86
+ * @param deadline Absolute deadline as a `Date` or Unix epoch milliseconds.
87
+ * @param options Clock, parent signal, timeout reason, and scheduler.
88
+ * @default options {}
89
+ * @throws {RangeError} Tagged `VIZE_COMPOSE_ABORT_DEADLINE_INVALID` when the
90
+ * deadline, current clock value, or their positive difference is non-finite
91
+ * or cannot fit the portable timeout range.
92
+ * @returns A new deadline or parent-cancelled signal.
93
+ */
94
+ declare function deadlineAbortSignal(deadline: Date | number, options?: DeadlineAbortSignalOptions): AbortSignal;
95
+ //#endregion
96
+ export { DeadlineAbortSignalOptions, TimeoutAbortSignalOptions, anyAbortSignal, deadlineAbortSignal, timeoutAbortSignal };
@@ -0,0 +1,203 @@
1
+ //#region src/abort-signal.ts
2
+ /**
3
+ * Create a signal that aborts when the first input signal aborts.
4
+ *
5
+ * The standard `AbortSignal.any()` implementation is used when available.
6
+ * Older runtimes receive an equivalent listener-based implementation that
7
+ * removes every retained listener as soon as the result aborts. The first
8
+ * already-aborted input wins in iteration order, and its exact reason is
9
+ * forwarded. An empty iterable returns a fresh signal that never aborts.
10
+ *
11
+ * This function reads runtime constructors only when called and is safe to
12
+ * import during server rendering. Materializing the iterable happens before
13
+ * listeners are attached, so an iterable that throws cannot leak a partial
14
+ * subscription. If a non-standard signal throws while registering, listeners
15
+ * already attached to earlier inputs are released before the error propagates.
16
+ *
17
+ * @param signals Abort signals to compose; consumed exactly once.
18
+ * @returns A new first-abort-wins signal.
19
+ */
20
+ function anyAbortSignal(signals) {
21
+ const inputs = [...signals];
22
+ const nativeAny = conformantNativeAbortSignalAny();
23
+ if (nativeAny !== void 0) return nativeAny.call(AbortSignal, inputs);
24
+ const controller = new AbortController();
25
+ const listeners = [];
26
+ const cleanup = () => {
27
+ for (const [signal, listener] of listeners) signal.removeEventListener("abort", listener);
28
+ listeners.length = 0;
29
+ };
30
+ const abortFrom = (signal) => {
31
+ if (controller.signal.aborted) return;
32
+ cleanup();
33
+ controller.abort(signal.reason);
34
+ };
35
+ for (const signal of inputs) {
36
+ if (signal.aborted) {
37
+ abortFrom(signal);
38
+ break;
39
+ }
40
+ const listener = () => abortFrom(signal);
41
+ listeners.push([signal, listener]);
42
+ try {
43
+ signal.addEventListener("abort", listener, { once: true });
44
+ } catch (error) {
45
+ cleanup();
46
+ throw error;
47
+ }
48
+ if (signal.aborted) {
49
+ abortFrom(signal);
50
+ break;
51
+ }
52
+ }
53
+ return controller.signal;
54
+ }
55
+ let probedNativeAny;
56
+ let cachedNativeAny;
57
+ /** Resolve the current native implementation only after its first-reason contract passes. */
58
+ function conformantNativeAbortSignalAny() {
59
+ let candidate;
60
+ try {
61
+ candidate = Reflect.get(AbortSignal, "any");
62
+ } catch {
63
+ return;
64
+ }
65
+ if (candidate === probedNativeAny) return cachedNativeAny;
66
+ probedNativeAny = candidate;
67
+ cachedNativeAny = typeof candidate === "function" && nativeAnyReasonIsStable(candidate) ? candidate : void 0;
68
+ return cachedNativeAny;
69
+ }
70
+ /**
71
+ * Detect runtimes whose combined reason changes when an earlier array member
72
+ * aborts after the winner. The probe deliberately does not read the reason
73
+ * until both inputs abort, catching lazy native implementations as well.
74
+ */
75
+ function nativeAnyReasonIsStable(candidate) {
76
+ try {
77
+ const late = new AbortController();
78
+ const winner = new AbortController();
79
+ const expected = {};
80
+ const combined = candidate.call(AbortSignal, [late.signal, winner.signal]);
81
+ winner.abort(expected);
82
+ late.abort({});
83
+ return combined.aborted && combined.reason === expected;
84
+ } catch {
85
+ return false;
86
+ }
87
+ }
88
+ /**
89
+ * Create a signal that aborts after a portable, non-negative delay.
90
+ *
91
+ * The native `AbortSignal.timeout()` implementation is used when available
92
+ * and neither a custom scheduler nor a custom reason is supplied. Older
93
+ * runtimes use the same owned-timer path as injected schedulers. Parent
94
+ * cancellation is composed with first-reason-wins semantics. Compatibility
95
+ * scheduling owns exactly one timer and removes its parent listener whenever
96
+ * either source aborts. A zero delay remains asynchronous.
97
+ *
98
+ * The delay must be an integer from `0` through `2_147_483_647`; this common
99
+ * signed 32-bit timer ceiling avoids host-specific clamping. The function
100
+ * accesses timers and abort constructors only when called and is safe to
101
+ * import during server rendering.
102
+ *
103
+ * @param delayMs Delay in milliseconds.
104
+ * @param options Parent signal, timeout reason, and scheduler.
105
+ * @default options {}
106
+ * @throws {RangeError} Tagged `VIZE_COMPOSE_ABORT_TIMEOUT_INVALID_DELAY` when
107
+ * the delay is fractional, negative, non-finite, or exceeds the portable
108
+ * timer ceiling.
109
+ * @returns A new timeout or parent-cancelled signal.
110
+ */
111
+ function timeoutAbortSignal(delayMs, options = {}) {
112
+ assertPortableTimeout(delayMs);
113
+ const parent = options.signal;
114
+ if (parent?.aborted) {
115
+ const controller = new AbortController();
116
+ controller.abort(parent.reason);
117
+ return controller.signal;
118
+ }
119
+ if (options.scheduler === void 0 && options.reason === void 0 && typeof AbortSignal.timeout === "function") {
120
+ const timeout = AbortSignal.timeout(delayMs);
121
+ return options.signal === void 0 ? timeout : anyAbortSignal([options.signal, timeout]);
122
+ }
123
+ const controller = new AbortController();
124
+ const scheduler = options.scheduler ?? defaultTimeoutScheduler;
125
+ let handle;
126
+ let timerPending = true;
127
+ let parentListening = false;
128
+ const stopTimer = () => {
129
+ if (!timerPending) return;
130
+ timerPending = false;
131
+ scheduler.clearTimeout(handle);
132
+ handle = void 0;
133
+ };
134
+ const stopParent = () => {
135
+ if (!parentListening || parent === void 0) return;
136
+ parentListening = false;
137
+ parent.removeEventListener("abort", abortFromParent);
138
+ };
139
+ const abort = (reason) => {
140
+ if (controller.signal.aborted) return;
141
+ stopTimer();
142
+ stopParent();
143
+ controller.abort(reason);
144
+ };
145
+ const abortFromParent = () => abort(parent?.reason);
146
+ const timeoutReason = options.reason === void 0 ? new DOMException("The operation timed out.", "TimeoutError") : options.reason;
147
+ handle = scheduler.setTimeout(() => {
148
+ timerPending = false;
149
+ handle = void 0;
150
+ abort(timeoutReason);
151
+ }, delayMs);
152
+ if (controller.signal.aborted || parent === void 0) return controller.signal;
153
+ try {
154
+ parentListening = true;
155
+ parent.addEventListener("abort", abortFromParent, { once: true });
156
+ if (controller.signal.aborted) {
157
+ parent.removeEventListener("abort", abortFromParent);
158
+ parentListening = false;
159
+ return controller.signal;
160
+ }
161
+ if (parent.aborted) abortFromParent();
162
+ } catch (error) {
163
+ stopParent();
164
+ stopTimer();
165
+ throw error;
166
+ }
167
+ return controller.signal;
168
+ }
169
+ /**
170
+ * Create a timeout signal from an absolute Unix-epoch deadline.
171
+ *
172
+ * Fractional positive differences are rounded up so cancellation never occurs
173
+ * before the requested deadline. Past deadlines become an asynchronous
174
+ * zero-delay timeout. `Date` and numeric deadlines are both accepted.
175
+ *
176
+ * @param deadline Absolute deadline as a `Date` or Unix epoch milliseconds.
177
+ * @param options Clock, parent signal, timeout reason, and scheduler.
178
+ * @default options {}
179
+ * @throws {RangeError} Tagged `VIZE_COMPOSE_ABORT_DEADLINE_INVALID` when the
180
+ * deadline, current clock value, or their positive difference is non-finite
181
+ * or cannot fit the portable timeout range.
182
+ * @returns A new deadline or parent-cancelled signal.
183
+ */
184
+ function deadlineAbortSignal(deadline, options = {}) {
185
+ const deadlineMs = deadline instanceof Date ? deadline.getTime() : deadline;
186
+ const nowMs = (options.now ?? Date.now)();
187
+ const difference = deadlineMs - nowMs;
188
+ if (!Number.isFinite(deadlineMs) || !Number.isFinite(nowMs) || !Number.isFinite(difference) || difference > maximumPortableTimeoutMs) throw new RangeError(`[VIZE_COMPOSE_ABORT_DEADLINE_INVALID] deadline and now must produce a finite delay from 0 through ${String(maximumPortableTimeoutMs)} milliseconds; received deadline=${String(deadlineMs)}, now=${String(nowMs)}`);
189
+ const { now: _now, ...timeoutOptions } = options;
190
+ return timeoutAbortSignal(Math.ceil(Math.max(0, difference)), timeoutOptions);
191
+ }
192
+ function assertPortableTimeout(delayMs) {
193
+ if (!Number.isSafeInteger(delayMs) || delayMs < 0 || delayMs > maximumPortableTimeoutMs) throw new RangeError(`[VIZE_COMPOSE_ABORT_TIMEOUT_INVALID_DELAY] delayMs must be an integer from 0 through ${String(maximumPortableTimeoutMs)}; received ${String(delayMs)}`);
194
+ }
195
+ const maximumPortableTimeoutMs = 2147483647;
196
+ const defaultTimeoutScheduler = {
197
+ setTimeout: (callback, delayMs) => globalThis.setTimeout(callback, delayMs),
198
+ clearTimeout: (handle) => {
199
+ globalThis.clearTimeout(handle);
200
+ }
201
+ };
202
+ //#endregion
203
+ export { anyAbortSignal, deadlineAbortSignal, timeoutAbortSignal };
@@ -0,0 +1,97 @@
1
+ import { ComputedRef, Ref, ShallowRef } from "vue";
2
+
3
+ //#region src/async-resource.d.ts
4
+ /** Lifecycle state of an asynchronous resource. */
5
+ type AsyncResourceStatus = "idle" | "pending" | "success" | "error" | "cancelled";
6
+ /** Context supplied to an asynchronous resource loader. */
7
+ interface AsyncResourceContext {
8
+ /** Signal aborted by cancellation, reset, scope disposal, or a newer execution. */
9
+ readonly signal: AbortSignal;
10
+ }
11
+ /** Explicit result of one asynchronous resource execution. */
12
+ type AsyncResourceExecution<Data, Failure> = {
13
+ readonly status: "success";
14
+ readonly data: Data;
15
+ } | {
16
+ readonly status: "error";
17
+ readonly error: Failure;
18
+ } | {
19
+ readonly status: "cancelled";
20
+ readonly reason: unknown;
21
+ } | {
22
+ readonly status: "superseded";
23
+ };
24
+ /** Options for {@link useAsyncResource}. */
25
+ interface UseAsyncResourceOptions<Data> {
26
+ /**
27
+ * Initial data restored by {@link AsyncResource.reset}.
28
+ *
29
+ * @default undefined
30
+ */
31
+ readonly initialData?: Data;
32
+ /**
33
+ * Abort the active execution when a newer execution starts.
34
+ *
35
+ * @default true
36
+ */
37
+ readonly cancelPrevious?: boolean;
38
+ /**
39
+ * Retain the current data while a new execution is pending.
40
+ *
41
+ * @default true
42
+ */
43
+ readonly keepData?: boolean;
44
+ /**
45
+ * Cancel an active execution when the current reactive scope is disposed.
46
+ *
47
+ * @default true
48
+ */
49
+ readonly scope?: boolean;
50
+ }
51
+ /** Reactive state and controls for an asynchronous loader. */
52
+ interface AsyncResource<Data, Arguments extends readonly unknown[], Failure> {
53
+ /** Data of the newest successful execution, retained according to `keepData`. */
54
+ readonly data: Readonly<ShallowRef<Data | undefined>>;
55
+ /** Failure of the newest settled execution, cleared when a new one starts. */
56
+ readonly error: Readonly<ShallowRef<Failure | undefined>>;
57
+ /** Current lifecycle status, driven only by the newest execution. */
58
+ readonly status: Readonly<Ref<AsyncResourceStatus>>;
59
+ /** Whether an execution is currently pending. */
60
+ readonly pending: ComputedRef<boolean>;
61
+ /**
62
+ * Run the loader. The returned promise never rejects: loader failures,
63
+ * cancellation, and supersession are reported as the discriminated result,
64
+ * and stale executions leave the reactive state untouched.
65
+ */
66
+ readonly execute: (...arguments_: Arguments) => Promise<AsyncResourceExecution<Data, Failure>>;
67
+ /**
68
+ * Abort the active execution and mark the resource cancelled.
69
+ *
70
+ * @param reason Abort reason forwarded to the loader's signal.
71
+ * @default reason DOMException("AbortError")
72
+ * @returns Whether an active execution was cancelled.
73
+ */
74
+ readonly cancel: (reason?: unknown) => boolean;
75
+ /** Cancel any active execution and restore the initial idle state. */
76
+ readonly reset: () => void;
77
+ }
78
+ /**
79
+ * Create a scoped, abortable asynchronous resource with latest-result-wins
80
+ * state. Every execution returns a discriminated result, so cancellation,
81
+ * supersession, loader failure, and successful `undefined` data stay distinct.
82
+ *
83
+ * When created inside an active reactive scope (and `scope` is enabled), the
84
+ * active execution is aborted when that scope stops; outside a scope,
85
+ * cancellation ownership stays with the caller. The execute promise never
86
+ * rejects — synchronous and asynchronous loader failures both settle into
87
+ * the `"error"` result. Safe during server rendering: no browser globals are
88
+ * read and abort reasons use the runtime-native `DOMException`.
89
+ *
90
+ * @param loader Asynchronous loader receiving the abort context first.
91
+ * @param options Data retention, supersession, and scope behavior.
92
+ * @default options {}
93
+ * @returns Reactive state and controls for the loader.
94
+ */
95
+ declare function useAsyncResource<Data, Arguments extends readonly unknown[], Failure = unknown>(loader: (context: AsyncResourceContext, ...arguments_: Arguments) => Promise<Data>, options?: UseAsyncResourceOptions<Data>): AsyncResource<Data, Arguments, Failure>;
96
+ //#endregion
97
+ export { AsyncResource, AsyncResourceContext, AsyncResourceExecution, AsyncResourceStatus, UseAsyncResourceOptions, useAsyncResource };
@@ -0,0 +1,99 @@
1
+ import { tryOnScopeDispose } from "./scope.mjs";
2
+ import { computed, shallowRef } from "vue";
3
+ //#region src/async-resource.ts
4
+ /**
5
+ * Create a scoped, abortable asynchronous resource with latest-result-wins
6
+ * state. Every execution returns a discriminated result, so cancellation,
7
+ * supersession, loader failure, and successful `undefined` data stay distinct.
8
+ *
9
+ * When created inside an active reactive scope (and `scope` is enabled), the
10
+ * active execution is aborted when that scope stops; outside a scope,
11
+ * cancellation ownership stays with the caller. The execute promise never
12
+ * rejects — synchronous and asynchronous loader failures both settle into
13
+ * the `"error"` result. Safe during server rendering: no browser globals are
14
+ * read and abort reasons use the runtime-native `DOMException`.
15
+ *
16
+ * @param loader Asynchronous loader receiving the abort context first.
17
+ * @param options Data retention, supersession, and scope behavior.
18
+ * @default options {}
19
+ * @returns Reactive state and controls for the loader.
20
+ */
21
+ function useAsyncResource(loader, options = {}) {
22
+ const data = shallowRef(options.initialData);
23
+ const error = shallowRef(void 0);
24
+ const status = shallowRef("idle");
25
+ const pending = computed(() => status.value === "pending");
26
+ let generation = 0;
27
+ let active;
28
+ const cancel = (reason = createAbortReason("The execution was cancelled.")) => {
29
+ if (active === void 0) return false;
30
+ generation += 1;
31
+ active.controller.abort(reason);
32
+ active = void 0;
33
+ status.value = "cancelled";
34
+ return true;
35
+ };
36
+ const execute = async (...arguments_) => {
37
+ if ((options.cancelPrevious ?? true) && active !== void 0) {
38
+ active.superseded = true;
39
+ active.controller.abort(createAbortReason("A newer execution started."));
40
+ }
41
+ const record = {
42
+ generation: ++generation,
43
+ controller: new AbortController(),
44
+ superseded: false
45
+ };
46
+ active = record;
47
+ error.value = void 0;
48
+ status.value = "pending";
49
+ if (!(options.keepData ?? true)) data.value = void 0;
50
+ try {
51
+ const result = await loader({ signal: record.controller.signal }, ...arguments_);
52
+ if (record.generation !== generation) return executionAfterInvalidation(record);
53
+ data.value = result;
54
+ status.value = "success";
55
+ return {
56
+ status: "success",
57
+ data: result
58
+ };
59
+ } catch (cause) {
60
+ if (record.generation !== generation || record.controller.signal.aborted) return executionAfterInvalidation(record);
61
+ error.value = cause;
62
+ status.value = "error";
63
+ return {
64
+ status: "error",
65
+ error: cause
66
+ };
67
+ } finally {
68
+ if (active === record) active = void 0;
69
+ }
70
+ };
71
+ const reset = () => {
72
+ cancel(createAbortReason("The resource was reset."));
73
+ data.value = options.initialData;
74
+ error.value = void 0;
75
+ status.value = "idle";
76
+ };
77
+ if (options.scope ?? true) tryOnScopeDispose(() => cancel(createAbortReason("The reactive scope was disposed.")));
78
+ return {
79
+ data,
80
+ error,
81
+ status,
82
+ pending,
83
+ execute,
84
+ cancel,
85
+ reset
86
+ };
87
+ }
88
+ function executionAfterInvalidation(execution) {
89
+ if (execution.superseded || !execution.controller.signal.aborted) return { status: "superseded" };
90
+ return {
91
+ status: "cancelled",
92
+ reason: execution.controller.signal.reason
93
+ };
94
+ }
95
+ function createAbortReason(message) {
96
+ return new DOMException(message, "AbortError");
97
+ }
98
+ //#endregion
99
+ export { useAsyncResource };
@@ -0,0 +1,93 @@
1
+ //#region src/capability.d.ts
2
+ /** Runtime families understood by composable capability metadata and adapters. */
3
+ type CapabilityTarget = "web" | "server" | "worker" | "native" | "desktop" | "terminal";
4
+ /** Built-in origins from which a capability value can be resolved. */
5
+ type CapabilitySource = "runtime" | "adapter" | "fallback";
6
+ /**
7
+ * Standard reasons why a capability cannot currently provide a value.
8
+ *
9
+ * Adapters may extend this vocabulary with a narrower string-literal union;
10
+ * consumers should preserve unknown extension reasons when crossing process
11
+ * or version boundaries.
12
+ */
13
+ type CapabilityUnavailableReason = "unsupported" | "unavailable" | "permission-denied" | "insecure-context" | "not-active" | "not-ready" | "cancelled" | "adapter-missing" | "adapter-error";
14
+ /** A capability value that is ready for use. */
15
+ interface AvailableCapability<Value, Source extends string = CapabilitySource> {
16
+ /** Stable discriminant for serialization and exhaustive matching. */
17
+ readonly status: "available";
18
+ /** Boolean discriminant for ergonomic guards in templates and JavaScript. */
19
+ readonly available: true;
20
+ /** Resolved capability implementation or value. */
21
+ readonly value: Value;
22
+ /** Origin that supplied the value, preserved as a string literal. */
23
+ readonly source: Source;
24
+ }
25
+ /** A capability that cannot currently provide a value. */
26
+ interface UnavailableCapability<Reason extends string = CapabilityUnavailableReason, Details = undefined> {
27
+ /** Stable discriminant for serialization and exhaustive matching. */
28
+ readonly status: "unavailable";
29
+ /** Boolean discriminant for ergonomic guards in templates and JavaScript. */
30
+ readonly available: false;
31
+ /** Typed, machine-readable explanation of the unavailable state. */
32
+ readonly reason: Reason;
33
+ /** Structured diagnostic or recovery information supplied by the adapter. */
34
+ readonly details: Details;
35
+ }
36
+ /** Explicit result of capability discovery or adapter negotiation. */
37
+ type CapabilityResult<Value, Reason extends string = CapabilityUnavailableReason, Details = undefined, Source extends string = CapabilitySource> = AvailableCapability<Value, Source> | UnavailableCapability<Reason, Details>;
38
+ /**
39
+ * Create an available capability supplied directly by the current runtime.
40
+ *
41
+ * The value and source retain literal types. The helper performs no global
42
+ * access and is safe during server rendering and module evaluation.
43
+ *
44
+ * @param value Resolved capability implementation or value.
45
+ * @returns An available result whose source is `"runtime"`.
46
+ */
47
+ declare function availableCapability<const Value>(value: Value): AvailableCapability<Value, "runtime">;
48
+ /**
49
+ * Create an available capability with an explicit, literal-preserving source.
50
+ *
51
+ * @param value Resolved capability implementation or value.
52
+ * @param source Runtime, adapter, fallback, or adapter-specific source name.
53
+ * @returns An available capability result.
54
+ */
55
+ declare function availableCapability<const Value, const Source extends string>(value: Value, source: Source): AvailableCapability<Value, Source>;
56
+ /**
57
+ * Create an unavailable capability without additional details.
58
+ *
59
+ * The reason retains its string-literal type. Capability absence is returned
60
+ * as data rather than thrown, making unsupported server, worker, native,
61
+ * desktop, and terminal environments deterministic.
62
+ *
63
+ * @param reason Machine-readable unavailability reason.
64
+ * @returns An unavailable result with `undefined` details.
65
+ */
66
+ declare function unavailableCapability<const Reason extends string>(reason: Reason): UnavailableCapability<Reason, undefined>;
67
+ /**
68
+ * Create an unavailable capability with typed recovery or diagnostic details.
69
+ *
70
+ * Passing `undefined` explicitly is distinct at the call boundary and still
71
+ * preserves the exact `undefined` details type.
72
+ *
73
+ * @param reason Machine-readable unavailability reason.
74
+ * @param details Structured diagnostic or recovery information.
75
+ * @returns An unavailable capability result.
76
+ */
77
+ declare function unavailableCapability<const Reason extends string, const Details>(reason: Reason, details: Details): UnavailableCapability<Reason, Details>;
78
+ /**
79
+ * Narrow a capability result to its available branch.
80
+ *
81
+ * @param result Capability discovery or negotiation result.
82
+ * @returns Whether `result.value` is ready for use.
83
+ */
84
+ declare function isCapabilityAvailable<Value, Reason extends string, Details, Source extends string>(result: CapabilityResult<Value, Reason, Details, Source>): result is AvailableCapability<Value, Source>;
85
+ /**
86
+ * Narrow a capability result to its unavailable branch.
87
+ *
88
+ * @param result Capability discovery or negotiation result.
89
+ * @returns Whether the capability has a typed unavailability reason.
90
+ */
91
+ declare function isCapabilityUnavailable<Value, Reason extends string, Details, Source extends string>(result: CapabilityResult<Value, Reason, Details, Source>): result is UnavailableCapability<Reason, Details>;
92
+ //#endregion
93
+ export { CapabilityUnavailableReason as a, isCapabilityAvailable as c, CapabilityTarget as i, isCapabilityUnavailable as l, CapabilityResult as n, UnavailableCapability as o, CapabilitySource as r, availableCapability as s, AvailableCapability as t, unavailableCapability as u };
@@ -0,0 +1,2 @@
1
+ import { a as CapabilityUnavailableReason, c as isCapabilityAvailable, i as CapabilityTarget, l as isCapabilityUnavailable, n as CapabilityResult, o as UnavailableCapability, r as CapabilitySource, s as availableCapability, t as AvailableCapability, u as unavailableCapability } from "./capability-Ptkjr_sD.mjs";
2
+ export { AvailableCapability, CapabilityResult, CapabilitySource, CapabilityTarget, CapabilityUnavailableReason, UnavailableCapability, availableCapability, isCapabilityAvailable, isCapabilityUnavailable, unavailableCapability };
@@ -0,0 +1,37 @@
1
+ //#region src/capability.ts
2
+ function availableCapability(value, source) {
3
+ return {
4
+ status: "available",
5
+ available: true,
6
+ value,
7
+ source: source ?? "runtime"
8
+ };
9
+ }
10
+ function unavailableCapability(reason, details) {
11
+ return {
12
+ status: "unavailable",
13
+ available: false,
14
+ reason,
15
+ details
16
+ };
17
+ }
18
+ /**
19
+ * Narrow a capability result to its available branch.
20
+ *
21
+ * @param result Capability discovery or negotiation result.
22
+ * @returns Whether `result.value` is ready for use.
23
+ */
24
+ function isCapabilityAvailable(result) {
25
+ return result.available;
26
+ }
27
+ /**
28
+ * Narrow a capability result to its unavailable branch.
29
+ *
30
+ * @param result Capability discovery or negotiation result.
31
+ * @returns Whether the capability has a typed unavailability reason.
32
+ */
33
+ function isCapabilityUnavailable(result) {
34
+ return !result.available;
35
+ }
36
+ //#endregion
37
+ export { availableCapability, isCapabilityAvailable, isCapabilityUnavailable, unavailableCapability };