From c5e3cd103d384a5ca2d2a2cf1ed20610c08e067c Mon Sep 17 00:00:00 2001
From: Brian Peiris <brianpeiris@gmail.com>
Date: Tue, 22 May 2018 00:15:01 -0700
Subject: [PATCH] Add docstrings to all a-frame components and systems

---
 src/components/animation-mixer.js             |  4 ++++
 src/components/audio-feedback.js              | 14 +++++++++++++
 src/components/avatar-replay.js               |  5 +++++
 src/components/block-button.js                |  5 +++++
 src/components/bone-mute-state-indicator.js   |  2 ++
 src/components/bone-visibility.js             |  5 +++++
 src/components/cardboard-controls.js          |  5 +++++
 src/components/character-controller.js        | 10 +++++++--
 src/components/controls-shape-offset.js       |  5 +++++
 src/components/css-class.js                   |  4 ++++
 src/components/cursor-controller.js           |  5 +++++
 src/components/duck.js                        |  4 ++++
 src/components/event-repeater.js              |  4 ++++
 src/components/freeze-controller.js           |  5 +++++
 src/components/gltf-bundle.js                 |  5 +++++
 src/components/gltf-model-plus.js             |  6 ++++++
 src/components/hand-controls2.js              |  5 +++++
 src/components/hand-poses.js                  | 10 +++++++++
 src/components/haptic-feedback.js             |  5 +++++
 src/components/hide-when-quality.js           |  4 ++++
 src/components/hud-controller.js              |  2 ++
 src/components/icon-button.js                 |  5 +++++
 src/components/ik-controller.js               | 16 ++++++++++++--
 src/components/in-world-hud.js                |  5 +++++
 src/components/layers.js                      |  4 ++++
 src/components/loop-animation.js              |  4 ++++
 src/components/mute-mic.js                    |  5 +++++
 src/components/nav-mesh-helper.js             |  4 ++++
 src/components/networked-avatar.js            |  5 +++++
 src/components/networked-counter.js           |  5 +++++
 src/components/networked-video-player.js      |  5 +++++
 src/components/offset-relative-to.js          |  4 ++++
 src/components/player-info.js                 |  5 +++++
 src/components/scene-shadow.js                |  5 ++++-
 src/components/spawn-controller.js            |  9 ++++++++
 .../super-networked-interactable.js           |  5 +++++
 src/components/super-spawner.js               |  5 +++++
 src/components/text-button.js                 |  5 +++++
 src/components/virtual-gamepad-controls.js    |  5 +++++
 src/components/visible-while-frozen.js        | 10 +++++++++
 src/components/wasd-to-analog2d.js            |  5 +++++
 src/systems/app-mode.js                       | 11 ++++++++++
 src/systems/personal-space-bubble.js          | 21 +++++++++++++++++++
 43 files changed, 257 insertions(+), 5 deletions(-)

