ed2c386603
账号设置弹窗复用认证壳层并保留 direct mode 唯一 dialog 语义 拼图运行态新增本地弹窗壳层收口确认设置退出失败和通关结算 抓大鹅与跳一跳结算弹窗提取本地结算结构并补测试 拼图 onboarding 登录保存覆盖层迁入 UnifiedModal 更新 PlatformUiKit 收口文档和 Hermes 决策记录
180 lines
5.7 KiB
TypeScript
180 lines
5.7 KiB
TypeScript
import { Loader2, Sparkles } from 'lucide-react';
|
|
|
|
import { PlatformActionButton } from '../../common/PlatformActionButton';
|
|
import { PlatformStatusMessage } from '../../common/PlatformStatusMessage';
|
|
import { PlatformTextField } from '../../common/PlatformTextField';
|
|
import { UnifiedModal } from '../../common/UnifiedModal';
|
|
|
|
export type PuzzleOnboardingPhase = 'input' | 'generating' | 'generated';
|
|
|
|
type PuzzleOnboardingViewProps = {
|
|
prompt: string;
|
|
phase: PuzzleOnboardingPhase;
|
|
error: string | null;
|
|
copy: string;
|
|
onPromptChange: (value: string) => void;
|
|
onSubmit: () => void;
|
|
onSkip: () => void;
|
|
};
|
|
|
|
export function PuzzleOnboardingView({
|
|
prompt,
|
|
phase,
|
|
error,
|
|
copy,
|
|
onPromptChange,
|
|
onSubmit,
|
|
onSkip,
|
|
}: PuzzleOnboardingViewProps) {
|
|
const isGenerating = phase === 'generating';
|
|
const isGenerated = phase === 'generated';
|
|
const canSubmit = Boolean(prompt.trim()) && !isGenerating && !isGenerated;
|
|
|
|
return (
|
|
<div className="relative flex min-h-screen items-center justify-center overflow-hidden bg-[radial-gradient(circle_at_30%_15%,rgba(251,191,36,0.22),transparent_30%),linear-gradient(135deg,#0f172a,#111827_46%,#1e1b4b)] px-4 py-8 text-white">
|
|
<div className="absolute inset-0 bg-[linear-gradient(rgba(255,255,255,0.045)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.04)_1px,transparent_1px)] bg-[length:38px_38px] opacity-30" />
|
|
<PlatformActionButton
|
|
type="button"
|
|
surface="editorDark"
|
|
tone="ghost"
|
|
size="sm"
|
|
shape="pill"
|
|
disabled={isGenerating}
|
|
onClick={onSkip}
|
|
className="absolute right-4 top-4 z-10 min-h-10 shadow-[0_12px_28px_rgba(0,0,0,0.22)] backdrop-blur sm:right-6 sm:top-6"
|
|
>
|
|
跳过
|
|
</PlatformActionButton>
|
|
<section className="relative flex w-full max-w-[34rem] flex-col items-center gap-5 text-center">
|
|
<div className="grid h-14 w-14 place-items-center rounded-[1.2rem] border border-amber-200/32 bg-amber-200/14 text-amber-100 shadow-[0_18px_48px_rgba(251,191,36,0.18)]">
|
|
{isGenerating ? (
|
|
<Loader2 className="h-6 w-6 animate-spin" />
|
|
) : (
|
|
<Sparkles className="h-6 w-6" />
|
|
)}
|
|
</div>
|
|
<h1 className="text-[2rem] font-black leading-tight sm:text-[2.85rem]">
|
|
{copy}
|
|
</h1>
|
|
<form
|
|
className="flex w-full flex-col gap-3"
|
|
onSubmit={(event) => {
|
|
event.preventDefault();
|
|
onSubmit();
|
|
}}
|
|
>
|
|
<PlatformTextField
|
|
variant="textarea"
|
|
surface="editorDark"
|
|
tone="warm"
|
|
density="roomy"
|
|
size="lg"
|
|
value={prompt}
|
|
disabled={isGenerating || isGenerated}
|
|
onChange={(event) => onPromptChange(event.target.value)}
|
|
placeholder="把你的梦讲给我听吧"
|
|
rows={4}
|
|
className="min-h-32 rounded-[1.25rem] border-white/14 bg-black/28 py-4 leading-7 shadow-[0_18px_50px_rgba(0,0,0,0.24)] backdrop-blur placeholder:text-white/42 focus:border-amber-200/70 focus:ring-2 focus:ring-amber-200/20 disabled:opacity-70"
|
|
/>
|
|
<PlatformActionButton
|
|
type="submit"
|
|
surface="editorDark"
|
|
tone="accent"
|
|
size="lg"
|
|
fullWidth
|
|
disabled={!canSubmit}
|
|
>
|
|
{isGenerating ? (
|
|
<>
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
生成
|
|
</>
|
|
) : (
|
|
'生成'
|
|
)}
|
|
</PlatformActionButton>
|
|
</form>
|
|
{error ? (
|
|
<PlatformStatusMessage
|
|
tone="error"
|
|
surface="editorDark"
|
|
size="md"
|
|
className="w-full font-semibold"
|
|
>
|
|
{error}
|
|
</PlatformStatusMessage>
|
|
) : null}
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
type PuzzleOnboardingLoginOverlayProps = {
|
|
isSaving: boolean;
|
|
error: string | null;
|
|
copy: string;
|
|
onLogin: () => void;
|
|
};
|
|
|
|
export function PuzzleOnboardingLoginOverlay({
|
|
isSaving,
|
|
error,
|
|
copy,
|
|
onLogin,
|
|
}: PuzzleOnboardingLoginOverlayProps) {
|
|
return (
|
|
<UnifiedModal
|
|
open
|
|
title={copy}
|
|
onClose={() => undefined}
|
|
portal={false}
|
|
showHeader={false}
|
|
showCloseButton={false}
|
|
closeOnBackdrop={false}
|
|
closeOnEscape={false}
|
|
size="sm"
|
|
zIndexClassName="z-[110]"
|
|
overlayClassName="!items-center bg-slate-950/72 !px-4 !py-6 text-white backdrop-blur-md"
|
|
panelClassName="!max-w-[24rem] !rounded-[1.35rem] border border-white/14 bg-slate-950/94 text-white shadow-[0_28px_90px_rgba(0,0,0,0.5)]"
|
|
bodyClassName="flex flex-col items-center gap-5 !px-5 !py-6 text-center"
|
|
>
|
|
<div className="grid h-12 w-12 place-items-center rounded-[1rem] bg-amber-200 text-slate-950">
|
|
{isSaving ? (
|
|
<Loader2 className="h-5 w-5 animate-spin" />
|
|
) : (
|
|
<Sparkles className="h-5 w-5" />
|
|
)}
|
|
</div>
|
|
<h2 className="text-2xl font-black leading-tight">{copy}</h2>
|
|
<PlatformActionButton
|
|
type="button"
|
|
surface="editorDark"
|
|
tone="accent"
|
|
size="lg"
|
|
fullWidth
|
|
disabled={isSaving}
|
|
onClick={onLogin}
|
|
>
|
|
{isSaving ? (
|
|
<>
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
注册账号 / 登录
|
|
</>
|
|
) : (
|
|
'注册账号 / 登录'
|
|
)}
|
|
</PlatformActionButton>
|
|
{error ? (
|
|
<PlatformStatusMessage
|
|
tone="error"
|
|
surface="editorDark"
|
|
size="md"
|
|
className="w-full font-semibold"
|
|
>
|
|
{error}
|
|
</PlatformStatusMessage>
|
|
) : null}
|
|
</UnifiedModal>
|
|
);
|
|
}
|