Files
QOffice/src/components/AppShell.tsx
T
Курнат Андрей 626576e156 Preserve QWord caret while typing
2026-06-04 21:00:40 +03:00

93 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
ChevronDown,
Redo2,
Save,
Search,
Share2,
Undo2
} from "lucide-react";
import type { MouseEvent, ReactNode } from "react";
import type { QOfficeCommand } from "../hooks/useQOfficeCommand";
import type { AppId } from "../types";
interface AppShellProps {
activeApp: AppId;
windowTitle?: string;
status: {
savedLabel: string;
updatedAt?: string;
content?: ReactNode;
trailing?: ReactNode;
className?: string;
};
children: ReactNode;
}
const appTitles: Record<AppId, string> = {
word: "Документ1 - QWord",
sheets: "Книга1 - QExcell",
slides: "Презентация1 - QPowerPoint",
mail: "Почта - QOutlook"
};
function dispatchQOfficeCommand(command: QOfficeCommand) {
window.dispatchEvent(new CustomEvent("qoffice-command", { detail: { command } }));
}
function keepActiveEditorFocus(event: MouseEvent<HTMLButtonElement>) {
event.preventDefault();
}
export function AppShell({ activeApp, windowTitle, status, children }: AppShellProps) {
const statusClassName = ["statusbar", status.className].filter(Boolean).join(" ");
const displayWindowTitle = windowTitle?.trim() || appTitles[activeApp];
return (
<div className="qoffice-shell">
<main className="workspace">
<header className="titlebar">
<div className="quick-access" aria-label="Панель быстрого доступа">
<button type="button" title="Сохранить" aria-label="Сохранить" onMouseDown={keepActiveEditorFocus} onClick={() => dispatchQOfficeCommand("save")}>
<Save size={16} />
</button>
<button type="button" title="Отменить" aria-label="Отменить" onMouseDown={keepActiveEditorFocus} onClick={() => dispatchQOfficeCommand("undo")}>
<Undo2 size={16} />
</button>
<button type="button" title="Повторить" aria-label="Повторить" onMouseDown={keepActiveEditorFocus} onClick={() => dispatchQOfficeCommand("redo")}>
<Redo2 size={16} />
</button>
<button type="button" title="Настроить панель" aria-label="Настроить панель">
<ChevronDown size={14} />
</button>
</div>
<strong className="window-title">{displayWindowTitle}</strong>
<div className="titlebar-actions">
<label className="command-search">
<Search size={16} />
<input placeholder="Поиск" aria-label="Поиск" />
</label>
<button className="primary-command" type="button">
<Share2 size={16} />
Поделиться
</button>
</div>
</header>
<div className="surface-host">{children}</div>
<footer className={statusClassName}>
<div className="statusbar-main">
{status.content ?? (
<>
<span>Готово</span>
<span>{status.updatedAt ? `Обновлено: ${new Date(status.updatedAt).toLocaleString("ru-RU")}` : "Локальная почта"}</span>
</>
)}
</div>
<div className="statusbar-trailing">{status.trailing ?? <span>Масштаб 100%</span>}</div>
</footer>
</main>
</div>
);
}