@solid/react-component 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/README.md +279 -0
- package/dist/index.cjs +945 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +918 -0
- package/dist/index.js.map +1 -0
- package/dist/login/index.cjs +945 -0
- package/dist/login/index.cjs.map +1 -0
- package/dist/login/index.d.cts +41 -0
- package/dist/login/index.d.ts +41 -0
- package/dist/login/index.js +918 -0
- package/dist/login/index.js.map +1 -0
- package/dist/login/next.cjs +924 -0
- package/dist/login/next.cjs.map +1 -0
- package/dist/login/next.d.cts +16 -0
- package/dist/login/next.d.ts +16 -0
- package/dist/login/next.js +904 -0
- package/dist/login/next.js.map +1 -0
- package/dist/navigation-8m8VBbGz.d.cts +103 -0
- package/dist/navigation-8m8VBbGz.d.ts +103 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# @solid/react-component
|
|
2
|
+
|
|
3
|
+
Reusable React components for Solid apps. One package that will grow to include login, profile, and other components—so you depend on a single library instead of many.
|
|
4
|
+
|
|
5
|
+
**Currently included:**
|
|
6
|
+
|
|
7
|
+
- **Login** – Solid OIDC login UI and auth guard. Two-column layout (branding + form), combobox-style provider picker, optional footer links. Next.js adapter included.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- **React** 18+
|
|
14
|
+
- **[@ldo/solid-react](https://www.npmjs.com/package/@ldo/solid-react)** – Your app must be wrapped in `BrowserSolidLdoProvider` (or `SolidLdoProvider`) so auth and session work.
|
|
15
|
+
|
|
16
|
+
For the **Next.js** login adapter you also need **Next.js 13+** (App Router).
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm i @solid/react-component @ldo/solid-react react
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For Next.js apps:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm i @solid/react-component @ldo/solid-react next react
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Login – Next.js implementation
|
|
35
|
+
|
|
36
|
+
### 1. Wrap the app with LDO’s provider
|
|
37
|
+
|
|
38
|
+
Your app must use `BrowserSolidLdoProvider` from `@ldo/solid-react` so session and login work.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// app/layout.tsx
|
|
42
|
+
import { BrowserSolidLdoProvider } from "@ldo/solid-react";
|
|
43
|
+
|
|
44
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
45
|
+
return (
|
|
46
|
+
<html lang="en">
|
|
47
|
+
<body>
|
|
48
|
+
<BrowserSolidLdoProvider>{children}</BrowserSolidLdoProvider>
|
|
49
|
+
</body>
|
|
50
|
+
</html>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 2. Protect routes with the auth guard
|
|
56
|
+
|
|
57
|
+
Wrap the part of the tree that requires authentication in **Suspense**, **SolidLoginNavigationProviderNext**, and **AuthGuard**. Use the same config for both the home page and the login page.
|
|
58
|
+
|
|
59
|
+
**Config:**
|
|
60
|
+
|
|
61
|
+
- `loginPath` – Path to your login page (e.g. `"/login"`). Unauthenticated users are redirected here.
|
|
62
|
+
- `homePath` – Path after login when there is no `returnTo` (e.g. `"/"`).
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
// app/page.tsx (home or any protected page)
|
|
66
|
+
"use client";
|
|
67
|
+
|
|
68
|
+
import { Suspense } from "react";
|
|
69
|
+
import { SolidLoginNavigationProviderNext, AuthGuard } from "@solid/react-component/login/next";
|
|
70
|
+
|
|
71
|
+
const loadingFallback = (
|
|
72
|
+
<div style={{ display: "flex", minHeight: "100vh", alignItems: "center", justifyContent: "center" }}>
|
|
73
|
+
<span>Loading...</span>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
export default function Home() {
|
|
78
|
+
return (
|
|
79
|
+
<Suspense fallback={loadingFallback}>
|
|
80
|
+
<SolidLoginNavigationProviderNext config={{ loginPath: "/login", homePath: "/" }}>
|
|
81
|
+
<AuthGuard fallback={loadingFallback}>
|
|
82
|
+
<YourMainApp />
|
|
83
|
+
</AuthGuard>
|
|
84
|
+
</SolidLoginNavigationProviderNext>
|
|
85
|
+
</Suspense>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 3. Add the login page
|
|
91
|
+
|
|
92
|
+
Render **SolidLoginPage** on your login route. Pass the **logo** from your app (the package does not ship assets). You can also pass **footer** URLs so the default footer shows “GitHub” and “Report an issue” links.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
// app/login/page.tsx
|
|
96
|
+
"use client";
|
|
97
|
+
|
|
98
|
+
import { Suspense } from "react";
|
|
99
|
+
import { useRouter } from "next/navigation";
|
|
100
|
+
import {
|
|
101
|
+
SolidLoginNavigationProviderNext,
|
|
102
|
+
AuthGuard,
|
|
103
|
+
SolidLoginPage,
|
|
104
|
+
} from "@solid/react-component/login/next";
|
|
105
|
+
|
|
106
|
+
const loadingFallback = (
|
|
107
|
+
<div style={{ display: "flex", minHeight: "100vh", alignItems: "center", justifyContent: "center" }}>
|
|
108
|
+
<span>Loading...</span>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
export default function Login() {
|
|
113
|
+
const router = useRouter();
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<Suspense fallback={loadingFallback}>
|
|
117
|
+
<SolidLoginNavigationProviderNext config={{ loginPath: "/login", homePath: "/" }}>
|
|
118
|
+
<AuthGuard fallback={loadingFallback}>
|
|
119
|
+
<SolidLoginPage
|
|
120
|
+
onAlreadyLoggedIn={() => router.replace("/")}
|
|
121
|
+
logo="/your-logo.svg"
|
|
122
|
+
logoAlt="My App Logo"
|
|
123
|
+
title="Sign in"
|
|
124
|
+
subtitle="to continue to My App"
|
|
125
|
+
footerGitHubUrl="https://github.com/your-org/your-app"
|
|
126
|
+
footerIssuesUrl="https://github.com/your-org/your-app/issues/new"
|
|
127
|
+
/>
|
|
128
|
+
</AuthGuard>
|
|
129
|
+
</SolidLoginNavigationProviderNext>
|
|
130
|
+
</Suspense>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Custom redirect after login
|
|
136
|
+
|
|
137
|
+
By default, the IdP redirects back to the login page URL after authentication. If you want the user to land on a different page (e.g. your home page with a query param), pass `redirectUrl`:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
<SolidLoginPage
|
|
141
|
+
redirectUrl={`${window.location.origin}/?showModal=true`}
|
|
142
|
+
onAlreadyLoggedIn={() => router.replace("/")}
|
|
143
|
+
logo="/logo.svg"
|
|
144
|
+
title="Sign in"
|
|
145
|
+
subtitle="to continue to My App"
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
This tells the IdP to send the user straight to `/?showModal=true` instead of back to `/login`, avoiding a visible bounce through the login page.
|
|
150
|
+
|
|
151
|
+
### 4. Next.js config (recommended)
|
|
152
|
+
|
|
153
|
+
If you use the package from npm, add it to `transpilePackages` so Next resolves the package’s subpath exports correctly:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
// next.config.ts
|
|
157
|
+
import type { NextConfig } from "next";
|
|
158
|
+
|
|
159
|
+
const nextConfig: NextConfig = {
|
|
160
|
+
transpilePackages: ["@solid/react-component"],
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export default nextConfig;
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## How auth and redirects work
|
|
169
|
+
|
|
170
|
+
### Session restore on refresh
|
|
171
|
+
|
|
172
|
+
The guard uses **LDO’s `ranInitialAuthCheck`** from `useSolidAuth()`. It shows the loading fallback until the initial auth check (including session restore from storage) has finished. Only then does it decide whether to redirect to login. So **refreshing while already logged in does not send you to the login page**; you stay on the same URL.
|
|
173
|
+
|
|
174
|
+
See [LDO useSolidAuth](https://ldo.js.org/1.0.0-alpha.X/api/solid-react/useSolidAuth/) for `ranInitialAuthCheck`.
|
|
175
|
+
|
|
176
|
+
### returnTo (deep link back after login)
|
|
177
|
+
|
|
178
|
+
- When an unauthenticated user hits a protected path (e.g. `/dashboard/settings`), the guard redirects to `/login?returnTo=%2Fdashboard%2Fsettings`.
|
|
179
|
+
- After successful login (including after the OAuth redirect), the guard redirects to the `returnTo` path if it’s present and safe (starts with `/`, not `//`). If the IdP strips query params on callback, the package stores `returnTo` in `sessionStorage` when you land on the login page and uses it after the callback.
|
|
180
|
+
- If there is no valid `returnTo`, the user is sent to `homePath` (e.g. `"/"`).
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## SolidLoginPage – props reference
|
|
185
|
+
|
|
186
|
+
| Prop | Type | Description |
|
|
187
|
+
|------|------|-------------|
|
|
188
|
+
| `onAlreadyLoggedIn` | `() => void` | Called when the user is already logged in (e.g. `() => router.replace("/")`). |
|
|
189
|
+
| `redirectUrl` | `string` | URL the IdP should redirect back to after authentication. Defaults to `window.location.href` (the login page). Useful when you want the IdP to send the user straight to a different page (e.g. `"/?showModal=true"`) instead of back to `/login`. |
|
|
190
|
+
| `logo` | `string` | **Required from your app.** URL to your logo image (e.g. `"/logo.svg"`). Not shipped in the package. |
|
|
191
|
+
| `logoAlt` | `string` | Alt text for the logo image. |
|
|
192
|
+
| `title` | `string` | Heading on the branding side (default: `"Sign in"`). |
|
|
193
|
+
| `subtitle` | `string` | Subheading (default: `"to continue"`). |
|
|
194
|
+
| `footerGitHubUrl` | `string` | If set with `footerIssuesUrl`, shows a footer with “GitHub” and “Report an issue” links. |
|
|
195
|
+
| `footerIssuesUrl` | `string` | See `footerGitHubUrl`. |
|
|
196
|
+
| `inputPlaceholder` | `string` | Placeholder for the provider URL input. |
|
|
197
|
+
| `inputLabel` | `string` | Label above the input (default: `"Solid Identity Provider"`). |
|
|
198
|
+
| `buttonLabel` | `string` | Submit button text (default: `"Next"`). |
|
|
199
|
+
| `buttonLoadingLabel` | `string` | Submit button text while logging in (default: `"Signing in..."`). |
|
|
200
|
+
| `defaultIssuer` | `string` | Pre-fill the issuer input. |
|
|
201
|
+
| `presetIssuers` | `PresetIssuer[]` | Options in the dropdown (default: Solid Community, Inrupt). |
|
|
202
|
+
| `className` | `string` | Extra class on the main container. |
|
|
203
|
+
| `renderLogo` | `() => ReactNode` | Replace the default logo block. |
|
|
204
|
+
| `renderForm` | `(props) => ReactNode` | Replace the entire form (see headless usage). |
|
|
205
|
+
| `renderFooter` | `() => ReactNode` | Replace the default footer. |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Customizing the login page
|
|
210
|
+
|
|
211
|
+
- **Logo:** Pass `logo="/path/to/logo.svg"` from your app’s `public` (or asset URL). The package does not include assets.
|
|
212
|
+
- **Footer links:** Set `footerGitHubUrl` and `footerIssuesUrl` to show the default “GitHub” and “Report an issue” links. Or use `renderFooter` for a custom footer.
|
|
213
|
+
- **Full custom form:** Use `renderForm` and receive `{ issuerInput, setIssuerInput, error, presetIssuers, isLoading, onSubmit, onIssuerChange }` to build your own UI while keeping auth logic.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Import paths
|
|
218
|
+
|
|
219
|
+
| Import from | Use for |
|
|
220
|
+
|-------------|--------|
|
|
221
|
+
| `@solid/react-component/login/next` | Next.js: `SolidLoginNavigationProviderNext`, `AuthGuard`, `SolidLoginPage`. Use in App Router pages. |
|
|
222
|
+
| `@solid/react-component/login` | Core login: `AuthGuard`, `SolidLoginPage`, `useSolidLogin`, `LoginFormControl`, etc. You provide navigation via `SolidLoginNavigationProvider`. |
|
|
223
|
+
| `@solid/react-component` | Barrel; re-exports from the login entry. Prefer subpaths above for clearer imports. |
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Headless login
|
|
228
|
+
|
|
229
|
+
If you want your own UI and only need the auth logic:
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { useSolidLogin, LoginFormControl, validateIssuerUrl } from "@solid/react-component/login";
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
- **`useSolidLogin({ defaultIssuer, presetIssuers, onAlreadyLoggedIn, redirectUrl })`** – Returns `session`, `issuerInput`, `setIssuerInput`, `isLoading`, `error`, `presetIssuers`, `validateAndSubmit`.
|
|
236
|
+
- **`LoginFormControl`** – Render-prop component that provides the same state and handlers to children.
|
|
237
|
+
- **`validateIssuerUrl(url)`** – Returns `{ valid: boolean, error: string | null }`.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## AuthGuard – fallback
|
|
242
|
+
|
|
243
|
+
`AuthGuard` accepts an optional **`fallback`** prop (e.g. a loading spinner). It is shown:
|
|
244
|
+
|
|
245
|
+
- Until LDO’s initial auth check has run (`ranInitialAuthCheck`).
|
|
246
|
+
- During the OAuth callback (when the URL has `code` and `state`).
|
|
247
|
+
|
|
248
|
+
Use the same fallback in both your protected pages and the login page for a consistent loading state.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Package structure
|
|
253
|
+
|
|
254
|
+
| Subpath | Contents |
|
|
255
|
+
|--------|----------|
|
|
256
|
+
| `@solid/react-component` | Re-exports (barrel). |
|
|
257
|
+
| `@solid/react-component/login` | Login: guard, page, hooks, types. |
|
|
258
|
+
| `@solid/react-component/login/next` | Login + Next.js adapter (provider + guard + page). |
|
|
259
|
+
|
|
260
|
+
Future components (e.g. profile) can follow the same pattern: `@solid/react-component/profile`, `@solid/react-component/profile/next`, etc.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Building and publishing
|
|
265
|
+
|
|
266
|
+
From the package directory:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
npm run build
|
|
270
|
+
npm publish
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Unscoped packages are public by default. Bump `version` in `package.json` before each publish.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
MIT
|