export type LaneMode = "displace" | "queue" | "block"; /** A single bind: a key, or a hold-combo (`hold` kept down while `press` is pressed). */ export type Hotkey = Enum.KeyCode | { hold: Enum.KeyCode; press: Enum.KeyCode; }; /** Rules for one window. `N` is the union of registered window names, so cross-references autocomplete and typos don't compile. */ export type Rules = { /** Closing (or displacing) the parent closes this window too, recursively. */ parent?: N; /** Opening this window force-closes these, regardless of exclusivity. */ closes?: readonly N[]; /** This window refuses to open while any of these are open. */ blockedBy?: readonly N[]; /** Starting state overrides, e.g. `{ open: true }` for a HUD. */ defaults?: { open?: boolean; }; /** Persistent windows survive closeAll. Default false. */ persistent?: boolean; /** One or more binds — keyboard/gamepad codes, plain or `{ hold, press }` combos. Plain binds don't fire while a modifier is held, so DPadLeft and L1+DPadLeft coexist. */ hotkey?: Hotkey | readonly Hotkey[]; onOpen?: () => void; onClose?: () => void; }; /** An exclusivity lane: only one member may be open. `mode` decides what happens when a member opens while another is open — displace it (default), queue behind it, or fail. */ export type Lane = readonly N[] | { mode?: LaneMode; members: readonly N[]; }; export type Config = { windows: T; exclusive?: Record>; }; /** Per-window API, e.g. `forge.shop.toggle()`. */ export type Handle = { /** Opens the window, enforcing its rules. Returns false if blocked or queued. `open(true)` ignores blockers and displaces any occupant. */ open: (force?: boolean) => boolean; close: () => void; toggle: () => void; /** Reactive open-state — bind to Visible/springs, or call for a plain read. */ state: () => boolean; }; /** A constructed forge: a `Handle` per window plus the methods below. */ export type Forge = { [K in keyof T]: Handle; } & { /** Closes every open window except `persistent` ones and clears lane queues. */ closeAll: () => void; /** Restores every window to its `defaults` and clears lane queues. */ reset: () => void; /** Binds every window's `hotkey` through an InputContext under `parent`. Returns a cleanup function. */ attachHotkeys: (parent: Instance) => () => void; }; /** Internal: normalized lane. */ export type NormalizedLane = { mode: LaneMode; members: readonly string[]; };