Added linting rules + updated docs

This commit is contained in:
Prozilla 2023-08-06 13:35:21 +02:00
parent 6f990ba66a
commit e223747795
No known key found for this signature in database
GPG key ID: 5858DFE71CAF31EE
35 changed files with 298 additions and 99 deletions

View file

@ -33,6 +33,10 @@
2. Run `npm run deploy` - This will create a new build by running the redeploy script, add a CNAME pointing to your domain and then push the build folder to a branch called `gh-pages`.
3. Configure your GitHub Pages to deploy the `gh-pages` branch to your domain.
Once the initial setup is complete, you can simply run `npm run deploy` and your website will be built and deployed to GitHub Pages.
> Note: When the deployment process is complete, you won't see the changes reflected on your website until a few moments later. This is because GitHub Pages needs to run its own build step before the website updates. You can view details about this process in the Actions tab on GitHub.
### Structure
- [src](../src) directory

View file

@ -4,6 +4,8 @@
Most code for features can be found in the [features](../../src/features) directory. This directory is a library that is mostly used by files in the [components](../../src/components) and [hooks](../../src/hooks) directory.
> Note: Inside this part of the docs you will often see mentions of directories like `features` or `components`. These paths are relative to the `src` directory. The respective paths relative to the root of this project are `src/features` and `src/components`.
## Table of Contents
- [Applications](applications/README.md)

114
package-lock.json generated
View file

@ -27,6 +27,7 @@
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"eslint-plugin-jsdoc": "^46.4.6",
"gh-pages": "^5.0.0"
}
},
@ -2315,6 +2316,20 @@
"postcss-selector-parser": "^6.0.10"
}
},
"node_modules/@es-joy/jsdoccomment": {
"version": "0.40.1",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz",
"integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==",
"dev": true,
"dependencies": {
"comment-parser": "1.4.0",
"esquery": "^1.5.0",
"jsdoc-type-pratt-parser": "~4.0.0"
},
"engines": {
"node": ">=16"
}
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@ -5154,6 +5169,15 @@
"node": ">= 8"
}
},
"node_modules/are-docs-informative": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
"integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
"dev": true,
"engines": {
"node": ">=14"
}
},
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
@ -6136,6 +6160,15 @@
"node": ">= 12"
}
},
"node_modules/comment-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz",
"integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==",
"dev": true,
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/common-path-prefix": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz",
@ -7556,6 +7589,41 @@
}
}
},
"node_modules/eslint-plugin-jsdoc": {
"version": "46.4.6",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz",
"integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==",
"dev": true,
"dependencies": {
"@es-joy/jsdoccomment": "~0.40.1",
"are-docs-informative": "^0.0.2",
"comment-parser": "1.4.0",
"debug": "^4.3.4",
"escape-string-regexp": "^4.0.0",
"esquery": "^1.5.0",
"is-builtin-module": "^3.2.1",
"semver": "^7.5.4",
"spdx-expression-parse": "^3.0.1"
},
"engines": {
"node": ">=16"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0"
}
},
"node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-plugin-jsx-a11y": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz",
@ -9517,6 +9585,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-builtin-module": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
"dev": true,
"dependencies": {
"builtin-modules": "^3.3.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@ -11923,6 +12006,15 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsdoc-type-pratt-parser": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
"integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
"dev": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/jsdom": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
@ -15735,6 +15827,28 @@
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"deprecated": "Please use @jridgewell/sourcemap-codec instead"
},
"node_modules/spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
"dev": true
},
"node_modules/spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/spdx-license-ids": {
"version": "3.0.13",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
"integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
"dev": true
},
"node_modules/spdy": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",

View file

@ -35,7 +35,37 @@
"extends": [
"react-app",
"react-app/jest"
]
],
"plugins": [
"jsdoc"
],
"rules": {
"indent": ["error", "tab", { "SwitchCase": 1 }],
"jsdoc/no-undefined-types": "warn",
"jsdoc/require-param": "warn",
"jsdoc/check-tag-names": "warn",
"jsdoc/check-types": ["warn", {}],
"jsdoc/check-values": "warn",
"jsdoc/empty-tags": "warn",
"jsdoc/check-param-names": "warn",
"jsdoc/check-property-names": "warn",
"jsdoc/check-access": "warn",
"jsdoc/check-alignment": "warn",
"jsdoc/multiline-blocks": "warn",
"jsdoc/no-blank-block-descriptions": "warn",
"jsdoc/require-hyphen-before-param-description": "warn"
},
"settings": {
"jsdoc": {
"preferredTypes": {
"Object":"object",
"object.<>":"Object<>",
"Object.<>":"Object<>",
"object<>":"Object<>"
}
}
}
},
"browserslist": {
"production": [
@ -51,6 +81,7 @@
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"eslint-plugin-jsdoc": "^46.4.6",
"gh-pages": "^5.0.0"
}
}

