@gaddario98/react-core 2.1.5 → 2.1.6

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,14 +1,640 @@
1
- # react-base-core
1
+ # @gaddario98/react-core
2
+
3
+ A modular, type-safe React framework that unifies state management, forms, data fetching, page orchestration, localization, authentication, and notifications into a single cohesive package. Built on Jotai, TanStack Form, and TanStack Query.
4
+
5
+ **Version**: 2.1.5 | **License**: MIT | **Author**: Giosuè Addario
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ - [Overview](#overview)
12
+ - [Installation](#installation)
13
+ - [Architecture](#architecture)
14
+ - [Quick Start — Unified Configuration](#quick-start--unified-configuration)
15
+ - [Modules](#modules)
16
+ - [State (`/state`)](#state-state)
17
+ - [Auth (`/auth`)](#auth-auth)
18
+ - [Notifications (`/notifications`)](#notifications-notifications)
19
+ - [Localization (`/localization`)](#localization-localization)
20
+ - [Form (`/form`)](#form-form)
21
+ - [Queries (`/queries`)](#queries-queries)
22
+ - [Pages (`/pages`)](#pages-pages)
23
+ - [Providers (`/providers`)](#providers-providers)
24
+ - [Utilities (`/utiles`)](#utilities-utiles)
25
+ - [Config (`/config`)](#config-config)
26
+ - [Entry Points](#entry-points)
27
+ - [Cross-Platform Support](#cross-platform-support)
28
+ - [TypeScript Support](#typescript-support)
29
+ - [Contributing](#contributing)
30
+
31
+ ---
32
+
33
+ ## Overview
34
+
35
+ `@gaddario98/react-core` is composed of independent modules that share a common state layer (Jotai atoms). Each module can be imported individually via sub-path exports or consumed together through the root entry point.
36
+
37
+ **Key design principles:**
38
+
39
+ - **Atom-based state**: Every module stores its configuration and runtime state in Jotai atoms via `atomStateGenerator`, enabling cross-module reactivity without React Context nesting
40
+ - **Platform-agnostic**: No DOM or React Native imports — platform behavior is injected via configurable container components
41
+ - **Tree-shakeable**: 10 independent sub-path exports; import only what you use
42
+ - **Zero-config defaults**: Every module works out of the box with sensible defaults, customizable at any depth
43
+ - **TypeScript-first**: Full generic type support with strict inference
44
+
45
+ ---
2
46
 
3
47
  ## Installation
4
48
 
5
49
  ```bash
6
- npm install @gaddario98/base
50
+ npm install @gaddario98/react-core
51
+ ```
52
+
53
+ ### Peer Dependencies
54
+
55
+ ```bash
56
+ npm install react@">=18.0.0 <20.0.0"
57
+ ```
58
+
59
+ All other dependencies (`@tanstack/react-form`, `@tanstack/react-query`, `jotai`, `axios`, `fast-deep-equal`, `fflate`) are bundled.
60
+
61
+ ---
62
+
63
+ ## Architecture
64
+
65
+ ```
66
+ @gaddario98/react-core
67
+ ├── state/ ← Jotai atom factory + compressed storage
68
+ ├── auth/ ← Authentication state (built on state/)
69
+ ├── notifications/ ← Toast/notification state (built on state/)
70
+ ├── localization/ ← i18n engine with ICU formatting (built on state/)
71
+ ├── form/ ← Dynamic form builder (built on TanStack Form + state/)
72
+ ├── queries/ ← Data fetching layer (built on TanStack Query + state/)
73
+ ├── pages/ ← Page orchestrator (composes form/ + queries/ + state/)
74
+ ├── providers/ ← Generic provider compositor
75
+ ├── utiles/ ← Utility functions (classnames, memoization)
76
+ └── config/ ← useCoreConfig — unified setup hook
77
+ ```
78
+
79
+ The **dependency flow** is bottom-up: `state/` is the foundation, `auth/`, `notifications/`, and `localization/` are state slices, `form/` and `queries/` are feature layers, and `pages/` orchestrates everything. `config/useCoreConfig` wires all modules together in a single hook.
80
+
81
+ ---
82
+
83
+ ## Quick Start — Unified Configuration
84
+
85
+ The `useCoreConfig` hook initializes all modules at once. Call it near the root of your app:
86
+
87
+ ```tsx
88
+ import { useCoreConfig, AppProviders, QueriesProvider } from "@gaddario98/react-core";
89
+
90
+ function CoreProvider({ children }: { children: React.ReactNode }) {
91
+ useCoreConfig({
92
+ localization: {
93
+ defaultLocale: "en",
94
+ supportedLocales: ["en", "it"],
95
+ locales: {
96
+ en: { common: { welcome: "Welcome" } },
97
+ it: { common: { welcome: "Benvenuto" } },
98
+ },
99
+ },
100
+ pages: {
101
+ PageContainer: ({ children, id }) => <main id={id}>{children}</main>,
102
+ BodyContainer: ({ children }) => <div className="body">{children}</div>,
103
+ defaultMetadata: { title: "My App" },
104
+ },
105
+ form: {
106
+ formFieldContainer: ({ children }) => <div className="field">{children}</div>,
107
+ },
108
+ apiConfig: {
109
+ endpoints: { api: "https://api.example.com" },
110
+ },
111
+ });
112
+
113
+ return <>{children}</>;
114
+ }
115
+
116
+ export default function App() {
117
+ return (
118
+ <AppProviders providers={[QueriesProvider]}>
119
+ <CoreProvider>
120
+ {/* your app */}
121
+ </CoreProvider>
122
+ </AppProviders>
123
+ );
124
+ }
125
+ ```
126
+
127
+ `useCoreConfig` automatically:
128
+ - Wires `translateText` from the localization module into forms and pages
129
+ - Wires `showNotification` into forms and queries
130
+ - Sets the `Authorization` header from `auth.token` on all API requests
131
+ - Passes `authValues` into pages for access control
132
+
133
+ ---
134
+
135
+ ## Modules
136
+
137
+ ### State (`/state`)
138
+
139
+ The foundational layer. Provides a factory function to create Jotai atoms with optional compressed persistence to `localStorage`.
140
+
141
+ ```tsx
142
+ import { atomStateGenerator } from "@gaddario98/react-core/state";
143
+
144
+ const {
145
+ atom: themeAtom,
146
+ useValue: useThemeValue, // read-only hook
147
+ useState: useThemeState, // [value, setter] hook
148
+ useReset: useThemeReset, // reset to default
149
+ } = atomStateGenerator<"light" | "dark">({
150
+ key: "app-theme",
151
+ defaultValue: "light",
152
+ persist: true, // compressed localStorage persistence
153
+ });
154
+ ```
155
+
156
+ **Storage features:**
157
+ - Data < 1 KB stored as raw JSON; larger payloads are deflated (fflate) and base64-encoded
158
+ - Writes are debounced (50 ms) and flushed on `beforeunload` / `visibilitychange`
159
+ - Swap the storage backend via `setCustomStorage(myStorage)` (e.g., AsyncStorage for React Native)
160
+
161
+ **Exports:**
162
+
163
+ | Export | Description |
164
+ |---|---|
165
+ | `atomStateGenerator<T>(options)` | Creates an atom with `useValue`, `useState`, `useReset` hooks |
166
+ | `storage` | Default compressed storage singleton |
167
+ | `setCustomStorage(s)` | Replace the storage backend |
168
+
169
+ ---
170
+
171
+ ### Auth (`/auth`)
172
+
173
+ A persisted authentication state slice.
174
+
175
+ ```tsx
176
+ import { useAuthState, useAuthValue } from "@gaddario98/react-core/auth";
177
+
178
+ // Read auth state
179
+ const auth = useAuthValue();
180
+ console.log(auth?.token, auth?.isLogged);
181
+
182
+ // Update auth state
183
+ const [auth, setAuth] = useAuthState();
184
+ setAuth({ id: "user-1", token: "jwt...", isLogged: true });
185
+
186
+ // Clear on logout
187
+ setAuth(null);
188
+ ```
189
+
190
+ **`AuthState` type:**
191
+
192
+ ```ts
193
+ type AuthState = {
194
+ id: string;
195
+ accountVerified?: boolean;
196
+ isLogged?: boolean;
197
+ token?: string;
198
+ phoneNumber?: string;
199
+ email?: string;
200
+ }
201
+ ```
202
+
203
+ The atom is persisted under the key `"reactAuthStore"` using compressed storage.
204
+
205
+ ---
206
+
207
+ ### Notifications (`/notifications`)
208
+
209
+ In-memory notification state for toast/snackbar systems.
210
+
211
+ ```tsx
212
+ import { useNotification } from "@gaddario98/react-core/notifications";
213
+
214
+ const { showNotification, clearNotification } = useNotification("myPage");
215
+
216
+ showNotification({
217
+ message: "Profile updated!",
218
+ type: "success",
219
+ autoHideDuration: 3000,
220
+ });
221
+ ```
222
+
223
+ **`NotificationMessage` type:**
224
+
225
+ ```ts
226
+ interface NotificationMessage {
227
+ id: string;
228
+ message: string;
229
+ type: "success" | "error" | "info" | "warning";
230
+ autoHideDuration?: number;
231
+ textTransOption?: Record<string, unknown>;
232
+ ns?: string;
233
+ }
234
+ ```
235
+
236
+ **Exports:**
237
+
238
+ | Export | Description |
239
+ |---|---|
240
+ | `useNotification(ns?)` | Returns `{ showNotification, clearNotification }` |
241
+ | `useNotificationValue()` | Read current notification |
242
+ | `useNotificationState()` | `[notification, setter]` tuple |
243
+ | `notificationAtom` | Raw Jotai atom |
244
+
245
+ ---
246
+
247
+ ### Localization (`/localization`)
248
+
249
+ A built-in i18n engine with no external library dependencies. Supports ICU-style interpolation, pluralization, gender selection, and number/date/currency formatting.
250
+
251
+ ```tsx
252
+ import { useTranslation, useLocalizationActions } from "@gaddario98/react-core/localization";
253
+
254
+ // Initialize locales at app startup
255
+ const { initializeLocale, switchLocale, addLocale } = useLocalizationActions();
256
+
257
+ initializeLocale({
258
+ defaultLocale: "en",
259
+ supportedLocales: ["en", "it"],
260
+ locales: {
261
+ en: { shop: { items: "{{count, plural, =0{No items} one{1 item} other{# items}}}" } },
262
+ it: { shop: { items: "{{count, plural, =0{Nessun articolo} one{1 articolo} other{# articoli}}}" } },
263
+ },
264
+ });
265
+
266
+ // Use translations
267
+ const { t, locale } = useTranslation("shop");
268
+ t("items", { count: 5 }); // "5 items"
269
+ ```
270
+
271
+ **Supported interpolation patterns:**
272
+ - `{{name}}` — simple variable substitution
273
+ - `{{count, number}}` — number formatting (locale-aware)
274
+ - `{{date, date}}` — date formatting
275
+ - `{{price, currency}}` — currency formatting
276
+ - `{{count, plural, =0{...} one{...} other{...}}}` — ICU plural rules
277
+ - `{{gender, select, male{...} female{...} other{...}}}` — gender/select
278
+
279
+ **Server-side usage (outside React):**
280
+
281
+ ```ts
282
+ import { createServerTranslator } from "@gaddario98/react-core/localization";
283
+
284
+ const { t } = createServerTranslator(resources, "en");
285
+ t("shop.items", { count: 3 }); // "3 items"
286
+ ```
287
+
288
+ ---
289
+
290
+ ### Form (`/form`)
291
+
292
+ A dynamic, type-safe form builder on top of TanStack React Form. Renders fields from a declarative configuration array.
293
+
294
+ ```tsx
295
+ import { FormManager } from "@gaddario98/react-core/form";
296
+
297
+ interface ContactForm {
298
+ name: string;
299
+ email: string;
300
+ }
301
+
302
+ <FormManager<ContactForm>
303
+ defaultValues={{ name: "", email: "" }}
304
+ data={[
305
+ {
306
+ name: "name",
307
+ label: "Full Name",
308
+ rules: { onChange: (val) => (!val ? "Required" : undefined) },
309
+ component: (props) => <input value={props.value} onChange={(e) => props.onChange(e.target.value)} />,
310
+ },
311
+ {
312
+ name: "email",
313
+ label: "Email",
314
+ component: (props) => <input value={props.value} onChange={(e) => props.onChange(e.target.value)} />,
315
+ },
316
+ ]}
317
+ submit={[
318
+ {
319
+ component: ({ onClick }) => <button onClick={onClick}>Save</button>,
320
+ onSuccess: async (values) => console.log(values),
321
+ },
322
+ ]}
323
+ />
324
+ ```
325
+
326
+ **Key features:**
327
+ - Static or dynamic field definitions (factory functions with `{ get, set }` access to current values)
328
+ - Partial form submission — validate only a subset of fields via `values: ["field1", "field2"]`
329
+ - Custom layout containers via `viewSettings` (dialogs, cards, drawers)
330
+ - Built-in notification integration for success/error feedback
331
+ - Headless alternative via `useFormManager` hook
332
+
333
+ **Global configuration:**
334
+
335
+ ```tsx
336
+ import { useFormConfigState } from "@gaddario98/react-core/form";
337
+
338
+ const [, setFormConfig] = useFormConfigState();
339
+ setFormConfig((prev) => ({
340
+ ...prev,
341
+ translateText: (key, opts) => t(key, opts),
342
+ formFieldContainer: MyFieldWrapper,
343
+ showNotification: (msg) => toast(msg.message),
344
+ }));
345
+ ```
346
+
347
+ For full API details, see [github.com/gaddario98/react-form](https://github.com/gaddario98/react-form).
348
+
349
+ ---
350
+
351
+ ### Queries (`/queries`)
352
+
353
+ A unified data fetching layer on top of TanStack React Query and Jotai. Manages queries, mutations, and WebSockets through a single declarative API.
354
+
355
+ ```tsx
356
+ import { useApi } from "@gaddario98/react-core/queries";
357
+ import type { QueriesArray } from "@gaddario98/react-core/queries";
358
+
359
+ const queries = [
360
+ {
361
+ type: "query",
362
+ key: "products",
363
+ queryConfig: {
364
+ endpoint: ["api", "v1/products"],
365
+ queryKey: ["products"],
366
+ },
367
+ },
368
+ {
369
+ type: "mutation",
370
+ key: "addProduct",
371
+ mutationConfig: {
372
+ endpoint: ["api", "v1/products"],
373
+ method: "POST",
374
+ queryKeyToInvalidate: ["products"],
375
+ },
376
+ },
377
+ ] as const satisfies QueriesArray;
378
+
379
+ const { allQuery, allMutation, refreshQueries } = useApi(queries, {
380
+ scopeId: "product-page",
381
+ });
382
+
383
+ const products = allQuery.products.data;
384
+ allMutation.addProduct.mutate({ body: { name: "New Product" } });
385
+ ```
386
+
387
+ **Key features:**
388
+ - Typed `allQuery` / `allMutation` / `allWebSocket` maps from the configuration array
389
+ - Automatic Jotai atom sync — query results are accessible cross-component without refetching
390
+ - Fine-grained subscriptions via `useApiValues` (re-render only on specific path changes)
391
+ - Built-in WebSocket support alongside REST queries
392
+ - Payload encryption/decryption (AES-GCM)
393
+ - Offline persistence via TanStack Query Persist
394
+ - Standalone `useQueryApi` / `useMutateApi` hooks for simpler one-off usage
395
+
396
+ **Global configuration:**
397
+
398
+ ```tsx
399
+ import { useApiConfigState } from "@gaddario98/react-core/queries";
400
+
401
+ const [, setApiConfig] = useApiConfigState();
402
+ setApiConfig({
403
+ endpoints: { api: "https://api.example.com" },
404
+ defaultHeaders: { "Cache-Control": "no-cache" },
405
+ validateAuthFn: () => !!localStorage.getItem("token"),
406
+ queryClient: new QueryClient({ defaultOptions: { queries: { retry: 2 } } }),
407
+ });
408
+ ```
409
+
410
+ Wrap your app with `QueriesProvider` to initialize the TanStack QueryClient:
411
+
412
+ ```tsx
413
+ import { QueriesProvider } from "@gaddario98/react-core/queries";
414
+
415
+ <QueriesProvider>
416
+ <App />
417
+ </QueriesProvider>
418
+ ```
419
+
420
+ For full API details, see [github.com/gaddario98/react-queries](https://github.com/gaddario98/react-queries).
421
+
422
+ ---
423
+
424
+ ### Pages (`/pages`)
425
+
426
+ A page orchestrator that composes forms, queries, metadata, lazy loading, and layout into a single `PageProps` configuration. Works on both web and React Native.
427
+
428
+ ```tsx
429
+ import { PageGenerator } from "@gaddario98/react-core/pages";
430
+ import type { PageProps, QueryDefinition } from "@gaddario98/react-core/pages";
431
+
432
+ interface MyForm { search: string }
433
+ type MyQueries = [QueryDefinition<"results", "query", never, Product[]>];
434
+
435
+ const props: PageProps<MyForm, MyQueries> = {
436
+ id: "search-page",
437
+ meta: { title: "Search", description: "Find products" },
438
+ form: {
439
+ defaultValues: { search: "" },
440
+ data: [{ name: "search", debounceDelay: 300, component: SearchInput }],
441
+ },
442
+ queries: [
443
+ {
444
+ type: "query",
445
+ key: "results",
446
+ queryConfig: ({ get }) => ({
447
+ queryKey: ["results", get("form", "search")],
448
+ queryFn: () => fetchProducts(get("form", "search")),
449
+ enabled: get("form", "search", "").length > 2,
450
+ }),
451
+ },
452
+ ],
453
+ contents: [
454
+ {
455
+ type: "custom",
456
+ component: ({ get }) => {
457
+ const results = get("query", "results.data", []);
458
+ return <ProductList products={results} />;
459
+ },
460
+ },
461
+ ],
462
+ };
463
+
464
+ <PageGenerator<MyForm, MyQueries> {...props} />;
465
+ ```
466
+
467
+ **Key features:**
468
+ - `get()` / `set()` API with automatic dependency tracking (90% fewer re-renders)
469
+ - Dynamic SEO metadata (Open Graph, Twitter Card, JSON-LD, AI hints, robots)
470
+ - Lazy loading with viewport, interaction, or conditional triggers
471
+ - Lifecycle callbacks (`onMountComplete`, `onQuerySuccess`, `onQueryError`, `onFormSubmit`, `onValuesChange`)
472
+ - Authentication gate via `enableAuthControl`
473
+ - Platform overrides via `platformOverrides: { web: {...}, native: {...} }`
474
+
475
+ For full API details, see [github.com/gaddario98/react-pages](https://github.com/gaddario98/react-pages).
476
+
477
+ ---
478
+
479
+ ### Providers (`/providers`)
480
+
481
+ A utility component that composes multiple React providers without deep nesting.
482
+
483
+ ```tsx
484
+ import { AppProviders } from "@gaddario98/react-core/providers";
485
+
486
+ <AppProviders
487
+ providers={[
488
+ QueriesProvider,
489
+ [ThemeProvider, { theme: "dark" }],
490
+ [IntlProvider, { locale: "en" }],
491
+ ]}
492
+ >
493
+ <App />
494
+ </AppProviders>
495
+ ```
496
+
497
+ Supports both bare components and `[Component, props]` tuples. Providers are composed in declaration order (first = outermost).
498
+
499
+ ---
500
+
501
+ ### Utilities (`/utiles`)
502
+
503
+ General-purpose React and JavaScript utilities.
504
+
505
+ ```tsx
506
+ import { cn, withMemo } from "@gaddario98/react-core/utiles";
507
+ ```
508
+
509
+ | Export | Description |
510
+ |---|---|
511
+ | `cn(...inputs)` | Combines `clsx` + `tailwind-merge` for safe Tailwind class merging |
512
+ | `withMemo(Component, areEqual?)` | Type-safe `React.memo` wrapper that preserves generic types |
513
+ | `createExtractor(data, cache?, keys?)` | Picks a subset of keys from an object with stable reference caching |
514
+
515
+ ---
516
+
517
+ ### Config (`/config`)
518
+
519
+ The unified configuration hook that wires all modules together.
520
+
521
+ ```tsx
522
+ import { useCoreConfig } from "@gaddario98/react-core/config";
523
+ ```
524
+
525
+ **`CoreConfig` interface:**
526
+
527
+ ```ts
528
+ interface CoreConfig {
529
+ form?: Partial<FormConfigProps>;
530
+ localization?: LocalizationConfigProps;
531
+ pages?: Partial<PageConfigProps>;
532
+ apiConfig?: Partial<ApiConfig>;
533
+ }
534
+ ```
535
+
536
+ See [Quick Start](#quick-start--unified-configuration) for usage.
537
+
538
+ **What `useCoreConfig` wires automatically:**
539
+
540
+ | Source | Target | What |
541
+ |---|---|---|
542
+ | `localization` | `form`, `pages` | `translateText` function |
543
+ | `notifications` | `form`, `queries` | `showNotification` handler |
544
+ | `auth` | `queries` | `Authorization` header (Bearer token) |
545
+ | `auth` | `queries` | `validateAuthFn` (auth validation) |
546
+ | `auth` | `pages` | `authValues` (access control) |
547
+
548
+ ---
549
+
550
+ ## Entry Points
551
+
552
+ The package exposes 10 sub-path exports for tree-shaking:
553
+
554
+ | Import Path | Module | Typical Use |
555
+ |---|---|---|
556
+ | `@gaddario98/react-core` | All modules | Full framework access |
557
+ | `@gaddario98/react-core/state` | State | Atom factory, storage |
558
+ | `@gaddario98/react-core/auth` | Auth | Authentication state |
559
+ | `@gaddario98/react-core/notifications` | Notifications | Toast state |
560
+ | `@gaddario98/react-core/localization` | Localization | i18n engine |
561
+ | `@gaddario98/react-core/form` | Form | Form builder |
562
+ | `@gaddario98/react-core/queries` | Queries | Data fetching |
563
+ | `@gaddario98/react-core/pages` | Pages | Page orchestrator |
564
+ | `@gaddario98/react-core/providers` | Providers | Provider compositor |
565
+ | `@gaddario98/react-core/utiles` | Utilities | Helpers |
566
+
567
+ ---
568
+
569
+ ## Cross-Platform Support
570
+
571
+ The entire package is platform-agnostic. No module imports `react-dom` or `react-native` directly.
572
+
573
+ **Web**: Works out of the box. Metadata is written to `document.head`.
574
+
575
+ **React Native**: Replace the storage backend and layout containers:
576
+
577
+ ```tsx
578
+ import { setCustomStorage } from "@gaddario98/react-core/state";
579
+ import { usePageConfigState } from "@gaddario98/react-core/pages";
580
+ import AsyncStorage from "@react-native-async-storage/async-storage";
581
+ import { View, ScrollView } from "react-native";
582
+
583
+ // Swap storage for React Native
584
+ setCustomStorage({
585
+ getItem: (key) => AsyncStorage.getItem(key) ?? null,
586
+ setItem: (key, val) => { AsyncStorage.setItem(key, val) },
587
+ removeItem: (key) => { AsyncStorage.removeItem(key) },
588
+ });
589
+
590
+ // Swap layout containers
591
+ const [, setPageConfig] = usePageConfigState();
592
+ setPageConfig((prev) => ({
593
+ ...prev,
594
+ PageContainer: ({ children, id }) => <View style={{ flex: 1 }}>{children}</View>,
595
+ BodyContainer: ({ children }) => <ScrollView>{children}</ScrollView>,
596
+ HeaderContainer: ({ children }) => <View>{children}</View>,
597
+ FooterContainer: ({ children }) => <View>{children}</View>,
598
+ ItemsContainer: ({ children }) => <View>{children}</View>,
599
+ }));
7
600
  ```
8
601
 
9
- ## Usage
602
+ See the [React Native Integration Strategy](https://github.com/gaddario98/react-pages#react-native-integration-strategy) in the pages documentation for a full setup guide.
603
+
604
+ ---
605
+
606
+ ## TypeScript Support
607
+
608
+ All modules are fully typed with generics. Key generic interfaces:
609
+
610
+ ```ts
611
+ // Form — generic over field values
612
+ FormManager<F extends FieldValues>
613
+ FormManagerProps<F extends FieldValues>
614
+
615
+ // Queries — generic over query array definition
616
+ useApi<Q extends QueriesArray>(queries: Q, options)
617
+ QueriesArray // tuple of query/mutation/websocket definitions
618
+
619
+ // Pages — generic over form, queries, and page variables
620
+ PageGenerator<F extends FieldValues, Q extends QueriesArray, V extends Record<string, unknown>>
621
+ PageProps<F, Q, V>
622
+ FunctionProps<F, Q, V> // the { get, set } interface
623
+
624
+ // State — generic over atom value type
625
+ atomStateGenerator<T>(options): AtomState<T>
626
+ ```
627
+
628
+ ---
629
+
630
+ ## Contributing
631
+
632
+ Contributions are welcome! Please feel free to submit a Pull Request.
633
+
634
+ - [Open an issue](https://github.com/gaddario98/react-core/issues)
635
+ - [Repository](https://github.com/gaddario98/react-core)
10
636
 
11
- [Add usage examples here]
637
+ ---
12
638
 
13
639
  ## License
14
640