mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-26 15:38:45 -07:00
4edf25b2d5
Targets Rec Room 2020.12.18 client.
Re-import after adding:
- DorkNet.ClientMod/dorknet-clientmod.json.template — config schema
the launcher's manifest-driven patcher renders into UserData/.
- tools/build-patcher-zip.ps1 — produces the dorknet-clientpatch-{key}.zip
Release asset the launcher fetches.
- .github/workflows/release.yml — auto-publishes both Release assets
on v1-december-* tag push.
Scrubbed via maintainer-side scrub-for-public.ps1: same drop rules as
the prior import, plus build-patcher-zip.ps1 added to the tools/
allow-list so it survives the scrub.
70 lines
2.4 KiB
TypeScript
70 lines
2.4 KiB
TypeScript
import { useEffect } from 'react';
|
|
|
|
interface Props {
|
|
title: string;
|
|
open: boolean;
|
|
onClose: () => void;
|
|
children: React.ReactNode;
|
|
// Wider for dense edit forms (e.g. player detail with multiple sections).
|
|
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
// Sticky action bar at the bottom — pass buttons here so the form
|
|
// body can scroll but the actions stay visible on small screens.
|
|
footer?: React.ReactNode;
|
|
}
|
|
|
|
export function Modal({ title, open, onClose, children, size = 'md', footer }: Props) {
|
|
useEffect(() => {
|
|
if (!open) return;
|
|
const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
|
|
document.addEventListener('keydown', onKey);
|
|
const prevOverflow = document.body.style.overflow;
|
|
document.body.style.overflow = 'hidden';
|
|
return () => {
|
|
document.removeEventListener('keydown', onKey);
|
|
document.body.style.overflow = prevOverflow;
|
|
};
|
|
}, [open, onClose]);
|
|
|
|
if (!open) return null;
|
|
const sizeClass = {
|
|
sm: 'max-w-sm',
|
|
md: 'max-w-lg',
|
|
lg: 'max-w-2xl',
|
|
xl: 'max-w-4xl',
|
|
}[size];
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 z-40 flex items-center justify-center bg-ink-950/70 backdrop-blur-sm px-4 py-6"
|
|
onClick={onClose}
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-label={title}
|
|
>
|
|
<div
|
|
className={`card flex max-h-full w-full flex-col ${sizeClass}`}
|
|
onClick={e => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center justify-between border-b border-ink-800 px-5 py-3">
|
|
<h2 className="text-sm font-semibold tracking-tight text-ink-50">{title}</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="rounded-md p-1 text-ink-400 hover:bg-ink-800 hover:text-ink-200"
|
|
aria-label="Close"
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
</button>
|
|
</div>
|
|
<div className="overflow-y-auto px-5 py-4">
|
|
{children}
|
|
</div>
|
|
{footer && (
|
|
<div className="flex items-center justify-end gap-2 border-t border-ink-800 px-5 py-3 bg-ink-900/40">
|
|
{footer}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|