feat(terminal): terminal wrapper and context

This commit is contained in:
Pihkaal
2024-01-22 11:50:37 +01:00
parent 070e198b43
commit f7b43b47bf
2 changed files with 73 additions and 16 deletions

View File

@@ -1,20 +1,62 @@
import { type FunctionComponent, type PropsWithChildren } from "react"; import { useRef, useState, useEffect, type ReactNode } from "react";
import clsx from "clsx"; import clsx from "clsx";
import { TerminalContextProvider } from "~/context/TerminalContext";
type TerminalProps = PropsWithChildren<{ export const Terminal = (props: {
children?: ReactNode;
className?: string; className?: string;
}>; }) => {
const terminalRef = useRef<HTMLDivElement>(null);
export const Terminal: FunctionComponent<TerminalProps> = ({ const [size, setSize] = useState<{ cols: number; rows: number }>();
children,
className, useEffect(() => {
}) => ( const precision = 300;
const calculateSize = () => {
if (!terminalRef.current) return;
const node = document.createElement("span");
node.style.color = "transparent";
node.style.position = "absolute";
node.textContent = "A".repeat(precision);
terminalRef.current.appendChild(node);
setSize({
cols: Math.floor(
(terminalRef.current.offsetWidth - 4) /
(node.offsetWidth / precision),
),
rows: Math.floor(
(terminalRef.current.offsetHeight - 4) / node.offsetHeight,
),
});
node.remove();
};
calculateSize();
window.addEventListener("resize", calculateSize);
return () => {
window.removeEventListener("resize", calculateSize);
};
}, []);
return (
<TerminalContextProvider value={size}>
<div <div
ref={terminalRef}
className={clsx( className={clsx(
"rounded-lg border-2 border-[#595959] bg-[#1e1e2e] bg-opacity-95 px-1 text-[#cdd6f4] shadow-window transition-colors duration-[500ms] ease-out hover:border-[#cdd6f4] hover:duration-[200ms]", "overflow-hidden rounded-lg border-2 border-borderInactive bg-background bg-opacity-80 text-lg text-color7 text-foreground shadow-window transition-colors duration-[500ms] ease-out hover:border-borderActive hover:duration-[200ms]",
className, props.className,
)} )}
style={{ backdropFilter: "blur(2px)" }}
> >
{children} {size && props.children}
</div> </div>
); </TerminalContextProvider>
);
};

View File

@@ -0,0 +1,15 @@
import { createContext, useContext } from "react";
const TerminalContext = createContext<{ cols: number; height: number } | null>(
null,
);
export const TerminalContextProvider = TerminalContext.Provider;
export const useTerminal = () => {
const context = useContext(TerminalContext);
if (!context)
throw new Error("useTerminal must be used inside a Terminal component");
return context;
};