@slyxup/ui 0.2.15 → 0.3.1
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/package.json +6 -3
- package/.turbo/turbo-build.log +0 -4
- package/CHANGELOG.md +0 -70
- package/src/components/AdminPanel/AdminPanel.tsx +0 -1081
- package/src/components/BillingPortal/BillingPortal.tsx +0 -184
- package/src/components/EmailVerification/EmailVerification.tsx +0 -182
- package/src/components/ForgotPassword/ForgotPassword.tsx +0 -124
- package/src/components/PricingTable/PricingTable.tsx +0 -157
- package/src/components/ResetPassword/ResetPassword.tsx +0 -122
- package/src/components/SignIn/SignIn.tsx +0 -239
- package/src/components/SignUp/SignUp.tsx +0 -211
- package/src/components/SocialButtons/SocialButtons.tsx +0 -47
- package/src/components/UserButton/UserButton.tsx +0 -101
- package/src/components/UserProfile/UserProfile.tsx +0 -1776
- package/src/icons.tsx +0 -71
- package/src/index.ts +0 -56
- package/src/lib/paddle.ts +0 -131
- package/src/styles.ts +0 -619
- package/test/components.test.tsx +0 -135
- package/test/icons.test.tsx +0 -32
- package/test/styles.test.ts +0 -47
- package/tsconfig.json +0 -1
- package/vitest.config.ts +0 -2
package/src/icons.tsx
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/** Shared icons (stroke = currentColor) */
|
|
2
|
-
|
|
3
|
-
export function KeyholeMark() {
|
|
4
|
-
return (
|
|
5
|
-
<svg
|
|
6
|
-
width="22"
|
|
7
|
-
height="22"
|
|
8
|
-
viewBox="0 0 24 24"
|
|
9
|
-
fill="none"
|
|
10
|
-
aria-hidden="true"
|
|
11
|
-
>
|
|
12
|
-
<circle cx="12" cy="9" r="3.2" fill="white" />
|
|
13
|
-
<path d="M10.6 11.5h2.8l.7 6h-4.2l.7-6z" fill="white" />
|
|
14
|
-
</svg>
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function GoogleIcon() {
|
|
19
|
-
return (
|
|
20
|
-
<svg width="17" height="17" viewBox="0 0 18 18" aria-hidden="true">
|
|
21
|
-
<path
|
|
22
|
-
fill="#4285F4"
|
|
23
|
-
d="M17.64 9.2c0-.63-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92a8.78 8.78 0 0 0 2.68-6.62z"
|
|
24
|
-
/>
|
|
25
|
-
<path
|
|
26
|
-
fill="#34A853"
|
|
27
|
-
d="M9 18c2.43 0 4.47-.8 5.96-2.18l-2.91-2.26c-.81.54-1.84.86-3.05.86-2.34 0-4.33-1.58-5.04-3.71H.96v2.33A9 9 0 0 0 9 18z"
|
|
28
|
-
/>
|
|
29
|
-
<path
|
|
30
|
-
fill="#FBBC05"
|
|
31
|
-
d="M3.96 10.71a5.41 5.41 0 0 1 0-3.42V4.96H.96a9 9 0 0 0 0 8.08l3-2.33z"
|
|
32
|
-
/>
|
|
33
|
-
<path
|
|
34
|
-
fill="#EA4335"
|
|
35
|
-
d="M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.59A9 9 0 0 0 .96 4.96l3 2.33C4.67 5.16 6.66 3.58 9 3.58z"
|
|
36
|
-
/>
|
|
37
|
-
</svg>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function GitHubIcon() {
|
|
42
|
-
return (
|
|
43
|
-
<svg
|
|
44
|
-
width="17"
|
|
45
|
-
height="17"
|
|
46
|
-
viewBox="0 0 16 16"
|
|
47
|
-
fill="currentColor"
|
|
48
|
-
aria-hidden="true"
|
|
49
|
-
>
|
|
50
|
-
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8z" />
|
|
51
|
-
</svg>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function CheckIcon() {
|
|
56
|
-
return (
|
|
57
|
-
<svg
|
|
58
|
-
width="22"
|
|
59
|
-
height="22"
|
|
60
|
-
viewBox="0 0 24 24"
|
|
61
|
-
fill="none"
|
|
62
|
-
stroke="currentColor"
|
|
63
|
-
strokeWidth="2.4"
|
|
64
|
-
strokeLinecap="round"
|
|
65
|
-
strokeLinejoin="round"
|
|
66
|
-
aria-hidden="true"
|
|
67
|
-
>
|
|
68
|
-
<path d="M20 6L9 17l-5-5" />
|
|
69
|
-
</svg>
|
|
70
|
-
);
|
|
71
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
export { injectStyles, CSS } from './styles';
|
|
2
|
-
export { KeyholeMark, GoogleIcon, GitHubIcon, CheckIcon } from './icons';
|
|
3
|
-
|
|
4
|
-
export { SignIn, type SignInProps } from './components/SignIn/SignIn';
|
|
5
|
-
export { SignUp, type SignUpProps } from './components/SignUp/SignUp';
|
|
6
|
-
export {
|
|
7
|
-
UserButton,
|
|
8
|
-
type UserButtonProps,
|
|
9
|
-
} from './components/UserButton/UserButton';
|
|
10
|
-
export {
|
|
11
|
-
UserProfile,
|
|
12
|
-
type UserProfileProps,
|
|
13
|
-
} from './components/UserProfile/UserProfile';
|
|
14
|
-
export {
|
|
15
|
-
ForgotPassword,
|
|
16
|
-
type ForgotPasswordProps,
|
|
17
|
-
} from './components/ForgotPassword/ForgotPassword';
|
|
18
|
-
export {
|
|
19
|
-
ResetPassword,
|
|
20
|
-
type ResetPasswordProps,
|
|
21
|
-
} from './components/ResetPassword/ResetPassword';
|
|
22
|
-
export {
|
|
23
|
-
EmailVerification,
|
|
24
|
-
type EmailVerificationProps,
|
|
25
|
-
} from './components/EmailVerification/EmailVerification';
|
|
26
|
-
export {
|
|
27
|
-
SocialButtons,
|
|
28
|
-
type SocialButtonsProps,
|
|
29
|
-
} from './components/SocialButtons/SocialButtons';
|
|
30
|
-
export {
|
|
31
|
-
BillingPortal,
|
|
32
|
-
type BillingPortalProps,
|
|
33
|
-
} from './components/BillingPortal/BillingPortal';
|
|
34
|
-
export {
|
|
35
|
-
PricingTable,
|
|
36
|
-
type PricingTableProps,
|
|
37
|
-
} from './components/PricingTable/PricingTable';
|
|
38
|
-
export {
|
|
39
|
-
AdminPanel,
|
|
40
|
-
type AdminPanelProps,
|
|
41
|
-
} from './components/AdminPanel/AdminPanel';
|
|
42
|
-
export { initPaddle, openPaddleCheckout } from './lib/paddle';
|
|
43
|
-
|
|
44
|
-
import { useEffect } from 'react';
|
|
45
|
-
import { injectStyles } from './styles';
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Inject the SlyxUp stylesheet once. Render inside your app root
|
|
49
|
-
* (or rely on any component auto-injecting on mount).
|
|
50
|
-
*/
|
|
51
|
-
export function SlyxUpStyles(): null {
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
injectStyles();
|
|
54
|
-
}, []);
|
|
55
|
-
return null;
|
|
56
|
-
}
|
package/src/lib/paddle.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
// Paddle.js loader — lazy-loads Paddle.js and initializes overlay checkout
|
|
2
|
-
// Docs: https://developer.paddle.com/paddle-js
|
|
3
|
-
|
|
4
|
-
declare global {
|
|
5
|
-
interface Window {
|
|
6
|
-
Paddle?: {
|
|
7
|
-
Initialize: (config: {
|
|
8
|
-
token: string;
|
|
9
|
-
eventCallback?: (data: Record<string, unknown>) => void;
|
|
10
|
-
}) => void;
|
|
11
|
-
Environment: { set: (env: 'sandbox' | 'production') => void };
|
|
12
|
-
Checkout: {
|
|
13
|
-
open: (options: {
|
|
14
|
-
items: Array<{ priceId: string; quantity: number }>;
|
|
15
|
-
customer?: { email?: string };
|
|
16
|
-
settings?: Record<string, unknown>;
|
|
17
|
-
customData?: Record<string, unknown>;
|
|
18
|
-
}) => void;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const PADDLE_JS_URL = 'https://cdn.paddle.com/paddle/v2/paddle.js';
|
|
25
|
-
let paddleLoaded = false;
|
|
26
|
-
let paddleInitPromise: Promise<void> | null = null;
|
|
27
|
-
|
|
28
|
-
function loadScript(src: string): Promise<void> {
|
|
29
|
-
return new Promise((resolve, reject) => {
|
|
30
|
-
if (document.querySelector(`script[src="${src}"]`)) {
|
|
31
|
-
resolve();
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
const s = document.createElement('script');
|
|
35
|
-
s.src = src;
|
|
36
|
-
s.onload = () => resolve();
|
|
37
|
-
s.onerror = () => reject(new Error(`Failed to load ${src}`));
|
|
38
|
-
document.head.appendChild(s);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Derive billing URL from auth API URL.
|
|
44
|
-
* localhost:8787 → localhost:8788, auth.slyxup.online → billing.slyxup.online
|
|
45
|
-
*/
|
|
46
|
-
function deriveBillingUrl(authApiUrl: string): string {
|
|
47
|
-
if (/^https?:\/\/localhost(:\d+)?$/.test(authApiUrl)) {
|
|
48
|
-
return authApiUrl.replace(/:(\d+)$/, ':8788');
|
|
49
|
-
}
|
|
50
|
-
return authApiUrl.replace('auth.slyxup.online', 'billing.slyxup.online');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface BillingConfig {
|
|
54
|
-
environment: 'sandbox' | 'production';
|
|
55
|
-
clientToken: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
let cachedConfig: BillingConfig | null = null;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Fetch Paddle config from billing Worker's /v1/billing/config endpoint.
|
|
62
|
-
* Cached after first fetch.
|
|
63
|
-
*/
|
|
64
|
-
async function fetchBillingConfig(billingUrl: string): Promise<BillingConfig> {
|
|
65
|
-
if (cachedConfig) return cachedConfig;
|
|
66
|
-
const res = await fetch(`${billingUrl}/v1/billing/config`);
|
|
67
|
-
const data = (await res.json().catch(() => ({}))) as {
|
|
68
|
-
ok?: boolean;
|
|
69
|
-
environment?: string;
|
|
70
|
-
clientToken?: string;
|
|
71
|
-
};
|
|
72
|
-
if (!res.ok || !data.ok || !data.clientToken) {
|
|
73
|
-
throw new Error('Failed to fetch billing config');
|
|
74
|
-
}
|
|
75
|
-
cachedConfig = {
|
|
76
|
-
environment: (data.environment as 'sandbox' | 'production') ?? 'sandbox',
|
|
77
|
-
clientToken: data.clientToken,
|
|
78
|
-
};
|
|
79
|
-
return cachedConfig;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Load Paddle.js and initialize with config from billing Worker.
|
|
84
|
-
* Safe to call multiple times — only loads the script once.
|
|
85
|
-
*/
|
|
86
|
-
export async function initPaddle(authApiUrl: string): Promise<void> {
|
|
87
|
-
if (paddleLoaded && window.Paddle) return;
|
|
88
|
-
|
|
89
|
-
if (!paddleInitPromise) {
|
|
90
|
-
paddleInitPromise = (async () => {
|
|
91
|
-
const billingUrl = deriveBillingUrl(authApiUrl);
|
|
92
|
-
const config = await fetchBillingConfig(billingUrl);
|
|
93
|
-
await loadScript(PADDLE_JS_URL);
|
|
94
|
-
if (!window.Paddle) throw new Error('Paddle.js failed to load');
|
|
95
|
-
window.Paddle.Environment.set(config.environment);
|
|
96
|
-
window.Paddle.Initialize({
|
|
97
|
-
token: config.clientToken,
|
|
98
|
-
eventCallback: (data) => {
|
|
99
|
-
if (data && data.name === 'checkout.completed') {
|
|
100
|
-
// Subscription is created via webhook. Notify the host app so it can
|
|
101
|
-
// refresh billing state and show a success confirmation.
|
|
102
|
-
window.dispatchEvent(new CustomEvent('slyxup:checkout-completed'));
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
paddleLoaded = true;
|
|
107
|
-
})();
|
|
108
|
-
}
|
|
109
|
-
return paddleInitPromise;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Open Paddle overlay checkout for a given price ID.
|
|
114
|
-
* `customData` is copied to the created transaction (and, for recurring
|
|
115
|
-
* items, to the related subscription) — the billing webhook uses it to
|
|
116
|
-
* attribute the subscription to a SlyxUp user + project + plan.
|
|
117
|
-
*/
|
|
118
|
-
export function openPaddleCheckout(
|
|
119
|
-
priceId: string,
|
|
120
|
-
customerEmail?: string,
|
|
121
|
-
customData?: Record<string, unknown>
|
|
122
|
-
): void {
|
|
123
|
-
if (!window.Paddle) {
|
|
124
|
-
throw new Error('Paddle.js not initialized — call initPaddle() first');
|
|
125
|
-
}
|
|
126
|
-
window.Paddle.Checkout.open({
|
|
127
|
-
items: [{ priceId, quantity: 1 }],
|
|
128
|
-
...(customerEmail ? { customer: { email: customerEmail } } : {}),
|
|
129
|
-
...(customData ? { customData } : {}),
|
|
130
|
-
});
|
|
131
|
-
}
|