mirror of
https://github.com/khairul169/code-share.git
synced 2025-04-28 16:49:36 +07:00
101 lines
2.9 KiB
TypeScript
101 lines
2.9 KiB
TypeScript
/* eslint-disable react/display-name */
|
|
import Panel from "~/components/ui/panel";
|
|
import { ComponentProps, useCallback, useEffect, useRef } from "react";
|
|
import { useProjectContext } from "../context/project";
|
|
import { Button } from "~/components/ui/button";
|
|
import { FaExternalLinkAlt, FaRedo } from "react-icons/fa";
|
|
import { previewStore } from "../stores/web-preview";
|
|
import { ImperativePanelHandle } from "react-resizable-panels";
|
|
import useCommandKey from "~/hooks/useCommandKey";
|
|
import { ResizablePanel } from "~/components/ui/resizable";
|
|
import { useConsoleLogger } from "~/hooks/useConsoleLogger";
|
|
|
|
type WebPreviewProps = ComponentProps<typeof ResizablePanel> & {
|
|
url?: string | null;
|
|
};
|
|
|
|
const WebPreview = ({ url, ...props }: WebPreviewProps) => {
|
|
const frameRef = useRef<HTMLIFrameElement>(null);
|
|
const panelRef = useRef<ImperativePanelHandle>(null);
|
|
const project = useProjectContext();
|
|
|
|
// hook into the console
|
|
useConsoleLogger();
|
|
|
|
const refresh = useCallback(() => {
|
|
if (frameRef.current) {
|
|
frameRef.current.src = `${url}?t=${Date.now()}`;
|
|
}
|
|
}, [url]);
|
|
|
|
const togglePanel = useCallback(
|
|
(toggle?: boolean) => {
|
|
const panel = panelRef.current;
|
|
if (!panel) {
|
|
return;
|
|
}
|
|
|
|
const expand = toggle != null ? toggle : !panel.isCollapsed();
|
|
|
|
if (expand) {
|
|
panel.collapse();
|
|
} else {
|
|
panel.expand();
|
|
panel.resize(
|
|
typeof props.defaultSize === "number" ? props.defaultSize : 25
|
|
);
|
|
}
|
|
},
|
|
[panelRef, props.defaultSize]
|
|
);
|
|
|
|
useCommandKey("p", togglePanel);
|
|
|
|
useEffect(() => {
|
|
previewStore.setState({ refresh, toggle: togglePanel });
|
|
refresh();
|
|
}, [refresh, togglePanel]);
|
|
|
|
const PanelComponent = !project.isCompact || !project.isEmbed ? Panel : "div";
|
|
|
|
return (
|
|
<ResizablePanel
|
|
ref={panelRef}
|
|
onExpand={() => previewStore.setState({ open: true })}
|
|
onCollapse={() => previewStore.setState({ open: false })}
|
|
{...props}
|
|
>
|
|
<PanelComponent className="h-full flex flex-col bg-slate-800">
|
|
<div className="h-10 hidden md:flex items-center pl-4">
|
|
<p className="flex-1 truncate text-xs uppercase">Preview</p>
|
|
<Button
|
|
variant="ghost"
|
|
className="dark:hover:bg-slate-700"
|
|
onClick={refresh}
|
|
>
|
|
<FaRedo />
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
className="dark:hover:bg-slate-700"
|
|
onClick={() => window.open(url || "#", "_blank")}
|
|
>
|
|
<FaExternalLinkAlt />
|
|
</Button>
|
|
</div>
|
|
|
|
{url != null ? (
|
|
<iframe
|
|
id="web-preview"
|
|
ref={frameRef}
|
|
className="border-none w-full flex-1 overflow-hidden bg-white"
|
|
sandbox="allow-scripts allow-forms"
|
|
/>
|
|
) : null}
|
|
</PanelComponent>
|
|
</ResizablePanel>
|
|
);
|
|
};
|
|
|
|
export default WebPreview;
|