elements-kit 0.0.8 → 0.0.9
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/README.md +3 -3
- package/dist/builder/dom.d.mts +1 -1
- package/dist/builder/index.d.mts +1 -1
- package/dist/{index-BGKVkZ6y.d.mts → index-BtqiEEfc.d.mts} +1 -1
- package/dist/{index-Ukqj0EcT.d.mts → index-CKjDUp1B.d.mts} +1 -1
- package/dist/jsx-runtime/index.d.mts +1 -1
- package/dist/magic-string.es-i62WTP6J.mjs +1011 -0
- package/dist/signals/index.d.mts +1 -1
- package/dist/signals/lib/active-element.d.mts +10 -0
- package/dist/signals/lib/active-element.mjs +20 -0
- package/dist/signals/lib/active-element.test.d.mts +1 -0
- package/dist/signals/lib/active-element.test.mjs +39 -0
- package/dist/signals/lib/animation-frames.d.mts +18 -0
- package/dist/signals/lib/animation-frames.mjs +48 -0
- package/dist/signals/lib/animation-frames.test.d.mts +1 -0
- package/dist/signals/lib/animation-frames.test.mjs +52 -0
- package/dist/signals/lib/async-retry.d.mts +21 -0
- package/dist/signals/lib/async-retry.mjs +57 -0
- package/dist/signals/lib/async-retry.test.d.mts +1 -0
- package/dist/signals/lib/async-retry.test.mjs +57 -0
- package/dist/signals/lib/audio.d.mts +26 -0
- package/dist/signals/lib/audio.mjs +60 -0
- package/dist/signals/lib/audio.test.d.mts +1 -0
- package/dist/signals/lib/audio.test.mjs +54 -0
- package/dist/signals/lib/battery.d.mts +17 -0
- package/dist/signals/lib/battery.mjs +45 -0
- package/dist/signals/lib/battery.test.d.mts +1 -0
- package/dist/signals/lib/battery.test.mjs +38 -0
- package/dist/signals/lib/before-unload.d.mts +11 -0
- package/dist/signals/lib/before-unload.mjs +20 -0
- package/dist/signals/lib/before-unload.test.d.mts +1 -0
- package/dist/signals/lib/before-unload.test.mjs +29 -0
- package/dist/signals/lib/clipboard.d.mts +15 -0
- package/dist/signals/lib/clipboard.mjs +25 -0
- package/dist/signals/lib/clipboard.test.d.mts +1 -0
- package/dist/signals/lib/clipboard.test.mjs +53 -0
- package/dist/signals/lib/counter.d.mts +18 -0
- package/dist/signals/lib/counter.mjs +21 -0
- package/dist/signals/lib/counter.test.d.mts +1 -0
- package/dist/signals/lib/counter.test.mjs +74 -0
- package/dist/signals/lib/debounced.d.mts +12 -0
- package/dist/signals/lib/debounced.mjs +20 -0
- package/dist/signals/lib/debounced.test.d.mts +1 -0
- package/dist/signals/lib/debounced.test.mjs +66 -0
- package/dist/signals/lib/document-title.d.mts +10 -0
- package/dist/signals/lib/document-title.mjs +15 -0
- package/dist/signals/lib/document-title.test.d.mts +1 -0
- package/dist/signals/lib/document-title.test.mjs +33 -0
- package/dist/signals/lib/element-rect.d.mts +21 -0
- package/dist/signals/lib/element-rect.mjs +46 -0
- package/dist/signals/lib/element-rect.test.d.mts +1 -0
- package/dist/signals/lib/element-rect.test.mjs +99 -0
- package/dist/signals/lib/element-size.d.mts +16 -0
- package/dist/signals/lib/element-size.mjs +32 -0
- package/dist/signals/lib/element-size.test.d.mts +1 -0
- package/dist/signals/lib/element-size.test.mjs +86 -0
- package/dist/signals/lib/event-listener.d.mts +14 -0
- package/dist/signals/lib/event-listener.mjs +28 -0
- package/dist/signals/lib/event-listener.test.d.mts +1 -0
- package/dist/signals/lib/event-listener.test.mjs +58 -0
- package/dist/signals/lib/favicon.d.mts +10 -0
- package/dist/signals/lib/favicon.mjs +24 -0
- package/dist/signals/lib/favicon.test.d.mts +1 -0
- package/dist/signals/lib/favicon.test.mjs +28 -0
- package/dist/signals/lib/finite-state-machine.d.mts +22 -0
- package/dist/signals/lib/finite-state-machine.mjs +26 -0
- package/dist/signals/lib/finite-state-machine.test.d.mts +1 -0
- package/dist/signals/lib/finite-state-machine.test.mjs +66 -0
- package/dist/signals/lib/fullscreen.d.mts +15 -0
- package/dist/signals/lib/fullscreen.mjs +26 -0
- package/dist/signals/lib/fullscreen.test.d.mts +1 -0
- package/dist/signals/lib/fullscreen.test.mjs +56 -0
- package/dist/signals/lib/geolocation.d.mts +15 -0
- package/dist/signals/lib/geolocation.mjs +30 -0
- package/dist/signals/lib/geolocation.test.d.mts +1 -0
- package/dist/signals/lib/geolocation.test.mjs +37 -0
- package/dist/signals/lib/hash.d.mts +10 -0
- package/dist/signals/lib/hash.mjs +20 -0
- package/dist/signals/lib/hash.test.d.mts +1 -0
- package/dist/signals/lib/hash.test.mjs +47 -0
- package/dist/signals/lib/hover.d.mts +11 -0
- package/dist/signals/lib/hover.mjs +23 -0
- package/dist/signals/lib/hover.test.d.mts +1 -0
- package/dist/signals/lib/hover.test.mjs +63 -0
- package/dist/signals/lib/intersection-observer.d.mts +8 -0
- package/dist/signals/lib/intersection-observer.mjs +16 -0
- package/dist/signals/lib/intersection-observer.test.d.mts +1 -0
- package/dist/signals/lib/intersection-observer.test.mjs +44 -0
- package/dist/signals/lib/interval.d.mts +18 -0
- package/dist/signals/lib/interval.mjs +38 -0
- package/dist/signals/lib/interval.test.d.mts +1 -0
- package/dist/signals/lib/interval.test.mjs +68 -0
- package/dist/signals/lib/is-document-visible.d.mts +11 -0
- package/dist/signals/lib/is-document-visible.mjs +19 -0
- package/dist/signals/lib/is-document-visible.test.d.mts +1 -0
- package/dist/signals/lib/is-document-visible.test.mjs +58 -0
- package/dist/signals/lib/is-focus-within.d.mts +10 -0
- package/dist/signals/lib/is-focus-within.mjs +28 -0
- package/dist/signals/lib/is-focus-within.test.d.mts +1 -0
- package/dist/signals/lib/is-focus-within.test.mjs +50 -0
- package/dist/signals/lib/is-idle.d.mts +10 -0
- package/dist/signals/lib/is-idle.mjs +37 -0
- package/dist/signals/lib/is-idle.test.d.mts +1 -0
- package/dist/signals/lib/is-idle.test.mjs +50 -0
- package/dist/signals/lib/is-in-viewport.d.mts +10 -0
- package/dist/signals/lib/is-in-viewport.mjs +16 -0
- package/dist/signals/lib/is-in-viewport.test.d.mts +1 -0
- package/dist/signals/lib/is-in-viewport.test.mjs +74 -0
- package/dist/signals/lib/key-press.d.mts +13 -0
- package/dist/signals/lib/key-press.mjs +25 -0
- package/dist/signals/lib/key-press.test.d.mts +1 -0
- package/dist/signals/lib/key-press.test.mjs +52 -0
- package/dist/signals/lib/list.d.mts +19 -0
- package/dist/signals/lib/list.mjs +36 -0
- package/dist/signals/lib/list.test.d.mts +1 -0
- package/dist/signals/lib/list.test.mjs +104 -0
- package/dist/signals/lib/lock-body-scroll.d.mts +8 -0
- package/dist/signals/lib/lock-body-scroll.mjs +17 -0
- package/dist/signals/lib/lock-body-scroll.test.d.mts +1 -0
- package/dist/signals/lib/lock-body-scroll.test.mjs +37 -0
- package/dist/signals/lib/long-press.d.mts +10 -0
- package/dist/signals/lib/long-press.mjs +29 -0
- package/dist/signals/lib/long-press.test.d.mts +1 -0
- package/dist/signals/lib/long-press.test.mjs +52 -0
- package/dist/signals/lib/map.d.mts +18 -0
- package/dist/signals/lib/map.mjs +33 -0
- package/dist/signals/lib/map.test.d.mts +1 -0
- package/dist/signals/lib/map.test.mjs +60 -0
- package/dist/signals/lib/media-devices.d.mts +10 -0
- package/dist/signals/lib/media-devices.mjs +18 -0
- package/dist/signals/lib/media-devices.test.d.mts +1 -0
- package/dist/signals/lib/media-devices.test.mjs +44 -0
- package/dist/signals/lib/media.d.mts +1 -1
- package/dist/signals/lib/motion.d.mts +15 -0
- package/dist/signals/lib/motion.mjs +27 -0
- package/dist/signals/lib/motion.test.d.mts +1 -0
- package/dist/signals/lib/motion.test.mjs +51 -0
- package/dist/signals/lib/mouse-position.d.mts +14 -0
- package/dist/signals/lib/mouse-position.mjs +22 -0
- package/dist/signals/lib/mouse-position.test.d.mts +1 -0
- package/dist/signals/lib/mouse-position.test.mjs +44 -0
- package/dist/signals/lib/mouse-wheel.d.mts +10 -0
- package/dist/signals/lib/mouse-wheel.mjs +17 -0
- package/dist/signals/lib/mouse-wheel.test.d.mts +1 -0
- package/dist/signals/lib/mouse-wheel.test.mjs +38 -0
- package/dist/signals/lib/mutation-observer.d.mts +8 -0
- package/dist/signals/lib/mutation-observer.mjs +16 -0
- package/dist/signals/lib/mutation-observer.test.d.mts +1 -0
- package/dist/signals/lib/mutation-observer.test.mjs +46 -0
- package/dist/signals/lib/network-state.d.mts +17 -0
- package/dist/signals/lib/network-state.mjs +34 -0
- package/dist/signals/lib/network-state.test.d.mts +1 -0
- package/dist/signals/lib/network-state.test.mjs +61 -0
- package/dist/signals/lib/on-click-outside.d.mts +11 -0
- package/dist/signals/lib/on-click-outside.mjs +20 -0
- package/dist/signals/lib/on-click-outside.test.d.mts +1 -0
- package/dist/signals/lib/on-click-outside.test.mjs +54 -0
- package/dist/signals/lib/orientation.d.mts +13 -0
- package/dist/signals/lib/orientation.mjs +21 -0
- package/dist/signals/lib/orientation.test.d.mts +1 -0
- package/dist/signals/lib/orientation.test.mjs +43 -0
- package/dist/signals/lib/page-leave.d.mts +8 -0
- package/dist/signals/lib/page-leave.mjs +12 -0
- package/dist/signals/lib/page-leave.test.d.mts +1 -0
- package/dist/signals/lib/page-leave.test.mjs +29 -0
- package/dist/signals/lib/permission.d.mts +14 -0
- package/dist/signals/lib/permission.mjs +26 -0
- package/dist/signals/lib/permission.test.d.mts +1 -0
- package/dist/signals/lib/permission.test.mjs +50 -0
- package/dist/signals/lib/persisted-state.d.mts +11 -0
- package/dist/signals/lib/persisted-state.mjs +25 -0
- package/dist/signals/lib/persisted-state.test.d.mts +1 -0
- package/dist/signals/lib/persisted-state.test.mjs +70 -0
- package/dist/signals/lib/pressed-keys.d.mts +10 -0
- package/dist/signals/lib/pressed-keys.mjs +32 -0
- package/dist/signals/lib/pressed-keys.test.d.mts +1 -0
- package/dist/signals/lib/pressed-keys.test.mjs +54 -0
- package/dist/signals/lib/previous-distinct.d.mts +10 -0
- package/dist/signals/lib/previous-distinct.mjs +22 -0
- package/dist/signals/lib/previous-distinct.test.d.mts +1 -0
- package/dist/signals/lib/previous-distinct.test.mjs +50 -0
- package/dist/signals/lib/previous.d.mts +10 -0
- package/dist/signals/lib/previous.mjs +18 -0
- package/dist/signals/lib/previous.test.d.mts +1 -0
- package/dist/signals/lib/previous.test.mjs +47 -0
- package/dist/signals/lib/queue.d.mts +17 -0
- package/dist/signals/lib/queue.mjs +28 -0
- package/dist/signals/lib/queue.test.d.mts +1 -0
- package/dist/signals/lib/queue.test.mjs +61 -0
- package/dist/signals/lib/raf.d.mts +17 -0
- package/dist/signals/lib/raf.mjs +38 -0
- package/dist/signals/lib/raf.test.d.mts +1 -0
- package/dist/signals/lib/raf.test.mjs +58 -0
- package/dist/signals/lib/react.d.mts +1 -1
- package/dist/signals/lib/resize-observer.d.mts +8 -0
- package/dist/signals/lib/resize-observer.mjs +16 -0
- package/dist/signals/lib/resize-observer.test.d.mts +1 -0
- package/dist/signals/lib/resize-observer.test.mjs +44 -0
- package/dist/signals/lib/resource.d.mts +23 -0
- package/dist/signals/lib/resource.mjs +43 -0
- package/dist/signals/lib/resource.test.d.mts +1 -0
- package/dist/signals/lib/resource.test.mjs +56 -0
- package/dist/signals/lib/scroll-state.d.mts +19 -0
- package/dist/signals/lib/scroll-state.mjs +46 -0
- package/dist/signals/lib/scroll-state.test.d.mts +1 -0
- package/dist/signals/lib/scroll-state.test.mjs +94 -0
- package/dist/signals/lib/scrolling.d.mts +12 -0
- package/dist/signals/lib/scrolling.mjs +26 -0
- package/dist/signals/lib/scrolling.test.d.mts +1 -0
- package/dist/signals/lib/scrolling.test.mjs +57 -0
- package/dist/signals/lib/search-params.d.mts +16 -0
- package/dist/signals/lib/search-params.mjs +37 -0
- package/dist/signals/lib/search-params.test.d.mts +1 -0
- package/dist/signals/lib/search-params.test.mjs +56 -0
- package/dist/signals/lib/set.d.mts +18 -0
- package/dist/signals/lib/set.mjs +38 -0
- package/dist/signals/lib/set.test.d.mts +1 -0
- package/dist/signals/lib/set.test.mjs +70 -0
- package/dist/signals/lib/start-typing.d.mts +9 -0
- package/dist/signals/lib/start-typing.mjs +39 -0
- package/dist/signals/lib/start-typing.test.d.mts +1 -0
- package/dist/signals/lib/start-typing.test.mjs +64 -0
- package/dist/signals/lib/state-history.d.mts +21 -0
- package/dist/signals/lib/state-history.mjs +61 -0
- package/dist/signals/lib/state-history.test.d.mts +1 -0
- package/dist/signals/lib/state-history.test.mjs +106 -0
- package/dist/signals/lib/state-validator.d.mts +16 -0
- package/dist/signals/lib/state-validator.mjs +21 -0
- package/dist/signals/lib/state-validator.test.d.mts +1 -0
- package/dist/signals/lib/state-validator.test.mjs +41 -0
- package/dist/signals/lib/throttled.d.mts +13 -0
- package/dist/signals/lib/throttled.mjs +45 -0
- package/dist/signals/lib/throttled.test.d.mts +1 -0
- package/dist/signals/lib/throttled.test.mjs +56 -0
- package/dist/signals/lib/timeout.d.mts +16 -0
- package/dist/signals/lib/timeout.mjs +39 -0
- package/dist/signals/lib/timeout.test.d.mts +1 -0
- package/dist/signals/lib/timeout.test.mjs +64 -0
- package/dist/signals/lib/toggle.d.mts +12 -0
- package/dist/signals/lib/toggle.mjs +12 -0
- package/dist/signals/lib/toggle.test.d.mts +1 -0
- package/dist/signals/lib/toggle.test.mjs +43 -0
- package/dist/signals/lib/video.d.mts +25 -0
- package/dist/signals/lib/video.mjs +59 -0
- package/dist/signals/lib/video.test.d.mts +1 -0
- package/dist/signals/lib/video.test.mjs +51 -0
- package/dist/signals/lib/watch.d.mts +16 -0
- package/dist/signals/lib/watch.mjs +31 -0
- package/dist/signals/lib/watch.test.d.mts +1 -0
- package/dist/signals/lib/watch.test.mjs +51 -0
- package/dist/signals/lib/window-size.d.mts +14 -0
- package/dist/signals/lib/window-size.mjs +22 -0
- package/dist/signals/lib/window-size.test.d.mts +1 -0
- package/dist/signals/lib/window-size.test.mjs +50 -0
- package/dist/slot.d.mts +1 -1
- package/dist/test.BmQO5GaM-CR2qjV1t.mjs +13314 -0
- package/package.json +1 -1
- /package/dist/{polyfill-BW_B2r6i.d.mts → polyfill-AFIi9kAN.d.mts} +0 -0
package/dist/signals/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as untracked, a as reactive, c as effect, d as isEffect, f as isEffectScope, g as trigger, h as signal, i as isReactive, l as effectScope, m as onCleanup, n as Signal, o as batch, p as isSignal, r as Updater, s as computed, t as Computed, u as isComputed } from "../index-
|
|
1
|
+
import { _ as untracked, a as reactive, c as effect, d as isEffect, f as isEffectScope, g as trigger, h as signal, i as isReactive, l as effectScope, m as onCleanup, n as Signal, o as batch, p as isSignal, r as Updater, s as computed, t as Computed, u as isComputed } from "../index-BtqiEEfc.mjs";
|
|
2
2
|
export { Computed, Signal, Updater, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, signal, trigger, untracked };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { t as Computed } from "../../index-BtqiEEfc.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/signals/lib/active-element.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns a `Computed` that tracks `document.activeElement`.
|
|
6
|
+
* Updates on every `focusin` / `focusout` event bubbling through the document.
|
|
7
|
+
*/
|
|
8
|
+
declare function createActiveElement(): Computed<Element | null> & Disposable;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { createActiveElement };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { f as signal } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { createEventListener } from "./event-listener.mjs";
|
|
3
|
+
//#region src/signals/lib/active-element.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns a `Computed` that tracks `document.activeElement`.
|
|
6
|
+
* Updates on every `focusin` / `focusout` event bubbling through the document.
|
|
7
|
+
*/
|
|
8
|
+
function createActiveElement() {
|
|
9
|
+
const active = signal(typeof document !== "undefined" ? document.activeElement : null);
|
|
10
|
+
const update = () => active(document.activeElement);
|
|
11
|
+
const r1 = createEventListener(document, "focusin", update);
|
|
12
|
+
const r2 = createEventListener(document, "focusout", update);
|
|
13
|
+
const cleanup = () => {
|
|
14
|
+
r1();
|
|
15
|
+
r2();
|
|
16
|
+
};
|
|
17
|
+
return Object.assign(active, { [Symbol.dispose]: cleanup });
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { createActiveElement };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { o as effectScope } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { a as describe, o as it, r as afterEach, t as globalExpect } from "../../test.BmQO5GaM-CR2qjV1t.mjs";
|
|
3
|
+
import { createActiveElement } from "./active-element.mjs";
|
|
4
|
+
//#region src/signals/lib/active-element.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
});
|
|
8
|
+
describe("createActiveElement", () => {
|
|
9
|
+
it("returns a computed that reads the current activeElement", () => {
|
|
10
|
+
let active;
|
|
11
|
+
effectScope(() => {
|
|
12
|
+
active = createActiveElement();
|
|
13
|
+
});
|
|
14
|
+
globalExpect(active()).toBe(document.activeElement);
|
|
15
|
+
});
|
|
16
|
+
it("updates when focus changes", () => {
|
|
17
|
+
const input = document.createElement("input");
|
|
18
|
+
document.body.appendChild(input);
|
|
19
|
+
let active;
|
|
20
|
+
effectScope(() => {
|
|
21
|
+
active = createActiveElement();
|
|
22
|
+
});
|
|
23
|
+
document.dispatchEvent(new FocusEvent("focusin", { relatedTarget: input }));
|
|
24
|
+
globalExpect(active()).toBe(document.activeElement);
|
|
25
|
+
});
|
|
26
|
+
it("stops updating after Symbol.dispose", () => {
|
|
27
|
+
let active;
|
|
28
|
+
effectScope(() => {
|
|
29
|
+
active = createActiveElement();
|
|
30
|
+
});
|
|
31
|
+
active[Symbol.dispose]();
|
|
32
|
+
const input = document.createElement("input");
|
|
33
|
+
document.body.appendChild(input);
|
|
34
|
+
input.focus();
|
|
35
|
+
globalExpect(typeof active()).not.toBe("undefined");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { t as Computed } from "../../index-BtqiEEfc.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/signals/lib/animation-frames.d.ts
|
|
4
|
+
type AnimationFramesResult = {
|
|
5
|
+
isRunning: Computed<boolean>;
|
|
6
|
+
delta: Computed<number>;
|
|
7
|
+
elapsed: Computed<number>;
|
|
8
|
+
start(): void;
|
|
9
|
+
stop(): void;
|
|
10
|
+
} & Disposable;
|
|
11
|
+
/**
|
|
12
|
+
* RAF loop with pause/resume, delta time, and elapsed time tracking.
|
|
13
|
+
*
|
|
14
|
+
* Starts paused — call `start()` to begin.
|
|
15
|
+
*/
|
|
16
|
+
declare function createAnimationFrames(): AnimationFramesResult;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createAnimationFrames };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { d as onCleanup, f as signal } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
//#region src/signals/lib/animation-frames.ts
|
|
3
|
+
/**
|
|
4
|
+
* RAF loop with pause/resume, delta time, and elapsed time tracking.
|
|
5
|
+
*
|
|
6
|
+
* Starts paused — call `start()` to begin.
|
|
7
|
+
*/
|
|
8
|
+
function createAnimationFrames() {
|
|
9
|
+
const isRunning = signal(false);
|
|
10
|
+
const delta = signal(0);
|
|
11
|
+
const elapsed = signal(0);
|
|
12
|
+
let rafId;
|
|
13
|
+
let lastTime;
|
|
14
|
+
const loop = (time) => {
|
|
15
|
+
if (lastTime !== void 0) {
|
|
16
|
+
const d = time - lastTime;
|
|
17
|
+
delta(d);
|
|
18
|
+
elapsed(elapsed() + d);
|
|
19
|
+
}
|
|
20
|
+
lastTime = time;
|
|
21
|
+
rafId = requestAnimationFrame(loop);
|
|
22
|
+
};
|
|
23
|
+
const start = () => {
|
|
24
|
+
if (isRunning()) return;
|
|
25
|
+
lastTime = void 0;
|
|
26
|
+
isRunning(true);
|
|
27
|
+
rafId = requestAnimationFrame(loop);
|
|
28
|
+
};
|
|
29
|
+
const stop = () => {
|
|
30
|
+
if (rafId !== void 0) {
|
|
31
|
+
cancelAnimationFrame(rafId);
|
|
32
|
+
rafId = void 0;
|
|
33
|
+
}
|
|
34
|
+
lastTime = void 0;
|
|
35
|
+
isRunning(false);
|
|
36
|
+
};
|
|
37
|
+
const cleanup = () => stop();
|
|
38
|
+
onCleanup(cleanup);
|
|
39
|
+
return Object.assign({
|
|
40
|
+
isRunning,
|
|
41
|
+
delta,
|
|
42
|
+
elapsed,
|
|
43
|
+
start,
|
|
44
|
+
stop
|
|
45
|
+
}, { [Symbol.dispose]: cleanup });
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { createAnimationFrames };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { o as effectScope } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { a as describe, n as vi, o as it, r as afterEach, t as globalExpect } from "../../test.BmQO5GaM-CR2qjV1t.mjs";
|
|
3
|
+
import { createAnimationFrames } from "./animation-frames.mjs";
|
|
4
|
+
//#region src/signals/lib/animation-frames.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
vi.unstubAllGlobals();
|
|
8
|
+
});
|
|
9
|
+
describe("createAnimationFrames", () => {
|
|
10
|
+
it("starts paused", () => {
|
|
11
|
+
let af;
|
|
12
|
+
effectScope(() => {
|
|
13
|
+
af = createAnimationFrames();
|
|
14
|
+
});
|
|
15
|
+
globalExpect(af.isRunning()).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
it("start() sets isRunning to true", () => {
|
|
18
|
+
vi.stubGlobal("requestAnimationFrame", vi.fn().mockReturnValue(1));
|
|
19
|
+
vi.stubGlobal("cancelAnimationFrame", vi.fn());
|
|
20
|
+
let af;
|
|
21
|
+
effectScope(() => {
|
|
22
|
+
af = createAnimationFrames();
|
|
23
|
+
});
|
|
24
|
+
af.start();
|
|
25
|
+
globalExpect(af.isRunning()).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it("stop() sets isRunning to false", () => {
|
|
28
|
+
vi.stubGlobal("requestAnimationFrame", vi.fn().mockReturnValue(1));
|
|
29
|
+
vi.stubGlobal("cancelAnimationFrame", vi.fn());
|
|
30
|
+
let af;
|
|
31
|
+
effectScope(() => {
|
|
32
|
+
af = createAnimationFrames();
|
|
33
|
+
});
|
|
34
|
+
af.start();
|
|
35
|
+
af.stop();
|
|
36
|
+
globalExpect(af.isRunning()).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
it("Symbol.dispose stops the loop", () => {
|
|
39
|
+
const cancel = vi.fn();
|
|
40
|
+
vi.stubGlobal("requestAnimationFrame", vi.fn().mockReturnValue(1));
|
|
41
|
+
vi.stubGlobal("cancelAnimationFrame", cancel);
|
|
42
|
+
let af;
|
|
43
|
+
effectScope(() => {
|
|
44
|
+
af = createAnimationFrames();
|
|
45
|
+
});
|
|
46
|
+
af.start();
|
|
47
|
+
af[Symbol.dispose]();
|
|
48
|
+
globalExpect(cancel).toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//#endregion
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { t as Computed } from "../../index-BtqiEEfc.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/signals/lib/async-retry.d.ts
|
|
4
|
+
type AsyncRetryResult<T> = {
|
|
5
|
+
data: Computed<T | undefined>;
|
|
6
|
+
loading: Computed<boolean>;
|
|
7
|
+
error: Computed<unknown>;
|
|
8
|
+
retry(): void;
|
|
9
|
+
attempt: Computed<number>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Like `createResource` but automatically retries on failure up to
|
|
13
|
+
* `maxRetries` times with an exponential-back-off delay.
|
|
14
|
+
*/
|
|
15
|
+
declare function createAsyncRetry<S, T>(source: () => S, fetcher: (source: S, signal: AbortSignal) => Promise<T>, options?: {
|
|
16
|
+
initialValue?: T;
|
|
17
|
+
maxRetries?: number;
|
|
18
|
+
delay?: number;
|
|
19
|
+
}): AsyncRetryResult<T>;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { createAsyncRetry };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { a as effect, d as onCleanup, f as signal } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
//#region src/signals/lib/async-retry.ts
|
|
3
|
+
/**
|
|
4
|
+
* Like `createResource` but automatically retries on failure up to
|
|
5
|
+
* `maxRetries` times with an exponential-back-off delay.
|
|
6
|
+
*/
|
|
7
|
+
function createAsyncRetry(source, fetcher, options) {
|
|
8
|
+
const { maxRetries = 3, delay = 1e3 } = options ?? {};
|
|
9
|
+
const data = signal(options?.initialValue);
|
|
10
|
+
const loading = signal(false);
|
|
11
|
+
const error = signal(void 0);
|
|
12
|
+
const attempt = signal(0);
|
|
13
|
+
const tick = signal(0);
|
|
14
|
+
effect(() => {
|
|
15
|
+
tick();
|
|
16
|
+
const src = source();
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
loading(true);
|
|
19
|
+
error(void 0);
|
|
20
|
+
attempt(0);
|
|
21
|
+
let currentAttempt = 0;
|
|
22
|
+
const run = () => {
|
|
23
|
+
fetcher(src, controller.signal).then((result) => {
|
|
24
|
+
data(result);
|
|
25
|
+
loading(false);
|
|
26
|
+
}, (err) => {
|
|
27
|
+
if (err.name === "AbortError") return;
|
|
28
|
+
if (currentAttempt < maxRetries) {
|
|
29
|
+
currentAttempt++;
|
|
30
|
+
attempt(currentAttempt);
|
|
31
|
+
const retryTimer = setTimeout(run, delay * 2 ** (currentAttempt - 1));
|
|
32
|
+
const orig = cleanup;
|
|
33
|
+
cleanup = () => {
|
|
34
|
+
clearTimeout(retryTimer);
|
|
35
|
+
orig();
|
|
36
|
+
};
|
|
37
|
+
} else {
|
|
38
|
+
error(err);
|
|
39
|
+
loading(false);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
let cleanup = () => controller.abort();
|
|
44
|
+
run();
|
|
45
|
+
onCleanup(() => cleanup());
|
|
46
|
+
});
|
|
47
|
+
const retry = () => tick(tick() + 1);
|
|
48
|
+
return {
|
|
49
|
+
data,
|
|
50
|
+
loading,
|
|
51
|
+
error,
|
|
52
|
+
attempt,
|
|
53
|
+
retry
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { createAsyncRetry };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { o as effectScope } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { a as describe, n as vi, o as it, r as afterEach, t as globalExpect } from "../../test.BmQO5GaM-CR2qjV1t.mjs";
|
|
3
|
+
import { createAsyncRetry } from "./async-retry.mjs";
|
|
4
|
+
//#region src/signals/lib/async-retry.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
vi.useRealTimers();
|
|
8
|
+
});
|
|
9
|
+
describe("createAsyncRetry", () => {
|
|
10
|
+
it("resolves successfully on first try", async () => {
|
|
11
|
+
const src = () => "url";
|
|
12
|
+
let r;
|
|
13
|
+
effectScope(() => {
|
|
14
|
+
r = createAsyncRetry(src, async () => "ok");
|
|
15
|
+
});
|
|
16
|
+
await new Promise((res) => setTimeout(res, 0));
|
|
17
|
+
globalExpect(r.data()).toBe("ok");
|
|
18
|
+
globalExpect(r.loading()).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it("retries on failure and eventually resolves", async () => {
|
|
21
|
+
vi.useFakeTimers();
|
|
22
|
+
let calls = 0;
|
|
23
|
+
const src = () => "url";
|
|
24
|
+
let r;
|
|
25
|
+
effectScope(() => {
|
|
26
|
+
r = createAsyncRetry(src, async () => {
|
|
27
|
+
calls++;
|
|
28
|
+
if (calls < 3) throw new Error("fail");
|
|
29
|
+
return "success";
|
|
30
|
+
}, {
|
|
31
|
+
maxRetries: 3,
|
|
32
|
+
delay: 100
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
await vi.runAllTicks();
|
|
36
|
+
await vi.runAllTimersAsync();
|
|
37
|
+
globalExpect(r.data()).toBe("success");
|
|
38
|
+
}, 1e4);
|
|
39
|
+
it("sets error after exhausting retries", async () => {
|
|
40
|
+
vi.useFakeTimers();
|
|
41
|
+
const src = () => "url";
|
|
42
|
+
let r;
|
|
43
|
+
effectScope(() => {
|
|
44
|
+
r = createAsyncRetry(src, async () => {
|
|
45
|
+
throw new Error("persistent");
|
|
46
|
+
}, {
|
|
47
|
+
maxRetries: 2,
|
|
48
|
+
delay: 50
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
await vi.runAllTimersAsync();
|
|
52
|
+
globalExpect(r.error()).toBeInstanceOf(Error);
|
|
53
|
+
globalExpect(r.loading()).toBe(false);
|
|
54
|
+
}, 1e4);
|
|
55
|
+
});
|
|
56
|
+
//#endregion
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { t as Computed } from "../../index-BtqiEEfc.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/signals/lib/audio.d.ts
|
|
4
|
+
type AudioResult = {
|
|
5
|
+
element: HTMLAudioElement;
|
|
6
|
+
playing: Computed<boolean>;
|
|
7
|
+
muted: Computed<boolean>;
|
|
8
|
+
volume: Computed<number>;
|
|
9
|
+
duration: Computed<number>;
|
|
10
|
+
time: Computed<number>;
|
|
11
|
+
ended: Computed<boolean>;
|
|
12
|
+
play(): void;
|
|
13
|
+
pause(): void;
|
|
14
|
+
toggle(): void;
|
|
15
|
+
setVolume(v: number): void;
|
|
16
|
+
setTime(t: number): void;
|
|
17
|
+
mute(): void;
|
|
18
|
+
unmute(): void;
|
|
19
|
+
} & Disposable;
|
|
20
|
+
/**
|
|
21
|
+
* Wraps an `HTMLAudioElement` with reactive state and playback controls.
|
|
22
|
+
* Pass a `src` string to create a new element, or pass an existing element.
|
|
23
|
+
*/
|
|
24
|
+
declare function createAudio(src: string | HTMLAudioElement): AudioResult;
|
|
25
|
+
//#endregion
|
|
26
|
+
export { createAudio };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { f as signal } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { createEventListener } from "./event-listener.mjs";
|
|
3
|
+
//#region src/signals/lib/audio.ts
|
|
4
|
+
/**
|
|
5
|
+
* Wraps an `HTMLAudioElement` with reactive state and playback controls.
|
|
6
|
+
* Pass a `src` string to create a new element, or pass an existing element.
|
|
7
|
+
*/
|
|
8
|
+
function createAudio(src) {
|
|
9
|
+
const el = typeof src === "string" ? new Audio(src) : src;
|
|
10
|
+
const playing = signal(!el.paused);
|
|
11
|
+
const muted = signal(el.muted);
|
|
12
|
+
const volume = signal(el.volume);
|
|
13
|
+
const duration = signal(el.duration || 0);
|
|
14
|
+
const time = signal(el.currentTime);
|
|
15
|
+
const ended = signal(el.ended);
|
|
16
|
+
const onPlay = () => playing(true);
|
|
17
|
+
const onPause = () => playing(false);
|
|
18
|
+
const onVolumeChange = () => {
|
|
19
|
+
muted(el.muted);
|
|
20
|
+
volume(el.volume);
|
|
21
|
+
};
|
|
22
|
+
const onDurationChange = () => duration(el.duration);
|
|
23
|
+
const onTimeUpdate = () => time(el.currentTime);
|
|
24
|
+
const onEnded = () => ended(true);
|
|
25
|
+
const cleanups = [
|
|
26
|
+
createEventListener(el, "play", onPlay),
|
|
27
|
+
createEventListener(el, "pause", onPause),
|
|
28
|
+
createEventListener(el, "volumechange", onVolumeChange),
|
|
29
|
+
createEventListener(el, "durationchange", onDurationChange),
|
|
30
|
+
createEventListener(el, "timeupdate", onTimeUpdate),
|
|
31
|
+
createEventListener(el, "ended", onEnded)
|
|
32
|
+
];
|
|
33
|
+
const cleanup = () => cleanups.forEach((fn) => fn());
|
|
34
|
+
return Object.assign({
|
|
35
|
+
element: el,
|
|
36
|
+
playing,
|
|
37
|
+
muted,
|
|
38
|
+
volume,
|
|
39
|
+
duration,
|
|
40
|
+
time,
|
|
41
|
+
ended,
|
|
42
|
+
play: () => el.play(),
|
|
43
|
+
pause: () => el.pause(),
|
|
44
|
+
toggle: () => el.paused ? el.play() : el.pause(),
|
|
45
|
+
setVolume: (v) => {
|
|
46
|
+
el.volume = Math.min(1, Math.max(0, v));
|
|
47
|
+
},
|
|
48
|
+
setTime: (t) => {
|
|
49
|
+
el.currentTime = t;
|
|
50
|
+
},
|
|
51
|
+
mute: () => {
|
|
52
|
+
el.muted = true;
|
|
53
|
+
},
|
|
54
|
+
unmute: () => {
|
|
55
|
+
el.muted = false;
|
|
56
|
+
}
|
|
57
|
+
}, { [Symbol.dispose]: cleanup });
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { createAudio };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { o as effectScope } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { a as describe, n as vi, o as it, r as afterEach, t as globalExpect } from "../../test.BmQO5GaM-CR2qjV1t.mjs";
|
|
3
|
+
import { createAudio } from "./audio.mjs";
|
|
4
|
+
//#region src/signals/lib/audio.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
vi.restoreAllMocks();
|
|
8
|
+
});
|
|
9
|
+
describe("createAudio", () => {
|
|
10
|
+
it("creates an Audio element from a src string", () => {
|
|
11
|
+
let a;
|
|
12
|
+
effectScope(() => {
|
|
13
|
+
a = createAudio("test.mp3");
|
|
14
|
+
});
|
|
15
|
+
globalExpect(a.element).toBeInstanceOf(HTMLAudioElement);
|
|
16
|
+
});
|
|
17
|
+
it("starts as paused", () => {
|
|
18
|
+
let a;
|
|
19
|
+
effectScope(() => {
|
|
20
|
+
a = createAudio("test.mp3");
|
|
21
|
+
});
|
|
22
|
+
globalExpect(a.playing()).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
it("mute() sets muted to true", () => {
|
|
25
|
+
let a;
|
|
26
|
+
effectScope(() => {
|
|
27
|
+
a = createAudio("test.mp3");
|
|
28
|
+
});
|
|
29
|
+
a.mute();
|
|
30
|
+
globalExpect(a.element.muted).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
it("setVolume clamps to [0, 1]", () => {
|
|
33
|
+
let a;
|
|
34
|
+
effectScope(() => {
|
|
35
|
+
a = createAudio("test.mp3");
|
|
36
|
+
});
|
|
37
|
+
a.setVolume(2);
|
|
38
|
+
globalExpect(a.element.volume).toBe(1);
|
|
39
|
+
a.setVolume(-1);
|
|
40
|
+
globalExpect(a.element.volume).toBe(0);
|
|
41
|
+
});
|
|
42
|
+
it("removes event listeners on Symbol.dispose", () => {
|
|
43
|
+
const removeSpy = vi.fn();
|
|
44
|
+
let a;
|
|
45
|
+
effectScope(() => {
|
|
46
|
+
a = createAudio("test.mp3");
|
|
47
|
+
});
|
|
48
|
+
vi.spyOn(a.element, "removeEventListener").mockImplementation(removeSpy);
|
|
49
|
+
a[Symbol.dispose]();
|
|
50
|
+
globalExpect(removeSpy).toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//#endregion
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { t as Computed } from "../../index-BtqiEEfc.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/signals/lib/battery.d.ts
|
|
4
|
+
type BatteryResult = {
|
|
5
|
+
charging: Computed<boolean>;
|
|
6
|
+
level: Computed<number>;
|
|
7
|
+
chargingTime: Computed<number>;
|
|
8
|
+
dischargingTime: Computed<number>;
|
|
9
|
+
supported: Computed<boolean>;
|
|
10
|
+
} & Disposable;
|
|
11
|
+
/**
|
|
12
|
+
* Exposes the Battery Status API as reactive signals.
|
|
13
|
+
* `supported` will be `false` when the API is unavailable.
|
|
14
|
+
*/
|
|
15
|
+
declare function createBattery(): BatteryResult;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { createBattery };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { d as onCleanup, f as signal } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
//#region src/signals/lib/battery.ts
|
|
3
|
+
/**
|
|
4
|
+
* Exposes the Battery Status API as reactive signals.
|
|
5
|
+
* `supported` will be `false` when the API is unavailable.
|
|
6
|
+
*/
|
|
7
|
+
function createBattery() {
|
|
8
|
+
const supported = signal(typeof navigator !== "undefined" && "getBattery" in navigator);
|
|
9
|
+
const charging = signal(false);
|
|
10
|
+
const level = signal(1);
|
|
11
|
+
const chargingTime = signal(0);
|
|
12
|
+
const dischargingTime = signal(Infinity);
|
|
13
|
+
let battery;
|
|
14
|
+
const update = () => {
|
|
15
|
+
if (!battery) return;
|
|
16
|
+
charging(battery.charging);
|
|
17
|
+
level(battery.level);
|
|
18
|
+
chargingTime(battery.chargingTime);
|
|
19
|
+
dischargingTime(battery.dischargingTime);
|
|
20
|
+
};
|
|
21
|
+
const events = [
|
|
22
|
+
"chargingchange",
|
|
23
|
+
"levelchange",
|
|
24
|
+
"chargingtimechange",
|
|
25
|
+
"dischargingtimechange"
|
|
26
|
+
];
|
|
27
|
+
const cleanup = () => {
|
|
28
|
+
events.forEach((e) => battery?.removeEventListener(e, update));
|
|
29
|
+
};
|
|
30
|
+
if (supported()) navigator.getBattery().then((b) => {
|
|
31
|
+
battery = b;
|
|
32
|
+
update();
|
|
33
|
+
events.forEach((e) => b.addEventListener(e, update));
|
|
34
|
+
});
|
|
35
|
+
onCleanup(cleanup);
|
|
36
|
+
return Object.assign({
|
|
37
|
+
supported,
|
|
38
|
+
charging,
|
|
39
|
+
level,
|
|
40
|
+
chargingTime,
|
|
41
|
+
dischargingTime
|
|
42
|
+
}, { [Symbol.dispose]: cleanup });
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { createBattery };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { o as effectScope } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { a as describe, n as vi, o as it, r as afterEach, t as globalExpect } from "../../test.BmQO5GaM-CR2qjV1t.mjs";
|
|
3
|
+
import { createBattery } from "./battery.mjs";
|
|
4
|
+
//#region src/signals/lib/battery.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
vi.unstubAllGlobals();
|
|
8
|
+
});
|
|
9
|
+
describe("createBattery", () => {
|
|
10
|
+
it("returns unsupported=false when getBattery not present", () => {
|
|
11
|
+
vi.stubGlobal("navigator", {});
|
|
12
|
+
let b;
|
|
13
|
+
effectScope(() => {
|
|
14
|
+
b = createBattery();
|
|
15
|
+
});
|
|
16
|
+
globalExpect(b.supported()).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
it("fetches battery info via getBattery", async () => {
|
|
19
|
+
const batteryMock = {
|
|
20
|
+
charging: true,
|
|
21
|
+
level: .8,
|
|
22
|
+
chargingTime: 3600,
|
|
23
|
+
dischargingTime: Infinity,
|
|
24
|
+
addEventListener: vi.fn(),
|
|
25
|
+
removeEventListener: vi.fn()
|
|
26
|
+
};
|
|
27
|
+
vi.stubGlobal("navigator", { getBattery: vi.fn().mockResolvedValue(batteryMock) });
|
|
28
|
+
let b;
|
|
29
|
+
effectScope(() => {
|
|
30
|
+
b = createBattery();
|
|
31
|
+
});
|
|
32
|
+
await new Promise((res) => setTimeout(res, 0));
|
|
33
|
+
globalExpect(b.charging()).toBe(true);
|
|
34
|
+
globalExpect(b.level()).toBe(.8);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//#endregion
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/signals/lib/before-unload.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Registers a `beforeunload` handler that shows a native confirmation dialog
|
|
4
|
+
* when the user tries to leave the page.
|
|
5
|
+
*
|
|
6
|
+
* `message` can be a string or a reactive getter (re-evaluated on each event).
|
|
7
|
+
* Modern browsers ignore custom messages and show a generic prompt instead.
|
|
8
|
+
*/
|
|
9
|
+
declare function createBeforeUnload(message?: string | (() => string)): Disposable;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { createBeforeUnload };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createEventListener } from "./event-listener.mjs";
|
|
2
|
+
//#region src/signals/lib/before-unload.ts
|
|
3
|
+
/**
|
|
4
|
+
* Registers a `beforeunload` handler that shows a native confirmation dialog
|
|
5
|
+
* when the user tries to leave the page.
|
|
6
|
+
*
|
|
7
|
+
* `message` can be a string or a reactive getter (re-evaluated on each event).
|
|
8
|
+
* Modern browsers ignore custom messages and show a generic prompt instead.
|
|
9
|
+
*/
|
|
10
|
+
function createBeforeUnload(message) {
|
|
11
|
+
const handler = (e) => {
|
|
12
|
+
const msg = typeof message === "function" ? message() : message;
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
if (msg !== void 0) e.returnValue = msg;
|
|
15
|
+
};
|
|
16
|
+
const cleanup = createEventListener(window, "beforeunload", handler);
|
|
17
|
+
return { [Symbol.dispose]: cleanup };
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { createBeforeUnload };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { o as effectScope } from "../../signals-CLAPw8kk.mjs";
|
|
2
|
+
import { a as describe, n as vi, o as it, r as afterEach, t as globalExpect } from "../../test.BmQO5GaM-CR2qjV1t.mjs";
|
|
3
|
+
import { createBeforeUnload } from "./before-unload.mjs";
|
|
4
|
+
//#region src/signals/lib/before-unload.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
document.body.innerHTML = "";
|
|
7
|
+
});
|
|
8
|
+
describe("createBeforeUnload", () => {
|
|
9
|
+
it("registers a beforeunload handler", () => {
|
|
10
|
+
const addSpy = vi.spyOn(window, "addEventListener");
|
|
11
|
+
effectScope(() => {
|
|
12
|
+
createBeforeUnload("Are you sure?");
|
|
13
|
+
});
|
|
14
|
+
globalExpect(addSpy).toHaveBeenCalledWith("beforeunload", globalExpect.any(Function));
|
|
15
|
+
addSpy.mockRestore();
|
|
16
|
+
});
|
|
17
|
+
it("removes the handler on Symbol.dispose", () => {
|
|
18
|
+
const removeSpy = vi.spyOn(window, "removeEventListener");
|
|
19
|
+
let bu;
|
|
20
|
+
effectScope(() => {
|
|
21
|
+
bu = createBeforeUnload();
|
|
22
|
+
});
|
|
23
|
+
bu[Symbol.dispose]();
|
|
24
|
+
globalExpect(removeSpy).toHaveBeenCalledWith("beforeunload", globalExpect.any(Function));
|
|
25
|
+
removeSpy.mockRestore();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
//#endregion
|
|
29
|
+
export {};
|