chore(core/frontend): remove dead codex-era exact-* code (§6)
Removed unused codex/iframe-era modules (confirmed no live imports; public/exact/*.html design baselines kept): - routes/exact-document.tsx, routes/exact-html.ts (~1.6MB generated), routes/exact-dashboard.tsx, routes/exact-pages/ (24 files) - exact-pages.css + its main.tsx import; index.ts ExactDashboardApp re-export App.tsx uses the real Dashboard; nothing referenced the removed cluster. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
099bf0e6aa
commit
579fb7cefa
@ -1,33 +0,0 @@
|
||||
/* Exact page-level CSS copied from 电商AI平台/index.html. */
|
||||
.exact-document-route {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
background: var(--background-base);
|
||||
}
|
||||
.exact-document-frame {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
border: 0;
|
||||
background: var(--background-base);
|
||||
}
|
||||
.app .brand { gap: 0; padding: 0; }
|
||||
.app .search-box .kbd { background: transparent; border: 0; border-radius: 0; padding: 0; }
|
||||
.dash-grid { display: grid; grid-template-columns: 1.7fr 1fr; gap: 24px; align-items: start; }
|
||||
.recent-row { display: grid; grid-template-columns: 54px 1fr 110px 130px 60px; align-items: center; gap: 16px; padding: 14px 18px; border-bottom: 1px solid var(--border-faint); cursor: pointer; width: auto; text-align: inherit; background: transparent; }
|
||||
.recent-row .prog, .recent-row .pill, .recent-row .btn { justify-self: start; }
|
||||
.recent-row:last-child { border-bottom: 0; }
|
||||
.recent-row:hover { background: var(--background-lighter); }
|
||||
.recent-row .thumb { width: 54px; height: 70px; border-radius: var(--r-md); }
|
||||
.recent-meta .name { font-weight: 600; font-size: 13.5px; color: var(--accent-black); }
|
||||
.recent-meta .sub { font-size: 12px; color: var(--black-alpha-48); margin-top: 3px; font-family: var(--font-mono); letter-spacing: .01em; }
|
||||
.shortcuts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
||||
.shortcut { background: var(--surface); border: 1px solid var(--border-faint); border-radius: var(--r-md); padding: 16px; display: flex; align-items: flex-start; gap: 12px; cursor: pointer; transition: background var(--t-base); }
|
||||
.shortcut:hover { background: var(--black-alpha-4); }
|
||||
.shortcut .ic { width: 32px; height: 32px; background: var(--heat-12); color: var(--heat); display: grid; place-items: center; border: 0; border-radius: var(--r-md); flex-shrink: 0; }
|
||||
.shortcut .ic svg { width: 16px; height: 16px; }
|
||||
.shortcut .t { font-size: 13px; font-weight: 600; }
|
||||
.shortcut .d { font-size: 11.5px; color: var(--black-alpha-48); margin-top: 3px; font-family: var(--font-mono); letter-spacing: .01em; }
|
||||
.tip { background: var(--surface); border: 1px dashed var(--border-faint); padding: 14px 16px; font-size: 12.5px; color: var(--black-alpha-56); line-height: 1.6; border-radius: var(--r-md); }
|
||||
.tip strong { color: var(--accent-black); font-weight: 600; display: block; margin-bottom: 4px; }
|
||||
.tip .mono { font-family: var(--font-mono); color: var(--heat); background: var(--heat-12); padding: 1px 5px; border-radius: var(--r-sm); font-size: 11.5px; }
|
||||
@ -2,7 +2,6 @@ import { createRoot } from "react-dom/client";
|
||||
import { App } from "./App";
|
||||
import "./styles.css";
|
||||
import "./design-restraint.css";
|
||||
import "./exact-pages.css";
|
||||
import "./account-page.css";
|
||||
import "./product-detail-page.css";
|
||||
import "./team-page.css";
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
import { IconKitSvg } from "../components/IconKitSvg";
|
||||
import { CornerMark } from "../components/app-shell";
|
||||
import type { NavigateFn, Page } from "./route-config";
|
||||
|
||||
export function ExactDashboardApp({ navigate, logout }: { navigate: NavigateFn; logout: () => void }) {
|
||||
const go = (next: Page) => (event: { preventDefault: () => void }) => {
|
||||
event.preventDefault();
|
||||
navigate(next);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
<aside className="sidebar">
|
||||
<div className="sidebar-head"><a className="brand" href="/dashboard" onClick={go("dashboard")}><span className="brand-clip"><img className="brand-logo" src="/assets/logo.png" alt="Airshelf" /></span></a></div>
|
||||
<div className="search-box"><IconKitSvg name="search" /><input placeholder="搜索" readOnly /><span className="kbd">Ctrl K</span></div>
|
||||
<div className="nav-section">主要</div>
|
||||
<nav>
|
||||
<a href="/dashboard" className="active" onClick={go("dashboard")}><IconKitSvg name="dashboard" /><span>工作台</span></a>
|
||||
<a href="/products" onClick={go("products")}><IconKitSvg name="package" /><span>商品库</span><span className="pill-mini">7</span></a>
|
||||
<a href="/projects" onClick={go("projects")}><IconKitSvg name="clapperboard" /><span>视频项目</span><span className="pill-mini">8</span></a>
|
||||
<a href="/asset-factory" onClick={go("assetFactory")}><IconKitSvg name="sparkles" /><span>图片生成</span></a>
|
||||
<a href="/library" onClick={go("library")}><IconKitSvg name="library" /><span>资产库</span></a>
|
||||
<a href="/team" onClick={go("team")}><IconKitSvg name="users" /><span>团队</span></a>
|
||||
<a href="/account" onClick={go("account")}><IconKitSvg name="creditCard" /><span>消费</span></a>
|
||||
<a href="/settings" onClick={go("settings")}><IconKitSvg name="settings" /><span>设置</span></a>
|
||||
</nav>
|
||||
<div className="aside-foot"><div className="user"><div className="av">李</div><div className="em">小李的店</div></div></div>
|
||||
</aside>
|
||||
<main>
|
||||
<div className="grid-bg"></div>
|
||||
<header className="topbar">
|
||||
<div className="crumbs"><span className="here">工作台</span></div>
|
||||
<div className="right">
|
||||
<button className="balance-chip" type="button" onClick={() => navigate("account")}><IconKitSvg name="creditCard" />余额 <strong>¥327.40</strong></button>
|
||||
<button className="icon-btn" type="button" onClick={() => navigate("messages")}><IconKitSvg name="bell" /><span className="count-noti">12</span></button>
|
||||
<button className="topbar-avatar" type="button" onDoubleClick={logout}><span>李</span></button>
|
||||
</div>
|
||||
</header>
|
||||
<div className="content" id="page-content">
|
||||
<CornerMark pos="tl" /><CornerMark pos="tr" /><CornerMark pos="bl" /><CornerMark pos="br" />
|
||||
<div className="page-head">
|
||||
<div><h1>欢迎回来,小李</h1><div className="sub"><span className="mono">// 05.14 · 周三</span><span>·</span><span>你有 <b>3 个项目</b> 正在进行中</span></div></div>
|
||||
<div className="actions"><a className="btn btn-create" href="/products/new" onClick={go("productCreateUpload")}><IconKitSvg name="productPlus" />新建商品</a><a className="btn btn-primary btn-lg btn-create" href="/projects/new" onClick={go("projectWizard")}><IconKitSvg name="clapperboard" />新建项目</a></div>
|
||||
</div>
|
||||
<div className="stats with-corners">
|
||||
<span className="corner-tr" /><span className="corner-bl" />
|
||||
<a className="stat" href="/projects" onClick={go("projects")}><div className="lbl">总项目 <span className="badge">ALL</span></div><div className="v">8</div><div className="delta up"><IconKitSvg name="arrowUp" size={14} /> 本月 +3</div></a>
|
||||
<a className="stat" href="/projects" onClick={go("projects")}><div className="lbl">进行中 <span className="badge">WIP</span></div><div className="v">3</div><div className="delta">2 个待审核</div></a>
|
||||
<a className="stat" href="/projects" onClick={go("projects")}><div className="lbl">本月成片 <span className="badge">DONE</span></div><div className="v">3</div><div className="delta up">较上月 +33%</div></a>
|
||||
<a className="stat" href="/account" onClick={go("account")}><div className="lbl">余额 <span className="badge">¥</span></div><div className="v">¥327<small>.40</small></div><div className="bar"><span style={{ width: "33%" }} /></div><div className="sub">已用 ¥162.60 / ¥500</div></a>
|
||||
</div>
|
||||
<div className="dash-grid">
|
||||
<div><div className="section-h"><h2>最近项目</h2><a className="more" href="/projects" onClick={go("projects")}>[ ALL · 8 ]</a></div><div className="card-hard">{["补水面膜 · 痛点种草 · v3", "透真防晒 · 通勤对比", "蓝牙耳机 · 开箱测评", "春日新品 · 立体口红"].map((title) => <ExactRecentRow key={title} title={title} go={go("pipeline")} />)}</div></div>
|
||||
<div className="dash-side"><div className="section-h"><h2>快捷入口</h2><span className="more">[ /shortcuts ]</span></div><div className="shortcuts">{[["商品库", "products"], ["资产库", "library"], ["充值", "account"], ["所有项目", "projects"]].map(([label, target]) => <a className="shortcut" href={`/${target}`} onClick={go(target as Page)} key={label}><div className="ic"><IconKitSvg name="package" /></div><div><div className="t">{label}</div><div className="d">快速进入</div></div></a>)}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function ExactRecentRow({ title, go }: { title: string; go: (event: { preventDefault: () => void }) => void }) {
|
||||
return (
|
||||
<a className="recent-row" href="/pipeline" onClick={go}>
|
||||
<div className="placeholder thumb"><span className="ph-frame">9:16</span></div>
|
||||
<div className="recent-meta"><div className="name">{title}</div><div className="sub">AI 全生 / 4 段</div></div>
|
||||
<div className="prog"><span className="done" /><span className="done" /><span className="cur" /><span /><span /></div>
|
||||
<span className="pill info"><span className="dot" />进行中</span>
|
||||
<span className="btn btn-sm">继续</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@ -1,349 +0,0 @@
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import type { FormEvent } from "react";
|
||||
import { exactHtmlDocuments } from "./exact-html";
|
||||
import type { ExactHtmlKey } from "./exact-html";
|
||||
import type { AuthMode, NavigateFn, Page } from "./route-config";
|
||||
|
||||
const fileToPage: Record<string, Page | "login" | "register" | null> = {
|
||||
"account.html": "account",
|
||||
"asset-factory.html": "assetFactory",
|
||||
"image-optimize.html": "imageOptimize",
|
||||
"index.html": "dashboard",
|
||||
"library.html": "library",
|
||||
"login.html": "login",
|
||||
"messages.html": "messages",
|
||||
"model-photo.html": "modelPhoto",
|
||||
"model-photo-demo-a.html": "modelPhotoDemoA",
|
||||
"model-photo-demo-b.html": "modelPhotoDemoB",
|
||||
"pipeline.html": "pipeline",
|
||||
"platform-cover.html": "platformCover",
|
||||
"product-create.html": "productCreateUpload",
|
||||
"product-create-upload.html": "productCreateUpload",
|
||||
"product-detail.html": "productDetail",
|
||||
"products.html": "products",
|
||||
"projects-new.html": "projectWizard",
|
||||
"projects.html": "projects",
|
||||
"register.html": "register",
|
||||
"settings.html": "settings",
|
||||
"team.html": "team"
|
||||
};
|
||||
|
||||
const pageToExactKey: Record<Page, ExactHtmlKey> = {
|
||||
dashboard: "dashboard",
|
||||
products: "products",
|
||||
productDetail: "productDetail",
|
||||
productCreateUpload: "productCreateUpload",
|
||||
projects: "projects",
|
||||
projectWizard: "projectWizard",
|
||||
pipeline: "pipeline",
|
||||
library: "library",
|
||||
account: "account",
|
||||
team: "team",
|
||||
messages: "messages",
|
||||
assetFactory: "assetFactory",
|
||||
imageOptimize: "imageOptimize",
|
||||
modelPhoto: "modelPhoto",
|
||||
modelPhotoDemoA: "modelPhotoDemoA",
|
||||
modelPhotoDemoB: "modelPhotoDemoB",
|
||||
platformCover: "platformCover",
|
||||
settings: "settings",
|
||||
settingsNotify: "settings"
|
||||
};
|
||||
|
||||
const exactKeyToPage: Partial<Record<ExactHtmlKey, Page | "login" | "register">> = {
|
||||
account: "account",
|
||||
assetFactory: "assetFactory",
|
||||
dashboard: "dashboard",
|
||||
imageOptimize: "imageOptimize",
|
||||
library: "library",
|
||||
login: "login",
|
||||
messages: "messages",
|
||||
modelPhoto: "modelPhoto",
|
||||
modelPhotoDemoA: "modelPhotoDemoA",
|
||||
modelPhotoDemoB: "modelPhotoDemoB",
|
||||
pipeline: "pipeline",
|
||||
platformCover: "platformCover",
|
||||
productCreate: "productCreateUpload",
|
||||
productCreateUpload: "productCreateUpload",
|
||||
productDetail: "productDetail",
|
||||
products: "products",
|
||||
projectWizard: "projectWizard",
|
||||
projects: "projects",
|
||||
register: "register",
|
||||
settings: "settings",
|
||||
team: "team"
|
||||
};
|
||||
|
||||
const exactKeyToFile: Record<ExactHtmlKey, string> = {
|
||||
account: "account.html",
|
||||
assetFactory: "asset-factory.html",
|
||||
dashboard: "index.html",
|
||||
imageOptimize: "image-optimize.html",
|
||||
library: "library.html",
|
||||
login: "login.html",
|
||||
messages: "messages.html",
|
||||
modelPhoto: "model-photo.html",
|
||||
modelPhotoDemoA: "model-photo-demo-a.html",
|
||||
modelPhotoDemoB: "model-photo-demo-b.html",
|
||||
pipeline: "pipeline.html",
|
||||
platformCover: "platform-cover.html",
|
||||
productCreate: "product-create.html",
|
||||
productCreateUpload: "product-create-upload.html",
|
||||
productDetail: "product-detail.html",
|
||||
products: "products.html",
|
||||
projectWizard: "projects-new.html",
|
||||
projects: "projects.html",
|
||||
register: "register.html",
|
||||
settings: "settings.html",
|
||||
team: "team.html"
|
||||
};
|
||||
|
||||
const liveHydratePages = new Set<ExactHtmlKey>([
|
||||
"dashboard",
|
||||
"products",
|
||||
"productDetail",
|
||||
"projectWizard",
|
||||
"projects",
|
||||
"pipeline",
|
||||
"library",
|
||||
"account",
|
||||
"settings",
|
||||
"team"
|
||||
]);
|
||||
|
||||
function routeFromHref(rawHref: string | null) {
|
||||
if (!rawHref || rawHref === "#" || rawHref.startsWith("javascript:")) return null;
|
||||
const url = new URL(rawHref, "https://airshelf.local/exact/");
|
||||
const fileName = url.pathname.split("/").filter(Boolean).pop() || "index.html";
|
||||
const page = fileToPage[fileName];
|
||||
if (!page) return null;
|
||||
const params = new URLSearchParams(url.search);
|
||||
return {
|
||||
page,
|
||||
hash: url.hash || "",
|
||||
search: url.search || "",
|
||||
productId: params.get("product_id") || undefined,
|
||||
projectId: params.get("project_id") || undefined
|
||||
};
|
||||
}
|
||||
|
||||
function routeFromInlineAction(action: string | null) {
|
||||
if (!action) return null;
|
||||
const hrefMatch = action.match(/location\.href\s*=\s*['"]([^'"]+)/);
|
||||
if (hrefMatch) return routeFromHref(hrefMatch[1]);
|
||||
const hashMatch = action.match(/location\.hash\s*=\s*['"]([^'"]+)/);
|
||||
if (hashMatch) return { page: null, hash: hashMatch[1], search: "" };
|
||||
return null;
|
||||
}
|
||||
|
||||
function setFrameHeight(frame: HTMLIFrameElement) {
|
||||
frame.style.height = `${Math.max(window.innerHeight, 720)}px`;
|
||||
}
|
||||
|
||||
export type ExactDocumentPageProps = {
|
||||
pageKey: ExactHtmlKey;
|
||||
hash?: string;
|
||||
productId?: string;
|
||||
projectId?: string;
|
||||
navigate?: NavigateFn;
|
||||
onAuthModeChange?: (mode: AuthMode) => void;
|
||||
onAuthSubmit?: (mode: AuthMode, event: FormEvent<HTMLFormElement>, form: HTMLFormElement) => void;
|
||||
};
|
||||
|
||||
export function exactKeyForPage(page: Page): ExactHtmlKey {
|
||||
return pageToExactKey[page] || "dashboard";
|
||||
}
|
||||
|
||||
function contextSearch(pageKey: ExactHtmlKey, productId?: string, projectId?: string) {
|
||||
const params = new URLSearchParams();
|
||||
if (pageKey === "productDetail" && productId) params.set("product_id", productId);
|
||||
if (pageKey === "pipeline" && projectId) params.set("project_id", projectId);
|
||||
const text = params.toString();
|
||||
return text ? `?${text}` : "";
|
||||
}
|
||||
|
||||
export function ExactDocumentPage({
|
||||
pageKey,
|
||||
hash,
|
||||
productId,
|
||||
projectId,
|
||||
navigate,
|
||||
onAuthModeChange,
|
||||
onAuthSubmit
|
||||
}: ExactDocumentPageProps) {
|
||||
const frameRef = useRef<HTMLIFrameElement | null>(null);
|
||||
const html = useMemo(() => {
|
||||
const context = {
|
||||
page: exactKeyToFile[pageKey],
|
||||
search: contextSearch(pageKey, productId, projectId),
|
||||
hash: hash ? `#${hash.replace(/^#/, "")}` : "",
|
||||
liveHydrate: liveHydratePages.has(pageKey)
|
||||
};
|
||||
return exactHtmlDocuments[pageKey].replace(
|
||||
"</head>",
|
||||
`<script>window.__AIR_SHELF_EXACT_CONTEXT__=${JSON.stringify(context)};</script></head>`
|
||||
);
|
||||
}, [hash, pageKey, productId, projectId]);
|
||||
|
||||
useEffect(() => {
|
||||
const frame = frameRef.current;
|
||||
if (!frame) return;
|
||||
const currentFrame: HTMLIFrameElement = frame;
|
||||
|
||||
function onLoad() {
|
||||
const doc = currentFrame.contentDocument;
|
||||
const win = currentFrame.contentWindow;
|
||||
if (!doc || !win) return;
|
||||
|
||||
(win as Window & { __AIR_SHELF_HOST_NAVIGATE__?: (href: string) => void }).__AIR_SHELF_HOST_NAVIGATE__ = (
|
||||
href: string
|
||||
) => {
|
||||
const hostRoute = routeFromHref(href);
|
||||
if (!hostRoute?.page) return;
|
||||
if (hostRoute.page === "login" || hostRoute.page === "register") {
|
||||
onAuthModeChange?.(hostRoute.page);
|
||||
return;
|
||||
}
|
||||
navigate?.(hostRoute.page, {
|
||||
hash: hostRoute.hash || undefined,
|
||||
productId: hostRoute.productId || (hostRoute.page === "productDetail" ? productId : undefined),
|
||||
projectId: hostRoute.projectId || (hostRoute.page === "pipeline" ? projectId : undefined)
|
||||
});
|
||||
};
|
||||
|
||||
const applyFrameHash = (nextHash: string) => {
|
||||
const cleanHash = nextHash.replace(/^#/, "");
|
||||
const stageMatch = cleanHash.match(/^stage-(\d+)$/);
|
||||
const pipelineWindow = win as Window & { activateStage?: (stage: number) => void };
|
||||
if (pageKey === "pipeline" && stageMatch && typeof pipelineWindow.activateStage === "function") {
|
||||
pipelineWindow.activateStage(Number(stageMatch[1]));
|
||||
return;
|
||||
}
|
||||
const settingsWindow = win as Window & { showSection?: (sectionId: string) => void };
|
||||
if (pageKey === "settings" && cleanHash.startsWith("sec-") && typeof settingsWindow.showSection === "function") {
|
||||
settingsWindow.showSection(cleanHash);
|
||||
return;
|
||||
}
|
||||
doc.getElementById(cleanHash)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
};
|
||||
|
||||
if (hash) {
|
||||
setTimeout(() => {
|
||||
applyFrameHash(hash);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
const clickHandler = (event: MouseEvent) => {
|
||||
const target = event.target as Element | null;
|
||||
if (!target) return;
|
||||
|
||||
const syncHashOnlyRoute = (nextHash: string) => {
|
||||
const cleanHash = nextHash.replace(/^#/, "");
|
||||
applyFrameHash(cleanHash);
|
||||
if (exactKeyToPage[pageKey]) {
|
||||
const nextUrl = `${window.location.pathname}${window.location.search}#${cleanHash}`;
|
||||
window.history.replaceState(null, "", nextUrl);
|
||||
}
|
||||
};
|
||||
|
||||
const actionNode = target.closest("[onclick]") as HTMLElement | null;
|
||||
const actionRoute = routeFromInlineAction(actionNode?.getAttribute("onclick") || null);
|
||||
if (actionRoute?.hash && actionRoute.page === null) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
syncHashOnlyRoute(actionRoute.hash);
|
||||
return;
|
||||
}
|
||||
if (actionRoute?.page) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
if (actionRoute.page === "login" || actionRoute.page === "register") {
|
||||
onAuthModeChange?.(actionRoute.page);
|
||||
return;
|
||||
}
|
||||
navigate?.(actionRoute.page, {
|
||||
hash: actionRoute.hash || undefined,
|
||||
productId: actionRoute.productId || (actionRoute.page === "productDetail" ? productId || "exact" : undefined),
|
||||
projectId: actionRoute.projectId
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const anchor = target.closest("a[href]") as HTMLAnchorElement | null;
|
||||
const rawAnchorHref = anchor?.getAttribute("href") || null;
|
||||
if (rawAnchorHref?.startsWith("#")) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
syncHashOnlyRoute(rawAnchorHref);
|
||||
return;
|
||||
}
|
||||
const anchorRoute = routeFromHref(rawAnchorHref);
|
||||
if (!anchorRoute) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
if (anchorRoute.page === "login" || anchorRoute.page === "register") {
|
||||
onAuthModeChange?.(anchorRoute.page);
|
||||
return;
|
||||
}
|
||||
navigate?.(anchorRoute.page, {
|
||||
hash: anchorRoute.hash || undefined,
|
||||
productId: anchorRoute.productId || (anchorRoute.page === "productDetail" ? productId || "exact" : undefined),
|
||||
projectId: anchorRoute.projectId
|
||||
});
|
||||
};
|
||||
|
||||
const submitHandler = (event: SubmitEvent) => {
|
||||
const form = event.target as HTMLFormElement | null;
|
||||
if (!form) return;
|
||||
const isLogin = pageKey === "login" && form.id === "login-form";
|
||||
const isRegister = pageKey === "register" && form.id === "register-form";
|
||||
if (!isLogin && !isRegister) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
onAuthSubmit?.(isLogin ? "login" : "register", event as unknown as FormEvent<HTMLFormElement>, form);
|
||||
};
|
||||
|
||||
doc.addEventListener("click", clickHandler, true);
|
||||
doc.addEventListener("submit", submitHandler, true);
|
||||
setFrameHeight(currentFrame);
|
||||
const resizeFrame = () => setFrameHeight(currentFrame);
|
||||
window.addEventListener("resize", resizeFrame);
|
||||
const observer = new ResizeObserver(() => setFrameHeight(currentFrame));
|
||||
observer.observe(doc.documentElement);
|
||||
observer.observe(doc.body);
|
||||
|
||||
const cleanup = () => {
|
||||
doc.removeEventListener("click", clickHandler, true);
|
||||
doc.removeEventListener("submit", submitHandler, true);
|
||||
window.removeEventListener("resize", resizeFrame);
|
||||
observer.disconnect();
|
||||
};
|
||||
currentFrame.dataset.cleanupKey = String(Date.now());
|
||||
(currentFrame as HTMLIFrameElement & { __airshelfCleanup?: () => void }).__airshelfCleanup?.();
|
||||
(currentFrame as HTMLIFrameElement & { __airshelfCleanup?: () => void }).__airshelfCleanup = cleanup;
|
||||
}
|
||||
|
||||
currentFrame.addEventListener("load", onLoad);
|
||||
if (currentFrame.contentDocument?.readyState !== "loading") onLoad();
|
||||
return () => {
|
||||
currentFrame.removeEventListener("load", onLoad);
|
||||
(currentFrame as HTMLIFrameElement & { __airshelfCleanup?: () => void }).__airshelfCleanup?.();
|
||||
(currentFrame as HTMLIFrameElement & { __airshelfCleanup?: () => void }).__airshelfCleanup = undefined;
|
||||
};
|
||||
}, [hash, navigate, onAuthModeChange, onAuthSubmit, pageKey]);
|
||||
|
||||
return (
|
||||
<div className="exact-document-route" data-exact-page={pageKey}>
|
||||
<iframe
|
||||
ref={frameRef}
|
||||
title={`Airshelf ${pageKey}`}
|
||||
className="exact-document-frame"
|
||||
srcDoc={html}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactAccountPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="account" />;
|
||||
}
|
||||
|
||||
export default ExactAccountPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactAssetFactoryPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="assetFactory" />;
|
||||
}
|
||||
|
||||
export default ExactAssetFactoryPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactDashboardPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="dashboard" />;
|
||||
}
|
||||
|
||||
export default ExactDashboardPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactImageOptimizePage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="imageOptimize" />;
|
||||
}
|
||||
|
||||
export default ExactImageOptimizePage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactLibraryPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="library" />;
|
||||
}
|
||||
|
||||
export default ExactLibraryPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactLoginPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="login" />;
|
||||
}
|
||||
|
||||
export default ExactLoginPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactMessagesPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="messages" />;
|
||||
}
|
||||
|
||||
export default ExactMessagesPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactModelPhotoDemoAPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="modelPhotoDemoA" />;
|
||||
}
|
||||
|
||||
export default ExactModelPhotoDemoAPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactModelPhotoDemoBPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="modelPhotoDemoB" />;
|
||||
}
|
||||
|
||||
export default ExactModelPhotoDemoBPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactModelPhotoPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="modelPhoto" />;
|
||||
}
|
||||
|
||||
export default ExactModelPhotoPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactPipelinePage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="pipeline" />;
|
||||
}
|
||||
|
||||
export default ExactPipelinePage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactPlatformCoverPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="platformCover" />;
|
||||
}
|
||||
|
||||
export default ExactPlatformCoverPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactProductCreateUploadPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="productCreateUpload" />;
|
||||
}
|
||||
|
||||
export default ExactProductCreateUploadPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactProductCreatePage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="productCreate" />;
|
||||
}
|
||||
|
||||
export default ExactProductCreatePage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactProductDetailPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="productDetail" />;
|
||||
}
|
||||
|
||||
export default ExactProductDetailPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactProductsPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="products" />;
|
||||
}
|
||||
|
||||
export default ExactProductsPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactProjectWizardPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="projectWizard" />;
|
||||
}
|
||||
|
||||
export default ExactProjectWizardPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactProjectsPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="projects" />;
|
||||
}
|
||||
|
||||
export default ExactProjectsPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactRegisterPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="register" />;
|
||||
}
|
||||
|
||||
export default ExactRegisterPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactSettingsPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="settings" />;
|
||||
}
|
||||
|
||||
export default ExactSettingsPage;
|
||||
@ -1,9 +0,0 @@
|
||||
/* Generated by scripts/generate-exact-html.mjs. Do not edit by hand. */
|
||||
import { ExactDocumentPage } from "../exact-document";
|
||||
import type { ExactDocumentPageProps } from "../exact-document";
|
||||
|
||||
export function ExactTeamPage(props: Omit<ExactDocumentPageProps, "pageKey">) {
|
||||
return <ExactDocumentPage {...props} pageKey="team" />;
|
||||
}
|
||||
|
||||
export default ExactTeamPage;
|
||||
@ -1,7 +1,6 @@
|
||||
|
||||
|
||||
export { AuthScreen } from "./auth-screen";
|
||||
export { ExactDashboardApp } from "./exact-dashboard";
|
||||
export { Dashboard } from "./dashboard";
|
||||
export { ProductsPage, ProductCreateUploadPage, ProductDetailPage } from "./products";
|
||||
export { ProjectWizardPage, ProjectsPage } from "./projects";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user