From 21e739070dd1c2f954b513a8811ce0a38a61ba94 Mon Sep 17 00:00:00 2001
From: thepaperpilot <thepaperpilot@gmail.com>
Date: Sun, 10 Jul 2022 00:43:34 -0500
Subject: [PATCH] Documented game/layers.tsx

---
 src/game/layers.tsx | 114 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 108 insertions(+), 6 deletions(-)

diff --git a/src/game/layers.tsx b/src/game/layers.tsx
index 351d1fc..e8d22c3 100644
--- a/src/game/layers.tsx
+++ b/src/game/layers.tsx
@@ -24,33 +24,51 @@ import { createLazyProxy } from "util/proxies";
 import type { InjectionKey, Ref } from "vue";
 import { ref, shallowReactive, unref } from "vue";
 
+/** A feature's node in the DOM that has its size tracked. */
 export interface FeatureNode {
     rect: DOMRect;
     observer: MutationObserver;
     element: HTMLElement;
 }
 
+/**
+ * An injection key that a {@link Context} will use to provide a function that registers a {@link FeatureNode} with the given id and HTML element.
+ */
 export const RegisterNodeInjectionKey: InjectionKey<(id: string, element: HTMLElement) => void> =
-    Symbol("RegisterNode");
+    Symbol("RegisterNode"); 
+/**
+ * An injection key that a {@link Context} will use to provide a function that unregisters a {@link FeatureNode} with the given id.
+ */
 export const UnregisterNodeInjectionKey: InjectionKey<(id: string) => void> =
     Symbol("UnregisterNode");
+/**
+ * An injection key that a {@link Context} will use to provide a ref to a map of all currently registered {@link FeatureNode}s.
+ */
 export const NodesInjectionKey: InjectionKey<Ref<Record<string, FeatureNode | undefined>>> =
     Symbol("Nodes");
+/**
+ * An injection key that a {@link Context} will use to provide a ref to a bounding rect of the Context.
+ */
 export const BoundsInjectionKey: InjectionKey<Ref<DOMRect | undefined>> = Symbol("Bounds");
 
+/** All types of events able to be sent or emitted from a layer's emitter. */
 export interface LayerEvents {
-    // Generation
+    /** Sent every game tick, before the update event. Intended for "generation" type actions. */
     preUpdate: (diff: number) => void;
-    // Actions (e.g. automation)
+    /** Sent every game tick. Intended for "automation" type actions. */
     update: (diff: number) => void;
-    // Effects (e.g. milestones)
+    /** Sent every game tick, after the update event. Intended for checking state. */
     postUpdate: (diff: number) => void;
 }
 
