@riktajs/react 0.10.3
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 +368 -0
- package/dist/index.cjs +316 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +609 -0
- package/dist/index.d.ts +609 -0
- package/dist/index.js +303 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { FC } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SSR data structure passed from server to client
|
|
6
|
+
* via window.__SSR_DATA__
|
|
7
|
+
*/
|
|
8
|
+
interface SsrData<T = unknown> {
|
|
9
|
+
/** Initial data rendered on server */
|
|
10
|
+
data: T;
|
|
11
|
+
/** Current URL path */
|
|
12
|
+
url: string;
|
|
13
|
+
/** HTTP status code */
|
|
14
|
+
status?: number;
|
|
15
|
+
/** Additional metadata */
|
|
16
|
+
meta?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Router context value interface
|
|
20
|
+
*/
|
|
21
|
+
interface RouterContextValue {
|
|
22
|
+
/** Current URL path */
|
|
23
|
+
pathname: string;
|
|
24
|
+
/** Current search params string (without ?) */
|
|
25
|
+
search: string;
|
|
26
|
+
/** Full URL */
|
|
27
|
+
href: string;
|
|
28
|
+
/** Navigate to a new URL */
|
|
29
|
+
navigate: (url: string, options?: NavigateOptions) => void;
|
|
30
|
+
/** Extracted route params (e.g., { id: '123' } for /item/:id) */
|
|
31
|
+
params: Record<string, string>;
|
|
32
|
+
/** Update route params (used internally by RiktaProvider) */
|
|
33
|
+
setParams: (params: Record<string, string>) => void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Navigation options
|
|
37
|
+
*/
|
|
38
|
+
interface NavigateOptions {
|
|
39
|
+
/** Replace current history entry instead of pushing */
|
|
40
|
+
replace?: boolean;
|
|
41
|
+
/** Scroll to top after navigation */
|
|
42
|
+
scroll?: boolean;
|
|
43
|
+
/** Additional state to store in history */
|
|
44
|
+
state?: unknown;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Result type for server actions
|
|
48
|
+
*/
|
|
49
|
+
interface ActionResult<T = unknown> {
|
|
50
|
+
/** Whether the action was successful */
|
|
51
|
+
success: boolean;
|
|
52
|
+
/** Response data on success */
|
|
53
|
+
data?: T;
|
|
54
|
+
/** Error message on failure */
|
|
55
|
+
error?: string;
|
|
56
|
+
/** Field-specific validation errors */
|
|
57
|
+
fieldErrors?: Record<string, string[]>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Fetch state for useFetch hook
|
|
61
|
+
*/
|
|
62
|
+
interface FetchState<T = unknown> {
|
|
63
|
+
/** Fetched data */
|
|
64
|
+
data: T | null;
|
|
65
|
+
/** Whether fetch is in progress */
|
|
66
|
+
loading: boolean;
|
|
67
|
+
/** Error message if fetch failed */
|
|
68
|
+
error: string | null;
|
|
69
|
+
/** Manually refetch data */
|
|
70
|
+
refetch: () => Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Action state for useAction hook
|
|
74
|
+
*/
|
|
75
|
+
interface ActionState<TInput = unknown, TResult = unknown> {
|
|
76
|
+
/** Execute the action */
|
|
77
|
+
execute: (input: TInput) => Promise<ActionResult<TResult>>;
|
|
78
|
+
/** Whether action is executing */
|
|
79
|
+
pending: boolean;
|
|
80
|
+
/** Last action result */
|
|
81
|
+
result: ActionResult<TResult> | null;
|
|
82
|
+
/** Reset action state */
|
|
83
|
+
reset: () => void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Link component props
|
|
87
|
+
*/
|
|
88
|
+
interface LinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
89
|
+
/** Target URL */
|
|
90
|
+
href: string;
|
|
91
|
+
/** Replace history entry instead of push */
|
|
92
|
+
replace?: boolean;
|
|
93
|
+
/** Scroll to top after navigation */
|
|
94
|
+
scroll?: boolean;
|
|
95
|
+
/** Prefetch the linked page (future enhancement) */
|
|
96
|
+
prefetch?: boolean;
|
|
97
|
+
/** Additional state to pass to navigation */
|
|
98
|
+
state?: unknown;
|
|
99
|
+
/** Children elements */
|
|
100
|
+
children: React.ReactNode;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* RiktaProvider props
|
|
104
|
+
*/
|
|
105
|
+
interface RiktaProviderProps {
|
|
106
|
+
/** Initial SSR data from server */
|
|
107
|
+
ssrData?: SsrData;
|
|
108
|
+
/** Initial route params extracted from URL */
|
|
109
|
+
initialParams?: Record<string, string>;
|
|
110
|
+
/** Children elements */
|
|
111
|
+
children: React.ReactNode;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Hydration state
|
|
115
|
+
*/
|
|
116
|
+
interface HydrationState {
|
|
117
|
+
/** Whether the app has hydrated on client */
|
|
118
|
+
isHydrated: boolean;
|
|
119
|
+
/** Whether currently running on server */
|
|
120
|
+
isServer: boolean;
|
|
121
|
+
}
|
|
122
|
+
declare global {
|
|
123
|
+
interface Window {
|
|
124
|
+
__SSR_DATA__?: SsrData;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* React context for router state
|
|
130
|
+
* Provides navigation utilities and current location info
|
|
131
|
+
*/
|
|
132
|
+
declare const RouterContext: react.Context<RouterContextValue>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* React context for SSR data
|
|
136
|
+
* Holds the server-rendered data passed via window.__SSR_DATA__
|
|
137
|
+
*/
|
|
138
|
+
declare const SsrContext: react.Context<SsrData<unknown> | null>;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* RiktaProvider - Main provider component for Rikta React utilities
|
|
142
|
+
*
|
|
143
|
+
* Provides routing context, SSR data, and navigation utilities to the app.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```tsx
|
|
147
|
+
* // In entry-client.tsx
|
|
148
|
+
* import { RiktaProvider } from '@riktajs/react';
|
|
149
|
+
*
|
|
150
|
+
* hydrateRoot(
|
|
151
|
+
* document.getElementById('root')!,
|
|
152
|
+
* <RiktaProvider>
|
|
153
|
+
* <App />
|
|
154
|
+
* </RiktaProvider>
|
|
155
|
+
* );
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
declare const RiktaProvider: FC<RiktaProviderProps>;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Link component for client-side navigation
|
|
162
|
+
*
|
|
163
|
+
* Renders an anchor tag that uses the History API for navigation
|
|
164
|
+
* instead of causing a full page reload.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```tsx
|
|
168
|
+
* import { Link } from '@riktajs/react';
|
|
169
|
+
*
|
|
170
|
+
* function Nav() {
|
|
171
|
+
* return (
|
|
172
|
+
* <nav>
|
|
173
|
+
* <Link href="/">Home</Link>
|
|
174
|
+
* <Link href="/about">About</Link>
|
|
175
|
+
* <Link href="/items/123">Item 123</Link>
|
|
176
|
+
* </nav>
|
|
177
|
+
* );
|
|
178
|
+
* }
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```tsx
|
|
183
|
+
* // With options
|
|
184
|
+
* <Link href="/dashboard" replace scroll={false}>
|
|
185
|
+
* Dashboard
|
|
186
|
+
* </Link>
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
declare const Link: FC<LinkProps>;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Hook for programmatic navigation
|
|
193
|
+
*
|
|
194
|
+
* @returns Object with navigate function and current location info
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```tsx
|
|
198
|
+
* import { useNavigation } from '@riktajs/react';
|
|
199
|
+
*
|
|
200
|
+
* function MyComponent() {
|
|
201
|
+
* const { navigate, pathname } = useNavigation();
|
|
202
|
+
*
|
|
203
|
+
* const handleSubmit = async () => {
|
|
204
|
+
* await saveData();
|
|
205
|
+
* navigate('/success');
|
|
206
|
+
* };
|
|
207
|
+
*
|
|
208
|
+
* return (
|
|
209
|
+
* <button onClick={handleSubmit}>
|
|
210
|
+
* Submit (current path: {pathname})
|
|
211
|
+
* </button>
|
|
212
|
+
* );
|
|
213
|
+
* }
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```tsx
|
|
218
|
+
* // With options
|
|
219
|
+
* const { navigate } = useNavigation();
|
|
220
|
+
*
|
|
221
|
+
* // Replace history entry (for redirects)
|
|
222
|
+
* navigate('/login', { replace: true });
|
|
223
|
+
*
|
|
224
|
+
* // Don't scroll to top
|
|
225
|
+
* navigate('/next', { scroll: false });
|
|
226
|
+
*
|
|
227
|
+
* // Pass state
|
|
228
|
+
* navigate('/edit', { state: { from: 'list' } });
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
declare function useNavigation(): {
|
|
232
|
+
/** Navigate to a new URL */
|
|
233
|
+
navigate: (url: string, options?: NavigateOptions) => void;
|
|
234
|
+
/** Current pathname */
|
|
235
|
+
pathname: string;
|
|
236
|
+
/** Current search string (without ?) */
|
|
237
|
+
search: string;
|
|
238
|
+
/** Full href */
|
|
239
|
+
href: string;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Hook to access route parameters
|
|
244
|
+
*
|
|
245
|
+
* Route parameters are extracted from the URL path by the server
|
|
246
|
+
* and passed via SSR data. They're stored in the RouterContext.
|
|
247
|
+
*
|
|
248
|
+
* @returns Object with route parameter values
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```tsx
|
|
252
|
+
* // For route /item/:id
|
|
253
|
+
* import { useParams } from '@riktajs/react';
|
|
254
|
+
*
|
|
255
|
+
* function ItemPage() {
|
|
256
|
+
* const { id } = useParams<{ id: string }>();
|
|
257
|
+
*
|
|
258
|
+
* return <h1>Item {id}</h1>;
|
|
259
|
+
* }
|
|
260
|
+
* ```
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```tsx
|
|
264
|
+
* // Multiple params - /users/:userId/posts/:postId
|
|
265
|
+
* function PostPage() {
|
|
266
|
+
* const { userId, postId } = useParams<{ userId: string; postId: string }>();
|
|
267
|
+
*
|
|
268
|
+
* return <h1>Post {postId} by User {userId}</h1>;
|
|
269
|
+
* }
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
declare function useParams<T extends Record<string, string> = Record<string, string>>(): T;
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Hook to access and manipulate URL search parameters
|
|
276
|
+
*
|
|
277
|
+
* @returns Tuple of [URLSearchParams, setSearchParams function]
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```tsx
|
|
281
|
+
* import { useSearchParams } from '@riktajs/react';
|
|
282
|
+
*
|
|
283
|
+
* function SearchPage() {
|
|
284
|
+
* const [searchParams, setSearchParams] = useSearchParams();
|
|
285
|
+
* const query = searchParams.get('q') ?? '';
|
|
286
|
+
* const page = parseInt(searchParams.get('page') ?? '1', 10);
|
|
287
|
+
*
|
|
288
|
+
* const handleSearch = (newQuery: string) => {
|
|
289
|
+
* setSearchParams({ q: newQuery, page: '1' });
|
|
290
|
+
* };
|
|
291
|
+
*
|
|
292
|
+
* const handleNextPage = () => {
|
|
293
|
+
* setSearchParams({ q: query, page: String(page + 1) });
|
|
294
|
+
* };
|
|
295
|
+
*
|
|
296
|
+
* return (
|
|
297
|
+
* <div>
|
|
298
|
+
* <input
|
|
299
|
+
* value={query}
|
|
300
|
+
* onChange={(e) => handleSearch(e.target.value)}
|
|
301
|
+
* />
|
|
302
|
+
* <button onClick={handleNextPage}>Next Page</button>
|
|
303
|
+
* </div>
|
|
304
|
+
* );
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
declare function useSearchParams(): [URLSearchParams, (params: Record<string, string> | URLSearchParams) => void];
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Location object returned by useLocation
|
|
312
|
+
*/
|
|
313
|
+
interface Location {
|
|
314
|
+
/** Current pathname (e.g., /items/123) */
|
|
315
|
+
pathname: string;
|
|
316
|
+
/** Current search string without ? (e.g., page=2&sort=asc) */
|
|
317
|
+
search: string;
|
|
318
|
+
/** Full href */
|
|
319
|
+
href: string;
|
|
320
|
+
/** Parsed search params */
|
|
321
|
+
searchParams: URLSearchParams;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Hook to access current location information
|
|
325
|
+
*
|
|
326
|
+
* @returns Location object with pathname, search, href, and searchParams
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```tsx
|
|
330
|
+
* import { useLocation } from '@riktajs/react';
|
|
331
|
+
*
|
|
332
|
+
* function Breadcrumbs() {
|
|
333
|
+
* const location = useLocation();
|
|
334
|
+
*
|
|
335
|
+
* return (
|
|
336
|
+
* <nav>
|
|
337
|
+
* Current path: {location.pathname}
|
|
338
|
+
* {location.search && <span>?{location.search}</span>}
|
|
339
|
+
* </nav>
|
|
340
|
+
* );
|
|
341
|
+
* }
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```tsx
|
|
346
|
+
* // Access search params
|
|
347
|
+
* function FilterDisplay() {
|
|
348
|
+
* const { searchParams } = useLocation();
|
|
349
|
+
* const filter = searchParams.get('filter');
|
|
350
|
+
*
|
|
351
|
+
* return filter ? <span>Filtered by: {filter}</span> : null;
|
|
352
|
+
* }
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
declare function useLocation(): Location;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Hook to access SSR data passed from server
|
|
359
|
+
*
|
|
360
|
+
* SSR data is passed via window.__SSR_DATA__ and contains
|
|
361
|
+
* the initial data rendered on the server.
|
|
362
|
+
*
|
|
363
|
+
* @returns SSR data object or null if not available
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```tsx
|
|
367
|
+
* import { useSsrData } from '@riktajs/react';
|
|
368
|
+
*
|
|
369
|
+
* interface PageData {
|
|
370
|
+
* title: string;
|
|
371
|
+
* items: Array<{ id: string; name: string }>;
|
|
372
|
+
* }
|
|
373
|
+
*
|
|
374
|
+
* function ItemList() {
|
|
375
|
+
* const ssrData = useSsrData<PageData>();
|
|
376
|
+
*
|
|
377
|
+
* if (!ssrData) {
|
|
378
|
+
* return <div>Loading...</div>;
|
|
379
|
+
* }
|
|
380
|
+
*
|
|
381
|
+
* return (
|
|
382
|
+
* <div>
|
|
383
|
+
* <h1>{ssrData.data.title}</h1>
|
|
384
|
+
* <ul>
|
|
385
|
+
* {ssrData.data.items.map(item => (
|
|
386
|
+
* <li key={item.id}>{item.name}</li>
|
|
387
|
+
* ))}
|
|
388
|
+
* </ul>
|
|
389
|
+
* </div>
|
|
390
|
+
* );
|
|
391
|
+
* }
|
|
392
|
+
* ```
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```tsx
|
|
396
|
+
* // Access just the data
|
|
397
|
+
* function MyComponent() {
|
|
398
|
+
* const ssrData = useSsrData<{ user: User }>();
|
|
399
|
+
* const user = ssrData?.data.user;
|
|
400
|
+
*
|
|
401
|
+
* return user ? <UserProfile user={user} /> : <LoginPrompt />;
|
|
402
|
+
* }
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
declare function useSsrData<T = unknown>(): SsrData<T> | null;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Hook to track hydration state
|
|
409
|
+
*
|
|
410
|
+
* Useful for rendering different content during SSR vs after hydration,
|
|
411
|
+
* or for avoiding hydration mismatches.
|
|
412
|
+
*
|
|
413
|
+
* @returns Hydration state object
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```tsx
|
|
417
|
+
* import { useHydration } from '@riktajs/react';
|
|
418
|
+
*
|
|
419
|
+
* function TimeDisplay() {
|
|
420
|
+
* const { isHydrated, isServer } = useHydration();
|
|
421
|
+
*
|
|
422
|
+
* // On server and initial render, show static content
|
|
423
|
+
* // After hydration, show dynamic content
|
|
424
|
+
* if (!isHydrated) {
|
|
425
|
+
* return <span>Loading time...</span>;
|
|
426
|
+
* }
|
|
427
|
+
*
|
|
428
|
+
* return <span>{new Date().toLocaleTimeString()}</span>;
|
|
429
|
+
* }
|
|
430
|
+
* ```
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* ```tsx
|
|
434
|
+
* // Avoid hydration mismatch with client-only content
|
|
435
|
+
* function ClientOnlyComponent() {
|
|
436
|
+
* const { isHydrated } = useHydration();
|
|
437
|
+
*
|
|
438
|
+
* if (!isHydrated) {
|
|
439
|
+
* return null; // Or a placeholder
|
|
440
|
+
* }
|
|
441
|
+
*
|
|
442
|
+
* return <SomeClientOnlyLibrary />;
|
|
443
|
+
* }
|
|
444
|
+
* ```
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```tsx
|
|
448
|
+
* // Conditional rendering based on environment
|
|
449
|
+
* function DebugPanel() {
|
|
450
|
+
* const { isServer } = useHydration();
|
|
451
|
+
*
|
|
452
|
+
* // Never render on server, only after client hydration
|
|
453
|
+
* if (isServer) return null;
|
|
454
|
+
*
|
|
455
|
+
* return <DevTools />;
|
|
456
|
+
* }
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
declare function useHydration(): HydrationState;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Options for useFetch hook
|
|
463
|
+
*/
|
|
464
|
+
interface UseFetchOptions extends Omit<RequestInit, 'body'> {
|
|
465
|
+
/** Skip initial fetch (useful for conditional fetching) */
|
|
466
|
+
skip?: boolean;
|
|
467
|
+
/** Dependencies that trigger refetch when changed */
|
|
468
|
+
deps?: unknown[];
|
|
469
|
+
/** Transform response before setting data */
|
|
470
|
+
transform?: (data: unknown) => unknown;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Hook for data fetching with loading and error states
|
|
474
|
+
*
|
|
475
|
+
* @param url URL to fetch from
|
|
476
|
+
* @param options Fetch options
|
|
477
|
+
* @returns Fetch state with data, loading, error, and refetch function
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```tsx
|
|
481
|
+
* import { useFetch } from '@riktajs/react';
|
|
482
|
+
*
|
|
483
|
+
* interface User {
|
|
484
|
+
* id: string;
|
|
485
|
+
* name: string;
|
|
486
|
+
* }
|
|
487
|
+
*
|
|
488
|
+
* function UserProfile({ userId }: { userId: string }) {
|
|
489
|
+
* const { data, loading, error, refetch } = useFetch<User>(
|
|
490
|
+
* `/api/users/${userId}`
|
|
491
|
+
* );
|
|
492
|
+
*
|
|
493
|
+
* if (loading) return <Spinner />;
|
|
494
|
+
* if (error) return <Error message={error} />;
|
|
495
|
+
* if (!data) return null;
|
|
496
|
+
*
|
|
497
|
+
* return (
|
|
498
|
+
* <div>
|
|
499
|
+
* <h1>{data.name}</h1>
|
|
500
|
+
* <button onClick={refetch}>Refresh</button>
|
|
501
|
+
* </div>
|
|
502
|
+
* );
|
|
503
|
+
* }
|
|
504
|
+
* ```
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* ```tsx
|
|
508
|
+
* // With options
|
|
509
|
+
* const { data } = useFetch<Item[]>('/api/items', {
|
|
510
|
+
* headers: { 'Authorization': `Bearer ${token}` },
|
|
511
|
+
* deps: [token], // Refetch when token changes
|
|
512
|
+
* skip: !token, // Don't fetch until we have a token
|
|
513
|
+
* });
|
|
514
|
+
* ```
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* ```tsx
|
|
518
|
+
* // With transform
|
|
519
|
+
* const { data } = useFetch<{ results: Item[] }>('/api/search', {
|
|
520
|
+
* transform: (res) => res.results, // Extract just the results array
|
|
521
|
+
* });
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
declare function useFetch<T = unknown>(url: string, options?: UseFetchOptions): FetchState<T>;
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Options for useAction hook
|
|
528
|
+
*/
|
|
529
|
+
interface UseActionOptions<TResult = unknown> {
|
|
530
|
+
/** Callback on successful action */
|
|
531
|
+
onSuccess?: (result: TResult) => void;
|
|
532
|
+
/** Callback on action error */
|
|
533
|
+
onError?: (error: string) => void;
|
|
534
|
+
/** HTTP method to use */
|
|
535
|
+
method?: 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
536
|
+
/** Additional headers */
|
|
537
|
+
headers?: Record<string, string>;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Hook for executing server actions (form submissions, mutations)
|
|
541
|
+
*
|
|
542
|
+
* @param url URL to send the action to
|
|
543
|
+
* @param options Action options
|
|
544
|
+
* @returns Action state with execute, pending, result, and reset
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```tsx
|
|
548
|
+
* import { useAction } from '@riktajs/react';
|
|
549
|
+
*
|
|
550
|
+
* interface CreateItemInput {
|
|
551
|
+
* name: string;
|
|
552
|
+
* price: number;
|
|
553
|
+
* }
|
|
554
|
+
*
|
|
555
|
+
* interface Item {
|
|
556
|
+
* id: string;
|
|
557
|
+
* name: string;
|
|
558
|
+
* price: number;
|
|
559
|
+
* }
|
|
560
|
+
*
|
|
561
|
+
* function CreateItemForm() {
|
|
562
|
+
* const { execute, pending, result } = useAction<CreateItemInput, Item>(
|
|
563
|
+
* '/api/items',
|
|
564
|
+
* {
|
|
565
|
+
* onSuccess: (item) => {
|
|
566
|
+
* console.log('Created item:', item);
|
|
567
|
+
* },
|
|
568
|
+
* }
|
|
569
|
+
* );
|
|
570
|
+
*
|
|
571
|
+
* const handleSubmit = async (e: FormEvent) => {
|
|
572
|
+
* e.preventDefault();
|
|
573
|
+
* const formData = new FormData(e.target as HTMLFormElement);
|
|
574
|
+
* await execute({
|
|
575
|
+
* name: formData.get('name') as string,
|
|
576
|
+
* price: Number(formData.get('price')),
|
|
577
|
+
* });
|
|
578
|
+
* };
|
|
579
|
+
*
|
|
580
|
+
* return (
|
|
581
|
+
* <form onSubmit={handleSubmit}>
|
|
582
|
+
* <input name="name" required />
|
|
583
|
+
* <input name="price" type="number" required />
|
|
584
|
+
* <button disabled={pending}>
|
|
585
|
+
* {pending ? 'Creating...' : 'Create Item'}
|
|
586
|
+
* </button>
|
|
587
|
+
* {result?.error && <p className="error">{result.error}</p>}
|
|
588
|
+
* {result?.fieldErrors?.name && (
|
|
589
|
+
* <p className="error">{result.fieldErrors.name[0]}</p>
|
|
590
|
+
* )}
|
|
591
|
+
* </form>
|
|
592
|
+
* );
|
|
593
|
+
* }
|
|
594
|
+
* ```
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* ```tsx
|
|
598
|
+
* // DELETE action
|
|
599
|
+
* const { execute, pending } = useAction<{ id: string }, void>(
|
|
600
|
+
* '/api/items',
|
|
601
|
+
* { method: 'DELETE' }
|
|
602
|
+
* );
|
|
603
|
+
*
|
|
604
|
+
* const handleDelete = () => execute({ id: itemId });
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
declare function useAction<TInput = unknown, TResult = unknown>(url: string, options?: UseActionOptions<TResult>): ActionState<TInput, TResult>;
|
|
608
|
+
|
|
609
|
+
export { type ActionResult, type ActionState, type FetchState, type HydrationState, Link, type LinkProps, type Location, type NavigateOptions, RiktaProvider, type RiktaProviderProps, RouterContext, type RouterContextValue, SsrContext, type SsrData, type UseActionOptions, type UseFetchOptions, useAction, useFetch, useHydration, useLocation, useNavigation, useParams, useSearchParams, useSsrData };
|