@solidjs/router 0.10.0-beta.4 → 0.10.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.jsx CHANGED
@@ -1,5 +1,5 @@
1
+ export * from "./routers";
1
2
  export * from "./components";
2
- export * from "./integration";
3
3
  export * from "./lifecycle";
4
4
  export { useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useSearchParams, useBeforeLeave, } from "./routing";
5
5
  export { mergeSearchString as _mergeSearchString } from "./utils";
@@ -0,0 +1,5 @@
1
+ import type { JSX } from "solid-js";
2
+ import type { BaseRouterProps } from "./components";
3
+ export declare function hashParser(str: string): string;
4
+ export type HashRouterProps = BaseRouterProps;
5
+ export declare function HashRouter(props: HashRouterProps): JSX.Element;
@@ -0,0 +1,36 @@
1
+ import { setupNativeEvents } from "../data/events";
2
+ import { createRouter, scrollToHash, bindEvent } from "./createRouter";
3
+ export function hashParser(str) {
4
+ const to = str.replace(/^.*?#/, "");
5
+ // Hash-only hrefs like `#foo` from plain anchors will come in as `/#foo` whereas a link to
6
+ // `/foo` will be `/#/foo`. Check if the to starts with a `/` and if not append it as a hash
7
+ // to the current path so we can handle these in-page anchors correctly.
8
+ if (!to.startsWith("/")) {
9
+ const [, path = "/"] = window.location.hash.split("#", 2);
10
+ return `${path}#${to}`;
11
+ }
12
+ return to;
13
+ }
14
+ export function HashRouter(props) {
15
+ return createRouter({
16
+ get: () => window.location.hash.slice(1),
17
+ set({ value, replace, scroll, state }) {
18
+ if (replace) {
19
+ window.history.replaceState(state, "", "#" + value);
20
+ }
21
+ else {
22
+ window.location.hash = value;
23
+ }
24
+ const hashIndex = value.indexOf("#");
25
+ const hash = hashIndex >= 0 ? value.slice(hashIndex + 1) : "";
26
+ scrollToHash(hash, scroll);
27
+ },
28
+ init: notify => bindEvent(window, "hashchange", () => notify()),
29
+ create: setupNativeEvents,
30
+ utils: {
31
+ go: delta => window.history.go(delta),
32
+ renderPath: path => `#${path}`,
33
+ parsePath: hashParser
34
+ }
35
+ })(props);
36
+ }
@@ -0,0 +1,21 @@
1
+ import type { LocationChange } from "../types";
2
+ import type { BaseRouterProps } from "./components";
3
+ import type { JSX } from "solid-js";
4
+ export type MemoryHistory = {
5
+ get: () => string;
6
+ set: (change: LocationChange) => void;
7
+ go: (delta: number) => void;
8
+ listen: (listener: (value: string) => void) => () => void;
9
+ };
10
+ export declare function createMemoryHistory(): {
11
+ get: () => string;
12
+ set: ({ value, scroll, replace }: LocationChange) => void;
13
+ back: () => void;
14
+ forward: () => void;
15
+ go: (n: number) => void;
16
+ listen: (listener: (value: string) => void) => () => void;
17
+ };
18
+ export type MemoryRouterProps = BaseRouterProps & {
19
+ history?: MemoryHistory;
20
+ };
21
+ export declare function MemoryRouter(props: MemoryRouterProps): JSX.Element;
@@ -0,0 +1,52 @@
1
+ import { createRouter, scrollToHash } from "./createRouter";
2
+ export function createMemoryHistory() {
3
+ const entries = ["/"];
4
+ let index = 0;
5
+ const listeners = [];
6
+ const go = (n) => {
7
+ // https://github.com/remix-run/react-router/blob/682810ca929d0e3c64a76f8d6e465196b7a2ac58/packages/router/history.ts#L245
8
+ index = Math.max(0, Math.min(index + n, entries.length - 1));
9
+ const value = entries[index];
10
+ listeners.forEach(listener => listener(value));
11
+ };
12
+ return {
13
+ get: () => entries[index],
14
+ set: ({ value, scroll, replace }) => {
15
+ if (replace) {
16
+ entries[index] = value;
17
+ }
18
+ else {
19
+ entries.splice(index + 1, entries.length - index, value);
20
+ index++;
21
+ }
22
+ if (scroll) {
23
+ scrollToHash(value.split("#")[1] || "", true);
24
+ }
25
+ },
26
+ back: () => {
27
+ go(-1);
28
+ },
29
+ forward: () => {
30
+ go(1);
31
+ },
32
+ go,
33
+ listen: (listener) => {
34
+ listeners.push(listener);
35
+ return () => {
36
+ const index = listeners.indexOf(listener);
37
+ listeners.splice(index, 1);
38
+ };
39
+ }
40
+ };
41
+ }
42
+ export function MemoryRouter(props) {
43
+ const memoryHistory = props.history || createMemoryHistory();
44
+ return createRouter({
45
+ get: memoryHistory.get,
46
+ set: memoryHistory.set,
47
+ init: memoryHistory.listen,
48
+ utils: {
49
+ go: memoryHistory.go
50
+ }
51
+ })(props);
52
+ }
@@ -0,0 +1,6 @@
1
+ import type { BaseRouterProps } from "./components";
2
+ import type { JSX } from "solid-js";
3
+ export type RouterProps = BaseRouterProps & {
4
+ url?: string;
5
+ };
6
+ export declare function Router(props: RouterProps): JSX.Element;
@@ -0,0 +1,28 @@
1
+ import { isServer } from "solid-js/web";
2
+ import { createRouter, scrollToHash, bindEvent } from "./createRouter";
3
+ import { StaticRouter } from "./StaticRouter";
4
+ import { setupNativeEvents } from "../data/events";
5
+ export function Router(props) {
6
+ if (isServer)
7
+ return StaticRouter(props);
8
+ return createRouter({
9
+ get: () => ({
10
+ value: window.location.pathname + window.location.search + window.location.hash,
11
+ state: history.state
12
+ }),
13
+ set({ value, replace, scroll, state }) {
14
+ if (replace) {
15
+ window.history.replaceState(state, "", value);
16
+ }
17
+ else {
18
+ window.history.pushState(state, "", value);
19
+ }
20
+ scrollToHash(window.location.hash.slice(1), scroll);
21
+ },
22
+ init: notify => bindEvent(window, "popstate", () => notify()),
23
+ create: setupNativeEvents,
24
+ utils: {
25
+ go: delta => window.history.go(delta)
26
+ }
27
+ })(props);
28
+ }
@@ -0,0 +1,6 @@
1
+ import { type BaseRouterProps } from "./components";
2
+ import type { JSX } from "solid-js";
3
+ export type StaticRouterProps = BaseRouterProps & {
4
+ url?: string;
5
+ };
6
+ export declare function StaticRouter(props: StaticRouterProps): JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { getRequestEvent } from "solid-js/web";
2
+ import { createRouterComponent } from "./components";
3
+ function getPath(url) {
4
+ const u = new URL(url);
5
+ return u.pathname + u.search;
6
+ }
7
+ export function StaticRouter(props) {
8
+ let e;
9
+ const obj = {
10
+ value: props.url || ((e = getRequestEvent()) && getPath(e.request.url)) || ""
11
+ };
12
+ return createRouterComponent({
13
+ signal: [() => obj, next => Object.assign(obj, next)]
14
+ })(props);
15
+ }
@@ -0,0 +1,17 @@
1
+ import type { Component, JSX } from "solid-js";
2
+ import type { MatchFilters, RouteLoadFunc, RouterIntegration, RouteSectionProps } from "../types";
3
+ export type BaseRouterProps = {
4
+ base?: string;
5
+ actionBase?: string;
6
+ root?: Component<RouteSectionProps>;
7
+ children?: JSX.Element;
8
+ };
9
+ export declare const createRouterComponent: (router: RouterIntegration) => (props: BaseRouterProps) => JSX.Element;
10
+ export type RouteProps<S extends string> = {
11
+ path?: S | S[];
12
+ children?: JSX.Element;
13
+ load?: RouteLoadFunc;
14
+ matchFilters?: MatchFilters<S>;
15
+ component?: Component;
16
+ };
17
+ export declare const Route: <S extends string>(props: RouteProps<S>) => JSX.Element;
@@ -0,0 +1,70 @@
1
+ /*@refresh skip*/
2
+ import { children, createMemo, createRoot, mergeProps, on, Show } from "solid-js";
3
+ import { createBranches, createRouteContext, createRouterContext, getRouteMatches, RouteContextObj, RouterContextObj } from "../routing";
4
+ import { createMemoObject } from "../utils";
5
+ export const createRouterComponent = (router) => (props) => {
6
+ const { base, actionBase } = props;
7
+ const routeDefs = children(() => props.children);
8
+ const branches = createMemo(() => createBranches(props.root ? { component: props.root, children: routeDefs() } : routeDefs(), props.base || ""));
9
+ const routerState = createRouterContext(router, branches, { base, actionBase });
10
+ router.create && router.create(routerState);
11
+ return (<RouterContextObj.Provider value={routerState}>
12
+ <Routes routerState={routerState} branches={branches()}/>
13
+ </RouterContextObj.Provider>);
14
+ };
15
+ function Routes(props) {
16
+ const matches = createMemo(() => getRouteMatches(props.branches, props.routerState.location.pathname));
17
+ const params = createMemoObject(() => {
18
+ const m = matches();
19
+ const params = {};
20
+ for (let i = 0; i < m.length; i++) {
21
+ Object.assign(params, m[i].params);
22
+ }
23
+ return params;
24
+ });
25
+ const disposers = [];
26
+ let root;
27
+ const routeStates = createMemo(on(matches, (nextMatches, prevMatches, prev) => {
28
+ let equal = prevMatches && nextMatches.length === prevMatches.length;
29
+ const next = [];
30
+ for (let i = 0, len = nextMatches.length; i < len; i++) {
31
+ const prevMatch = prevMatches && prevMatches[i];
32
+ const nextMatch = nextMatches[i];
33
+ if (prev && prevMatch && nextMatch.route.key === prevMatch.route.key) {
34
+ next[i] = prev[i];
35
+ }
36
+ else {
37
+ equal = false;
38
+ if (disposers[i]) {
39
+ disposers[i]();
40
+ }
41
+ createRoot(dispose => {
42
+ disposers[i] = dispose;
43
+ next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => matches()[i], params);
44
+ });
45
+ }
46
+ }
47
+ disposers.splice(nextMatches.length).forEach(dispose => dispose());
48
+ if (prev && equal) {
49
+ return prev;
50
+ }
51
+ root = next[0];
52
+ return next;
53
+ }));
54
+ return (<Show when={routeStates() && root} keyed>
55
+ {route => <RouteContextObj.Provider value={route}>{route.outlet()}</RouteContextObj.Provider>}
56
+ </Show>);
57
+ }
58
+ const createOutlet = (child) => {
59
+ return () => (<Show when={child()} keyed>
60
+ {child => <RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>}
61
+ </Show>);
62
+ };
63
+ export const Route = (props) => {
64
+ const childRoutes = children(() => props.children);
65
+ return mergeProps(props, {
66
+ get children() {
67
+ return childRoutes();
68
+ }
69
+ });
70
+ };
@@ -0,0 +1,4 @@
1
+ import type { LocationChange, RouterContext, RouterUtils } from "../types";
2
+ export declare function createIntegration(get: () => string | LocationChange, set: (next: LocationChange) => void, init?: (notify: (value?: string | LocationChange) => void) => () => void, create?: (router: RouterContext) => void, utils?: Partial<RouterUtils>): (props: import("./components").RouterProps) => import("solid-js").JSX.Element;
3
+ export declare function bindEvent(target: EventTarget, type: string, handler: EventListener): () => void;
4
+ export declare function scrollToHash(hash: string, fallbackTop?: boolean): void;
@@ -0,0 +1,49 @@
1
+ import { createSignal, onCleanup } from "solid-js";
2
+ import { createRouter } from "./components";
3
+ function intercept([value, setValue], get, set) {
4
+ return [get ? () => get(value()) : value, set ? (v) => setValue(set(v)) : setValue];
5
+ }
6
+ function querySelector(selector) {
7
+ if (selector === "#") {
8
+ return null;
9
+ }
10
+ // Guard against selector being an invalid CSS selector
11
+ try {
12
+ return document.querySelector(selector);
13
+ }
14
+ catch (e) {
15
+ return null;
16
+ }
17
+ }
18
+ export function createIntegration(get, set, init, create, utils) {
19
+ let ignore = false;
20
+ const wrap = (value) => (typeof value === "string" ? { value } : value);
21
+ const signal = intercept(createSignal(wrap(get()), { equals: (a, b) => a.value === b.value }), undefined, next => {
22
+ !ignore && set(next);
23
+ return next;
24
+ });
25
+ init &&
26
+ onCleanup(init((value = get()) => {
27
+ ignore = true;
28
+ signal[1](wrap(value));
29
+ ignore = false;
30
+ }));
31
+ return createRouter({
32
+ signal,
33
+ create,
34
+ utils
35
+ });
36
+ }
37
+ export function bindEvent(target, type, handler) {
38
+ target.addEventListener(type, handler);
39
+ return () => target.removeEventListener(type, handler);
40
+ }
41
+ export function scrollToHash(hash, fallbackTop) {
42
+ const el = querySelector(`#${hash}`);
43
+ if (el) {
44
+ el.scrollIntoView();
45
+ }
46
+ else if (fallbackTop) {
47
+ window.scrollTo(0, 0);
48
+ }
49
+ }
@@ -0,0 +1,48 @@
1
+ import { createSignal, onCleanup } from "solid-js";
2
+ function intercept([value, setValue], get, set) {
3
+ return [get ? () => get(value()) : value, set ? (v) => setValue(set(v)) : setValue];
4
+ }
5
+ function querySelector(selector) {
6
+ if (selector === "#") {
7
+ return null;
8
+ }
9
+ // Guard against selector being an invalid CSS selector
10
+ try {
11
+ return document.querySelector(selector);
12
+ }
13
+ catch (e) {
14
+ return null;
15
+ }
16
+ }
17
+ export function createIntegration(get, set, init, create, utils) {
18
+ let ignore = false;
19
+ const wrap = (value) => (typeof value === "string" ? { value } : value);
20
+ const signal = intercept(createSignal(wrap(get()), { equals: (a, b) => a.value === b.value }), undefined, next => {
21
+ !ignore && set(next);
22
+ return next;
23
+ });
24
+ init &&
25
+ onCleanup(init((value = get()) => {
26
+ ignore = true;
27
+ signal[1](wrap(value));
28
+ ignore = false;
29
+ }));
30
+ return {
31
+ signal,
32
+ create,
33
+ utils
34
+ };
35
+ }
36
+ export function bindEvent(target, type, handler) {
37
+ target.addEventListener(type, handler);
38
+ return () => target.removeEventListener(type, handler);
39
+ }
40
+ export function scrollToHash(hash, fallbackTop) {
41
+ const el = querySelector(`#${hash}`);
42
+ if (el) {
43
+ el.scrollIntoView();
44
+ }
45
+ else if (fallbackTop) {
46
+ window.scrollTo(0, 0);
47
+ }
48
+ }
@@ -0,0 +1,10 @@
1
+ import type { LocationChange, RouterContext, RouterUtils } from "../types";
2
+ export declare function createRouter(config: {
3
+ get: () => string | LocationChange;
4
+ set: (next: LocationChange) => void;
5
+ init?: (notify: (value?: string | LocationChange) => void) => () => void;
6
+ create?: (router: RouterContext) => void;
7
+ utils?: Partial<RouterUtils>;
8
+ }): (props: import("./components").BaseRouterProps) => import("solid-js").JSX.Element;
9
+ export declare function bindEvent(target: EventTarget, type: string, handler: EventListener): () => void;
10
+ export declare function scrollToHash(hash: string, fallbackTop?: boolean): void;
@@ -0,0 +1,49 @@
1
+ import { createSignal, onCleanup } from "solid-js";
2
+ import { createRouterComponent } from "./components";
3
+ function intercept([value, setValue], get, set) {
4
+ return [get ? () => get(value()) : value, set ? (v) => setValue(set(v)) : setValue];
5
+ }
6
+ function querySelector(selector) {
7
+ if (selector === "#") {
8
+ return null;
9
+ }
10
+ // Guard against selector being an invalid CSS selector
11
+ try {
12
+ return document.querySelector(selector);
13
+ }
14
+ catch (e) {
15
+ return null;
16
+ }
17
+ }
18
+ export function createRouter(config) {
19
+ let ignore = false;
20
+ const wrap = (value) => (typeof value === "string" ? { value } : value);
21
+ const signal = intercept(createSignal(wrap(config.get()), { equals: (a, b) => a.value === b.value }), undefined, next => {
22
+ !ignore && config.set(next);
23
+ return next;
24
+ });
25
+ config.init &&
26
+ onCleanup(config.init((value = config.get()) => {
27
+ ignore = true;
28
+ signal[1](wrap(value));
29
+ ignore = false;
30
+ }));
31
+ return createRouterComponent({
32
+ signal,
33
+ create: config.create,
34
+ utils: config.utils
35
+ });
36
+ }
37
+ export function bindEvent(target, type, handler) {
38
+ target.addEventListener(type, handler);
39
+ return () => target.removeEventListener(type, handler);
40
+ }
41
+ export function scrollToHash(hash, fallbackTop) {
42
+ const el = querySelector(`#${hash}`);
43
+ if (el) {
44
+ el.scrollIntoView();
45
+ }
46
+ else if (fallbackTop) {
47
+ window.scrollTo(0, 0);
48
+ }
49
+ }
@@ -0,0 +1,11 @@
1
+ export { Route } from "./components";
2
+ export type { BaseRouterProps, RouteProps } from "./components";
3
+ export { createRouter } from "./createRouter";
4
+ export { Router } from "./Router";
5
+ export type { RouterProps } from "./Router";
6
+ export { HashRouter } from "./HashRouter";
7
+ export type { HashRouterProps } from "./HashRouter";
8
+ export { MemoryRouter, createMemoryHistory } from "./MemoryRouter";
9
+ export type { MemoryRouterProps, MemoryHistory } from "./MemoryRouter";
10
+ export { StaticRouter } from "./StaticRouter";
11
+ export type { StaticRouterProps } from "./StaticRouter";
@@ -0,0 +1,6 @@
1
+ export { Route } from "./components";
2
+ export { createRouter } from "./createRouter";
3
+ export { Router } from "./Router";
4
+ export { HashRouter } from "./HashRouter";
5
+ export { MemoryRouter, createMemoryHistory } from "./MemoryRouter";
6
+ export { StaticRouter } from "./StaticRouter";
package/dist/routing.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { JSX, Accessor } from "solid-js";
2
- import type { BeforeLeaveEventArgs, Branch, Intent, Location, LocationChangeSignal, MatchFilters, NavigateOptions, Navigator, Params, Route, RouteContext, RouteDefinition, RouteMatch, RouterContext, RouterIntegration, SetParams } from "./types";
2
+ import type { BeforeLeaveEventArgs, Branch, Intent, Location, MatchFilters, NavigateOptions, Navigator, Params, Route, RouteContext, RouteDefinition, RouteMatch, RouterContext, RouterIntegration, SetParams } from "./types";
3
3
  export declare const RouterContextObj: import("solid-js").Context<RouterContext | undefined>;
4
4
  export declare const RouteContextObj: import("solid-js").Context<RouteContext | undefined>;
5
5
  export declare const useRouter: () => RouterContext;
@@ -18,9 +18,8 @@ export declare function createBranch(routes: Route[], index?: number): Branch;
18
18
  export declare function createBranches(routeDef: RouteDefinition | RouteDefinition[], base?: string, stack?: Route[], branches?: Branch[]): Branch[];
19
19
  export declare function getRouteMatches(branches: Branch[], location: string): RouteMatch[];
20
20
  export declare function createLocation(path: Accessor<string>, state: Accessor<any>): Location;
21
- export declare function registerAction(url: string, fn: Function): void;
22
21
  export declare function getIntent(): Intent | undefined;
23
- export declare function createRouterContext(integration?: RouterIntegration | LocationChangeSignal, getBranches?: () => Branch[], options?: {
22
+ export declare function createRouterContext(integration: RouterIntegration, getBranches?: () => Branch[], options?: {
24
23
  base?: string;
25
24
  actionBase?: string;
26
25
  }): RouterContext;