intentx-react-router 0.1.0 → 0.1.2
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 +110 -9
- package/build/core/index.d.ts +0 -1
- package/build/index.esm.js +1 -2
- package/build/index.js +1 -2
- package/build/router/RouterBinder.d.ts +1 -0
- package/build/router/index.d.ts +2 -0
- package/package.json +9 -5
- package/build/index.esm.js.map +0 -1
- package/build/index.js.map +0 -1
- /package/build/{core → router}/IntentRoute.d.ts +0 -0
package/README.md
CHANGED
|
@@ -39,14 +39,22 @@ navigateIntent("edit-user", 42)
|
|
|
39
39
|
# Installation
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
npm install intentx-react-router eventbus-z react-router
|
|
42
|
+
npm install intentx-react-router eventbus-z react-router@^7 react-router-dom@^7
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
## Recommended Versions
|
|
46
|
+
|
|
47
|
+
- react: >=18
|
|
48
|
+
- react-dom: >=18
|
|
49
|
+
- react-router: >=7
|
|
50
|
+
- react-router-dom: >=7
|
|
51
|
+
- eventbus-z: ^2.4.0
|
|
52
|
+
|
|
45
53
|
---
|
|
46
54
|
|
|
47
55
|
# Basic Setup
|
|
48
56
|
|
|
49
|
-
## Define intents
|
|
57
|
+
## 1. Define intents
|
|
50
58
|
|
|
51
59
|
``` ts
|
|
52
60
|
import { createIntentRouter } from "intentx-react-router"
|
|
@@ -54,31 +62,124 @@ import { createIntentRouter } from "intentx-react-router"
|
|
|
54
62
|
createIntentRouter({
|
|
55
63
|
"view-user": "/users/:userId/name/:page",
|
|
56
64
|
"edit-user": "/users/:userId/edit",
|
|
57
|
-
"open-cart": "/cart",
|
|
58
65
|
"checkout": "/checkout"
|
|
59
66
|
})
|
|
60
67
|
```
|
|
61
68
|
|
|
62
69
|
---
|
|
63
70
|
|
|
64
|
-
## Bind React Router navigate
|
|
71
|
+
## 2. Bind React Router navigate
|
|
65
72
|
|
|
66
73
|
``` ts
|
|
74
|
+
import React from "react"
|
|
75
|
+
import { useNavigate } from "react-router-dom"
|
|
67
76
|
import { bindNavigate } from "intentx-react-router"
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
function RouterBinder() {
|
|
78
|
+
export function RouterBinder() {
|
|
72
79
|
const navigate = useNavigate()
|
|
73
|
-
|
|
74
80
|
bindNavigate(navigate)
|
|
75
|
-
|
|
76
81
|
return null
|
|
77
82
|
}
|
|
78
83
|
```
|
|
79
84
|
|
|
80
85
|
---
|
|
81
86
|
|
|
87
|
+
## 3. IntentLink
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import React from "react"
|
|
91
|
+
import { Link } from "react-router-dom"
|
|
92
|
+
import { generatePathFromIntent } from "intentx-react-router"
|
|
93
|
+
|
|
94
|
+
export function IntentLink({ intent, params, query, children }) {
|
|
95
|
+
let path = generatePathFromIntent(intent, params)
|
|
96
|
+
if (query) {
|
|
97
|
+
const qs = new URLSearchParams(query).toString()
|
|
98
|
+
if (qs) path += "?" + qs
|
|
99
|
+
}
|
|
100
|
+
return <Link to={path}>{children}</Link>
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 4. IntentRoute
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import React from "react"
|
|
112
|
+
import { Route } from "react-router-dom"
|
|
113
|
+
import { generatePathFromIntent } from "intentx-react-router"
|
|
114
|
+
|
|
115
|
+
export function IntentRoute({ intent, component: Component }) {
|
|
116
|
+
const path = generatePathFromIntent(intent)
|
|
117
|
+
return <Route path={path} render={(props) => <Component {...props} />} />
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 5. Use in App
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import React from "react"
|
|
127
|
+
import { BrowserRouter, Switch } from "react-router-dom"
|
|
128
|
+
import { RouterBinder, IntentLink, IntentRoute } from "./router"
|
|
129
|
+
|
|
130
|
+
import { UserPage } from "./pages/UserPage"
|
|
131
|
+
import { EditUserPage } from "./pages/EditUserPage"
|
|
132
|
+
import { CheckoutPage } from "./pages/CheckoutPage"
|
|
133
|
+
|
|
134
|
+
export default function App() {
|
|
135
|
+
return (
|
|
136
|
+
<BrowserRouter>
|
|
137
|
+
<RouterBinder />
|
|
138
|
+
|
|
139
|
+
<nav style={{ marginBottom: 20 }}>
|
|
140
|
+
<IntentLink intent="view-user" params={[1, 2]}>View User</IntentLink>{" "}
|
|
141
|
+
| <IntentLink intent="edit-user" params={1}>Edit User</IntentLink>{" "}
|
|
142
|
+
| <IntentLink intent="checkout">Checkout</IntentLink>
|
|
143
|
+
</nav>
|
|
144
|
+
|
|
145
|
+
<Switch>
|
|
146
|
+
<IntentRoute intent="view-user" component={UserPage} />
|
|
147
|
+
<IntentRoute intent="edit-user" component={EditUserPage} />
|
|
148
|
+
<IntentRoute intent="checkout" component={CheckoutPage} />
|
|
149
|
+
</Switch>
|
|
150
|
+
</BrowserRouter>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 6. useIntent Hook
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { useLocation } from "react-router-dom"
|
|
161
|
+
import { resolveIntentFromUrl } from "intentx-react-router"
|
|
162
|
+
|
|
163
|
+
export function useIntent() {
|
|
164
|
+
const location = useLocation()
|
|
165
|
+
const resolved = resolveIntentFromUrl(location.pathname)
|
|
166
|
+
|
|
167
|
+
const searchParams = new URLSearchParams(location.search)
|
|
168
|
+
const query = {}
|
|
169
|
+
searchParams.forEach((value, key) => {
|
|
170
|
+
query[key] = value
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
intent: resolved?.intent ?? null,
|
|
175
|
+
params: resolved?.params ?? {},
|
|
176
|
+
query
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
82
183
|
# Navigation
|
|
83
184
|
|
|
84
185
|
## Object params
|
package/build/core/index.d.ts
CHANGED
package/build/index.esm.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import{createEventBus as n}from"eventbus-z";import{jsx as t}from"react/jsx-runtime";import{
|
|
2
|
-
//# sourceMappingURL=index.esm.js.map
|
|
1
|
+
import{createEventBus as n}from"eventbus-z";import{jsx as t}from"react/jsx-runtime";import{Link as r,useLocation as o,useNavigate as e}from"react-router-dom";import{useEffect as i}from"react";const c=n(),u="INTENT_NAVIGATE";let s={},f=null,a=!1;const l=[],p={},m={};function h(n){s=n}function d(n){f=n,a||(c.$onMultiple(u,E),a=!0)}function v(n,t){c.$emit(u,{intent:n,params:t})}function g(n){l.push(n)}function y(n,t){p[n]||(p[n]=[]),p[n].push(t)}function A(n,t){m[n]||(m[n]=[]),m[n].push(t)}function w(n){z(n)}function E(n){const t=s[n.intent];if(!t)return void console.warn("Unknown intent:",n.intent);const r=$(t,n.params);for(const t of l){const o=t(n.intent,r);if(!1===o)return;if("string"==typeof o)return void(null==f||f(o))}const o=p[n.intent]||[];for(const t of o){const o=t(n.intent,r);if(!1===o)return;if("string"==typeof o)return void(null==f||f(o))}z(n.intent);const e=_(t,r);null==f||f(e)}function z(n){const t=m[n];if(t)for(const n of t)try{const t=n();t instanceof Promise&&t.catch(()=>{})}catch{}}function $(n,t){const r=function(n){const t=[];return n.replace(/:([A-Za-z0-9_]+)/g,(n,r)=>(t.push(r),"")),t}(n);if(!t)return{};if(Array.isArray(t)){const n={};return r.forEach((r,o)=>{void 0===t[o]&&console.warn(`Missing param "${r}"`),n[r]=t[o]}),n}return"object"==typeof t?t:1===r.length?{[r[0]]:t}:{}}function _(n,t){return n.replace(/:([A-Za-z0-9_]+)/g,(n,r)=>{var o;return null!==(o=t[r])&&void 0!==o?o:""})}function x(n,t){const r=s[n];if(!r)return"";return _(r,$(r,t))}function N(n){for(const t in s){const r=s[t],o=[],e=new RegExp("^"+r.replace(/:([A-Za-z0-9_]+)/g,(n,t)=>(o.push(t),"([^/]+)"))+"$"),i=n.match(e);if(!i)continue;const c={};return o.forEach((n,t)=>{c[n]=i[t+1]}),{intent:t,params:c}}return null}function P({intent:n,params:o,query:e,children:i}){let c=x(n,o);if(e){const n=new URLSearchParams(e).toString();n&&(c+="?"+n)}return t(r,{to:c,children:i})}function R(){var n,t;const r=o(),e=N(r.pathname),i=new URLSearchParams(r.search),c={};return i.forEach((n,t)=>{c[t]=n}),{intent:null!==(n=null==e?void 0:e.intent)&&void 0!==n?n:null,params:null!==(t=null==e?void 0:e.params)&&void 0!==t?t:{},query:c}}function S({intent:n,component:r}){const o=R();return o.intent!==n?null:t(r,{...o})}function T(n){const t=e();return d(n||t),null}function U(){const n=e();return i(()=>{d(n)},[n]),v}export{P as IntentLink,S as IntentRoute,T as RouterBinder,g as addIntentGuard,y as addIntentGuardFor,A as addIntentPreload,d as bindNavigate,h as createIntentRouter,x as generatePathFromIntent,v as navigateIntent,w as preloadIntent,N as resolveIntentFromUrl,R as useIntent,U as useNavigateIntent};
|
package/build/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use strict";var n=require("eventbus-z"),t=require("react/jsx-runtime"),e=require("react-router"),r=require("react");const o=n.createEventBus(),i="INTENT_NAVIGATE";let u={},s=null,c=!1;const a=[],f={},l={};function p(n){s=n,c||(o.$onMultiple(i,
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
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(),i="INTENT_NAVIGATE";let u={},s=null,c=!1;const a=[],f={},l={};function p(n){s=n,c||(o.$onMultiple(i,v),c=!0)}function d(n,t){o.$emit(i,{intent:n,params:t})}function v(n){const t=u[n.intent];if(!t)return void console.warn("Unknown intent:",n.intent);const e=m(t,n.params);for(const t of a){const r=t(n.intent,e);if(!1===r)return;if("string"==typeof r)return void(null==s||s(r))}const r=f[n.intent]||[];for(const t of r){const r=t(n.intent,e);if(!1===r)return;if("string"==typeof r)return void(null==s||s(r))}h(n.intent);const o=x(t,e);null==s||s(o)}function h(n){const t=l[n];if(t)for(const n of t)try{const t=n();t instanceof Promise&&t.catch(()=>{})}catch{}}function m(n,t){const e=function(n){const t=[];return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"")),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 x(n,t){return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>{var r;return null!==(r=t[e])&&void 0!==r?r:""})}function g(n,t){const e=u[n];if(!e)return"";return x(e,m(e,t))}function I(n){for(const t in u){const e=u[t],r=[],o=new RegExp("^"+e.replace(/:([A-Za-z0-9_]+)/g,(n,t)=>(r.push(t),"([^/]+)"))+"$"),i=n.match(o);if(!i)continue;const s={};return r.forEach((n,t)=>{s[n]=i[t+1]}),{intent:t,params:s}}return null}function y(){var n,t;const r=e.useLocation(),o=I(r.pathname),i=new URLSearchParams(r.search),u={};return i.forEach((n,t)=>{u[t]=n}),{intent:null!==(n=null==o?void 0:o.intent)&&void 0!==n?n:null,params:null!==(t=null==o?void 0:o.params)&&void 0!==t?t:{},query:u}}exports.IntentLink=function({intent:n,params:r,query:o,children:i}){let u=g(n,r);if(o){const n=new URLSearchParams(o).toString();n&&(u+="?"+n)}return t.jsx(e.Link,{to:u,children:i})},exports.IntentRoute=function({intent:n,component:e}){const r=y();return r.intent!==n?null:t.jsx(e,{...r})},exports.RouterBinder=function(n){const t=e.useNavigate();return p(n||t),null},exports.addIntentGuard=function(n){a.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=p,exports.createIntentRouter=function(n){u=n},exports.generatePathFromIntent=g,exports.navigateIntent=d,exports.preloadIntent=function(n){h(n)},exports.resolveIntentFromUrl=I,exports.useIntent=y,exports.useNavigateIntent=function(){const n=e.useNavigate();return r.useEffect(()=>{p(n)},[n]),d};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function RouterBinder(navigate?: any): null;
|
package/build/router/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intentx-react-router",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Intent-based routing for React. Navigate by intent instead of URLs.",
|
|
5
5
|
"author": "Delpi.Kye",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
|
|
8
8
|
"type": "module",
|
|
9
|
-
"main": "./build/index.
|
|
9
|
+
"main": "./build/index.js",
|
|
10
10
|
"module": "./build/index.esm.js",
|
|
11
11
|
"types": "./build/index.d.ts",
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
14
|
"types": "./build/index.d.ts",
|
|
15
15
|
"import": "./build/index.esm.js",
|
|
16
|
-
"require": "./build/index.
|
|
16
|
+
"require": "./build/index.js"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
"repository": {
|
|
36
36
|
"type": "git",
|
|
37
|
-
"url": "https://github.com/delpikye-v/intentx-
|
|
37
|
+
"url": "https://github.com/delpikye-v/intentx-react-router.git"
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://github.com/delpikye-v/intentx-react-router#readme",
|
|
40
40
|
"bugs": {
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"react": ">=18",
|
|
58
|
-
"react-
|
|
58
|
+
"react-dom": ">=18",
|
|
59
|
+
"react-router": "^7.0.0",
|
|
60
|
+
"react-router-dom": "^7.0.0"
|
|
59
61
|
},
|
|
60
62
|
"dependencies": {
|
|
61
63
|
"eventbus-z": "^2.4.0"
|
|
@@ -68,6 +70,8 @@
|
|
|
68
70
|
"@types/react-dom": "^18.0.0",
|
|
69
71
|
"react": "^18.0.0",
|
|
70
72
|
"react-dom": "^18.0.0",
|
|
73
|
+
"react-router": "^7.13.1",
|
|
74
|
+
"react-router-dom": "^7.13.1",
|
|
71
75
|
"rimraf": "^5.0.5",
|
|
72
76
|
"rollup": "^3.29.4",
|
|
73
77
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
package/build/index.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/build/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
File without changes
|