+/**
+ * A reference to all the current layers.
+ * It is shallow reactive so it will update when layers are added or removed, but not interfere with the existing refs within each layer.
+ */
 export const layers: Record<string, Readonly<GenericLayer> | undefined> = shallowReactive({});
 
 declare global {
-    /** Augment the window object so the layers can be accessed from the console */
+    /** Augment the window object so the layers can be accessed from the console. */
     interface Window {
         layers: Record<string, Readonly<GenericLayer> | undefined>;
     }
@@ -58,36 +76,81 @@ declare global {
 window.layers = layers;
 
 declare module "@vue/runtime-dom" {
+    /** Augment CSS Properties to allow for setting the layer color CSS variable. */
     interface CSSProperties {
         "--layer-color"?: string;
     }
 }
 
+/** An object representing the position of some entity. */
 export interface Position {
+    /** The X component of the entity's position. */
     x: number;
+    /** The Y component of the entity's position. */
     y: number;
 }
 
+/**
+ * An object that configures a {@link Layer}.
+ * Even moreso than features, the developer is expected to include extra properties in this object.
+ * All {@link persistent} refs must be included somewhere within the layer object.
+ */
 export interface LayerOptions {
+    /** The color of the layer, used to theme the entire layer's display. */
     color?: Computable<string>;
+    /**
+     * The layout of this layer's features.
+     * When the layer is open in {@link player.tabs}, this is the content that is display.
+     */
     display: Computable<CoercableComponent>;
+    /** An object of classes that should be applied to the display. */
     classes?: Computable<Record<string, boolean>>;
+    /** Styles that should be applied to the display. */
     style?: Computable<StyleValue>;
+    /**
+     * The name of the layer, used on minimized tabs.
+     * Defaults to {@link id}.
+     */
     name?: Computable<string>;
+    /**
+     * Whether or not the layer can be minimized.
+     * Defaults to true.
+     */
     minimizable?: Computable<boolean>;
+    /**
+     * Whether or not to force the go back button to be hidden.
+     * If true, go back will be hidden regardless of {@link projInfo.allowGoBack}.
+     */
     forceHideGoBack?: Computable<boolean>;
+    /**
+     * A CSS min-width value that is applied to the layer.
+     * Can be a number, in which case the unit is assumed to be px.
+     * Defaults to 600px.
+     */
     minWidth?: Computable<number | string>;
 }
 
+/** The properties that are added onto a processed {@link LayerOptions} to create a {@link Layer} */
 export interface BaseLayer {
+    /**
+     * The ID of the layer.
+     * Populated from the {@link createLayer} parameters.
+     * Used for saving and tracking open tabs.
+     */
     id: string;
+    /** A persistent ref tracking if the tab is minimized or not. */
     minimized: Persistent<boolean>;
+    /** An emitter for sending {@link LayerEvents} events for this layer. */
     emitter: Emitter<LayerEvents>;
+    /** A function to register an event listener on {@link emitter}. */
     on: OmitThisParameter<Emitter<LayerEvents>["on"]>;
-    emit: <K extends keyof LayerEvents>(event: K, ...args: Parameters<LayerEvents[K]>) => void;
+    /** A function to emit a {@link LayerEvents} event to this layer. */
+    emit: <K extends keyof LayerEvents>(...args: [K, ...Parameters<LayerEvents[K]>]) => void;
+    /** A map of {@link FeatureNode}s present in this layer's {@link Context} component. */
     nodes: Ref<Record<string, FeatureNode | undefined>>;
 }
 
+/** An unit of game content. Displayed to the user as a tab or modal. */
 export type Layer<T extends LayerOptions> = Replace<
     T & BaseLayer,
     {
@@ -102,6 +165,7 @@ export type Layer<T extends LayerOptions> = Replace<
     }
 >;
 
+/** A type that matches any valid {@link Layer} object. */
 export type GenericLayer = Replace<
     Layer<LayerOptions>,
     {
@@ -111,8 +175,19 @@ export type GenericLayer = Replace<
     }
 >;
 
+/**
+ * When creating layers, this object a map of layer ID to a set of any created persistent refs in order to check they're all included in the final layer object.
+ */
 export const persistentRefs: Record<string, Set<Persistent>> = {};
+/**
+ * When creating layers, this array stores the layers currently being created, as a stack.
+ */
 export const addingLayers: string[] = [];
+/**
+ * Lazily creates a layer with the given options.
+ * @param id The ID this layer will have. See {@link BaseLayer.id}.
+ * @param optionsFunc Layer options.
+ */
 export function createLayer<T extends LayerOptions>(
     id: string,
     optionsFunc: OptionsFunc<T, BaseLayer>
@@ -150,6 +225,14 @@ export function createLayer<T extends LayerOptions>(
     });
 }
 
+/**
+ * Enables a layer object, so it will be updated every tick.
+ * Note that accessing a layer/its properties does NOT require it to be enabled.
+ * For dynamic layers you can call this function and {@link removeLayer} as necessary. Just make sure {@link projEntry.getInitialLayers} will provide an accurate list of layers based on the player data object.
+ * For static layers just make {@link projEntry.getInitialLayers} return all the layers.
+ * @param layer The layer to add.
+ * @param player The player data object, which will have a data object for this layer.
+ */
 export function addLayer(
     layer: GenericLayer,
     player: { layers?: Record<string, Record<string, unknown>> }
@@ -173,10 +256,19 @@ export function addLayer(
     globalBus.emit("addLayer", layer, player.layers[layer.id]);
 }
 
+/**
+ * Convenience method for getting a layer by its ID with correct typing.
+ * @param layerID The ID of the layer to get.
+ */
 export function getLayer<T extends GenericLayer>(layerID: string): T {
     return layers[layerID] as T;
 }
 
+/**
+ * Disables a layer, so it will no longer be updated every tick.
+ * Note that accessing a layer/its properties does NOT require it to be enabled.
+ * @param layer The layer to remove.
+ */
 export function removeLayer(layer: GenericLayer): void {
     console.info("Removing layer", layer.id);
     globalBus.emit("removeLayer", layer);
@@ -184,6 +276,11 @@ export function removeLayer(layer: GenericLayer): void {
     layers[layer.id] = undefined;
 }
 
+/**
+ * Convenience method for removing and immediately re-adding a layer.
+ * This is useful for layers with dynamic content, to ensure persistent refs are correctly configured.
+ * @param layer Layer to remove and then re-add
+ */
 export function reloadLayer(layer: GenericLayer): void {
     removeLayer(layer);
 
@@ -191,6 +288,11 @@ export function reloadLayer(layer: GenericLayer): void {
     addLayer(layer, player);
 }
 
+/**
+ * Utility function for creating a modal that display's a {@link layer.display}.
+ * Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal.
+ * @param layer The layer to display in the modal.
+ */
 export function setupLayerModal(layer: GenericLayer): {
     openModal: VoidFunction;
     modal: JSXFunction;