1import { createSignal, Show, Switch, Match } from "solid-js";2import { sendMessage } from "../App";3import { RuneCanvas } from "../components/RuneCanvas";45interface PanicProps {6 onCancel: () => void;7 onOpenExport: () => void;8 onDestroyed: () => void | Promise<void>;9}101112const PANIC_RUNES = Array.from({ length: 80 }, (_, i) =>13 String.fromCodePoint(0xe000 + (i * 19 + 7) % 256)14).join("");1516function OverlayHeader(props: { title: string; onBack: () => void }) {17 return (18 <div class="peach-overlay-header">19 <button20 class="peach-btn peach-btn--ghost peach-btn--sm peach-icon-btn"21 onClick={props.onBack}22 aria-label="Back"23 >24 <svg width="7" height="12" viewBox="0 0 7 12" fill="none" stroke="currentColor" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round">25 <path d="M6 1L1 6L6 11" />26 </svg>27 </button>28 <span class="peach-overlay-title">{props.title}</span>29 <div class="peach-overlay-spacer"></div>30 </div>31 );32}3334export function PanicView(props: PanicProps) {35 const [step, setStep] = createSignal<1 | 2 | 3>(1);36 const [confirmText, setConfirmText] = createSignal("");37 const [destroying, setDestroying] = createSignal(false);3839 const canDestroy = () => confirmText() === "DESTROY";4041 async function handleDestroy() {42 if (destroying()) return;43 setDestroying(true);44 const res = await sendMessage({ type: "DESTROY_VAULT" });45 if (!res?.ok) {46 setDestroying(false);47 return;48 }49 await props.onDestroyed();50 }5152 return (53 <div class="peach-overlay-view ov-enter-right" style="display:flex;flex-direction:column">54 <Switch>55 <Match when={step() === 1}>56 <OverlayHeader title="danger zone" onBack={props.onCancel} />57 <div class="peach-panic">58 <h2 class="peach-panic-title">Before you destroy your vault</h2>59 <p class="peach-panic-body">60 Once destroyed, your vault cannot be recovered. Ever. There is no61 undo, no support ticket, no way back.62 </p>63 <p class="peach-panic-body">64 If you haven't already, export your vault now. It takes ten65 seconds and you'll be glad you did.66 </p>67 <button68 class="peach-panic-button peach-panic-button--primary"69 onClick={() => props.onOpenExport()}70 >71 Export my vault first72 </button>73 <div class="peach-panic-divider"></div>74 <p class="peach-panic-body">75 I have already exported my vault or I don't want to.76 </p>77 <button class="peach-panic-link" onClick={() => setStep(2)}>78 Continue to destruction →79 </button>80 </div>81 </Match>8283 <Match when={step() === 2}>84 <div class="peach-panic peach-panic-step2">85 <span class="peach-panic-icon" aria-hidden="true">⚠</span>86 <h2 class="peach-panic-title peach-panic-title--severe">87 This will permanently destroy your vault.88 </h2>89 <p class="peach-panic-body peach-panic-body--severe">90 Every password, card, passkey, note, and setting will be wiped91 from this device. This cannot be undone.92 </p>93 <p class="peach-panic-confirm-label">Type DESTROY to confirm:</p>94 <input95 class="peach-panic-confirm-input"96 classList={{ "peach-panic-confirm-input--match": canDestroy() }}97 type="text"98 value={confirmText()}99 onInput={(e) => setConfirmText(e.currentTarget.value)}100 autocomplete="off"101 spellcheck={false}102 autocapitalize="off"103 aria-label="Type DESTROY to confirm"104 />105 <div class="peach-panic-actions">106 <button107 class="peach-panic-button peach-panic-button--danger"108 disabled={!canDestroy()}109 onClick={() => setStep(3)}110 >111 Yes, destroy my vault112 </button>113 <button114 class="peach-panic-button peach-panic-button--ghost"115 onClick={() => {116 setConfirmText("");117 props.onCancel();118 }}119 >120 Cancel — keep my vault121 </button>122 </div>123 </div>124 </Match>125126 <Match when={step() === 3}>127 <div class="peach-panic peach-panic-step3">128 <div class="peach-panic-rune-bg" aria-hidden="true">129 <RuneCanvas runeString={PANIC_RUNES} width={320} height={480} />130 </div>131 <div class="peach-panic-bar">THIS IS YOUR LAST CHANCE</div>132 <p class="peach-panic-body peach-panic-body--final-intro">133 Your vault is about to be permanently destroyed.134 </p>135 <p class="peach-panic-body peach-panic-body--final">136 There is no recovery.137 <br />138 There is no support.139 <br />140 There is no undo.141 </p>142 <div class="peach-panic-divider"></div>143 <div class="peach-panic-actions">144 <button145 class="peach-panic-final-button"146 disabled={destroying()}147 onClick={() => void handleDestroy()}148 >149 {destroying() ? "Destroying…" : "Destroy my vault forever"}150 </button>151 <Show when={!destroying()}>152 <button153 class="peach-panic-button peach-panic-button--ghost"154 onClick={() => {155 setConfirmText("");156 setStep(1);157 }}158 >159 No — take me back160 </button>161 </Show>162 </div>163 </div>164 </Match>165 </Switch>166 </div>167 );168}