@sypra-ui/pages 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
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,30 @@
1
+ # @sypra-ui/pages
2
+
3
+ Reusable frontend-only page compositions. Supply data and callbacks; no
4
+ provider, API, or router is required.
5
+
6
+ ## Install
7
+
8
+ ```sh
9
+ pnpm add @sypra-ui/ui @sypra-ui/pages
10
+ ```
11
+
12
+ Pages use `@sypra-ui/ui` for all visual styling. Follow the UI package's
13
+ Tailwind setup and import `@sypra-ui/ui/styles.css` once. Include both package
14
+ builds in Tailwind's content configuration:
15
+
16
+ ```ts
17
+ // tailwind.config.ts
18
+ export default {
19
+ content: [
20
+ './src/**/*.{ts,tsx}',
21
+ './node_modules/@sypra-ui/ui/dist/**/*.{js,mjs}',
22
+ './node_modules/@sypra-ui/pages/dist/**/*.{js,mjs}',
23
+ ],
24
+ };
25
+ ```
26
+
27
+ Apply `--rui-*` CSS variables to your application or a page wrapper to change
28
+ the color palette and shape. Page components remain data-and-callback driven,
29
+ so your application retains ownership of authentication, routing, APIs, and
30
+ payments.
@@ -0,0 +1,221 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ type AuthProvider = 'google' | 'github' | string;
5
+ type AuthValues = {
6
+ email: string;
7
+ password: string;
8
+ name?: string;
9
+ };
10
+ type AuthCallbacks = {
11
+ providers?: AuthProvider[];
12
+ loading?: boolean;
13
+ error?: ReactNode;
14
+ onProviderLogin?: (provider: AuthProvider) => void;
15
+ onForgotPassword?: () => void;
16
+ onSignup?: () => void;
17
+ onLogin?: () => void;
18
+ };
19
+ declare function AuthForm({ mode, onSubmit, providers, loading, error, onProviderLogin, onForgotPassword, onSignup, onLogin, }: AuthCallbacks & {
20
+ mode: 'login' | 'signup' | 'forgot';
21
+ onSubmit: (values: AuthValues) => void | Promise<void>;
22
+ }): react.JSX.Element;
23
+ declare function LoginPage({ title, description, onSubmit, as, ...props }: AuthCallbacks & {
24
+ title?: string;
25
+ description?: string;
26
+ as?: 'main' | 'div';
27
+ onSubmit: (values: AuthValues) => void | Promise<void>;
28
+ }): react.JSX.Element;
29
+ declare function SignupPage({ title, description, onSubmit, as, ...props }: AuthCallbacks & {
30
+ title?: string;
31
+ description?: string;
32
+ as?: 'main' | 'div';
33
+ onSubmit: (values: AuthValues) => void | Promise<void>;
34
+ }): react.JSX.Element;
35
+ declare function ForgotPasswordPage({ onSubmit, as, ...props }: AuthCallbacks & {
36
+ onSubmit: (values: AuthValues) => void | Promise<void>;
37
+ as?: 'main' | 'div';
38
+ }): react.JSX.Element;
39
+ declare function AuthModal({ open, onOpenChange, onSubmit, ...props }: AuthCallbacks & {
40
+ open: boolean;
41
+ onOpenChange: (open: boolean) => void;
42
+ onSubmit: (values: AuthValues) => void | Promise<void>;
43
+ }): react.JSX.Element;
44
+
45
+ declare function SettingsLayout({ children }: {
46
+ children: ReactNode;
47
+ }): react.JSX.Element;
48
+ type Profile = {
49
+ name: string;
50
+ email: string;
51
+ avatar?: string;
52
+ };
53
+ declare function ProfilePage({ profile, loading, onSave, }: {
54
+ profile: Profile;
55
+ loading?: boolean;
56
+ onSave: (profile: Profile) => void | Promise<void>;
57
+ }): react.JSX.Element;
58
+ type Session = {
59
+ id: string;
60
+ device: string;
61
+ location?: string;
62
+ lastActive: string;
63
+ };
64
+ declare function SessionManager({ sessions, currentSessionId, loading, onRevoke, onRevokeAll, }: {
65
+ sessions: Session[];
66
+ currentSessionId?: string;
67
+ loading?: boolean;
68
+ onRevoke: (id: string) => void | Promise<void>;
69
+ onRevokeAll: () => void | Promise<void>;
70
+ }): react.JSX.Element;
71
+ declare function SecurityPage({ sessions, currentSessionId, onRevoke, onRevokeAll, passwordEnabled, twoFactorEnabled, onChangePassword, onToggleTwoFactor, }: {
72
+ sessions: Session[];
73
+ currentSessionId?: string;
74
+ onRevoke: (id: string) => void | Promise<void>;
75
+ onRevokeAll: () => void | Promise<void>;
76
+ passwordEnabled?: boolean;
77
+ twoFactorEnabled?: boolean;
78
+ onChangePassword?: () => void;
79
+ onToggleTwoFactor?: (enabled: boolean) => void;
80
+ }): react.JSX.Element;
81
+ type ApiKey = {
82
+ id: string;
83
+ name: string;
84
+ prefix: string;
85
+ createdAt: string;
86
+ lastUsedAt?: string;
87
+ permissions?: string[];
88
+ };
89
+ declare function CreateApiKeyDialog({ open, onOpenChange, onCreate, }: {
90
+ open: boolean;
91
+ onOpenChange: (open: boolean) => void;
92
+ onCreate: (values: {
93
+ name: string;
94
+ permissions: string[];
95
+ }) => void | Promise<void>;
96
+ }): react.JSX.Element;
97
+ declare function ApiKeyManager({ keys, loading, onCreate, onRevoke, }: {
98
+ keys: ApiKey[];
99
+ loading?: boolean;
100
+ onCreate: (values: {
101
+ name: string;
102
+ permissions: string[];
103
+ }) => void | Promise<void>;
104
+ onRevoke: (id: string) => void | Promise<void>;
105
+ }): react.JSX.Element;
106
+ declare function ApiKeyPage(props: ComponentProps<typeof ApiKeyManager>): react.JSX.Element;
107
+ type ComponentProps<T> = T extends (props: infer Props) => unknown ? Props : never;
108
+ declare function DangerZone({ onDeleteAccount, confirmationText, }: {
109
+ onDeleteAccount: () => void | Promise<void>;
110
+ confirmationText?: string;
111
+ }): react.JSX.Element;
112
+
113
+ type Subscription = {
114
+ plan: string;
115
+ price: string;
116
+ interval?: string;
117
+ nextBillingDate?: string;
118
+ status?: string;
119
+ usage?: Array<{
120
+ label: string;
121
+ value: string;
122
+ }>;
123
+ };
124
+ type PaymentMethod = {
125
+ brand: string;
126
+ last4: string;
127
+ expiresAt?: string;
128
+ };
129
+ type Invoice = {
130
+ id: string;
131
+ date: string;
132
+ amount: string;
133
+ status: string;
134
+ href?: string;
135
+ };
136
+ declare function SubscriptionCard({ subscription, onChangePlan, onCancel, }: {
137
+ subscription?: Subscription;
138
+ onChangePlan?: () => void;
139
+ onCancel?: () => void;
140
+ }): react.JSX.Element;
141
+ declare function PaymentMethodCard({ paymentMethod, onUpdate, }: {
142
+ paymentMethod?: PaymentMethod;
143
+ onUpdate?: () => void;
144
+ }): react.JSX.Element;
145
+ declare function InvoiceTable({ invoices, onView, }: {
146
+ invoices: Invoice[];
147
+ onView?: (invoice: Invoice) => void;
148
+ }): react.JSX.Element;
149
+ declare function PricingTable({ plans, onSelect, }: {
150
+ plans: Array<{
151
+ name: string;
152
+ price: string;
153
+ description?: string;
154
+ features: string[];
155
+ highlighted?: boolean;
156
+ }>;
157
+ onSelect: (plan: string) => void;
158
+ }): react.JSX.Element;
159
+ declare function BillingPage({ subscription, paymentMethod, invoices, onChangePlan, onUpdatePaymentMethod, onCancel, onViewInvoice, }: {
160
+ subscription?: Subscription;
161
+ paymentMethod?: PaymentMethod;
162
+ invoices: Invoice[];
163
+ onChangePlan?: () => void;
164
+ onUpdatePaymentMethod?: () => void;
165
+ onCancel?: () => void;
166
+ onViewInvoice?: (invoice: Invoice) => void;
167
+ }): react.JSX.Element;
168
+
169
+ declare function Hero({ eyebrow, title, description, primaryAction, secondaryAction, }: {
170
+ eyebrow?: ReactNode;
171
+ title: ReactNode;
172
+ description: ReactNode;
173
+ primaryAction?: ReactNode;
174
+ secondaryAction?: ReactNode;
175
+ }): react.JSX.Element;
176
+ declare function FeatureGrid({ features, }: {
177
+ features: Array<{
178
+ title: string;
179
+ description: string;
180
+ icon?: ReactNode;
181
+ }>;
182
+ }): react.JSX.Element;
183
+ declare function FAQ({ items, }: {
184
+ items: Array<{
185
+ question: string;
186
+ answer: ReactNode;
187
+ }>;
188
+ }): react.JSX.Element;
189
+ declare function CTA({ title, description, action, }: {
190
+ title: ReactNode;
191
+ description?: ReactNode;
192
+ action: ReactNode;
193
+ }): react.JSX.Element;
194
+ declare function Footer({ brand, links, }: {
195
+ brand: ReactNode;
196
+ links?: Array<{
197
+ label: string;
198
+ href: string;
199
+ }>;
200
+ }): react.JSX.Element;
201
+ declare function LandingPage({ brand, hero, features, children, as, }: {
202
+ brand: ReactNode;
203
+ hero: {
204
+ title: ReactNode;
205
+ description: ReactNode;
206
+ primaryAction?: ReactNode;
207
+ secondaryAction?: ReactNode;
208
+ };
209
+ features?: Array<{
210
+ title: string;
211
+ description: string;
212
+ icon?: ReactNode;
213
+ }>;
214
+ children?: ReactNode;
215
+ as?: 'main' | 'div';
216
+ }): react.JSX.Element;
217
+ declare function SettingsPageDemo({ children }: {
218
+ children: ReactNode;
219
+ }): react.JSX.Element;
220
+
221
+ export { type ApiKey, ApiKeyManager, ApiKeyPage, AuthForm, AuthModal, type AuthProvider, type AuthValues, BillingPage, CTA, CreateApiKeyDialog, DangerZone, FAQ, FeatureGrid, Footer, ForgotPasswordPage, Hero, type Invoice, InvoiceTable, LandingPage, LoginPage, type PaymentMethod, PaymentMethodCard, PricingTable, type Profile, ProfilePage, SecurityPage, type Session, SessionManager, SettingsLayout, SettingsPageDemo, SignupPage, type Subscription, SubscriptionCard };
package/dist/index.js ADDED
@@ -0,0 +1,850 @@
1
+ // src/pages/auth.tsx
2
+ import { useState } from "react";
3
+ import {
4
+ Alert,
5
+ Button,
6
+ Card,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ Dialog,
11
+ DialogContent,
12
+ DialogDescription,
13
+ DialogHeader,
14
+ DialogTitle,
15
+ Input,
16
+ Label,
17
+ PageShell,
18
+ PasswordInput,
19
+ Separator
20
+ } from "@sypra-ui/ui";
21
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
+ function AuthForm({
23
+ mode,
24
+ onSubmit,
25
+ providers = [],
26
+ loading,
27
+ error,
28
+ onProviderLogin,
29
+ onForgotPassword,
30
+ onSignup,
31
+ onLogin
32
+ }) {
33
+ const [values, setValues] = useState({
34
+ email: "",
35
+ password: "",
36
+ name: ""
37
+ });
38
+ const submit = (event) => {
39
+ event.preventDefault();
40
+ void onSubmit(values);
41
+ };
42
+ const isForgot = mode === "forgot";
43
+ return /* @__PURE__ */ jsxs("form", { className: "space-y-4", onSubmit: submit, children: [
44
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", title: "Could not continue", children: error }),
45
+ mode === "signup" && /* @__PURE__ */ jsxs("div", { children: [
46
+ /* @__PURE__ */ jsx(Label, { htmlFor: "name", children: "Name" }),
47
+ /* @__PURE__ */ jsx(
48
+ Input,
49
+ {
50
+ id: "name",
51
+ value: values.name,
52
+ onChange: (event) => setValues({ ...values, name: event.target.value }),
53
+ autoComplete: "name",
54
+ required: true
55
+ }
56
+ )
57
+ ] }),
58
+ /* @__PURE__ */ jsxs("div", { children: [
59
+ /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "Email" }),
60
+ /* @__PURE__ */ jsx(
61
+ Input,
62
+ {
63
+ id: "email",
64
+ type: "email",
65
+ value: values.email,
66
+ onChange: (event) => setValues({ ...values, email: event.target.value }),
67
+ autoComplete: "email",
68
+ required: true
69
+ }
70
+ )
71
+ ] }),
72
+ !isForgot && /* @__PURE__ */ jsxs("div", { children: [
73
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
74
+ /* @__PURE__ */ jsx(Label, { htmlFor: "password", children: "Password" }),
75
+ mode === "login" && /* @__PURE__ */ jsx(
76
+ "button",
77
+ {
78
+ type: "button",
79
+ className: "rui-focus text-xs text-[hsl(var(--rui-primary))]",
80
+ onClick: onForgotPassword,
81
+ children: "Forgot password?"
82
+ }
83
+ )
84
+ ] }),
85
+ /* @__PURE__ */ jsx(
86
+ PasswordInput,
87
+ {
88
+ id: "password",
89
+ value: values.password,
90
+ onChange: (event) => setValues({ ...values, password: event.target.value }),
91
+ autoComplete: mode === "signup" ? "new-password" : "current-password",
92
+ required: true
93
+ }
94
+ )
95
+ ] }),
96
+ /* @__PURE__ */ jsx(Button, { className: "w-full", type: "submit", loading, children: isForgot ? "Send reset link" : mode === "signup" ? "Create account" : "Continue" }),
97
+ providers.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
98
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-xs text-[hsl(var(--rui-muted-foreground))]", children: [
99
+ /* @__PURE__ */ jsx(Separator, {}),
100
+ /* @__PURE__ */ jsx("span", { children: "OR" }),
101
+ /* @__PURE__ */ jsx(Separator, {})
102
+ ] }),
103
+ /* @__PURE__ */ jsx("div", { className: "grid gap-2", children: providers.map((provider) => /* @__PURE__ */ jsxs(
104
+ Button,
105
+ {
106
+ type: "button",
107
+ variant: "outline",
108
+ onClick: () => onProviderLogin?.(provider),
109
+ children: [
110
+ "Continue with",
111
+ " ",
112
+ provider.slice(0, 1).toUpperCase() + provider.slice(1)
113
+ ]
114
+ },
115
+ provider
116
+ )) })
117
+ ] }),
118
+ /* @__PURE__ */ jsx("p", { className: "text-center text-sm text-[hsl(var(--rui-muted-foreground))]", children: mode === "login" ? /* @__PURE__ */ jsxs(Fragment, { children: [
119
+ "No account?",
120
+ " ",
121
+ /* @__PURE__ */ jsx(
122
+ "button",
123
+ {
124
+ type: "button",
125
+ className: "rui-focus text-[hsl(var(--rui-primary))]",
126
+ onClick: onSignup,
127
+ children: "Sign up"
128
+ }
129
+ )
130
+ ] }) : mode === "signup" ? /* @__PURE__ */ jsxs(Fragment, { children: [
131
+ "Already have an account?",
132
+ " ",
133
+ /* @__PURE__ */ jsx(
134
+ "button",
135
+ {
136
+ type: "button",
137
+ className: "rui-focus text-[hsl(var(--rui-primary))]",
138
+ onClick: onLogin,
139
+ children: "Log in"
140
+ }
141
+ )
142
+ ] }) : /* @__PURE__ */ jsx(
143
+ "button",
144
+ {
145
+ type: "button",
146
+ className: "rui-focus text-[hsl(var(--rui-primary))]",
147
+ onClick: onLogin,
148
+ children: "Back to login"
149
+ }
150
+ ) })
151
+ ] });
152
+ }
153
+ function LoginPage({
154
+ title = "Welcome back",
155
+ description = "Sign in to continue.",
156
+ onSubmit,
157
+ as,
158
+ ...props
159
+ }) {
160
+ return /* @__PURE__ */ jsx(AuthPage, { title, description, as, children: /* @__PURE__ */ jsx(AuthForm, { mode: "login", onSubmit, ...props }) });
161
+ }
162
+ function SignupPage({
163
+ title = "Create your account",
164
+ description = "Start with a free account.",
165
+ onSubmit,
166
+ as,
167
+ ...props
168
+ }) {
169
+ return /* @__PURE__ */ jsx(AuthPage, { title, description, as, children: /* @__PURE__ */ jsx(AuthForm, { mode: "signup", onSubmit, ...props }) });
170
+ }
171
+ function ForgotPasswordPage({
172
+ onSubmit,
173
+ as,
174
+ ...props
175
+ }) {
176
+ return /* @__PURE__ */ jsx(
177
+ AuthPage,
178
+ {
179
+ title: "Reset your password",
180
+ description: "We\u2019ll email a reset link.",
181
+ as,
182
+ children: /* @__PURE__ */ jsx(AuthForm, { mode: "forgot", onSubmit, ...props })
183
+ }
184
+ );
185
+ }
186
+ function AuthPage({
187
+ title,
188
+ description,
189
+ children,
190
+ as
191
+ }) {
192
+ return /* @__PURE__ */ jsx(PageShell, { as, className: "grid place-items-center p-4", children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-md", children: [
193
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { children: [
194
+ /* @__PURE__ */ jsx(CardTitle, { children: title }),
195
+ /* @__PURE__ */ jsx(CardDescription, { children: description })
196
+ ] }) }),
197
+ children
198
+ ] }) });
199
+ }
200
+ function AuthModal({
201
+ open,
202
+ onOpenChange,
203
+ onSubmit,
204
+ ...props
205
+ }) {
206
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { children: [
207
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
208
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Welcome back" }),
209
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Sign in to your account." })
210
+ ] }),
211
+ /* @__PURE__ */ jsx(AuthForm, { mode: "login", onSubmit, ...props })
212
+ ] }) });
213
+ }
214
+
215
+ // src/pages/settings.tsx
216
+ import { useState as useState2 } from "react";
217
+ import {
218
+ Avatar,
219
+ Badge,
220
+ Button as Button2,
221
+ Card as Card2,
222
+ CardDescription as CardDescription2,
223
+ CardTitle as CardTitle2,
224
+ Checkbox,
225
+ Dialog as Dialog2,
226
+ DialogBody,
227
+ DialogClose,
228
+ DialogContent as DialogContent2,
229
+ DialogDescription as DialogDescription2,
230
+ DialogFooter,
231
+ DialogHeader as DialogHeader2,
232
+ DialogTitle as DialogTitle2,
233
+ EmptyState,
234
+ Input as Input2,
235
+ Label as Label2,
236
+ Section,
237
+ Separator as Separator2,
238
+ Stack,
239
+ Switch
240
+ } from "@sypra-ui/ui";
241
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
242
+ function SettingsLayout({ children }) {
243
+ return /* @__PURE__ */ jsx2("div", { className: "min-w-0 space-y-8", children });
244
+ }
245
+ function ProfilePage({
246
+ profile,
247
+ loading,
248
+ onSave
249
+ }) {
250
+ const [next, setNext] = useState2(profile);
251
+ return /* @__PURE__ */ jsx2(Section, { title: "Profile", description: "Update the details people see.", children: /* @__PURE__ */ jsxs2(Card2, { children: [
252
+ /* @__PURE__ */ jsxs2("div", { className: "mb-5 flex items-center gap-3", children: [
253
+ /* @__PURE__ */ jsx2(Avatar, { src: next.avatar, alt: next.name }),
254
+ /* @__PURE__ */ jsxs2("div", { children: [
255
+ /* @__PURE__ */ jsx2(CardTitle2, { children: next.name || "Your profile" }),
256
+ /* @__PURE__ */ jsx2(CardDescription2, { children: next.email })
257
+ ] })
258
+ ] }),
259
+ /* @__PURE__ */ jsxs2(
260
+ "form",
261
+ {
262
+ className: "max-w-lg space-y-4",
263
+ onSubmit: (event) => {
264
+ event.preventDefault();
265
+ void onSave(next);
266
+ },
267
+ children: [
268
+ /* @__PURE__ */ jsxs2("div", { children: [
269
+ /* @__PURE__ */ jsx2(Label2, { htmlFor: "profile-name", children: "Name" }),
270
+ /* @__PURE__ */ jsx2(
271
+ Input2,
272
+ {
273
+ id: "profile-name",
274
+ value: next.name,
275
+ onChange: (event) => setNext({ ...next, name: event.target.value }),
276
+ required: true
277
+ }
278
+ )
279
+ ] }),
280
+ /* @__PURE__ */ jsxs2("div", { children: [
281
+ /* @__PURE__ */ jsx2(Label2, { htmlFor: "profile-email", children: "Email" }),
282
+ /* @__PURE__ */ jsx2(
283
+ Input2,
284
+ {
285
+ id: "profile-email",
286
+ type: "email",
287
+ value: next.email,
288
+ onChange: (event) => setNext({ ...next, email: event.target.value }),
289
+ required: true
290
+ }
291
+ )
292
+ ] }),
293
+ /* @__PURE__ */ jsx2(Button2, { type: "submit", loading, children: "Save changes" })
294
+ ]
295
+ }
296
+ )
297
+ ] }) });
298
+ }
299
+ function SessionManager({
300
+ sessions,
301
+ currentSessionId,
302
+ loading,
303
+ onRevoke,
304
+ onRevokeAll
305
+ }) {
306
+ return /* @__PURE__ */ jsxs2(
307
+ Section,
308
+ {
309
+ title: "Active sessions",
310
+ description: "Review where your account is signed in.",
311
+ children: [
312
+ /* @__PURE__ */ jsx2(Stack, { children: sessions.length ? sessions.map((session) => /* @__PURE__ */ jsxs2(
313
+ Card2,
314
+ {
315
+ className: "flex flex-wrap items-center justify-between gap-3",
316
+ children: [
317
+ /* @__PURE__ */ jsxs2("div", { children: [
318
+ /* @__PURE__ */ jsxs2(CardTitle2, { children: [
319
+ session.device,
320
+ " ",
321
+ session.id === currentSessionId && /* @__PURE__ */ jsx2(Badge, { children: "Current" })
322
+ ] }),
323
+ /* @__PURE__ */ jsx2(CardDescription2, { children: [session.location, session.lastActive].filter(Boolean).join(" \xB7 ") })
324
+ ] }),
325
+ session.id !== currentSessionId && /* @__PURE__ */ jsx2(
326
+ Button2,
327
+ {
328
+ variant: "outline",
329
+ size: "sm",
330
+ loading,
331
+ onClick: () => void onRevoke(session.id),
332
+ children: "Revoke"
333
+ }
334
+ )
335
+ ]
336
+ },
337
+ session.id
338
+ )) : /* @__PURE__ */ jsx2(EmptyState, { title: "No sessions" }) }),
339
+ sessions.length > 1 && /* @__PURE__ */ jsx2(
340
+ Button2,
341
+ {
342
+ variant: "destructive",
343
+ loading,
344
+ onClick: () => void onRevokeAll(),
345
+ children: "Sign out of other sessions"
346
+ }
347
+ )
348
+ ]
349
+ }
350
+ );
351
+ }
352
+ function SecurityPage({
353
+ sessions,
354
+ currentSessionId,
355
+ onRevoke,
356
+ onRevokeAll,
357
+ passwordEnabled = true,
358
+ twoFactorEnabled,
359
+ onChangePassword,
360
+ onToggleTwoFactor
361
+ }) {
362
+ return /* @__PURE__ */ jsxs2(Stack, { gap: 8, children: [
363
+ /* @__PURE__ */ jsx2(Section, { title: "Security", description: "Keep your account secure.", children: /* @__PURE__ */ jsxs2(Card2, { className: "space-y-4", children: [
364
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-3", children: [
365
+ /* @__PURE__ */ jsxs2("div", { children: [
366
+ /* @__PURE__ */ jsx2(CardTitle2, { children: "Password" }),
367
+ /* @__PURE__ */ jsx2(CardDescription2, { children: passwordEnabled ? "Password is enabled." : "Passwordless sign-in." })
368
+ ] }),
369
+ onChangePassword && /* @__PURE__ */ jsx2(Button2, { variant: "outline", onClick: onChangePassword, children: "Change password" })
370
+ ] }),
371
+ /* @__PURE__ */ jsx2(Separator2, {}),
372
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-3", children: [
373
+ /* @__PURE__ */ jsxs2("div", { children: [
374
+ /* @__PURE__ */ jsx2(CardTitle2, { children: "Two-factor authentication" }),
375
+ /* @__PURE__ */ jsx2(CardDescription2, { children: twoFactorEnabled ? "Enabled" : "Not enabled" })
376
+ ] }),
377
+ /* @__PURE__ */ jsx2(
378
+ Switch,
379
+ {
380
+ checked: twoFactorEnabled,
381
+ onChange: (event) => onToggleTwoFactor?.(event.target.checked)
382
+ }
383
+ )
384
+ ] })
385
+ ] }) }),
386
+ /* @__PURE__ */ jsx2(
387
+ SessionManager,
388
+ {
389
+ sessions,
390
+ currentSessionId,
391
+ onRevoke,
392
+ onRevokeAll
393
+ }
394
+ )
395
+ ] });
396
+ }
397
+ function CreateApiKeyDialog({
398
+ open,
399
+ onOpenChange,
400
+ onCreate
401
+ }) {
402
+ const [name, setName] = useState2("");
403
+ const [write, setWrite] = useState2(false);
404
+ return /* @__PURE__ */ jsx2(Dialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs2(DialogContent2, { children: [
405
+ /* @__PURE__ */ jsxs2(DialogHeader2, { children: [
406
+ /* @__PURE__ */ jsx2(DialogTitle2, { children: "Create API key" }),
407
+ /* @__PURE__ */ jsx2(DialogDescription2, { children: "The full key should only be shown once by your application." })
408
+ ] }),
409
+ /* @__PURE__ */ jsxs2(DialogBody, { children: [
410
+ /* @__PURE__ */ jsxs2("div", { children: [
411
+ /* @__PURE__ */ jsx2(Label2, { htmlFor: "key-name", children: "Name" }),
412
+ /* @__PURE__ */ jsx2(
413
+ Input2,
414
+ {
415
+ id: "key-name",
416
+ value: name,
417
+ onChange: (event) => setName(event.target.value),
418
+ placeholder: "Production"
419
+ }
420
+ )
421
+ ] }),
422
+ /* @__PURE__ */ jsxs2("label", { className: "flex items-center gap-2 text-sm", children: [
423
+ /* @__PURE__ */ jsx2(
424
+ Checkbox,
425
+ {
426
+ checked: write,
427
+ onChange: (event) => setWrite(event.target.checked)
428
+ }
429
+ ),
430
+ " ",
431
+ "Allow write access"
432
+ ] })
433
+ ] }),
434
+ /* @__PURE__ */ jsxs2(DialogFooter, { children: [
435
+ /* @__PURE__ */ jsx2(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx2(Button2, { variant: "outline", children: "Cancel" }) }),
436
+ /* @__PURE__ */ jsx2(
437
+ Button2,
438
+ {
439
+ onClick: () => {
440
+ void onCreate({
441
+ name,
442
+ permissions: write ? ["read", "write"] : ["read"]
443
+ });
444
+ onOpenChange(false);
445
+ },
446
+ disabled: !name.trim(),
447
+ children: "Create key"
448
+ }
449
+ )
450
+ ] })
451
+ ] }) });
452
+ }
453
+ function ApiKeyManager({
454
+ keys,
455
+ loading,
456
+ onCreate,
457
+ onRevoke
458
+ }) {
459
+ const [createOpen, setCreateOpen] = useState2(false);
460
+ return /* @__PURE__ */ jsxs2(
461
+ Section,
462
+ {
463
+ title: "API keys",
464
+ description: "Create keys for programmatic access.",
465
+ children: [
466
+ /* @__PURE__ */ jsx2("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx2(Button2, { onClick: () => setCreateOpen(true), children: "Create API key" }) }),
467
+ /* @__PURE__ */ jsx2(Stack, { children: keys.length ? keys.map((key) => /* @__PURE__ */ jsxs2(
468
+ Card2,
469
+ {
470
+ className: "flex flex-wrap items-center justify-between gap-3",
471
+ children: [
472
+ /* @__PURE__ */ jsxs2("div", { children: [
473
+ /* @__PURE__ */ jsx2(CardTitle2, { children: key.name }),
474
+ /* @__PURE__ */ jsxs2(CardDescription2, { children: [
475
+ /* @__PURE__ */ jsxs2("code", { children: [
476
+ key.prefix,
477
+ "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
478
+ ] }),
479
+ " \xB7 Created ",
480
+ key.createdAt,
481
+ key.lastUsedAt ? ` \xB7 Last used ${key.lastUsedAt}` : " \xB7 Never used"
482
+ ] })
483
+ ] }),
484
+ /* @__PURE__ */ jsx2(
485
+ Button2,
486
+ {
487
+ variant: "outline",
488
+ size: "sm",
489
+ loading,
490
+ onClick: () => void onRevoke(key.id),
491
+ children: "Revoke"
492
+ }
493
+ )
494
+ ]
495
+ },
496
+ key.id
497
+ )) : /* @__PURE__ */ jsx2(
498
+ EmptyState,
499
+ {
500
+ title: "No API keys",
501
+ description: "Create one when you need programmatic access."
502
+ }
503
+ ) }),
504
+ /* @__PURE__ */ jsx2(
505
+ CreateApiKeyDialog,
506
+ {
507
+ open: createOpen,
508
+ onOpenChange: setCreateOpen,
509
+ onCreate
510
+ }
511
+ )
512
+ ]
513
+ }
514
+ );
515
+ }
516
+ function ApiKeyPage(props) {
517
+ return /* @__PURE__ */ jsx2(ApiKeyManager, { ...props });
518
+ }
519
+ function DangerZone({
520
+ onDeleteAccount,
521
+ confirmationText = "DELETE"
522
+ }) {
523
+ const [value, setValue] = useState2("");
524
+ return /* @__PURE__ */ jsx2(Section, { title: "Danger zone", description: "These actions are permanent.", children: /* @__PURE__ */ jsxs2(Card2, { className: "border-[hsl(var(--rui-destructive))]", children: [
525
+ /* @__PURE__ */ jsx2(CardTitle2, { children: "Delete account" }),
526
+ /* @__PURE__ */ jsx2(CardDescription2, { children: "Delete all account data. This cannot be undone." }),
527
+ /* @__PURE__ */ jsxs2("div", { className: "mt-4 max-w-sm", children: [
528
+ /* @__PURE__ */ jsxs2(Label2, { htmlFor: "delete-confirmation", children: [
529
+ "Type ",
530
+ confirmationText,
531
+ " to confirm"
532
+ ] }),
533
+ /* @__PURE__ */ jsx2(
534
+ Input2,
535
+ {
536
+ id: "delete-confirmation",
537
+ value,
538
+ onChange: (event) => setValue(event.target.value)
539
+ }
540
+ )
541
+ ] }),
542
+ /* @__PURE__ */ jsx2(
543
+ Button2,
544
+ {
545
+ className: "mt-4",
546
+ variant: "destructive",
547
+ disabled: value !== confirmationText,
548
+ onClick: () => void onDeleteAccount(),
549
+ children: "Delete account"
550
+ }
551
+ )
552
+ ] }) });
553
+ }
554
+
555
+ // src/pages/billing.tsx
556
+ import {
557
+ Badge as Badge2,
558
+ Button as Button3,
559
+ Card as Card3,
560
+ CardDescription as CardDescription3,
561
+ CardHeader as CardHeader2,
562
+ CardTitle as CardTitle3,
563
+ DataTable,
564
+ EmptyState as EmptyState2,
565
+ Section as Section2,
566
+ Stack as Stack2
567
+ } from "@sypra-ui/ui";
568
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
569
+ function SubscriptionCard({
570
+ subscription,
571
+ onChangePlan,
572
+ onCancel
573
+ }) {
574
+ if (!subscription)
575
+ return /* @__PURE__ */ jsx3(
576
+ EmptyState2,
577
+ {
578
+ title: "No active subscription",
579
+ action: onChangePlan && /* @__PURE__ */ jsx3(Button3, { onClick: onChangePlan, children: "View plans" })
580
+ }
581
+ );
582
+ return /* @__PURE__ */ jsxs3(Card3, { children: [
583
+ /* @__PURE__ */ jsxs3(CardHeader2, { children: [
584
+ /* @__PURE__ */ jsxs3("div", { children: [
585
+ /* @__PURE__ */ jsx3(CardTitle3, { children: subscription.plan }),
586
+ /* @__PURE__ */ jsxs3(CardDescription3, { children: [
587
+ subscription.price,
588
+ subscription.interval && ` / ${subscription.interval}`
589
+ ] })
590
+ ] }),
591
+ subscription.status && /* @__PURE__ */ jsx3(Badge2, { variant: "success", children: subscription.status })
592
+ ] }),
593
+ subscription.nextBillingDate && /* @__PURE__ */ jsxs3("p", { className: "text-sm text-[hsl(var(--rui-muted-foreground))]", children: [
594
+ "Next billing date: ",
595
+ subscription.nextBillingDate
596
+ ] }),
597
+ subscription.usage?.length ? /* @__PURE__ */ jsx3("div", { className: "mt-4 grid gap-2 text-sm sm:grid-cols-2", children: subscription.usage.map((item) => /* @__PURE__ */ jsxs3(
598
+ "div",
599
+ {
600
+ className: "rounded bg-[hsl(var(--rui-muted))] p-3",
601
+ children: [
602
+ /* @__PURE__ */ jsx3("strong", { className: "block", children: item.value }),
603
+ /* @__PURE__ */ jsx3("span", { className: "text-[hsl(var(--rui-muted-foreground))]", children: item.label })
604
+ ]
605
+ },
606
+ item.label
607
+ )) }) : null,
608
+ /* @__PURE__ */ jsxs3("div", { className: "mt-5 flex flex-wrap gap-2", children: [
609
+ onChangePlan && /* @__PURE__ */ jsx3(Button3, { onClick: onChangePlan, children: "Change plan" }),
610
+ onCancel && /* @__PURE__ */ jsx3(Button3, { variant: "outline", onClick: onCancel, children: "Manage subscription" })
611
+ ] })
612
+ ] });
613
+ }
614
+ function PaymentMethodCard({
615
+ paymentMethod,
616
+ onUpdate
617
+ }) {
618
+ return /* @__PURE__ */ jsx3(Card3, { children: /* @__PURE__ */ jsxs3(CardHeader2, { children: [
619
+ /* @__PURE__ */ jsxs3("div", { children: [
620
+ /* @__PURE__ */ jsx3(CardTitle3, { children: "Payment method" }),
621
+ /* @__PURE__ */ jsx3(CardDescription3, { children: paymentMethod ? `${paymentMethod.brand} \u2022\u2022\u2022\u2022 ${paymentMethod.last4}${paymentMethod.expiresAt ? ` \xB7 Expires ${paymentMethod.expiresAt}` : ""}` : "No payment method on file." })
622
+ ] }),
623
+ onUpdate && /* @__PURE__ */ jsx3(Button3, { variant: "outline", size: "sm", onClick: onUpdate, children: paymentMethod ? "Update" : "Add payment method" })
624
+ ] }) });
625
+ }
626
+ function InvoiceTable({
627
+ invoices,
628
+ onView
629
+ }) {
630
+ const columns = [
631
+ { key: "date", header: "Date", sortable: true },
632
+ { key: "amount", header: "Amount" },
633
+ {
634
+ key: "status",
635
+ header: "Status",
636
+ cell: (invoice) => /* @__PURE__ */ jsx3(
637
+ Badge2,
638
+ {
639
+ variant: invoice.status.toLowerCase() === "paid" ? "success" : "warning",
640
+ children: invoice.status
641
+ }
642
+ )
643
+ },
644
+ {
645
+ key: "id",
646
+ header: /* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Actions" }),
647
+ cell: (invoice) => onView && /* @__PURE__ */ jsx3(Button3, { variant: "ghost", size: "sm", onClick: () => onView(invoice), children: "View" })
648
+ }
649
+ ];
650
+ return /* @__PURE__ */ jsx3(
651
+ DataTable,
652
+ {
653
+ data: invoices,
654
+ columns,
655
+ emptyMessage: "No invoices yet."
656
+ }
657
+ );
658
+ }
659
+ function PricingTable({
660
+ plans,
661
+ onSelect
662
+ }) {
663
+ return /* @__PURE__ */ jsx3("div", { className: "grid gap-4 md:grid-cols-3", children: plans.map((plan) => /* @__PURE__ */ jsxs3(
664
+ Card3,
665
+ {
666
+ className: plan.highlighted ? "border-[hsl(var(--rui-primary))]" : void 0,
667
+ children: [
668
+ /* @__PURE__ */ jsx3(CardTitle3, { children: plan.name }),
669
+ /* @__PURE__ */ jsx3("p", { className: "mt-3 text-2xl font-bold", children: plan.price }),
670
+ plan.description && /* @__PURE__ */ jsx3(CardDescription3, { children: plan.description }),
671
+ /* @__PURE__ */ jsx3("ul", { className: "my-5 space-y-2 text-sm", children: plan.features.map((feature) => /* @__PURE__ */ jsxs3("li", { children: [
672
+ "\u2713 ",
673
+ feature
674
+ ] }, feature)) }),
675
+ /* @__PURE__ */ jsxs3(
676
+ Button3,
677
+ {
678
+ className: "w-full",
679
+ variant: plan.highlighted ? "primary" : "outline",
680
+ onClick: () => onSelect(plan.name),
681
+ children: [
682
+ "Choose ",
683
+ plan.name
684
+ ]
685
+ }
686
+ )
687
+ ]
688
+ },
689
+ plan.name
690
+ )) });
691
+ }
692
+ function BillingPage({
693
+ subscription,
694
+ paymentMethod,
695
+ invoices,
696
+ onChangePlan,
697
+ onUpdatePaymentMethod,
698
+ onCancel,
699
+ onViewInvoice
700
+ }) {
701
+ return /* @__PURE__ */ jsxs3(Stack2, { gap: 8, children: [
702
+ /* @__PURE__ */ jsx3(
703
+ Section2,
704
+ {
705
+ title: "Billing",
706
+ description: "Manage your plan and payment details.",
707
+ children: /* @__PURE__ */ jsx3(
708
+ SubscriptionCard,
709
+ {
710
+ subscription,
711
+ onChangePlan,
712
+ onCancel
713
+ }
714
+ )
715
+ }
716
+ ),
717
+ /* @__PURE__ */ jsx3(
718
+ PaymentMethodCard,
719
+ {
720
+ paymentMethod,
721
+ onUpdate: onUpdatePaymentMethod
722
+ }
723
+ ),
724
+ /* @__PURE__ */ jsx3(Section2, { title: "Invoices", children: /* @__PURE__ */ jsx3(InvoiceTable, { invoices, onView: onViewInvoice }) })
725
+ ] });
726
+ }
727
+
728
+ // src/pages/marketing.tsx
729
+ import {
730
+ Badge as Badge3,
731
+ Card as Card4,
732
+ CardDescription as CardDescription4,
733
+ CardTitle as CardTitle4,
734
+ Container,
735
+ PageContent,
736
+ PageHeader,
737
+ PageShell as PageShell2
738
+ } from "@sypra-ui/ui";
739
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
740
+ function Hero({
741
+ eyebrow,
742
+ title,
743
+ description,
744
+ primaryAction,
745
+ secondaryAction
746
+ }) {
747
+ return /* @__PURE__ */ jsxs4("section", { className: "py-20 text-center sm:py-28", children: [
748
+ eyebrow && /* @__PURE__ */ jsx4(Badge3, { children: eyebrow }),
749
+ /* @__PURE__ */ jsx4("h1", { className: "mx-auto mt-5 max-w-3xl text-4xl font-bold tracking-tight sm:text-6xl", children: title }),
750
+ /* @__PURE__ */ jsx4("p", { className: "mx-auto mt-5 max-w-2xl text-lg text-[hsl(var(--rui-muted-foreground))]", children: description }),
751
+ /* @__PURE__ */ jsxs4("div", { className: "mt-8 flex flex-wrap justify-center gap-3", children: [
752
+ primaryAction,
753
+ secondaryAction
754
+ ] })
755
+ ] });
756
+ }
757
+ function FeatureGrid({
758
+ features
759
+ }) {
760
+ return /* @__PURE__ */ jsx4("section", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3", children: features.map((feature) => /* @__PURE__ */ jsxs4(Card4, { children: [
761
+ feature.icon && /* @__PURE__ */ jsx4("div", { className: "mb-3 text-[hsl(var(--rui-primary))]", children: feature.icon }),
762
+ /* @__PURE__ */ jsx4(CardTitle4, { children: feature.title }),
763
+ /* @__PURE__ */ jsx4(CardDescription4, { children: feature.description })
764
+ ] }, feature.title)) });
765
+ }
766
+ function FAQ({
767
+ items
768
+ }) {
769
+ return /* @__PURE__ */ jsx4("section", { className: "mx-auto max-w-3xl space-y-4", children: items.map((item) => /* @__PURE__ */ jsxs4(Card4, { children: [
770
+ /* @__PURE__ */ jsx4(CardTitle4, { children: item.question }),
771
+ /* @__PURE__ */ jsx4(CardDescription4, { children: item.answer })
772
+ ] }, item.question)) });
773
+ }
774
+ function CTA({
775
+ title,
776
+ description,
777
+ action
778
+ }) {
779
+ return /* @__PURE__ */ jsxs4("section", { className: "rounded-[calc(var(--rui-radius)+.2rem)] bg-[hsl(var(--rui-primary))] px-6 py-14 text-center text-[hsl(var(--rui-primary-foreground))]", children: [
780
+ /* @__PURE__ */ jsx4("h2", { className: "text-3xl font-bold", children: title }),
781
+ description && /* @__PURE__ */ jsx4("p", { className: "mt-3 opacity-85", children: description }),
782
+ /* @__PURE__ */ jsx4("div", { className: "mt-6", children: action })
783
+ ] });
784
+ }
785
+ function Footer({
786
+ brand,
787
+ links
788
+ }) {
789
+ return /* @__PURE__ */ jsx4("footer", { className: "mt-16 border-t border-[hsl(var(--rui-border))] py-8 text-sm text-[hsl(var(--rui-muted-foreground))]", children: /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
790
+ /* @__PURE__ */ jsx4("strong", { className: "text-[hsl(var(--rui-foreground))]", children: brand }),
791
+ /* @__PURE__ */ jsx4("div", { className: "flex gap-4", children: links?.map((link) => /* @__PURE__ */ jsx4(
792
+ "a",
793
+ {
794
+ href: link.href,
795
+ className: "hover:text-[hsl(var(--rui-foreground))]",
796
+ children: link.label
797
+ },
798
+ link.href
799
+ )) })
800
+ ] }) });
801
+ }
802
+ function LandingPage({
803
+ brand,
804
+ hero,
805
+ features,
806
+ children,
807
+ as
808
+ }) {
809
+ return /* @__PURE__ */ jsx4(PageShell2, { as, children: /* @__PURE__ */ jsxs4(Container, { children: [
810
+ /* @__PURE__ */ jsx4("header", { className: "flex h-16 items-center justify-between", children: /* @__PURE__ */ jsx4("strong", { children: brand }) }),
811
+ /* @__PURE__ */ jsx4(Hero, { ...hero }),
812
+ features && /* @__PURE__ */ jsx4(FeatureGrid, { features }),
813
+ children,
814
+ /* @__PURE__ */ jsx4(Footer, { brand })
815
+ ] }) });
816
+ }
817
+ function SettingsPageDemo({ children }) {
818
+ return /* @__PURE__ */ jsx4(PageShell2, { children: /* @__PURE__ */ jsxs4(Container, { className: "py-8", children: [
819
+ /* @__PURE__ */ jsx4(PageHeader, { title: "Settings", description: "Manage your account." }),
820
+ /* @__PURE__ */ jsx4(PageContent, { children })
821
+ ] }) });
822
+ }
823
+ export {
824
+ ApiKeyManager,
825
+ ApiKeyPage,
826
+ AuthForm,
827
+ AuthModal,
828
+ BillingPage,
829
+ CTA,
830
+ CreateApiKeyDialog,
831
+ DangerZone,
832
+ FAQ,
833
+ FeatureGrid,
834
+ Footer,
835
+ ForgotPasswordPage,
836
+ Hero,
837
+ InvoiceTable,
838
+ LandingPage,
839
+ LoginPage,
840
+ PaymentMethodCard,
841
+ PricingTable,
842
+ ProfilePage,
843
+ SecurityPage,
844
+ SessionManager,
845
+ SettingsLayout,
846
+ SettingsPageDemo,
847
+ SignupPage,
848
+ SubscriptionCard
849
+ };
850
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pages/auth.tsx","../src/pages/settings.tsx","../src/pages/billing.tsx","../src/pages/marketing.tsx"],"sourcesContent":["'use client';\n\nimport { useState, type FormEvent, type ReactNode } from 'react';\nimport {\n Alert,\n Button,\n Card,\n CardDescription,\n CardHeader,\n CardTitle,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Input,\n Label,\n PageShell,\n PasswordInput,\n Separator,\n} from '@sypra-ui/ui';\n\nexport type AuthProvider = 'google' | 'github' | string;\nexport type AuthValues = { email: string; password: string; name?: string };\ntype AuthCallbacks = {\n providers?: AuthProvider[];\n loading?: boolean;\n error?: ReactNode;\n onProviderLogin?: (provider: AuthProvider) => void;\n onForgotPassword?: () => void;\n onSignup?: () => void;\n onLogin?: () => void;\n};\nexport function AuthForm({\n mode,\n onSubmit,\n providers = [],\n loading,\n error,\n onProviderLogin,\n onForgotPassword,\n onSignup,\n onLogin,\n}: AuthCallbacks & {\n mode: 'login' | 'signup' | 'forgot';\n onSubmit: (values: AuthValues) => void | Promise<void>;\n}) {\n const [values, setValues] = useState<AuthValues>({\n email: '',\n password: '',\n name: '',\n });\n const submit = (event: FormEvent) => {\n event.preventDefault();\n void onSubmit(values);\n };\n const isForgot = mode === 'forgot';\n return (\n <form className=\"space-y-4\" onSubmit={submit}>\n {error && (\n <Alert variant=\"destructive\" title=\"Could not continue\">\n {error}\n </Alert>\n )}\n {mode === 'signup' && (\n <div>\n <Label htmlFor=\"name\">Name</Label>\n <Input\n id=\"name\"\n value={values.name}\n onChange={(event) =>\n setValues({ ...values, name: event.target.value })\n }\n autoComplete=\"name\"\n required\n />\n </div>\n )}\n <div>\n <Label htmlFor=\"email\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n value={values.email}\n onChange={(event) =>\n setValues({ ...values, email: event.target.value })\n }\n autoComplete=\"email\"\n required\n />\n </div>\n {!isForgot && (\n <div>\n <div className=\"flex justify-between\">\n <Label htmlFor=\"password\">Password</Label>\n {mode === 'login' && (\n <button\n type=\"button\"\n className=\"rui-focus text-xs text-[hsl(var(--rui-primary))]\"\n onClick={onForgotPassword}\n >\n Forgot password?\n </button>\n )}\n </div>\n <PasswordInput\n id=\"password\"\n value={values.password}\n onChange={(event) =>\n setValues({ ...values, password: event.target.value })\n }\n autoComplete={\n mode === 'signup' ? 'new-password' : 'current-password'\n }\n required\n />\n </div>\n )}\n <Button className=\"w-full\" type=\"submit\" loading={loading}>\n {isForgot\n ? 'Send reset link'\n : mode === 'signup'\n ? 'Create account'\n : 'Continue'}\n </Button>\n {providers.length > 0 && (\n <>\n <div className=\"flex items-center gap-3 text-xs text-[hsl(var(--rui-muted-foreground))]\">\n <Separator />\n <span>OR</span>\n <Separator />\n </div>\n <div className=\"grid gap-2\">\n {providers.map((provider) => (\n <Button\n key={provider}\n type=\"button\"\n variant=\"outline\"\n onClick={() => onProviderLogin?.(provider)}\n >\n Continue with{' '}\n {provider.slice(0, 1).toUpperCase() + provider.slice(1)}\n </Button>\n ))}\n </div>\n </>\n )}\n <p className=\"text-center text-sm text-[hsl(var(--rui-muted-foreground))]\">\n {mode === 'login' ? (\n <>\n No account?{' '}\n <button\n type=\"button\"\n className=\"rui-focus text-[hsl(var(--rui-primary))]\"\n onClick={onSignup}\n >\n Sign up\n </button>\n </>\n ) : mode === 'signup' ? (\n <>\n Already have an account?{' '}\n <button\n type=\"button\"\n className=\"rui-focus text-[hsl(var(--rui-primary))]\"\n onClick={onLogin}\n >\n Log in\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n className=\"rui-focus text-[hsl(var(--rui-primary))]\"\n onClick={onLogin}\n >\n Back to login\n </button>\n )}\n </p>\n </form>\n );\n}\nexport function LoginPage({\n title = 'Welcome back',\n description = 'Sign in to continue.',\n onSubmit,\n as,\n ...props\n}: AuthCallbacks & {\n title?: string;\n description?: string;\n as?: 'main' | 'div';\n onSubmit: (values: AuthValues) => void | Promise<void>;\n}) {\n return (\n <AuthPage title={title} description={description} as={as}>\n <AuthForm mode=\"login\" onSubmit={onSubmit} {...props} />\n </AuthPage>\n );\n}\nexport function SignupPage({\n title = 'Create your account',\n description = 'Start with a free account.',\n onSubmit,\n as,\n ...props\n}: AuthCallbacks & {\n title?: string;\n description?: string;\n as?: 'main' | 'div';\n onSubmit: (values: AuthValues) => void | Promise<void>;\n}) {\n return (\n <AuthPage title={title} description={description} as={as}>\n <AuthForm mode=\"signup\" onSubmit={onSubmit} {...props} />\n </AuthPage>\n );\n}\nexport function ForgotPasswordPage({\n onSubmit,\n as,\n ...props\n}: AuthCallbacks & {\n onSubmit: (values: AuthValues) => void | Promise<void>;\n as?: 'main' | 'div';\n}) {\n return (\n <AuthPage\n title=\"Reset your password\"\n description=\"We’ll email a reset link.\"\n as={as}\n >\n <AuthForm mode=\"forgot\" onSubmit={onSubmit} {...props} />\n </AuthPage>\n );\n}\nfunction AuthPage({\n title,\n description,\n children,\n as,\n}: {\n title: string;\n description: string;\n children: ReactNode;\n as?: 'main' | 'div';\n}) {\n return (\n <PageShell as={as} className=\"grid place-items-center p-4\">\n <Card className=\"w-full max-w-md\">\n <CardHeader>\n <div>\n <CardTitle>{title}</CardTitle>\n <CardDescription>{description}</CardDescription>\n </div>\n </CardHeader>\n {children}\n </Card>\n </PageShell>\n );\n}\nexport function AuthModal({\n open,\n onOpenChange,\n onSubmit,\n ...props\n}: AuthCallbacks & {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSubmit: (values: AuthValues) => void | Promise<void>;\n}) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Welcome back</DialogTitle>\n <DialogDescription>Sign in to your account.</DialogDescription>\n </DialogHeader>\n <AuthForm mode=\"login\" onSubmit={onSubmit} {...props} />\n </DialogContent>\n </Dialog>\n );\n}\n","'use client';\n\nimport { useState, type ReactNode } from 'react';\nimport {\n Avatar,\n Badge,\n Button,\n Card,\n CardDescription,\n CardTitle,\n Checkbox,\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n EmptyState,\n Input,\n Label,\n Section,\n Separator,\n Stack,\n Switch,\n} from '@sypra-ui/ui';\n\nexport function SettingsLayout({ children }: { children: ReactNode }) {\n return <div className=\"min-w-0 space-y-8\">{children}</div>;\n}\nexport type Profile = { name: string; email: string; avatar?: string };\nexport function ProfilePage({\n profile,\n loading,\n onSave,\n}: {\n profile: Profile;\n loading?: boolean;\n onSave: (profile: Profile) => void | Promise<void>;\n}) {\n const [next, setNext] = useState(profile);\n return (\n <Section title=\"Profile\" description=\"Update the details people see.\">\n <Card>\n <div className=\"mb-5 flex items-center gap-3\">\n <Avatar src={next.avatar} alt={next.name} />\n <div>\n <CardTitle>{next.name || 'Your profile'}</CardTitle>\n <CardDescription>{next.email}</CardDescription>\n </div>\n </div>\n <form\n className=\"max-w-lg space-y-4\"\n onSubmit={(event) => {\n event.preventDefault();\n void onSave(next);\n }}\n >\n <div>\n <Label htmlFor=\"profile-name\">Name</Label>\n <Input\n id=\"profile-name\"\n value={next.name}\n onChange={(event) =>\n setNext({ ...next, name: event.target.value })\n }\n required\n />\n </div>\n <div>\n <Label htmlFor=\"profile-email\">Email</Label>\n <Input\n id=\"profile-email\"\n type=\"email\"\n value={next.email}\n onChange={(event) =>\n setNext({ ...next, email: event.target.value })\n }\n required\n />\n </div>\n <Button type=\"submit\" loading={loading}>\n Save changes\n </Button>\n </form>\n </Card>\n </Section>\n );\n}\nexport type Session = {\n id: string;\n device: string;\n location?: string;\n lastActive: string;\n};\nexport function SessionManager({\n sessions,\n currentSessionId,\n loading,\n onRevoke,\n onRevokeAll,\n}: {\n sessions: Session[];\n currentSessionId?: string;\n loading?: boolean;\n onRevoke: (id: string) => void | Promise<void>;\n onRevokeAll: () => void | Promise<void>;\n}) {\n return (\n <Section\n title=\"Active sessions\"\n description=\"Review where your account is signed in.\"\n >\n <Stack>\n {sessions.length ? (\n sessions.map((session) => (\n <Card\n key={session.id}\n className=\"flex flex-wrap items-center justify-between gap-3\"\n >\n <div>\n <CardTitle>\n {session.device}{' '}\n {session.id === currentSessionId && <Badge>Current</Badge>}\n </CardTitle>\n <CardDescription>\n {[session.location, session.lastActive]\n .filter(Boolean)\n .join(' · ')}\n </CardDescription>\n </div>\n {session.id !== currentSessionId && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n loading={loading}\n onClick={() => void onRevoke(session.id)}\n >\n Revoke\n </Button>\n )}\n </Card>\n ))\n ) : (\n <EmptyState title=\"No sessions\" />\n )}\n </Stack>\n {sessions.length > 1 && (\n <Button\n variant=\"destructive\"\n loading={loading}\n onClick={() => void onRevokeAll()}\n >\n Sign out of other sessions\n </Button>\n )}\n </Section>\n );\n}\nexport function SecurityPage({\n sessions,\n currentSessionId,\n onRevoke,\n onRevokeAll,\n passwordEnabled = true,\n twoFactorEnabled,\n onChangePassword,\n onToggleTwoFactor,\n}: {\n sessions: Session[];\n currentSessionId?: string;\n onRevoke: (id: string) => void | Promise<void>;\n onRevokeAll: () => void | Promise<void>;\n passwordEnabled?: boolean;\n twoFactorEnabled?: boolean;\n onChangePassword?: () => void;\n onToggleTwoFactor?: (enabled: boolean) => void;\n}) {\n return (\n <Stack gap={8}>\n <Section title=\"Security\" description=\"Keep your account secure.\">\n <Card className=\"space-y-4\">\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <CardTitle>Password</CardTitle>\n <CardDescription>\n {passwordEnabled\n ? 'Password is enabled.'\n : 'Passwordless sign-in.'}\n </CardDescription>\n </div>\n {onChangePassword && (\n <Button variant=\"outline\" onClick={onChangePassword}>\n Change password\n </Button>\n )}\n </div>\n <Separator />\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <CardTitle>Two-factor authentication</CardTitle>\n <CardDescription>\n {twoFactorEnabled ? 'Enabled' : 'Not enabled'}\n </CardDescription>\n </div>\n <Switch\n checked={twoFactorEnabled}\n onChange={(event) => onToggleTwoFactor?.(event.target.checked)}\n />\n </div>\n </Card>\n </Section>\n <SessionManager\n sessions={sessions}\n currentSessionId={currentSessionId}\n onRevoke={onRevoke}\n onRevokeAll={onRevokeAll}\n />\n </Stack>\n );\n}\n\nexport type ApiKey = {\n id: string;\n name: string;\n prefix: string;\n createdAt: string;\n lastUsedAt?: string;\n permissions?: string[];\n};\nexport function CreateApiKeyDialog({\n open,\n onOpenChange,\n onCreate,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onCreate: (values: {\n name: string;\n permissions: string[];\n }) => void | Promise<void>;\n}) {\n const [name, setName] = useState('');\n const [write, setWrite] = useState(false);\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Create API key</DialogTitle>\n <DialogDescription>\n The full key should only be shown once by your application.\n </DialogDescription>\n </DialogHeader>\n <DialogBody>\n <div>\n <Label htmlFor=\"key-name\">Name</Label>\n <Input\n id=\"key-name\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"Production\"\n />\n </div>\n <label className=\"flex items-center gap-2 text-sm\">\n <Checkbox\n checked={write}\n onChange={(event) => setWrite(event.target.checked)}\n />{' '}\n Allow write access\n </label>\n </DialogBody>\n <DialogFooter>\n <DialogClose asChild>\n <Button variant=\"outline\">Cancel</Button>\n </DialogClose>\n <Button\n onClick={() => {\n void onCreate({\n name,\n permissions: write ? ['read', 'write'] : ['read'],\n });\n onOpenChange(false);\n }}\n disabled={!name.trim()}\n >\n Create key\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\nexport function ApiKeyManager({\n keys,\n loading,\n onCreate,\n onRevoke,\n}: {\n keys: ApiKey[];\n loading?: boolean;\n onCreate: (values: {\n name: string;\n permissions: string[];\n }) => void | Promise<void>;\n onRevoke: (id: string) => void | Promise<void>;\n}) {\n const [createOpen, setCreateOpen] = useState(false);\n return (\n <Section\n title=\"API keys\"\n description=\"Create keys for programmatic access.\"\n >\n <div className=\"flex justify-end\">\n <Button onClick={() => setCreateOpen(true)}>Create API key</Button>\n </div>\n <Stack>\n {keys.length ? (\n keys.map((key) => (\n <Card\n key={key.id}\n className=\"flex flex-wrap items-center justify-between gap-3\"\n >\n <div>\n <CardTitle>{key.name}</CardTitle>\n <CardDescription>\n <code>{key.prefix}••••••••</code> · Created {key.createdAt}\n {key.lastUsedAt\n ? ` · Last used ${key.lastUsedAt}`\n : ' · Never used'}\n </CardDescription>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n loading={loading}\n onClick={() => void onRevoke(key.id)}\n >\n Revoke\n </Button>\n </Card>\n ))\n ) : (\n <EmptyState\n title=\"No API keys\"\n description=\"Create one when you need programmatic access.\"\n />\n )}\n </Stack>\n <CreateApiKeyDialog\n open={createOpen}\n onOpenChange={setCreateOpen}\n onCreate={onCreate}\n />\n </Section>\n );\n}\nexport function ApiKeyPage(props: ComponentProps<typeof ApiKeyManager>) {\n return <ApiKeyManager {...props} />;\n}\ntype ComponentProps<T> = T extends (props: infer Props) => unknown\n ? Props\n : never;\nexport function DangerZone({\n onDeleteAccount,\n confirmationText = 'DELETE',\n}: {\n onDeleteAccount: () => void | Promise<void>;\n confirmationText?: string;\n}) {\n const [value, setValue] = useState('');\n return (\n <Section title=\"Danger zone\" description=\"These actions are permanent.\">\n <Card className=\"border-[hsl(var(--rui-destructive))]\">\n <CardTitle>Delete account</CardTitle>\n <CardDescription>\n Delete all account data. This cannot be undone.\n </CardDescription>\n <div className=\"mt-4 max-w-sm\">\n <Label htmlFor=\"delete-confirmation\">\n Type {confirmationText} to confirm\n </Label>\n <Input\n id=\"delete-confirmation\"\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </div>\n <Button\n className=\"mt-4\"\n variant=\"destructive\"\n disabled={value !== confirmationText}\n onClick={() => void onDeleteAccount()}\n >\n Delete account\n </Button>\n </Card>\n </Section>\n );\n}\n","import {\n Badge,\n Button,\n Card,\n CardDescription,\n CardHeader,\n CardTitle,\n DataTable,\n EmptyState,\n Section,\n Stack,\n type DataColumn,\n} from '@sypra-ui/ui';\n\nexport type Subscription = {\n plan: string;\n price: string;\n interval?: string;\n nextBillingDate?: string;\n status?: string;\n usage?: Array<{ label: string; value: string }>;\n};\nexport type PaymentMethod = {\n brand: string;\n last4: string;\n expiresAt?: string;\n};\nexport type Invoice = {\n id: string;\n date: string;\n amount: string;\n status: string;\n href?: string;\n};\nexport function SubscriptionCard({\n subscription,\n onChangePlan,\n onCancel,\n}: {\n subscription?: Subscription;\n onChangePlan?: () => void;\n onCancel?: () => void;\n}) {\n if (!subscription)\n return (\n <EmptyState\n title=\"No active subscription\"\n action={\n onChangePlan && <Button onClick={onChangePlan}>View plans</Button>\n }\n />\n );\n return (\n <Card>\n <CardHeader>\n <div>\n <CardTitle>{subscription.plan}</CardTitle>\n <CardDescription>\n {subscription.price}\n {subscription.interval && ` / ${subscription.interval}`}\n </CardDescription>\n </div>\n {subscription.status && (\n <Badge variant=\"success\">{subscription.status}</Badge>\n )}\n </CardHeader>\n {subscription.nextBillingDate && (\n <p className=\"text-sm text-[hsl(var(--rui-muted-foreground))]\">\n Next billing date: {subscription.nextBillingDate}\n </p>\n )}\n {subscription.usage?.length ? (\n <div className=\"mt-4 grid gap-2 text-sm sm:grid-cols-2\">\n {subscription.usage.map((item) => (\n <div\n key={item.label}\n className=\"rounded bg-[hsl(var(--rui-muted))] p-3\"\n >\n <strong className=\"block\">{item.value}</strong>\n <span className=\"text-[hsl(var(--rui-muted-foreground))]\">\n {item.label}\n </span>\n </div>\n ))}\n </div>\n ) : null}\n <div className=\"mt-5 flex flex-wrap gap-2\">\n {onChangePlan && <Button onClick={onChangePlan}>Change plan</Button>}\n {onCancel && (\n <Button variant=\"outline\" onClick={onCancel}>\n Manage subscription\n </Button>\n )}\n </div>\n </Card>\n );\n}\nexport function PaymentMethodCard({\n paymentMethod,\n onUpdate,\n}: {\n paymentMethod?: PaymentMethod;\n onUpdate?: () => void;\n}) {\n return (\n <Card>\n <CardHeader>\n <div>\n <CardTitle>Payment method</CardTitle>\n <CardDescription>\n {paymentMethod\n ? `${paymentMethod.brand} •••• ${paymentMethod.last4}${paymentMethod.expiresAt ? ` · Expires ${paymentMethod.expiresAt}` : ''}`\n : 'No payment method on file.'}\n </CardDescription>\n </div>\n {onUpdate && (\n <Button variant=\"outline\" size=\"sm\" onClick={onUpdate}>\n {paymentMethod ? 'Update' : 'Add payment method'}\n </Button>\n )}\n </CardHeader>\n </Card>\n );\n}\nexport function InvoiceTable({\n invoices,\n onView,\n}: {\n invoices: Invoice[];\n onView?: (invoice: Invoice) => void;\n}) {\n const columns: DataColumn<Invoice>[] = [\n { key: 'date', header: 'Date', sortable: true },\n { key: 'amount', header: 'Amount' },\n {\n key: 'status',\n header: 'Status',\n cell: (invoice) => (\n <Badge\n variant={\n invoice.status.toLowerCase() === 'paid' ? 'success' : 'warning'\n }\n >\n {invoice.status}\n </Badge>\n ),\n },\n {\n key: 'id',\n header: <span className=\"sr-only\">Actions</span>,\n cell: (invoice) =>\n onView && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onView(invoice)}>\n View\n </Button>\n ),\n },\n ];\n return (\n <DataTable\n data={invoices}\n columns={columns}\n emptyMessage=\"No invoices yet.\"\n />\n );\n}\nexport function PricingTable({\n plans,\n onSelect,\n}: {\n plans: Array<{\n name: string;\n price: string;\n description?: string;\n features: string[];\n highlighted?: boolean;\n }>;\n onSelect: (plan: string) => void;\n}) {\n return (\n <div className=\"grid gap-4 md:grid-cols-3\">\n {plans.map((plan) => (\n <Card\n key={plan.name}\n className={\n plan.highlighted ? 'border-[hsl(var(--rui-primary))]' : undefined\n }\n >\n <CardTitle>{plan.name}</CardTitle>\n <p className=\"mt-3 text-2xl font-bold\">{plan.price}</p>\n {plan.description && (\n <CardDescription>{plan.description}</CardDescription>\n )}\n <ul className=\"my-5 space-y-2 text-sm\">\n {plan.features.map((feature) => (\n <li key={feature}>✓ {feature}</li>\n ))}\n </ul>\n <Button\n className=\"w-full\"\n variant={plan.highlighted ? 'primary' : 'outline'}\n onClick={() => onSelect(plan.name)}\n >\n Choose {plan.name}\n </Button>\n </Card>\n ))}\n </div>\n );\n}\nexport function BillingPage({\n subscription,\n paymentMethod,\n invoices,\n onChangePlan,\n onUpdatePaymentMethod,\n onCancel,\n onViewInvoice,\n}: {\n subscription?: Subscription;\n paymentMethod?: PaymentMethod;\n invoices: Invoice[];\n onChangePlan?: () => void;\n onUpdatePaymentMethod?: () => void;\n onCancel?: () => void;\n onViewInvoice?: (invoice: Invoice) => void;\n}) {\n return (\n <Stack gap={8}>\n <Section\n title=\"Billing\"\n description=\"Manage your plan and payment details.\"\n >\n <SubscriptionCard\n subscription={subscription}\n onChangePlan={onChangePlan}\n onCancel={onCancel}\n />\n </Section>\n <PaymentMethodCard\n paymentMethod={paymentMethod}\n onUpdate={onUpdatePaymentMethod}\n />\n <Section title=\"Invoices\">\n <InvoiceTable invoices={invoices} onView={onViewInvoice} />\n </Section>\n </Stack>\n );\n}\n","import { type ReactNode } from 'react';\nimport {\n Badge,\n Card,\n CardDescription,\n CardTitle,\n Container,\n PageContent,\n PageHeader,\n PageShell,\n} from '@sypra-ui/ui';\n\nexport function Hero({\n eyebrow,\n title,\n description,\n primaryAction,\n secondaryAction,\n}: {\n eyebrow?: ReactNode;\n title: ReactNode;\n description: ReactNode;\n primaryAction?: ReactNode;\n secondaryAction?: ReactNode;\n}) {\n return (\n <section className=\"py-20 text-center sm:py-28\">\n {eyebrow && <Badge>{eyebrow}</Badge>}\n <h1 className=\"mx-auto mt-5 max-w-3xl text-4xl font-bold tracking-tight sm:text-6xl\">\n {title}\n </h1>\n <p className=\"mx-auto mt-5 max-w-2xl text-lg text-[hsl(var(--rui-muted-foreground))]\">\n {description}\n </p>\n <div className=\"mt-8 flex flex-wrap justify-center gap-3\">\n {primaryAction}\n {secondaryAction}\n </div>\n </section>\n );\n}\nexport function FeatureGrid({\n features,\n}: {\n features: Array<{ title: string; description: string; icon?: ReactNode }>;\n}) {\n return (\n <section className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {features.map((feature) => (\n <Card key={feature.title}>\n {feature.icon && (\n <div className=\"mb-3 text-[hsl(var(--rui-primary))]\">\n {feature.icon}\n </div>\n )}\n <CardTitle>{feature.title}</CardTitle>\n <CardDescription>{feature.description}</CardDescription>\n </Card>\n ))}\n </section>\n );\n}\nexport function FAQ({\n items,\n}: {\n items: Array<{ question: string; answer: ReactNode }>;\n}) {\n return (\n <section className=\"mx-auto max-w-3xl space-y-4\">\n {items.map((item) => (\n <Card key={item.question}>\n <CardTitle>{item.question}</CardTitle>\n <CardDescription>{item.answer}</CardDescription>\n </Card>\n ))}\n </section>\n );\n}\nexport function CTA({\n title,\n description,\n action,\n}: {\n title: ReactNode;\n description?: ReactNode;\n action: ReactNode;\n}) {\n return (\n <section className=\"rounded-[calc(var(--rui-radius)+.2rem)] bg-[hsl(var(--rui-primary))] px-6 py-14 text-center text-[hsl(var(--rui-primary-foreground))]\">\n <h2 className=\"text-3xl font-bold\">{title}</h2>\n {description && <p className=\"mt-3 opacity-85\">{description}</p>}\n <div className=\"mt-6\">{action}</div>\n </section>\n );\n}\nexport function Footer({\n brand,\n links,\n}: {\n brand: ReactNode;\n links?: Array<{ label: string; href: string }>;\n}) {\n return (\n <footer className=\"mt-16 border-t border-[hsl(var(--rui-border))] py-8 text-sm text-[hsl(var(--rui-muted-foreground))]\">\n <div className=\"flex flex-wrap items-center justify-between gap-4\">\n <strong className=\"text-[hsl(var(--rui-foreground))]\">{brand}</strong>\n <div className=\"flex gap-4\">\n {links?.map((link) => (\n <a\n key={link.href}\n href={link.href}\n className=\"hover:text-[hsl(var(--rui-foreground))]\"\n >\n {link.label}\n </a>\n ))}\n </div>\n </div>\n </footer>\n );\n}\nexport function LandingPage({\n brand,\n hero,\n features,\n children,\n as,\n}: {\n brand: ReactNode;\n hero: {\n title: ReactNode;\n description: ReactNode;\n primaryAction?: ReactNode;\n secondaryAction?: ReactNode;\n };\n features?: Array<{ title: string; description: string; icon?: ReactNode }>;\n children?: ReactNode;\n as?: 'main' | 'div';\n}) {\n return (\n <PageShell as={as}>\n <Container>\n <header className=\"flex h-16 items-center justify-between\">\n <strong>{brand}</strong>\n </header>\n <Hero {...hero} />\n {features && <FeatureGrid features={features} />}\n {children}\n <Footer brand={brand} />\n </Container>\n </PageShell>\n );\n}\n\nexport function SettingsPageDemo({ children }: { children: ReactNode }) {\n return (\n <PageShell>\n <Container className=\"py-8\">\n <PageHeader title=\"Settings\" description=\"Manage your account.\" />\n <PageContent>{children}</PageContent>\n </Container>\n </PageShell>\n );\n}\n"],"mappings":"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","names":["useState","Button","Card","CardDescription","CardTitle","Dialog","DialogContent","DialogDescription","DialogHeader","DialogTitle","Input","Label","Separator","jsx","jsxs","Badge","Button","Card","CardDescription","CardHeader","CardTitle","EmptyState","Section","Stack","jsx","jsxs","Badge","Card","CardDescription","CardTitle","PageShell","jsx","jsxs"]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@sypra-ui/pages",
3
+ "version": "0.1.0",
4
+ "description": "Data-and-callback driven React page compositions.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/surya-mp/ui-components.git",
9
+ "directory": "pages"
10
+ },
11
+ "homepage": "https://github.com/surya-mp/ui-components#readme",
12
+ "bugs": "https://github.com/surya-mp/ui-components/issues",
13
+ "keywords": [
14
+ "auth",
15
+ "billing",
16
+ "pages",
17
+ "react",
18
+ "saas",
19
+ "tailwindcss",
20
+ "typescript"
21
+ ],
22
+ "type": "module",
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "peerDependencies": {
38
+ "react": ">=18",
39
+ "react-dom": ">=18",
40
+ "@sypra-ui/ui": "^0.1.0"
41
+ },
42
+ "devDependencies": {
43
+ "@testing-library/jest-dom": "^6.6.3",
44
+ "@testing-library/react": "^16.1.0",
45
+ "@testing-library/user-event": "^14.5.2",
46
+ "@types/react": "^19.0.2",
47
+ "@types/react-dom": "^19.0.2",
48
+ "react": "^19.0.0",
49
+ "react-dom": "^19.0.0",
50
+ "jsdom": "^25.0.1",
51
+ "tsup": "^8.3.5",
52
+ "typescript": "^5.7.2",
53
+ "vitest": "^2.1.8",
54
+ "@sypra-ui/ui": "0.1.0"
55
+ },
56
+ "scripts": {
57
+ "build": "tsup src/index.tsx --format esm --dts --sourcemap --external react --external react-dom --external @sypra-ui/ui --clean",
58
+ "typecheck": "tsc --noEmit",
59
+ "test": "vitest run",
60
+ "lint": "eslint src && prettier --check src"
61
+ }
62
+ }