intentx-react-router 1.0.3 → 1.1.0-z

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
@@ -1,13 +1,12 @@
1
1
  # 🕹️ intentx-react-router
2
2
 
3
- [![NPM](https://img.shields.io/npm/v/intentx-react-router.svg)](https://www.npmjs.com/package/intentx-react-router) ![Downloads](https://img.shields.io/npm/dt/intentx-react-router.svg)
3
+ [![NPM](https://img.shields.io/npm/v/intentx-react-router.svg)](https://www.npmjs.com/package/intentx-react-router) ![Downloads](https://img.shields.io/npm/dt/intentx-react-router.svg) ![Bundle Size](https://img.shields.io/bundlephobia/minzip/intentx-react-router)
4
4
 
5
- <a href="https://codesandbox.io/p/sandbox/q8gg5s" target="_blank">LIVE EXAMPLE</a>
5
+ <a href="https://codesandbox.io/p/sandbox/7x3hqr" target="_blank">LIVE EXAMPLE</a>
6
6
 
7
- Intentbased navigation layer for React applications.
7
+ Intent-based navigation layer for React applications.
8
8
 
9
- Built on top of **React Router** and designed to work nicely with
10
- event‑driven architectures like **eventbus-z**.
9
+ Built on top of React Router and designed for **domain-driven and event-driven navigation**.
11
10
 
12
11
  > Navigate by **intent**, not by URL.
13
12
 
@@ -23,6 +22,7 @@ navigate("/users/42/edit")
23
22
  Intent Router:
24
23
  ```ts
25
24
  navigateIntent("edit-user", 42)
25
+ // → /users/42/edit
26
26
  ```
27
27
 
28
28
  <b>Benefits:</b>
@@ -32,7 +32,6 @@ navigateIntent("edit-user", 42)
32
32
  - 🔧 Easy URL refactor
33
33
  - 🧩 Micro‑frontend friendly
34
34
  - 📡 Event‑driven navigation support
35
- - 🪶 Lightweight core (\~200 lines)
36
35
 
37
36
  ---
38
37
 
@@ -51,44 +50,85 @@ npm install intentx-react-router react-router@^7 react-router-dom@^7
51
50
 
52
51
  ---
53
52
 
53
+ # Quick Start
54
+
55
+ ```tsx
56
+ import { createIntentRouter, navigateIntent } from "intentx-react-router"
57
+
58
+ createIntentRouter({
59
+ "view-user": "/users/:id",
60
+ "edit-user": "/users/:id/edit"
61
+ })
62
+
63
+ // navigate by intent
64
+ navigateIntent("view-user", 42)
65
+ ```
66
+
67
+ Result:
68
+ ```ts
69
+ /users/42
70
+ ```
71
+
72
+ ---
73
+
54
74
  # Basic Setup
55
75
 
56
- ## 1. Define intents
76
+ ## 1️⃣ Define intents
57
77
 
58
78
  ``` ts
59
- import { createIntentRouter } from "intentx-react-router"
79
+ import { createIntentRouter, NavigateFn } from "intentx-react-router"
60
80
 
61
81
  createIntentRouter({
62
- "view-user": "/users/:userId/name/:page",
82
+ "view-user": {
83
+ path: "/users/:userId/name/:page",
84
+ meta: {
85
+ title: "User Profile"
86
+ }
87
+ },
63
88
  "edit-user": "/users/:userId/edit",
64
89
  "checkout": "/checkout"
65
90
  })
91
+
92
+ // Bind navigate in App
93
+ export function bindRouterNavigate(navigate: NavigateFn) {
94
+ bindNavigate(navigate);
95
+ }
96
+
66
97
  ```
67
98
 
68
99
  ---
69
100
 
70
- ## 2. Bind React Router navigate
101
+ ## 2️⃣ Bind React Router
71
102
 
72
103
  ``` ts
73
104
  import React from "react"
74
105
  import { useNavigate } from "react-router-dom"
75
- import { bindNavigate } from "intentx-react-router"
106
+ import { bindRouterNavigate } from "./router"
76
107
 
77
108
  export function RouterBinder() {
78
- const navigate = useNavigate()
79
- bindNavigate(navigate)
80
- return null
109
+ const navigate = useNavigate();
110
+
111
+ React.useEffect(() => {
112
+ // require
113
+ bindRouterNavigate(navigate);
114
+ }, [navigate]);
115
+
116
+ return null;
81
117
  }
82
118
  ```
83
119
  ---
84
120
 
85
- ## 3. Use in App
121
+ ## 3️⃣ Use in App
86
122
 
87
123
  ```ts
88
124
  import React from "react"
89
125
  import { BrowserRouter, Routes } from "react-router-dom"
90
126
  import { IntentLink, IntentRoute } from "intentx-react-router"
127
+
91
128
  import { RouterBinder } from "./router"
129
+ // or
130
+ // import "./router"
131
+ // import { RouterBinder } from "intentx-react-router"
92
132
 
93
133
  import { UserPage } from "./pages/UserPage"
94
134
  import { EditUserPage } from "./pages/EditUserPage"
@@ -115,25 +155,127 @@ export default function App() {
115
155
  }
116
156
  ```
117
157
 
118
- ## 4. IntentRouter
158
+ IntentRoute automatically maps the intent path to a React Router route.
159
+
160
+ ---
161
+
162
+ # Modular Router Setup
163
+ ## 1️⃣ Define intents
164
+
165
+ ```ts
166
+ // intents/user-intents.ts
167
+ export const userIntents = {
168
+ home: "/",
169
+ userProfile: "/users/:id",
170
+ settings: "/settings"
171
+ }
172
+
173
+ // intents/cart-intents.ts
174
+ export const cartIntents = {
175
+ cart: "/cart",
176
+ checkout: "/checkout"
177
+ }
178
+ ```
179
+
180
+ ---
181
+
182
+ ## 2️⃣ Setup router
119
183
 
120
184
  ```ts
121
- import { IntentRouter } from "intentx-react-router"
122
- import { Routes } from "react-router-dom"
185
+ // router/setupRouter.ts
186
+
187
+ import { setupIntentRouter } from "intentx-react-router"
188
+
189
+ import { userIntents } from "../intents/user-intents"
190
+ import { cartIntents } from "../intents/cart-intents"
191
+
192
+ export function setupRouter(navigate) {
193
+ setupIntentRouter({
194
+ intents: [
195
+ userIntents,
196
+ cartIntents
197
+ ],
198
+
199
+ guards: [
200
+ (intent, params) => {
201
+ console.log("Navigate:", intent, params)
202
+ }
203
+ ],
204
+
205
+ intentGuards: {
206
+ checkout() {
207
+ const cartReady = true
208
+
209
+ if (!cartReady) {
210
+ return "/cart"
211
+ }
212
+ }
213
+ },
214
+
215
+ navigate
216
+ })
217
+ }
218
+ ```
219
+
220
+ ---
221
+
222
+ ## 3️⃣ Bind router to React Router
223
+
224
+ ```ts
225
+ // App.tsx
226
+
227
+ import { RouterBinder } from "intentx-react-router"
228
+ import { setupRouter } from "./router/setupRouter"
229
+
230
+ setupRouter()
123
231
 
124
232
  export default function App() {
125
233
  return (
126
- <IntentRouter>
127
- <Routes>
128
- <IntentRoute intent="checkout" component={CheckoutPage} />
129
- </Routes>
130
- </IntentRouter>
234
+ <>
235
+ <RouterBinder />
236
+
237
+ {/* your routes */}
238
+ </>
131
239
  )
132
240
  }
133
241
  ```
134
242
 
135
243
  ---
136
244
 
245
+ ## 4️⃣ Navigate using intent
246
+
247
+ ```ts
248
+ import { navigateIntent } from "intentx-react-router"
249
+
250
+ navigateIntent("userProfile", { id: 42 })
251
+
252
+ navigateIntent("checkout")
253
+ ```
254
+
255
+ Generated URL:
256
+
257
+ ```ts
258
+ /users/42
259
+ /checkout
260
+ ```
261
+
262
+ ---
263
+
264
+ ## 5️⃣ Object navigation
265
+ ```ts
266
+ navigateIntentObject("userProfile", {
267
+ params: { id: 10 },
268
+ query: { tab: "posts" }
269
+ })
270
+ ```
271
+
272
+ Result:
273
+ ```ts
274
+ /users/10?tab=posts
275
+ ```
276
+
277
+ ---
278
+
137
279
  # Navigation
138
280
 
139
281
  ## Object params
@@ -343,7 +485,7 @@ import { IntentRoute } from "intentx-react-router"
343
485
 
344
486
  # Guards
345
487
 
346
- Global guard:
488
+ ## Global guard
347
489
 
348
490
  ```ts
349
491
  addIntentGuard((intent, params) => {
@@ -355,7 +497,7 @@ addIntentGuard((intent, params) => {
355
497
  })
356
498
  ```
357
499
 
358
- Perintent guard:
500
+ ## Per-intent guard
359
501
 
360
502
  ```ts
361
503
  addIntentGuardFor("checkout", () => {
@@ -369,6 +511,38 @@ addIntentGuardFor("checkout", () => {
369
511
 
370
512
  ---
371
513
 
514
+ ## Guard inside intent
515
+
516
+ You can attach guards directly to intents.
517
+
518
+ ```ts
519
+ createIntentRouter({
520
+
521
+ "checkout": {
522
+ path: "/checkout",
523
+ guard: () => {
524
+ if (!isLoggedIn()) {
525
+ return "/login"
526
+ }
527
+ }
528
+ },
529
+
530
+ "admin": {
531
+ path: "/admin",
532
+ guard: () => {
533
+ if (!isAdmin()) {
534
+ return "/forbidden"
535
+ }
536
+ }
537
+ }
538
+
539
+ })
540
+ ```
541
+
542
+ This keeps route logic close to its definition.
543
+
544
+ ---
545
+
372
546
  # Preload
373
547
 
374
548
  Preload logic before navigation.
@@ -472,17 +646,257 @@ This allows:
472
646
 
473
647
  ---
474
648
 
649
+ # Why not just use React Router?
650
+
651
+ :contentReference[oaicite:1]{index=1} is an excellent routing library and intentx-react-router **does not replace it**.
652
+
653
+ Instead, it adds a **navigation abstraction layer** on top of React Router.
654
+
655
+ React Router focuses on **URL-driven navigation**, while intentx-react-router focuses on **intent-driven navigation**.
656
+
657
+ ---
658
+
659
+ ## React Router navigation
660
+
661
+ In React Router, navigation is usually done by URLs:
662
+
663
+ ```ts
664
+ navigate("/users/42/edit")
665
+ ```
666
+
667
+ The application logic becomes tied to the URL structure.
668
+
669
+ If the URL changes later:
670
+
671
+ ```text
672
+ /users/:id/edit
673
+
674
+ /profile/:id/edit
675
+ ```
676
+
677
+ You must update navigation code across the app.
678
+
679
+ ---
680
+
681
+ ## Intent navigation
682
+
683
+ intentx-react-router introduces intent-based navigation.
684
+
685
+ Instead of navigating by URL:
686
+
687
+ ```ts
688
+ navigateIntent("edit-user", 42)
689
+ ```
690
+
691
+ The router resolves the intent into a URL:
692
+
693
+ ```text
694
+ /edit-user → /users/42/edit
695
+ ```
696
+
697
+ If the URL changes later:
698
+
699
+ ```text
700
+ /users/:id/edit
701
+
702
+ /profile/:id/edit
703
+ ```
704
+
705
+ You only update the router definition:
706
+
707
+ ```ts
708
+ createIntentRouter({
709
+ "edit-user": "/profile/:id/edit"
710
+ })
711
+ ```
712
+
713
+ ---
714
+
475
715
  # Comparison
476
716
 
477
- | Criteria | intent-router | React Router |
478
- |-------------------------|---------------|--------------|
479
- | Intent-based navigation | ✅ | ❌ |
480
- | URL refactor safety | ✅ | ⚠️ |
481
- | Event-driven navigation | ✅ | ❌ |
482
- | Micro-frontend friendly | ✅ | ⚠️ |
483
- | Reverse routing | | |
484
- | Type-safe intent params | ✅ | ⚠️ |
485
- | Query support | ✅ | ⚠️ |
717
+ intentx-react-router focuses on **intent-driven navigation** rather than URL-driven navigation.
718
+
719
+ Instead of navigating by path strings, you navigate by **domain intent**.
720
+
721
+ ## vs React Router
722
+
723
+ | Criteria | intentx-react-router | React Router |
724
+ |-------------------------|----------------------|--------------|
725
+ | Intent-based navigation | ✅ | |
726
+ | URL refactor safety | ✅ | ⚠️ |
727
+ | Event-driven navigation | ✅ | ❌ |
728
+ | Micro-frontend friendly | ✅ | ⚠️ |
729
+ | Reverse routing | ✅ | ❌ |
730
+ | Type-safe intent params | ✅ | ⚠️ |
731
+ | Query support | ✅ | ⚠️ |
732
+
733
+
734
+ <br />
735
+
736
+ ```ts
737
+ // React Router:
738
+ navigate("/users/42/edit")
739
+
740
+ // intentx-react-router:
741
+ navigateIntent("edit-user", 42)
742
+ ```
743
+
744
+ ---
745
+
746
+ ## vs TanStack Router
747
+
748
+ :contentReference[oaicite:4]{index=4} is a powerful type-safe router with a full route tree and data loading system.
749
+
750
+ | Criteria | intentx-react-router | TanStack Router |
751
+ | ----------------------- | -------------------- | --------------- |
752
+ | Intent navigation | ✅ | ❌ |
753
+ | Route tree system | ❌ | ✅ |
754
+ | Data loaders | ❌ | ✅ |
755
+ | Reverse routing | ✅ | ⚠️ |
756
+ | Guards | ✅ | ⚠️ |
757
+ | Event-driven navigation | ✅ | ❌ |
758
+ | Micro-frontend friendly | ✅ | ⚠️ |
759
+
760
+ <br />
761
+
762
+ Intent Router is designed to be minimal and flexible, especially for event-driven or micro-frontend architectures.
763
+
764
+ ---
765
+
766
+ ## vs Remix Router
767
+
768
+ :contentReference[oaicite:5]{index=5} provides a full-stack routing system with loaders and server rendering.
769
+
770
+ | Criteria | intentx-react-router | Remix |
771
+ | ------------------------- | --------------------- | -----------|
772
+ | Intent navigation | ✅ | ❌ |
773
+ | Reverse routing | ✅ | ❌ |
774
+ | Guards | ✅ | ⚠️ loaders |
775
+ | Event-driven navigation | ✅ | ❌ |
776
+ | Server loaders | ❌ | ✅ |
777
+ | Full-stack routing | ❌ | ✅ |
778
+ | Lightweight client router | ✅ | ❌ |
779
+
780
+
781
+ <br />
782
+
783
+ Remix focuses on server-first routing, while intentx-react-router focuses on client-side intent navigation.
784
+
785
+ ---
786
+
787
+ # Route Meta
788
+
789
+ You can attach metadata to intents.
790
+
791
+ This is useful for:
792
+
793
+ - auth
794
+ - role permission
795
+ - page title
796
+ - layout selection
797
+ - analytics
798
+
799
+ ---
800
+
801
+ ## Define meta
802
+
803
+ ```ts
804
+ createIntentRouter({
805
+
806
+ "home": "/",
807
+
808
+ "dashboard": {
809
+ path: "/dashboard",
810
+ meta: {
811
+ title: "Dashboard",
812
+ auth: true
813
+ }
814
+ },
815
+
816
+ "admin": {
817
+ path: "/admin",
818
+ meta: {
819
+ title: "Admin Panel",
820
+ auth: true,
821
+ role: "admin"
822
+ }
823
+ }
824
+
825
+ })
826
+ ```
827
+
828
+ ---
829
+
830
+ ## Read meta
831
+
832
+ ```ts
833
+ import { getIntentMeta } from "intentx-react-router"
834
+
835
+ const meta = getIntentMeta("admin")
836
+
837
+ console.log(meta)
838
+ ```
839
+
840
+ Result:
841
+
842
+ ```ts
843
+ {
844
+ title: "Admin Panel",
845
+ auth: true,
846
+ role: "admin"
847
+ }
848
+ ```
849
+
850
+ ---
851
+
852
+ ## Meta with guards
853
+
854
+ Meta works perfectly with guards.
855
+
856
+ ```ts
857
+ addIntentGuard((intent) => {
858
+
859
+ const meta = getIntentMeta(intent)
860
+
861
+ if (meta?.auth && !isLoggedIn()) {
862
+ return "/login"
863
+ }
864
+
865
+ })
866
+ ```
867
+
868
+ Example with role protection:
869
+
870
+ ```ts
871
+ addIntentGuard((intent) => {
872
+
873
+ const meta = getIntentMeta(intent)
874
+
875
+ if (meta?.role === "admin" && !isAdmin()) {
876
+ return "/forbidden"
877
+ }
878
+
879
+ })
880
+ ```
881
+
882
+ ---
883
+
884
+ ## Meta in React
885
+
886
+ You can also read meta inside components.
887
+
888
+ ```ts
889
+ import { useIntentRouter, getIntentMeta } from "intentx-react-router"
890
+
891
+ function PageHeader() {
892
+
893
+ const { intent } = useIntentRouter()
894
+
895
+ const meta = getIntentMeta(intent)
896
+
897
+ return <h1>{meta?.title}</h1>
898
+ }
899
+ ```
486
900
 
487
901
  ---
488
902
 
@@ -490,16 +904,26 @@ This allows:
490
904
 
491
905
  ```text
492
906
  Component
493
-
907
+
494
908
  navigateIntent()
495
-
496
- eventbus-z
497
-
909
+
498
910
  Intent Router
499
-
911
+
912
+ (eventbus-z optional)
913
+
500
914
  React Router navigate()
501
-
502
- URL
915
+
916
+ URL
917
+ ```
918
+
919
+ ---
920
+
921
+ # Debug Mode
922
+
923
+ Enable debug logs:
924
+
925
+ ```js
926
+ window.__INTENT_ROUTER_DEBUG__ = true
503
927
  ```
504
928
 
505
929
  ---
@@ -0,0 +1 @@
1
+ export declare const __DEV__: boolean;
@@ -1 +1,2 @@
1
1
  export * from "./intentCore";
2
+ export * from "./setupIntentRouter";
@@ -1,36 +1,49 @@
1
1
  import type { GlobalBus } from "eventbus-z";
2
+ export type IntentSchema = Record<string, {
3
+ params?: Record<string, any>;
4
+ query?: Record<string, any>;
5
+ }>;
6
+ export type NavigateOptions = {
7
+ replace?: boolean;
8
+ scrollTop?: boolean;
9
+ [key: string]: any;
10
+ };
2
11
  export type NavigateIntentOptions<P = any> = {
3
12
  params?: P | any[] | string | number;
4
13
  query?: Record<string, any>;
5
- options?: {
6
- replace?: boolean;
7
- scrollTop?: boolean;
8
- };
14
+ options?: NavigateOptions;
9
15
  };
10
- type IntentMap = Record<string, string>;
11
- type GuardFn = (intent: string, params: any) => boolean | string | void;
12
- type NavigateFn = (path: string, options?: {
13
- replace?: boolean;
14
- scrollTop?: boolean;
15
- }) => void;
16
+ export type NavigateFn = (path: string, options?: NavigateOptions) => void;
17
+ type GuardFn = ((intent: string, params: any) => boolean | string | void | Promise<boolean | string | void>);
16
18
  type PreloadFn = () => Promise<any> | void;
17
- export declare function createIntentRouter(map: IntentMap): void;
19
+ type IntentMeta = Record<string, any> | ((params: any) => Record<string, any>);
20
+ type IntentConfig = {
21
+ path: string;
22
+ meta?: IntentMeta;
23
+ guard?: GuardFn;
24
+ preload?: PreloadFn;
25
+ };
26
+ type IntentMapInput = Record<string, string | IntentConfig>;
27
+ export declare function registerIntents(map: IntentMapInput): void;
28
+ export declare function bootstrapRouter(): void;
29
+ export declare function createIntentRouter(map: IntentMapInput): void;
30
+ export declare function getIntentMeta(intent: string, params?: any): any;
31
+ export declare function setIntentMeta(intent: string, meta: IntentMeta): void;
18
32
  export declare function bindNavigate(fn: NavigateFn): void;
19
33
  export declare function setFallbackPath(path: string): void;
20
- export declare function navigateIntent<P = any>(intent: string, params?: P | any[] | string | number, query?: Record<string, any>, options?: {
21
- replace?: boolean;
22
- scrollTop?: boolean;
23
- }): void;
24
- export declare function navigateIntentObject<P = any>(intent: string, navigateIntentOption?: NavigateIntentOptions<P>): void;
34
+ export declare function warnRouterNotReady(intent: string): void;
35
+ export declare function navigateIntent(intent: string, params?: any, query?: Record<string, any>, options?: NavigateOptions): void;
36
+ export declare function navigateIntentObject<P = any>(intent: string, args?: NavigateIntentOptions<P>): void;
25
37
  export declare function addIntentGuard(fn: GuardFn): void;
26
38
  export declare function addIntentGuardFor(intent: string, fn: GuardFn): void;
27
39
  export declare function addIntentPreload(intent: string, fn: PreloadFn): void;
28
40
  export declare function preloadIntent(intent: string): void;
29
- export declare function generatePathFromIntent(intent: string, params?: Record<string, any> | any[] | string | number, query?: Record<string, any>): string;
41
+ export declare function generatePathFromIntent(intent: string, params?: any, query?: Record<string, any>): string;
30
42
  export declare function resolveIntentFromUrl(url: string): {
31
43
  intent: string;
32
44
  params: Record<string, any>;
33
45
  query: Record<string, any>;
34
46
  } | null;
47
+ export declare function syncIntentFromUrl(url: string): void;
35
48
  export declare function setSharedBus(externalBus: GlobalBus): void;
36
49
  export {};
@@ -0,0 +1,9 @@
1
+ type GuardFn = (intent: string, params: any) => any;
2
+ type SetupOptions = {
3
+ intents?: Record<string, any>[];
4
+ guards?: GuardFn[];
5
+ intentGuards?: Record<string, GuardFn>;
6
+ navigate?: (path: string, options?: any) => void;
7
+ };
8
+ export declare function setupIntentRouter({ intents, guards, intentGuards, navigate }?: SetupOptions): void;
9
+ export {};
@@ -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 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||(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};
1
+ import{createEventBus as n}from"eventbus-z";import{jsx as t,Fragment as e}from"react/jsx-runtime";import{Link as o,useLocation as r,useNavigate as i}from"react-router-dom";import{useEffect as c,useRef as a}from"react";const u="undefined"!=typeof window&&!0===window.__INTENT_ROUTER_DEBUG__,s=n();let f=null,l=null;const p="INTENT_NAVIGATE_DELPIK";let d={},h={},m={},y={},w=!1;const g=[],R={},E={};let _=null;const I=[];let v=!1;function T(...n){u&&console.log("[IntentRouter]",...n)}function $(n){if(!n)return"";const t=new URLSearchParams;for(const e in n){const o=n[e];null!=o&&(Array.isArray(o)?o.forEach(n=>t.append(e,String(n))):t.append(e,String(o)))}const e=t.toString();return e?`?${e}`:""}function A(n){for(const t in n){u&&d[t]&&console.warn(`[IntentRouter] duplicate intent "${t}"`);const e=n[t];"string"!=typeof e?(d[t]=e.path,e.meta&&(h[t]=e.meta),e.guard&&(m[t]=e.guard),e.preload&&(y[t]=e.preload)):d[t]=e}}function k(n){I.push(n),v&&A(n)}function U(){if(v)return;v=!0;const n={};I.length||console.warn("[IntentRouter] no intents registered");for(const t of I)Object.assign(n,t);A(n),T("intent map",d)}function P(n){k(n),U()}function S(n,t){const e=h[n];return e?"function"==typeof e?e(t):e:{}}function b(n,t){h[n]=t}function q(n){l&&l!==n&&u&&console.warn("IntentRouter navigate replaced"),l=n,w||(s.$onMultiple(p,D),w=!0)}function z(n){_=n}function M(n){u&&(l||console.warn(`[IntentRouter] navigateIntent("${n}") called before router initialized.\nMake sure <RouterBinder /> is mounted.`))}function x(n,t,e,o){M(n);const r={intent:n,params:t,query:e,options:o};T("emit",r),s.$emit(p,r),f&&f!==s&&f.$emit(p,r)}function K(n,t){const{params:e,query:o,options:r}=t||{};x(n,e,o,r)}function N(n){g.push(n)}function j(n,t){R[n]||(R[n]=[]),R[n].push(t)}function C(n,t){E[n]||(E[n]=[]),E[n].push(t)}function L(n){G(n)}async function D(n){if(n.__handled)return;n.__handled=!0;const t=d[n.intent];if(!t)return console.warn("Unknown intent:",n.intent),void(_&&l?.(_));const e=Z(t,n.params),o=S(n.intent,e);for(const t of g){const o=await t(n.intent,e);if(!1===o)return;if("string"==typeof o)return void l?.(o)}const r=R[n.intent]||[];for(const t of r){const o=await t(n.intent,e);if(!1===o)return;if("string"==typeof o)return void l?.(o)}const i=m[n.intent];if(i){const t=await i(n.intent,e);if(!1===t)return;if("string"==typeof t)return void l?.(t)}try{const t=y[n.intent]?.();t instanceof Promise&&t.catch(()=>console.warn(`Preload failed for ${n.intent}`))}catch{}G(n.intent);const c=B(t,e)+$(n.query);T("navigate",{intent:n.intent,params:e,meta:o,url:c});const{scrollTop:a,...u}=n.options||{};("undefined"!=typeof window?window.location.pathname+window.location.search:null)!==c||u?.replace?(l?.(c,u),a&&"undefined"!=typeof window&&window.scrollTo(0,0)):T("skip navigation",c)}function G(n){const t=E[n];if(t)for(const e of t)try{const t=e();t instanceof Promise&&t.catch(()=>console.warn(`Preload failed for ${n}`))}catch{}}const O={};function Z(n,t){const e=function(n){if(O[n])return O[n];const t=[];return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"")),O[n]=t,t}(n);if(!t)return{};if(Array.isArray(t)){const n={};return e.forEach((e,o)=>{n[e]=t[o]}),n}return"object"==typeof t?t:1===e.length?{[e[0]]:t}:{}}function B(n,t){return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>{const o=t[e];return void 0===o?(console.warn(`Missing param "${e}"`),""):encodeURIComponent(o)})}function V(n,t,e){const o=d[n];if(!o)return"";return B(o,Z(o,t))+$(e)}const F={};function H(n){if(F[n])return F[n];const t=[],e=new RegExp("^"+n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"([^/]+)"))+"$");return F[n]={regex:e,keys:t},F[n]}function J(n){const[t,e]=n.split("?"),o=decodeURI(t),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 d){const t=d[n],{regex:e,keys:i}=H(t),c=o.match(e);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(n){const t=J(n);t&&x(t.intent,t.params,t.query)}function W(n){f=n,f!==s&&f.$onMultiple(p,D)}let X=!1;function Y({intents:n=[],guards:t=[],intentGuards:e={},navigate:o}={}){if(X)return;X=!0;const r={};for(const t of n)for(const n in t)u&&r[n]&&console.warn(`[IntentRouter] duplicate intent "${n}"`),r[n]=t[n];Object.keys(r).length&&P(r),t.forEach(N);for(const n in e)j(n,e[n]);o&&q(o)}function nn({intent:n,params:r,query:i,scrollTop:c,prefetch:a,onClick:u,onMouseEnter:s,onTouchStart:f,...l}){const p=V(n,r,i);return p?t(o,{to:p,onClick:t=>{t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||0!==t.button||(t.preventDefault(),x(n,r,i,{scrollTop:c}),u?.(t))},onMouseEnter:t=>{a&&L(n),s?.(t)},onTouchStart:t=>{a&&L(n),f?.(t)},...l}):(M(n),t(e,{children:l.children}))}function tn(){const n=r(),t=J(n.pathname),e=new URLSearchParams(n.search),o={};return e.forEach((n,t)=>{o[t]=n}),{intent:t?.intent??null,params:t?.params??{},query:o}}function en({intent:n,component:o,fallback:r=null,loading:i,guard:c}){const a=tn();return a?a.intent!==n?null:c&&!c(a)?t(e,{children:r}):t(o,{...a}):i?t(e,{children:i}):null}function on(n){const t=i();return c(()=>{q(n??t)},[n,t]),x}function rn({initializeRouter:n}){const t=i(),e=r(),o=a(!1);return on(),c(()=>{n&&(o.current||(o.current=!0,n(t)))},[t,n]),c(()=>{Q(e.pathname+e.search)},[e.pathname,e.search]),null}export{nn as IntentLink,en as IntentRoute,rn as RouterBinder,N as addIntentGuard,j as addIntentGuardFor,C as addIntentPreload,q as bindNavigate,U as bootstrapRouter,P as createIntentRouter,V as generatePathFromIntent,S as getIntentMeta,x as navigateIntent,K as navigateIntentObject,L as preloadIntent,k as registerIntents,J as resolveIntentFromUrl,z as setFallbackPath,b as setIntentMeta,W as setSharedBus,Y as setupIntentRouter,Q as syncIntentFromUrl,tn as useIntentRouter,on as useNavigateIntent,M as warnRouterNotReady};
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,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||(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
+ "use strict";var n=require("eventbus-z"),t=require("react/jsx-runtime"),e=require("react-router-dom"),o=require("react");const r="undefined"!=typeof window&&!0===window.__INTENT_ROUTER_DEBUG__,i=n.createEventBus();let s=null,a=null;const c="INTENT_NAVIGATE_DELPIK";let u={},f={},l={},p={},d=!1;const h=[],g={},m={};let y=null;const x=[];let w=!1;function I(...n){r&&console.log("[IntentRouter]",...n)}function R(n){if(!n)return"";const t=new URLSearchParams;for(const e in n){const o=n[e];null!=o&&(Array.isArray(o)?o.forEach(n=>t.append(e,String(n))):t.append(e,String(o)))}const e=t.toString();return e?`?${e}`:""}function v(n){for(const t in n){r&&u[t]&&console.warn(`[IntentRouter] duplicate intent "${t}"`);const e=n[t];"string"!=typeof e?(u[t]=e.path,e.meta&&(f[t]=e.meta),e.guard&&(l[t]=e.guard),e.preload&&(p[t]=e.preload)):u[t]=e}}function E(n){x.push(n),w&&v(n)}function _(){if(w)return;w=!0;const n={};x.length||console.warn("[IntentRouter] no intents registered");for(const t of x)Object.assign(n,t);v(n),I("intent map",u)}function k(n){E(n),_()}function T(n,t){const e=f[n];return e?"function"==typeof e?e(t):e:{}}function $(n){a&&a!==n&&r&&console.warn("IntentRouter navigate replaced"),a=n,d||(i.$onMultiple(c,j),d=!0)}function b(n){r&&(a||console.warn(`[IntentRouter] navigateIntent("${n}") called before router initialized.\nMake sure <RouterBinder /> is mounted.`))}function q(n,t,e,o){b(n);const r={intent:n,params:t,query:e,options:o};I("emit",r),i.$emit(c,r),s&&s!==i&&s.$emit(c,r)}function A(n){h.push(n)}function P(n,t){g[n]||(g[n]=[]),g[n].push(t)}function U(n){N(n)}async function j(n){if(n.__handled)return;n.__handled=!0;const t=u[n.intent];if(!t)return console.warn("Unknown intent:",n.intent),void(y&&a?.(y));const e=F(t,n.params),o=T(n.intent,e);for(const t of h){const o=await t(n.intent,e);if(!1===o)return;if("string"==typeof o)return void a?.(o)}const r=g[n.intent]||[];for(const t of r){const o=await t(n.intent,e);if(!1===o)return;if("string"==typeof o)return void a?.(o)}const i=l[n.intent];if(i){const t=await i(n.intent,e);if(!1===t)return;if("string"==typeof t)return void a?.(t)}try{const t=p[n.intent]?.();t instanceof Promise&&t.catch(()=>console.warn(`Preload failed for ${n.intent}`))}catch{}N(n.intent);const s=L(t,e)+R(n.query);I("navigate",{intent:n.intent,params:e,meta:o,url:s});const{scrollTop:c,...f}=n.options||{};("undefined"!=typeof window?window.location.pathname+window.location.search:null)!==s||f?.replace?(a?.(s,f),c&&"undefined"!=typeof window&&window.scrollTo(0,0)):I("skip navigation",s)}function N(n){const t=m[n];if(t)for(const e of t)try{const t=e();t instanceof Promise&&t.catch(()=>console.warn(`Preload failed for ${n}`))}catch{}}const S={};function F(n,t){const e=function(n){if(S[n])return S[n];const t=[];return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"")),S[n]=t,t}(n);if(!t)return{};if(Array.isArray(t)){const n={};return e.forEach((e,o)=>{n[e]=t[o]}),n}return"object"==typeof t?t:1===e.length?{[e[0]]:t}:{}}function L(n,t){return n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>{const o=t[e];return void 0===o?(console.warn(`Missing param "${e}"`),""):encodeURIComponent(o)})}function M(n,t,e){const o=u[n];if(!o)return"";return L(o,F(o,t))+R(e)}const z={};function B(n){if(z[n])return z[n];const t=[],e=new RegExp("^"+n.replace(/:([A-Za-z0-9_]+)/g,(n,e)=>(t.push(e),"([^/]+)"))+"$");return z[n]={regex:e,keys:t},z[n]}function G(n){const[t,e]=n.split("?"),o=decodeURI(t),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 u){const t=u[n],{regex:e,keys:i}=B(t),s=o.match(e);if(!s)continue;const a={};return i.forEach((n,t)=>{a[n]=decodeURIComponent(s[t+1])}),{intent:n,params:a,query:r}}return null}function K(n){const t=G(n);t&&q(t.intent,t.params,t.query)}let C=!1;function O(){const n=e.useLocation(),t=G(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 D(n){const t=e.useNavigate();return o.useEffect(()=>{$(n??t)},[n,t]),q}exports.IntentLink=function({intent:n,params:o,query:r,scrollTop:i,prefetch:s,onClick:a,onMouseEnter:c,onTouchStart:u,...f}){const l=M(n,o,r);return l?t.jsx(e.Link,{to:l,onClick:t=>{t.metaKey||t.ctrlKey||t.shiftKey||t.altKey||0!==t.button||(t.preventDefault(),q(n,o,r,{scrollTop:i}),a?.(t))},onMouseEnter:t=>{s&&U(n),c?.(t)},onTouchStart:t=>{s&&U(n),u?.(t)},...f}):(b(n),t.jsx(t.Fragment,{children:f.children}))},exports.IntentRoute=function({intent:n,component:e,fallback:o=null,loading:r,guard:i}){const s=O();return s?s.intent!==n?null:i&&!i(s)?t.jsx(t.Fragment,{children:o}):t.jsx(e,{...s}):r?t.jsx(t.Fragment,{children:r}):null},exports.RouterBinder=function({initializeRouter:n}){const t=e.useNavigate(),r=e.useLocation(),i=o.useRef(!1);return D(),o.useEffect(()=>{n&&(i.current||(i.current=!0,n(t)))},[t,n]),o.useEffect(()=>{K(r.pathname+r.search)},[r.pathname,r.search]),null},exports.addIntentGuard=A,exports.addIntentGuardFor=P,exports.addIntentPreload=function(n,t){m[n]||(m[n]=[]),m[n].push(t)},exports.bindNavigate=$,exports.bootstrapRouter=_,exports.createIntentRouter=k,exports.generatePathFromIntent=M,exports.getIntentMeta=T,exports.navigateIntent=q,exports.navigateIntentObject=function(n,t){const{params:e,query:o,options:r}=t||{};q(n,e,o,r)},exports.preloadIntent=U,exports.registerIntents=E,exports.resolveIntentFromUrl=G,exports.setFallbackPath=function(n){y=n},exports.setIntentMeta=function(n,t){f[n]=t},exports.setSharedBus=function(n){s=n,s!==i&&s.$onMultiple(c,j)},exports.setupIntentRouter=function({intents:n=[],guards:t=[],intentGuards:e={},navigate:o}={}){if(C)return;C=!0;const i={};for(const t of n)for(const n in t)r&&i[n]&&console.warn(`[IntentRouter] duplicate intent "${n}"`),i[n]=t[n];Object.keys(i).length&&k(i),t.forEach(A);for(const n in e)P(n,e[n]);o&&$(o)},exports.syncIntentFromUrl=K,exports.useIntentRouter=O,exports.useNavigateIntent=D,exports.warnRouterNotReady=b;
@@ -5,6 +5,6 @@ type Props = {
5
5
  query?: Record<string, any>;
6
6
  scrollTop?: boolean;
7
7
  prefetch?: boolean;
8
- } & Omit<LinkProps, "to" | "prefetch">;
8
+ } & Omit<LinkProps, "to">;
9
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: any) => boolean;
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,5 +1,6 @@
1
- type Props = {
2
- navigate?: any;
1
+ import type { NavigateFn } from "../core/intentCore";
2
+ type RouterBinderProps = {
3
+ initializeRouter?: (navigate: NavigateFn) => void;
3
4
  };
4
- export declare function RouterBinder({ navigate }: Props): null;
5
+ export declare function RouterBinder({ initializeRouter }: RouterBinderProps): null;
5
6
  export {};
@@ -1,6 +1,5 @@
1
1
  export * from "./IntentLink";
2
2
  export * from "./IntentRoute";
3
- export * from "./IntentRouter";
4
3
  export * from "./RouterBinder";
5
4
  export * from "./useIntentRouter";
6
5
  export * from "./useNavigateIntent";
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "intentx-react-router",
3
- "version": "1.0.3",
3
+ "version": "1.1.0-z",
4
4
  "description": "Intent-based routing for React. Navigate by intent instead of URLs.",
5
5
  "author": "Delpi.Kye",
6
6
  "license": "MIT",
7
+ "sideEffects": false,
8
+
7
9
  "type": "module",
8
10
  "main": "./build/index.js",
9
11
  "module": "./build/index.esm.js",
10
12
  "types": "./build/index.d.ts",
13
+
11
14
  "exports": {
12
15
  ".": {
13
16
  "types": "./build/index.d.ts",
@@ -18,13 +21,14 @@
18
21
  "files": [
19
22
  "build"
20
23
  ],
21
- "sideEffects": false,
24
+
22
25
  "scripts": {
23
26
  "clean": "rimraf build",
24
27
  "build": "rimraf build && rollup -c",
25
28
  "watch": "rollup -c -w",
26
29
  "typecheck": "tsc --noEmit"
27
30
  },
31
+
28
32
  "engines": {
29
33
  "node": ">=16"
30
34
  },
@@ -36,6 +40,7 @@
36
40
  "bugs": {
37
41
  "url": "https://github.com/delpikye-v/intentx-react-router/issues"
38
42
  },
43
+
39
44
  "keywords": [
40
45
  "react",
41
46
  "react-router",
@@ -48,6 +53,7 @@
48
53
  "spa",
49
54
  "routing"
50
55
  ],
56
+
51
57
  "peerDependencies": {
52
58
  "react": ">=18",
53
59
  "react-dom": ">=18",
@@ -1,5 +0,0 @@
1
- type Props = {
2
- children: React.ReactNode;
3
- };
4
- export declare function IntentRouter({ children }: Props): JSX.Element;
5
- export {};