diff --git a/src/components/animation-mixer.js b/src/components/animation-mixer.js
index 791854f1e..480a4de23 100644
--- a/src/components/animation-mixer.js
+++ b/src/components/animation-mixer.js
@@ -1,3 +1,7 @@
+/**
+ * Instantiates and updates a THREE.AnimationMixer on an entity.
+ * @component animation-mixer
+ */
 AFRAME.registerComponent("animation-mixer", {
   init() {
     this.mixer = null;
diff --git a/src/components/audio-feedback.js b/src/components/audio-feedback.js
index a72ec196e..7edf3ec3f 100644
--- a/src/components/audio-feedback.js
+++ b/src/components/audio-feedback.js
@@ -1,3 +1,8 @@
+/**
+ * Emits audioFrequencyChange events based on a networked audio source
+ * @namespace avatar
+ * @component networked-audio-analyser
+ */
 AFRAME.registerComponent("networked-audio-analyser", {
   schema: {},
   async init() {
@@ -27,6 +32,10 @@ AFRAME.registerComponent("networked-audio-analyser", {
   }
 });
 
+/**
+ * Sets an entity's color base on audioFrequencyChange events.
+ * @component matcolor-audio-feedback
+ */
 AFRAME.registerComponent("matcolor-audio-feedback", {
   schema: {
     analyserSrc: { type: "selector" }
@@ -49,6 +58,11 @@ AFRAME.registerComponent("matcolor-audio-feedback", {
   }
 });
 
+/**
+ * Sets an entity's scale base on audioFrequencyChange events.
+ * @namespace avatar
+ * @component scale-audio-feedback
+ */
 AFRAME.registerComponent("scale-audio-feedback", {
   schema: {
     analyserSrc: { type: "selector" },
diff --git a/src/components/avatar-replay.js b/src/components/avatar-replay.js
index bbcb397cf..260744549 100644
--- a/src/components/avatar-replay.js
+++ b/src/components/avatar-replay.js
@@ -11,6 +11,11 @@ const controlsBlacklist = [
   "gearvr-controls"
 ];
 
+/**
+ * Replays a recorded motion capture with the given avatar body parts
+ * @namespace avatar
+ * @component avatar-replay
+ */
 AFRAME.registerComponent("avatar-replay", {
   schema: {
     camera: { type: "selector" },
diff --git a/src/components/block-button.js b/src/components/block-button.js
index 9dc23988c..603de3bc6 100644
--- a/src/components/block-button.js
+++ b/src/components/block-button.js
@@ -1,3 +1,8 @@
+/**
+ * Registers a click handler and invokes the block method on the NAF adapter for the owner associated with its entity.
+ * @namespace network
+ * @component block-button
+ */
 AFRAME.registerComponent("block-button", {
   init() {
     this.onClick = () => {
diff --git a/src/components/bone-mute-state-indicator.js b/src/components/bone-mute-state-indicator.js
index 92a2590e2..cf7305576 100644
--- a/src/components/bone-mute-state-indicator.js
+++ b/src/components/bone-mute-state-indicator.js
@@ -1,5 +1,7 @@
 /**
  * Toggles the position of 2 bones into "on" and "off" positions to indicate mute state.
+ * @namespace avatar
+ * @component bone-mute-state-indicator
  */
 AFRAME.registerComponent("bone-mute-state-indicator", {
   schema: {
diff --git a/src/components/bone-visibility.js b/src/components/bone-visibility.js
index 6f6f1a53e..84016d598 100644
--- a/src/components/bone-visibility.js
+++ b/src/components/bone-visibility.js
@@ -1,3 +1,8 @@
+/**
+ * Scales an object to near-zero if the object is invisible. Useful for bones representing avatar body parts.
+ * @namespace avatar
+ * @component bone-visibility
+ */
 AFRAME.registerComponent("bone-visibility", {
   tick() {
     const { visible } = this.el.object3D;
diff --git a/src/components/cardboard-controls.js b/src/components/cardboard-controls.js
index 766fda015..792fa1bd0 100644
--- a/src/components/cardboard-controls.js
+++ b/src/components/cardboard-controls.js
@@ -1,5 +1,10 @@
 const CARDBOARD_BUTTON_GAMEPAD_ID = "Cardboard Button";
 
+/**
+ * Polls the Gamepad API for Cardboard Button input and emits cardboardbutton events.
+ * @namespace user-input
+ * @component cardboard-controls
+ */
 module.exports = AFRAME.registerComponent("cardboard-controls", {
   init: function() {
     this.buttons = {};
diff --git a/src/components/character-controller.js b/src/components/character-controller.js
index 2b86ff0a3..a079671e2 100644
--- a/src/components/character-controller.js
+++ b/src/components/character-controller.js
@@ -2,7 +2,12 @@ const CLAMP_VELOCITY = 0.01;
 const MAX_DELTA = 0.2;
 const EPS = 10e-6;
 
-// Does not have any type of collisions yet.
+/**
+ * Avatar movement controller that listens to move, rotate and teleportation events and moves the avatar accordingly.
+ * The controller accounts for playspace offset and orientation and depends on the nav mesh system for translation.
+ * @namespace avatar
+ * @component character-controller
+ */
 AFRAME.registerComponent("character-controller", {
   schema: {
     groundAcc: { default: 5.5 },
@@ -136,7 +141,8 @@ AFRAME.registerComponent("character-controller", {
       // Reapply playspace (player rig) translation
       root.applyMatrix(trans);
 
-      // TODO: the above matrix trnsfomraitons introduce some floating point erros in scale, this reverts them to avoid spamming network with fake scale updates
+      // TODO: the above matrix trnsfomraitons introduce some floating point errors in scale, this reverts them to
+      // avoid spamming network with fake scale updates
       root.scale.copy(startScale);
 
       this.pendingSnapRotationMatrix.identity(); // Revert to identity
diff --git a/src/components/controls-shape-offset.js b/src/components/controls-shape-offset.js
index 7f47c498b..d234b971a 100644
--- a/src/components/controls-shape-offset.js
+++ b/src/components/controls-shape-offset.js
@@ -1,5 +1,10 @@
 import { CONTROLLER_OFFSETS } from "./hand-controls2.js";
 
+/**
+ * Sets the offset of the aframe-physics shape on this entity based on the current VR controller type
+ * @namespace user-input
+ * @component controls-shape-offset
+ */
 AFRAME.registerComponent("controls-shape-offset", {
   schema: {
     additionalOffset: { type: "vec3", default: { x: 0, y: -0.03, z: -0.04 } }
diff --git a/src/components/css-class.js b/src/components/css-class.js
index 1528ed4d4..77882e9bc 100644
--- a/src/components/css-class.js
+++ b/src/components/css-class.js
@@ -1,3 +1,7 @@
+/**
+ * Sets the CSS class on an entity.
+ * @component css-class
+ */
 AFRAME.registerComponent("css-class", {
   schema: {
     type: "string"
diff --git a/src/components/cursor-controller.js b/src/components/cursor-controller.js
index 7ae7aa529..3f81d7ea0 100644
--- a/src/components/cursor-controller.js
+++ b/src/components/cursor-controller.js
@@ -4,6 +4,11 @@ const TARGET_TYPE_UI = 4;
 const TARGET_TYPE_INTERACTABLE_OR_UI = TARGET_TYPE_INTERACTABLE | TARGET_TYPE_UI;
 const virtualJoystickCutoff = 0.8;
 
+/**
+ * Controls virtual cursor behavior in various modalities to affect teleportation, interatables and UI.
+ * @namespace user-input
+ * @component cursor-controller
+ */
 AFRAME.registerComponent("cursor-controller", {
   dependencies: ["raycaster", "line"],
   schema: {
diff --git a/src/components/duck.js b/src/components/duck.js
index 591729420..2b18f32c5 100644
--- a/src/components/duck.js
+++ b/src/components/duck.js
@@ -1,4 +1,8 @@
 /* global CANNON */
+/**
+ * Floats a duck based on its scale.
+ * @component duck
+ */
 AFRAME.registerComponent("duck", {
   schema: {
     initialForce: { default: 0 },
diff --git a/src/components/event-repeater.js b/src/components/event-repeater.js
index e5e5ffd19..100611325 100644
--- a/src/components/event-repeater.js
+++ b/src/components/event-repeater.js
@@ -1,3 +1,7 @@
+/**
+ * Listens to events from an event source and re-emits them on this entity
+ * @component event-repeater
+ */
 AFRAME.registerComponent("event-repeater", {
   schema: {
     eventSource: { type: "selector" },
diff --git a/src/components/freeze-controller.js b/src/components/freeze-controller.js
index 3cb64d76d..b7305ea72 100644
--- a/src/components/freeze-controller.js
+++ b/src/components/freeze-controller.js
@@ -1,3 +1,8 @@
+/**
+ * Toggles freezing of network traffic on the given event.
+ * @namespace network
+ * @component freeze-controller
+ */
 AFRAME.registerComponent("freeze-controller", {
   schema: {
     toggleEvent: { type: "string" }
diff --git a/src/components/gltf-bundle.js b/src/components/gltf-bundle.js
index ba6f7b3dc..72163ec54 100644
--- a/src/components/gltf-bundle.js
+++ b/src/components/gltf-bundle.js
@@ -1,3 +1,8 @@
+/**
+ * Instantiates GLTF models as specified in a bundle JSON.
+ * @namespace gltf
+ * @component gltf-bundle
+ */
 AFRAME.registerComponent("gltf-bundle", {
   schema: {
     src: { default: "" }
diff --git a/src/components/gltf-model-plus.js b/src/components/gltf-model-plus.js
index cc8032351..0d9d55417 100644
--- a/src/components/gltf-model-plus.js
+++ b/src/components/gltf-model-plus.js
@@ -194,6 +194,12 @@ function cachedLoadGLTF(src, preferredTechnique, onProgress) {
   });
 }
 
+/**
+ * Loads a GLTF model, optionally recursively "inflates" the child nodes of a model into a-entities and sets 
+ * whitelisted components on them if defined in the node's extras.
+ * @namespace gltf
+ * @component gltf-model-plus
+ */
 AFRAME.registerComponent("gltf-model-plus", {
   schema: {
     src: { type: "string" },
diff --git a/src/components/hand-controls2.js b/src/components/hand-controls2.js
index d99d5fc06..961790fea 100644
--- a/src/components/hand-controls2.js
+++ b/src/components/hand-controls2.js
@@ -28,6 +28,11 @@ export const CONTROLLER_OFFSETS = {
   "gearvr-controls": new THREE.Matrix4()
 };
 
+/**
+ * Converts events from various 6DoF and 3DoF controllers into hand-pose events.
+ * @namespace user-input
+ * @component hand-controls2
+ */
 AFRAME.registerComponent("hand-controls2", {
   schema: { default: "left" },
 
diff --git a/src/components/hand-poses.js b/src/components/hand-poses.js
index 7a0f9a4d2..98c1282cb 100644
--- a/src/components/hand-poses.js
+++ b/src/components/hand-poses.js
@@ -11,6 +11,11 @@ const POSES = {
 
 const NETWORK_POSES = ["allOpen", "thumbDown", "indexDown", "mrpDown", "thumbsUp", "point", "allGrip", "pinch"];
 
+/**
+ * Animates between poses based on networked pose state using an animation mixer.
+ * @namespace avatar
+ * @component hand-pose
+ */
 AFRAME.registerComponent("hand-pose", {
   multiple: true,
 
@@ -66,6 +71,11 @@ AFRAME.registerComponent("hand-pose", {
   }
 });
 
+/**
+ * Sets the networked hand pose state based on hand-pose events.
+ * @namespace avatar
+ * @component hand-pose-controller
+ */
 AFRAME.registerComponent("hand-pose-controller", {
   multiple: true,
   schema: {
diff --git a/src/components/haptic-feedback.js b/src/components/haptic-feedback.js
index 9a0a2337d..72ce54ad0 100644
--- a/src/components/haptic-feedback.js
+++ b/src/components/haptic-feedback.js
@@ -4,6 +4,11 @@ const strengthForIntensity = {
   high: 1
 };
 
+/**
+ * Listens for haptic events and actuates hardware controllers accordingly
+ * @namespace user-input
+ * @component haptic-feedback
+ */
 AFRAME.registerComponent("haptic-feedback", {
   schema: {
     hapticEventName: { default: "haptic_pulse" }
diff --git a/src/components/hide-when-quality.js b/src/components/hide-when-quality.js
index 93e238d61..612f83435 100644
--- a/src/components/hide-when-quality.js
+++ b/src/components/hide-when-quality.js
@@ -1,3 +1,7 @@
+/**
+ * Hides entities based on the scene's quality mode
+ * @component hide-when-quality
+ */
 AFRAME.registerComponent("hide-when-quality", {
   schema: { type: "string", default: "low" },
 
diff --git a/src/components/hud-controller.js b/src/components/hud-controller.js
index 2fac822d8..1f94a319b 100644
--- a/src/components/hud-controller.js
+++ b/src/components/hud-controller.js
@@ -8,6 +8,8 @@ function deltaAngle(a, b) {
 
 /**
  * Positions the HUD and toggles app mode based on where the user is looking
+ * @namespace ui
+ * @component hud-controller
  */
 AFRAME.registerComponent("hud-controller", {
   schema: {
diff --git a/src/components/icon-button.js b/src/components/icon-button.js
index 88f5e7303..0f0e21a1d 100644
--- a/src/components/icon-button.js
+++ b/src/components/icon-button.js
@@ -1,3 +1,8 @@
+/**
+ * A button with an image, tooltip, hover states and haptics.
+ * @namespace ui
+ * @component icon-button
+ */
 AFRAME.registerComponent("icon-button", {
   schema: {
     image: { type: "string" },
diff --git a/src/components/ik-controller.js b/src/components/ik-controller.js
index 23f2dbf79..3b2f3026a 100644
--- a/src/components/ik-controller.js
+++ b/src/components/ik-controller.js
@@ -1,4 +1,9 @@
 const { Vector3, Quaternion, Matrix4, Euler } = THREE;
+/**
+ * Provides access to the end effectors for IK.
+ * @namespace avatar
+ * @component ik-root
+ */
 AFRAME.registerComponent("ik-root", {
   schema: {
     camera: { type: "string", default: ".camera" },
@@ -27,6 +32,11 @@ function findIKRoot(entity) {
   return entity && entity.components["ik-root"];
 }
 
+/**
+ * Performs IK on a hip-rooted skeleton to align the hip, head and hands with camera and controller inputs.
+ * @namespace avatar
+ * @component ik-controller
+ */
 AFRAME.registerComponent("ik-controller", {
   schema: {
     leftEye: { type: "string", default: ".LeftEye" },
@@ -150,7 +160,8 @@ AFRAME.registerComponent("ik-controller", {
     // Compute the head position such that the hmd position would be in line with the middleEye
     headTransform.multiplyMatrices(cameraForward, invMiddleEyeToHead);
 
-    // Then position the hips such that the head is aligned with headTransform (which positions middleEye in line with the hmd)
+    // Then position the hips such that the head is aligned with headTransform
+    // (which positions middleEye in line with the hmd)
     hips.object3D.position.setFromMatrixPosition(headTransform).add(invHipsToHeadVector);
 
     // Animate the hip rotation to follow the Y rotation of the camera with some damping.
@@ -165,7 +176,8 @@ AFRAME.registerComponent("ik-controller", {
       this.data.rotationSpeed * dt / 1000
     );
 
-    // Take the head orientation computed from the hmd, remove the Y rotation already applied to it by the hips, and apply it to the head
+    // Take the head orientation computed from the hmd, remove the Y rotation already applied to it by the hips,
+    // and apply it to the head
     invHipsQuaternion.copy(hips.object3D.quaternion).inverse();
     head.object3D.quaternion.setFromRotationMatrix(headTransform).premultiply(invHipsQuaternion);
 
diff --git a/src/components/in-world-hud.js b/src/components/in-world-hud.js
index 2077b7ef2..a4fe8c965 100644
--- a/src/components/in-world-hud.js
+++ b/src/components/in-world-hud.js
@@ -1,3 +1,8 @@
+/**
+ * HUD panel for muting, freezing, and space bubble controls.
+ * @namespace ui
+ * @component in-world-hud
+ */
 AFRAME.registerComponent("in-world-hud", {
   schema: {
     haptic: { type: "selector" },
diff --git a/src/components/layers.js b/src/components/layers.js
index 2838cf754..1c96ad56e 100644
--- a/src/components/layers.js
+++ b/src/components/layers.js
@@ -3,6 +3,10 @@ export const Layers = {
   reflection: 3
 };
 
+/**
+ * Sets layer flags on the underlying Object3D
+ * @component layers
+ */
 AFRAME.registerComponent("layers", {
   schema: {
     reflection: { type: "boolean", default: false }
diff --git a/src/components/loop-animation.js b/src/components/loop-animation.js
index 09a9e9daf..76d3a0ec2 100644
--- a/src/components/loop-animation.js
+++ b/src/components/loop-animation.js
@@ -1,3 +1,7 @@
+/**
+ * Loops the given clip using this entity's animation mixer
+ * @component loop-animation
+ */
 AFRAME.registerComponent("loop-animation", {
   dependencies: ["animation-mixer"],
   schema: {
diff --git a/src/components/mute-mic.js b/src/components/mute-mic.js
index 00729ba19..9498d90a4 100644
--- a/src/components/mute-mic.js
+++ b/src/components/mute-mic.js
@@ -17,6 +17,11 @@ const unbindAllEvents = function(elements, events, f) {
   }
 };
 
+/**
+ * Toggles the microphone on the current network connection based on the given events.
+ * @namespace network
+ * @component mute-mic
+ */
 AFRAME.registerComponent("mute-mic", {
   schema: {
     eventSrc: { type: "selectorAll" },
diff --git a/src/components/nav-mesh-helper.js b/src/components/nav-mesh-helper.js
index 5c1be4ce9..571821b58 100644
--- a/src/components/nav-mesh-helper.js
+++ b/src/components/nav-mesh-helper.js
@@ -1,3 +1,7 @@
+/**
+ * Initializes teleport-controls when the environment bundle has loaded.
+ * @component nav-mesh-helper
+ */
 AFRAME.registerComponent("nav-mesh-helper", {
   schema: {
     teleportControls: { type: "selectorAll", default: "[teleport-controls]" }
diff --git a/src/components/networked-avatar.js b/src/components/networked-avatar.js
index 8820509cd..04a5fac8e 100644
--- a/src/components/networked-avatar.js
+++ b/src/components/networked-avatar.js
@@ -1,3 +1,8 @@
+/**
+ * Stores networked avatar state.
+ * @namespace avatar
+ * @component networked-avatar
+ */
 AFRAME.registerComponent("networked-avatar", {
   schema: {
     left_hand_pose: { default: 0 },
diff --git a/src/components/networked-counter.js b/src/components/networked-counter.js
index 39f76ddb7..be9725cf6 100644
--- a/src/components/networked-counter.js
+++ b/src/components/networked-counter.js
@@ -1,3 +1,8 @@
+/**
+ * Limits networked interactables to a maximum number at any given time
+ * @namespace network
+ * @component networked-counter
+ */
 AFRAME.registerComponent("networked-counter", {
   schema: {
     max: { default: 3 },
diff --git a/src/components/networked-video-player.js b/src/components/networked-video-player.js
index 189a43e39..eb4a93e0a 100644
--- a/src/components/networked-video-player.js
+++ b/src/components/networked-video-player.js
@@ -8,6 +8,11 @@ const nafConnected = function() {
   });
 };
 
+/**
+ * Instantiates and plays a network video stream, setting the video as the source material for this entity.
+ * @namespace network
+ * @component networked-video-player
+ */
 AFRAME.registerComponent("networked-video-player", {
   schema: {},
   async init() {
diff --git a/src/components/offset-relative-to.js b/src/components/offset-relative-to.js
index 393610224..3cd45b942 100644
--- a/src/components/offset-relative-to.js
+++ b/src/components/offset-relative-to.js
@@ -1,3 +1,7 @@
+/**
+ * Positions an entity relative to a given target when the given event is fired.
+ * @component offset-relative-to
+ */
 AFRAME.registerComponent("offset-relative-to", {
   schema: {
     target: {
diff --git a/src/components/player-info.js b/src/components/player-info.js
index b9455352a..a7e0812f8 100644
--- a/src/components/player-info.js
+++ b/src/components/player-info.js
@@ -1,3 +1,8 @@
+/**
+ * Sets player info state, including avatar choice and display name.
+ * @namespace avatar
+ * @component player-info
+ */
 AFRAME.registerComponent("player-info", {
   schema: {
     displayName: { type: "string" },
diff --git a/src/components/scene-shadow.js b/src/components/scene-shadow.js
index 14b2e23cc..6a367f2ab 100644
--- a/src/components/scene-shadow.js
+++ b/src/components/scene-shadow.js
@@ -1,4 +1,7 @@
-// For use in environment gltf bundles to set scene shadow properties.
+/**
+ * For use in environment gltf bundles to set scene shadow properties.
+ * @component scene-shadow
+ */
 AFRAME.registerComponent("scene-shadow", {
   schema: {
     type: {
diff --git a/src/components/spawn-controller.js b/src/components/spawn-controller.js
index 1daf01b75..908266af6 100644
--- a/src/components/spawn-controller.js
+++ b/src/components/spawn-controller.js
@@ -1,3 +1,8 @@
+/**
+ * Used on a player-rig to move the player to a random spawn point on entry.
+ * @namespace avatar
+ * @component spawn-controller
+ */
 AFRAME.registerComponent("spawn-controller", {
   schema: {
     target: { type: "selector" },
@@ -23,4 +28,8 @@ AFRAME.registerComponent("spawn-controller", {
   }
 });
 
+/**
+ * Marks an entity as a potential spawn point.
+ * @component spawn-point
+ */
 AFRAME.registerComponent("spawn-point", {});
diff --git a/src/components/super-networked-interactable.js b/src/components/super-networked-interactable.js
index 0d9fc26de..903302562 100644
--- a/src/components/super-networked-interactable.js
+++ b/src/components/super-networked-interactable.js
@@ -1,3 +1,8 @@
+/**
+ * Manages ownership and haptics on an interatable
+ * @namespace network
+ * @component super-networked-interactable
+ */
 AFRAME.registerComponent("super-networked-interactable", {
   schema: {
     mass: { default: 1 },
diff --git a/src/components/super-spawner.js b/src/components/super-spawner.js
index 7bd554f5a..083f81db7 100644
--- a/src/components/super-spawner.js
+++ b/src/components/super-spawner.js
@@ -1,3 +1,8 @@
+/**
+ * Spawns networked objects when grabbed.
+ * @namespace network
+ * @component super-spawner
+ */
 AFRAME.registerComponent("super-spawner", {
   schema: {
     template: { default: "" },
diff --git a/src/components/text-button.js b/src/components/text-button.js
index 2668694c0..67af3653d 100644
--- a/src/components/text-button.js
+++ b/src/components/text-button.js
@@ -1,3 +1,8 @@
+/**
+ * A button with text and haptics
+ * @namespace ui
+ * @component text-button
+ */
 AFRAME.registerComponent("text-button", {
   schema: {
     haptic: { type: "selector" },
diff --git a/src/components/virtual-gamepad-controls.js b/src/components/virtual-gamepad-controls.js
index 5b45d07cb..5da2c3c8e 100644
--- a/src/components/virtual-gamepad-controls.js
+++ b/src/components/virtual-gamepad-controls.js
@@ -1,6 +1,11 @@
 import nipplejs from "nipplejs";
 import styles from "./virtual-gamepad-controls.css";
 
+/**
+ * Instantiates 2D virtual gamepads and emits associated events.
+ * @namespace user-input
+ * @component virtual-gamepad-controls
+ */
 AFRAME.registerComponent("virtual-gamepad-controls", {
   schema: {},
 
diff --git a/src/components/visible-while-frozen.js b/src/components/visible-while-frozen.js
index 59448cb6b..4acff3d42 100644
--- a/src/components/visible-while-frozen.js
+++ b/src/components/visible-while-frozen.js
@@ -1,3 +1,8 @@
+/**
+ * Toggles the visibility of this entity when the scene is frozen.
+ * @namespace ui
+ * @component visible-while-frozen
+ */
 AFRAME.registerComponent("visible-while-frozen", {
   init() {
     this.onStateChange = evt => {
@@ -18,6 +23,11 @@ AFRAME.registerComponent("visible-while-frozen", {
   }
 });
 
+/**
+ * Toggles the interactivity of a UI entity while the scene is frozen.
+ * @namespace ui
+ * @component ui-class-while-frozen
+ */
 AFRAME.registerComponent("ui-class-while-frozen", {
   init() {
     this.onStateChange = evt => {
diff --git a/src/components/wasd-to-analog2d.js b/src/components/wasd-to-analog2d.js
index a86641623..a99babe7d 100644
--- a/src/components/wasd-to-analog2d.js
+++ b/src/components/wasd-to-analog2d.js
@@ -1,3 +1,8 @@
+/**
+ * Converts WASD keyboard inputs to simulated analog inputs.
+ * @namespace user-input
+ * @component wasd-to-analog2d
+ */
 AFRAME.registerComponent("wasd-to-analog2d", {
   schema: {
     analog2dOutputAction: { default: "wasd_analog2d" }
diff --git a/src/systems/app-mode.js b/src/systems/app-mode.js
index 49e8d361b..6954d3ad5 100644
--- a/src/systems/app-mode.js
+++ b/src/systems/app-mode.js
@@ -4,6 +4,7 @@ export const AppModes = Object.freeze({ DEFAULT: "default", HUD: "hud" });
 
 /**
  * Simple system for keeping track of a modal app state
+ * @system app-mode
  */
 AFRAME.registerSystem("app-mode", {
   init() {
@@ -20,6 +21,8 @@ AFRAME.registerSystem("app-mode", {
 
 /**
  * Toggle the isPlaying state of a component based on app mode
+ * @namespace app-mode
+ * @component app-mode-toggle-playing
  */
 AFRAME.registerComponent("app-mode-toggle-playing", {
   multiple: true,
@@ -44,6 +47,8 @@ AFRAME.registerComponent("app-mode-toggle-playing", {
 
 /**
  * Toggle a boolean property of a component based on app mode
+ * @namespace app-mode
+ * @component app-mode-toggle-attribute
  */
 AFRAME.registerComponent("app-mode-toggle-attribute", {
   multiple: true,
@@ -69,6 +74,8 @@ AFRAME.registerComponent("app-mode-toggle-attribute", {
 
 /**
  * Toggle aframe input mappings action set based on app mode
+ * @namespace app-mode
+ * @component app-mode-input-mappings
  */
 AFRAME.registerComponent("app-mode-input-mappings", {
   schema: {
@@ -91,6 +98,8 @@ AFRAME.registerComponent("app-mode-input-mappings", {
 
 /**
  * Toggle visibility of an entity based on if the user is in vr mode or not
+ * @namespace vr-mode
+ * @component vr-mode-toggle-visibility
  */
 AFRAME.registerComponent("vr-mode-toggle-visibility", {
   schema: {
@@ -120,6 +129,8 @@ AFRAME.registerComponent("vr-mode-toggle-visibility", {
 
 /**
  * Toggle the isPlaying state of a component based on app mode
+ * @namespace vr-mode
+ * @component vr-mode-toggle-playing
  */
 AFRAME.registerComponent("vr-mode-toggle-playing", {
   multiple: true,
diff --git a/src/systems/personal-space-bubble.js b/src/systems/personal-space-bubble.js
index d89a59cae..0ba3cee5d 100644
--- a/src/systems/personal-space-bubble.js
+++ b/src/systems/personal-space-bubble.js
@@ -1,6 +1,12 @@
 const invaderPos = new AFRAME.THREE.Vector3();
 const bubblePos = new AFRAME.THREE.Vector3();
 
+/**
+ * Iterates through bubbles and invaders on every tick and sets invader state accordingly.
+ * testing multiline things
+ * @namespace avatar/personal-space-bubble
+ * @system personal-space-bubble
+ */
 AFRAME.registerSystem("personal-space-bubble", {
   schema: {
     debug: { default: false },
@@ -110,6 +116,11 @@ function createSphereGizmo(radius) {
 }
 
 // TODO: we need to come up with a more generic way of doing this as this is very specific to our avatars.
+/**
+ * Specifies a mesh associated with an invader.
+ * @namespace avatar/personal-space-bubble
+ * @component space-invader-mesh
+ */
 AFRAME.registerComponent("space-invader-mesh", {
   schema: {
     meshSelector: { type: "string" }
@@ -128,6 +139,11 @@ function findInvaderMesh(entity) {
 
 const DEBUG_OBJ = "psb-debug";
 
+/**
+ * Represents an entity that can invade a personal space bubble
+ * @namespace avatar/personal-space-bubble
+ * @component personal-space-invader
+ */
 AFRAME.registerComponent("personal-space-invader", {
   schema: {
     radius: { type: "number", default: 0.1 },
@@ -177,6 +193,11 @@ AFRAME.registerComponent("personal-space-invader", {
   }
 });
 
+/**
+ * Represents a personal space bubble on an entity.
+ * @namespace avatar/personal-space-bubble
+ * @component personal-space-bubble
+ */
 AFRAME.registerComponent("personal-space-bubble", {
   schema: {
     radius: { type: "number", default: 0.8 },
-- 
GitLab