@optare/react 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Optare
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # @optare/react
2
+
3
+ React bindings for Optare — a provider, session hooks, and drop-in **white-label**
4
+ sign-in / sign-up / account components. Built on [`@optare/client`](../client).
5
+
6
+ The entire integration contract is one string: a publishable key (`pk_live_…`).
7
+ It is **not** a secret — it ships in your browser bundle — so the SDK uses it to
8
+ look up, from a public endpoint, where the auth API lives and what the project's
9
+ branding is (logo, name, primary colour, corner radius). That is how a customer
10
+ gets a branded login screen without hosting anything.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @optare/react
16
+ # peer deps: react >= 18, react-dom >= 18
17
+ ```
18
+
19
+ ## Quick start
20
+
21
+ ```tsx
22
+ import { OptareProvider, SignIn, AccountButton, useSession } from "@optare/react";
23
+
24
+ function Root() {
25
+ return (
26
+ <OptareProvider publishableKey={import.meta.env.VITE_OPTARE_PK}>
27
+ <App />
28
+ </OptareProvider>
29
+ );
30
+ }
31
+
32
+ function App() {
33
+ const { isPending, isAuthenticated, user } = useSession();
34
+ if (isPending) return null;
35
+ return isAuthenticated ? (
36
+ <>
37
+ <p>Hello {user?.name}</p>
38
+ <AccountButton />
39
+ </>
40
+ ) : (
41
+ <SignIn onSuccess={() => location.assign("/dashboard")} />
42
+ );
43
+ }
44
+ ```
45
+
46
+ Nothing above configures branding — the provider resolves it from the key and
47
+ every component renders against `--optare-*` CSS variables you can override.
48
+
49
+ ## SSR
50
+
51
+ Resolve the config on the server and hand it to the provider as `bootstrap` to
52
+ skip the client-side fetch:
53
+
54
+ ```tsx
55
+ import { resolveOptareConfig } from "@optare/react";
56
+
57
+ const bootstrap = await resolveOptareConfig({ publishableKey: process.env.OPTARE_PK! });
58
+ // ...serialize `bootstrap` into the page, then:
59
+ <OptareProvider publishableKey={pk} bootstrap={bootstrap}>{children}</OptareProvider>
60
+ ```
61
+
62
+ ## API
63
+
64
+ ### `<OptareProvider>`
65
+
66
+ | prop | type | notes |
67
+ |---|---|---|
68
+ | `publishableKey` | `string` | required |
69
+ | `bootstrap` | `OptareBootstrap` | pre-resolved config; skips the network |
70
+ | `baseURL` | `string` | override the auth API origin (self-hosted / preview) |
71
+ | `configURL` | `string` | where `GET /api/public/config` lives; defaults to `baseURL` then the hosted origin |
72
+ | `fetch` | `typeof fetch` | custom fetch (tests, RN) |
73
+ | `loadingFallback` / `errorFallback` | `ReactNode` \| `(err, retry) => ReactNode` | optional gates; default is optimistic (render children, expose `status`) |
74
+
75
+ ### Hooks
76
+
77
+ - `useOptare()` — `{ status, error, bootstrap, branding, project, cssVars, auth, retry }`
78
+ - `useOptareAuth()` — the better-auth React client (throws until `status === "ready"`)
79
+ - `useSession()` — `{ data, user, isPending, isAuthenticated, error, refetch }`
80
+ - `useUser()` — the current user or `null`
81
+ - `useSignOut()` — `{ signOut, isPending, error }`
82
+ - `useActiveOrganization()` — `{ activeOrganizationId, setActive, isPending }`
83
+ - `useBranding()` / `useOptareConfig()`
84
+
85
+ ### Components
86
+
87
+ - `<SignIn />` — email + password, optional magic-link path, 2FA-challenge
88
+ callback (`onTwoFactor`), `onSuccess` / `redirectTo`.
89
+ - `<SignUp />` — name + email + password with a strength meter; the landing
90
+ organization is decided server-side from the publishable key (F6).
91
+ `onVerificationRequired` fires when an email must be confirmed first.
92
+ - `<AccountButton />` — avatar + dropdown (profile slot, sign out); renders
93
+ `signInSlot` (or nothing) when signed out.
94
+
95
+ ### Theming
96
+
97
+ `brandingToCssVars(branding)` returns the `--optare-*` map the provider applies.
98
+ All colour/length values from branding are sanitised (`safeColor`, `safeLength`)
99
+ so a project's branding string can never inject CSS. Override any variable in
100
+ your own stylesheet, or pass `style` / `className` to a component.
101
+
102
+ ## Server-side
103
+
104
+ `sk_live_` management calls and offline JWT verification are **not** in this
105
+ package — use [`@optare/node`](../node).
106
+
107
+ ## Versioning
108
+
109
+ See [`docs/SDK_VERSIONING.md`](../../docs/SDK_VERSIONING.md). Pre-1.0: minor =
110
+ breaking, patch = fixes.