From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- apps/web/src/preview/overlays.ts | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 apps/web/src/preview/overlays.ts (limited to 'apps/web/src/preview/overlays.ts') diff --git a/apps/web/src/preview/overlays.ts b/apps/web/src/preview/overlays.ts new file mode 100644 index 00000000..6e5b0816 --- /dev/null +++ b/apps/web/src/preview/overlays.ts @@ -0,0 +1,108 @@ +import type { ReactNode } from "react"; + +export type PreviewOverlayHudAnchor = + | "top-left" + | "top-right" + | "bottom-left" + | "bottom-right"; + +export type PreviewOverlayMount = + | { + kind: "hud"; + anchor: PreviewOverlayHudAnchor; + order?: number; + } + | { + kind: "scene"; + x?: number; + y?: number; + width?: number; + height?: number; + } + | { + kind: "viewport"; + x?: number; + y?: number; + width?: number; + height?: number; + }; + +export type PreviewOverlayPlane = "under-interaction" | "over-interaction"; + +export interface PreviewOverlayRenderContext { + sceneHeight: number; + sceneWidth: number; +} + +export interface PreviewOverlayInstance { + id: string; + mount: PreviewOverlayMount; + plane?: PreviewOverlayPlane; + pointerEvents?: "none" | "auto"; + zIndex?: number; + render: (context: PreviewOverlayRenderContext) => ReactNode; +} + +export interface PreviewOverlayDefinition { + id: string; + label: string; + defaultVisible?: boolean; +} + +export interface PreviewOverlayControl extends PreviewOverlayDefinition { + isVisible: boolean; +} + +export interface PreviewOverlaySourceResult { + definitions: PreviewOverlayDefinition[]; + instances: PreviewOverlayInstance[]; +} + +export const EMPTY_PREVIEW_OVERLAY_SOURCE_RESULT: PreviewOverlaySourceResult = { + definitions: [], + instances: [], +}; + +export function isPreviewOverlayVisible({ + overlay, + overlays, +}: { + overlay: PreviewOverlayDefinition; + overlays: Record; +}): boolean { + return overlays[overlay.id] ?? overlay.defaultVisible ?? true; +} + +export function createPreviewOverlayControl({ + overlay, + overlays, +}: { + overlay: PreviewOverlayDefinition; + overlays: Record; +}): PreviewOverlayControl { + return { + ...overlay, + isVisible: isPreviewOverlayVisible({ overlay, overlays }), + }; +} + +export function mergePreviewOverlaySources({ + sources, +}: { + sources: PreviewOverlaySourceResult[]; +}): PreviewOverlaySourceResult { + const definitionsById = new Map(); + const instances: PreviewOverlayInstance[] = []; + + for (const source of sources) { + for (const definition of source.definitions) { + definitionsById.set(definition.id, definition); + } + instances.push(...source.instances); + } + + return { + definitions: [...definitionsById.values()], + instances, + }; +} -- cgit v1.3.1