elements-kit 0.0.10 → 0.0.11
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 -4
- package/dist/builder/dom.d.mts +1 -1
- package/dist/builder/index.d.mts +87 -1
- package/dist/builder/index.mjs +1 -1
- package/dist/{element-Ddk9YaoE.mjs → element-MXzFk4G2.mjs} +1 -1
- package/dist/{index-BtqiEEfc.d.mts → index-Cvdhuy6Y.d.mts} +8 -4
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/{signals/lib → integrations}/react.d.mts +2 -2
- package/dist/{signals/lib → integrations}/react.mjs +2 -2
- package/dist/jsx-runtime/index.d.mts +2 -2
- package/dist/jsx-runtime/index.mjs +3 -3
- package/dist/lib-BYJ5jPTG.d.mts +4 -0
- package/dist/polyfill-DR5XVnh_.d.mts +9 -0
- package/dist/signals/index.d.mts +2 -2
- package/dist/signals/index.mjs +2 -2
- package/dist/{signals-CLAPw8kk.mjs → signals-DcgXhkU2.mjs} +41 -9
- package/dist/slot.d.mts +1 -2
- package/dist/{test.BmQO5GaM-CR2qjV1t.mjs → test.BmQO5GaM-ANkhHvbr.mjs} +1 -1
- package/dist/utilities/active-element.d.mts +6 -0
- package/dist/utilities/active-element.mjs +13 -0
- package/dist/utilities/active-element.test.mjs +24 -0
- package/dist/{signals/lib → utilities}/debounced.d.mts +3 -3
- package/dist/{signals/lib → utilities}/debounced.mjs +7 -6
- package/dist/{signals/lib → utilities}/debounced.test.mjs +3 -3
- package/dist/{signals/lib → utilities}/element-rect.d.mts +3 -3
- package/dist/{signals/lib → utilities}/element-rect.mjs +7 -7
- package/dist/{signals/lib → utilities}/element-rect.test.mjs +3 -3
- package/dist/utilities/element-scroll.d.mts +16 -0
- package/dist/utilities/element-scroll.mjs +52 -0
- package/dist/utilities/element-scroll.test.mjs +25 -0
- package/dist/{signals/lib → utilities}/event-driven.d.mts +2 -2
- package/dist/{signals/lib → utilities}/event-driven.mjs +2 -2
- package/dist/utilities/event-listener.d.mts +16 -0
- package/dist/{signals/lib → utilities}/event-listener.mjs +4 -4
- package/dist/{signals/lib → utilities}/event-listener.test.mjs +8 -8
- package/dist/utilities/focus-within.d.mts +10 -0
- package/dist/utilities/focus-within.mjs +20 -0
- package/dist/{signals/lib/is-focus-within.test.mjs → utilities/focus-within.test.mjs} +10 -11
- package/dist/utilities/hover.d.mts +11 -0
- package/dist/utilities/hover.mjs +20 -0
- package/dist/{signals/lib → utilities}/hover.test.mjs +5 -16
- package/dist/utilities/intersection-observer.d.mts +8 -0
- package/dist/{signals/lib → utilities}/intersection-observer.mjs +3 -4
- package/dist/{signals/lib → utilities}/intersection-observer.test.mjs +3 -3
- package/dist/{signals/lib → utilities}/interval.d.mts +2 -2
- package/dist/{signals/lib → utilities}/interval.mjs +6 -5
- package/dist/{signals/lib → utilities}/interval.test.mjs +3 -3
- package/dist/utilities/location.d.mts +24 -0
- package/dist/utilities/location.mjs +54 -0
- package/dist/utilities/location.test.mjs +60 -0
- package/dist/utilities/long-press.d.mts +10 -0
- package/dist/utilities/long-press.mjs +27 -0
- package/dist/{signals/lib → utilities}/long-press.test.mjs +3 -3
- package/dist/{signals/lib → utilities}/media-devices.d.mts +3 -3
- package/dist/{signals/lib → utilities}/media-devices.mjs +5 -5
- package/dist/{signals/lib → utilities}/media-devices.test.mjs +6 -8
- package/dist/utilities/media-player.d.mts +22 -0
- package/dist/{signals/lib/video.mjs → utilities/media-player.mjs} +5 -4
- package/dist/utilities/media-player.test.mjs +100 -0
- package/dist/{signals/lib/media.d.mts → utilities/media-query.d.mts} +4 -4
- package/dist/{signals/lib/media.mjs → utilities/media-query.mjs} +6 -6
- package/dist/utilities/mutation-observer.d.mts +8 -0
- package/dist/{signals/lib → utilities}/mutation-observer.mjs +3 -3
- package/dist/{signals/lib → utilities}/mutation-observer.test.mjs +3 -3
- package/dist/{signals/lib → utilities}/on-click-outside.d.mts +3 -3
- package/dist/utilities/on-click-outside.mjs +17 -0
- package/dist/{signals/lib → utilities}/on-click-outside.test.mjs +7 -18
- package/dist/utilities/orientation.d.mts +10 -0
- package/dist/{signals/lib → utilities}/orientation.mjs +3 -2
- package/dist/utilities/previous.d.mts +12 -0
- package/dist/utilities/previous.mjs +24 -0
- package/dist/utilities/previous.test.mjs +88 -0
- package/dist/utilities/resize-observer.d.mts +8 -0
- package/dist/{signals/lib → utilities}/resize-observer.mjs +4 -5
- package/dist/utilities/routing.d.mts +59 -0
- package/dist/utilities/routing.mjs +89 -0
- package/dist/utilities/routing.test.mjs +128 -0
- package/dist/utilities/search-params.d.mts +13 -0
- package/dist/utilities/search-params.mjs +23 -0
- package/dist/utilities/search-params.test.mjs +35 -0
- package/dist/utilities/storage.d.mts +22 -0
- package/dist/utilities/storage.mjs +65 -0
- package/dist/utilities/storage.test.mjs +137 -0
- package/dist/{signals/lib → utilities}/throttled.d.mts +2 -2
- package/dist/utilities/throttled.mjs +36 -0
- package/dist/{signals/lib → utilities}/throttled.test.mjs +3 -3
- package/dist/{signals/lib → utilities}/timeout.d.mts +6 -5
- package/dist/utilities/timeout.mjs +42 -0
- package/dist/{signals/lib → utilities}/timeout.test.mjs +7 -7
- package/dist/utilities/window-size.d.mts +10 -0
- package/dist/utilities/window-size.mjs +22 -0
- package/dist/utilities/window-size.test.mjs +42 -0
- package/package.json +11 -6
- package/dist/index-CKjDUp1B.d.mts +0 -89
- package/dist/polyfill-AFIi9kAN.d.mts +0 -14
- package/dist/signals/lib/active-element.d.mts +0 -10
- package/dist/signals/lib/active-element.mjs +0 -12
- package/dist/signals/lib/active-element.test.mjs +0 -39
- package/dist/signals/lib/animation-frames.d.mts +0 -18
- package/dist/signals/lib/animation-frames.mjs +0 -48
- package/dist/signals/lib/animation-frames.test.mjs +0 -52
- package/dist/signals/lib/async-retry.d.mts +0 -21
- package/dist/signals/lib/async-retry.mjs +0 -57
- package/dist/signals/lib/async-retry.test.mjs +0 -57
- package/dist/signals/lib/audio.d.mts +0 -21
- package/dist/signals/lib/audio.mjs +0 -35
- package/dist/signals/lib/audio.test.mjs +0 -57
- package/dist/signals/lib/battery.d.mts +0 -17
- package/dist/signals/lib/battery.mjs +0 -45
- package/dist/signals/lib/battery.test.mjs +0 -38
- package/dist/signals/lib/before-unload.d.mts +0 -11
- package/dist/signals/lib/before-unload.mjs +0 -20
- package/dist/signals/lib/before-unload.test.mjs +0 -29
- package/dist/signals/lib/clipboard.d.mts +0 -15
- package/dist/signals/lib/clipboard.mjs +0 -25
- package/dist/signals/lib/clipboard.test.mjs +0 -53
- package/dist/signals/lib/counter.d.mts +0 -18
- package/dist/signals/lib/counter.mjs +0 -21
- package/dist/signals/lib/counter.test.d.mts +0 -1
- package/dist/signals/lib/counter.test.mjs +0 -74
- package/dist/signals/lib/document-title.d.mts +0 -10
- package/dist/signals/lib/document-title.mjs +0 -15
- package/dist/signals/lib/document-title.test.d.mts +0 -1
- package/dist/signals/lib/document-title.test.mjs +0 -33
- package/dist/signals/lib/element-size.d.mts +0 -16
- package/dist/signals/lib/element-size.mjs +0 -32
- package/dist/signals/lib/element-size.test.d.mts +0 -1
- package/dist/signals/lib/element-size.test.mjs +0 -86
- package/dist/signals/lib/event-listener.d.mts +0 -14
- package/dist/signals/lib/favicon.d.mts +0 -10
- package/dist/signals/lib/favicon.mjs +0 -24
- package/dist/signals/lib/favicon.test.d.mts +0 -1
- package/dist/signals/lib/favicon.test.mjs +0 -28
- package/dist/signals/lib/finite-state-machine.d.mts +0 -22
- package/dist/signals/lib/finite-state-machine.mjs +0 -26
- package/dist/signals/lib/finite-state-machine.test.d.mts +0 -1
- package/dist/signals/lib/finite-state-machine.test.mjs +0 -66
- package/dist/signals/lib/fullscreen.d.mts +0 -15
- package/dist/signals/lib/fullscreen.mjs +0 -24
- package/dist/signals/lib/fullscreen.test.d.mts +0 -1
- package/dist/signals/lib/fullscreen.test.mjs +0 -48
- package/dist/signals/lib/geolocation.d.mts +0 -15
- package/dist/signals/lib/geolocation.mjs +0 -30
- package/dist/signals/lib/geolocation.test.d.mts +0 -1
- package/dist/signals/lib/geolocation.test.mjs +0 -37
- package/dist/signals/lib/hash.d.mts +0 -10
- package/dist/signals/lib/hash.mjs +0 -14
- package/dist/signals/lib/hash.test.d.mts +0 -1
- package/dist/signals/lib/hash.test.mjs +0 -46
- package/dist/signals/lib/hover.d.mts +0 -11
- package/dist/signals/lib/hover.mjs +0 -23
- package/dist/signals/lib/intersection-observer.d.mts +0 -8
- package/dist/signals/lib/is-document-visible.d.mts +0 -11
- package/dist/signals/lib/is-document-visible.mjs +0 -13
- package/dist/signals/lib/is-document-visible.test.d.mts +0 -1
- package/dist/signals/lib/is-document-visible.test.mjs +0 -58
- package/dist/signals/lib/is-focus-within.d.mts +0 -10
- package/dist/signals/lib/is-focus-within.mjs +0 -28
- package/dist/signals/lib/is-focus-within.test.d.mts +0 -1
- package/dist/signals/lib/is-idle.d.mts +0 -10
- package/dist/signals/lib/is-idle.mjs +0 -37
- package/dist/signals/lib/is-idle.test.d.mts +0 -1
- package/dist/signals/lib/is-idle.test.mjs +0 -50
- package/dist/signals/lib/is-in-viewport.d.mts +0 -10
- package/dist/signals/lib/is-in-viewport.mjs +0 -16
- package/dist/signals/lib/is-in-viewport.test.d.mts +0 -1
- package/dist/signals/lib/is-in-viewport.test.mjs +0 -74
- package/dist/signals/lib/key-press.d.mts +0 -13
- package/dist/signals/lib/key-press.mjs +0 -25
- package/dist/signals/lib/key-press.test.d.mts +0 -1
- package/dist/signals/lib/key-press.test.mjs +0 -52
- package/dist/signals/lib/list.d.mts +0 -19
- package/dist/signals/lib/list.mjs +0 -36
- package/dist/signals/lib/list.test.d.mts +0 -1
- package/dist/signals/lib/list.test.mjs +0 -104
- package/dist/signals/lib/lock-body-scroll.d.mts +0 -8
- package/dist/signals/lib/lock-body-scroll.mjs +0 -17
- package/dist/signals/lib/lock-body-scroll.test.d.mts +0 -1
- package/dist/signals/lib/lock-body-scroll.test.mjs +0 -37
- package/dist/signals/lib/long-press.d.mts +0 -10
- package/dist/signals/lib/long-press.mjs +0 -29
- package/dist/signals/lib/map.d.mts +0 -18
- package/dist/signals/lib/map.mjs +0 -33
- package/dist/signals/lib/map.test.d.mts +0 -1
- package/dist/signals/lib/map.test.mjs +0 -60
- package/dist/signals/lib/motion.d.mts +0 -15
- package/dist/signals/lib/motion.mjs +0 -27
- package/dist/signals/lib/motion.test.d.mts +0 -1
- package/dist/signals/lib/motion.test.mjs +0 -51
- package/dist/signals/lib/mouse-position.d.mts +0 -14
- package/dist/signals/lib/mouse-position.mjs +0 -22
- package/dist/signals/lib/mouse-position.test.d.mts +0 -1
- package/dist/signals/lib/mouse-position.test.mjs +0 -44
- package/dist/signals/lib/mouse-wheel.d.mts +0 -10
- package/dist/signals/lib/mouse-wheel.mjs +0 -17
- package/dist/signals/lib/mouse-wheel.test.d.mts +0 -1
- package/dist/signals/lib/mouse-wheel.test.mjs +0 -38
- package/dist/signals/lib/mutation-observer.d.mts +0 -8
- package/dist/signals/lib/network-state.d.mts +0 -17
- package/dist/signals/lib/network-state.mjs +0 -34
- package/dist/signals/lib/network-state.test.d.mts +0 -1
- package/dist/signals/lib/network-state.test.mjs +0 -61
- package/dist/signals/lib/on-click-outside.mjs +0 -20
- package/dist/signals/lib/orientation.d.mts +0 -13
- package/dist/signals/lib/orientation.test.d.mts +0 -1
- package/dist/signals/lib/orientation.test.mjs +0 -43
- package/dist/signals/lib/page-leave.d.mts +0 -8
- package/dist/signals/lib/page-leave.mjs +0 -12
- package/dist/signals/lib/page-leave.test.d.mts +0 -1
- package/dist/signals/lib/page-leave.test.mjs +0 -29
- package/dist/signals/lib/permission.d.mts +0 -14
- package/dist/signals/lib/permission.mjs +0 -26
- package/dist/signals/lib/permission.test.d.mts +0 -1
- package/dist/signals/lib/permission.test.mjs +0 -50
- package/dist/signals/lib/persisted-state.d.mts +0 -11
- package/dist/signals/lib/persisted-state.mjs +0 -25
- package/dist/signals/lib/persisted-state.test.d.mts +0 -1
- package/dist/signals/lib/persisted-state.test.mjs +0 -70
- package/dist/signals/lib/pressed-keys.d.mts +0 -10
- package/dist/signals/lib/pressed-keys.mjs +0 -32
- package/dist/signals/lib/pressed-keys.test.d.mts +0 -1
- package/dist/signals/lib/pressed-keys.test.mjs +0 -54
- package/dist/signals/lib/previous-distinct.d.mts +0 -10
- package/dist/signals/lib/previous-distinct.mjs +0 -22
- package/dist/signals/lib/previous-distinct.test.d.mts +0 -1
- package/dist/signals/lib/previous-distinct.test.mjs +0 -50
- package/dist/signals/lib/previous.d.mts +0 -10
- package/dist/signals/lib/previous.mjs +0 -18
- package/dist/signals/lib/previous.test.mjs +0 -47
- package/dist/signals/lib/queue.d.mts +0 -17
- package/dist/signals/lib/queue.mjs +0 -28
- package/dist/signals/lib/queue.test.d.mts +0 -1
- package/dist/signals/lib/queue.test.mjs +0 -61
- package/dist/signals/lib/raf.d.mts +0 -17
- package/dist/signals/lib/raf.mjs +0 -38
- package/dist/signals/lib/raf.test.d.mts +0 -1
- package/dist/signals/lib/raf.test.mjs +0 -58
- package/dist/signals/lib/resize-observer.d.mts +0 -8
- package/dist/signals/lib/resize-observer.test.d.mts +0 -1
- package/dist/signals/lib/resize-observer.test.mjs +0 -44
- package/dist/signals/lib/resource.d.mts +0 -23
- package/dist/signals/lib/resource.mjs +0 -43
- package/dist/signals/lib/resource.test.d.mts +0 -1
- package/dist/signals/lib/resource.test.mjs +0 -56
- package/dist/signals/lib/scroll-state.d.mts +0 -19
- package/dist/signals/lib/scroll-state.mjs +0 -46
- package/dist/signals/lib/scroll-state.test.d.mts +0 -1
- package/dist/signals/lib/scroll-state.test.mjs +0 -94
- package/dist/signals/lib/scrolling.d.mts +0 -12
- package/dist/signals/lib/scrolling.mjs +0 -26
- package/dist/signals/lib/scrolling.test.d.mts +0 -1
- package/dist/signals/lib/scrolling.test.mjs +0 -57
- package/dist/signals/lib/search-params.d.mts +0 -16
- package/dist/signals/lib/search-params.mjs +0 -37
- package/dist/signals/lib/search-params.test.mjs +0 -56
- package/dist/signals/lib/set.d.mts +0 -18
- package/dist/signals/lib/set.mjs +0 -38
- package/dist/signals/lib/set.test.d.mts +0 -1
- package/dist/signals/lib/set.test.mjs +0 -70
- package/dist/signals/lib/start-typing.d.mts +0 -9
- package/dist/signals/lib/start-typing.mjs +0 -39
- package/dist/signals/lib/start-typing.test.d.mts +0 -1
- package/dist/signals/lib/start-typing.test.mjs +0 -64
- package/dist/signals/lib/state-history.d.mts +0 -21
- package/dist/signals/lib/state-history.mjs +0 -61
- package/dist/signals/lib/state-history.test.d.mts +0 -1
- package/dist/signals/lib/state-history.test.mjs +0 -106
- package/dist/signals/lib/state-validator.d.mts +0 -16
- package/dist/signals/lib/state-validator.mjs +0 -21
- package/dist/signals/lib/state-validator.test.d.mts +0 -1
- package/dist/signals/lib/state-validator.test.mjs +0 -41
- package/dist/signals/lib/throttled.mjs +0 -45
- package/dist/signals/lib/timeout.mjs +0 -39
- package/dist/signals/lib/toggle.d.mts +0 -12
- package/dist/signals/lib/toggle.mjs +0 -12
- package/dist/signals/lib/toggle.test.d.mts +0 -1
- package/dist/signals/lib/toggle.test.mjs +0 -43
- package/dist/signals/lib/video.d.mts +0 -21
- package/dist/signals/lib/video.test.d.mts +0 -1
- package/dist/signals/lib/video.test.mjs +0 -51
- package/dist/signals/lib/watch.d.mts +0 -16
- package/dist/signals/lib/watch.mjs +0 -31
- package/dist/signals/lib/watch.test.d.mts +0 -1
- package/dist/signals/lib/watch.test.mjs +0 -51
- package/dist/signals/lib/window-size.d.mts +0 -14
- package/dist/signals/lib/window-size.mjs +0 -21
- package/dist/signals/lib/window-size.test.mjs +0 -50
- /package/dist/{signals/lib → utilities}/active-element.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/debounced.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/element-rect.test.d.mts +0 -0
- /package/dist/{signals/lib/animation-frames.test.d.mts → utilities/element-scroll.test.d.mts} +0 -0
- /package/dist/{signals/lib → utilities}/event-listener.test.d.mts +0 -0
- /package/dist/{signals/lib/async-retry.test.d.mts → utilities/focus-within.test.d.mts} +0 -0
- /package/dist/{signals/lib → utilities}/hover.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/intersection-observer.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/interval.test.d.mts +0 -0
- /package/dist/{signals/lib/audio.test.d.mts → utilities/location.test.d.mts} +0 -0
- /package/dist/{signals/lib → utilities}/long-press.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/media-devices.test.d.mts +0 -0
- /package/dist/{signals/lib/battery.test.d.mts → utilities/media-player.test.d.mts} +0 -0
- /package/dist/{signals/lib → utilities}/mutation-observer.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/on-click-outside.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/previous.test.d.mts +0 -0
- /package/dist/{signals/lib/before-unload.test.d.mts → utilities/routing.test.d.mts} +0 -0
- /package/dist/{signals/lib → utilities}/search-params.test.d.mts +0 -0
- /package/dist/{signals/lib/clipboard.test.d.mts → utilities/storage.test.d.mts} +0 -0
- /package/dist/{signals/lib → utilities}/throttled.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/timeout.test.d.mts +0 -0
- /package/dist/{signals/lib → utilities}/window-size.test.d.mts +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { i as beforeAll, n as vi, o as describe, r as afterEach, s as it, t as globalExpect } from "../test.BmQO5GaM-ANkhHvbr.mjs";
|
|
2
|
+
import { isLocalNavigationEvent, match, matches, navigate, patchHistory } from "./routing.mjs";
|
|
3
|
+
//#region src/utilities/routing.test.ts
|
|
4
|
+
beforeAll(() => {
|
|
5
|
+
patchHistory();
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
history.replaceState(null, "", "/");
|
|
9
|
+
});
|
|
10
|
+
describe("navigate", () => {
|
|
11
|
+
it("pushes a new history entry", () => {
|
|
12
|
+
navigate("/about");
|
|
13
|
+
globalExpect(location.pathname).toBe("/about");
|
|
14
|
+
});
|
|
15
|
+
it("replaces the current entry when replace is true", () => {
|
|
16
|
+
const before = history.length;
|
|
17
|
+
navigate("/replaced", { replace: true });
|
|
18
|
+
globalExpect(location.pathname).toBe("/replaced");
|
|
19
|
+
globalExpect(history.length).toBe(before);
|
|
20
|
+
});
|
|
21
|
+
it("dispatches pushstate event so currentLocation updates", () => {
|
|
22
|
+
const handler = vi.fn();
|
|
23
|
+
window.addEventListener("pushstate", handler);
|
|
24
|
+
navigate("/dispatched");
|
|
25
|
+
window.removeEventListener("pushstate", handler);
|
|
26
|
+
globalExpect(handler).toHaveBeenCalledOnce();
|
|
27
|
+
});
|
|
28
|
+
it("dispatches replacestate event on replace", () => {
|
|
29
|
+
const handler = vi.fn();
|
|
30
|
+
window.addEventListener("replacestate", handler);
|
|
31
|
+
navigate("/dispatched", { replace: true });
|
|
32
|
+
window.removeEventListener("replacestate", handler);
|
|
33
|
+
globalExpect(handler).toHaveBeenCalledOnce();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe("isLocalNavigationEvent", () => {
|
|
37
|
+
function makeClick(el, init = {}) {
|
|
38
|
+
const e = new MouseEvent("click", {
|
|
39
|
+
bubbles: true,
|
|
40
|
+
cancelable: true,
|
|
41
|
+
...init
|
|
42
|
+
});
|
|
43
|
+
Object.defineProperty(e, "currentTarget", {
|
|
44
|
+
value: el,
|
|
45
|
+
configurable: true
|
|
46
|
+
});
|
|
47
|
+
return e;
|
|
48
|
+
}
|
|
49
|
+
it("returns true for a same-origin link", () => {
|
|
50
|
+
const el = document.createElement("a");
|
|
51
|
+
el.href = "/linked";
|
|
52
|
+
globalExpect(isLocalNavigationEvent(makeClick(el))).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
it("returns false for an external link", () => {
|
|
55
|
+
const el = document.createElement("a");
|
|
56
|
+
el.href = "https://example.com/page";
|
|
57
|
+
globalExpect(isLocalNavigationEvent(makeClick(el))).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
it("returns false when metaKey is held", () => {
|
|
60
|
+
const el = document.createElement("a");
|
|
61
|
+
el.href = "/about";
|
|
62
|
+
globalExpect(isLocalNavigationEvent(makeClick(el, { metaKey: true }))).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
it("returns false when ctrlKey is held", () => {
|
|
65
|
+
const el = document.createElement("a");
|
|
66
|
+
el.href = "/about";
|
|
67
|
+
globalExpect(isLocalNavigationEvent(makeClick(el, { ctrlKey: true }))).toBe(false);
|
|
68
|
+
});
|
|
69
|
+
it("returns false for download links", () => {
|
|
70
|
+
const el = document.createElement("a");
|
|
71
|
+
el.href = "/file.pdf";
|
|
72
|
+
el.setAttribute("download", "");
|
|
73
|
+
globalExpect(isLocalNavigationEvent(makeClick(el))).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
it("returns false for _blank links", () => {
|
|
76
|
+
const el = document.createElement("a");
|
|
77
|
+
el.href = "/page";
|
|
78
|
+
el.setAttribute("target", "_blank");
|
|
79
|
+
globalExpect(isLocalNavigationEvent(makeClick(el))).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
it("returns false for non-primary button clicks", () => {
|
|
82
|
+
const el = document.createElement("a");
|
|
83
|
+
el.href = "/page";
|
|
84
|
+
globalExpect(isLocalNavigationEvent(makeClick(el, { button: 1 }))).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe("matches", () => {
|
|
88
|
+
it("returns true when current URL matches", () => {
|
|
89
|
+
navigate("/users/42");
|
|
90
|
+
globalExpect(matches({ pathname: "/users/:id" })()).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
it("returns false when current URL does not match", () => {
|
|
93
|
+
navigate("/other");
|
|
94
|
+
globalExpect(matches({ pathname: "/users/:id" })()).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
it("updates reactively on navigation", () => {
|
|
97
|
+
const result = matches({ pathname: "/home" });
|
|
98
|
+
navigate("/other");
|
|
99
|
+
globalExpect(result()).toBe(false);
|
|
100
|
+
navigate("/home");
|
|
101
|
+
globalExpect(result()).toBe(true);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
describe("match", () => {
|
|
105
|
+
it("returns null when current URL does not match", () => {
|
|
106
|
+
navigate("/other");
|
|
107
|
+
globalExpect(match({ pathname: "/users/:id" })()).toBeNull();
|
|
108
|
+
});
|
|
109
|
+
it("returns URLPatternResult with groups when matched", () => {
|
|
110
|
+
navigate("/users/42");
|
|
111
|
+
globalExpect(match({ pathname: "/users/:id" })()?.pathname.groups.id).toBe("42");
|
|
112
|
+
});
|
|
113
|
+
it("updates reactively on navigation", () => {
|
|
114
|
+
const result = match({ pathname: "/posts/:slug" });
|
|
115
|
+
navigate("/posts/hello");
|
|
116
|
+
globalExpect(result()?.pathname.groups.slug).toBe("hello");
|
|
117
|
+
navigate("/other");
|
|
118
|
+
globalExpect(result()).toBeNull();
|
|
119
|
+
});
|
|
120
|
+
it("extracts multiple params", () => {
|
|
121
|
+
navigate("/posts/2024/my-slug");
|
|
122
|
+
const result = match({ pathname: "/posts/:year/:slug" });
|
|
123
|
+
globalExpect(result()?.pathname.groups.year).toBe("2024");
|
|
124
|
+
globalExpect(result()?.pathname.groups.slug).toBe("my-slug");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
//#endregion
|
|
128
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { t as Computed } from "../index-Cvdhuy6Y.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utilities/search-params.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns a read-only `Computed<string | null>` bound to a single URL search
|
|
6
|
+
* parameter.
|
|
7
|
+
*
|
|
8
|
+
* Returns the raw string value, or `null` when absent.
|
|
9
|
+
* Reacts to `popstate` so back/forward navigation is reflected.
|
|
10
|
+
*/
|
|
11
|
+
declare function createSearchParam(key: string): Computed<string | null>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { createSearchParam };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { fromEvent, sync } from "./event-driven.mjs";
|
|
2
|
+
//#region src/utilities/search-params.ts
|
|
3
|
+
/**
|
|
4
|
+
* Returns a read-only `Computed<string | null>` bound to a single URL search
|
|
5
|
+
* parameter.
|
|
6
|
+
*
|
|
7
|
+
* Returns the raw string value, or `null` when absent.
|
|
8
|
+
* Reacts to `popstate` so back/forward navigation is reflected.
|
|
9
|
+
*/
|
|
10
|
+
function createSearchParam(key) {
|
|
11
|
+
const read = () => {
|
|
12
|
+
if (typeof location === "undefined") return null;
|
|
13
|
+
return new URLSearchParams(location.search).get(key);
|
|
14
|
+
};
|
|
15
|
+
const [s] = sync(fromEvent(window, [
|
|
16
|
+
"popstate",
|
|
17
|
+
"pushstate",
|
|
18
|
+
"replacestate"
|
|
19
|
+
]), read);
|
|
20
|
+
return s;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { createSearchParam };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { s as effectScope } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
import { o as describe, r as afterEach, s as it, t as globalExpect } from "../test.BmQO5GaM-ANkhHvbr.mjs";
|
|
3
|
+
import { createSearchParam } from "./search-params.mjs";
|
|
4
|
+
//#region src/utilities/search-params.test.ts
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
history.replaceState(null, "", location.pathname);
|
|
7
|
+
});
|
|
8
|
+
describe("createSearchParam", () => {
|
|
9
|
+
it("returns null when param is absent", () => {
|
|
10
|
+
let s;
|
|
11
|
+
effectScope(() => {
|
|
12
|
+
s = createSearchParam("q");
|
|
13
|
+
});
|
|
14
|
+
globalExpect(s()).toBeNull();
|
|
15
|
+
});
|
|
16
|
+
it("reads an existing param from the URL", () => {
|
|
17
|
+
history.replaceState(null, "", "?q=hello");
|
|
18
|
+
let s;
|
|
19
|
+
effectScope(() => {
|
|
20
|
+
s = createSearchParam("q");
|
|
21
|
+
});
|
|
22
|
+
globalExpect(s()).toBe("hello");
|
|
23
|
+
});
|
|
24
|
+
it("reacts to popstate events", () => {
|
|
25
|
+
let s;
|
|
26
|
+
effectScope(() => {
|
|
27
|
+
s = createSearchParam("q");
|
|
28
|
+
});
|
|
29
|
+
history.replaceState(null, "", "?q=changed");
|
|
30
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
31
|
+
globalExpect(s()).toBe("changed");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//#endregion
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { r as Signal } from "../index-Cvdhuy6Y.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utilities/storage.d.ts
|
|
4
|
+
type StorageOptions<T> = {
|
|
5
|
+
/** Custom serialiser (default `JSON.stringify`). */serialise?: (value: T) => string; /** Custom deserialiser (default `JSON.parse`). */
|
|
6
|
+
deserialise?: (raw: string) => T;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Returns a `Signal` persisted to `localStorage`.
|
|
10
|
+
*
|
|
11
|
+
* Changes made in other tabs/windows are synchronised automatically via
|
|
12
|
+
* the `StorageEvent`.
|
|
13
|
+
*/
|
|
14
|
+
declare function createLocalStorage<T>(key: string, initialValue: T, options?: StorageOptions<T>): Signal<T>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a `Signal` persisted to `sessionStorage`.
|
|
17
|
+
*
|
|
18
|
+
* Session storage is scoped to the current tab — no cross-tab sync.
|
|
19
|
+
*/
|
|
20
|
+
declare function createSessionStorage<T>(key: string, initialValue: T, options?: StorageOptions<T>): Signal<T>;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { createLocalStorage, createSessionStorage };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { sync } from "./event-driven.mjs";
|
|
2
|
+
//#region src/utilities/storage.ts
|
|
3
|
+
function readOrDefault(storage, key, initialValue, deserialise) {
|
|
4
|
+
try {
|
|
5
|
+
const item = storage.getItem(key);
|
|
6
|
+
if (item !== null) return deserialise(item);
|
|
7
|
+
} catch {}
|
|
8
|
+
return initialValue;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Returns a `Signal` persisted to `localStorage`.
|
|
12
|
+
*
|
|
13
|
+
* Changes made in other tabs/windows are synchronised automatically via
|
|
14
|
+
* the `StorageEvent`.
|
|
15
|
+
*/
|
|
16
|
+
function createLocalStorage(key, initialValue, options) {
|
|
17
|
+
const serialise = options?.serialise ?? ((v) => JSON.stringify(v));
|
|
18
|
+
const deserialise = options?.deserialise ?? ((raw) => JSON.parse(raw));
|
|
19
|
+
const storage = localStorage;
|
|
20
|
+
let notify;
|
|
21
|
+
const subscribe = (cb) => {
|
|
22
|
+
notify = cb;
|
|
23
|
+
const handler = (e) => {
|
|
24
|
+
if (e.key === key && e.storageArea === storage) cb();
|
|
25
|
+
};
|
|
26
|
+
window.addEventListener("storage", handler);
|
|
27
|
+
return () => {
|
|
28
|
+
window.removeEventListener("storage", handler);
|
|
29
|
+
notify = void 0;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
const [s] = sync(subscribe, () => readOrDefault(storage, key, initialValue, deserialise), (v) => {
|
|
33
|
+
try {
|
|
34
|
+
storage.setItem(key, serialise(v));
|
|
35
|
+
} catch {}
|
|
36
|
+
notify?.();
|
|
37
|
+
});
|
|
38
|
+
return s;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns a `Signal` persisted to `sessionStorage`.
|
|
42
|
+
*
|
|
43
|
+
* Session storage is scoped to the current tab — no cross-tab sync.
|
|
44
|
+
*/
|
|
45
|
+
function createSessionStorage(key, initialValue, options) {
|
|
46
|
+
const serialise = options?.serialise ?? ((v) => JSON.stringify(v));
|
|
47
|
+
const deserialise = options?.deserialise ?? ((raw) => JSON.parse(raw));
|
|
48
|
+
const storage = sessionStorage;
|
|
49
|
+
let notify;
|
|
50
|
+
const subscribe = (cb) => {
|
|
51
|
+
notify = cb;
|
|
52
|
+
return () => {
|
|
53
|
+
notify = void 0;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
const [s] = sync(subscribe, () => readOrDefault(storage, key, initialValue, deserialise), (v) => {
|
|
57
|
+
try {
|
|
58
|
+
storage.setItem(key, serialise(v));
|
|
59
|
+
} catch {}
|
|
60
|
+
notify?.();
|
|
61
|
+
});
|
|
62
|
+
return s;
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { createLocalStorage, createSessionStorage };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { s as effectScope } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
import { o as describe, r as afterEach, s as it, t as globalExpect } from "../test.BmQO5GaM-ANkhHvbr.mjs";
|
|
3
|
+
import { createLocalStorage, createSessionStorage } from "./storage.mjs";
|
|
4
|
+
//#region src/utilities/storage.test.ts
|
|
5
|
+
describe("createLocalStorage", () => {
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
localStorage.clear();
|
|
8
|
+
});
|
|
9
|
+
it("uses initialValue when storage is empty", () => {
|
|
10
|
+
let s;
|
|
11
|
+
effectScope(() => {
|
|
12
|
+
s = createLocalStorage("count", 0);
|
|
13
|
+
});
|
|
14
|
+
globalExpect(s()).toBe(0);
|
|
15
|
+
});
|
|
16
|
+
it("reads an existing value from localStorage", () => {
|
|
17
|
+
localStorage.setItem("count", "42");
|
|
18
|
+
let s;
|
|
19
|
+
effectScope(() => {
|
|
20
|
+
s = createLocalStorage("count", 0);
|
|
21
|
+
});
|
|
22
|
+
globalExpect(s()).toBe(42);
|
|
23
|
+
});
|
|
24
|
+
it("persists writes to localStorage", () => {
|
|
25
|
+
let s;
|
|
26
|
+
effectScope(() => {
|
|
27
|
+
s = createLocalStorage("key", "a");
|
|
28
|
+
});
|
|
29
|
+
s("b");
|
|
30
|
+
globalExpect(JSON.parse(localStorage.getItem("key"))).toBe("b");
|
|
31
|
+
});
|
|
32
|
+
it("persists complex values as JSON", () => {
|
|
33
|
+
let s;
|
|
34
|
+
effectScope(() => {
|
|
35
|
+
s = createLocalStorage("obj", { x: 1 });
|
|
36
|
+
});
|
|
37
|
+
s({ x: 99 });
|
|
38
|
+
globalExpect(JSON.parse(localStorage.getItem("obj"))).toEqual({ x: 99 });
|
|
39
|
+
});
|
|
40
|
+
it("falls back to initialValue on invalid JSON", () => {
|
|
41
|
+
localStorage.setItem("broken", "{not json}");
|
|
42
|
+
let s;
|
|
43
|
+
effectScope(() => {
|
|
44
|
+
s = createLocalStorage("broken", 7);
|
|
45
|
+
});
|
|
46
|
+
globalExpect(s()).toBe(7);
|
|
47
|
+
});
|
|
48
|
+
it("supports custom serialise / deserialise", () => {
|
|
49
|
+
let s;
|
|
50
|
+
effectScope(() => {
|
|
51
|
+
s = createLocalStorage("date", /* @__PURE__ */ new Date("2024-01-01"), {
|
|
52
|
+
serialise: (d) => d.toISOString(),
|
|
53
|
+
deserialise: (raw) => new Date(raw)
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
const d = /* @__PURE__ */ new Date("2025-06-15");
|
|
57
|
+
s(d);
|
|
58
|
+
globalExpect(localStorage.getItem("date")).toBe(d.toISOString());
|
|
59
|
+
});
|
|
60
|
+
it("reacts to storage events from other tabs", () => {
|
|
61
|
+
let s;
|
|
62
|
+
effectScope(() => {
|
|
63
|
+
s = createLocalStorage("sync-key", "init");
|
|
64
|
+
});
|
|
65
|
+
localStorage.setItem("sync-key", JSON.stringify("from-other-tab"));
|
|
66
|
+
window.dispatchEvent(new StorageEvent("storage", {
|
|
67
|
+
key: "sync-key",
|
|
68
|
+
newValue: JSON.stringify("from-other-tab"),
|
|
69
|
+
storageArea: localStorage
|
|
70
|
+
}));
|
|
71
|
+
globalExpect(s()).toBe("from-other-tab");
|
|
72
|
+
});
|
|
73
|
+
it("ignores storage events for different keys", () => {
|
|
74
|
+
let s;
|
|
75
|
+
effectScope(() => {
|
|
76
|
+
s = createLocalStorage("my-key", "init");
|
|
77
|
+
});
|
|
78
|
+
window.dispatchEvent(new StorageEvent("storage", {
|
|
79
|
+
key: "other-key",
|
|
80
|
+
newValue: JSON.stringify("nope"),
|
|
81
|
+
storageArea: localStorage
|
|
82
|
+
}));
|
|
83
|
+
globalExpect(s()).toBe("init");
|
|
84
|
+
});
|
|
85
|
+
it("resets to initialValue when key is removed", () => {
|
|
86
|
+
let s;
|
|
87
|
+
effectScope(() => {
|
|
88
|
+
s = createLocalStorage("rm-key", "default");
|
|
89
|
+
});
|
|
90
|
+
s("changed");
|
|
91
|
+
localStorage.removeItem("rm-key");
|
|
92
|
+
window.dispatchEvent(new StorageEvent("storage", {
|
|
93
|
+
key: "rm-key",
|
|
94
|
+
newValue: null,
|
|
95
|
+
storageArea: localStorage
|
|
96
|
+
}));
|
|
97
|
+
globalExpect(s()).toBe("default");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe("createSessionStorage", () => {
|
|
101
|
+
afterEach(() => {
|
|
102
|
+
sessionStorage.clear();
|
|
103
|
+
});
|
|
104
|
+
it("uses initialValue when storage is empty", () => {
|
|
105
|
+
let s;
|
|
106
|
+
effectScope(() => {
|
|
107
|
+
s = createSessionStorage("count", 0);
|
|
108
|
+
});
|
|
109
|
+
globalExpect(s()).toBe(0);
|
|
110
|
+
});
|
|
111
|
+
it("reads an existing value from sessionStorage", () => {
|
|
112
|
+
sessionStorage.setItem("count", "42");
|
|
113
|
+
let s;
|
|
114
|
+
effectScope(() => {
|
|
115
|
+
s = createSessionStorage("count", 0);
|
|
116
|
+
});
|
|
117
|
+
globalExpect(s()).toBe(42);
|
|
118
|
+
});
|
|
119
|
+
it("persists writes to sessionStorage", () => {
|
|
120
|
+
let s;
|
|
121
|
+
effectScope(() => {
|
|
122
|
+
s = createSessionStorage("key", "a");
|
|
123
|
+
});
|
|
124
|
+
s("b");
|
|
125
|
+
globalExpect(JSON.parse(sessionStorage.getItem("key"))).toBe("b");
|
|
126
|
+
});
|
|
127
|
+
it("falls back to initialValue on invalid JSON", () => {
|
|
128
|
+
sessionStorage.setItem("broken", "{not json}");
|
|
129
|
+
let s;
|
|
130
|
+
effectScope(() => {
|
|
131
|
+
s = createSessionStorage("broken", 7);
|
|
132
|
+
});
|
|
133
|
+
globalExpect(s()).toBe(7);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
//#endregion
|
|
137
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as Computed } from "
|
|
1
|
+
import { t as Computed } from "../index-Cvdhuy6Y.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/utilities/throttled.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Returns a `Computed` that mirrors `getter` but updates at most once per
|
|
6
6
|
* `interval` milliseconds. A trailing-edge update is scheduled so the final
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { o as effect, p as signal } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
import { createTimeout } from "./timeout.mjs";
|
|
3
|
+
//#region src/utilities/throttled.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns a `Computed` that mirrors `getter` but updates at most once per
|
|
6
|
+
* `interval` milliseconds. A trailing-edge update is scheduled so the final
|
|
7
|
+
* value is never lost.
|
|
8
|
+
*
|
|
9
|
+
* The initial value is read synchronously.
|
|
10
|
+
*/
|
|
11
|
+
function createThrottled(getter, interval) {
|
|
12
|
+
const s = signal(getter());
|
|
13
|
+
let lastRun = -Infinity;
|
|
14
|
+
let firstRun = true;
|
|
15
|
+
let latest;
|
|
16
|
+
const { stop, reset } = createTimeout(() => {
|
|
17
|
+
lastRun = Date.now();
|
|
18
|
+
s(latest);
|
|
19
|
+
}, () => interval - (Date.now() - lastRun), false);
|
|
20
|
+
effect(() => {
|
|
21
|
+
latest = getter();
|
|
22
|
+
if (firstRun) {
|
|
23
|
+
firstRun = false;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const elapsed = Date.now() - lastRun;
|
|
27
|
+
stop();
|
|
28
|
+
if (elapsed >= interval) {
|
|
29
|
+
lastRun = Date.now();
|
|
30
|
+
s(latest);
|
|
31
|
+
} else reset();
|
|
32
|
+
});
|
|
33
|
+
return s;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { createThrottled };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
1
|
+
import { p as signal, s as effectScope } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
import { a as beforeEach, n as vi, o as describe, r as afterEach, s as it, t as globalExpect } from "../test.BmQO5GaM-ANkhHvbr.mjs";
|
|
3
3
|
import { createThrottled } from "./throttled.mjs";
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/utilities/throttled.test.ts
|
|
5
5
|
beforeEach(() => {
|
|
6
6
|
vi.useFakeTimers();
|
|
7
7
|
});
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { t as Computed } from "
|
|
1
|
+
import { t as Computed } from "../index-Cvdhuy6Y.mjs";
|
|
2
2
|
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/utilities/timeout.d.ts
|
|
4
4
|
type TimeoutResult = {
|
|
5
|
-
|
|
5
|
+
isRunning: Computed<boolean>;
|
|
6
6
|
start(): void;
|
|
7
7
|
stop(): void;
|
|
8
8
|
reset(): void;
|
|
9
9
|
} & Disposable;
|
|
10
10
|
/**
|
|
11
11
|
* Reactive `setTimeout` wrapper with pause/resume/reset control.
|
|
12
|
-
* The callback fires once after `delay` ms. Starts running immediately
|
|
12
|
+
* The callback fires once after `delay` ms. Starts running immediately
|
|
13
|
+
* unless `immediate` is set to `false`.
|
|
13
14
|
*/
|
|
14
|
-
declare function createTimeout(callback: () => void, delay: number): TimeoutResult;
|
|
15
|
+
declare function createTimeout(callback: () => void, delay: number | (() => number), immediate?: boolean): TimeoutResult;
|
|
15
16
|
//#endregion
|
|
16
17
|
export { createTimeout };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { f as onCleanup, p as signal } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
//#region src/utilities/timeout.ts
|
|
3
|
+
/**
|
|
4
|
+
* Reactive `setTimeout` wrapper with pause/resume/reset control.
|
|
5
|
+
* The callback fires once after `delay` ms. Starts running immediately
|
|
6
|
+
* unless `immediate` is set to `false`.
|
|
7
|
+
*/
|
|
8
|
+
function createTimeout(callback, delay, immediate = true) {
|
|
9
|
+
const isRunning = signal(false);
|
|
10
|
+
let id;
|
|
11
|
+
const getDelay = typeof delay === "function" ? delay : () => delay;
|
|
12
|
+
const stop = () => {
|
|
13
|
+
clearTimeout(id);
|
|
14
|
+
id = void 0;
|
|
15
|
+
isRunning(false);
|
|
16
|
+
};
|
|
17
|
+
const start = () => {
|
|
18
|
+
if (isRunning()) return;
|
|
19
|
+
isRunning(true);
|
|
20
|
+
id = setTimeout(() => {
|
|
21
|
+
isRunning(false);
|
|
22
|
+
id = void 0;
|
|
23
|
+
callback();
|
|
24
|
+
}, getDelay());
|
|
25
|
+
};
|
|
26
|
+
const reset = () => {
|
|
27
|
+
stop();
|
|
28
|
+
start();
|
|
29
|
+
};
|
|
30
|
+
if (immediate) start();
|
|
31
|
+
const cleanup = () => stop();
|
|
32
|
+
onCleanup(cleanup);
|
|
33
|
+
return {
|
|
34
|
+
isRunning,
|
|
35
|
+
start,
|
|
36
|
+
stop,
|
|
37
|
+
reset,
|
|
38
|
+
[Symbol.dispose]: cleanup
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { createTimeout };
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { s as effectScope } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
import { n as vi, o as describe, r as afterEach, s as it, t as globalExpect } from "../test.BmQO5GaM-ANkhHvbr.mjs";
|
|
3
3
|
import { createTimeout } from "./timeout.mjs";
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/utilities/timeout.test.ts
|
|
5
5
|
afterEach(() => {
|
|
6
6
|
document.body.innerHTML = "";
|
|
7
7
|
vi.useRealTimers();
|
|
8
8
|
});
|
|
9
9
|
describe("createTimeout", () => {
|
|
10
|
-
it("starts as
|
|
10
|
+
it("starts as running", () => {
|
|
11
11
|
vi.useFakeTimers();
|
|
12
12
|
let t;
|
|
13
13
|
const cb = vi.fn();
|
|
14
14
|
effectScope(() => {
|
|
15
15
|
t = createTimeout(cb, 500);
|
|
16
16
|
});
|
|
17
|
-
globalExpect(t.
|
|
17
|
+
globalExpect(t.isRunning()).toBe(true);
|
|
18
18
|
});
|
|
19
19
|
it("fires callback after delay", () => {
|
|
20
20
|
vi.useFakeTimers();
|
|
@@ -25,14 +25,14 @@ describe("createTimeout", () => {
|
|
|
25
25
|
vi.advanceTimersByTime(600);
|
|
26
26
|
globalExpect(cb).toHaveBeenCalledOnce();
|
|
27
27
|
});
|
|
28
|
-
it("
|
|
28
|
+
it("isRunning becomes false after firing", () => {
|
|
29
29
|
vi.useFakeTimers();
|
|
30
30
|
let t;
|
|
31
31
|
effectScope(() => {
|
|
32
32
|
t = createTimeout(vi.fn(), 200);
|
|
33
33
|
});
|
|
34
34
|
vi.advanceTimersByTime(300);
|
|
35
|
-
globalExpect(t.
|
|
35
|
+
globalExpect(t.isRunning()).toBe(false);
|
|
36
36
|
});
|
|
37
37
|
it("stop() cancels the timeout", () => {
|
|
38
38
|
vi.useFakeTimers();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { t as Computed } from "../index-Cvdhuy6Y.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/utilities/window-size.d.ts
|
|
4
|
+
type WindowSizeResult = {
|
|
5
|
+
width: Computed<number>;
|
|
6
|
+
height: Computed<number>;
|
|
7
|
+
} & Disposable;
|
|
8
|
+
declare const windowSize: WindowSizeResult;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { windowSize };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { a as computed } from "../signals-DcgXhkU2.mjs";
|
|
2
|
+
import { fromEvent, sync } from "./event-driven.mjs";
|
|
3
|
+
//#region src/utilities/window-size.ts
|
|
4
|
+
/**
|
|
5
|
+
* Returns reactive `width` and `height` signals tracking the browser window
|
|
6
|
+
* inner dimensions.
|
|
7
|
+
*/
|
|
8
|
+
function createWindowSize() {
|
|
9
|
+
const isBrowser = typeof window !== "undefined";
|
|
10
|
+
const [size, stop] = sync(fromEvent(window, "resize"), () => ({
|
|
11
|
+
w: isBrowser ? window.innerWidth : 0,
|
|
12
|
+
h: isBrowser ? window.innerHeight : 0
|
|
13
|
+
}));
|
|
14
|
+
return {
|
|
15
|
+
width: computed(() => size().w),
|
|
16
|
+
height: computed(() => size().h),
|
|
17
|
+
[Symbol.dispose]: stop
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const windowSize = createWindowSize();
|
|
21
|
+
//#endregion
|
|
22
|
+
export { windowSize };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { o as describe, s as it, t as globalExpect } from "../test.BmQO5GaM-ANkhHvbr.mjs";
|
|
2
|
+
import { windowSize } from "./window-size.mjs";
|
|
3
|
+
//#region src/utilities/window-size.test.ts
|
|
4
|
+
describe("windowSize (singleton)", () => {
|
|
5
|
+
it("starts with current window dimensions", () => {
|
|
6
|
+
globalExpect(windowSize.width()).toBe(window.innerWidth);
|
|
7
|
+
globalExpect(windowSize.height()).toBe(window.innerHeight);
|
|
8
|
+
});
|
|
9
|
+
it("updates on resize event", () => {
|
|
10
|
+
const origWidth = window.innerWidth;
|
|
11
|
+
const origHeight = window.innerHeight;
|
|
12
|
+
Object.defineProperty(window, "innerWidth", {
|
|
13
|
+
value: 1234,
|
|
14
|
+
configurable: true
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(window, "innerHeight", {
|
|
17
|
+
value: 5678,
|
|
18
|
+
configurable: true
|
|
19
|
+
});
|
|
20
|
+
window.dispatchEvent(new Event("resize"));
|
|
21
|
+
globalExpect(windowSize.width()).toBe(1234);
|
|
22
|
+
globalExpect(windowSize.height()).toBe(5678);
|
|
23
|
+
Object.defineProperty(window, "innerWidth", {
|
|
24
|
+
value: origWidth,
|
|
25
|
+
configurable: true
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(window, "innerHeight", {
|
|
28
|
+
value: origHeight,
|
|
29
|
+
configurable: true
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
it("remains reactive after Symbol.dispose", () => {
|
|
33
|
+
Object.defineProperty(window, "innerWidth", {
|
|
34
|
+
value: 42,
|
|
35
|
+
configurable: true
|
|
36
|
+
});
|
|
37
|
+
window.dispatchEvent(new Event("resize"));
|
|
38
|
+
globalExpect(windowSize.width()).toBe(42);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
//#endregion
|
|
42
|
+
export {};
|