51925e955f
Everything sat in the eager startup graph (App.tsx statically imported all 28
routes; the editor pulled TipTap + KaTeX + ~45 lowlight grammars + drawio;
posthog + AI SDK loaded for everyone) — a /login visitor downloaded+compiled the
whole editor. Client-only; functionality 1:1, only WHEN code loads changed.
Result (prod build): eager JS 3.5MB -> ~1.12MB, entry 1920KB -> 552KB; KaTeX
(250KB) and the TipTap engine (~586KB) are now lazy chunks, off the startup path.
- App.tsx: route-level React.lazy + Suspense (editor Page, all settings/*, share,
space/home routes). Auth/redirect/cold-start routes stay eager. Suspense lives
inside Layout/ShareLayout around the Outlet so the shell stays mounted.
- Lazy KaTeX node views (math-inline-lazy/math-block-lazy) + lazy drawio
(drawio-view-lazy/drawio-menu-lazy), mirroring mermaid/excalidraw, each with a
node-sized Suspense placeholder so a slow chunk can't crash the editor.
- posthog-js is now a conditional dynamic import under the unchanged
isCloud() && isPostHogEnabled gate — self-hosted never downloads it.
- AiChatWindow is React.lazy, mounted on first open and kept mounted (a live AI
stream isn't torn down); renders null while closed (identical behavior).
- Cut eager TipTap pulls from always-loaded shell modules: editor-atoms /
global-bridge Editor -> import type; Aside lazily loaded (page routes only);
config.ts sanitizeUrl and use-clipboard execCommandCopy moved to client-local
src/lib/{sanitize-url,copy-to-clipboard}.ts (byte-identical to the editor-ext
originals, dropping the barrel's top-level @tiptap import); WebSocketStatus
import replaced with the "connected" literal the status atom already stores.
- vite.config.ts: a vendor-katex chunk group (TipTap/PM/Yjs intentionally NOT
grouped — grouping dragged the engine eager; documented in the config).
- lowlight grammar registration is left inside the (now-lazy) editor chunk:
listLanguages()/highlighting are synchronous, so deferring registration would
change behavior for marginal in-chunk gain — the route split already removes it
from startup, which was the complaint.
Gate: client build succeeds, tsc --noEmit clean, frozen install EXIT 0 (added
@braintree/sanitize-url as a direct client dep + regenerated the lock).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
// Source: https://github.com/mantinedev/mantine/blob/master/packages/@mantine/hooks/src/use-clipboard/use-clipboard.ts
|
|
// polyfilled to support execCommand fallback
|
|
import { useState } from "react";
|
|
import { execCommandCopy } from "@/lib/copy-to-clipboard.ts";
|
|
|
|
export type UseClipboardOptions = {
|
|
timeout?: number;
|
|
};
|
|
|
|
export type UseClipboardReturnValue = {
|
|
copy: (value: string) => void;
|
|
reset: () => void;
|
|
error: Error | null;
|
|
copied: boolean;
|
|
};
|
|
|
|
export function useClipboard(
|
|
options: UseClipboardOptions = { timeout: 2000 },
|
|
): UseClipboardReturnValue {
|
|
const [error, setError] = useState<Error | null>(null);
|
|
const [copied, setCopied] = useState(false);
|
|
const [copyTimeout, setCopyTimeout] = useState<number | null>(null);
|
|
|
|
const handleCopyResult = (value: boolean) => {
|
|
window.clearTimeout(copyTimeout!);
|
|
setCopyTimeout(window.setTimeout(() => setCopied(false), options.timeout));
|
|
setCopied(value);
|
|
};
|
|
|
|
const copy = (value: string) => {
|
|
if ("clipboard" in navigator) {
|
|
navigator.clipboard
|
|
.writeText(value)
|
|
.then(() => handleCopyResult(true))
|
|
.catch(() => {
|
|
try {
|
|
execCommandCopy(value);
|
|
handleCopyResult(true);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err : new Error("Failed to copy"));
|
|
}
|
|
});
|
|
} else {
|
|
try {
|
|
execCommandCopy(value);
|
|
handleCopyResult(true);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err : new Error("Failed to copy"));
|
|
}
|
|
}
|
|
};
|
|
|
|
const reset = () => {
|
|
setCopied(false);
|
|
setError(null);
|
|
window.clearTimeout(copyTimeout!);
|
|
};
|
|
|
|
return { copy, reset, error, copied };
|
|
}
|