pejay-ui 1.2.1 → 1.3.0
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/bin/cli.js +2 -2
- package/package.json +1 -1
- package/registry.json +39 -3
- package/templates/notes/create-pejay.md +222 -0
- package/templates/notes/notes-v1.md +516 -0
- package/templates/notes/notes-v2.md +764 -0
- package/templates/notes/notes-v3.md +574 -0
- package/templates/notes/notes-v4.md +811 -0
- package/templates/notes/notes-v5.md +579 -0
- package/templates/notes/notes-vf+1.md +311 -0
- package/templates/notes/notes-vfinal.md +852 -0
- package/templates/scaffolds/axios/api/index.ts +40 -0
- package/templates/scaffolds/axios/api/one.api.ts +94 -0
- package/templates/scaffolds/axios/endpoints.ts +9 -0
- package/templates/scaffolds/axios/index.ts +26 -0
- package/templates/scaffolds/axios/interceptors.ts +103 -0
- package/templates/scaffolds/axios/request.ts +32 -0
- package/templates/scaffolds/react-router/hook/useRouterSearch.ts +8 -0
- package/templates/scaffolds/react-router/router/guards/private.route.tsx +1 -0
- package/templates/scaffolds/react-router/router/index.ts +26 -0
- package/templates/scaffolds/react-router/router/layouts/error.layout.tsx +1 -1
- package/templates/scaffolds/redux-store/middlewares.ts +0 -0
- package/templates/scaffolds/redux-store/reducers.ts +30 -0
- package/templates/scaffolds/redux-store/selector/one.selector.ts +43 -0
- package/templates/scaffolds/redux-store/selector/two.selector.ts +11 -0
- package/templates/scaffolds/redux-store/slices/one.slice.ts +202 -0
- package/templates/scaffolds/redux-store/slices/two.slice.ts +21 -0
- package/templates/scaffolds/redux-store/store.ts +38 -0
- package/templates/scaffolds/rtk-query/baseApi.ts +24 -0
- package/templates/scaffolds/rtk-query/baseQuery.ts +12 -0
- package/templates/scaffolds/rtk-query/endpoints/api.one.ts +82 -0
- package/templates/scaffolds/rtk-query/endpoints/index.ts +1 -0
- package/templates/scaffolds/rtk-query/middlewares.ts +11 -0
- package/templates/scaffolds/rtk-query/queryTags.ts +13 -0
- package/templates/scaffolds/tanstack-query/api-base.ts +68 -68
- package/templates/scaffolds/tanstack-query/api-queries.ts +0 -19
- package/templates/scaffolds/tanstack-query/client.ts +8 -0
- package/templates/scaffolds/tanstack-query/module/index.ts +12 -12
- package/templates/scaffolds/tanstack-query/module/keys.ts +17 -17
- package/templates/scaffolds/tanstack-query/module/mappers.ts +15 -15
- package/templates/scaffolds/tanstack-query/module/mutations.ts +59 -55
- package/templates/scaffolds/tanstack-query/module/queries.ts +145 -156
- package/templates/scaffolds/tanstack-query/module/services.ts +74 -66
- package/templates/scaffolds/tanstack-router/layout/404.layout.tsx +3 -0
- package/templates/scaffolds/tanstack-router/layout/app.layout.tsx +10 -0
- package/templates/scaffolds/tanstack-router/layout/auth.layout.tsx +10 -0
- package/templates/scaffolds/tanstack-router/layout/error.layout.tsx +3 -0
- package/templates/scaffolds/tanstack-router/page/auth/login.tsx +3 -0
- package/templates/scaffolds/tanstack-router/page/one/index.tsx +3 -0
- package/templates/scaffolds/tanstack-router/page/one/one-id.tsx +128 -0
- package/templates/scaffolds/tanstack-router/router.ts +90 -0
- package/templates/scaffolds/tanstack-router/routes/_404.tsx +0 -0
- package/templates/scaffolds/tanstack-router/routes/__root.tsx +9 -0
- package/templates/scaffolds/tanstack-router/routes/_app.tsx +6 -0
- package/templates/scaffolds/tanstack-router/routes/_auth.tsx +6 -0
- package/templates/scaffolds/tanstack-router/routes/_error.tsx +0 -0
- package/templates/scaffolds/tanstack-router/routes/auth/login.tsx +6 -0
- package/templates/scaffolds/tanstack-router/routes/one/$id.tsx +191 -0
- package/templates/scaffolds/tanstack-router/routes/one/index.tsx +6 -0
- package/templates/scripts/setup.bat +284 -0
- package/templates/scripts/setup.ps1 +318 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# TanStack Router Notes
|
|
2
|
+
|
|
3
|
+
## Navigation APIs
|
|
4
|
+
|
|
5
|
+
### `<Link>`
|
|
6
|
+
|
|
7
|
+
Use when navigation is triggered by user interaction.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<Link to="/users">
|
|
11
|
+
Users
|
|
12
|
+
</Link>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Benefits:
|
|
16
|
+
|
|
17
|
+
* Accessible
|
|
18
|
+
* Supports Ctrl+Click / Open in New Tab
|
|
19
|
+
* Preferred for menus and navigation links
|
|
20
|
+
* Supports prefetching in TanStack Router
|
|
21
|
+
|
|
22
|
+
Use for:
|
|
23
|
+
|
|
24
|
+
* Sidebar items
|
|
25
|
+
* Navbar links
|
|
26
|
+
* Menu navigation
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### `useNavigate()`
|
|
31
|
+
|
|
32
|
+
Use when navigation happens from code.
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
const navigate = useNavigate();
|
|
36
|
+
|
|
37
|
+
navigate({
|
|
38
|
+
to: "/users",
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Common use cases:
|
|
43
|
+
|
|
44
|
+
* Login success
|
|
45
|
+
* Form submit
|
|
46
|
+
* Search/filter actions
|
|
47
|
+
* Button click navigation
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
const handleLogin = async () => {
|
|
53
|
+
await login();
|
|
54
|
+
|
|
55
|
+
navigate({
|
|
56
|
+
to: "/dashboard",
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### `router.navigate()`
|
|
64
|
+
|
|
65
|
+
Use outside React components.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
router.navigate({
|
|
69
|
+
to: "/login",
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Useful in:
|
|
74
|
+
|
|
75
|
+
* Utility functions
|
|
76
|
+
* Services
|
|
77
|
+
* Auth helpers
|
|
78
|
+
|
|
79
|
+
Example:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
export async function logout(router: Router) {
|
|
83
|
+
localStorage.removeItem("token");
|
|
84
|
+
|
|
85
|
+
router.navigate({
|
|
86
|
+
to: "/login",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### `redirect()`
|
|
94
|
+
|
|
95
|
+
Used inside:
|
|
96
|
+
|
|
97
|
+
* loader
|
|
98
|
+
* beforeLoad
|
|
99
|
+
* guards
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
throw redirect({
|
|
105
|
+
to: "/login",
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Common auth guard pattern:
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
export function PrivateRoute({ context }) {
|
|
113
|
+
if (!context.auth.isAuthenticated) {
|
|
114
|
+
throw redirect({
|
|
115
|
+
to: "/login",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Quick Navigation Rules
|
|
124
|
+
|
|
125
|
+
```txt
|
|
126
|
+
User clicks link?
|
|
127
|
+
-> <Link>
|
|
128
|
+
|
|
129
|
+
Code decides navigation?
|
|
130
|
+
-> useNavigate()
|
|
131
|
+
|
|
132
|
+
Outside React component?
|
|
133
|
+
-> router.navigate()
|
|
134
|
+
|
|
135
|
+
Guard/Loader blocks access?
|
|
136
|
+
-> redirect()
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
# Code Splitting
|
|
142
|
+
|
|
143
|
+
## What Is Code Splitting?
|
|
144
|
+
|
|
145
|
+
Without splitting:
|
|
146
|
+
|
|
147
|
+
```txt
|
|
148
|
+
main.js
|
|
149
|
+
├── Dashboard
|
|
150
|
+
├── Users
|
|
151
|
+
├── Reports
|
|
152
|
+
├── Settings
|
|
153
|
+
└── Modals
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Everything downloads immediately.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
With splitting:
|
|
161
|
+
|
|
162
|
+
```txt
|
|
163
|
+
main.js
|
|
164
|
+
users.chunk.js
|
|
165
|
+
reports.chunk.js
|
|
166
|
+
settings.chunk.js
|
|
167
|
+
history-drawer.chunk.js
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Files download only when needed.
|
|
171
|
+
|
|
172
|
+
Benefits:
|
|
173
|
+
|
|
174
|
+
* Smaller initial bundle
|
|
175
|
+
* Faster first load
|
|
176
|
+
* Better performance
|
|
177
|
+
* Better Lighthouse scores
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
# Auto Route Splitting
|
|
182
|
+
|
|
183
|
+
Handled by TanStack Router.
|
|
184
|
+
|
|
185
|
+
Routes become separate chunks automatically.
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
|
|
189
|
+
```txt
|
|
190
|
+
/users
|
|
191
|
+
/reports
|
|
192
|
+
/settings
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Each route gets its own JS chunk.
|
|
196
|
+
|
|
197
|
+
Advantages:
|
|
198
|
+
|
|
199
|
+
* Almost zero setup
|
|
200
|
+
* Recommended approach
|
|
201
|
+
* Easy maintenance
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
# Manual Component Splitting
|
|
206
|
+
|
|
207
|
+
Useful for large components inside a route.
|
|
208
|
+
|
|
209
|
+
Example:
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
import { lazy } from "react";
|
|
213
|
+
|
|
214
|
+
const HistoryDrawer = lazy(
|
|
215
|
+
() => import("./HistoryDrawer")
|
|
216
|
+
);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Render:
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
<Suspense fallback={<div>Loading...</div>}>
|
|
223
|
+
<HistoryDrawer />
|
|
224
|
+
</Suspense>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Good Candidates For Manual Splitting
|
|
230
|
+
|
|
231
|
+
* Rich Text Editors
|
|
232
|
+
* PDF Viewers
|
|
233
|
+
* Maps
|
|
234
|
+
* Analytics Charts
|
|
235
|
+
* Large Modals
|
|
236
|
+
* Drawers
|
|
237
|
+
* Multi-step Wizards
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
const PdfViewer = lazy(() => import("./PdfViewer"));
|
|
243
|
+
const NotesDrawer = lazy(() => import("./NotesDrawer"));
|
|
244
|
+
const AnalyticsChart = lazy(() => import("./AnalyticsChart"));
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Bad Candidates
|
|
250
|
+
|
|
251
|
+
Avoid splitting:
|
|
252
|
+
|
|
253
|
+
* Button
|
|
254
|
+
* Input
|
|
255
|
+
* Small Forms
|
|
256
|
+
* Small Cards
|
|
257
|
+
* Table Rows
|
|
258
|
+
|
|
259
|
+
The overhead usually outweighs the benefits.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## CRM Recommendation
|
|
264
|
+
|
|
265
|
+
For projects like:
|
|
266
|
+
|
|
267
|
+
* Prime Hearing
|
|
268
|
+
* Fleet Nexa
|
|
269
|
+
|
|
270
|
+
Use:
|
|
271
|
+
|
|
272
|
+
```txt
|
|
273
|
+
Auto Route Splitting -> YES
|
|
274
|
+
|
|
275
|
+
Manual Splitting ->
|
|
276
|
+
Only for heavy components
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
# Suspense + React.lazy
|
|
282
|
+
|
|
283
|
+
Example:
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
const HistoryDrawer = lazy(
|
|
287
|
+
() => import("./HistoryDrawer")
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
<Suspense fallback={<DrawerSkeleton />}>
|
|
291
|
+
<HistoryDrawer />
|
|
292
|
+
</Suspense>
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Flow:
|
|
296
|
+
|
|
297
|
+
```txt
|
|
298
|
+
Component requested
|
|
299
|
+
↓
|
|
300
|
+
Chunk not downloaded
|
|
301
|
+
↓
|
|
302
|
+
Fallback shown
|
|
303
|
+
↓
|
|
304
|
+
Chunk arrives
|
|
305
|
+
↓
|
|
306
|
+
Component renders
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Works exactly the same in:
|
|
310
|
+
|
|
311
|
+
* React Router
|
|
312
|
+
* TanStack Router
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
# Route.useLoaderData()
|
|
317
|
+
|
|
318
|
+
Purpose:
|
|
319
|
+
|
|
320
|
+
Read data returned by a route loader.
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Example
|
|
325
|
+
|
|
326
|
+
Route:
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
export const Route = createFileRoute("/users/$id")({
|
|
330
|
+
loader: async ({ params }) => {
|
|
331
|
+
return {
|
|
332
|
+
id: params.id,
|
|
333
|
+
name: "John",
|
|
334
|
+
};
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
component: UserPage,
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Component:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
export default function UserPage() {
|
|
345
|
+
const data = Route.useLoaderData();
|
|
346
|
+
|
|
347
|
+
return (
|
|
348
|
+
<>
|
|
349
|
+
<div>{data.id}</div>
|
|
350
|
+
<div>{data.name}</div>
|
|
351
|
+
</>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Loader Flow
|
|
359
|
+
|
|
360
|
+
```txt
|
|
361
|
+
Navigate
|
|
362
|
+
↓
|
|
363
|
+
Run Loader
|
|
364
|
+
↓
|
|
365
|
+
Store Result
|
|
366
|
+
↓
|
|
367
|
+
Render Component
|
|
368
|
+
↓
|
|
369
|
+
useLoaderData()
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
# Loader + TanStack Query
|
|
375
|
+
|
|
376
|
+
Common pattern:
|
|
377
|
+
|
|
378
|
+
```tsx
|
|
379
|
+
loader: ({ context, params }) =>
|
|
380
|
+
context.queryClient.ensureQueryData(
|
|
381
|
+
apiQueries.users.detail(params.id)
|
|
382
|
+
)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Then component:
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
const { id } = Route.useParams();
|
|
389
|
+
|
|
390
|
+
const { data } = useSuspenseQuery(
|
|
391
|
+
apiQueries.users.detail(id)
|
|
392
|
+
);
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Why Not Use useLoaderData Here?
|
|
398
|
+
|
|
399
|
+
Because TanStack Query already provides:
|
|
400
|
+
|
|
401
|
+
* Cache
|
|
402
|
+
* Refetching
|
|
403
|
+
* Invalidation
|
|
404
|
+
* Mutations
|
|
405
|
+
* Background updates
|
|
406
|
+
|
|
407
|
+
Loader simply pre-populates the cache.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
# Route Hooks Cheat Sheet
|
|
412
|
+
|
|
413
|
+
## URL Params
|
|
414
|
+
|
|
415
|
+
```tsx
|
|
416
|
+
const { id } = Route.useParams();
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Reads:
|
|
420
|
+
|
|
421
|
+
```txt
|
|
422
|
+
/users/123
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
Result:
|
|
426
|
+
|
|
427
|
+
```tsx
|
|
428
|
+
id = "123"
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Search Params
|
|
434
|
+
|
|
435
|
+
```tsx
|
|
436
|
+
const search = Route.useSearch();
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Reads:
|
|
440
|
+
|
|
441
|
+
```txt
|
|
442
|
+
/users?search=john&type=active
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Result:
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
{
|
|
449
|
+
search: "john",
|
|
450
|
+
type: "active"
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Loader Data
|
|
457
|
+
|
|
458
|
+
```tsx
|
|
459
|
+
const data = Route.useLoaderData();
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Reads:
|
|
463
|
+
|
|
464
|
+
```tsx
|
|
465
|
+
return {...}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
from the route loader.
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Query Data
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
const { data } = useSuspenseQuery(...)
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Reads:
|
|
479
|
+
|
|
480
|
+
```txt
|
|
481
|
+
TanStack Query Cache
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
and provides caching, invalidation, refetching, and mutations.
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
# Mental Model
|
|
489
|
+
|
|
490
|
+
```txt
|
|
491
|
+
Route.useParams()
|
|
492
|
+
↓
|
|
493
|
+
URL Params
|
|
494
|
+
|
|
495
|
+
Route.useSearch()
|
|
496
|
+
↓
|
|
497
|
+
URL Search Params
|
|
498
|
+
|
|
499
|
+
Route.useLoaderData()
|
|
500
|
+
↓
|
|
501
|
+
Loader Return Value
|
|
502
|
+
|
|
503
|
+
useSuspenseQuery()
|
|
504
|
+
↓
|
|
505
|
+
TanStack Query Cache
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
For CRUD/CRM projects, the most common combination is:
|
|
509
|
+
|
|
510
|
+
```tsx
|
|
511
|
+
Route.useParams()
|
|
512
|
+
Route.useSearch()
|
|
513
|
+
useSuspenseQuery()
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
with loaders used primarily for prefetching query data.
|