View file

@ -6,8 +6,8 @@ import styles from "./HeaderMenu.module.css";
/**
* @param {Object} props
* @param {Object<String, Object<String, Function>>} props.options
* @param {Object<String, Object<String, Array<String>>>} props.shortcuts
* @param {Object<String, Object<string, function>>} props.options
* @param {Object<String, Object<string, string[]>>} props.shortcuts
*/
export function HeaderMenu({ options, shortcuts }) {
const [activeKeys, setActiveKeys] = useState([]);

View file

@ -8,7 +8,7 @@ import { VirtualFile } from "../../../features/virtual-drive/virtual-file.js";
import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.js";
/**
* @param {Object} props
* @param {object} props
* @param {VirtualFile} props.file
*/
function FilePreview({ file }) {

View file

@ -4,10 +4,9 @@ import { useWindowsManager } from "../../../hooks/windows/WindowsManagerContext.
import styles from "./MediaViewer.module.css";
/**
*
* @param {Object} props
* @param {object} props
* @param {VirtualFile} props.file
* @returns
* @param {Function} props.close
*/
export function MediaViewer({ file, close }) {
const windowsManager = useWindowsManager();

View file

@ -9,7 +9,7 @@ import { SettingsManager } from "../../../features/settings/settings.js";
import { VirtualRoot } from "../../../features/virtual-drive/virtual-root.js";
/**
* @param {Object} props
* @param {object} props
* @param {VirtualRoot} props.virtualRoot
* @param {SettingsManager} props.settingsManager
*/

View file

@ -7,8 +7,8 @@ const USERNAME = "user";
const HOSTNAME = "prozilla-os";
/**
* @param {Object} props
* @param {String} props.text
* @param {object} props
* @param {string} props.text
*/
function OutputLine({ text }) {
return (
@ -17,9 +17,9 @@ function OutputLine({ text }) {
}
/**
* @param {Object} props
* @param {String} props.value
* @param {String} props.prefix
* @param {object} props
* @param {string} props.value
* @param {string} props.prefix
* @param {Function} props.onChange
* @param {Function} props.onKeyUp
* @param {Function} props.onKeyDown

View file

@ -9,8 +9,11 @@ const defaultZoom = 16;
const zoomSpeed = 4;
/**
* @param {Object} props
* @param {object} props
* @param {VirtualFile} props.file
* @param {Function} props.setTitle
* @param {Function} props.close
* @param {string} props.mode
*/
export function TextEditor({ file, setTitle, close, mode }) {
const [currentFile, setCurrentFile] = useState(file);

View file

@ -6,7 +6,6 @@ import ApplicationsManager from "../../features/applications/applications.js";
import { useWindows } from "../../hooks/windows/WindowsContext.js";
import { useWindowsManager } from "../../hooks/windows/WindowsManagerContext.js";
import { ReactSVG } from "react-svg";
// eslint-disable-next-line no-unused-vars
import Application from "../../features/applications/application.js";
import { HomeMenu } from "./menus/HomeMenu.jsx";
import OutsideClickListener from "../../hooks/utils/outsideClick.js";
@ -18,7 +17,7 @@ import { Calendar } from "./indicators/Calendar.jsx";
import { useScrollWithShadow } from "../../hooks/utils/scrollWithShadows.js";
/**
* @param {Object} props
* @param {object} props
* @param {Application} props.app
*/
function AppButton({ app }) {
@ -96,7 +95,7 @@ export function Taskbar() {
const search = (query) => {
updateShowSearch(true);
}
};
return (
<div className={styles["Task-bar"]}>

View file

@ -9,6 +9,12 @@ import { closeTab } from "../../../features/utils/browser.js";
import { useKeyboardListener } from "../../../hooks/utils/keyboard.js";
import { useVirtualRoot } from "../../../hooks/virtual-drive/VirtualRootContext.js";
/**
* @param {object} props
* @param {boolean} props.active
* @param {Function} props.setActive
* @param {Function} props.search
*/
export function HomeMenu({ active, setActive, search }) {
const windowsManager = useWindowsManager();
const virtualRoot = useVirtualRoot();

View file

@ -6,6 +6,14 @@ import { ReactSVG } from "react-svg";
import { useEffect } from "react";
import { useState } from "react";
/**
* @param {object} props
* @param {boolean} props.active
* @param {Function} props.setActive
* @param {string} props.searchQuery
* @param {Function} props.setSearchQuery
* @param {import("react").ElementRef} props.inputRef
*/
export function SearchMenu({ active, setActive, searchQuery, setSearchQuery, inputRef }) {
const windowsManager = useWindowsManager();
const [apps, setApps] = useState(null);

View file

@ -4,9 +4,10 @@ import OutsideClickListener from "../../hooks/utils/outsideClick.js";
import { formatShortcut } from "../../features/utils/string.js";
/**
* @param {Object} props
* @param {String} props.label
* @param {Object.<string, Function>} props.options
* @param {object} props
* @param {string} props.label
* @param {Object<string, Function>} props.options
* @param {Object<string, string[]>} props.shortcuts
*/
export function DropdownButton({ label, options, shortcuts }) {
const [open, setOpen] = useState(false);
@ -33,7 +34,7 @@ export function DropdownButton({ label, options, shortcuts }) {
)}
</div>)
: null
}
}
</div>
</OutsideClickListener>
)

View file

@ -12,13 +12,14 @@ import Application from "../../features/applications/application.js";
import Vector2 from "../../features/math/vector2.js";
/**
* @param {Object} props
* @param {String} props.id
* @param {object} props
* @param {string} props.id
* @param {Application} props.app
* @param {Vector2} props.size
* @param {Vector2} props.position
* @param {boolean} props.focused
* @param {Function} props.onInteract
* @param {object} props.options
*/
export function Window({ id, app, size, position, focused = false, onInteract, options }) {
const windowsManager = useWindowsManager();
@ -28,18 +29,18 @@ export function Window({ id, app, size, position, focused = false, onInteract, o
const [minimized, setMinimized] = useState(false);
const [screenWidth, setScreenWidth] = useState(100);
const [screenHeight, setScreenHeight] = useState(100);
const [screenHeight, setScreenHeight] = useState(100);
const [title, setTitle] = useState(app.name);
useEffect(() => {
const resizeObserver = new ResizeObserver((event) => {
setScreenWidth(event[0].contentBoxSize[0].inlineSize);
setScreenHeight(event[0].contentBoxSize[0].blockSize);
});
useEffect(() => {
const resizeObserver = new ResizeObserver((event) => {
setScreenWidth(event[0].contentBoxSize[0].inlineSize);
setScreenHeight(event[0].contentBoxSize[0].blockSize);
});
resizeObserver.observe(document.getElementById("root"));
});
resizeObserver.observe(document.getElementById("root"));
});
const close = () => {
windowsManager.close(id);

View file

@ -1,9 +1,11 @@
import React from "react";
export default class Application {
/**
* @param {String} name
* @param {String} id
* @param {string} name
* @param {string} id
* @param {React.ReactElement} windowContent
* @param {Object|null} windowOptions - Default window options
* @param {object | null} windowOptions - Default window options
*/
constructor(name, id, windowContent, windowOptions) {
Object.assign(this, { name, id, windowContent, windowOptions });

View file

@ -22,7 +22,7 @@ export default class ApplicationsManager {
]
/**
* @param {String} id
* @param {string} id
* @returns {Application}
*/
static getApplication(id) {
@ -40,7 +40,7 @@ export default class ApplicationsManager {
/**
* Get the application associated with a file extension
* @param {String} fileExtension
* @param {string} fileExtension
* @returns {Application}
*/
static getFileApplication(fileExtension) {

View file

@ -1,6 +1,6 @@
export class Command {
/**
* @param {String} name
* @param {string} name
* @param {Function} execute
*/
constructor(name, execute) {

View file

@ -1,3 +1,8 @@
/**
* @param {number} min
* @param {number} max
* @returns {number}
*/
export function randomRange(min, max) {
return Math.random() * (max - min) + min;
}

View file

@ -13,7 +13,7 @@ export class Settings {
/**
* @param {VirtualRoot} virtualRoot
* @param {String} path
* @param {string} path
*/
constructor(virtualRoot, path) {
this.#virtualRoot = virtualRoot;
@ -63,7 +63,7 @@ export class Settings {
/**
* Checks if xml doc is missing
* @returns {Promise<Boolean>}
* @returns {Promise<boolean>}
*/
async isMissingXmlDoc() {
if (this.xmlDoc == null)
@ -74,14 +74,14 @@ export class Settings {
/**
* @callback valueCallback
* @param {String} value
* @param {string} value
*/
/**
* Gets a value by a given key if it exists or calls a callback function whenever the value changes
* @param {String} key
* @param {string} key
* @param {valueCallback} callback
* @returns {Promise<String|null>}
* @returns {Promise<string | null>}
*/
async get(key, callback) {
if (await this.isMissingXmlDoc())
@ -107,8 +107,8 @@ export class Settings {
}
/**
* @param {String} key
* @param {String} value
* @param {string} key
* @param {string} value
*/
async set(key, value) {
if (await this.isMissingXmlDoc())
@ -123,14 +123,14 @@ export class Settings {
export class SettingsManager {
/**
* @type {Object<String, String>}
* @type {Object<string, string>}
*/
static VIRTUAL_PATHS = {
"desktop": "~/.config/desktop.xml"
};
/**
* @type {Object<String, Settings>}
* @type {Object<string, Settings>}
*/
#pathToSettings = {};
@ -151,7 +151,7 @@ export class SettingsManager {
}
/**
* @param {String} path
* @param {string} path
* @returns {Settings}
*/
get(path) {

View file

@ -1,3 +1,7 @@
/**
* @param {*} item
* @param {*[]} array
*/
export function removeFromArray(item, array) {
const index = array.indexOf(item);
if (index !== -1) {

View file

@ -1,17 +1,17 @@
export class EventEmitter {
/**
* @type {Object<String, String>}
* @type {Object<string, string>}
*/
static EVENT_NAMES = {};
/**
* @type {Object<String, Array<Function>>}
* @type {Object<string, Array<Function>>}
*/
#events = {}
/**
* Add event listener for an event
* @param {EVENT_NAMES} eventName
* @param {EventEmitter.EVENT_NAMES} eventName
* @param {Function} callback
*/
on(eventName, callback) {
@ -23,7 +23,7 @@ export class EventEmitter {
/**
* Remove event listener for an event
* @param {EVENT_NAMES} eventName
* @param {string} eventName
* @param {Function} callback
*/
off(eventName, callback) {
@ -36,7 +36,7 @@ export class EventEmitter {
/**
* Dispatch event
* @param {EVENT_NAMES} eventName
* @param {string} eventName
* @param {*} data
*/
emit(eventName, data) {

View file

@ -1,3 +1,7 @@
/**
* @param {string[]} shortcut
* @returns {string}
*/
export function formatShortcut(shortcut) {
const specialKeys = [];
const singleKeys = [];

View file

@ -4,7 +4,7 @@ import { VirtualRoot } from "./virtual-root.js";
export class VirtualBase extends EventEmitter {
/**
* @param {String} name
* @param {string} name
*/
constructor(name) {
super();
@ -16,7 +16,7 @@ export class VirtualBase extends EventEmitter {
}
/**
* @param {String} name
* @param {string} name
* @returns {VirtualBase}
*/
setName(name) {
@ -26,7 +26,7 @@ export class VirtualBase extends EventEmitter {
}
/**
* @param {String} alias
* @param {string} alias
* @returns {ThisType}
*/
setAlias(alias) {

View file

@ -13,8 +13,8 @@ export class VirtualFile extends VirtualBase {
};
/**
* @param {String} name
* @param {String=} extension
* @param {string} name
* @param {string=} extension
*/
constructor(name, extension) {
super(name);
@ -22,7 +22,7 @@ export class VirtualFile extends VirtualBase {
}
/**
* @param {String} alias
* @param {string} alias
* @returns {VirtualFile}
*/
setAlias(alias) {
@ -31,7 +31,7 @@ export class VirtualFile extends VirtualBase {
/**
* Sets the source of this file and removes the content
* @param {String} source
* @param {string} source
* @returns {VirtualFile}
*/
setSource(source) {
@ -46,7 +46,7 @@ export class VirtualFile extends VirtualBase {
/**
* Sets the content of this file and removes the source
* @param {String|*} content
* @param {string | *} content
* @returns {VirtualFile}
*/
setContent(content) {
@ -67,7 +67,7 @@ export class VirtualFile extends VirtualBase {
}
/**
* @return {Promise<String|null>}
* @returns {Promise<string | null>}
*/
async read() {
if (this.content != null)

View file

@ -12,8 +12,8 @@ export class VirtualFolder extends VirtualBase {
}
/**
* @param {String} name
* @param {Number} type
* @param {string} name
* @param {number} type
*/
constructor(name, type) {
super(name);
@ -23,7 +23,7 @@ export class VirtualFolder extends VirtualBase {
}
/**
* @param {String} alias
* @param {string} alias
* @returns {VirtualFolder}
*/
setAlias(alias) {
@ -32,8 +32,8 @@ export class VirtualFolder extends VirtualBase {
/**
* Returns true if this folder contains a file matching a name and extension
* @param {String} name
* @param {String} extension
* @param {string} name
* @param {string} extension
* @returns {VirtualFile}
*/
hasFile(name, extension) {
@ -42,7 +42,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Returns true if this folder contains a folder matching a name
* @param {String} name
* @param {string} name
* @returns {boolean}
*/
hasFolder(name) {
@ -51,8 +51,8 @@ export class VirtualFolder extends VirtualBase {
/**
* Finds and returns a file inside this folder matching a name and extension
* @param {String} name
* @param {String} extension
* @param {string} name
* @param {string} extension
* @returns {VirtualFile}
*/
findFile(name, extension) {
@ -69,7 +69,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Finds and returns a folder inside this folder matching a name
* @param {String} name
* @param {string} name
* @returns {VirtualFolder}
*/
findSubFolder(name) {
@ -91,8 +91,8 @@ export class VirtualFolder extends VirtualBase {
/**
* Creates a file with a name and extension
* @param {String} name
* @param {String} extension
* @param {string} name
* @param {string} extension
* @param {createFileCallback} callback
* @returns {VirtualFolder}
*/
@ -107,9 +107,9 @@ export class VirtualFolder extends VirtualBase {
/**
* Creates files based on an array of objects with file names and extensions
* @param {Object[]} files
* @param {String} Object[].name
* @param {String} Object[].extension
* @param {object[]} files
* @param {string} files.name
* @param {string} files.extension
* @returns {VirtualFolder}
*/
createFiles(files) {
@ -127,7 +127,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Creates a folder with a name
* @param {String} name
* @param {string} name
* @returns {VirtualFolder}
* @param {createFolderCallback} callback
*/
@ -142,7 +142,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Creates folders based on an array of folder names
* @param {String[]} folders
* @param {string[]} folders
* @returns {VirtualFolder}
*/
createFolders(folders) {
@ -156,7 +156,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Adds a file at a destination
* @deprecated
* @param {String} destination
* @param {string} destination
*/
addFile(destination) {
const folderNames = destination.split("/");
@ -182,7 +182,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Adds a folder at a destination
* @deprecated
* @param {String} destination
* @param {string} destination
*/
addFolder(destination) {
if (destination.endsWith("/"))
@ -218,7 +218,7 @@ export class VirtualFolder extends VirtualBase {
/**
* Returns the file or folder at a relative path or null if it doesn't exist
* @param {String} relativePath
* @param {string} relativePath
* @returns {VirtualFile|VirtualFolder|null}
*/
navigate(relativePath) {

View file

@ -170,7 +170,7 @@ export class VirtualRoot extends VirtualFolder {
/**
* Adds a shortcut to a file or folder
* @param {String} name
* @param {string} name
* @param {VirtualFile|VirtualFolder} destination
* @returns {VirtualRoot}
*/

View file

@ -11,9 +11,9 @@ export default class WindowsManager {
}
/**
* @param {String} appId
* @param {Object|null} options
* @returns {Object}
* @param {string} appId
* @param {object | null} options
* @returns {object}
*/
open(appId, options) {
const app = ApplicationsManager.getApplication(appId);
@ -45,7 +45,7 @@ export default class WindowsManager {
/**
* @param {VirtualFile} file
* @returns {Object}
* @returns {object}
*/
openFile(file) {
const app = ApplicationsManager.getFileApplication(file.extension);
@ -54,7 +54,7 @@ export default class WindowsManager {
}
/**
* @param {String} windowId
* @param {string} windowId
*/
close(windowId) {
windowId = windowId.toString();
@ -72,7 +72,7 @@ export default class WindowsManager {
}
/**
* @param {Object} window
* @param {string} windowId
*/
focus(windowId) {
windowId = windowId.toString();
@ -89,8 +89,8 @@ export default class WindowsManager {
}
/**
* @param {String} appId
* @returns {Boolean}
* @param {string} appId
* @returns {boolean}
*/
isAppActive(appId) {
let active = false;

View file

@ -6,7 +6,9 @@ const SettingsContext = createContext();
/**
* Note: needs to be inside a virtual root provider
* @returns {React.Provider<SettingsManager>}
* @param props
* @param props.children
* @returns {import("react").Provider<SettingsManager>}
*/
export function SettingsProvider({ children }) {
const virtualRoot = useVirtualRoot();

View file

@ -1,7 +1,7 @@
import { useEffect } from "react";
/**
* @param {Object} params
* @param {object} params
* @param {Function} params.onKeyDown
* @param {Function} params.onKeyUp
*/

View file

@ -2,15 +2,18 @@
* https://stackoverflow.com/a/42234988
*/
import React, { useRef, useEffect } from "react";
import { useRef, useEffect } from "react";
/**
* Hook that alerts clicks outside of the passed ref
* @param {import("react").ElementRef} ref
* @param {Function} callback
*/
function useOutsideClickListener(ref, callback) {
useEffect(() => {
/**
* Alert if clicked on outside of element
* @param event
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
@ -27,8 +30,9 @@ function useOutsideClickListener(ref, callback) {
}
/**
* @param {Object} props
* @param {object} props
* @param {Function} props.onOutsideClick
* @param {import("react").ElementType} props.children
*/
export default function OutsideClickListener({ onOutsideClick, children }) {
const wrapperRef = useRef(null);

View file

@ -7,16 +7,16 @@ import React, { useCallback, useEffect, useRef } from "react";
import { useState } from "react";
/**
* @param {Object} options
* @param {object} options
* @param {React.ElementRef} options.ref
* @param {Boolean=true} options.horizontal
* @param {Boolean=true} options.dynamicOffset
* @param {Number=1} options.dynamicOffsetFactor
* @param {Object} options.shadow
* @param {object} options.shadow
* @param {Number=8} options.shadow.offset
* @param {Number=5} options.shadow.blurRadius
* @param {Number=-5} options.shadow.spreadRadius
* @param {Object} options.shadow.color
* @param {object} options.shadow.color
* @param {Number=0} options.shadow.color.r
* @param {Number=0} options.shadow.color.g
* @param {Number=0} options.shadow.color.b

View file

@ -4,7 +4,9 @@ import { VirtualRoot } from "../../features/virtual-drive/virtual-root.js";
const VirtualRootContext = createContext();
/**
* @returns {React.Provider<VirtualRoot>}
* @param props
* @param props.children
* @returns {import("react").Provider<VirtualRoot>}
*/
export function VirtualRootProvider({ children }) {
const virtualRoot = new VirtualRoot().init();

View file

@ -3,7 +3,10 @@ import { createContext, useCallback, useContext, useState } from "react";
const WindowsContext = createContext();
/**
* @returns {React.Provider<any>}
* @param props
* @param props.children
* @param props.windowsManager
* @returns {import("react").Provider<any>}
*/
export function WindowsProvider({ children, windowsManager }) {
const [windows, setWindows] = useState([]);
@ -22,6 +25,9 @@ export function WindowsProvider({ children, windowsManager }) {
);
}
/**
* @returns {object[]}
*/
export function useWindows() {
return useContext(WindowsContext);
}

View file

@ -5,7 +5,9 @@ import { WindowsProvider } from "./WindowsContext.js";
const WindowsManagerContext = createContext();
/**
* @returns {React.Provider<any>}
* @param {object} props
* @param {import("react").ElementType} props.children
* @returns {import("react").Provider<any>}
*/
export function WindowsManagerProvider({ children }) {
const windowsManager = new WindowsManager();