preact-hashish-router 0.1.11 → 0.1.13

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 CHANGED
@@ -103,6 +103,72 @@ export default function Header() {
103
103
  }
104
104
  ```
105
105
 
106
+ ### DataRouter
107
+
108
+ Alternative you can use `createDataRouter`
109
+
110
+ ```tsx
111
+ import { createDataRouter, NotFound, RouterErrorBoundary } from "preact-hashish-router";
112
+ import { lazy } from "preact/compat";
113
+ import { AllLevelWildcard } from "./routes/AllLevelWildcard";
114
+ import { Home } from "./routes/Home";
115
+ import { OneLevelWildcard } from "./routes/OneLevelWildcard";
116
+ import { ProductDetails } from "./routes/ProductDetails";
117
+
118
+ const AboutLazy = lazy(() => import("./routes/About"));
119
+
120
+ const DataRouter = createDataRouter([
121
+ {
122
+ path: "/",
123
+ element: <Home />,
124
+ children: [
125
+ {
126
+ path: "about",
127
+ lazy: true,
128
+ fallback: <h1>Loading About...</h1>,
129
+ element: <AboutLazy />,
130
+ children: [
131
+ {
132
+ path: "test",
133
+ element: <h1>About/test</h1>,
134
+ },
135
+ ],
136
+ },
137
+ {
138
+ path: "product/:id",
139
+ element: <ProductDetails />,
140
+ },
141
+ {
142
+ path: "one-level-wildcard/*",
143
+ element: <OneLevelWildcard />,
144
+ },
145
+ {
146
+ path: "all-level-wildcard/**",
147
+ element: <AllLevelWildcard />,
148
+ },
149
+ ],
150
+ },
151
+ ]);
152
+
153
+ export function App() {
154
+ return (
155
+ <RouterErrorBoundary>
156
+ <DataRouter
157
+ onRouteDidChange={(url) => {
158
+ console.log("onRouteDidChange", url);
159
+ }}
160
+ onBeforeRouteChange={(url) => {
161
+ console.log("onBeforeRouteChange", url);
162
+ }}
163
+ >
164
+ <NotFound element={<h1>Custom Not Found Element</h1>} />
165
+ </DataRouter>
166
+ </RouterErrorBoundary>
167
+ );
168
+ }
169
+ ```
170
+
106
171
  ## Development
107
172
 
108
173
  If you have any improvements or find any issues, feel free to contribute or open an issue in the associated repository.
174
+
@@ -1,4 +1,4 @@
1
- import type { VNode } from "preact";
1
+ import { type VNode } from "preact";
2
2
  export declare const NotFound: (props: {
3
3
  element: VNode<any>;
4
4
  }) => import("preact").JSX.Element;
package/dist/Route.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { VNode } from "preact";
1
+ import { type VNode } from "preact";
2
2
  export type RouteProps = {
3
3
  /** The route path matcher
4
4
  * @example "/"
package/dist/Router.d.ts CHANGED
@@ -15,13 +15,13 @@ export type RouterProps = PropsWithChildren<{
15
15
  */
16
16
  redirect_path_to_hash?: boolean;
17
17
  /**
18
- * Trigger hook before the next route calcultation begin
18
+ * Trigger hook before push new route entry
19
19
  */
20
- onBeforeRouteChange?: () => Promise<void> | void;
20
+ onBeforeRouteChange?: (path: string) => Promise<void> | void;
21
21
  /**
22
- * Trigger hook when the next route calcultation finish
22
+ * Trigger hook after push new route entry
23
23
  */
24
- onRouteDidChange?: () => Promise<void> | void;
24
+ onRouteDidChange?: (path: string) => Promise<void> | void;
25
25
  /**
26
26
  * If true don't trigger hooks on first render
27
27
  * @default false
@@ -0,0 +1,5 @@
1
+ import type { RouteProps } from "./Route";
2
+ export type RouteData = RouteProps & {
3
+ children?: RouteData[] | undefined;
4
+ };
5
+ export declare function createDataRouter(data: RouteData[]): ({ type: router_type, ignoreInitial, ...props }: import("./Router").RouterProps) => import("preact").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export { NotFound } from "./NotFound";
4
4
  export { Route } from "./Route";
5
5
  export { Router } from "./Router";
6
6
  export { RouterErrorBoundary } from "./RouterErrorBoundary";
7
+ export { createDataRouter, type RouteData } from "./createDataRouter";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{forwardRef as A}from"preact/compat";import{createContext as k}from"preact";import{useContext as c}from"preact/hooks";var s=k({active_path:"",active_route_data:null,params:void 0,searchParams:new URLSearchParams,async go(){}}),p=()=>{let e=c(s);if(!e)throw new Error("useHashisherContext should be inside a HashisherContext provider");return e};function E(){let e=c(s);if(!e)throw new Error("useParams should be inside a HashisherContext provider");return e.params}function D(){let e=c(s);if(!e)throw new Error("useSearchParams should be inside a HashisherContext provider");return e.searchParams}var U=()=>{let e=c(s);if(!e)throw new Error("useRouter should be inside a HashisherContext provider");return{path:e.active_path,params:e.params,searchParams:e.searchParams,go:e.go}};import{jsx as B}from"preact/jsx-runtime";var z=A(({href:e,...t},r)=>{let{go:n}=p();if(!e)throw new Error("A: href must be defined");return B("a",{ref:r,href:e,onClick:o=>{o&&o.type==="click"&&(o.ctrlKey||o.metaKey||o.altKey||o.shiftKey||o.button!==0)||(o.preventDefault(),n(e))},...t})});import{Fragment as K,jsx as _}from"preact/jsx-runtime";var W=e=>(F(e.element),_(K,{})),R=_("div",{children:"404 Not Found"}),F=e=>{R=e},l=()=>R;import{addRoute as T,createRouter as O}from"rou3";var f=O(),P=(e,t)=>{T(f,void 0,e,{component:t.element,fallback:t.fallback||null,lazy:!!t.lazy})};import{Fragment as G,jsx as J}from"preact/jsx-runtime";function q(e){return P(e.path,e),J(G,{})}import{useCallback as Y,useLayoutEffect as w,useRef as Z,useState as u}from"preact/hooks";import{findRoute as $}from"rou3";import{parseURL as C}from"ufo";import{Suspense as Q}from"preact/compat";import{jsx as X}from"preact/jsx-runtime";var y=()=>{let{active_route_data:e}=p();return e?e.component===null?l():e.lazy?X(Q,{fallback:e.fallback,children:e.component}):e.component:l()};import{jsx as ee,jsxs as te}from"preact/jsx-runtime";var I=({type:e="browser",ignoreInitial:t=!1,...r})=>{let[n,o]=u("/"),[g,v]=u(void 0),[b,H]=u(new URLSearchParams),[V,M]=u(null),h=Z(0),i=Y(async a=>{console.log({ignoreInitial:t,renderCount:h}),t===!0?h.current!==0&&await r.onBeforeRouteChange?.():await r.onBeforeRouteChange?.();let{params:m,path:d,route_data:S,search_params:L}=await j(a,e);e==="browser"&&window.history.pushState(null,"",d),e==="hash"&&(window.location.hash=d),o(d),v(m),H(L),M(S),t===!0?h.current!==0&&await r.onRouteDidChange?.():await r.onRouteDidChange?.(),h.current+=1},[e,r.onBeforeRouteChange,r.onRouteDidChange]);w(()=>{if(e!=="browser")return;let a=()=>{i(null)};return window.addEventListener("popstate",a),a(),()=>{window.removeEventListener("popstate",a)}},[i,e]),w(()=>{if(e!=="hash")return;let a=()=>{i(null)};return window.addEventListener("hashchange",a),a(),()=>{window.removeEventListener("hashchange",a)}},[i,e]);let N=async a=>{let m=C(a).pathname;i(m)};return te(s.Provider,{value:{active_path:n,searchParams:b,params:g,active_route_data:V,go:N},children:[r.children,ee(y,{})]})},j=async(e,t="browser")=>{let r=C(window.location.href),n=e||"";e===null&&(t==="hash"?n=r.hash:n=r.pathname);let o=$(f,void 0,n);return o?{path:n,search_params:new URLSearchParams(r.search),route_data:{...o.data},params:{...o.params}}:{path:n,search_params:new URLSearchParams(r.search),route_data:null,params:void 0}};import{Component as re}from"preact";import{jsxs as oe}from"preact/jsx-runtime";var x=class extends re{state={error:null};static getDerivedStateFromError(t){return{error:t.message}}componentDidCatch(t){this.setState({error:t.message})}render(){return this.state.error?this.props.fallback?this.props.fallback:oe("p",{children:["Oh no! We ran into an error: ",this.state.error]}):this.props.children}};export{z as A,W as NotFound,q as Route,I as Router,x as RouterErrorBoundary,E as useParams,U as useRouter,D as useSearchParams};
1
+ import{forwardRef as A}from"preact/compat";import{createContext as E}from"preact";import{useContext as c}from"preact/hooks";var i=E({active_path:"",active_route_data:null,params:void 0,searchParams:new URLSearchParams,async go(){}}),p=()=>{let e=c(i);if(!e)throw new Error("useHashisherContext should be inside a HashisherContext provider");return e};function z(){let e=c(i);if(!e)throw new Error("useParams should be inside a HashisherContext provider");return e.params}function B(){let e=c(i);if(!e)throw new Error("useSearchParams should be inside a HashisherContext provider");return e.searchParams}var U=()=>{let e=c(i);if(!e)throw new Error("useRouter should be inside a HashisherContext provider");return{path:e.active_path,params:e.params,searchParams:e.searchParams,go:e.go}};import{jsx as W}from"preact/jsx-runtime";var F=A(({href:e,...r},t)=>{let{go:a}=p();if(!e)throw new Error("A: href must be defined");return W("a",{ref:t,href:e,onClick:o=>{o&&o.type==="click"&&(o.ctrlKey||o.metaKey||o.altKey||o.shiftKey||o.button!==0)||(o.preventDefault(),a(e))},...r})});import{Fragment as K}from"preact";import{jsx as g}from"preact/jsx-runtime";var T=e=>(O(e.element),g(K,{})),y=g("div",{children:"404 Not Found"}),O=e=>{y=e},R=()=>y;import{Fragment as G}from"preact";import{addRoute as $,createRouter as q}from"rou3";var P=q(),u=(e,r)=>{$(P,void 0,e,{component:r.element,fallback:r.fallback||null,lazy:!!r.lazy})};import{jsx as J}from"preact/jsx-runtime";function I(e){return u(e.path,e),J(G,{})}import{useCallback as Y,useLayoutEffect as C,useRef as Z,useState as m}from"preact/hooks";import{findRoute as j}from"rou3";import{parseURL as v}from"ufo";import{Suspense as Q}from"preact/compat";import{jsx as X}from"preact/jsx-runtime";var w=()=>{let{active_route_data:e}=p();return e?e.component===null?R():e.lazy?X(Q,{fallback:e.fallback,children:e.component}):e.component:R()};import{jsx as te,jsxs as re}from"preact/jsx-runtime";var x=({type:e="browser",ignoreInitial:r=!1,...t})=>{let[a,o]=m("/"),[l,H]=m(void 0),[V,k]=m(new URLSearchParams),[M,N]=m(null),d=Z(0),h=Y(async n=>{let{params:f,path:s,route_data:D,search_params:L}=await ee(n,e);r===!0?d.current!==0&&await t.onBeforeRouteChange?.(s):await t.onBeforeRouteChange?.(s),e==="browser"&&window.history.pushState(null,"",s),e==="hash"&&(window.location.hash=s),o(s),H(f),k(L),N(D),r===!0?d.current!==0&&await t.onRouteDidChange?.(s):await t.onRouteDidChange?.(s),d.current+=1},[e,t.onBeforeRouteChange,t.onRouteDidChange]);C(()=>{if(e!=="browser")return;let n=()=>{h(null)};return window.addEventListener("popstate",n),n(),()=>{window.removeEventListener("popstate",n)}},[h,e]),C(()=>{if(e!=="hash")return;let n=()=>{h(null)};return window.addEventListener("hashchange",n),n(),()=>{window.removeEventListener("hashchange",n)}},[h,e]);let S=async n=>{let f=v(n).pathname;h(f)};return re(i.Provider,{value:{active_path:a,searchParams:V,params:l,active_route_data:M,go:S},children:[t.children,te(w,{})]})},ee=async(e,r="browser")=>{let t=v(window.location.href),a=e||"";e===null&&(r==="hash"?a=t.hash:a=t.pathname);let o=j(P,void 0,a);return o?{path:a,search_params:new URLSearchParams(t.search),route_data:{...o.data},params:{...o.params}}:{path:a,search_params:new URLSearchParams(t.search),route_data:null,params:void 0}};import{Component as oe}from"preact";import{jsxs as ae}from"preact/jsx-runtime";var _=class extends oe{state={error:null};static getDerivedStateFromError(r){return{error:r.message}}componentDidCatch(r){this.setState({error:r.message})}render(){return this.state.error?this.props.fallback?this.props.fallback:ae("p",{children:["Oh no! We ran into an error: ",this.state.error]}):this.props.children}};function ne(e){return b(e),x}function b(e,r=""){for(let t of e){let a=se(r,t.path);u(a,{element:t.element,fallback:t.fallback,lazy:t.lazy}),t.children&&t.children.length>0&&b(t.children,a)}}var se=(e,r)=>{let t=e.split("/").filter(Boolean),a=r.split("/").filter(Boolean);for(let l of a)t.push(l);return`/${t.join("/")}`};export{F as A,T as NotFound,I as Route,x as Router,_ as RouterErrorBoundary,ne as createDataRouter,z as useParams,U as useRouter,B as useSearchParams};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "preact-hashish-router",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "description": "A simple router for preact",
6
6
  "scripts": {
@@ -45,19 +45,19 @@
45
45
  "README.md"
46
46
  ],
47
47
  "dependencies": {
48
- "rou3": "0.7.3",
48
+ "rou3": "0.7.7",
49
49
  "ufo": "1.6.1"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "preact": "10.27.2"
53
53
  },
54
54
  "devDependencies": {
55
- "@biomejs/biome": "1.8.3",
56
- "@types/node": "22.18.0",
55
+ "@biomejs/biome": "2.0.6",
56
+ "@types/node": "24.7.2",
57
57
  "changelogen": "0.6.2",
58
- "esbuild": "0.25.9",
58
+ "esbuild": "0.25.11",
59
59
  "prettier": "3.6.2",
60
- "prettier-plugin-organize-imports": "4.2.0",
61
- "typescript": "5.9.2"
60
+ "prettier-plugin-organize-imports": "4.3.0",
61
+ "typescript": "5.9.3"
62
62
  }
63
63
  }