astryx-dracula 0.5.0 → 0.6.2
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/BRAND.md +3 -3
- package/README.md +7 -4
- package/USAGE.md +49 -49
- package/astryx-dracula.d.ts +2 -2
- package/astryx-dracula.js +25 -9
- package/astryx-dracula.variants.d.ts +2 -2
- package/astryx.integration.mjs +1 -1
- package/icons.mjs +21 -17
- package/icons.tsx +69 -62
- package/package.json +125 -120
- package/shared/auth-chrome-config.ts +6 -6
- package/shared/auth-chrome.tsx +143 -144
- package/shared/auth-copy.ts +14 -14
- package/shared/chaptered-doc-config.ts +48 -51
- package/shared/chaptered-doc.tsx +267 -289
- package/shared/chart-hues.ts +25 -10
- package/shared/chart-labels.tsx +31 -30
- package/shared/chart-legend.tsx +55 -56
- package/shared/chart-panel-style.ts +3 -3
- package/shared/data-bar.tsx +97 -102
- package/shared/format-money.ts +1 -1
- package/shared/gallery-image.ts +6 -6
- package/shared/login-demo.ts +1 -1
- package/shared/metric-card.tsx +101 -105
- package/shared/metric-delta.tsx +28 -27
- package/shared/order-desk.tsx +205 -216
- package/shared/revenue-chart.tsx +145 -165
- package/shared/scene-castle.tsx +206 -291
- package/shared/scene-frame.tsx +33 -32
- package/shared/scene-hues.ts +17 -17
- package/shared/scene-tile.tsx +88 -92
- package/shared/settings-data.ts +119 -125
- package/shared/settings-rows.tsx +122 -159
- package/shared/sparkline.tsx +75 -88
- package/shared/sso-icons.tsx +10 -22
- package/shared/stars.tsx +16 -25
- package/templates/ai-chat-landing.template.mjs +5 -4
- package/templates/ai-chat-landing.tsx +473 -460
- package/templates/ai-chat.template.mjs +5 -4
- package/templates/ai-chat.tsx +543 -612
- package/templates/blank.template.mjs +5 -4
- package/templates/blank.tsx +18 -14
- package/templates/centered-hero.template.mjs +5 -4
- package/templates/centered-hero.tsx +55 -68
- package/templates/classic-gallery.template.mjs +5 -4
- package/templates/classic-gallery.tsx +97 -104
- package/templates/contact-form.template.mjs +5 -4
- package/templates/contact-form.tsx +247 -282
- package/templates/dashboard-portfolio.template.mjs +5 -4
- package/templates/dashboard-portfolio.tsx +717 -548
- package/templates/dashboard.template.mjs +5 -4
- package/templates/dashboard.tsx +596 -567
- package/templates/detail-page.template.mjs +5 -4
- package/templates/detail-page.tsx +546 -603
- package/templates/documentation-design.template.mjs +5 -4
- package/templates/documentation-design.tsx +231 -243
- package/templates/documentation-technical.template.mjs +5 -4
- package/templates/documentation-technical.tsx +236 -239
- package/templates/documentation.template.mjs +5 -4
- package/templates/documentation.tsx +267 -279
- package/templates/editor.template.mjs +5 -4
- package/templates/editor.tsx +844 -877
- package/templates/file-explorer.template.mjs +5 -4
- package/templates/file-explorer.tsx +566 -590
- package/templates/form-two-column.template.mjs +5 -4
- package/templates/form-two-column.tsx +195 -210
- package/templates/gallery-hero.template.mjs +5 -4
- package/templates/gallery-hero.tsx +93 -114
- package/templates/ide.template.mjs +5 -4
- package/templates/ide.tsx +407 -453
- package/templates/incident-console.template.mjs +5 -4
- package/templates/incident-console.tsx +593 -575
- package/templates/kanban-board.template.mjs +5 -4
- package/templates/kanban-board.tsx +665 -683
- package/templates/library.template.mjs +5 -4
- package/templates/library.tsx +409 -430
- package/templates/login-card.template.mjs +5 -4
- package/templates/login-card.tsx +63 -72
- package/templates/login-split.template.mjs +5 -4
- package/templates/login-split.tsx +192 -193
- package/templates/login-sso.template.mjs +5 -4
- package/templates/login-sso.tsx +257 -258
- package/templates/login.template.mjs +5 -4
- package/templates/login.tsx +53 -49
- package/templates/messaging-shell.template.mjs +5 -4
- package/templates/messaging-shell.tsx +556 -574
- package/templates/mixed-gallery.template.mjs +5 -4
- package/templates/mixed-gallery.tsx +60 -58
- package/templates/payment-form.template.mjs +5 -4
- package/templates/payment-form.tsx +882 -991
- package/templates/product-detail.template.mjs +5 -4
- package/templates/product-detail.tsx +261 -272
- package/templates/product-gallery.template.mjs +5 -4
- package/templates/product-gallery.tsx +126 -137
- package/templates/product-tour.template.mjs +5 -4
- package/templates/product-tour.tsx +741 -773
- package/templates/settings-dialog.template.mjs +5 -4
- package/templates/settings-dialog.tsx +688 -717
- package/templates/settings-sidebar.template.mjs +5 -4
- package/templates/settings-sidebar.tsx +762 -807
- package/templates/settings.template.mjs +5 -4
- package/templates/settings.tsx +289 -304
- package/templates/shell-nav.template.mjs +5 -4
- package/templates/shell-nav.tsx +212 -219
- package/templates/shell-side-nav.template.mjs +5 -4
- package/templates/shell-side-nav.tsx +135 -157
- package/templates/shell-top-nav.template.mjs +5 -4
- package/templates/shell-top-nav.tsx +182 -203
- package/templates/side-gallery.template.mjs +5 -4
- package/templates/side-gallery.tsx +85 -90
- package/templates/table-grouped.template.mjs +5 -4
- package/templates/table-grouped.tsx +1000 -1053
- package/templates/table-page-chart.template.mjs +5 -4
- package/templates/table-page-chart.tsx +400 -398
- package/templates/table-page-heatmap-status.template.mjs +5 -4
- package/templates/table-page-heatmap-status.tsx +483 -512
- package/templates/table-page-shoe-store-heatmap.template.mjs +5 -4
- package/templates/table-page-shoe-store-heatmap.tsx +748 -746
- package/templates/table-page.template.mjs +5 -4
- package/templates/table-page.tsx +396 -405
- package/templates/table.template.mjs +5 -4
- package/templates/table.tsx +92 -93
- package/templates/tech-report.template.mjs +5 -4
- package/templates/tech-report.tsx +1316 -1304
- package/templates/theme-showcase.template.mjs +5 -4
- package/templates/theme-showcase.tsx +871 -951
- package/theme.css +35 -77
- package/theme.css.d.ts +9 -0
- package/tokens.css +373 -380
package/templates/login-sso.tsx
CHANGED
|
@@ -1,311 +1,310 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
// XLE (canonical structure
|
|
3
|
-
//
|
|
2
|
+
// XLE (canonical structure of the tree below; the CLI had no XLE validator
|
|
3
|
+
// after `astryx layout` was removed in 0.7.0, so this is a reading aid and a
|
|
4
|
+
// human drift check — update it with the file, never alone):
|
|
5
|
+
// Ctr > C[p=4 mw=400] > V[g=4] > ((V[g=1 a=center] > Hd"Welcome back to the night"[level=1 t=display-2] + Tx"Whisper your details to enter the night"[t=body]) + (V[g=1] > TI"Work email"[t=email] + Lk"Having trouble signing in?") + B.primary"Continue" + D"Or continue with" + B.secondary"Continue with SSO" + (V[a=center] > Tx"New to the castle?"[t=supporting] + Lk"Request access") + (V[g=2 a=center] > Av + Hd"Sign in with Google Workspace"[level=1 t=display-2] + Tx"You will be redirected back after signing in."[t=body]) + (C.muted[p=4] > (H[g=2 a=center] > Ic + (V[g=0] > Tx"Google Workspace"[t=label] + Tx"vlad@castle.ro"[t=supporting]))) + (V[g=3] > B.primary"Continue with Google Workspace" + B.ghost"Use a different email") + (V[g=1 a=center] > Hd"Welcome back to the night"[level=1 t=display-2] + Tx"vlad@castle.ro"[t=body]) + (V[g=4] > (V[g=1] > TI"Password"[t=password] + Lk"Forgot password?") + (V[g=3] > B.primary"Sign in" + B.ghost"Use a different email")) + (V[a=center] > Tx"By clicking continue, you agree to our Terms of service and Privacy policy"[t=supporting]))
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { Avatar } from "@astryxdesign/core/Avatar";
|
|
8
|
+
import { Button } from "@astryxdesign/core/Button";
|
|
9
|
+
import { Card } from "@astryxdesign/core/Card";
|
|
10
|
+
import { Center } from "@astryxdesign/core/Center";
|
|
11
|
+
import { Divider } from "@astryxdesign/core/Divider";
|
|
12
|
+
import { Icon } from "@astryxdesign/core/Icon";
|
|
13
|
+
import { HStack, VStack } from "@astryxdesign/core/Layout";
|
|
14
|
+
import { Link } from "@astryxdesign/core/Link";
|
|
15
|
+
import { Heading, Text } from "@astryxdesign/core/Text";
|
|
16
|
+
import { TextInput } from "@astryxdesign/core/TextInput";
|
|
11
17
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
import {Card} from '@astryxdesign/core/Card';
|
|
29
|
-
import {Link} from '@astryxdesign/core/Link';
|
|
30
|
-
import {Divider} from '@astryxdesign/core/Divider';
|
|
31
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
32
|
-
import {Avatar} from '@astryxdesign/core/Avatar';
|
|
33
|
-
|
|
18
|
+
inputAutoComplete,
|
|
19
|
+
authPageStyle as pageStyle,
|
|
20
|
+
} from "astryx-dracula/shared/auth-chrome-config";
|
|
21
|
+
import {
|
|
22
|
+
AUTH_EMAIL_PLACEHOLDER,
|
|
23
|
+
AUTH_ERROR_MESSAGE,
|
|
24
|
+
AUTH_FORGOT_PASSWORD,
|
|
25
|
+
AUTH_HEADING,
|
|
26
|
+
AUTH_PRIMARY_CTA,
|
|
27
|
+
AUTH_SIGNUP_PROMPT,
|
|
28
|
+
AUTH_SSO_DIVIDER,
|
|
29
|
+
AUTH_TERMS_PREFIX,
|
|
30
|
+
AUTH_TERMS_PRIVACY,
|
|
31
|
+
AUTH_TERMS_SERVICE,
|
|
32
|
+
} from "astryx-dracula/shared/auth-copy";
|
|
33
|
+
import { demoLogin } from "astryx-dracula/shared/login-demo";
|
|
34
34
|
// ============= ICONS (verified lucide-react exports) =============
|
|
35
35
|
// ShieldCheck ← ShieldCheckIcon.
|
|
36
|
-
import {ShieldCheck} from
|
|
36
|
+
import { ShieldCheck } from "lucide-react";
|
|
37
|
+
// Step-conditional h1: the email and SSO-confirm steps each render their own
|
|
38
|
+
// h1 (email entry vs provider confirm); the password fallback reuses the
|
|
39
|
+
// family heading, so exactly one h1 shows per step.
|
|
40
|
+
import { useState, useTransition } from "react";
|
|
37
41
|
|
|
38
42
|
type SSOProvider = {
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
name: string;
|
|
44
|
+
abbr: string;
|
|
41
45
|
};
|
|
42
46
|
const SSO_PROVIDERS: Record<string, SSOProvider> = {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
"google.com": { name: "Google Workspace", abbr: "G" },
|
|
48
|
+
"microsoft.com": { name: "Microsoft Entra ID", abbr: "M" },
|
|
49
|
+
"okta.com": { name: "Okta", abbr: "O" },
|
|
50
|
+
"meta.com": { name: "Meta SSO", abbr: "M" },
|
|
51
|
+
"apple.com": { name: "Apple Business", abbr: "A" },
|
|
48
52
|
};
|
|
49
53
|
|
|
50
54
|
function getProvider(email: string) {
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
const domain = email.split("@")[1]?.toLowerCase();
|
|
56
|
+
return domain ? (SSO_PROVIDERS[domain] ?? null) : null;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
function isValidEmail(email: string) {
|
|
56
|
-
|
|
60
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
// ---------------------------------------------------------------------------
|
|
60
64
|
// Component
|
|
61
65
|
// ---------------------------------------------------------------------------
|
|
62
66
|
|
|
63
|
-
type Step =
|
|
67
|
+
type Step = "email" | "sso-confirm" | "password-fallback";
|
|
64
68
|
|
|
65
69
|
export default function LoginSso() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
const [step, setStep] = useState<Step>("email");
|
|
71
|
+
const [email, setEmail] = useState("");
|
|
72
|
+
const [password, setPassword] = useState("");
|
|
73
|
+
const [error, setError] = useState<string | null>(null);
|
|
74
|
+
const [isLoading, startTransition] = useTransition();
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
const provider = getProvider(email);
|
|
77
|
+
const emailValid = isValidEmail(email);
|
|
74
78
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
const handleContinue = () => {
|
|
80
|
+
if (!emailValid) {
|
|
81
|
+
// The Continue buttons stay enabled and explain themselves. Disabling
|
|
82
|
+
// them greyed the buttons out with no stated reason, so a malformed
|
|
83
|
+
// address produced silence rather than guidance.
|
|
84
|
+
setError("Enter a valid email address to continue.");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setError(null);
|
|
88
|
+
if (provider) {
|
|
89
|
+
setStep("sso-confirm");
|
|
90
|
+
} else {
|
|
91
|
+
setStep("password-fallback");
|
|
92
|
+
}
|
|
93
|
+
};
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
const handleBack = () => {
|
|
96
|
+
setStep("email");
|
|
97
|
+
setError(null);
|
|
98
|
+
};
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
const handleSignIn = () => {
|
|
101
|
+
if (!password) {
|
|
102
|
+
setError(AUTH_ERROR_MESSAGE);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
setError(null);
|
|
106
|
+
startTransition(async () => {
|
|
107
|
+
await demoLogin();
|
|
108
|
+
setError(AUTH_ERROR_MESSAGE);
|
|
109
|
+
});
|
|
110
|
+
};
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
return (
|
|
113
|
+
<Center axis="both" style={pageStyle}>
|
|
114
|
+
<Card padding={4} width="100%" maxWidth={400}>
|
|
115
|
+
<VStack gap={4} hAlign="stretch">
|
|
116
|
+
{/* ── Step 1: Email entry, route by domain ──
|
|
113
117
|
The password is collected on the fallback step below, never
|
|
114
118
|
here: a recognised domain goes straight to SSO. */}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
{step === "email" && (
|
|
120
|
+
<>
|
|
121
|
+
<VStack gap={1} hAlign="center">
|
|
122
|
+
<Heading level={1} type="display-2">
|
|
123
|
+
{AUTH_HEADING}
|
|
124
|
+
</Heading>
|
|
125
|
+
<Text type="body" color="secondary">
|
|
126
|
+
Whisper your details to enter the night
|
|
127
|
+
</Text>
|
|
128
|
+
</VStack>
|
|
125
129
|
|
|
126
|
-
|
|
130
|
+
{/* The helper link belongs to the field above it, so the two
|
|
127
131
|
share a gap={1} group — as the password step below groups
|
|
128
132
|
its own. As siblings in the outer gap={4} flow it read as
|
|
129
133
|
one more control in the button column, 16px from each. */}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
134
|
+
<VStack gap={1}>
|
|
135
|
+
<TextInput
|
|
136
|
+
label="Work email"
|
|
137
|
+
isLabelHidden
|
|
138
|
+
type="email"
|
|
139
|
+
{...inputAutoComplete("email")}
|
|
140
|
+
placeholder={AUTH_EMAIL_PLACEHOLDER}
|
|
141
|
+
value={email}
|
|
142
|
+
onChange={(v: string) => {
|
|
143
|
+
setEmail(v);
|
|
144
|
+
setError(null);
|
|
145
|
+
}}
|
|
146
|
+
size="lg"
|
|
147
|
+
onKeyDown={(e: React.KeyboardEvent) => {
|
|
148
|
+
if (e.key === "Enter") {
|
|
149
|
+
handleContinue();
|
|
150
|
+
}
|
|
151
|
+
}}
|
|
152
|
+
status={error ? { type: "error", message: error } : undefined}
|
|
153
|
+
/>
|
|
150
154
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
<Link href="#/templates/login-sso" isStandalone>
|
|
156
|
+
Having trouble signing in?
|
|
157
|
+
</Link>
|
|
158
|
+
</VStack>
|
|
155
159
|
|
|
156
|
-
|
|
157
|
-
label="Continue"
|
|
158
|
-
variant="primary"
|
|
159
|
-
size="lg"
|
|
160
|
-
onClick={handleContinue}
|
|
161
|
-
/>
|
|
160
|
+
<Button label="Continue" variant="primary" size="lg" onClick={handleContinue} />
|
|
162
161
|
|
|
163
|
-
|
|
162
|
+
<Divider label={AUTH_SSO_DIVIDER} />
|
|
164
163
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
<Button
|
|
165
|
+
label="Continue with SSO"
|
|
166
|
+
variant="secondary"
|
|
167
|
+
size="lg"
|
|
168
|
+
onClick={handleContinue}
|
|
169
|
+
/>
|
|
171
170
|
|
|
172
|
-
|
|
171
|
+
{/* Prose link: colour alone is not a cue inside a sentence
|
|
173
172
|
(WCAG 1.4.1 / F73), so it asks for the underline the kit
|
|
174
173
|
only gives on hover. */}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
174
|
+
<VStack hAlign="center">
|
|
175
|
+
<Text type="supporting" color="secondary">
|
|
176
|
+
{AUTH_SIGNUP_PROMPT}{" "}
|
|
177
|
+
<Link href="#/templates/login-sso" type="supporting" hasUnderline>
|
|
178
|
+
Request access
|
|
179
|
+
</Link>
|
|
180
|
+
</Text>
|
|
181
|
+
</VStack>
|
|
182
|
+
</>
|
|
183
|
+
)}
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
185
|
+
{/* ── Step 2a: SSO provider detected ── */}
|
|
186
|
+
{step === "sso-confirm" && provider && (
|
|
187
|
+
<>
|
|
188
|
+
<VStack gap={2} hAlign="center">
|
|
189
|
+
<Avatar name={provider.name} size={48} />
|
|
190
|
+
<Heading level={1} type="display-2">
|
|
191
|
+
Sign in with {provider.name}
|
|
192
|
+
</Heading>
|
|
193
|
+
<Text type="body" color="secondary">
|
|
194
|
+
You will be redirected back after signing in.
|
|
195
|
+
</Text>
|
|
196
|
+
</VStack>
|
|
198
197
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
198
|
+
<Card padding={4} variant="muted">
|
|
199
|
+
<HStack gap={2} vAlign="center">
|
|
200
|
+
<Icon icon={ShieldCheck} color="secondary" />
|
|
201
|
+
<VStack gap={0}>
|
|
202
|
+
<Text type="label">{provider.name}</Text>
|
|
203
|
+
<Text type="supporting" color="secondary">
|
|
204
|
+
{email}
|
|
205
|
+
</Text>
|
|
206
|
+
</VStack>
|
|
207
|
+
</HStack>
|
|
208
|
+
</Card>
|
|
210
209
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
210
|
+
<VStack gap={3}>
|
|
211
|
+
<Button
|
|
212
|
+
label={`Continue with ${provider.name}`}
|
|
213
|
+
variant="primary"
|
|
214
|
+
size="lg"
|
|
215
|
+
isLoading={isLoading}
|
|
216
|
+
onClick={() => {
|
|
217
|
+
startTransition(async () => {
|
|
218
|
+
await demoLogin();
|
|
219
|
+
});
|
|
220
|
+
}}
|
|
221
|
+
/>
|
|
222
|
+
<Button
|
|
223
|
+
label="Use a different email"
|
|
224
|
+
variant="ghost"
|
|
225
|
+
size="lg"
|
|
226
|
+
onClick={handleBack}
|
|
227
|
+
/>
|
|
228
|
+
</VStack>
|
|
229
|
+
</>
|
|
230
|
+
)}
|
|
232
231
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
232
|
+
{/* ── Step 2b: No SSO — password fallback ── */}
|
|
233
|
+
{step === "password-fallback" && (
|
|
234
|
+
<>
|
|
235
|
+
<VStack gap={1} hAlign="center">
|
|
236
|
+
<Heading level={1} type="display-2">
|
|
237
|
+
{AUTH_HEADING}
|
|
238
|
+
</Heading>
|
|
239
|
+
<Text type="body" color="secondary">
|
|
240
|
+
{email}
|
|
241
|
+
</Text>
|
|
242
|
+
</VStack>
|
|
244
243
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
244
|
+
<VStack gap={4}>
|
|
245
|
+
<VStack gap={1}>
|
|
246
|
+
<TextInput
|
|
247
|
+
label="Password"
|
|
248
|
+
type="password"
|
|
249
|
+
{...inputAutoComplete("current-password")}
|
|
250
|
+
value={password}
|
|
251
|
+
size="lg"
|
|
252
|
+
onChange={(v: string) => {
|
|
253
|
+
setPassword(v);
|
|
254
|
+
setError(null);
|
|
255
|
+
}}
|
|
256
|
+
onEnter={handleSignIn}
|
|
257
|
+
status={error ? { type: "error", message: error } : undefined}
|
|
258
|
+
/>
|
|
259
|
+
{error && (
|
|
260
|
+
<VStack hAlign="end">
|
|
261
|
+
<Link href="#/templates/login-sso" isStandalone>
|
|
262
|
+
{AUTH_FORGOT_PASSWORD}
|
|
263
|
+
</Link>
|
|
264
|
+
</VStack>
|
|
265
|
+
)}
|
|
266
|
+
</VStack>
|
|
268
267
|
|
|
269
|
-
|
|
268
|
+
{/* gap={3} is the family rhythm for a button pair: the
|
|
270
269
|
primary/ghost pair in the confirm step above, the social
|
|
271
270
|
pairs in login-card and login-split. At the outer gap={4}
|
|
272
271
|
the same two buttons sat 4px further apart in this step
|
|
273
272
|
than in the step above it. */}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
273
|
+
<VStack gap={3}>
|
|
274
|
+
<Button
|
|
275
|
+
label={AUTH_PRIMARY_CTA}
|
|
276
|
+
variant="primary"
|
|
277
|
+
size="lg"
|
|
278
|
+
isLoading={isLoading}
|
|
279
|
+
onClick={handleSignIn}
|
|
280
|
+
/>
|
|
281
|
+
<Button
|
|
282
|
+
label="Use a different email"
|
|
283
|
+
variant="ghost"
|
|
284
|
+
size="lg"
|
|
285
|
+
onClick={handleBack}
|
|
286
|
+
/>
|
|
287
|
+
</VStack>
|
|
288
|
+
</VStack>
|
|
289
|
+
</>
|
|
290
|
+
)}
|
|
292
291
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
292
|
+
{/* Terms — family line, shown on every step */}
|
|
293
|
+
<VStack hAlign="center" width="100%">
|
|
294
|
+
<Text type="supporting" color="secondary" justify="center">
|
|
295
|
+
{AUTH_TERMS_PREFIX}{" "}
|
|
296
|
+
<Link href="#/templates/login-sso" type="supporting" hasUnderline>
|
|
297
|
+
{AUTH_TERMS_SERVICE}
|
|
298
|
+
</Link>{" "}
|
|
299
|
+
and{" "}
|
|
300
|
+
<Link href="#/templates/login-sso" type="supporting" hasUnderline>
|
|
301
|
+
{AUTH_TERMS_PRIVACY}
|
|
302
|
+
</Link>
|
|
303
|
+
.
|
|
304
|
+
</Text>
|
|
305
|
+
</VStack>
|
|
306
|
+
</VStack>
|
|
307
|
+
</Card>
|
|
308
|
+
</Center>
|
|
309
|
+
);
|
|
311
310
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
type: "page",
|
|
3
|
+
name: "Basic Login",
|
|
4
|
+
description: "Auth form with email and password inputs",
|
|
5
|
+
keywords: ["login", "sign in", "auth", "credentials", "account", "form"],
|
|
6
|
+
category: "auth",
|
|
6
7
|
};
|