Import december-2020-12-18 from private repo (scrubbed 2026-05-27)

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.
This commit is contained in:
Alexa
2026-05-27 01:04:12 +03:00
commit 4edf25b2d5
375 changed files with 201291 additions and 0 deletions
@@ -0,0 +1,69 @@
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>
);
}