@slyxup/ui 0.2.1 → 0.2.3
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +67 -3
- package/dist/components/BillingPortal/BillingPortal.d.ts.map +1 -1
- package/dist/components/BillingPortal/BillingPortal.js +2 -0
- package/dist/components/BillingPortal/BillingPortal.js.map +1 -1
- package/dist/components/EmailVerification/EmailVerification.d.ts.map +1 -1
- package/dist/components/EmailVerification/EmailVerification.js +2 -0
- package/dist/components/EmailVerification/EmailVerification.js.map +1 -1
- package/dist/components/ForgotPassword/ForgotPassword.d.ts.map +1 -1
- package/dist/components/ForgotPassword/ForgotPassword.js +2 -0
- package/dist/components/ForgotPassword/ForgotPassword.js.map +1 -1
- package/dist/components/PricingTable/PricingTable.d.ts.map +1 -1
- package/dist/components/PricingTable/PricingTable.js +2 -0
- package/dist/components/PricingTable/PricingTable.js.map +1 -1
- package/dist/components/ResetPassword/ResetPassword.d.ts.map +1 -1
- package/dist/components/ResetPassword/ResetPassword.js +2 -0
- package/dist/components/ResetPassword/ResetPassword.js.map +1 -1
- package/dist/components/SignIn/SignIn.d.ts +3 -1
- package/dist/components/SignIn/SignIn.d.ts.map +1 -1
- package/dist/components/SignIn/SignIn.js +5 -11
- package/dist/components/SignIn/SignIn.js.map +1 -1
- package/dist/components/SignUp/SignUp.d.ts.map +1 -1
- package/dist/components/SignUp/SignUp.js +4 -10
- package/dist/components/SignUp/SignUp.js.map +1 -1
- package/dist/components/SocialButtons/SocialButtons.d.ts +1 -1
- package/dist/components/SocialButtons/SocialButtons.d.ts.map +1 -1
- package/dist/components/SocialButtons/SocialButtons.js +7 -2
- package/dist/components/SocialButtons/SocialButtons.js.map +1 -1
- package/dist/components/UserButton/UserButton.d.ts.map +1 -1
- package/dist/components/UserButton/UserButton.js +2 -0
- package/dist/components/UserButton/UserButton.js.map +1 -1
- package/dist/components/UserProfile/UserProfile.d.ts +8 -2
- package/dist/components/UserProfile/UserProfile.d.ts.map +1 -1
- package/dist/components/UserProfile/UserProfile.js +202 -6
- package/dist/components/UserProfile/UserProfile.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/styles.d.ts +6 -3
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +194 -73
- package/dist/styles.js.map +1 -1
- package/package.json +2 -2
- package/src/components/BillingPortal/BillingPortal.tsx +2 -0
- package/src/components/EmailVerification/EmailVerification.tsx +2 -0
- package/src/components/ForgotPassword/ForgotPassword.tsx +2 -0
- package/src/components/PricingTable/PricingTable.tsx +2 -0
- package/src/components/ResetPassword/ResetPassword.tsx +2 -0
- package/src/components/SignIn/SignIn.tsx +22 -17
- package/src/components/SignUp/SignUp.tsx +5 -13
- package/src/components/SocialButtons/SocialButtons.tsx +10 -3
- package/src/components/UserButton/UserButton.tsx +2 -0
- package/src/components/UserProfile/UserProfile.tsx +538 -56
- package/src/index.ts +4 -1
- package/src/styles.ts +194 -73
package/dist/styles.js
CHANGED
|
@@ -1,41 +1,69 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SlyxUp UI — design tokens + stylesheet.
|
|
3
|
-
* Injected
|
|
3
|
+
* Injected automatically by every SlyxUp component. Theme by overriding
|
|
4
|
+
* CSS variables on :root or .slyxup-scope.
|
|
4
5
|
*/
|
|
5
6
|
export const FONT_LINK = `<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600;9..40,700;9..40,800&family=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">`;
|
|
6
7
|
export const CSS = `
|
|
7
8
|
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600;9..40,700;9..40,800&family=Space+Grotesk:wght@400;500;600;700&display=swap');
|
|
8
9
|
|
|
9
10
|
.slyxup-root {
|
|
11
|
+
/* ── Tokens ── */
|
|
10
12
|
--slx-accent: #5b5bd6;
|
|
11
13
|
--slx-accent-hover: #4c4cc4;
|
|
12
|
-
--slx-accent-soft: rgba(91, 91, 214, 0.
|
|
14
|
+
--slx-accent-soft: rgba(91, 91, 214, 0.12);
|
|
13
15
|
--slx-bg: #ffffff;
|
|
16
|
+
--slx-bg-subtle: #f7f7fb;
|
|
14
17
|
--slx-bg-page: #e9eaf6;
|
|
15
18
|
--slx-ink: #16161d;
|
|
19
|
+
--slx-ink-strong: #0c0c12;
|
|
16
20
|
--slx-muted: #6f6f7b;
|
|
17
|
-
--slx-border: #
|
|
21
|
+
--slx-border: #e3e3ee;
|
|
22
|
+
--slx-border-strong: #d3d3e2;
|
|
18
23
|
--slx-danger: #d64550;
|
|
19
|
-
--slx-
|
|
24
|
+
--slx-success: #1f9d55;
|
|
25
|
+
--slx-radius-sm: 8px;
|
|
26
|
+
--slx-radius: 10px;
|
|
27
|
+
--slx-radius-lg: 14px;
|
|
20
28
|
--slx-font: "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
21
29
|
--slx-display: "Space Grotesk", "DM Sans", sans-serif;
|
|
22
30
|
--slx-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
31
|
+
--slx-shadow-card:
|
|
32
|
+
0 1px 2px rgba(18,18,28,.05),
|
|
33
|
+
0 8px 24px -6px rgba(18,18,28,.09),
|
|
34
|
+
0 24px 64px -16px rgba(18,18,28,.13);
|
|
35
|
+
--slx-shadow-pop:
|
|
36
|
+
0 2px 6px rgba(18,18,28,.08),
|
|
37
|
+
0 16px 48px -12px rgba(18,18,28,.18);
|
|
23
38
|
|
|
24
39
|
font-family: var(--slx-font);
|
|
25
40
|
color: var(--slx-ink);
|
|
26
41
|
-webkit-font-smoothing: antialiased;
|
|
42
|
+
text-rendering: optimizeLegibility;
|
|
43
|
+
font-feature-settings: "cv11", "ss01";
|
|
27
44
|
}
|
|
28
45
|
@media (prefers-color-scheme: dark) {
|
|
29
46
|
.slyxup-root:not(.slyxup-light) {
|
|
30
47
|
--slx-accent: #8484f2;
|
|
31
48
|
--slx-accent-hover: #9696f5;
|
|
32
|
-
--slx-accent-soft: rgba(132, 132, 242, 0.
|
|
33
|
-
--slx-bg: #
|
|
34
|
-
--slx-bg-
|
|
35
|
-
--slx-
|
|
49
|
+
--slx-accent-soft: rgba(132, 132, 242, 0.16);
|
|
50
|
+
--slx-bg: #17171f;
|
|
51
|
+
--slx-bg-subtle: #1e1e28;
|
|
52
|
+
--slx-bg-page: #101016;
|
|
53
|
+
--slx-ink: #f0f0f4;
|
|
54
|
+
--slx-ink-strong: #ffffff;
|
|
36
55
|
--slx-muted: #9a9aa6;
|
|
37
|
-
--slx-border: #
|
|
56
|
+
--slx-border: #292935;
|
|
57
|
+
--slx-border-strong: #343442;
|
|
38
58
|
--slx-danger: #f0737d;
|
|
59
|
+
--slx-success: #4ade80;
|
|
60
|
+
--slx-shadow-card:
|
|
61
|
+
0 1px 2px rgba(0,0,0,.25),
|
|
62
|
+
0 12px 32px -8px rgba(0,0,0,.5),
|
|
63
|
+
0 32px 72px -20px rgba(0,0,0,.55);
|
|
64
|
+
--slx-shadow-pop:
|
|
65
|
+
0 4px 12px rgba(0,0,0,.4),
|
|
66
|
+
0 24px 56px -12px rgba(0,0,0,.6);
|
|
39
67
|
}
|
|
40
68
|
}
|
|
41
69
|
|
|
@@ -46,6 +74,15 @@ export const CSS = `
|
|
|
46
74
|
40%, 60% { transform: translateX(4px); }
|
|
47
75
|
}
|
|
48
76
|
@keyframes slx-spin { to { transform: rotate(360deg); } }
|
|
77
|
+
@keyframes slx-rise {
|
|
78
|
+
from { opacity: 0; transform: translateY(8px) scale(.985); }
|
|
79
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
80
|
+
}
|
|
81
|
+
@keyframes slx-pop {
|
|
82
|
+
0% { transform: scale(.5); opacity: 0; }
|
|
83
|
+
60% { transform: scale(1.08); opacity: 1; }
|
|
84
|
+
100% { transform: scale(1); }
|
|
85
|
+
}
|
|
49
86
|
@media (prefers-reduced-motion: reduce) {
|
|
50
87
|
.slyxup-root * { animation: none !important; transition: none !important; }
|
|
51
88
|
}
|
|
@@ -53,101 +90,155 @@ export const CSS = `
|
|
|
53
90
|
/* ── Card ── */
|
|
54
91
|
.slx-card {
|
|
55
92
|
width: 100%;
|
|
56
|
-
max-width:
|
|
93
|
+
max-width: 400px;
|
|
57
94
|
background: var(--slx-bg);
|
|
58
95
|
border: 1px solid var(--slx-border);
|
|
59
|
-
border-radius:
|
|
60
|
-
padding:
|
|
61
|
-
box-shadow:
|
|
96
|
+
border-radius: var(--slx-radius-lg);
|
|
97
|
+
padding: 34px 34px 30px;
|
|
98
|
+
box-shadow: var(--slx-shadow-card);
|
|
62
99
|
box-sizing: border-box;
|
|
100
|
+
animation: slx-rise .38s cubic-bezier(.22,.9,.32,1) both;
|
|
63
101
|
}
|
|
64
|
-
.slyxup-root .slx-card
|
|
102
|
+
.slyxup-root:not(.slyxup-light) .slx-card,
|
|
103
|
+
.slx-card { color: var(--slx-ink); }
|
|
65
104
|
.slx-card-error { animation: slx-shake .45s cubic-bezier(.36,.07,.19,.97) both; }
|
|
66
105
|
|
|
67
106
|
/* ── Header / keyhole mark ── */
|
|
68
107
|
.slx-mark {
|
|
69
|
-
width:
|
|
108
|
+
width: 46px; height: 46px; border-radius: 13px;
|
|
70
109
|
display: flex; align-items: center; justify-content: center;
|
|
71
|
-
background: linear-gradient(
|
|
72
|
-
|
|
110
|
+
background: linear-gradient(140deg, var(--slx-accent) 0%, #8b5cf6 100%);
|
|
111
|
+
box-shadow:
|
|
112
|
+
inset 0 1px 0 rgba(255,255,255,.28),
|
|
113
|
+
0 6px 16px -6px rgba(91,91,214,.55);
|
|
114
|
+
margin-bottom: 20px;
|
|
115
|
+
}
|
|
116
|
+
.slx-mark svg { display: block; filter: drop-shadow(0 1px 1px rgba(0,0,0,.18)); }
|
|
117
|
+
.slx-title {
|
|
118
|
+
font-family: var(--slx-display);
|
|
119
|
+
font-size: 21px; font-weight: 650; letter-spacing: -0.022em;
|
|
120
|
+
color: var(--slx-ink-strong);
|
|
121
|
+
margin: 0 0 6px;
|
|
73
122
|
}
|
|
74
|
-
.slx-
|
|
75
|
-
.slx-title { font-family: var(--slx-display); font-size: 20px; font-weight: 650; letter-spacing: -0.02em; margin: 0 0 6px; }
|
|
76
|
-
.slx-subtitle { font-size: 13.5px; color: var(--slx-muted); margin: 0 0 22px; line-height: 1.5; }
|
|
123
|
+
.slx-subtitle { font-size: 13.5px; color: var(--slx-muted); margin: 0 0 24px; line-height: 1.55; }
|
|
77
124
|
|
|
78
125
|
/* ── Fields ── */
|
|
79
|
-
.slx-field { margin-bottom:
|
|
80
|
-
.slx-
|
|
126
|
+
.slx-field { margin-bottom: 15px; }
|
|
127
|
+
.slx-row {
|
|
128
|
+
display: flex; align-items: baseline; justify-content: space-between;
|
|
129
|
+
margin-bottom: 6px;
|
|
130
|
+
}
|
|
131
|
+
.slx-label {
|
|
132
|
+
display: inline-block;
|
|
133
|
+
font-size: 12.5px; font-weight: 550; letter-spacing: 0.01em;
|
|
134
|
+
color: var(--slx-ink);
|
|
135
|
+
}
|
|
81
136
|
.slx-input {
|
|
82
137
|
width: 100%; box-sizing: border-box;
|
|
83
|
-
font: inherit; font-size: 14px; color: var(--slx-ink);
|
|
84
|
-
background:
|
|
138
|
+
font: inherit; font-size: 14px; line-height: 1.4; color: var(--slx-ink);
|
|
139
|
+
background: var(--slx-bg-subtle);
|
|
85
140
|
border: 1px solid var(--slx-border);
|
|
86
141
|
border-radius: var(--slx-radius);
|
|
87
|
-
padding: 10px
|
|
142
|
+
padding: 10px 13px;
|
|
88
143
|
outline: none;
|
|
89
|
-
transition: border-color .15s, box-shadow .15s;
|
|
144
|
+
transition: border-color .15s, box-shadow .15s, background .15s;
|
|
90
145
|
}
|
|
91
|
-
.slx-input::placeholder { color: var(--slx-muted); opacity: .
|
|
146
|
+
.slx-input::placeholder { color: var(--slx-muted); opacity: .7; }
|
|
147
|
+
.slx-input:hover { border-color: var(--slx-border-strong); }
|
|
92
148
|
.slx-input:focus-visible {
|
|
149
|
+
background: var(--slx-bg);
|
|
93
150
|
border-color: var(--slx-accent);
|
|
94
|
-
box-shadow: 0 0 0
|
|
151
|
+
box-shadow: 0 0 0 3.5px var(--slx-accent-soft);
|
|
95
152
|
}
|
|
96
153
|
.slx-hint { font-size: 12px; color: var(--slx-muted); margin-top: 5px; }
|
|
97
154
|
.slx-error-text {
|
|
98
155
|
font-size: 13px; color: var(--slx-danger);
|
|
99
|
-
background: color-mix(in srgb, var(--slx-danger)
|
|
100
|
-
border
|
|
156
|
+
background: color-mix(in srgb, var(--slx-danger) 8%, transparent);
|
|
157
|
+
border: 1px solid color-mix(in srgb, var(--slx-danger) 26%, transparent);
|
|
158
|
+
border-left: 3px solid var(--slx-danger);
|
|
159
|
+
border-radius: var(--slx-radius-sm);
|
|
160
|
+
padding: 10px 12px; margin: 0 0 16px; line-height: 1.45;
|
|
161
|
+
}
|
|
162
|
+
.slx-setup-note {
|
|
163
|
+
font-size: 12px; line-height: 1.45;
|
|
164
|
+
color: #7a5c00;
|
|
165
|
+
background: #fff7dc;
|
|
166
|
+
border: 1px solid #f3e3a0;
|
|
167
|
+
border-radius: var(--slx-radius-sm);
|
|
168
|
+
padding: 9px 11px; margin: 0 0 16px;
|
|
169
|
+
}
|
|
170
|
+
.slyxup-root:not(.slyxup-light) .slx-setup-note {
|
|
171
|
+
color: #f5d878; background: rgba(250,204,21,.07); border-color: rgba(250,204,21,.25);
|
|
101
172
|
}
|
|
173
|
+
.slx-setup-note code {
|
|
174
|
+
font-family: var(--slx-mono); font-size: 11px;
|
|
175
|
+
background: rgba(0,0,0,.05); border-radius: 4px; padding: 1px 4px;
|
|
176
|
+
}
|
|
177
|
+
.slyxup-root:not(.slyxup-light) .slx-setup-note code { background: rgba(255,255,255,.08); }
|
|
102
178
|
|
|
103
|
-
/* ──
|
|
179
|
+
/* ── Primary button ── */
|
|
104
180
|
.slx-btn {
|
|
105
181
|
width: 100%; box-sizing: border-box;
|
|
106
182
|
font-family: var(--slx-font); font-size: 14px; font-weight: 600; letter-spacing: 0.01em;
|
|
107
|
-
color: #fff; background: #0a0a0f;
|
|
183
|
+
color: #fff; background: linear-gradient(180deg, #23232e 0%, #0a0a0f 100%);
|
|
108
184
|
border: 1px solid #0a0a0f; border-radius: var(--slx-radius);
|
|
109
185
|
padding: 11px 14px; cursor: pointer;
|
|
186
|
+
box-shadow: 0 1px 2px rgba(10,10,15,.35), inset 0 1px 0 rgba(255,255,255,.08);
|
|
110
187
|
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
|
111
|
-
transition:
|
|
188
|
+
transition: filter .15s, transform .06s, box-shadow .15s;
|
|
112
189
|
}
|
|
113
|
-
.slx-btn:hover {
|
|
114
|
-
.slx-btn:active { transform: scale(.985);
|
|
115
|
-
.slx-btn:focus-visible { outline: none; box-shadow: 0 0 0
|
|
116
|
-
.slx-btn[disabled] { opacity: .
|
|
190
|
+
.slx-btn:hover { filter: brightness(1.22); }
|
|
191
|
+
.slx-btn:active { transform: scale(.985); filter: brightness(.92); }
|
|
192
|
+
.slx-btn:focus-visible { outline: none; box-shadow: 0 0 0 3.5px rgba(10,10,15,.16), 0 0 0 1.5px #0a0a0f; }
|
|
193
|
+
.slx-btn[disabled] { opacity: .55; cursor: not-allowed; }
|
|
117
194
|
@media (prefers-color-scheme: dark) {
|
|
118
|
-
.slyxup-root:not(.slyxup-light) .slx-btn {
|
|
119
|
-
|
|
195
|
+
.slyxup-root:not(.slyxup-light) .slx-btn {
|
|
196
|
+
background: linear-gradient(180deg, #ffffff 0%, #ececf1 100%);
|
|
197
|
+
color: #0a0a0f; border-color: #ececf1;
|
|
198
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.9);
|
|
199
|
+
}
|
|
200
|
+
.slyxup-root:not(.slyxup-light) .slx-btn:hover { filter: brightness(.94); }
|
|
120
201
|
}
|
|
121
202
|
.slx-spinner {
|
|
122
203
|
width: 15px; height: 15px; flex: none;
|
|
123
204
|
border: 2px solid rgba(255,255,255,.35); border-top-color: #fff;
|
|
124
205
|
border-radius: 50%; animation: slx-spin .7s linear infinite;
|
|
125
206
|
}
|
|
207
|
+
.slyxup-root:not(.slyxup-light) .slx-spinner { border-color: rgba(10,10,15,.25); border-top-color: #0a0a0f; }
|
|
126
208
|
|
|
127
209
|
/* ── Social ── */
|
|
128
|
-
.slx-social { display: grid; gap:
|
|
210
|
+
.slx-social { display: grid; gap: 9px; margin-bottom: 4px; }
|
|
129
211
|
.slx-social-btn {
|
|
130
212
|
width: 100%; box-sizing: border-box;
|
|
131
213
|
font: inherit; font-size: 13.5px; font-weight: 550;
|
|
132
214
|
color: var(--slx-ink); background: var(--slx-bg);
|
|
133
|
-
border: 1px solid var(--slx-border); border-radius: var(--slx-radius);
|
|
215
|
+
border: 1px solid var(--slx-border-strong); border-radius: var(--slx-radius);
|
|
134
216
|
padding: 10px 14px; cursor: pointer;
|
|
135
217
|
display: inline-flex; align-items: center; justify-content: center; gap: 10px;
|
|
136
|
-
transition: background .15s, border-color .15s;
|
|
218
|
+
transition: background .15s, border-color .15s, transform .06s, box-shadow .15s;
|
|
137
219
|
}
|
|
138
|
-
.slx-social-btn:hover {
|
|
139
|
-
|
|
220
|
+
.slx-social-btn:hover {
|
|
221
|
+
background: var(--slx-bg-subtle);
|
|
222
|
+
border-color: var(--slx-border-strong);
|
|
223
|
+
box-shadow: 0 2px 8px -2px rgba(18,18,28,.12);
|
|
224
|
+
}
|
|
225
|
+
.slx-social-btn:active { transform: scale(.985); }
|
|
226
|
+
.slx-social-btn:focus-visible { outline: none; box-shadow: 0 0 0 3.5px var(--slx-accent-soft); }
|
|
227
|
+
.slx-social-btn svg { flex: none; }
|
|
140
228
|
|
|
141
229
|
/* ── Divider & footer ── */
|
|
142
230
|
.slx-divider {
|
|
143
|
-
display: flex; align-items: center; gap:
|
|
144
|
-
color: var(--slx-muted); font-size:
|
|
231
|
+
display: flex; align-items: center; gap: 14px;
|
|
232
|
+
color: var(--slx-muted); font-size: 11.5px;
|
|
233
|
+
letter-spacing: .04em; text-transform: uppercase;
|
|
145
234
|
margin: 18px 0;
|
|
146
235
|
}
|
|
147
236
|
.slx-divider::before, .slx-divider::after {
|
|
148
|
-
content: ""; height: 1px; flex: 1;
|
|
237
|
+
content: ""; height: 1px; flex: 1;
|
|
238
|
+
background: linear-gradient(90deg, transparent, var(--slx-border-strong));
|
|
149
239
|
}
|
|
150
|
-
.slx-
|
|
240
|
+
.slx-divider::after { background: linear-gradient(90deg, var(--slx-border-strong), transparent); }
|
|
241
|
+
.slx-footer { font-size: 13px; color: var(--slx-muted); margin-top: 22px; text-align: center; }
|
|
151
242
|
.slx-link {
|
|
152
243
|
color: var(--slx-accent); font-weight: 600; text-decoration: none; cursor: pointer;
|
|
153
244
|
background: none; border: none; font: inherit; font-size: inherit;
|
|
@@ -155,13 +246,16 @@ export const CSS = `
|
|
|
155
246
|
}
|
|
156
247
|
.slx-link:hover { text-decoration: underline; color: var(--slx-accent-hover); }
|
|
157
248
|
.slx-link:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--slx-accent-soft); border-radius: 4px; }
|
|
249
|
+
.slx-forgot { font-size: 12px; }
|
|
158
250
|
|
|
159
251
|
/* ── Success state ── */
|
|
160
252
|
.slx-success-icon {
|
|
161
|
-
width:
|
|
253
|
+
width: 48px; height: 48px; border-radius: 50%;
|
|
162
254
|
display: flex; align-items: center; justify-content: center;
|
|
163
|
-
background: color-mix(in srgb,
|
|
164
|
-
color:
|
|
255
|
+
background: color-mix(in srgb, var(--slx-success) 12%, transparent);
|
|
256
|
+
color: var(--slx-success); margin: 4px auto 18px;
|
|
257
|
+
animation: slx-pop .45s cubic-bezier(.22,.9,.32,1) both;
|
|
258
|
+
box-shadow: 0 0 0 6px color-mix(in srgb, var(--slx-success) 6%, transparent);
|
|
165
259
|
}
|
|
166
260
|
|
|
167
261
|
/* ── User button ── */
|
|
@@ -171,49 +265,76 @@ export const CSS = `
|
|
|
171
265
|
border: 1px solid var(--slx-border); cursor: pointer;
|
|
172
266
|
display: flex; align-items: center; justify-content: center;
|
|
173
267
|
font-size: 14px; font-weight: 650; color: #fff;
|
|
174
|
-
background: linear-gradient(135deg, var(--slx-accent), #
|
|
268
|
+
background: linear-gradient(135deg, var(--slx-accent), #8b5cf6);
|
|
175
269
|
padding: 0; overflow: hidden;
|
|
270
|
+
transition: box-shadow .15s, transform .06s;
|
|
176
271
|
}
|
|
272
|
+
.slx-userbtn-avatar:hover { box-shadow: 0 0 0 3px var(--slx-accent-soft); }
|
|
273
|
+
.slx-userbtn-avatar:active { transform: scale(.96); }
|
|
177
274
|
.slx-userbtn-avatar img { width: 100%; height: 100%; object-fit: cover; }
|
|
178
|
-
.slx-userbtn-avatar:focus-visible { outline: none; box-shadow: 0 0 0
|
|
275
|
+
.slx-userbtn-avatar:focus-visible { outline: none; box-shadow: 0 0 0 3.5px var(--slx-accent-soft); }
|
|
179
276
|
.slx-menu {
|
|
180
277
|
position: absolute; right: 0; top: calc(100% + 8px);
|
|
181
|
-
min-width:
|
|
278
|
+
min-width: 240px;
|
|
182
279
|
background: var(--slx-bg);
|
|
183
280
|
border: 1px solid var(--slx-border);
|
|
184
|
-
border-radius: var(--slx-radius);
|
|
185
|
-
box-shadow:
|
|
281
|
+
border-radius: var(--slx-radius-lg);
|
|
282
|
+
box-shadow: var(--slx-shadow-pop);
|
|
186
283
|
overflow: hidden; z-index: 1000;
|
|
284
|
+
animation: slx-rise .22s cubic-bezier(.22,.9,.32,1) both;
|
|
187
285
|
}
|
|
188
|
-
.slx-menu-header { padding: 14px 16px; border-bottom: 1px solid var(--slx-border); }
|
|
189
|
-
.slx-menu-name { font-size: 14px; font-weight: 600; margin: 0 0 2px; }
|
|
286
|
+
.slx-menu-header { padding: 14px 16px; border-bottom: 1px solid var(--slx-border); background: var(--slx-bg-subtle); }
|
|
287
|
+
.slx-menu-name { font-size: 14px; font-weight: 600; margin: 0 0 2px; color: var(--slx-ink-strong); }
|
|
190
288
|
.slx-menu-email { font-size: 12.5px; color: var(--slx-muted); margin: 0; word-break: break-all; }
|
|
191
289
|
.slx-menu-item {
|
|
192
290
|
display: block; width: 100%; text-align: left; box-sizing: border-box;
|
|
193
291
|
font: inherit; font-size: 13.5px; color: var(--slx-ink);
|
|
194
292
|
background: none; border: none; padding: 10px 16px; cursor: pointer;
|
|
293
|
+
transition: background .12s;
|
|
195
294
|
}
|
|
196
|
-
.slx-menu-item:hover { background: color-mix(in srgb, var(--slx-ink)
|
|
295
|
+
.slx-menu-item:hover { background: color-mix(in srgb, var(--slx-ink) 4%, transparent); }
|
|
197
296
|
.slx-menu-item:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--slx-accent-soft); }
|
|
198
297
|
.slx-menu-item-danger { color: var(--slx-danger); }
|
|
298
|
+
.slx-menu-item-danger:hover { background: color-mix(in srgb, var(--slx-danger) 7%, transparent); }
|
|
299
|
+
|
|
300
|
+
/* ── Badge (verified etc.) ── */
|
|
301
|
+
.slx-badge {
|
|
302
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
303
|
+
font-size: 11px; font-weight: 600; letter-spacing: .02em;
|
|
304
|
+
padding: 2.5px 9px; border-radius: 999px;
|
|
305
|
+
color: var(--slx-success);
|
|
306
|
+
background: color-mix(in srgb, var(--slx-success) 9%, transparent);
|
|
307
|
+
border: 1px solid color-mix(in srgb, var(--slx-success) 30%, transparent);
|
|
308
|
+
}
|
|
199
309
|
`;
|
|
200
310
|
let injected = false;
|
|
201
|
-
/** Inject the SlyxUp stylesheet +
|
|
311
|
+
/** Inject the SlyxUp stylesheet + fonts once per document. Idempotent + SSR-safe. */
|
|
202
312
|
export function injectStyles() {
|
|
203
|
-
if (
|
|
313
|
+
if (typeof document === 'undefined')
|
|
204
314
|
return;
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
315
|
+
// Design tokens are scoped to .slyxup-root — apply to <html> so the
|
|
316
|
+
// components work in ANY host app without a wrapper element.
|
|
317
|
+
document.documentElement.classList.add('slyxup-root');
|
|
318
|
+
if (!document.querySelector('style[data-slyxup="styles"]')) {
|
|
319
|
+
if (!document.querySelector('link[href*="DM+Sans"]')) {
|
|
320
|
+
const fontLink = document.createElement('link');
|
|
321
|
+
fontLink.rel = 'stylesheet';
|
|
322
|
+
fontLink.href =
|
|
323
|
+
'https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,300;9..40,400;9..40,500;9..40,600;9..40,700;9..40,800&family=Space+Grotesk:wght@400;500;600;700&display=swap';
|
|
324
|
+
document.head.appendChild(fontLink);
|
|
325
|
+
}
|
|
326
|
+
const style = document.createElement('style');
|
|
327
|
+
style.setAttribute('data-slyxup', 'styles');
|
|
328
|
+
style.textContent = CSS;
|
|
329
|
+
document.head.appendChild(style);
|
|
330
|
+
injected = true;
|
|
212
331
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
332
|
+
else {
|
|
333
|
+
injected = true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/** Test hook — whether styles are present. */
|
|
337
|
+
export function stylesInjected() {
|
|
338
|
+
return injected;
|
|
218
339
|
}
|
|
219
340
|
//# sourceMappingURL=styles.js.map
|
package/dist/styles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,6UAA6U,CAAC;AAEvW,MAAM,CAAC,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8SlB,CAAC;AAEF,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,qFAAqF;AACrF,MAAM,UAAU,YAAY;IAC1B,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO;IAC5C,oEAAoE;IACpE,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,6BAA6B,CAAC,EAAE,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAChD,QAAQ,CAAC,GAAG,GAAG,YAAY,CAAC;YAC5B,QAAQ,CAAC,IAAI;gBACX,+KAA+K,CAAC;YAClL,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC5C,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACjC,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;AACH,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slyxup/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "@slyxup/ui — SlyxUp SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@slyxup/core": "0.2.1",
|
|
27
|
-
"@slyxup/react": "0.2.
|
|
27
|
+
"@slyxup/react": "0.2.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "^26.2.0",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
|
+
import { injectStyles } from '../../styles';
|
|
4
5
|
|
|
5
6
|
interface Subscription {
|
|
6
7
|
id: string;
|
|
@@ -28,6 +29,7 @@ export function BillingPortal({
|
|
|
28
29
|
invoices,
|
|
29
30
|
onCancel,
|
|
30
31
|
}: BillingPortalProps) {
|
|
32
|
+
injectStyles();
|
|
31
33
|
if (!subscription) {
|
|
32
34
|
return (
|
|
33
35
|
<div className="slx-card">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type FormEvent, useEffect, useState } from 'react';
|
|
2
2
|
import { CheckIcon, KeyholeMark } from '../../icons';
|
|
3
|
+
import { injectStyles } from '../../styles';
|
|
3
4
|
|
|
4
5
|
export interface EmailVerificationProps {
|
|
5
6
|
/** Verification token (from email link ?token=...). If absent, shows resend form. */
|
|
@@ -14,6 +15,7 @@ export function EmailVerification({
|
|
|
14
15
|
apiUrl,
|
|
15
16
|
onSuccess,
|
|
16
17
|
}: EmailVerificationProps) {
|
|
18
|
+
injectStyles();
|
|
17
19
|
const [status, setStatus] = useState<
|
|
18
20
|
'verifying' | 'success' | 'error' | 'resend'
|
|
19
21
|
>(token ? 'verifying' : 'resend');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SlyxupClient } from '@slyxup/core';
|
|
2
2
|
import { type FormEvent, useEffect, useState } from 'react';
|
|
3
3
|
import { CheckIcon, KeyholeMark } from '../../icons';
|
|
4
|
+
import { injectStyles } from '../../styles';
|
|
4
5
|
|
|
5
6
|
export interface ForgotPasswordProps {
|
|
6
7
|
apiUrl?: string;
|
|
@@ -14,6 +15,7 @@ export function ForgotPassword({
|
|
|
14
15
|
onSuccess,
|
|
15
16
|
onBackToSignIn,
|
|
16
17
|
}: ForgotPasswordProps) {
|
|
18
|
+
injectStyles();
|
|
17
19
|
const [email, setEmail] = useState('');
|
|
18
20
|
const [sent, setSent] = useState(false);
|
|
19
21
|
const [busy, setBusy] = useState(false);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
|
+
import { injectStyles } from '../../styles';
|
|
4
5
|
|
|
5
6
|
interface Plan {
|
|
6
7
|
id: string;
|
|
@@ -21,6 +22,7 @@ export interface PricingTableProps {
|
|
|
21
22
|
|
|
22
23
|
/** Clean pricing grid with popular badge */
|
|
23
24
|
export function PricingTable({ plans, onSelect, loading }: PricingTableProps) {
|
|
25
|
+
injectStyles();
|
|
24
26
|
if (loading) {
|
|
25
27
|
return (
|
|
26
28
|
<div
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type FormEvent, useEffect, useState } from 'react';
|
|
2
2
|
import { CheckIcon, KeyholeMark } from '../../icons';
|
|
3
|
+
import { injectStyles } from '../../styles';
|
|
3
4
|
|
|
4
5
|
export interface ResetPasswordProps {
|
|
5
6
|
/** Reset token (from email link ?token=...) */
|
|
@@ -14,6 +15,7 @@ export function ResetPassword({
|
|
|
14
15
|
apiUrl,
|
|
15
16
|
onSuccess,
|
|
16
17
|
}: ResetPasswordProps) {
|
|
18
|
+
injectStyles();
|
|
17
19
|
const [password, setPassword] = useState('');
|
|
18
20
|
const [done, setDone] = useState(false);
|
|
19
21
|
const [busy, setBusy] = useState(false);
|
|
@@ -2,6 +2,7 @@ import { SlyxupError } from '@slyxup/core';
|
|
|
2
2
|
import { useAuth } from '@slyxup/react';
|
|
3
3
|
import { type FormEvent, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { GitHubIcon, GoogleIcon, KeyholeMark } from '../../icons';
|
|
5
|
+
import { injectStyles } from '../../styles';
|
|
5
6
|
|
|
6
7
|
export interface SignInProps {
|
|
7
8
|
/** Show social buttons (default true) */
|
|
@@ -10,6 +11,8 @@ export interface SignInProps {
|
|
|
10
11
|
onSuccess?: () => void;
|
|
11
12
|
/** Switch to sign up */
|
|
12
13
|
onSignUpClick?: () => void;
|
|
14
|
+
/** Show "Forgot password?" — navigates via this callback */
|
|
15
|
+
onForgotPasswordClick?: () => void;
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
/** Email/password + OAuth sign-in card. */
|
|
@@ -17,10 +20,12 @@ export function SignIn({
|
|
|
17
20
|
social = true,
|
|
18
21
|
onSuccess,
|
|
19
22
|
onSignUpClick,
|
|
23
|
+
onForgotPasswordClick,
|
|
20
24
|
}: SignInProps) {
|
|
25
|
+
injectStyles();
|
|
21
26
|
const { signIn, client } = useAuth() as unknown as {
|
|
22
27
|
signIn: ReturnType<typeof useAuth>['signIn'];
|
|
23
|
-
client: { publishableKey?: string };
|
|
28
|
+
client: { publishableKey?: string; apiUrl: string };
|
|
24
29
|
};
|
|
25
30
|
const [email, setEmail] = useState('');
|
|
26
31
|
const [password, setPassword] = useState('');
|
|
@@ -54,7 +59,7 @@ export function SignIn({
|
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
function oauth(provider: 'google' | 'github') {
|
|
57
|
-
window.location.href =
|
|
62
|
+
window.location.href = `${client.apiUrl}/v1/oauth/${provider}`;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
const missingKey =
|
|
@@ -65,17 +70,7 @@ export function SignIn({
|
|
|
65
70
|
return (
|
|
66
71
|
<div ref={cardRef} className={`slx-card${error ? ' slx-card-error' : ''}`}>
|
|
67
72
|
{missingKey && (
|
|
68
|
-
<p
|
|
69
|
-
style={{
|
|
70
|
-
fontSize: 12,
|
|
71
|
-
background: '#fff3cd',
|
|
72
|
-
border: '1px solid #ffe69c',
|
|
73
|
-
borderRadius: 8,
|
|
74
|
-
padding: '8px 10px',
|
|
75
|
-
marginBottom: 14,
|
|
76
|
-
lineHeight: 1.4,
|
|
77
|
-
}}
|
|
78
|
-
>
|
|
73
|
+
<p className="slx-setup-note">
|
|
79
74
|
<strong>Setup:</strong> Add{' '}
|
|
80
75
|
<code>NEXT_PUBLIC_SLYXUP_PUBLISHABLE_KEY</code> to{' '}
|
|
81
76
|
<code>.env.local</code> — run <code>npx @slyxup/cli keys create</code>
|
|
@@ -134,9 +129,20 @@ export function SignIn({
|
|
|
134
129
|
/>
|
|
135
130
|
</div>
|
|
136
131
|
<div className="slx-field">
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
132
|
+
<div className="slx-row">
|
|
133
|
+
<label className="slx-label" htmlFor="slx-signin-password">
|
|
134
|
+
Password
|
|
135
|
+
</label>
|
|
136
|
+
{onForgotPasswordClick && (
|
|
137
|
+
<button
|
|
138
|
+
type="button"
|
|
139
|
+
className="slx-link slx-forgot"
|
|
140
|
+
onClick={onForgotPasswordClick}
|
|
141
|
+
>
|
|
142
|
+
Forgot password?
|
|
143
|
+
</button>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
140
146
|
<input
|
|
141
147
|
id="slx-signin-password"
|
|
142
148
|
className="slx-input"
|
|
@@ -146,7 +152,6 @@ export function SignIn({
|
|
|
146
152
|
value={password}
|
|
147
153
|
onChange={(e) => setPassword(e.target.value)}
|
|
148
154
|
required
|
|
149
|
-
minLength={8}
|
|
150
155
|
/>
|
|
151
156
|
</div>
|
|
152
157
|
<button className="slx-btn" type="submit" disabled={busy}>
|
|
@@ -2,6 +2,7 @@ import { SlyxupError } from '@slyxup/core';
|
|
|
2
2
|
import { useAuth } from '@slyxup/react';
|
|
3
3
|
import { type FormEvent, useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { GitHubIcon, GoogleIcon, KeyholeMark } from '../../icons';
|
|
5
|
+
import { injectStyles } from '../../styles';
|
|
5
6
|
|
|
6
7
|
export interface SignUpProps {
|
|
7
8
|
social?: boolean;
|
|
@@ -15,9 +16,10 @@ export function SignUp({
|
|
|
15
16
|
onSuccess,
|
|
16
17
|
onSignInClick,
|
|
17
18
|
}: SignUpProps) {
|
|
19
|
+
injectStyles();
|
|
18
20
|
const { signUp, client } = useAuth() as unknown as {
|
|
19
21
|
signUp: ReturnType<typeof useAuth>['signUp'];
|
|
20
|
-
client: { publishableKey?: string };
|
|
22
|
+
client: { publishableKey?: string; apiUrl: string };
|
|
21
23
|
};
|
|
22
24
|
const [firstName, setFirstName] = useState('');
|
|
23
25
|
const [email, setEmail] = useState('');
|
|
@@ -52,7 +54,7 @@ export function SignUp({
|
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
function oauth(provider: 'google' | 'github') {
|
|
55
|
-
window.location.href =
|
|
57
|
+
window.location.href = `${client.apiUrl}/v1/oauth/${provider}`;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
const missingKey =
|
|
@@ -63,17 +65,7 @@ export function SignUp({
|
|
|
63
65
|
return (
|
|
64
66
|
<div ref={cardRef} className={`slx-card${error ? ' slx-card-error' : ''}`}>
|
|
65
67
|
{missingKey && (
|
|
66
|
-
<p
|
|
67
|
-
style={{
|
|
68
|
-
fontSize: 12,
|
|
69
|
-
background: '#fff3cd',
|
|
70
|
-
border: '1px solid #ffe69c',
|
|
71
|
-
borderRadius: 8,
|
|
72
|
-
padding: '8px 10px',
|
|
73
|
-
marginBottom: 14,
|
|
74
|
-
lineHeight: 1.4,
|
|
75
|
-
}}
|
|
76
|
-
>
|
|
68
|
+
<p className="slx-setup-note">
|
|
77
69
|
<strong>Setup:</strong> Add{' '}
|
|
78
70
|
<code>NEXT_PUBLIC_SLYXUP_PUBLISHABLE_KEY</code> — run{' '}
|
|
79
71
|
<code>npx @slyxup/cli keys create</code>
|