-
Notifications
You must be signed in to change notification settings - Fork 177
Expand file tree
/
Copy pathcreateRouter.ts
More file actions
62 lines (56 loc) · 1.85 KB
/
createRouter.ts
File metadata and controls
62 lines (56 loc) · 1.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import { type Signal, createSignal, onCleanup, sharedConfig } from "solid-js";
import type { LocationChange, RouterContext, RouterUtils } from "../types.js";
import { createRouterComponent } from "./components.jsx";
function intercept<T>(
[value, setValue]: [() => T, (v: T) => void],
get?: (v: T) => T,
set?: (v: T) => T
): [() => T, (v: T) => void] {
return [get ? () => get(value()) : value, set ? (v: T) => setValue(set(v)) : setValue];
}
export function createRouter(config: {
get: () => string | LocationChange,
set: (next: LocationChange) => void,
init?: (notify: (value?: string | LocationChange) => void) => () => void,
create?: (router: RouterContext) => void,
utils?: Partial<RouterUtils>
}) {
let ignore = false;
const wrap = (value: string | LocationChange) => (typeof value === "string" ? { value } : value);
const signal = intercept<LocationChange>(
createSignal(wrap(config.get()), {
equals: (a, b) => a.value === b.value && a.state === b.state
}),
undefined,
next => {
!ignore && config.set(next);
if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = true;
return next;
}
) as Signal<LocationChange>;
config.init &&
onCleanup(
config.init((value = config.get()) => {
ignore = true;
signal[1](wrap(value));
ignore = false;
})
);
return createRouterComponent({
signal,
create: config.create,
utils: config.utils
});
}
export function bindEvent(target: EventTarget, type: string, handler: EventListener) {
target.addEventListener(type, handler);
return () => target.removeEventListener(type, handler);
}
export function scrollToHash(hash: string, fallbackTop?: boolean) {
const el = hash && document.getElementById(hash);
if (el) {
el.scrollIntoView();
} else if (fallbackTop) {
window.scrollTo(0, 0);
}
}