intentx-react-router 1.0.2 → 1.0.4
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
|
@@ -56,13 +56,19 @@ npm install intentx-react-router react-router@^7 react-router-dom@^7
|
|
|
56
56
|
## 1. Define intents
|
|
57
57
|
|
|
58
58
|
``` ts
|
|
59
|
-
import { createIntentRouter } from "intentx-react-router"
|
|
59
|
+
import { createIntentRouter, NavigateFn } from "intentx-react-router"
|
|
60
60
|
|
|
61
61
|
createIntentRouter({
|
|
62
62
|
"view-user": "/users/:userId/name/:page",
|
|
63
63
|
"edit-user": "/users/:userId/edit",
|
|
64
64
|
"checkout": "/checkout"
|
|
65
65
|
})
|
|
66
|
+
|
|
67
|
+
// Bind navigate in App
|
|
68
|
+
export function bindRouterNavigate(navigate: NavigateFn) {
|
|
69
|
+
bindNavigate(navigate);
|
|
70
|
+
}
|
|
71
|
+
|
|
66
72
|
```
|
|
67
73
|
|
|
68
74
|
---
|
|
@@ -75,9 +81,14 @@ import { useNavigate } from "react-router-dom"
|
|
|
75
81
|
import { bindNavigate } from "intentx-react-router"
|
|
76
82
|
|
|
77
83
|
export function RouterBinder() {
|
|
78
|
-
const navigate = useNavigate()
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
const navigate = useNavigate();
|
|
85
|
+
|
|
86
|
+
React.useEffect(() => {
|
|
87
|
+
// require
|
|
88
|
+
bindRouterNavigate(navigate);
|
|
89
|
+
}, [navigate]);
|
|
90
|
+
|
|
91
|
+
return null;
|
|
81
92
|
}
|
|
82
93
|
```
|
|
83
94
|
---
|
|
@@ -114,24 +125,6 @@ export default function App() {
|
|
|
114
125
|
)
|
|
115
126
|
}
|
|
116
127
|
```
|
|
117
|
-
|
|
118
|
-
## 4. IntentRouter
|
|
119
|
-
|
|
120
|
-
```ts
|
|
121
|
-
import { IntentRouter } from "intentx-react-router"
|
|
122
|
-
import { Routes } from "react-router-dom"
|
|
123
|
-
|
|
124
|
-
export default function App() {
|
|
125
|
-
return (
|
|
126
|
-
<IntentRouter>
|
|
127
|
-
<Routes>
|
|
128
|
-
<IntentRoute intent="checkout" component={CheckoutPage} />
|
|
129
|
-
</Routes>
|
|
130
|
-
</IntentRouter>
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
128
|
---
|
|
136
129
|
|
|
137
130
|
# Navigation
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { GlobalBus } from "eventbus-z";
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
export type NavigateIntentOptions<P = any> = {
|
|
3
|
+
params?: P | any[] | string | number;
|
|
4
|
+
query?: Record<string, any>;
|
|
5
|
+
options?: {
|
|
6
|
+
replace?: boolean;
|
|
7
|
+
scrollTop?: boolean;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export type NavigateOptions = {
|
|
5
11
|
replace?: boolean;
|
|
6
12
|
scrollTop?: boolean;
|
|
7
|
-
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
};
|
|
15
|
+
type IntentMap = Record<string, string>;
|
|
16
|
+
type GuardFn = (intent: string, params: any) => boolean | string | void;
|
|
17
|
+
export type NavigateFn = (path: string, options?: NavigateOptions) => void;
|
|
8
18
|
type PreloadFn = () => Promise<any> | void;
|
|
9
19
|
export declare function createIntentRouter(map: IntentMap): void;
|
|
10
20
|
export declare function bindNavigate(fn: NavigateFn): void;
|
|
@@ -13,6 +23,7 @@ export declare function navigateIntent<P = any>(intent: string, params?: P | any
|
|
|
13
23
|
replace?: boolean;
|
|
14
24
|
scrollTop?: boolean;
|
|
15
25
|
}): void;
|
|
26
|
+
export declare function navigateIntentObject<P = any>(intent: string, navigateIntentOption?: NavigateIntentOptions<P>): void;
|
|
16
27
|
export declare function addIntentGuard(fn: GuardFn): void;
|
|
17
28
|
export declare function addIntentGuardFor(intent: string, fn: GuardFn): void;
|
|
18
29
|
export declare function addIntentPreload(intent: string, fn: PreloadFn): void;
|
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createEventBus as n}from"eventbus-z";import{jsx as t,Fragment as o,jsxs as r}from"react/jsx-runtime";import{Link as e,useLocation as i,useNavigate as c,BrowserRouter as u}from"react-router-dom";import{useEffect as s}from"react";const a=n();let f=null;let l={},p=null,m=!1;const
|
|
1
|
+
import{createEventBus as n}from"eventbus-z";import{jsx as t,Fragment as o,jsxs as r}from"react/jsx-runtime";import{Link as e,useLocation as i,useNavigate as c,BrowserRouter as u}from"react-router-dom";import{useEffect as s}from"react";const a=n();let f=null;let l={},p=null,m=!1;const d=[],h={},T={};let y=null;const E="undefined"!=typeof window&&!0===window.__INTENT_ROUTER_DEBUG__;function A(...n){E&&console.log("[IntentRouter]",...n)}function N(n){if(!n)return"";const t=new URLSearchParams;for(const o in n){const r=n[o];null!=r&&(Array.isArray(r)?r.forEach(n=>t.append(o,String(n))):t.append(o,String(r)))}const o=t.toString();return o?`?${o}`:""}function w(n){l=n,A("intent map loaded",n)}function I(n){p&&p!==n&&E&&console.warn("IntentRouter navigate replaced"),p=n,m||(a.$onMultiple("INTENT_NAVIGATE",G),m=!0)}function g(n){y=n}function _(n,t,o,r){A("emit",n,{params:t,query:o});const e={intent:n,params:t,query:o,...r?{options:r}:{}};a.$emit("INTENT_NAVIGATE",e),f&&f.$emit("INTENT_NAVIGATE",e)}function $(n,t){const{params:o,query:r,options:e}=t||{};A("emit",n,{params:o,query:r});const i={intent:n,params:o,query:r,...e?{options:e}:{}};a.$emit("INTENT_NAVIGATE",i),f&&f.$emit("INTENT_NAVIGATE",i)}function q(n){d.push(n)}function v(n,t){h[n]||(h[n]=[]),h[n].push(t)}function R(n,t){T[n]||(T[n]=[]),T[n].push(t)}function k(n){S(n)}async function G(n){const t=l[n.intent];if(A("receive",n.intent,n),!t)return y&&p?.(y),void console.warn("Unknown intent:",n.intent);const o=V(t,n.params);for(const t of d){const r=await t(n.intent,o);if(!1===r)return;if("string"==typeof r)return void p?.(r,n.options)}const r=h[n.intent]||[];for(const t of r){const r=await t(n.intent,o);if(!1===r)return;if("string"==typeof r)return void p?.(r,n.options)}S(n.intent);const e=P(t,o)+N(n.query);A("navigate",{intent:n.intent,params:o,query:n.query,url:e}),p?.(e,n.options),f&&f.$emit("INTENT_NAVIGATE",n)}function S(n){const t=T[n];if(t)for(const o of t)try{const t=o();t instanceof Promise&&t.catch(()=>{console.warn(`Preload for intent "${n}" failed`)})}catch(t){console.warn(`Preload for intent "${n}" sync error`,t)}}const U={};function V(n,t){const o=function(n){if(U[n])return U[n];const t=[];return n.replace(/:([A-Za-z0-9_]+)/g,(n,o)=>(t.push(o),"")),U[n]=t,t}(n);if(!t)return{};if(Array.isArray(t)){const n={};return o.forEach((o,r)=>{void 0===t[r]&&console.warn(`Missing param "${o}"`),n[o]=t[r]}),n}return"object"==typeof t?t:1===o.length?{[o[0]]:t}:{}}function P(n,t){return n.replace(/:([A-Za-z0-9_]+)/g,(n,o)=>{const r=t[o];return void 0!==r?encodeURIComponent(r):""})}function x(n,t,o){const r=l[n];if(!r)return"";return P(r,V(r,t))+N(o)}const M={};function z(n){if(M[n])return M[n];const t=[],o=new RegExp("^"+n.replace(/:([A-Za-z0-9_]+)/g,(n,o)=>(t.push(o),"([^/]+)"))+"$");return M[n]={regex:o,keys:t},M[n]}function C(n){const[t,o]=n.split("?"),r=function(n){if(!n)return{};const t=new URLSearchParams(n),o={};return t.forEach((n,t)=>{o[t]?Array.isArray(o[t])?o[t].push(n):o[t]=[o[t],n]:o[t]=n}),o}(o);for(const n in l){const o=l[n],{regex:e,keys:i}=z(o),c=t.match(e);if(!c)continue;const u={};return i.forEach((n,t)=>{u[n]=decodeURIComponent(c[t+1])}),{intent:n,params:u,query:r}}return null}function L(n){f=n,f.$onMultiple("INTENT_NAVIGATE",G)}function b({intent:n,params:r,query:i,scrollTop:c,prefetch:u,onClick:s,onMouseEnter:a,onTouchStart:f,...l}){const p=x(n,r,i);return p?t(e,{to:p,onClick:n=>{c&&window.scrollTo({top:0}),s?.(n)},onMouseEnter:t=>{u&&k(n),a?.(t)},onTouchStart:t=>{u&&k(n),f?.(t)},...l}):(console.warn("IntentLink: unknown intent",n),t(o,{children:l.children}))}function Z(){const n=i(),t=C(n.pathname),o=new URLSearchParams(n.search),r={};return o.forEach((n,t)=>{r[t]=n}),{intent:t?.intent??null,params:t?.params??{},query:r}}function j({intent:n,component:r,fallback:e=null,loading:i,guard:c}){const u=Z();return u?u.intent!==n?null:c&&!c(u)?t(o,{children:e}):t(r,{...u}):i?t(o,{children:i}):null}function B({navigate:n}){const t=c();return s(()=>{I(n??t)},[n,t]),null}function D({children:n}){return r(u,{children:[t(B,{}),n]})}function O(n){const t=c();return s(()=>{I(n??t)},[n,t]),_}export{b as IntentLink,j as IntentRoute,D as IntentRouter,B as RouterBinder,q as addIntentGuard,v as addIntentGuardFor,R as addIntentPreload,I as bindNavigate,w as createIntentRouter,x as generatePathFromIntent,_ as navigateIntent,$ as navigateIntentObject,k as preloadIntent,C as resolveIntentFromUrl,g as setFallbackPath,L as setSharedBus,Z as useIntentRouter,O as useNavigateIntent};
|
package/build/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var n=require("eventbus-z"),t=require("react/jsx-runtime"),e=require("react-router-dom"),r=require("react");const o=n.createEventBus();let i=null;let s={},c=null,
|
|
1
|
+
"use strict";var n=require("eventbus-z"),t=require("react/jsx-runtime"),e=require("react-router-dom"),r=require("react");const o=n.createEventBus();let i=null;let s={},c=null,a=!1;const u=[],f={},l={};let p=null;const d="undefined"!=typeof window&&!0===window.__INTENT_ROUTER_DEBUG__;function m(...n){d&&console.log("[IntentRouter]",...n)}function I(n){if(!n)return"";const t=new URLSearchParams;for(const e in n){const r=n[e];null!=r&&(Array.isArray(r)?r.forEach(n=>t.append(e,String(n))):t.append(e,String(r)))}const e=t.toString();return e?`?${e}`:""}function h(n){c&&c!==n&&d&&console.warn("IntentRouter navigate replaced"),c=n,a||(o.$onMultiple("INTENT_NAVIGATE",E),a=!0)}function g(n,t,e,r){m("emit",n,{params:t,query:e});const s={intent:n,params:t,query:e,...r?{options:r}:{}};o.$emit("INTENT_NAVIGATE",s),i&&i.$emit("INTENT_NAVIGATE",s)}function x(n){T(n)}async function E(n){const t=s[n.intent];if(m("receive",n.intent,n),!t)return p&&c?.(p),void console.warn("Unknown intent:",n.intent);const e=y(t,n.params);for(const t of u){const r=await t(n.intent,e);if(!1===r)return;if("string"==typeof r)return void c?.(r,n.options)}const r=f[n.intent]||[];for(const t of r){const r=await t(n.intent,e);if(!1===r)return;if("string"==typeof r)return void c?.(r,n.options)}T(n.intent);const o=A(t,e)+I(n.query);m("navigate",{intent:n.intent,params:e,query:n.query,url:o}),c?.(o,n.options),i&&i.$emit("INTENT_NAVIGATE",n)}function T(n){const t=l[n];if(t)for(const e of t)try{const t=e();t instanceof Promise&&t.catch(()=>{console.warn(`Preload for intent "${n}" failed`)})}catch(t){console.warn(`Preload for intent "${n}" sync error`,t)}}const N={};function y(n,t){const e=function(n){if(N[n])return N[n];const t=[];return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"")),N[n]=t,t}(n);if(!t)return{};if(Array.isArray(t)){const n={};return e.forEach((e,r)=>{void 0===t[r]&&console.warn(`Missing param "${e}"`),n[e]=t[r]}),n}return"object"==typeof t?t:1===e.length?{[e[0]]:t}:{}}function A(n,t){return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>{const r=t[e];return void 0!==r?encodeURIComponent(r):""})}function w(n,t,e){const r=s[n];if(!r)return"";return A(r,y(r,t))+I(e)}const v={};function R(n){if(v[n])return v[n];const t=[],e=new RegExp("^"+n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"([^/]+)"))+"$");return v[n]={regex:e,keys:t},v[n]}function _(n){const[t,e]=n.split("?"),r=function(n){if(!n)return{};const t=new URLSearchParams(n),e={};return t.forEach((n,t)=>{e[t]?Array.isArray(e[t])?e[t].push(n):e[t]=[e[t],n]:e[t]=n}),e}(e);for(const n in s){const e=s[n],{regex:o,keys:i}=R(e),c=t.match(o);if(!c)continue;const a={};return i.forEach((n,t)=>{a[n]=decodeURIComponent(c[t+1])}),{intent:n,params:a,query:r}}return null}function q(){const n=e.useLocation(),t=_(n.pathname),r=new URLSearchParams(n.search),o={};return r.forEach((n,t)=>{o[t]=n}),{intent:t?.intent??null,params:t?.params??{},query:o}}function $({navigate:n}){const t=e.useNavigate();return r.useEffect(()=>{h(n??t)},[n,t]),null}exports.IntentLink=function({intent:n,params:r,query:o,scrollTop:i,prefetch:s,onClick:c,onMouseEnter:a,onTouchStart:u,...f}){const l=w(n,r,o);return l?t.jsx(e.Link,{to:l,onClick:n=>{i&&window.scrollTo({top:0}),c?.(n)},onMouseEnter:t=>{s&&x(n),a?.(t)},onTouchStart:t=>{s&&x(n),u?.(t)},...f}):(console.warn("IntentLink: unknown intent",n),t.jsx(t.Fragment,{children:f.children}))},exports.IntentRoute=function({intent:n,component:e,fallback:r=null,loading:o,guard:i}){const s=q();return s?s.intent!==n?null:i&&!i(s)?t.jsx(t.Fragment,{children:r}):t.jsx(e,{...s}):o?t.jsx(t.Fragment,{children:o}):null},exports.IntentRouter=function({children:n}){return t.jsxs(e.BrowserRouter,{children:[t.jsx($,{}),n]})},exports.RouterBinder=$,exports.addIntentGuard=function(n){u.push(n)},exports.addIntentGuardFor=function(n,t){f[n]||(f[n]=[]),f[n].push(t)},exports.addIntentPreload=function(n,t){l[n]||(l[n]=[]),l[n].push(t)},exports.bindNavigate=h,exports.createIntentRouter=function(n){s=n,m("intent map loaded",n)},exports.generatePathFromIntent=w,exports.navigateIntent=g,exports.navigateIntentObject=function(n,t){const{params:e,query:r,options:s}=t||{};m("emit",n,{params:e,query:r});const c={intent:n,params:e,query:r,...s?{options:s}:{}};o.$emit("INTENT_NAVIGATE",c),i&&i.$emit("INTENT_NAVIGATE",c)},exports.preloadIntent=x,exports.resolveIntentFromUrl=_,exports.setFallbackPath=function(n){p=n},exports.setSharedBus=function(n){i=n,i.$onMultiple("INTENT_NAVIGATE",E)},exports.useIntentRouter=q,exports.useNavigateIntent=function(n){const t=e.useNavigate();return r.useEffect(()=>{h(n??t)},[n,t]),g};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LinkProps } from "react-router-dom";
|
|
2
2
|
type Props = {
|
|
3
3
|
intent: string;
|
|
4
4
|
params?: any;
|
|
@@ -6,5 +6,5 @@ type Props = {
|
|
|
6
6
|
scrollTop?: boolean;
|
|
7
7
|
prefetch?: boolean;
|
|
8
8
|
} & Omit<LinkProps, "to" | "prefetch">;
|
|
9
|
-
export declare function IntentLink({ intent, params, query, scrollTop, prefetch, onClick, onMouseEnter, onTouchStart, ...
|
|
9
|
+
export declare function IntentLink({ intent, params, query, scrollTop, prefetch, onClick, onMouseEnter, onTouchStart, ...props }: Props): JSX.Element;
|
|
10
10
|
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { type IntentData } from "./useIntentRouter";
|
|
1
2
|
type Props = {
|
|
2
3
|
intent: string;
|
|
3
4
|
component: React.ComponentType<any>;
|
|
4
5
|
fallback?: React.ReactNode;
|
|
5
6
|
loading?: React.ReactNode;
|
|
6
|
-
guard?: (data:
|
|
7
|
+
guard?: (data: IntentData) => boolean;
|
|
7
8
|
};
|
|
8
9
|
export declare function IntentRoute({ intent, component: Component, fallback, loading, guard, }: Props): JSX.Element | null;
|
|
9
10
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { navigateIntent } from "../core/intentCore";
|
|
2
|
-
export declare function useNavigateIntent(): typeof navigateIntent;
|
|
2
|
+
export declare function useNavigateIntent(navigate?: any): typeof navigateIntent;
|