@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 +21 -0
- package/README.md +30 -0
- package/dist/index.d.ts +221 -0
- package/dist/index.js +850 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
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.
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|