preact-hashish-router 0.0.7 → 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/dist/Router.js CHANGED
@@ -3,7 +3,7 @@ import { useEffect, useMemo, useState } from "preact/hooks";
3
3
  import { router_context } from "./context";
4
4
  const get_hash_route = () => location.hash.slice(1) || "/";
5
5
  export const Router = (props) => {
6
- const [path, setPath] = useState(get_hash_route());
6
+ const [path, setPath] = useState();
7
7
  const [query, setQuery] = useState("");
8
8
  const [itMatch, setItMatch] = useState(false);
9
9
  const router_type = useMemo(() => {
@@ -44,6 +44,10 @@ export const Router = (props) => {
44
44
  const [path, query] = get_hash_route().split("?");
45
45
  setQuery(query || "");
46
46
  setPath(path);
47
+ if (location.pathname !== "/") {
48
+ location.hash = location.pathname;
49
+ location.pathname = "";
50
+ }
47
51
  hashEffectHandler.effect();
48
52
  return () => hashEffectHandler.cleanUp();
49
53
  }, []);
@@ -55,15 +59,15 @@ export const Router = (props) => {
55
59
  browserEffectHandler.effect();
56
60
  return () => browserEffectHandler.cleanUp();
57
61
  }, []);
58
- const handlerManualRouteChange = (r) => {
59
- setPath(r);
62
+ const handlerManualRouteChange = (newPath) => {
63
+ setPath(newPath);
60
64
  setItMatch(false);
61
65
  if (router_type === "hash") {
62
- location.hash = r;
66
+ location.hash = newPath;
63
67
  return;
64
68
  }
65
69
  if (router_type === "browser") {
66
- history.pushState(null, "", new URL(r, location.origin));
70
+ history.pushState(null, "", new URL(newPath, location.origin));
67
71
  return;
68
72
  }
69
73
  };
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "preact-hashish-router",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "description": "A simple router for preact",
7
7
  "scripts": {
8
- "build": "tsc -p ./tsconfig.json",
8
+ "build": "tsc -p ./tsconfig.lib.json",
9
9
  "format": "prettier --write src --ignore-unknown",
10
+ "app:dev": "vite",
10
11
  "prepublishOnly": "npm run build && npm run format",
11
12
  "push": "npm version patch && git push",
12
13
  "push-minor": "npm version minor && git push",
@@ -30,6 +31,7 @@
30
31
  "author": "LiasCode",
31
32
  "devDependencies": {
32
33
  "@preact/preset-vite": "^2.10.1",
34
+ "@types/node": "^22.13.4",
33
35
  "preact-hashish-router": "^0.0.6",
34
36
  "prettier": "^3.5.1",
35
37
  "prettier-plugin-organize-imports": "^4.1.0",
@@ -37,7 +39,6 @@
37
39
  "vite": "^6.1.0"
38
40
  },
39
41
  "files": [
40
- "src",
41
42
  "dist",
42
43
  "LICENSE",
43
44
  "package.json",
package/src/A.tsx DELETED
@@ -1,32 +0,0 @@
1
- import { AnchorHTMLAttributes, forwardRef, MouseEventHandler, PropsWithChildren } from "preact/compat";
2
- import { useCallback, useMemo } from "preact/hooks";
3
- import { useRouter } from "./useRouter";
4
-
5
- export type AProps = PropsWithChildren & AnchorHTMLAttributes;
6
-
7
- export const A = forwardRef<HTMLAnchorElement, AProps>(({ href, className, ...props }) => {
8
- const router = useRouter();
9
-
10
- const isActive = useMemo(() => {
11
- return router.path === href;
12
- }, [router.path, href]);
13
-
14
- const browserRouterClickAnchorHandler: MouseEventHandler<HTMLAnchorElement> = useCallback(
15
- (e) => {
16
- e.preventDefault();
17
- e.stopPropagation();
18
- router.go(href.toString());
19
- },
20
- [router.type]
21
- );
22
-
23
- return (
24
- <a
25
- href={router.type === "browser" ? href : `#${href}`}
26
- className={className}
27
- data-route-active={isActive}
28
- {...props}
29
- onClick={router.type === "browser" ? browserRouterClickAnchorHandler : undefined}
30
- />
31
- );
32
- });
@@ -1,14 +0,0 @@
1
- import { PropsWithChildren, Suspense } from "preact/compat";
2
- import { useRouter } from "./useRouter";
3
-
4
- export function ErrorRoute(props: PropsWithChildren<{ lazy?: boolean }>) {
5
- const router = useRouter();
6
-
7
- if (router.itMatch) return null;
8
-
9
- if (props.lazy) {
10
- return <Suspense fallback={<div>Loading...</div>}>{props.children}</Suspense>;
11
- }
12
-
13
- return props.children;
14
- }
package/src/Route.tsx DELETED
@@ -1,27 +0,0 @@
1
- import { VNode } from "preact";
2
- import { PropsWithChildren, Suspense } from "preact/compat";
3
- import { useRouter } from "./useRouter";
4
-
5
- type RouteProps = PropsWithChildren & { path: string; exact?: boolean; lazy?: boolean; fallback?: VNode };
6
-
7
- export function Route(props: RouteProps) {
8
- const router = useRouter();
9
-
10
- if (props.exact === undefined) {
11
- props.exact = true;
12
- }
13
-
14
- if (props.exact && router.path !== props.path) {
15
- return null;
16
- } else if (!router.path.includes(props.path)) {
17
- return null;
18
- }
19
-
20
- router.setItMatch(true);
21
-
22
- if (props.lazy) {
23
- return <Suspense fallback={props.fallback ?? <div>Loading...</div>}>{props.children}</Suspense>;
24
- }
25
-
26
- return props.children;
27
- }
package/src/Router.tsx DELETED
@@ -1,86 +0,0 @@
1
- import { PropsWithChildren } from "preact/compat";
2
- import { useEffect, useMemo, useState } from "preact/hooks";
3
- import { RouterContext, router_context } from "./context";
4
-
5
- const get_hash_route = () => location.hash.slice(1) || "/";
6
-
7
- type RouterProps = PropsWithChildren & {
8
- type: RouterContext["type"];
9
- };
10
-
11
- export const Router = (props: RouterProps) => {
12
- const [path, setPath] = useState(get_hash_route());
13
- const [query, setQuery] = useState("");
14
- const [itMatch, setItMatch] = useState(false);
15
-
16
- const router_type = useMemo(() => {
17
- return props.type;
18
- }, [props.type]);
19
-
20
- const hashEffectHandler = {
21
- listener: () => {
22
- const [path, query] = get_hash_route().split("?");
23
- setQuery(query || "");
24
- setPath(path);
25
- setItMatch(false);
26
- },
27
- effect: () => {
28
- if (location.hash === "") location.hash = "/";
29
- window.addEventListener("hashchange", hashEffectHandler.listener);
30
- },
31
- cleanUp: () => {
32
- window.removeEventListener("hashchange", hashEffectHandler.listener);
33
- },
34
- };
35
-
36
- const browserEffectHandler = {
37
- listener: () => {
38
- setPath(location.pathname);
39
- setQuery(location.search || "");
40
- setItMatch(false);
41
- },
42
- effect: () => {
43
- window.addEventListener("popstate", browserEffectHandler.listener);
44
- },
45
- cleanUp: () => {
46
- window.removeEventListener("hashchange", browserEffectHandler.listener);
47
- },
48
- };
49
-
50
- useEffect(() => {
51
- if (router_type !== "hash") return;
52
- const [path, query] = get_hash_route().split("?");
53
- setQuery(query || "");
54
- setPath(path);
55
-
56
- hashEffectHandler.effect();
57
- return () => hashEffectHandler.cleanUp();
58
- }, []);
59
-
60
- useEffect(() => {
61
- if (router_type !== "browser") return;
62
- setPath(location.pathname);
63
- setQuery(location.search || "");
64
- browserEffectHandler.effect();
65
- return () => browserEffectHandler.cleanUp();
66
- }, []);
67
-
68
- const handlerManualRouteChange = (r: string) => {
69
- setPath(r);
70
- setItMatch(false);
71
- if (router_type === "hash") {
72
- location.hash = r;
73
- return;
74
- }
75
- if (router_type === "browser") {
76
- history.pushState(null, "", new URL(r, location.origin));
77
- return;
78
- }
79
- };
80
-
81
- const ProviderValue: RouterContext = useMemo(() => {
82
- return { path, go: handlerManualRouteChange, itMatch, setItMatch, type: router_type, query };
83
- }, [path, handlerManualRouteChange, itMatch, setItMatch, router_type]);
84
-
85
- return <router_context.Provider value={ProviderValue}>{props.children}</router_context.Provider>;
86
- };
@@ -1,24 +0,0 @@
1
- import { Component, VNode } from "preact";
2
- import { PropsWithChildren } from "preact/compat";
3
-
4
- export class RouterErrorBoundary extends Component<PropsWithChildren & { fallback?: VNode }> {
5
- state = { error: null };
6
-
7
- static getDerivedStateFromError(error: any) {
8
- return { error: error.message };
9
- }
10
-
11
- componentDidCatch(error: any) {
12
- console.error(error);
13
- this.setState({ error: error.message });
14
- }
15
-
16
- render() {
17
- if (this.state.error) {
18
- if (this.props.fallback) return this.props.fallback;
19
-
20
- return <p>Oh no! We ran into an error: {this.state.error}</p>;
21
- }
22
- return this.props.children;
23
- }
24
- }
package/src/context.tsx DELETED
@@ -1,12 +0,0 @@
1
- import { createContext } from "preact";
2
-
3
- export type RouterContext = {
4
- path: string;
5
- query: string;
6
- go: (r: string) => void;
7
- itMatch: boolean;
8
- setItMatch: (r: boolean) => void;
9
- type: "hash" | "browser";
10
- };
11
-
12
- export const router_context = createContext<RouterContext>(null);
package/src/index.ts DELETED
@@ -1,6 +0,0 @@
1
- export * from "./A";
2
- export * from "./ErrorRoute";
3
- export * from "./Route";
4
- export * from "./Router";
5
- export * from "./RouterErrorBoundary";
6
- export * from "./useRouter";
package/src/useRouter.tsx DELETED
@@ -1,12 +0,0 @@
1
- import { useContext } from "preact/hooks";
2
- import { router_context } from "./context";
3
-
4
- export function useRouter() {
5
- const context = useContext(router_context);
6
-
7
- if (!context) {
8
- throw new Error("useRoute should be used within a Router");
9
- }
10
-
11
- return context;
12
- }