diff --git a/dist/common/assets.d.ts b/dist/common/assets.d.ts deleted file mode 100644 index 93fced7..0000000 --- a/dist/common/assets.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Middleware } from './redux'; - -export declare function resolveAsset(name: string): string; -export declare const assetMiddleware: Middleware; diff --git a/dist/common/assets.js b/dist/common/assets.js deleted file mode 100644 index c6adab8..0000000 --- a/dist/common/assets.js +++ /dev/null @@ -1,25 +0,0 @@ -const c = [/v4shim/i], a = {}; -function l(t) { - return a[t] || t; -} -const f = (t) => (d) => (n) => { - const { type: i, payload: e } = n; - if (i === "asset/stylesheet") { - Byond.loadCss(e); - return; - } - if (i === "asset/mappings") { - for (const s of Object.keys(e)) { - if (c.some((p) => p.test(s))) - continue; - const o = e[s], r = s.split(".").pop(); - a[s] = o, r === "css" && Byond.loadCss(o), r === "js" && Byond.loadJs(o); - } - return; - } - d(n); -}; -export { - f as assetMiddleware, - l as resolveAsset -}; diff --git a/dist/common/constants.d.ts b/dist/common/constants.d.ts index 8b7f41b..e096244 100644 --- a/dist/common/constants.d.ts +++ b/dist/common/constants.d.ts @@ -96,7 +96,7 @@ export declare const RADIO_CHANNELS: readonly [{ readonly color: "#1ecc43"; }]; export declare function getGasLabel(gasId: string, fallbackValue?: string): string; -export declare function getGasColor(gasId: string): "black" | "blue" | "brown" | "grey" | "olive" | "pink" | "purple" | "teal" | "white" | "yellow" | "lightsteelblue" | "bisque" | "limegreen" | "mediumpurple" | "mediumslateblue" | "paleturquoise" | "salmon" | "greenyellow" | "darkgreen" | "aliceblue" | "maroon"; +export declare function getGasColor(gasId: string): string; export declare const getGasFromId: (gasId: string) => Gas | undefined; export declare const getGasFromPath: (gasPath: string) => Gas | undefined; export {}; diff --git a/dist/common/exhaustive.d.ts b/dist/common/exhaustive.d.ts index 9556a91..12a8bbc 100644 --- a/dist/common/exhaustive.d.ts +++ b/dist/common/exhaustive.d.ts @@ -14,4 +14,4 @@ * exhaustiveCheck(color); * } */ -export declare function exhaustiveCheck(input: never): void; +export declare function exhaustiveCheck(input: never): never; diff --git a/dist/common/format.d.ts b/dist/common/format.d.ts index 1d16ac2..93830d2 100644 --- a/dist/common/format.d.ts +++ b/dist/common/format.d.ts @@ -1,11 +1,11 @@ -export declare const formatSiUnit: (value: number, minBase1000?: number, unit?: string) => string; +export declare function formatSiUnit(value: number, minBase1000?: number, unit?: string): string; export declare function formatPower(value: number, minBase1000?: number): string; export declare function formatEnergy(value: number, minBase1000?: number): string; export declare function formatMoney(value: number, precision?: number): string; export declare function formatDb(value: number): string; -export declare const formatSiBaseTenUnit: (value: number, minBase1000?: number, unit?: string) => string; +export declare function formatSiBaseTenUnit(value: number, minBase1000?: number, unit?: string): string; /** * Formats decisecond count into HH:MM:SS display by default * "short" format does not pad and adds hms suffixes */ -export declare const formatTime: (val: number, formatType?: "short" | "default") => string; +export declare function formatTime(val: number, formatType?: 'short' | 'default'): string; diff --git a/dist/common/format.js b/dist/common/format.js index caa7b4e..917fc1a 100644 --- a/dist/common/format.js +++ b/dist/common/format.js @@ -38,18 +38,19 @@ const d = [ "F", "N", "H" -], l = d.indexOf(" "), m = (t, n = -l, s = "") => { +], l = d.indexOf(" "); +function u(t, n = -l, s = "") { if (!isFinite(t)) return t.toString(); const o = Math.floor(Math.log10(Math.abs(t))), r = Math.max(n * 3, o), e = Math.floor(r / 3), i = d[Math.min(e + l, d.length - 1)]; let a = (t / Math.pow(1e3, e)).toFixed(2); return a.endsWith(".00") ? a = a.slice(0, -3) : a.endsWith(".0") && (a = a.slice(0, -2)), `${a} ${i.trim()}${s}`.trim(); -}; +} function S(t, n = 0) { - return m(t, n, "W"); + return u(t, n, "W"); } function $(t, n = 0) { - return m(t, n, "J"); + return u(t, n, "J"); } function b(t, n = 0) { if (!Number.isFinite(t)) @@ -89,26 +90,28 @@ const M = [ "· 10³³", "· 10³⁶", "· 10³⁹" -], p = (t, n = 0, s = "") => { +]; +function p(t, n = 0, s = "") { if (!isFinite(t)) return "NaN"; const o = Math.floor(Math.log10(t)), r = Math.max(n * 3, o), e = Math.floor(r / 3), i = M[e], c = t / Math.pow(1e3, e), a = Math.max(0, 2 - r % 3); return `${c.toFixed(a)} ${i} ${s}`.trim(); -}, F = (t, n = "default") => { +} +function F(t, n = "default") { const s = Math.floor(t / 10), o = Math.floor(s / 3600), r = Math.floor(s % 3600 / 60), e = s % 60; if (n === "short") { - const f = o > 0 ? `${o}h` : "", u = r > 0 ? `${r}m` : "", h = e > 0 ? `${e}s` : ""; - return `${f}${u}${h}`; + const f = o > 0 ? `${o}h` : "", m = r > 0 ? `${r}m` : "", h = e > 0 ? `${e}s` : ""; + return `${f}${m}${h}`; } const i = String(o).padStart(2, "0"), c = String(r).padStart(2, "0"), a = String(e).padStart(2, "0"); return `${i}:${c}:${a}`; -}; +} export { g as formatDb, $ as formatEnergy, b as formatMoney, S as formatPower, p as formatSiBaseTenUnit, - m as formatSiUnit, + u as formatSiUnit, F as formatTime }; diff --git a/dist/common/math.d.ts b/dist/common/math.d.ts index 536832b..c8e8388 100644 --- a/dist/common/math.d.ts +++ b/dist/common/math.d.ts @@ -1,39 +1,39 @@ /** * Limits a number to the range between 'min' and 'max'. */ -export declare function clamp(value: any, min: any, max: any): any; +export declare function clamp(value: number, min: number, max: number): number; /** * Limits a number between 0 and 1. */ -export declare function clamp01(value: any): any; +export declare function clamp01(value: number): number; /** * Scales a number to fit into the range between min and max. */ -export declare function scale(value: any, min: any, max: any): number; +export declare function scale(value: number, min?: number, max?: number): number; /** * Robust number rounding, similar to PHP's round() function. * * @url https://stackoverflow.com/questions/53450248/how-to-round-in-javascript-like-php-do/54721202#54721202 */ -export declare function round(num: any, dec: any): number; +export declare function round(num: number, dec: number): number; /** * Returns a string representing a number in fixed point notation. */ -export declare function toFixed(value: any, fractionDigits?: number): string; +export declare function toFixed(value: number, fractionDigits?: number): string; /** * Checks whether a value is within the provided range. * * Range is an array of two numbers, for example: [0, 15]. */ -export declare function inRange(value: any, range: any): any; +export declare function inRange(value: number, range: number[]): boolean; /** * Walks over the object with ranges, comparing value against every range, * and returns the key of the first matching range. * * Range is an array of two numbers, for example: [0, 15]. */ -export declare function keyOfMatchingRange(value: any, ranges: any): string | undefined; +export declare function keyOfMatchingRange(value: number, ranges: Record): string | undefined; /** * Get number of digits following the decimal point in a number */ -export declare function numberOfDecimalDigits(value: any): any; +export declare function numberOfDecimalDigits(value: number): number; diff --git a/dist/common/math.js b/dist/common/math.js index c8cba3b..943aa2e 100644 --- a/dist/common/math.js +++ b/dist/common/math.js @@ -4,7 +4,7 @@ function e(t, n, r) { function c(t) { return t < 0 ? 0 : t > 1 ? 1 : t; } -function f(t, n, r) { +function f(t, n = 0, r = 100) { return (t - n) / (r - n); } function u(t, n) { diff --git a/dist/common/perf.d.ts b/dist/common/perf.d.ts deleted file mode 100644 index ca4a046..0000000 --- a/dist/common/perf.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Ghetto performance measurement tools. - * - * Uses NODE_ENV to remove itself from production builds. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ -/** - * Marks a certain spot in the code for later measurements. - */ -declare function mark(name: string, timestamp?: number): void; -/** - * Calculates and returns the difference between two markers as a string. - * - * Use logger.log() to print the measurement. - */ -declare function measure(markerNameA: string, markerNameB: string): string | undefined; -export declare const perf: { - mark: typeof mark; - measure: typeof measure; -}; -export {}; diff --git a/dist/common/perf.js b/dist/common/perf.js deleted file mode 100644 index 7097292..0000000 --- a/dist/common/perf.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Ghetto performance measurement tools. - * - * Uses NODE_ENV to remove itself from production builds. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ -const i = 16.666666666666668; -var c; -const a = !!((c = window.performance) != null && c.now), t = {}, s = {}; -function p(o, n) { - process.env.NODE_ENV !== "production" && (a && !n && (t[o] = performance.now()), s[o] = n || Date.now()); -} -function u(o, n) { - if (process.env.NODE_ENV === "production") return; - let r = t[o], e = t[n]; - (!r || !e) && (r = s[o], e = s[n]); - const f = Math.abs(e - r); - return F(f); -} -function F(o) { - const n = o / i; - return o.toFixed(o < 10 ? 1 : 0) + "ms (" + n.toFixed(2) + " frames)"; -} -const d = { - mark: p, - measure: u -}; -export { - d as perf -}; diff --git a/dist/common/random.d.ts b/dist/common/random.d.ts index a19794a..45291a2 100644 --- a/dist/common/random.d.ts +++ b/dist/common/random.d.ts @@ -9,7 +9,7 @@ export declare function randomInteger(lowerBound: number, upperBound: number): n /** * Returns random array element */ -export declare const randomPick: (array: T[]) => T; +export declare function randomPick(array: T[]): T; /** * Return 1 with probability P percent; otherwise 0 */ diff --git a/dist/common/random.js b/dist/common/random.js index 9301e44..2f8c196 100644 --- a/dist/common/random.js +++ b/dist/common/random.js @@ -1,14 +1,16 @@ -import { clamp as n } from "./math.js"; -function o(t, r) { - return Math.random() * (r - t) + t; +import { clamp as r } from "./math.js"; +function o(t, n) { + return Math.random() * (n - t) + t; } -function m(t, r) { - return t = Math.ceil(t), r = Math.floor(r), Math.floor(Math.random() * (r - t) + t); +function m(t, n) { + return t = Math.ceil(t), n = Math.floor(n), Math.floor(Math.random() * (n - t) + t); +} +function h(t) { + return t[Math.floor(Math.random() * t.length)]; } -const h = (t) => t[Math.floor(Math.random() * t.length)]; function c(t) { - const r = n(t, 0, 100) / 100; - return Math.random() <= r; + const n = r(t, 0, 100) / 100; + return Math.random() <= n; } export { m as randomInteger, diff --git a/dist/common/react.d.ts b/dist/common/react.d.ts index bba1cdf..ab183b6 100644 --- a/dist/common/react.d.ts +++ b/dist/common/react.d.ts @@ -11,7 +11,7 @@ export declare function normalizeChildren(children: T | T[]): T[]; * Shallowly checks if two objects are different. * Credit: https://github.com/developit/preact-compat */ -export declare function shallowDiffers(a: object, b: object): boolean; +export declare function shallowDiffers(a: Record, b: Record): boolean; /** * A common case in tgui, when you pass a value conditionally, these are * the types that can fall through the condition. diff --git a/dist/common/redux.d.ts b/dist/common/redux.d.ts deleted file mode 100644 index 7e3676c..0000000 --- a/dist/common/redux.d.ts +++ /dev/null @@ -1,64 +0,0 @@ -export type Reducer = (state: State | undefined, action: ActionType) => State; -export type Store = { - dispatch: Dispatch; - getState: () => State; - subscribe: (listener: () => void) => void; -}; -type MiddlewareAPI = { - dispatch: Dispatch; - getState: () => State; -}; -export type Middleware = (storeApi: MiddlewareAPI) => (next: Dispatch) => Dispatch; -export type Action = { - type: TType; -}; -export type AnyAction = Action & { - [extraProps: string]: any; -}; -export type Dispatch = (action: ActionType) => void; -type StoreEnhancer = (createStoreFunction: Function) => Function; -type PreparedAction = { - meta?: any; - payload?: any; -}; -/** - * Creates a Redux store. - */ -export declare function createStore(reducer: Reducer, enhancer?: StoreEnhancer): Store; -/** - * Creates a store enhancer which applies middleware to all dispatched - * actions. - */ -export declare function applyMiddleware(...middlewares: Middleware[]): StoreEnhancer; -/** - * Combines reducers by running them in their own object namespaces as - * defined in reducersObj paramter. - * - * Main difference from redux/combineReducers is that it preserves keys - * in the state that are not present in the reducers object. This function - * is also more flexible than the redux counterpart. - */ -export declare function combineReducers(reducersObj: Record): Reducer; -/** - * A utility function to create an action creator for the given action - * type string. The action creator accepts a single argument, which will - * be included in the action object as a field called payload. The action - * creator function will also have its toString() overriden so that it - * returns the action type, allowing it to be used in reducer logic that - * is looking for that action type. - * - * @param {string} type The action type to use for created actions. - * @param {any} prepare (optional) a method that takes any number of arguments - * and returns { payload } or { payload, meta }. If this is given, the - * resulting action creator will pass it's arguments to this method to - * calculate payload & meta. - * - * @public - */ -export declare function createAction(type: TAction, prepare?: (...args: any[]) => PreparedAction): { - (...args: any[]): Action & PreparedAction; - toString(): TAction; - type: TAction; - match(action: any): boolean; -}; -export {}; diff --git a/dist/common/redux.js b/dist/common/redux.js deleted file mode 100644 index f5554aa..0000000 --- a/dist/common/redux.js +++ /dev/null @@ -1,72 +0,0 @@ -function f(n, i) { - if (i) - return i(f)(n); - let t; - const r = [], e = () => t; - function c(s) { - r.push(s); - } - function a(s) { - t = n(t, s); - for (let o = 0; o < r.length; o++) - r[o](); - } - return a({ type: "@@INIT" }), { - dispatch: a, - subscribe: c, - getState: e - }; -} -function l(...n) { - return (i) => (t, ...r) => { - const e = i(t, ...r); - let c = () => { - throw new Error( - "Dispatching while constructing your middleware is not allowed." - ); - }; - const a = { - getState: e.getState, - dispatch: (o, ...u) => c(o, ...u) - }; - return c = n.map((o) => o(a)).reduceRight( - (o, u) => u(o), - e.dispatch - ), { - ...e, - dispatch: c - }; - }; -} -function d(n) { - const i = Object.keys(n); - return (t = {}, r) => { - const e = { ...t }; - let c = !1; - for (const a of i) { - const s = n[a], o = t[a], u = s(o, r); - o !== u && (c = !0, e[a] = u); - } - return c ? e : t; - }; -} -function h(n, i) { - function t(...r) { - let e = { type: n }; - if (i) { - const c = i(...r); - if (!c) - throw new Error("prepare function did not return an object"); - e = { ...e, ...c }; - } else - e.payload = r[0]; - return e; - } - return t.toString = () => n, t.type = n, t.match = (r) => r.type === n, t; -} -export { - l as applyMiddleware, - d as combineReducers, - h as createAction, - f as createStore -}; diff --git a/dist/common/storage.d.ts b/dist/common/storage.d.ts deleted file mode 100644 index fdd509d..0000000 --- a/dist/common/storage.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Browser-agnostic abstraction of key-value web storage. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ -export declare const IMPL_MEMORY = 0; -export declare const IMPL_LOCAL_STORAGE = 1; -export declare const IMPL_INDEXED_DB = 2; -/** - * Web Storage Proxy object, which selects the best backend available - * depending on the environment. - */ -declare class StorageProxy { - backendPromise: Promise; - constructor(); - get(key: any): Promise; - set(key: any, value: any): Promise; - remove(key: any): Promise; - clear(): Promise; -} -export declare const storage: StorageProxy; -export {}; diff --git a/dist/common/storage.js b/dist/common/storage.js deleted file mode 100644 index 89a91bc..0000000 --- a/dist/common/storage.js +++ /dev/null @@ -1,133 +0,0 @@ -var l = Object.defineProperty; -var D = (r, e, t) => e in r ? l(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t; -var s = (r, e, t) => D(r, typeof e != "symbol" ? e + "" : e, t); -/** - * Browser-agnostic abstraction of key-value web storage. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ -const h = 0, P = 1, B = 2; -const w = "tgui", a = "storage-v1", m = "readonly", i = "readwrite", d = (r) => () => { - try { - return !!r(); - } catch { - return !1; - } -}, I = d( - () => window.localStorage && window.localStorage.getItem -), E = d( - () => (window.indexedDB || window.msIndexedDB) && (window.IDBTransaction || window.msIDBTransaction) -); -class g { - constructor() { - s(this, "impl", 0); - s(this, "store", {}); - this.impl = 0, this.store = {}; - } - get(e) { - return this.store[e]; - } - set(e, t) { - this.store[e] = t; - } - remove(e) { - this.store[e] = void 0; - } - clear() { - this.store = {}; - } -} -class u { - constructor() { - s(this, "impl", 1); - this.impl = 1; - } - get(e) { - const t = localStorage.getItem(e); - if (typeof t == "string") - return JSON.parse(t); - } - set(e, t) { - localStorage.setItem(e, JSON.stringify(t)); - } - remove(e) { - localStorage.removeItem(e); - } - clear() { - localStorage.clear(); - } -} -class _ { - constructor() { - s(this, "impl", 2); - s(this, "dbPromise"); - this.impl = 2, this.dbPromise = new Promise((e, t) => { - const o = (window.indexedDB || window.msIndexedDB).open(w, 1); - o.onupgradeneeded = () => { - try { - o.result.createObjectStore(a); - } catch { - t(new Error("Failed to upgrade IDB: " + o.error)); - } - }, o.onsuccess = () => e(o.result), o.onerror = () => { - t(new Error("Failed to open IDB: " + o.error)); - }; - }); - } - getStore(e) { - return this.dbPromise.then( - (t) => t.transaction(a, e).objectStore(a) - ); - } - async get(e) { - const t = await this.getStore(m); - return new Promise((c, o) => { - const n = t.get(e); - n.onsuccess = () => c(n.result), n.onerror = () => o(n.error); - }); - } - async set(e, t) { - t === null && (t = void 0), (await this.getStore(i)).put(t, e); - } - async remove(e) { - (await this.getStore(i)).delete(e); - } - async clear() { - (await this.getStore(i)).clear(); - } -} -class S { - constructor() { - s(this, "backendPromise"); - this.backendPromise = (async () => { - if (E()) - try { - const e = new _(); - return await e.dbPromise, e; - } catch { - } - return I() ? new u() : new g(); - })(); - } - async get(e) { - return (await this.backendPromise).get(e); - } - async set(e, t) { - return (await this.backendPromise).set(e, t); - } - async remove(e) { - return (await this.backendPromise).remove(e); - } - async clear() { - return (await this.backendPromise).clear(); - } -} -const k = new S(); -export { - B as IMPL_INDEXED_DB, - P as IMPL_LOCAL_STORAGE, - h as IMPL_MEMORY, - k as storage -}; diff --git a/dist/components/BodyZoneSelector.d.ts b/dist/components/BodyZoneSelector.d.ts deleted file mode 100644 index 08aafdd..0000000 --- a/dist/components/BodyZoneSelector.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Component } from 'react'; - -export declare enum BodyZone { - Chest = "chest", - Eyes = "eyes", - Groin = "groin", - Head = "head", - LeftArm = "l_arm", - LeftLeg = "l_leg", - Mouth = "mouth", - RightArm = "r_arm", - RightLeg = "r_leg" -} -type BodyZoneSelectorProps = { - onClick?: (zone: BodyZone) => void; - scale?: number; - selectedZone: BodyZone | null; - theme?: string; -}; -type BodyZoneSelectorState = { - hoverZone: BodyZone | null; -}; -export declare class BodyZoneSelector extends Component { - ref: import('react').RefObject; - state: BodyZoneSelectorState; - render(): import("react/jsx-runtime").JSX.Element; -} -export {}; diff --git a/dist/components/BodyZoneSelector.js b/dist/components/BodyZoneSelector.js deleted file mode 100644 index 97d0001..0000000 --- a/dist/components/BodyZoneSelector.js +++ /dev/null @@ -1,115 +0,0 @@ -var g = Object.defineProperty; -var _ = (e, t, s) => t in e ? g(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s; -var l = (e, t, s) => _(e, typeof t != "symbol" ? t + "" : t, s); -import { jsxs as d, jsx as h } from "react/jsx-runtime"; -import { Component as v, createRef as $ } from "react"; -import { resolveAsset as p } from "../common/assets.js"; -import { Image as f } from "./Image.js"; -var b = /* @__PURE__ */ ((e) => (e.Chest = "chest", e.Eyes = "eyes", e.Groin = "groin", e.Head = "head", e.LeftArm = "l_arm", e.LeftLeg = "l_leg", e.Mouth = "mouth", e.RightArm = "r_arm", e.RightLeg = "r_leg", e))(b || {}); -const C = (e, t) => { - if (t < 1) - return null; - if (t < 10) { - if (e > 10 && e < 15) - return "r_leg"; - if (e > 17 && e < 22) - return "l_leg"; - } else if (t < 13) { - if (e > 8 && e < 11) - return "r_arm"; - if (e > 12 && e < 20) - return "groin"; - if (e > 21 && e < 24) - return "l_arm"; - } else if (t < 22) { - if (e > 8 && e < 11) - return "r_arm"; - if (e > 12 && e < 20) - return "chest"; - if (e > 21 && e < 24) - return "l_arm"; - } else if (t < 30 && e > 12 && e < 20) - return t > 23 && t < 24 && e > 15 && e < 17 ? "mouth" : t > 25 && t < 27 && e > 14 && e < 18 ? "eyes" : "head"; - return null; -}; -class A extends v { - constructor() { - super(...arguments); - l(this, "ref", $()); - l(this, "state", { - hoverZone: null - }); - } - render() { - const { hoverZone: s } = this.state, { scale: r = 3, selectedZone: n, theme: c = "midnight" } = this.props; - return /* @__PURE__ */ d( - "div", - { - ref: this.ref, - style: { - width: `${32 * r}px`, - height: `${32 * r}px`, - position: "relative" - }, - children: [ - /* @__PURE__ */ h( - f, - { - src: p(`body_zones.base_${c}.png`), - onClick: () => { - const i = this.props.onClick; - i && this.state.hoverZone && i(this.state.hoverZone); - }, - onMouseMove: (i) => { - var u; - if (!this.props.onClick) - return; - const o = (u = this.ref.current) == null ? void 0 : u.getBoundingClientRect(); - if (!o) - return; - const a = i.clientX - o.left, m = 32 * r - (i.clientY - o.top); - this.setState({ - hoverZone: C(a / r, m / r) - }); - }, - style: { - position: "absolute", - width: `${32 * r}px`, - height: `${32 * r}px` - } - } - ), - n && /* @__PURE__ */ h( - f, - { - src: p(`body_zones.${n}.png`), - style: { - pointerEvents: "none", - position: "absolute", - width: `${32 * r}px`, - height: `${32 * r}px` - } - } - ), - s && s !== n && /* @__PURE__ */ h( - f, - { - src: p(`body_zones.${s}.png`), - style: { - opacity: "0.5", - pointerEvents: "none", - position: "absolute", - width: `${32 * r}px`, - height: `${32 * r}px` - } - } - ) - ] - } - ); - } -} -export { - b as BodyZone, - A as BodyZoneSelector -}; diff --git a/dist/components/DmIcon.d.ts b/dist/components/DmIcon.d.ts deleted file mode 100644 index 0da510f..0000000 --- a/dist/components/DmIcon.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { ReactNode } from 'react'; -import { BooleanLike } from '../common/react'; -import { BoxProps } from './Box'; - -declare enum Direction { - NORTH = 1, - SOUTH = 2, - EAST = 4, - WEST = 8, - NORTHEAST = 5, - NORTHWEST = 9, - SOUTHEAST = 6, - SOUTHWEST = 10 -} -type Props = { - /** Required: The path of the icon */ - icon: string; - /** Required: The state of the icon */ - icon_state: string; -} & Partial<{ - /** Facing direction. See direction enum. Default is South */ - direction: Direction; - /** Fallback icon. */ - fallback: ReactNode; - /** Frame number. Default is 1 */ - frame: number; - /** Movement state. Default is false */ - movement: BooleanLike; -}> & BoxProps; -export declare function DmIcon(props: Props): string; -export {}; diff --git a/dist/components/DmIcon.js b/dist/components/DmIcon.js deleted file mode 100644 index a3c5643..0000000 --- a/dist/components/DmIcon.js +++ /dev/null @@ -1,21 +0,0 @@ -import { useState as o, useEffect as c } from "react"; -import { resolveAsset as n } from "../common/assets.js"; -function i(a) { - o(""); - const [r, t] = o("unloaded"); - return c(() => { - fetch(n("icon_ref_map.json")).then((e) => e.text()).then((e) => { - try { - const s = JSON.parse(e); - t("success " + Object.keys(s).length.toString()); - } catch { - t(e); - } - }).catch((e) => { - t(e.message); - }); - }, []), r; -} -export { - i as DmIcon -}; diff --git a/dist/components/index.d.ts b/dist/components/index.d.ts index 0bdfaa9..481f295 100644 --- a/dist/components/index.d.ts +++ b/dist/components/index.d.ts @@ -11,7 +11,6 @@ export { ColorBox } from './ColorBox'; export { Dialog } from './Dialog'; export { Dimmer } from './Dimmer'; export { Divider } from './Divider'; -export { DmIcon } from './DmIcon'; export { DraggableControl } from './DraggableControl'; export { Dropdown } from './Dropdown'; export { FitText } from './FitText'; diff --git a/dist/components/index.js b/dist/components/index.js index 9155325..799cb26 100644 --- a/dist/components/index.js +++ b/dist/components/index.js @@ -4,45 +4,44 @@ import { Blink as x } from "./Blink.js"; import { BlockQuote as i } from "./BlockQuote.js"; import { Box as a } from "./Box.js"; import { Button as u } from "./Button.js"; -import { ByondUi as c } from "./ByondUi.js"; -import { Chart as b } from "./Chart.js"; -import { Collapsible as D } from "./Collapsible.js"; -import { ColorBox as T } from "./ColorBox.js"; -import { Dialog as C } from "./Dialog.js"; +import { ByondUi as d } from "./ByondUi.js"; +import { Chart as c } from "./Chart.js"; +import { Collapsible as T } from "./Collapsible.js"; +import { ColorBox as C } from "./ColorBox.js"; +import { Dialog as I } from "./Dialog.js"; import { Dimmer as L } from "./Dimmer.js"; import { Divider as y } from "./Divider.js"; -import { DmIcon as N } from "./DmIcon.js"; -import { DraggableControl as F } from "./DraggableControl.js"; -import { Dropdown as M } from "./Dropdown.js"; -import { FitText as h } from "./FitText.js"; -import { Flex as w } from "./Flex.js"; -import { Icon as O } from "./Icon.js"; -import { Image as U } from "./Image.js"; -import { InfinitePlane as j } from "./InfinitePlane.js"; -import { Input as z } from "./Input.js"; -import { KeyListener as H } from "./KeyListener.js"; -import { Knob as W } from "./Knob.js"; -import { LabeledControls as Y } from "./LabeledControls.js"; -import { LabeledList as _ } from "./LabeledList.js"; -import { MenuBar as oo } from "./MenuBar.js"; -import { Modal as eo } from "./Modal.js"; -import { NoticeBox as po } from "./NoticeBox.js"; -import { NumberInput as xo } from "./NumberInput.js"; -import { Popper as io } from "./Popper.js"; -import { ProgressBar as ao } from "./ProgressBar.js"; -import { RestrictedInput as uo } from "./RestrictedInput.js"; -import { RoundGauge as co } from "./RoundGauge.js"; -import { Section as Bo } from "./Section.js"; -import { Slider as Io } from "./Slider.js"; +import { DraggableControl as N } from "./DraggableControl.js"; +import { Dropdown as F } from "./Dropdown.js"; +import { FitText as M } from "./FitText.js"; +import { Flex as h } from "./Flex.js"; +import { Icon as w } from "./Icon.js"; +import { Image as O } from "./Image.js"; +import { InfinitePlane as U } from "./InfinitePlane.js"; +import { Input as j } from "./Input.js"; +import { KeyListener as z } from "./KeyListener.js"; +import { Knob as H } from "./Knob.js"; +import { LabeledControls as W } from "./LabeledControls.js"; +import { LabeledList as Y } from "./LabeledList.js"; +import { MenuBar as _ } from "./MenuBar.js"; +import { Modal as oo } from "./Modal.js"; +import { NoticeBox as eo } from "./NoticeBox.js"; +import { NumberInput as po } from "./NumberInput.js"; +import { Popper as xo } from "./Popper.js"; +import { ProgressBar as io } from "./ProgressBar.js"; +import { RestrictedInput as ao } from "./RestrictedInput.js"; +import { RoundGauge as uo } from "./RoundGauge.js"; +import { Section as bo } from "./Section.js"; +import { Slider as Bo } from "./Slider.js"; import { Stack as go } from "./Stack.js"; -import { StyleableSection as ko } from "./StyleableSection.js"; -import { Table as So } from "./Table.js"; -import { Tabs as Ao } from "./Tabs.js"; -import { TextArea as Po } from "./TextArea.js"; -import { TimeDisplay as Ko } from "./TimeDisplay.js"; -import { Tooltip as Ro } from "./Tooltip.js"; -import { TrackOutsideClicks as vo } from "./TrackOutsideClicks.js"; -import { VirtualList as Go } from "./VirtualList.js"; +import { StyleableSection as Do } from "./StyleableSection.js"; +import { Table as ko } from "./Table.js"; +import { Tabs as So } from "./Tabs.js"; +import { TextArea as Ao } from "./TextArea.js"; +import { TimeDisplay as Po } from "./TimeDisplay.js"; +import { Tooltip as Ko } from "./Tooltip.js"; +import { TrackOutsideClicks as Ro } from "./TrackOutsideClicks.js"; +import { VirtualList as vo } from "./VirtualList.js"; export { e as AnimatedNumber, p as Autofocus, @@ -50,43 +49,42 @@ export { i as BlockQuote, a as Box, u as Button, - c as ByondUi, - b as Chart, - D as Collapsible, - T as ColorBox, - C as Dialog, + d as ByondUi, + c as Chart, + T as Collapsible, + C as ColorBox, + I as Dialog, L as Dimmer, y as Divider, - N as DmIcon, - F as DraggableControl, - M as Dropdown, - h as FitText, - w as Flex, - O as Icon, - U as Image, - j as InfinitePlane, - z as Input, - H as KeyListener, - W as Knob, - Y as LabeledControls, - _ as LabeledList, - oo as MenuBar, - eo as Modal, - po as NoticeBox, - xo as NumberInput, - io as Popper, - ao as ProgressBar, - uo as RestrictedInput, - co as RoundGauge, - Bo as Section, - Io as Slider, + N as DraggableControl, + F as Dropdown, + M as FitText, + h as Flex, + w as Icon, + O as Image, + U as InfinitePlane, + j as Input, + z as KeyListener, + H as Knob, + W as LabeledControls, + Y as LabeledList, + _ as MenuBar, + oo as Modal, + eo as NoticeBox, + po as NumberInput, + xo as Popper, + io as ProgressBar, + ao as RestrictedInput, + uo as RoundGauge, + bo as Section, + Bo as Slider, go as Stack, - ko as StyleableSection, - So as Table, - Ao as Tabs, - Po as TextArea, - Ko as TimeDisplay, - Ro as Tooltip, - vo as TrackOutsideClicks, - Go as VirtualList + Do as StyleableSection, + ko as Table, + So as Tabs, + Ao as TextArea, + Po as TimeDisplay, + Ko as Tooltip, + Ro as TrackOutsideClicks, + vo as VirtualList }; diff --git a/lib/common/assets.ts b/lib/common/assets.ts deleted file mode 100644 index c5aae65..0000000 --- a/lib/common/assets.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { Action, AnyAction, Dispatch, Middleware } from './redux'; - -const EXCLUDED_PATTERNS = [/v4shim/i]; -const loadedMappings: Record = {}; - -export function resolveAsset(name: string): string { - return loadedMappings[name] || name; -} - -export const assetMiddleware: Middleware = - (_storeApi) => - (next: Dispatch) => - (action: ActionType) => { - const { type, payload } = action as AnyAction; - if (type === 'asset/stylesheet') { - Byond.loadCss(payload); - return; - } - if (type === 'asset/mappings') { - for (const name of Object.keys(payload)) { - // Skip anything that matches excluded patterns - if (EXCLUDED_PATTERNS.some((regex) => regex.test(name))) { - continue; - } - const url = payload[name]; - const ext = name.split('.').pop(); - loadedMappings[name] = url; - if (ext === 'css') { - Byond.loadCss(url); - } - if (ext === 'js') { - Byond.loadJs(url); - } - } - return; - } - next(action); - }; diff --git a/lib/common/constants.ts b/lib/common/constants.ts index 44e0fbb..2d74e75 100644 --- a/lib/common/constants.ts +++ b/lib/common/constants.ts @@ -295,7 +295,7 @@ const GASES = [ ] as const; // Returns gas label based on gasId -export function getGasLabel(gasId: string, fallbackValue?: string) { +export function getGasLabel(gasId: string, fallbackValue?: string): string { if (!gasId) return fallbackValue || 'None'; const gasSearchString = gasId.toLowerCase(); @@ -310,7 +310,7 @@ export function getGasLabel(gasId: string, fallbackValue?: string) { } // Returns gas color based on gasId -export function getGasColor(gasId: string) { +export function getGasColor(gasId: string): string { if (!gasId) return 'black'; const gasSearchString = gasId.toLowerCase(); diff --git a/lib/common/exhaustive.ts b/lib/common/exhaustive.ts index 4d6d79d..a4e3296 100644 --- a/lib/common/exhaustive.ts +++ b/lib/common/exhaustive.ts @@ -14,6 +14,6 @@ * exhaustiveCheck(color); * } */ -export function exhaustiveCheck(input: never) { +export function exhaustiveCheck(input: never): never { throw new Error(`Unhandled case: ${input}`); } diff --git a/lib/common/format.ts b/lib/common/format.ts index 8945148..56deeeb 100644 --- a/lib/common/format.ts +++ b/lib/common/format.ts @@ -27,11 +27,11 @@ const SI_SYMBOLS = [ const SI_BASE_INDEX = SI_SYMBOLS.indexOf(' '); // Formats a number to a human readable form, with a custom unit -export const formatSiUnit = ( +export function formatSiUnit( value: number, minBase1000 = -SI_BASE_INDEX, unit = '', -): string => { +): string { if (!isFinite(value)) { return value.toString(); } @@ -52,19 +52,19 @@ export const formatSiUnit = ( } return `${formattedValue} ${symbol.trim()}${unit}`.trim(); -}; +} // Formats a number to a human readable form, with power (W) as the unit -export function formatPower(value: number, minBase1000 = 0) { +export function formatPower(value: number, minBase1000 = 0): string { return formatSiUnit(value, minBase1000, 'W'); } -export function formatEnergy(value: number, minBase1000 = 0) { +export function formatEnergy(value: number, minBase1000 = 0): string { return formatSiUnit(value, minBase1000, 'J'); } // Formats a number as a currency string -export function formatMoney(value: number, precision = 0) { +export function formatMoney(value: number, precision = 0): string { if (!Number.isFinite(value)) { return String(value); } @@ -86,7 +86,7 @@ export function formatMoney(value: number, precision = 0) { } // Formats a floating point number as a number on the decibel scale -export function formatDb(value: number) { +export function formatDb(value: number): string { const db = 20 * Math.log10(value); const sign = db >= 0 ? '+' : '-'; let formatted: string | number = Math.abs(db); @@ -118,11 +118,11 @@ const SI_BASE_TEN_UNITS = [ ] as const; // Converts a number to a string with SI base 10 units -export const formatSiBaseTenUnit = ( +export function formatSiBaseTenUnit( value: number, minBase1000 = 0, unit = '', -): string => { +): string { if (!isFinite(value)) { return 'NaN'; } @@ -137,16 +137,16 @@ export const formatSiBaseTenUnit = ( const formattedValue = scaledValue.toFixed(precision); return `${formattedValue} ${symbol} ${unit}`.trim(); -}; +} /** * Formats decisecond count into HH:MM:SS display by default * "short" format does not pad and adds hms suffixes */ -export const formatTime = ( +export function formatTime( val: number, formatType: 'short' | 'default' = 'default', -): string => { +): string { const totalSeconds = Math.floor(val / 10); const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); @@ -164,4 +164,4 @@ export const formatTime = ( const secondsPadded = String(seconds).padStart(2, '0'); return `${hoursPadded}:${minutesPadded}:${secondsPadded}`; -}; +} diff --git a/lib/common/math.ts b/lib/common/math.ts index 0d71b32..1308311 100644 --- a/lib/common/math.ts +++ b/lib/common/math.ts @@ -1,21 +1,21 @@ /** * Limits a number to the range between 'min' and 'max'. */ -export function clamp(value, min, max) { +export function clamp(value: number, min: number, max: number): number { return value < min ? min : value > max ? max : value; } /** * Limits a number between 0 and 1. */ -export function clamp01(value) { +export function clamp01(value: number): number { return value < 0 ? 0 : value > 1 ? 1 : value; } /** * Scales a number to fit into the range between min and max. */ -export function scale(value, min, max) { +export function scale(value: number, min = 0, max = 100): number { return (value - min) / (max - min); } @@ -24,7 +24,7 @@ export function scale(value, min, max) { * * @url https://stackoverflow.com/questions/53450248/how-to-round-in-javascript-like-php-do/54721202#54721202 */ -export function round(num, dec) { +export function round(num: number, dec: number): number { const num_sign = num >= 0 ? 1 : -1; return parseFloat( ( @@ -37,7 +37,7 @@ export function round(num, dec) { /** * Returns a string representing a number in fixed point notation. */ -export function toFixed(value, fractionDigits = 0) { +export function toFixed(value: number, fractionDigits = 0): string { return Number(value).toFixed(Math.max(fractionDigits, 0)); } @@ -46,7 +46,7 @@ export function toFixed(value, fractionDigits = 0) { * * Range is an array of two numbers, for example: [0, 15]. */ -export function inRange(value, range) { +export function inRange(value: number, range: number[]): boolean { return range && value >= range[0] && value <= range[1]; } @@ -56,7 +56,10 @@ export function inRange(value, range) { * * Range is an array of two numbers, for example: [0, 15]. */ -export function keyOfMatchingRange(value, ranges) { +export function keyOfMatchingRange( + value: number, + ranges: Record, +): string | undefined { for (const rangeName of Object.keys(ranges)) { const range = ranges[rangeName]; if (inRange(value, range)) { @@ -68,7 +71,7 @@ export function keyOfMatchingRange(value, ranges) { /** * Get number of digits following the decimal point in a number */ -export function numberOfDecimalDigits(value) { +export function numberOfDecimalDigits(value: number): number { if (Math.floor(value) !== value) { return value.toString().split('.')[1].length || 0; } diff --git a/lib/common/perf.ts b/lib/common/perf.ts deleted file mode 100644 index a7dfefc..0000000 --- a/lib/common/perf.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Ghetto performance measurement tools. - * - * Uses NODE_ENV to remove itself from production builds. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ - -const FPS = 60; -const FRAME_DURATION = 1000 / FPS; - -// True if Performance API is supported -const supportsPerf = !!window.performance?.now; -// High precision markers -const hpMarkersByName: Record = {}; -// Low precision markers -const lpMarkersByName: Record = {}; - -/** - * Marks a certain spot in the code for later measurements. - */ -function mark(name: string, timestamp?: number): void { - if (process.env.NODE_ENV !== 'production') { - if (supportsPerf && !timestamp) { - hpMarkersByName[name] = performance.now(); - } - lpMarkersByName[name] = timestamp || Date.now(); - } -} - -/** - * Calculates and returns the difference between two markers as a string. - * - * Use logger.log() to print the measurement. - */ -function measure(markerNameA: string, markerNameB: string): string | undefined { - if (process.env.NODE_ENV === 'production') return; - - let markerA = hpMarkersByName[markerNameA]; - let markerB = hpMarkersByName[markerNameB]; - - if (!markerA || !markerB) { - markerA = lpMarkersByName[markerNameA]; - markerB = lpMarkersByName[markerNameB]; - } - - const duration = Math.abs(markerB - markerA); - - return formatDuration(duration); -} - -/** - * Formats a duration in milliseconds and frames. - */ -function formatDuration(duration: number): string { - const durationInFrames = duration / FRAME_DURATION; - - return ( - duration.toFixed(duration < 10 ? 1 : 0) + - 'ms ' + - '(' + - durationInFrames.toFixed(2) + - ' frames)' - ); -} - -export const perf = { - mark, - measure, -}; diff --git a/lib/common/random.ts b/lib/common/random.ts index 584589b..d8a12eb 100644 --- a/lib/common/random.ts +++ b/lib/common/random.ts @@ -3,14 +3,14 @@ import { clamp } from './math'; /** * Returns random number between lowerBound exclusive and upperBound inclusive */ -export function randomNumber(lowerBound: number, upperBound: number) { +export function randomNumber(lowerBound: number, upperBound: number): number { return Math.random() * (upperBound - lowerBound) + lowerBound; } /** * Returns random integer between lowerBound exclusive and upperBound inclusive */ -export function randomInteger(lowerBound: number, upperBound: number) { +export function randomInteger(lowerBound: number, upperBound: number): number { lowerBound = Math.ceil(lowerBound); upperBound = Math.floor(upperBound); return Math.floor(Math.random() * (upperBound - lowerBound) + lowerBound); @@ -19,14 +19,14 @@ export function randomInteger(lowerBound: number, upperBound: number) { /** * Returns random array element */ -export const randomPick = (array: T[]) => { +export function randomPick(array: T[]): T { return array[Math.floor(Math.random() * array.length)]; -}; +} /** * Return 1 with probability P percent; otherwise 0 */ -export function randomProb(probability: number) { +export function randomProb(probability: number): boolean { const normalized = clamp(probability, 0, 100) / 100; return Math.random() <= normalized; } diff --git a/lib/common/react.ts b/lib/common/react.ts index 68e7cbe..dcfd436 100644 --- a/lib/common/react.ts +++ b/lib/common/react.ts @@ -1,7 +1,7 @@ /** * Helper for conditionally adding/removing classes in React */ -export function classes(classNames: (string | BooleanLike)[]) { +export function classes(classNames: (string | BooleanLike)[]): string { let className = ''; for (let i = 0; i < classNames.length; i++) { const part = classNames[i]; @@ -16,7 +16,7 @@ export function classes(classNames: (string | BooleanLike)[]) { * Normalizes children prop, so that it is always an array of VDom * elements. */ -export function normalizeChildren(children: T | T[]) { +export function normalizeChildren(children: T | T[]): T[] { if (Array.isArray(children)) { return children.flat().filter((value) => value) as T[]; } @@ -30,8 +30,11 @@ export function normalizeChildren(children: T | T[]) { * Shallowly checks if two objects are different. * Credit: https://github.com/developit/preact-compat */ -export function shallowDiffers(a: object, b: object) { - let i; +export function shallowDiffers( + a: Record, + b: Record, +): boolean { + let i: string; for (i in a) { if (!(i in b)) { return true; @@ -54,6 +57,6 @@ export type BooleanLike = number | boolean | null | undefined; /** * A helper to determine whether the object is renderable by React. */ -export function canRender(value: unknown) { +export function canRender(value: unknown): boolean { return value !== undefined && value !== null && typeof value !== 'boolean'; } diff --git a/lib/common/redux.ts b/lib/common/redux.ts deleted file mode 100644 index a27ed48..0000000 --- a/lib/common/redux.ts +++ /dev/null @@ -1,187 +0,0 @@ -export type Reducer = ( - state: State | undefined, - action: ActionType, -) => State; - -export type Store = { - dispatch: Dispatch; - getState: () => State; - subscribe: (listener: () => void) => void; -}; - -type MiddlewareAPI = { - dispatch: Dispatch; - getState: () => State; -}; - -export type Middleware = ( - storeApi: MiddlewareAPI, -) => (next: Dispatch) => Dispatch; - -export type Action = { - type: TType; -}; - -export type AnyAction = Action & { - [extraProps: string]: any; -}; - -export type Dispatch = ( - action: ActionType, -) => void; - -// eslint-disable-next-line @typescript-eslint/ban-types -type StoreEnhancer = (createStoreFunction: Function) => Function; - -type PreparedAction = { - meta?: any; - payload?: any; -}; - -/** - * Creates a Redux store. - */ -export function createStore( - reducer: Reducer, - enhancer?: StoreEnhancer, -): Store { - // Apply a store enhancer (applyMiddleware is one of them). - if (enhancer) { - return enhancer(createStore)(reducer); - } - - let currentState: State; - const listeners: Array<() => void> = []; - - const getState = (): State => currentState; - - function subscribe(listener: () => void): void { - listeners.push(listener); - } - - function dispatch(action: ActionType): void { - currentState = reducer(currentState, action); - for (let i = 0; i < listeners.length; i++) { - listeners[i](); - } - } - - // This creates the initial store by causing each reducer to be called - // with an undefined state - dispatch({ type: '@@INIT' } as ActionType); - - return { - dispatch, - subscribe, - getState, - }; -} - -/** - * Creates a store enhancer which applies middleware to all dispatched - * actions. - */ -export function applyMiddleware(...middlewares: Middleware[]): StoreEnhancer { - return ( - createStoreFunction: (reducer: Reducer, enhancer?: StoreEnhancer) => Store, - ) => { - return (reducer, ...args): Store => { - const store = createStoreFunction(reducer, ...args); - - let dispatch: Dispatch = () => { - throw new Error( - 'Dispatching while constructing your middleware is not allowed.', - ); - }; - - const storeApi: MiddlewareAPI = { - getState: store.getState, - dispatch: (action, ...args) => dispatch(action, ...args), - }; - - const chain = middlewares.map((middleware) => middleware(storeApi)); - dispatch = chain.reduceRight( - (next, middleware) => middleware(next), - store.dispatch, - ); - - return { - ...store, - dispatch, - }; - }; - }; -} - -/** - * Combines reducers by running them in their own object namespaces as - * defined in reducersObj paramter. - * - * Main difference from redux/combineReducers is that it preserves keys - * in the state that are not present in the reducers object. This function - * is also more flexible than the redux counterpart. - */ -export function combineReducers(reducersObj: Record): Reducer { - const keys = Object.keys(reducersObj); - - return (prevState = {}, action) => { - const nextState = { ...prevState }; - let hasChanged = false; - - for (const key of keys) { - const reducer = reducersObj[key]; - const prevDomainState = prevState[key]; - const nextDomainState = reducer(prevDomainState, action); - - if (prevDomainState !== nextDomainState) { - hasChanged = true; - nextState[key] = nextDomainState; - } - } - - return hasChanged ? nextState : prevState; - }; -} - -/** - * A utility function to create an action creator for the given action - * type string. The action creator accepts a single argument, which will - * be included in the action object as a field called payload. The action - * creator function will also have its toString() overriden so that it - * returns the action type, allowing it to be used in reducer logic that - * is looking for that action type. - * - * @param {string} type The action type to use for created actions. - * @param {any} prepare (optional) a method that takes any number of arguments - * and returns { payload } or { payload, meta }. If this is given, the - * resulting action creator will pass it's arguments to this method to - * calculate payload & meta. - * - * @public - */ -export function createAction( - type: TAction, - prepare?: (...args: any[]) => PreparedAction, -) { - function actionCreator(...args: any[]) { - let action: Action & PreparedAction = { type }; - - if (prepare) { - const prepared = prepare(...args); - if (!prepared) { - throw new Error('prepare function did not return an object'); - } - action = { ...action, ...prepared }; - } else { - action.payload = args[0]; - } - - return action; - } - - actionCreator.toString = () => type; - actionCreator.type = type; - actionCreator.match = (action) => action.type === type; - - return actionCreator; -} diff --git a/lib/common/storage.ts b/lib/common/storage.ts deleted file mode 100644 index beaaff3..0000000 --- a/lib/common/storage.ts +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Browser-agnostic abstraction of key-value web storage. - * - * @file - * @copyright 2020 Aleksej Komarov - * @license MIT - */ - -export const IMPL_MEMORY = 0; -export const IMPL_LOCAL_STORAGE = 1; -export const IMPL_INDEXED_DB = 2; - -const INDEXED_DB_VERSION = 1; -const INDEXED_DB_NAME = 'tgui'; -const INDEXED_DB_STORE_NAME = 'storage-v1'; - -const READ_ONLY = 'readonly'; -const READ_WRITE = 'readwrite'; - -const testGeneric = (testFn) => () => { - try { - return Boolean(testFn()); - } catch { - return false; - } -}; - -// Localstorage can sometimes throw an error, even if DOM storage is not -// disabled in IE11 settings. -// See: https://superuser.com/questions/1080011 - -const testLocalStorage = testGeneric( - () => window.localStorage && window.localStorage.getItem, -); - -const testIndexedDb = testGeneric( - () => - (window.indexedDB || window.msIndexedDB) && - (window.IDBTransaction || window.msIDBTransaction), -); - -class MemoryBackend { - impl = IMPL_MEMORY; - store: Record = {}; - - constructor() { - this.impl = IMPL_MEMORY; - this.store = {}; - } - - get(key) { - return this.store[key]; - } - - set(key, value) { - this.store[key] = value; - } - - remove(key) { - this.store[key] = undefined; - } - - clear() { - this.store = {}; - } -} - -class LocalStorageBackend { - impl = IMPL_LOCAL_STORAGE; - - constructor() { - this.impl = IMPL_LOCAL_STORAGE; - } - - get(key) { - const value = localStorage.getItem(key); - if (typeof value === 'string') { - return JSON.parse(value); - } - } - - set(key, value) { - localStorage.setItem(key, JSON.stringify(value)); - } - - remove(key) { - localStorage.removeItem(key); - } - - clear() { - localStorage.clear(); - } -} - -class IndexedDbBackend { - impl = IMPL_INDEXED_DB; - dbPromise: Promise; - - constructor() { - this.impl = IMPL_INDEXED_DB; - this.dbPromise = new Promise((resolve, reject) => { - const indexedDB = window.indexedDB || window.msIndexedDB; - const req = indexedDB.open(INDEXED_DB_NAME, INDEXED_DB_VERSION); - req.onupgradeneeded = () => { - try { - req.result.createObjectStore(INDEXED_DB_STORE_NAME); - } catch (err) { - reject(new Error('Failed to upgrade IDB: ' + req.error)); - } - }; - req.onsuccess = () => resolve(req.result); - req.onerror = () => { - reject(new Error('Failed to open IDB: ' + req.error)); - }; - }); - } - - getStore(mode) { - return this.dbPromise.then((db) => - db - .transaction(INDEXED_DB_STORE_NAME, mode) - .objectStore(INDEXED_DB_STORE_NAME), - ); - } - - async get(key) { - const store = await this.getStore(READ_ONLY); - return new Promise((resolve, reject) => { - const req = store.get(key); - req.onsuccess = () => resolve(req.result); - req.onerror = () => reject(req.error); - }); - } - - async set(key, value) { - // The reason we don't _save_ null is because IE 10 does - // not support saving the `null` type in IndexedDB. How - // ironic, given the bug below! - // See: https://github.com/mozilla/localForage/issues/161 - if (value === null) { - value = undefined; - } - // NOTE: We deliberately make this operation transactionless - const store = await this.getStore(READ_WRITE); - store.put(value, key); - } - - async remove(key) { - // NOTE: We deliberately make this operation transactionless - const store = await this.getStore(READ_WRITE); - store.delete(key); - } - - async clear() { - // NOTE: We deliberately make this operation transactionless - const store = await this.getStore(READ_WRITE); - store.clear(); - } -} - -/** - * Web Storage Proxy object, which selects the best backend available - * depending on the environment. - */ -class StorageProxy { - backendPromise: Promise; - - constructor() { - this.backendPromise = (async () => { - if (testIndexedDb()) { - try { - const backend = new IndexedDbBackend(); - await backend.dbPromise; - return backend; - } catch { - // Ignore errors - } - } - if (testLocalStorage()) { - return new LocalStorageBackend(); - } - return new MemoryBackend(); - })(); - } - - async get(key) { - const backend = await this.backendPromise; - return backend.get(key); - } - - async set(key, value) { - const backend = await this.backendPromise; - return backend.set(key, value); - } - - async remove(key) { - const backend = await this.backendPromise; - return backend.remove(key); - } - - async clear() { - const backend = await this.backendPromise; - return backend.clear(); - } -} - -export const storage = new StorageProxy(); diff --git a/lib/components/BodyZoneSelector.tsx b/lib/components/BodyZoneSelector.tsx deleted file mode 100644 index d27db73..0000000 --- a/lib/components/BodyZoneSelector.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { Component, createRef } from 'react'; - -import { resolveAsset } from '../common/assets'; -import { Image } from './Image'; - -export enum BodyZone { - Chest = 'chest', - Eyes = 'eyes', - Groin = 'groin', - Head = 'head', - LeftArm = 'l_arm', - LeftLeg = 'l_leg', - Mouth = 'mouth', - RightArm = 'r_arm', - RightLeg = 'r_leg', -} - -const bodyZonePixelToZone = (x: number, y: number): BodyZone | null => { - // TypeScript translation of /atom/movable/screen/zone_sel/proc/get_zone_at - if (y < 1) { - return null; - } else if (y < 10) { - if (x > 10 && x < 15) { - return BodyZone.RightLeg; - } else if (x > 17 && x < 22) { - return BodyZone.LeftLeg; - } - } else if (y < 13) { - if (x > 8 && x < 11) { - return BodyZone.RightArm; - } else if (x > 12 && x < 20) { - return BodyZone.Groin; - } else if (x > 21 && x < 24) { - return BodyZone.LeftArm; - } - } else if (y < 22) { - if (x > 8 && x < 11) { - return BodyZone.RightArm; - } else if (x > 12 && x < 20) { - return BodyZone.Chest; - } else if (x > 21 && x < 24) { - return BodyZone.LeftArm; - } - } else if (y < 30 && x > 12 && x < 20) { - if (y > 23 && y < 24 && x > 15 && x < 17) { - return BodyZone.Mouth; - } else if (y > 25 && y < 27 && x > 14 && x < 18) { - return BodyZone.Eyes; - } else { - return BodyZone.Head; - } - } - - return null; -}; - -type BodyZoneSelectorProps = { - onClick?: (zone: BodyZone) => void; - scale?: number; - selectedZone: BodyZone | null; - theme?: string; -}; - -type BodyZoneSelectorState = { - hoverZone: BodyZone | null; -}; - -export class BodyZoneSelector extends Component< - BodyZoneSelectorProps, - BodyZoneSelectorState -> { - ref = createRef(); - state: BodyZoneSelectorState = { - hoverZone: null, - }; - - render() { - const { hoverZone } = this.state; - const { scale = 3, selectedZone, theme = 'midnight' } = this.props; - - return ( -
- { - const onClick = this.props.onClick; - if (onClick && this.state.hoverZone) { - onClick(this.state.hoverZone); - } - }} - onMouseMove={(event) => { - if (!this.props.onClick) { - return; - } - - const rect = this.ref.current?.getBoundingClientRect(); - if (!rect) { - return; - } - - const x = event.clientX - rect.left; - const y = 32 * scale - (event.clientY - rect.top); - - this.setState({ - hoverZone: bodyZonePixelToZone(x / scale, y / scale), - }); - }} - style={{ - position: 'absolute', - width: `${32 * scale}px`, - height: `${32 * scale}px`, - }} - /> - - {selectedZone && ( - - )} - - {hoverZone && hoverZone !== selectedZone && ( - - )} -
- ); - } -} diff --git a/lib/components/DmIcon.tsx b/lib/components/DmIcon.tsx deleted file mode 100644 index 6baeed3..0000000 --- a/lib/components/DmIcon.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { ReactNode, useEffect, useState } from 'react'; - -import { resolveAsset } from '../common/assets'; -import { BooleanLike } from '../common/react'; -import { BoxProps } from './Box'; - -enum Direction { - NORTH = 1, - SOUTH = 2, - EAST = 4, - WEST = 8, - NORTHEAST = NORTH | EAST, - NORTHWEST = NORTH | WEST, - SOUTHEAST = SOUTH | EAST, - SOUTHWEST = SOUTH | WEST, -} - -type Props = { - /** Required: The path of the icon */ - icon: string; - /** Required: The state of the icon */ - icon_state: string; -} & Partial<{ - /** Facing direction. See direction enum. Default is South */ - direction: Direction; - /** Fallback icon. */ - fallback: ReactNode; - /** Frame number. Default is 1 */ - frame: number; - /** Movement state. Default is false */ - movement: BooleanLike; -}> & - BoxProps; - -let refMap: Record; - -export function DmIcon(props: Props) { - const { - // className, - // direction = Direction.SOUTH, - // fallback, - // frame = 1, - // icon_state, - icon, - // movement = false, - // ...rest - } = props; - - const [_, setIconRef] = useState(''); - const [displayText, setDisplayText] = useState('unloaded'); - - // const query = `${iconRef}?state=${icon_state}&dir=${direction}&movement=${movement}&frame=${frame}`; - - useEffect(() => { - if (refMap) { - setDisplayText(Object.keys(refMap).length.toString()); - setIconRef(refMap[icon]); - return; - } - - fetch(resolveAsset('icon_ref_map.json')) - .then((response) => response.text()) // Get the response text - .then((text) => { - try { - const data = JSON.parse(text); // Try parsing the text as JSON - setDisplayText('success' + ' ' + Object.keys(data).length.toString()); - } catch (error) { - setDisplayText(text); // If parsing fails, set the text as the error message - } - }) - .catch((error) => { - // Ignore errors - setDisplayText(error.message); - }); - }, []); - - // if (!iconRef) return fallback; - - return displayText; -} diff --git a/lib/components/index.ts b/lib/components/index.ts index 0bdfaa9..481f295 100644 --- a/lib/components/index.ts +++ b/lib/components/index.ts @@ -11,7 +11,6 @@ export { ColorBox } from './ColorBox'; export { Dialog } from './Dialog'; export { Dimmer } from './Dimmer'; export { Divider } from './Divider'; -export { DmIcon } from './DmIcon'; export { DraggableControl } from './DraggableControl'; export { Dropdown } from './Dropdown'; export { FitText } from './FitText'; diff --git a/package.json b/package.json index 349d008..0c1aa39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tgui-core", - "version": "1.1.15", + "version": "1.1.16", "description": "TGUI core component library", "keywords": [ "TGUI",