mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-24 04:28:12 +01:00
Added prettierx
This commit is contained in:
Vendored
+2
-1
@@ -9,6 +9,7 @@
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"donkie.vscode-tgstation-test-adapter",
|
||||
"icrawl.discord-vscode"
|
||||
"icrawl.discord-vscode",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+26
-13
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"eslint.nodePath": "./tgui/.yarn/sdks",
|
||||
"eslint.workingDirectories": [
|
||||
"./tgui"
|
||||
],
|
||||
"eslint.workingDirectories": ["./tgui"],
|
||||
"prettier.prettierPath": "./tgui/.yarn/sdks/prettier/index.js",
|
||||
"typescript.tsdk": "./tgui/.yarn/sdks/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"search.exclude": {
|
||||
@@ -13,24 +12,38 @@
|
||||
"*.dmi": "imagePreview.previewEditor"
|
||||
},
|
||||
"files.eol": "\n",
|
||||
"files.encoding": "utf8",
|
||||
"files.associations": {
|
||||
"*.{dme,dmf,dmm,dm}": "dm",
|
||||
},
|
||||
"gitlens.advanced.blame.customArguments": [
|
||||
"-w"
|
||||
],
|
||||
"tgstationTestExplorer.project.resultsType": "json",
|
||||
"[javascript]": {
|
||||
"editor.rulers": [
|
||||
120
|
||||
]
|
||||
"editor.rulers": [120],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.rulers": [120],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.rulers": [
|
||||
120
|
||||
]
|
||||
"editor.rulers": [120],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.rulers": [120],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.rulers": [
|
||||
120
|
||||
]
|
||||
"editor.rulers": [120],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"tgstationTestExplorer.project.DMEName": "tgmc.dme"
|
||||
}
|
||||
}
|
||||
|
||||
+28
-27
@@ -1,4 +1,5 @@
|
||||
root: true
|
||||
extends: prettier
|
||||
parser: '@typescript-eslint/parser'
|
||||
parserOptions:
|
||||
ecmaVersion: 2020
|
||||
@@ -349,15 +350,15 @@ rules:
|
||||
## Enforce the location of arrow function bodies
|
||||
# implicit-arrow-linebreak: error
|
||||
## Enforce consistent indentation
|
||||
indent: [error, 2, { SwitchCase: 1 }]
|
||||
# indent: [warn, 2, { SwitchCase: 1 }]
|
||||
## Enforce the consistent use of either double or single quotes in JSX
|
||||
## attributes
|
||||
jsx-quotes: [error, prefer-double]
|
||||
# jsx-quotes: [warn, prefer-double]
|
||||
## Enforce consistent spacing between keys and values in object literal
|
||||
## properties
|
||||
key-spacing: [error, { beforeColon: false, afterColon: true }]
|
||||
# key-spacing: [warn, { beforeColon: false, afterColon: true }]
|
||||
## Enforce consistent spacing before and after keywords
|
||||
keyword-spacing: [error, { before: true, after: true }]
|
||||
# keyword-spacing: [warn, { before: true, after: true }]
|
||||
## Enforce position of line comments
|
||||
# line-comment-position: error
|
||||
## Enforce consistent linebreak style
|
||||
@@ -369,15 +370,15 @@ rules:
|
||||
## Enforce a maximum depth that blocks can be nested
|
||||
# max-depth: error
|
||||
## Enforce a maximum line length
|
||||
max-len: [error, {
|
||||
code: 120,
|
||||
## Ignore imports
|
||||
ignorePattern: '^(import\s.+\sfrom\s|.*require\()',
|
||||
ignoreUrls: true,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreStrings: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
}]
|
||||
# max-len: [warn, {
|
||||
# code: 120,
|
||||
# ## Ignore imports
|
||||
# ignorePattern: '^(import\s.+\sfrom\s|.*require\()',
|
||||
# ignoreUrls: true,
|
||||
# ignoreRegExpLiterals: true,
|
||||
# ignoreStrings: true,
|
||||
# ignoreTemplateLiterals: true,
|
||||
# }]
|
||||
## Enforce a maximum number of lines per file
|
||||
# max-lines: error
|
||||
## Enforce a maximum number of line of code in a function
|
||||
@@ -414,7 +415,7 @@ rules:
|
||||
## Disallow mixed binary operators
|
||||
# no-mixed-operators: error
|
||||
## Disallow mixed spaces and tabs for indentation
|
||||
no-mixed-spaces-and-tabs: error
|
||||
no-mixed-spaces-and-tabs: warn
|
||||
## Disallow use of chained assignment expressions
|
||||
# no-multi-assign: error
|
||||
## Disallow multiple empty lines
|
||||
@@ -440,7 +441,7 @@ rules:
|
||||
## Disallow ternary operators when simpler alternatives exist
|
||||
# no-unneeded-ternary: error
|
||||
## Disallow whitespace before properties
|
||||
no-whitespace-before-property: error
|
||||
# no-whitespace-before-property: warn
|
||||
## Enforce the location of single-line statements
|
||||
# nonblock-statement-body-position: error
|
||||
## Enforce consistent line breaks inside braces
|
||||
@@ -457,7 +458,7 @@ rules:
|
||||
## Require or disallow assignment operator shorthand where possible
|
||||
# operator-assignment: error
|
||||
## Enforce consistent linebreak style for operators
|
||||
operator-linebreak: [error, before]
|
||||
# operator-linebreak: [warn, before]
|
||||
## Require or disallow padding within blocks
|
||||
# padded-blocks: error
|
||||
## Require or disallow padding lines between statements
|
||||
@@ -482,11 +483,11 @@ rules:
|
||||
## Enforce consistent spacing before blocks
|
||||
space-before-blocks: [error, always]
|
||||
## Enforce consistent spacing before function definition opening parenthesis
|
||||
space-before-function-paren: [error, {
|
||||
anonymous: always,
|
||||
named: never,
|
||||
asyncArrow: always,
|
||||
}]
|
||||
# space-before-function-paren: [warn, {
|
||||
# anonymous: always,
|
||||
# named: never,
|
||||
# asyncArrow: always,
|
||||
# }]
|
||||
## Enforce consistent spacing inside parentheses
|
||||
space-in-parens: [error, never]
|
||||
## Require spacing around infix operators
|
||||
@@ -695,7 +696,7 @@ rules:
|
||||
react/jsx-closing-tag-location: error
|
||||
## Enforce or disallow newlines inside of curly braces in JSX attributes and
|
||||
## expressions (fixable)
|
||||
react/jsx-curly-newline: error
|
||||
# react/jsx-curly-newline: warn
|
||||
## Enforce or disallow spaces inside of curly braces in JSX attributes and
|
||||
## expressions (fixable)
|
||||
react/jsx-curly-spacing: error
|
||||
@@ -708,13 +709,13 @@ rules:
|
||||
## Enforce event handler naming conventions in JSX
|
||||
react/jsx-handler-names: error
|
||||
## Validate JSX indentation (fixable)
|
||||
react/jsx-indent: [error, 2, {
|
||||
checkAttributes: true,
|
||||
}]
|
||||
# react/jsx-indent: [warn, 2, {
|
||||
# checkAttributes: true,
|
||||
# }]
|
||||
## Validate props indentation in JSX (fixable)
|
||||
react/jsx-indent-props: [error, 2]
|
||||
# react/jsx-indent-props: [warn, 2]
|
||||
## Validate JSX has key prop when in array or iterator
|
||||
react/jsx-key: error
|
||||
# react/jsx-key: warn
|
||||
## Validate JSX maximum depth
|
||||
react/jsx-max-depth: [error, { max: 10 }] ## Generous
|
||||
## Limit maximum of props on a single line in JSX (fixable)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
## NPM
|
||||
/**/node_modules
|
||||
|
||||
## Yarn
|
||||
/.yarn
|
||||
/yarn.lock
|
||||
/.pnp.*
|
||||
|
||||
/docs
|
||||
/public
|
||||
/packages/tgui-polyfill
|
||||
/packages/tgfont/static
|
||||
**/*.json
|
||||
**/*.yml
|
||||
**/*.md
|
||||
|
||||
## Build artifacts
|
||||
/public/.tmp/**/*
|
||||
/public/*.map
|
||||
@@ -1,8 +1,10 @@
|
||||
arrowParens: always
|
||||
bracketSpacing: true
|
||||
breakLongMethodChains: true
|
||||
endOfLine: lf
|
||||
importFormatting: oneline
|
||||
jsxBracketSameLine: true
|
||||
jsxSingleQuote: false
|
||||
offsetTernaryExpressions: true
|
||||
printWidth: 120
|
||||
proseWrap: preserve
|
||||
quoteProps: preserve
|
||||
@@ -10,3 +12,4 @@ semi: true
|
||||
singleQuote: true
|
||||
tabWidth: 2
|
||||
trailingComma: es5
|
||||
useTabs: false
|
||||
|
||||
Vendored
+3
-3
@@ -11,10 +11,10 @@ const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require eslint/lib/api.js
|
||||
// Setup the environment to be able to require eslint
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real eslint/lib/api.js your application uses
|
||||
module.exports = absRequire(`eslint/lib/api.js`);
|
||||
// Defer to the real eslint your application uses
|
||||
module.exports = absRequire(`eslint`);
|
||||
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire, createRequireFromPath} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = (createRequire || createRequireFromPath)(absPnpApiPath);
|
||||
|
||||
if (existsSync(absPnpApiPath)) {
|
||||
if (!process.versions.pnp) {
|
||||
// Setup the environment to be able to require prettier/index.js
|
||||
require(absPnpApiPath).setup();
|
||||
}
|
||||
}
|
||||
|
||||
// Defer to the real prettier/index.js your application uses
|
||||
module.exports = absRequire(`prettier/index.js`);
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "prettier",
|
||||
"version": "0.19.0-sdk",
|
||||
"main": "./index.js",
|
||||
"type": "commonjs"
|
||||
}
|
||||
+78
-12
@@ -18,6 +18,7 @@ const moduleWrapper = tsserver => {
|
||||
const pnpApi = require(`pnpapi`);
|
||||
|
||||
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = str => str.startsWith("portal:/");
|
||||
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
|
||||
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||
@@ -30,7 +31,7 @@ const moduleWrapper = tsserver => {
|
||||
|
||||
function toEditorPath(str) {
|
||||
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||
if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
// We also take the opportunity to turn virtual paths into physical ones;
|
||||
// this makes it much easier to work with workspaces that list peer
|
||||
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||
@@ -44,7 +45,7 @@ const moduleWrapper = tsserver => {
|
||||
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||
if (resolved) {
|
||||
const locator = pnpApi.findPackageLocator(resolved);
|
||||
if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) {
|
||||
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||
str = resolved;
|
||||
}
|
||||
}
|
||||
@@ -60,10 +61,34 @@ const moduleWrapper = tsserver => {
|
||||
//
|
||||
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||
//
|
||||
case `vscode`: {
|
||||
// 2021-10-08: VSCode changed the format in 1.61.
|
||||
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-04-06: VSCode changed the format in 1.66.
|
||||
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-05-06: VSCode changed the format in 1.68
|
||||
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
case `vscode <1.61`: {
|
||||
str = `^zip:${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.66`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.68`: {
|
||||
str = `^/zip${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
// To make "go to definition" work,
|
||||
// We have to resolve the actual file system path from virtual path
|
||||
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||
@@ -77,7 +102,7 @@ const moduleWrapper = tsserver => {
|
||||
// everything else is up to neovim
|
||||
case `neovim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile:${str}`;
|
||||
str = `zipfile://${str}`;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
@@ -91,9 +116,28 @@ const moduleWrapper = tsserver => {
|
||||
}
|
||||
|
||||
function fromEditorPath(str) {
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^\^?zip:\//, ``)
|
||||
: str.replace(/^\^?zip:/, ``);
|
||||
switch (hostInfo) {
|
||||
case `coc-nvim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
} break;
|
||||
|
||||
case `neovim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
} break;
|
||||
|
||||
case `vscode`:
|
||||
default: {
|
||||
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// Force enable 'allowLocalPluginLoads'
|
||||
@@ -119,8 +163,9 @@ const moduleWrapper = tsserver => {
|
||||
let hostInfo = `unknown`;
|
||||
|
||||
Object.assign(Session.prototype, {
|
||||
onMessage(/** @type {string} */ message) {
|
||||
const parsedMessage = JSON.parse(message)
|
||||
onMessage(/** @type {string | object} */ message) {
|
||||
const isStringMessage = typeof message === 'string';
|
||||
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||
|
||||
if (
|
||||
parsedMessage != null &&
|
||||
@@ -129,11 +174,32 @@ const moduleWrapper = tsserver => {
|
||||
typeof parsedMessage.arguments.hostInfo === `string`
|
||||
) {
|
||||
hostInfo = parsedMessage.arguments.hostInfo;
|
||||
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []).map(Number)
|
||||
|
||||
if (major === 1) {
|
||||
if (minor < 61) {
|
||||
hostInfo += ` <1.61`;
|
||||
} else if (minor < 66) {
|
||||
hostInfo += ` <1.66`;
|
||||
} else if (minor < 68) {
|
||||
hostInfo += ` <1.68`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === `string` ? fromEditorPath(value) : value;
|
||||
}));
|
||||
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||
});
|
||||
|
||||
return originalOnMessage.call(
|
||||
this,
|
||||
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||
);
|
||||
},
|
||||
|
||||
send(/** @type {any} */ msg) {
|
||||
|
||||
+78
-12
@@ -18,6 +18,7 @@ const moduleWrapper = tsserver => {
|
||||
const pnpApi = require(`pnpapi`);
|
||||
|
||||
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = str => str.startsWith("portal:/");
|
||||
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
|
||||
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||
@@ -30,7 +31,7 @@ const moduleWrapper = tsserver => {
|
||||
|
||||
function toEditorPath(str) {
|
||||
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||
if (isAbsolute(str) && !str.match(/^\^zip:/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
// We also take the opportunity to turn virtual paths into physical ones;
|
||||
// this makes it much easier to work with workspaces that list peer
|
||||
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||
@@ -44,7 +45,7 @@ const moduleWrapper = tsserver => {
|
||||
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||
if (resolved) {
|
||||
const locator = pnpApi.findPackageLocator(resolved);
|
||||
if (locator && dependencyTreeRoots.has(`${locator.name}@${locator.reference}`)) {
|
||||
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||
str = resolved;
|
||||
}
|
||||
}
|
||||
@@ -60,10 +61,34 @@ const moduleWrapper = tsserver => {
|
||||
//
|
||||
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||
//
|
||||
case `vscode`: {
|
||||
// 2021-10-08: VSCode changed the format in 1.61.
|
||||
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-04-06: VSCode changed the format in 1.66.
|
||||
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||
//
|
||||
// 2022-05-06: VSCode changed the format in 1.68
|
||||
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
case `vscode <1.61`: {
|
||||
str = `^zip:${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.66`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode <1.68`: {
|
||||
str = `^/zip${str}`;
|
||||
} break;
|
||||
|
||||
case `vscode`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
|
||||
// To make "go to definition" work,
|
||||
// We have to resolve the actual file system path from virtual path
|
||||
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||
@@ -77,7 +102,7 @@ const moduleWrapper = tsserver => {
|
||||
// everything else is up to neovim
|
||||
case `neovim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile:${str}`;
|
||||
str = `zipfile://${str}`;
|
||||
} break;
|
||||
|
||||
default: {
|
||||
@@ -91,9 +116,28 @@ const moduleWrapper = tsserver => {
|
||||
}
|
||||
|
||||
function fromEditorPath(str) {
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^\^?zip:\//, ``)
|
||||
: str.replace(/^\^?zip:/, ``);
|
||||
switch (hostInfo) {
|
||||
case `coc-nvim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
} break;
|
||||
|
||||
case `neovim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
} break;
|
||||
|
||||
case `vscode`:
|
||||
default: {
|
||||
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// Force enable 'allowLocalPluginLoads'
|
||||
@@ -119,8 +163,9 @@ const moduleWrapper = tsserver => {
|
||||
let hostInfo = `unknown`;
|
||||
|
||||
Object.assign(Session.prototype, {
|
||||
onMessage(/** @type {string} */ message) {
|
||||
const parsedMessage = JSON.parse(message)
|
||||
onMessage(/** @type {string | object} */ message) {
|
||||
const isStringMessage = typeof message === 'string';
|
||||
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||
|
||||
if (
|
||||
parsedMessage != null &&
|
||||
@@ -129,11 +174,32 @@ const moduleWrapper = tsserver => {
|
||||
typeof parsedMessage.arguments.hostInfo === `string`
|
||||
) {
|
||||
hostInfo = parsedMessage.arguments.hostInfo;
|
||||
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []).map(Number)
|
||||
|
||||
if (major === 1) {
|
||||
if (minor < 61) {
|
||||
hostInfo += ` <1.61`;
|
||||
} else if (minor < 66) {
|
||||
hostInfo += ` <1.66`;
|
||||
} else if (minor < 68) {
|
||||
hostInfo += ` <1.68`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return originalOnMessage.call(this, JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === `string` ? fromEditorPath(value) : value;
|
||||
}));
|
||||
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||
});
|
||||
|
||||
return originalOnMessage.call(
|
||||
this,
|
||||
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||
);
|
||||
},
|
||||
|
||||
send(/** @type {any} */ msg) {
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
const createBabelConfig = options => {
|
||||
const createBabelConfig = (options) => {
|
||||
const { presets = [], plugins = [], removeConsole } = options;
|
||||
// prettier-ignore
|
||||
return {
|
||||
presets: [
|
||||
[require.resolve('@babel/preset-typescript'), {
|
||||
@@ -34,7 +35,7 @@ const createBabelConfig = options => {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = api => {
|
||||
module.exports = (api) => {
|
||||
api.cache(true);
|
||||
const mode = process.env.NODE_ENV;
|
||||
return createBabelConfig({ mode });
|
||||
|
||||
@@ -54,6 +54,10 @@ function task-bench {
|
||||
yarn tgui:bench @Args
|
||||
}
|
||||
|
||||
function task-prettier {
|
||||
yarn tgui:prettier @Args
|
||||
}
|
||||
|
||||
## Run a linter through all packages
|
||||
function task-lint {
|
||||
yarn run tsc
|
||||
@@ -148,6 +152,7 @@ if ($Args.Length -gt 0) {
|
||||
## Make a production webpack build
|
||||
if ($Args.Length -eq 0) {
|
||||
task-install
|
||||
task-prettier
|
||||
task-lint
|
||||
task-webpack --mode=production
|
||||
exit 0
|
||||
|
||||
Vendored
+12
-13
@@ -27,12 +27,11 @@ type TguiMessage = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
|
||||
type ByondType = {
|
||||
/**
|
||||
* ID of the Byond window this script is running on.
|
||||
* Can be used as a parameter to winget/winset.
|
||||
*/
|
||||
* ID of the Byond window this script is running on.
|
||||
* Can be used as a parameter to winget/winset.
|
||||
*/
|
||||
windowId: string;
|
||||
|
||||
/**
|
||||
@@ -41,8 +40,8 @@ type ByondType = {
|
||||
IS_BYOND: boolean;
|
||||
|
||||
/**
|
||||
* Version of Trident engine of Internet Explorer. Null if N/A.
|
||||
*/
|
||||
* Version of Trident engine of Internet Explorer. Null if N/A.
|
||||
*/
|
||||
TRIDENT: number | null;
|
||||
|
||||
/**
|
||||
@@ -145,20 +144,20 @@ type ByondType = {
|
||||
parseJson(text: string): any;
|
||||
|
||||
/**
|
||||
* Sends a message to `/datum/tgui_window` which hosts this window instance.
|
||||
*/
|
||||
* Sends a message to `/datum/tgui_window` which hosts this window instance.
|
||||
*/
|
||||
sendMessage(type: string, payload?: any): void;
|
||||
sendMessage(message: TguiMessage): void;
|
||||
|
||||
/**
|
||||
* Subscribe to incoming messages that were sent from `/datum/tgui_window`.
|
||||
*/
|
||||
* Subscribe to incoming messages that were sent from `/datum/tgui_window`.
|
||||
*/
|
||||
subscribe(listener: (type: string, payload: any) => void): void;
|
||||
|
||||
/**
|
||||
* Subscribe to incoming messages *of some specific type*
|
||||
* that were sent from `/datum/tgui_window`.
|
||||
*/
|
||||
* Subscribe to incoming messages *of some specific type*
|
||||
* that were sent from `/datum/tgui_window`.
|
||||
*/
|
||||
subscribeTo(type: string, listener: (payload: any) => void): void;
|
||||
|
||||
/**
|
||||
|
||||
+2
-7
@@ -1,12 +1,7 @@
|
||||
module.exports = {
|
||||
roots: ['<rootDir>/packages'],
|
||||
testMatch: [
|
||||
'<rootDir>/packages/**/__tests__/*.{js,ts,tsx}',
|
||||
'<rootDir>/packages/**/*.{spec,test}.{js,ts,tsx}',
|
||||
],
|
||||
testPathIgnorePatterns: [
|
||||
'<rootDir>/packages/tgui-bench',
|
||||
],
|
||||
testMatch: ['<rootDir>/packages/**/__tests__/*.{js,ts,tsx}', '<rootDir>/packages/**/*.{spec,test}.{js,ts,tsx}'],
|
||||
testPathIgnorePatterns: ['<rootDir>/packages/tgui-bench'],
|
||||
testEnvironment: 'jsdom',
|
||||
testRunner: require.resolve('jest-circus/runner'),
|
||||
transform: {
|
||||
|
||||
+6
-3
@@ -7,16 +7,17 @@
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"tgui:build": "webpack",
|
||||
"tgui:analyze": "webpack --analyze",
|
||||
"tgui:bench": "webpack --env TGUI_BENCH=1 && node packages/tgui-bench/index.js",
|
||||
"tgui:build": "webpack",
|
||||
"tgui:dev": "node --experimental-modules packages/tgui-dev-server/index.js",
|
||||
"tgui:lint": "eslint packages --ext .js,.cjs,.ts,.tsx",
|
||||
"tgui:prettier": "prettierx --check .",
|
||||
"tgui:sonar": "eslint packages --ext .js,.cjs,.ts,.tsx -c .eslintrc-harder.yml",
|
||||
"tgui:tsc": "tsc",
|
||||
"tgui:test": "jest --watch",
|
||||
"tgui:test-simple": "CI=true jest --color",
|
||||
"tgui:test-ci": "CI=true jest --color --collect-coverage",
|
||||
"tgui:bench": "webpack --env TGUI_BENCH=1 && node packages/tgui-bench/index.js"
|
||||
"tgui:tsc": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.18.0",
|
||||
@@ -38,6 +39,7 @@
|
||||
"common": "workspace:*",
|
||||
"css-loader": "^6.7.1",
|
||||
"eslint": "^8.16.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-radar": "^0.2.1",
|
||||
"eslint-plugin-react": "^7.30.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
@@ -48,6 +50,7 @@
|
||||
"jest-environment-jsdom": "^28.1.0",
|
||||
"jsdom": "^19.0.0",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"prettier": "npm:prettierx@0.19.0",
|
||||
"sass": "^1.52.1",
|
||||
"sass-loader": "^13.0.0",
|
||||
"style-loader": "^3.3.1",
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { range, zip } from "./collections";
|
||||
import { range, zip } from './collections';
|
||||
|
||||
// Type assertions, these will lint if the types are wrong.
|
||||
const _zip1: [string, number] = zip(["a"], [1])[0];
|
||||
const _zip1: [string, number] = zip(['a'], [1])[0];
|
||||
|
||||
describe("range", () => {
|
||||
test("range(0, 5)", () => {
|
||||
describe('range', () => {
|
||||
test('range(0, 5)', () => {
|
||||
expect(range(0, 5)).toEqual([0, 1, 2, 3, 4]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("zip", () => {
|
||||
describe('zip', () => {
|
||||
test("zip(['a', 'b', 'c'], [1, 2, 3, 4])", () => {
|
||||
expect(zip(["a", "b", "c"], [1, 2, 3, 4])).toEqual([
|
||||
["a", 1],
|
||||
["b", 2],
|
||||
["c", 3],
|
||||
expect(zip(['a', 'b', 'c'], [1, 2, 3, 4])).toEqual([
|
||||
['a', 1],
|
||||
['b', 2],
|
||||
['c', 3],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,40 +14,31 @@
|
||||
*
|
||||
* @returns {any[]}
|
||||
*/
|
||||
export const filter = <T>(iterateeFn: (
|
||||
input: T,
|
||||
index: number,
|
||||
collection: T[],
|
||||
) => boolean) =>
|
||||
(collection: T[]): T[] => {
|
||||
if (collection === null || collection === undefined) {
|
||||
return collection;
|
||||
}
|
||||
if (Array.isArray(collection)) {
|
||||
const result: T[] = [];
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
const item = collection[i];
|
||||
if (iterateeFn(item, i, collection)) {
|
||||
result.push(item);
|
||||
}
|
||||
export const filter =
|
||||
<T>(iterateeFn: (input: T, index: number, collection: T[]) => boolean) =>
|
||||
(collection: T[]): T[] => {
|
||||
if (collection === null || collection === undefined) {
|
||||
return collection;
|
||||
}
|
||||
if (Array.isArray(collection)) {
|
||||
const result: T[] = [];
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
const item = collection[i];
|
||||
if (iterateeFn(item, i, collection)) {
|
||||
result.push(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throw new Error(`filter() can't iterate on type ${typeof collection}`);
|
||||
};
|
||||
return result;
|
||||
}
|
||||
throw new Error(`filter() can't iterate on type ${typeof collection}`);
|
||||
};
|
||||
|
||||
type MapFunction = {
|
||||
<T, U>(iterateeFn: (
|
||||
value: T,
|
||||
index: number,
|
||||
collection: T[],
|
||||
) => U): (collection: T[]) => U[];
|
||||
<T, U>(iterateeFn: (value: T, index: number, collection: T[]) => U): (collection: T[]) => U[];
|
||||
|
||||
<T, U, K extends string | number>(iterateeFn: (
|
||||
value: T,
|
||||
index: K,
|
||||
collection: Record<K, T>,
|
||||
) => U): (collection: Record<K, T>) => U[];
|
||||
<T, U, K extends string | number>(iterateeFn: (value: T, index: K, collection: Record<K, T>) => U): (
|
||||
collection: Record<K, T>
|
||||
) => U[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -58,7 +49,8 @@ type MapFunction = {
|
||||
* If collection is 'null' or 'undefined', it will be returned "as is"
|
||||
* without emitting any errors (which can be useful in some cases).
|
||||
*/
|
||||
export const map: MapFunction = <T, U>(iterateeFn) =>
|
||||
export const map: MapFunction =
|
||||
<T, U>(iterateeFn) =>
|
||||
(collection: T[]): U[] => {
|
||||
if (collection === null || collection === undefined) {
|
||||
return collection;
|
||||
@@ -102,22 +94,22 @@ const COMPARATOR = (objA, objB) => {
|
||||
*
|
||||
* @returns {any[]}
|
||||
*/
|
||||
export const sortBy = <T>(
|
||||
...iterateeFns: ((input: T) => unknown)[]
|
||||
) => (array: T[]): T[] => {
|
||||
export const sortBy =
|
||||
<T>(...iterateeFns: ((input: T) => unknown)[]) =>
|
||||
(array: T[]): T[] => {
|
||||
if (!Array.isArray(array)) {
|
||||
return array;
|
||||
}
|
||||
let length = array.length;
|
||||
// Iterate over the array to collect criteria to sort it by
|
||||
let mappedArray: {
|
||||
criteria: unknown[],
|
||||
value: T,
|
||||
criteria: unknown[];
|
||||
value: T;
|
||||
}[] = [];
|
||||
for (let i = 0; i < length; i++) {
|
||||
const value = array[i];
|
||||
mappedArray.push({
|
||||
criteria: iterateeFns.map(fn => fn(value)),
|
||||
criteria: iterateeFns.map((fn) => fn(value)),
|
||||
value,
|
||||
});
|
||||
}
|
||||
@@ -144,15 +136,14 @@ export const range = (start: number, end: number): number[] =>
|
||||
/**
|
||||
* A fast implementation of reduce.
|
||||
*/
|
||||
export const reduce = (reducerFn, initialValue) => array => {
|
||||
export const reduce = (reducerFn, initialValue) => (array) => {
|
||||
const length = array.length;
|
||||
let i;
|
||||
let result;
|
||||
if (initialValue === undefined) {
|
||||
i = 1;
|
||||
result = array[0];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
i = 0;
|
||||
result = initialValue;
|
||||
}
|
||||
@@ -173,15 +164,14 @@ export const reduce = (reducerFn, initialValue) => array => {
|
||||
* is determined by the order they occur in the array. The iteratee is
|
||||
* invoked with one argument: value.
|
||||
*/
|
||||
export const uniqBy = <T extends unknown>(
|
||||
iterateeFn?: (value: T) => unknown
|
||||
) => (array: T[]): T[] => {
|
||||
export const uniqBy =
|
||||
<T extends unknown>(iterateeFn?: (value: T) => unknown) =>
|
||||
(array: T[]): T[] => {
|
||||
const { length } = array;
|
||||
const result: T[] = [];
|
||||
const seen: unknown[] = iterateeFn ? [] : result;
|
||||
let index = -1;
|
||||
outer:
|
||||
while (++index < length) {
|
||||
outer: while (++index < length) {
|
||||
let value: T | 0 = array[index];
|
||||
const computed = iterateeFn ? iterateeFn(value) : value;
|
||||
if (computed === computed) {
|
||||
@@ -195,8 +185,7 @@ export const uniqBy = <T extends unknown>(
|
||||
seen.push(computed);
|
||||
}
|
||||
result.push(value);
|
||||
}
|
||||
else if (!seen.includes(computed)) {
|
||||
} else if (!seen.includes(computed)) {
|
||||
if (seen !== result) {
|
||||
seen.push(computed);
|
||||
}
|
||||
@@ -242,7 +231,8 @@ export const zip = <T extends unknown[][]>(...arrays: T): Zip<T> => {
|
||||
* specify how grouped values should be combined. The iteratee is
|
||||
* invoked with the elements of each group.
|
||||
*/
|
||||
export const zipWith = <T, U>(iterateeFn: (...values: T[]) => U) =>
|
||||
export const zipWith =
|
||||
<T, U>(iterateeFn: (...values: T[]) => U) =>
|
||||
(...arrays: T[][]): U[] => {
|
||||
return map((values: T[]) => iterateeFn(...values))(zip(...arrays));
|
||||
};
|
||||
|
||||
@@ -22,23 +22,14 @@ export class Color {
|
||||
/**
|
||||
* Creates a color from the CSS hex color notation.
|
||||
*/
|
||||
Color.fromHex = hex => (
|
||||
new Color(
|
||||
parseInt(hex.substr(1, 2), 16),
|
||||
parseInt(hex.substr(3, 2), 16),
|
||||
parseInt(hex.substr(5, 2), 16))
|
||||
);
|
||||
Color.fromHex = (hex) =>
|
||||
new Color(parseInt(hex.substr(1, 2), 16), parseInt(hex.substr(3, 2), 16), parseInt(hex.substr(5, 2), 16));
|
||||
|
||||
/**
|
||||
* Linear interpolation of two colors.
|
||||
*/
|
||||
Color.lerp = (c1, c2, n) => (
|
||||
new Color(
|
||||
(c2.r - c1.r) * n + c1.r,
|
||||
(c2.g - c1.g) * n + c1.g,
|
||||
(c2.b - c1.b) * n + c1.b,
|
||||
(c2.a - c1.a) * n + c1.a)
|
||||
);
|
||||
Color.lerp = (c1, c2, n) =>
|
||||
new Color((c2.r - c1.r) * n + c1.r, (c2.g - c1.g) * n + c1.g, (c2.b - c1.b) * n + c1.b, (c2.a - c1.a) * n + c1.a);
|
||||
|
||||
/**
|
||||
* Loops up the color in the provided list of colors
|
||||
|
||||
@@ -19,10 +19,9 @@ export class EventEmitter {
|
||||
if (!listeners) {
|
||||
throw new Error(`There is no listeners for "${name}"`);
|
||||
}
|
||||
this.listeners[name] = listeners
|
||||
.filter(existingListener => {
|
||||
return existingListener !== listener;
|
||||
});
|
||||
this.listeners[name] = listeners.filter((existingListener) => {
|
||||
return existingListener !== listener;
|
||||
});
|
||||
}
|
||||
|
||||
emit(name, ...params) {
|
||||
|
||||
+19
-15
@@ -9,19 +9,20 @@
|
||||
* functions, where each successive invocation is supplied the return
|
||||
* value of the previous.
|
||||
*/
|
||||
export const flow = (...funcs) => (input, ...rest) => {
|
||||
let output = input;
|
||||
for (let func of funcs) {
|
||||
// Recurse into the array of functions
|
||||
if (Array.isArray(func)) {
|
||||
output = flow(...func)(output, ...rest);
|
||||
export const flow =
|
||||
(...funcs) =>
|
||||
(input, ...rest) => {
|
||||
let output = input;
|
||||
for (let func of funcs) {
|
||||
// Recurse into the array of functions
|
||||
if (Array.isArray(func)) {
|
||||
output = flow(...func)(output, ...rest);
|
||||
} else if (func) {
|
||||
output = func(output, ...rest);
|
||||
}
|
||||
}
|
||||
else if (func) {
|
||||
output = func(output, ...rest);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
return output;
|
||||
};
|
||||
|
||||
/**
|
||||
* Composes single-argument functions from right to left.
|
||||
@@ -37,11 +38,14 @@ export const flow = (...funcs) => (input, ...rest) => {
|
||||
*/
|
||||
export const compose = (...funcs) => {
|
||||
if (funcs.length === 0) {
|
||||
return arg => arg;
|
||||
return (arg) => arg;
|
||||
}
|
||||
if (funcs.length === 1) {
|
||||
return funcs[0];
|
||||
}
|
||||
return funcs.reduce((a, b) => (value, ...rest) =>
|
||||
a(b(value, ...rest), ...rest));
|
||||
return funcs.reduce(
|
||||
(a, b) =>
|
||||
(value, ...rest) =>
|
||||
a(b(value, ...rest), ...rest)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ export const clamp = (value, min, max) => {
|
||||
/**
|
||||
* Limits a number between 0 and 1.
|
||||
*/
|
||||
export const clamp01 = value => {
|
||||
export const clamp01 = (value) => {
|
||||
return value < 0 ? 0 : value > 1 ? 1 : value;
|
||||
};
|
||||
|
||||
@@ -69,9 +69,7 @@ export const toFixed = (value, fractionDigits = 0) => {
|
||||
* Range is an array of two numbers, for example: [0, 15].
|
||||
*/
|
||||
export const inRange = (value, range) => {
|
||||
return range
|
||||
&& value >= range[0]
|
||||
&& value <= range[1];
|
||||
return range && value >= range[0] && value <= range[1];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -92,7 +90,7 @@ export const keyOfMatchingRange = (value, ranges) => {
|
||||
/**
|
||||
* Get number of digits following the decimal point in a number
|
||||
*/
|
||||
export const numberOfDecimalDigits = value => {
|
||||
export const numberOfDecimalDigits = (value) => {
|
||||
if (Math.floor(value) !== value) {
|
||||
return value.toString().split('.')[1].length || 0;
|
||||
}
|
||||
|
||||
@@ -48,10 +48,9 @@ const measure = (markerNameA, markerNameB) => {
|
||||
}
|
||||
};
|
||||
|
||||
const formatDuration = duration => {
|
||||
const formatDuration = (duration) => {
|
||||
const durationInFrames = duration / FRAME_DURATION;
|
||||
return duration.toFixed(duration < 10 ? 1 : 0) + 'ms '
|
||||
+ '(' + durationInFrames.toFixed(2) + ' frames)';
|
||||
return duration.toFixed(duration < 10 ? 1 : 0) + 'ms ' + '(' + durationInFrames.toFixed(2) + ' frames)';
|
||||
};
|
||||
|
||||
export const perf = {
|
||||
|
||||
@@ -24,7 +24,7 @@ export const classes = (classNames: (string | BooleanLike)[]) => {
|
||||
*/
|
||||
export const normalizeChildren = <T>(children: T | T[]) => {
|
||||
if (Array.isArray(children)) {
|
||||
return children.flat().filter(value => value) as T[];
|
||||
return children.flat().filter((value) => value) as T[];
|
||||
}
|
||||
if (typeof children === 'object') {
|
||||
return [children];
|
||||
@@ -64,9 +64,7 @@ export const pureComponentHooks = {
|
||||
* A helper to determine whether the object is renderable by React.
|
||||
*/
|
||||
export const canRender = (value: unknown) => {
|
||||
return value !== undefined
|
||||
&& value !== null
|
||||
&& typeof value !== 'boolean';
|
||||
return value !== undefined && value !== null && typeof value !== 'boolean';
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,11 +20,11 @@ export const createStore = (reducer, enhancer) => {
|
||||
|
||||
const getState = () => currentState;
|
||||
|
||||
const subscribe = listener => {
|
||||
const subscribe = (listener) => {
|
||||
listeners.push(listener);
|
||||
};
|
||||
|
||||
const dispatch = action => {
|
||||
const dispatch = (action) => {
|
||||
currentState = reducer(currentState, action);
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i]();
|
||||
@@ -49,27 +49,27 @@ export const createStore = (reducer, enhancer) => {
|
||||
* actions.
|
||||
*/
|
||||
export const applyMiddleware = (...middlewares) => {
|
||||
return createStore => (reducer, ...args) => {
|
||||
const store = createStore(reducer, ...args);
|
||||
return (createStore) =>
|
||||
(reducer, ...args) => {
|
||||
const store = createStore(reducer, ...args);
|
||||
|
||||
let dispatch = () => {
|
||||
throw new Error(
|
||||
'Dispatching while constructing your middleware is not allowed.');
|
||||
let dispatch = () => {
|
||||
throw new Error('Dispatching while constructing your middleware is not allowed.');
|
||||
};
|
||||
|
||||
const storeApi = {
|
||||
getState: store.getState,
|
||||
dispatch: (action, ...args) => dispatch(action, ...args),
|
||||
};
|
||||
|
||||
const chain = middlewares.map((middleware) => middleware(storeApi));
|
||||
dispatch = compose(...chain)(store.dispatch);
|
||||
|
||||
return {
|
||||
...store,
|
||||
dispatch,
|
||||
};
|
||||
};
|
||||
|
||||
const storeApi = {
|
||||
getState: store.getState,
|
||||
dispatch: (action, ...args) => dispatch(action, ...args),
|
||||
};
|
||||
|
||||
const chain = middlewares.map(middleware => middleware(storeApi));
|
||||
dispatch = compose(...chain)(store.dispatch);
|
||||
|
||||
return {
|
||||
...store,
|
||||
dispatch,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -80,7 +80,7 @@ export const applyMiddleware = (...middlewares) => {
|
||||
* in the state that are not present in the reducers object. This function
|
||||
* is also more flexible than the redux counterpart.
|
||||
*/
|
||||
export const combineReducers = reducersObj => {
|
||||
export const combineReducers = (reducersObj) => {
|
||||
const keys = Object.keys(reducersObj);
|
||||
let hasChanged = false;
|
||||
return (prevState = {}, action) => {
|
||||
@@ -94,9 +94,7 @@ export const combineReducers = reducersObj => {
|
||||
nextState[key] = nextDomainState;
|
||||
}
|
||||
}
|
||||
return hasChanged
|
||||
? nextState
|
||||
: prevState;
|
||||
return hasChanged ? nextState : prevState;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -136,15 +134,14 @@ export const createAction = (type, prepare = null) => {
|
||||
};
|
||||
actionCreator.toString = () => '' + type;
|
||||
actionCreator.type = type;
|
||||
actionCreator.match = action => action.type === type;
|
||||
actionCreator.match = (action) => action.type === type;
|
||||
return actionCreator;
|
||||
};
|
||||
|
||||
|
||||
// Implementation specific
|
||||
// --------------------------------------------------------
|
||||
|
||||
export const useDispatch = context => {
|
||||
export const useDispatch = (context) => {
|
||||
return context.store.dispatch;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,11 +17,10 @@ const INDEXED_DB_STORE_NAME = 'storage-v1';
|
||||
const READ_ONLY = 'readonly';
|
||||
const READ_WRITE = 'readwrite';
|
||||
|
||||
const testGeneric = testFn => () => {
|
||||
const testGeneric = (testFn) => () => {
|
||||
try {
|
||||
return Boolean(testFn());
|
||||
}
|
||||
catch {
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -29,14 +28,11 @@ const testGeneric = testFn => () => {
|
||||
// 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 testLocalStorage = testGeneric(() => window.localStorage && window.localStorage.getItem);
|
||||
|
||||
const testIndexedDb = testGeneric(() => (
|
||||
(window.indexedDB || window.msIndexedDB)
|
||||
&& (window.IDBTransaction || window.msIDBTransaction)
|
||||
));
|
||||
const testIndexedDb = testGeneric(
|
||||
() => (window.indexedDB || window.msIndexedDB) && (window.IDBTransaction || window.msIDBTransaction)
|
||||
);
|
||||
|
||||
class MemoryBackend {
|
||||
constructor() {
|
||||
@@ -96,8 +92,7 @@ class IndexedDbBackend {
|
||||
req.onupgradeneeded = () => {
|
||||
try {
|
||||
req.result.createObjectStore(INDEXED_DB_STORE_NAME);
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
reject(new Error('Failed to upgrade IDB: ' + req.error));
|
||||
}
|
||||
};
|
||||
@@ -109,9 +104,7 @@ class IndexedDbBackend {
|
||||
}
|
||||
|
||||
getStore(mode) {
|
||||
return this.dbPromise.then(db => db
|
||||
.transaction(INDEXED_DB_STORE_NAME, mode)
|
||||
.objectStore(INDEXED_DB_STORE_NAME));
|
||||
return this.dbPromise.then((db) => db.transaction(INDEXED_DB_STORE_NAME, mode).objectStore(INDEXED_DB_STORE_NAME));
|
||||
}
|
||||
|
||||
async get(key) {
|
||||
@@ -161,8 +154,7 @@ class StorageProxy {
|
||||
const backend = new IndexedDbBackend();
|
||||
await backend.dbPromise;
|
||||
return backend;
|
||||
}
|
||||
catch {}
|
||||
} catch {}
|
||||
}
|
||||
if (testLocalStorage()) {
|
||||
return new LocalStorageBackend();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
/**
|
||||
* Removes excess whitespace and indentation from the string.
|
||||
*/
|
||||
const multiline = str => {
|
||||
const multiline = (str) => {
|
||||
const lines = str.split('\n');
|
||||
// Determine base indentation
|
||||
let minIndent;
|
||||
@@ -40,15 +40,15 @@ const multiline = str => {
|
||||
// Remove this base indentation and trim the resulting string
|
||||
// from both ends.
|
||||
return lines
|
||||
.map(line => line.substr(minIndent).trimRight())
|
||||
.map((line) => line.substr(minIndent).trimRight())
|
||||
.join('\n')
|
||||
.trim();
|
||||
};
|
||||
|
||||
const StringPlugin = ref => {
|
||||
const StringPlugin = (ref) => {
|
||||
return {
|
||||
visitor: {
|
||||
TaggedTemplateExpression: path => {
|
||||
TaggedTemplateExpression: (path) => {
|
||||
if (path.node.tag.name === 'multiline') {
|
||||
const { quasi } = path.node;
|
||||
if (quasi.expressions.length > 0) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/**
|
||||
* Removes excess whitespace and indentation from the string.
|
||||
*/
|
||||
export const multiline = str => {
|
||||
export const multiline = (str) => {
|
||||
if (Array.isArray(str)) {
|
||||
// Small stub to allow usage as a template tag
|
||||
return multiline(str.join(''));
|
||||
@@ -32,7 +32,7 @@ export const multiline = str => {
|
||||
// Remove this base indentation and trim the resulting string
|
||||
// from both ends.
|
||||
return lines
|
||||
.map(line => line.substr(minIndent).trimRight())
|
||||
.map((line) => line.substr(minIndent).trimRight())
|
||||
.join('\n')
|
||||
.trim();
|
||||
};
|
||||
@@ -44,12 +44,17 @@ export const multiline = str => {
|
||||
*
|
||||
* Example: createGlobPattern('*@domain')('user@domain') === true
|
||||
*/
|
||||
export const createGlobPattern = pattern => {
|
||||
const escapeString = str => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
|
||||
const regex = new RegExp('^'
|
||||
+ pattern.split(/\*+/).map(escapeString).join('.*')
|
||||
+ '$');
|
||||
return str => regex.test(str);
|
||||
export const createGlobPattern = (pattern) => {
|
||||
const escapeString = (str) => str.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
|
||||
const regex = new RegExp(
|
||||
'^' +
|
||||
pattern
|
||||
.split(/\*+/)
|
||||
.map(escapeString)
|
||||
.join('.*') +
|
||||
'$'
|
||||
);
|
||||
return (str) => regex.test(str);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -64,7 +69,7 @@ export const createGlobPattern = pattern => {
|
||||
*/
|
||||
export const createSearch = (searchText, stringifier) => {
|
||||
const preparedSearchText = searchText.toLowerCase().trim();
|
||||
return obj => {
|
||||
return (obj) => {
|
||||
if (!preparedSearchText) {
|
||||
return true;
|
||||
}
|
||||
@@ -72,17 +77,15 @@ export const createSearch = (searchText, stringifier) => {
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
return str
|
||||
.toLowerCase()
|
||||
.includes(preparedSearchText);
|
||||
return str.toLowerCase().includes(preparedSearchText);
|
||||
};
|
||||
};
|
||||
|
||||
export const isUppercase = chr => {
|
||||
export const isUppercase = (chr) => {
|
||||
return chr.toUpperCase() === chr;
|
||||
};
|
||||
|
||||
export const capitalize = str => {
|
||||
export const capitalize = (str) => {
|
||||
// Handle array
|
||||
if (Array.isArray(str)) {
|
||||
return str.map(capitalize);
|
||||
@@ -95,7 +98,7 @@ export const capitalize = str => {
|
||||
return chr.toUpperCase() + str.slice(1).toLowerCase();
|
||||
};
|
||||
|
||||
export const toTitleCase = str => {
|
||||
export const toTitleCase = (str) => {
|
||||
// Handle array
|
||||
if (Array.isArray(str)) {
|
||||
return str.map(toTitleCase);
|
||||
@@ -107,19 +110,38 @@ export const toTitleCase = str => {
|
||||
// Handle string
|
||||
const WORDS_UPPER = ['Id', 'Tv', 'Rcd']; // VOREStation Edit
|
||||
const WORDS_LOWER = [
|
||||
'A', 'An', 'And', 'As', 'At', 'But', 'By', 'For', 'For', 'From', 'In',
|
||||
'Into', 'Near', 'Nor', 'Of', 'On', 'Onto', 'Or', 'The', 'To', 'With',
|
||||
'A',
|
||||
'An',
|
||||
'And',
|
||||
'As',
|
||||
'At',
|
||||
'But',
|
||||
'By',
|
||||
'For',
|
||||
'For',
|
||||
'From',
|
||||
'In',
|
||||
'Into',
|
||||
'Near',
|
||||
'Nor',
|
||||
'Of',
|
||||
'On',
|
||||
'Onto',
|
||||
'Or',
|
||||
'The',
|
||||
'To',
|
||||
'With',
|
||||
];
|
||||
let currentStr = str.replace(/([^\W_]+[^\s-]*) */g, str => {
|
||||
let currentStr = str.replace(/([^\W_]+[^\s-]*) */g, (str) => {
|
||||
return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
|
||||
});
|
||||
for (let word of WORDS_LOWER) {
|
||||
const regex = new RegExp('\\s' + word + '\\s', 'g');
|
||||
currentStr = currentStr.replace(regex, str => str.toLowerCase());
|
||||
currentStr = currentStr.replace(regex, (str) => str.toLowerCase());
|
||||
}
|
||||
for (let word of WORDS_UPPER) {
|
||||
const regex = new RegExp('\\b' + word + '\\b', 'g');
|
||||
currentStr = currentStr.replace(regex, str => str.toUpperCase());
|
||||
currentStr = currentStr.replace(regex, (str) => str.toUpperCase());
|
||||
}
|
||||
return currentStr;
|
||||
};
|
||||
@@ -130,7 +152,7 @@ export const toTitleCase = str => {
|
||||
* @param {String} str Encoded HTML string
|
||||
* @return {String} Decoded HTML string
|
||||
*/
|
||||
export const decodeHtmlEntities = str => {
|
||||
export const decodeHtmlEntities = (str) => {
|
||||
if (!str) {
|
||||
return str;
|
||||
}
|
||||
@@ -142,31 +164,33 @@ export const decodeHtmlEntities = str => {
|
||||
quot: '"',
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
apos: '\'',
|
||||
apos: "'",
|
||||
trade: '™',
|
||||
};
|
||||
return str
|
||||
// Newline tags
|
||||
.replace(/<br>/gi, '\n')
|
||||
.replace(/<\/?[a-z0-9-_]+[^>]*>/gi, '')
|
||||
// Basic entities
|
||||
.replace(translate_re, (match, entity) => translate[entity])
|
||||
// Decimal entities
|
||||
.replace(/&#?([0-9]+);/gi, (match, numStr) => {
|
||||
const num = parseInt(numStr, 10);
|
||||
return String.fromCharCode(num);
|
||||
})
|
||||
// Hex entities
|
||||
.replace(/&#x?([0-9a-f]+);/gi, (match, numStr) => {
|
||||
const num = parseInt(numStr, 16);
|
||||
return String.fromCharCode(num);
|
||||
});
|
||||
return (
|
||||
str
|
||||
// Newline tags
|
||||
.replace(/<br>/gi, '\n')
|
||||
.replace(/<\/?[a-z0-9-_]+[^>]*>/gi, '')
|
||||
// Basic entities
|
||||
.replace(translate_re, (match, entity) => translate[entity])
|
||||
// Decimal entities
|
||||
.replace(/&#?([0-9]+);/gi, (match, numStr) => {
|
||||
const num = parseInt(numStr, 10);
|
||||
return String.fromCharCode(num);
|
||||
})
|
||||
// Hex entities
|
||||
.replace(/&#x?([0-9a-f]+);/gi, (match, numStr) => {
|
||||
const num = parseInt(numStr, 16);
|
||||
return String.fromCharCode(num);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an object into a query string,
|
||||
*/
|
||||
export const buildQueryString = obj => Object.keys(obj)
|
||||
.map(key => encodeURIComponent(key)
|
||||
+ '=' + encodeURIComponent(obj[key]))
|
||||
.join('&');
|
||||
export const buildQueryString = (obj) =>
|
||||
Object.keys(obj)
|
||||
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
|
||||
.join('&');
|
||||
|
||||
@@ -33,6 +33,4 @@ export const debounce = (fn, time, immediate = false) => {
|
||||
*
|
||||
* @param {number} time
|
||||
*/
|
||||
export const sleep = time => (
|
||||
new Promise(resolve => setTimeout(resolve, time))
|
||||
);
|
||||
export const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/**
|
||||
* Returns the arguments of a function F as an array.
|
||||
*/
|
||||
export type ArgumentsOf<F extends Function>
|
||||
= F extends (...args: infer A) => unknown ? A : never;
|
||||
export type ArgumentsOf<F extends Function> = F extends (...args: infer A) => unknown ? A : never;
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
*/
|
||||
export const createUuid = () => {
|
||||
let d = new Date().getTime();
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
const r = (d + Math.random() * 16) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -32,17 +32,17 @@ export const vecDivide = (...vecs) => {
|
||||
};
|
||||
|
||||
export const vecScale = (vec, n) => {
|
||||
return map(x => x * n)(vec);
|
||||
return map((x) => x * n)(vec);
|
||||
};
|
||||
|
||||
export const vecInverse = vec => {
|
||||
return map(x => -x)(vec);
|
||||
export const vecInverse = (vec) => {
|
||||
return map((x) => -x)(vec);
|
||||
};
|
||||
|
||||
export const vecLength = vec => {
|
||||
export const vecLength = (vec) => {
|
||||
return Math.sqrt(reduce(ADD)(zipWith(MUL)(vec, vec)));
|
||||
};
|
||||
|
||||
export const vecNormalize = vec => {
|
||||
export const vecNormalize = (vec) => {
|
||||
return vecDivide(vec, vecLength(vec));
|
||||
};
|
||||
|
||||
Vendored
+24
-23
@@ -1,50 +1,51 @@
|
||||
@font-face {
|
||||
font-family: "tgfont";
|
||||
src: url("./tgfont.woff2?45c3c7acc69dd413375d77898d24e41e") format("woff2"),
|
||||
url("./tgfont.eot?45c3c7acc69dd413375d77898d24e41e#iefix") format("embedded-opentype");
|
||||
font-family: 'tgfont';
|
||||
src: url('./tgfont.woff2?45c3c7acc69dd413375d77898d24e41e') format('woff2'),
|
||||
url('./tgfont.eot?45c3c7acc69dd413375d77898d24e41e#iefix') format('embedded-opentype');
|
||||
}
|
||||
|
||||
i[class^="tg-"]:before, i[class*=" tg-"]:before {
|
||||
font-family: tgfont !important;
|
||||
font-style: normal;
|
||||
font-weight: normal !important;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
i[class^='tg-']:before,
|
||||
i[class*=' tg-']:before {
|
||||
font-family: tgfont !important;
|
||||
font-style: normal;
|
||||
font-weight: normal !important;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.tg-air-tank-slash:before {
|
||||
content: "\f101";
|
||||
content: '\f101';
|
||||
}
|
||||
.tg-air-tank:before {
|
||||
content: "\f102";
|
||||
content: '\f102';
|
||||
}
|
||||
.tg-bad-touch:before {
|
||||
content: "\f103";
|
||||
content: '\f103';
|
||||
}
|
||||
.tg-image-minus:before {
|
||||
content: "\f104";
|
||||
content: '\f104';
|
||||
}
|
||||
.tg-image-plus:before {
|
||||
content: "\f105";
|
||||
content: '\f105';
|
||||
}
|
||||
.tg-nanotrasen-logo:before {
|
||||
content: "\f106";
|
||||
content: '\f106';
|
||||
}
|
||||
.tg-non-binary:before {
|
||||
content: "\f107";
|
||||
content: '\f107';
|
||||
}
|
||||
.tg-prosthetic-leg:before {
|
||||
content: "\f108";
|
||||
content: '\f108';
|
||||
}
|
||||
.tg-sound-minus:before {
|
||||
content: "\f109";
|
||||
content: '\f109';
|
||||
}
|
||||
.tg-sound-plus:before {
|
||||
content: "\f10a";
|
||||
content: '\f10a';
|
||||
}
|
||||
.tg-syndicate-logo:before {
|
||||
content: "\f10b";
|
||||
content: '\f10b';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
bad-touch.svg contains:
|
||||
|
||||
- hug by Phạm Thanh Lộc from the Noun Project
|
||||
- Fight by Rudez Studio from the Noun Project
|
||||
|
||||
prosthetic-leg.svg contains:
|
||||
|
||||
- prosthetic leg by Gan Khoon Lay from the Noun Project
|
||||
|
||||
@@ -10,5 +10,4 @@ process.chdir(__dirname);
|
||||
// Silently make a dist folder
|
||||
try {
|
||||
require('fs').mkdirSync('dist');
|
||||
}
|
||||
catch (err) {}
|
||||
} catch (err) {}
|
||||
|
||||
@@ -62,8 +62,7 @@ const setupApp = async () => {
|
||||
}
|
||||
suite.run();
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
sendMessage({ type: 'error', error });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@ const setup = async () => {
|
||||
assets += `</script>\n`;
|
||||
|
||||
const publicDir = path.resolve(__dirname, '../../public');
|
||||
const page = fs.readFileSync(path.join(publicDir, 'tgui.html'), 'utf-8')
|
||||
.replace('<!-- tgui:assets -->\n', assets);
|
||||
const page = fs.readFileSync(path.join(publicDir, 'tgui.html'), 'utf-8').replace('<!-- tgui:assets -->\n', assets);
|
||||
|
||||
server.register(require('@fastify/static'), {
|
||||
root: publicDir,
|
||||
@@ -67,8 +66,7 @@ const setup = async () => {
|
||||
|
||||
try {
|
||||
await server.listen(3002, '0.0.0.0');
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
+2
-10
@@ -11,11 +11,7 @@ declare class Benchmark {
|
||||
static filter<T>(arr: T[], filter: string, thisArg?: any): T[];
|
||||
static formatNumber(num: number): string;
|
||||
static join(obj: Object, separator1?: string, separator2?: string): string;
|
||||
static invoke(
|
||||
benches: Benchmark[],
|
||||
name: string | Object,
|
||||
...args: any[]
|
||||
): any[];
|
||||
static invoke(benches: Benchmark[], name: string | Object, ...args: any[]): any[];
|
||||
static runInContext(context: Object): Function;
|
||||
|
||||
static each(obj: Object | any[], callback: Function, thisArg?: any): void;
|
||||
@@ -24,11 +20,7 @@ declare class Benchmark {
|
||||
static has(obj: Object, path: any[] | string): boolean;
|
||||
static indexOf<T>(arr: T[], value: T, fromIndex?: number): number;
|
||||
static map<T, K>(arr: T[], callback: (value: T) => K, thisArg?: any): K[];
|
||||
static reduce<T, K>(
|
||||
arr: T[],
|
||||
callback: (accumulator: K, value: T) => K,
|
||||
thisArg?: any
|
||||
): K;
|
||||
static reduce<T, K>(arr: T[], callback: (accumulator: K, value: T) => K, thisArg?: any): K;
|
||||
|
||||
static options: Benchmark.Options;
|
||||
static platform: Benchmark.Platform;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,40 +7,24 @@ const render = createRenderer();
|
||||
const handleClick = () => undefined;
|
||||
|
||||
export const SingleButton = () => {
|
||||
const node = (
|
||||
<Button>
|
||||
Hello world!
|
||||
</Button>
|
||||
);
|
||||
const node = <Button>Hello world!</Button>;
|
||||
render(node);
|
||||
};
|
||||
|
||||
export const SingleButtonWithCallback = () => {
|
||||
const node = (
|
||||
<Button onClick={() => undefined}>
|
||||
Hello world!
|
||||
</Button>
|
||||
);
|
||||
const node = <Button onClick={() => undefined}>Hello world!</Button>;
|
||||
render(node);
|
||||
};
|
||||
|
||||
export const SingleButtonWithLinkEvent = () => {
|
||||
const node = (
|
||||
<Button onClick={linkEvent(null, handleClick)}>
|
||||
Hello world!
|
||||
</Button>
|
||||
);
|
||||
const node = <Button onClick={linkEvent(null, handleClick)}>Hello world!</Button>;
|
||||
render(node);
|
||||
};
|
||||
|
||||
export const ListOfButtons = () => {
|
||||
const nodes: JSX.Element[] = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const node = (
|
||||
<Button key={i}>
|
||||
Hello world! {i}
|
||||
</Button>
|
||||
);
|
||||
const node = <Button key={i}>Hello world! {i}</Button>;
|
||||
nodes.push(node);
|
||||
}
|
||||
render(<div>{nodes}</div>);
|
||||
|
||||
@@ -6,9 +6,11 @@ import { configureStore, StoreProvider } from 'tgui/store';
|
||||
const store = configureStore({ sideEffets: false });
|
||||
|
||||
const renderUi = createRenderer((dataJson: string) => {
|
||||
store.dispatch(backendUpdate({
|
||||
data: Byond.parseJson(dataJson),
|
||||
}));
|
||||
store.dispatch(
|
||||
backendUpdate({
|
||||
data: Byond.parseJson(dataJson),
|
||||
})
|
||||
);
|
||||
return (
|
||||
<StoreProvider store={store}>
|
||||
<DisposalBin />
|
||||
|
||||
@@ -6,9 +6,7 @@ const render = createRenderer();
|
||||
export const Default = () => {
|
||||
const node = (
|
||||
<Flex align="baseline">
|
||||
<Flex.Item mr={1}>
|
||||
Text {Math.random()}
|
||||
</Flex.Item>
|
||||
<Flex.Item mr={1}>Text {Math.random()}</Flex.Item>
|
||||
<Flex.Item grow={1} basis={0}>
|
||||
Text {Math.random()}
|
||||
</Flex.Item>
|
||||
|
||||
@@ -6,9 +6,7 @@ const render = createRenderer();
|
||||
export const Default = () => {
|
||||
const node = (
|
||||
<Stack align="baseline">
|
||||
<Stack.Item>
|
||||
Text {Math.random()}
|
||||
</Stack.Item>
|
||||
<Stack.Item>Text {Math.random()}</Stack.Item>
|
||||
<Stack.Item grow={1} basis={0}>
|
||||
Text {Math.random()}
|
||||
</Stack.Item>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Box, Tooltip } from "tgui/components";
|
||||
import { createRenderer } from "tgui/renderer";
|
||||
import { Box, Tooltip } from 'tgui/components';
|
||||
import { createRenderer } from 'tgui/renderer';
|
||||
|
||||
const render = createRenderer();
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ export class DreamSeeker {
|
||||
|
||||
topic(params = {}) {
|
||||
const query = Object.keys(params)
|
||||
.map(key => encodeURIComponent(key)
|
||||
+ '=' + encodeURIComponent(params[key]))
|
||||
.map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
|
||||
.join('&');
|
||||
return this.client.get('/dummy?' + query);
|
||||
}
|
||||
@@ -36,7 +35,7 @@ export class DreamSeeker {
|
||||
* @param {number[]} pids
|
||||
* @returns {DreamSeeker[]}
|
||||
*/
|
||||
DreamSeeker.getInstancesByPids = async pids => {
|
||||
DreamSeeker.getInstancesByPids = async (pids) => {
|
||||
if (process.platform !== 'win32') {
|
||||
return [];
|
||||
}
|
||||
@@ -46,8 +45,7 @@ DreamSeeker.getInstancesByPids = async pids => {
|
||||
const instance = instanceByPid.get(pid);
|
||||
if (instance) {
|
||||
instances.push(instance);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pidsToResolve.push(pid);
|
||||
}
|
||||
}
|
||||
@@ -83,12 +81,10 @@ DreamSeeker.getInstancesByPids = async pids => {
|
||||
instances.push(instance);
|
||||
instanceByPid.set(pid, instance);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
if (err.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') {
|
||||
logger.error(err.message, err.code);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
logger.error(err);
|
||||
}
|
||||
return [];
|
||||
@@ -97,4 +93,4 @@ DreamSeeker.getInstancesByPids = async pids => {
|
||||
return instances;
|
||||
};
|
||||
|
||||
const plural = (word, n) => n !== 1 ? word + 's' : word;
|
||||
const plural = (word, n) => (n !== 1 ? word + 's' : word);
|
||||
|
||||
@@ -23,7 +23,7 @@ const ensureConnection = () => {
|
||||
socket.send(msg);
|
||||
}
|
||||
};
|
||||
socket.onmessage = event => {
|
||||
socket.onmessage = (event) => {
|
||||
const msg = JSON.parse(event.data);
|
||||
for (let subscriber of subscribers) {
|
||||
subscriber(msg);
|
||||
@@ -37,14 +37,14 @@ if (process.env.NODE_ENV !== 'production') {
|
||||
window.onunload = () => socket && socket.close();
|
||||
}
|
||||
|
||||
const subscribe = fn => subscribers.push(fn);
|
||||
const subscribe = (fn) => subscribers.push(fn);
|
||||
|
||||
/**
|
||||
* A json serializer which handles circular references and other junk.
|
||||
*/
|
||||
const serializeObject = obj => {
|
||||
const serializeObject = (obj) => {
|
||||
let refs = [];
|
||||
const primitiveReviver = value => {
|
||||
const primitiveReviver = (value) => {
|
||||
if (typeof value === 'number' && !Number.isFinite(value)) {
|
||||
return {
|
||||
__number__: String(value),
|
||||
@@ -68,9 +68,7 @@ const serializeObject = obj => {
|
||||
}
|
||||
refs.push(value);
|
||||
// Error object
|
||||
const isError = value instanceof Error || (
|
||||
value.code && value.message && value.message.includes('Error')
|
||||
);
|
||||
const isError = value instanceof Error || (value.code && value.message && value.message.includes('Error'));
|
||||
if (isError) {
|
||||
return {
|
||||
__error__: true,
|
||||
@@ -91,7 +89,7 @@ const serializeObject = obj => {
|
||||
return json;
|
||||
};
|
||||
|
||||
const sendMessage = msg => {
|
||||
const sendMessage = (msg) => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const json = serializeObject(msg);
|
||||
// Send message using WebSocket
|
||||
@@ -99,8 +97,7 @@ const sendMessage = msg => {
|
||||
ensureConnection();
|
||||
if (socket.readyState === WebSocket.OPEN) {
|
||||
socket.send(json);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Keep only 100 latest messages in the queue
|
||||
if (queue.length > 100) {
|
||||
queue.shift();
|
||||
@@ -130,19 +127,16 @@ const sendLogEntry = (level, ns, ...args) => {
|
||||
args,
|
||||
},
|
||||
});
|
||||
}
|
||||
catch (err) {}
|
||||
} catch (err) {}
|
||||
}
|
||||
};
|
||||
|
||||
const setupHotReloading = () => {
|
||||
if (process.env.NODE_ENV !== 'production'
|
||||
&& process.env.WEBPACK_HMR_ENABLED
|
||||
&& window.WebSocket) {
|
||||
if (process.env.NODE_ENV !== 'production' && process.env.WEBPACK_HMR_ENABLED && window.WebSocket) {
|
||||
if (module.hot) {
|
||||
ensureConnection();
|
||||
sendLogEntry(0, null, 'setting up hot reloading');
|
||||
subscribe(msg => {
|
||||
subscribe((msg) => {
|
||||
const { type } = msg;
|
||||
sendLogEntry(0, null, 'received', type);
|
||||
if (type === 'hotUpdate') {
|
||||
@@ -157,10 +151,10 @@ const setupHotReloading = () => {
|
||||
ignoreDeclined: true,
|
||||
ignoreErrored: true,
|
||||
})
|
||||
.then(modules => {
|
||||
.then((modules) => {
|
||||
sendLogEntry(0, null, 'outdated modules', modules);
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err) => {
|
||||
sendLogEntry(0, null, 'reload error', err);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const logger = createLogger('retrace');
|
||||
const { SourceMapConsumer } = SourceMap;
|
||||
const sourceMaps = [];
|
||||
|
||||
export const loadSourceMaps = async bundleDir => {
|
||||
export const loadSourceMaps = async (bundleDir) => {
|
||||
// Destroy and garbage collect consumers
|
||||
while (sourceMaps.length !== 0) {
|
||||
const { consumer } = sourceMaps.shift();
|
||||
@@ -29,30 +29,28 @@ export const loadSourceMaps = async bundleDir => {
|
||||
for (let path of paths) {
|
||||
try {
|
||||
const file = basename(path).replace('.map', '');
|
||||
const consumer = await new SourceMapConsumer(
|
||||
JSON.parse(fs.readFileSync(path, 'utf8')));
|
||||
const consumer = await new SourceMapConsumer(JSON.parse(fs.readFileSync(path, 'utf8')));
|
||||
sourceMaps.push({ file, consumer });
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
}
|
||||
}
|
||||
logger.log(`loaded ${sourceMaps.length} source maps`);
|
||||
};
|
||||
|
||||
export const retrace = stack => {
|
||||
export const retrace = (stack) => {
|
||||
if (typeof stack !== 'string') {
|
||||
logger.log('ERROR: Stack is not a string!', stack);
|
||||
return stack;
|
||||
}
|
||||
const header = stack.split(/\n\s.*at/)[0];
|
||||
const mappedStack = parseStackTrace(stack)
|
||||
.map(frame => {
|
||||
.map((frame) => {
|
||||
if (!frame.file) {
|
||||
return frame;
|
||||
}
|
||||
// Find the correct source map
|
||||
const sourceMap = sourceMaps.find(sourceMap => {
|
||||
const sourceMap = sourceMaps.find((sourceMap) => {
|
||||
return frame.file.includes(sourceMap.file);
|
||||
});
|
||||
if (!sourceMap) {
|
||||
@@ -72,15 +70,13 @@ export const retrace = stack => {
|
||||
column: mappedFrame.column,
|
||||
};
|
||||
})
|
||||
.map(frame => {
|
||||
.map((frame) => {
|
||||
// Stringify the frame
|
||||
const { file, methodName, lineNumber } = frame;
|
||||
if (!file) {
|
||||
return ` at ${methodName}`;
|
||||
}
|
||||
const compactPath = file
|
||||
.replace(/^webpack:\/\/\/?/, './')
|
||||
.replace(/.*node_modules\//, '');
|
||||
const compactPath = file.replace(/^webpack:\/\/\/?/, './').replace(/.*node_modules\//, '');
|
||||
return ` at ${methodName} (${compactPath}:${lineNumber})`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
@@ -32,9 +32,9 @@ class LinkServer {
|
||||
setupWebSocketLink() {
|
||||
const port = 3000;
|
||||
this.wss = new WebSocket.Server({ port });
|
||||
this.wss.on('connection', ws => {
|
||||
this.wss.on('connection', (ws) => {
|
||||
logger.log('client connected');
|
||||
ws.on('message', json => {
|
||||
ws.on('message', (json) => {
|
||||
const msg = deserializeObject(json);
|
||||
this.handleLinkMessage(ws, msg);
|
||||
});
|
||||
@@ -51,7 +51,7 @@ class LinkServer {
|
||||
this.httpServer = http.createServer((req, res) => {
|
||||
if (req.method === 'POST') {
|
||||
let body = '';
|
||||
req.on('data', chunk => {
|
||||
req.on('data', (chunk) => {
|
||||
body += chunk.toString();
|
||||
});
|
||||
req.on('end', () => {
|
||||
@@ -76,16 +76,19 @@ class LinkServer {
|
||||
if (level <= 0 && !DEBUG) {
|
||||
return;
|
||||
}
|
||||
directLog(ns, ...args.map(arg => {
|
||||
if (typeof arg === 'object') {
|
||||
return inspect(arg, {
|
||||
depth: Infinity,
|
||||
colors: true,
|
||||
compact: 8,
|
||||
});
|
||||
}
|
||||
return arg;
|
||||
}));
|
||||
directLog(
|
||||
ns,
|
||||
...args.map((arg) => {
|
||||
if (typeof arg === 'object') {
|
||||
return inspect(arg, {
|
||||
depth: Infinity,
|
||||
colors: true,
|
||||
compact: 8,
|
||||
});
|
||||
}
|
||||
return arg;
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (type === 'relay') {
|
||||
@@ -117,7 +120,7 @@ class LinkServer {
|
||||
}
|
||||
}
|
||||
|
||||
const deserializeObject = str => {
|
||||
const deserializeObject = (str) => {
|
||||
return JSON.parse(str, (key, value) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (value.__undefined__) {
|
||||
|
||||
@@ -11,8 +11,7 @@ const isNode = process && process.release && process.release.name === 'node';
|
||||
let isChrome = false;
|
||||
try {
|
||||
isChrome = window.navigator.userAgent.toLowerCase().includes('chrome');
|
||||
}
|
||||
catch {}
|
||||
} catch {}
|
||||
|
||||
// Timestamping function
|
||||
const getTimestamp = () => {
|
||||
@@ -32,9 +31,7 @@ const getPrefix = (() => {
|
||||
bright: '\x1b[37;1m',
|
||||
reset: '\x1b[0m',
|
||||
};
|
||||
return ns => [
|
||||
`${ESC.dimmed}${getTimestamp()} ${ESC.bright}${ns}${ESC.reset}`,
|
||||
];
|
||||
return (ns) => [`${ESC.dimmed}${getTimestamp()} ${ESC.bright}${ns}${ESC.reset}`];
|
||||
}
|
||||
if (isChrome) {
|
||||
// Styles
|
||||
@@ -42,21 +39,15 @@ const getPrefix = (() => {
|
||||
dimmed: 'color: #888',
|
||||
bright: 'font-weight: bold',
|
||||
};
|
||||
return ns => [
|
||||
`%c${getTimestamp()}%c ${ns}`,
|
||||
styles.dimmed,
|
||||
styles.bright,
|
||||
];
|
||||
return (ns) => [`%c${getTimestamp()}%c ${ns}`, styles.dimmed, styles.bright];
|
||||
}
|
||||
return ns => [
|
||||
`${getTimestamp()} ${ns}`,
|
||||
];
|
||||
return (ns) => [`${getTimestamp()} ${ns}`];
|
||||
})();
|
||||
|
||||
/**
|
||||
* Creates a logger object.
|
||||
*/
|
||||
export const createLogger = ns => ({
|
||||
export const createLogger = (ns) => ({
|
||||
log: (...args) => console.log(...getPrefix(ns), ...args),
|
||||
trace: (...args) => console.trace(...getPrefix(ns), ...args),
|
||||
debug: (...args) => console.debug(...getPrefix(ns), ...args),
|
||||
@@ -68,5 +59,4 @@ export const createLogger = ns => ({
|
||||
/**
|
||||
* Explicitly log with chosen namespace.
|
||||
*/
|
||||
export const directLog = (ns, ...args) =>
|
||||
console.log(...getPrefix(ns), ...args);
|
||||
export const directLog = (ns, ...args) => console.log(...getPrefix(ns), ...args);
|
||||
|
||||
@@ -50,14 +50,9 @@ export const findCacheRoot = async () => {
|
||||
// Query the Windows Registry
|
||||
if (process.platform === 'win32') {
|
||||
logger.log('querying windows registry');
|
||||
let userpath = await regQuery(
|
||||
'HKCU\\Software\\Dantom\\BYOND',
|
||||
'userpath');
|
||||
let userpath = await regQuery('HKCU\\Software\\Dantom\\BYOND', 'userpath');
|
||||
if (userpath) {
|
||||
cacheRoot = userpath
|
||||
.replace(/\\$/, '')
|
||||
.replace(/\\/g, '/')
|
||||
+ '/cache';
|
||||
cacheRoot = userpath.replace(/\\$/, '').replace(/\\/g, '/') + '/cache';
|
||||
onCacheRootFound(cacheRoot);
|
||||
return cacheRoot;
|
||||
}
|
||||
@@ -65,13 +60,13 @@ export const findCacheRoot = async () => {
|
||||
logger.log('found no cache directories');
|
||||
};
|
||||
|
||||
const onCacheRootFound = cacheRoot => {
|
||||
const onCacheRootFound = (cacheRoot) => {
|
||||
logger.log(`found cache at '${cacheRoot}'`);
|
||||
// Plant a dummy
|
||||
fs.closeSync(fs.openSync(cacheRoot + '/dummy', 'w'));
|
||||
};
|
||||
|
||||
export const reloadByondCache = async bundleDir => {
|
||||
export const reloadByondCache = async (bundleDir) => {
|
||||
const cacheRoot = await findCacheRoot();
|
||||
if (!cacheRoot) {
|
||||
return;
|
||||
@@ -83,9 +78,7 @@ export const reloadByondCache = async bundleDir => {
|
||||
return;
|
||||
}
|
||||
// Get dreamseeker instances
|
||||
const pids = cacheDirs.map(cacheDir => (
|
||||
parseInt(cacheDir.split('/cache/tmp').pop(), 10)
|
||||
));
|
||||
const pids = cacheDirs.map((cacheDir) => parseInt(cacheDir.split('/cache/tmp').pop(), 10));
|
||||
const dssPromise = DreamSeeker.getInstancesByPids(pids);
|
||||
// Copy assets
|
||||
const assets = await resolveGlob(bundleDir, './*.+(bundle|chunk|hot-update).*');
|
||||
@@ -102,8 +95,7 @@ export const reloadByondCache = async bundleDir => {
|
||||
fs.writeFileSync(destination, fs.readFileSync(asset));
|
||||
}
|
||||
logger.log(`copied ${assets.length} files to '${cacheDir}'`);
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
logger.error(`failed copying to '${cacheDir}'`);
|
||||
logger.error(err);
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ export const resolveGlob = (...sections) => {
|
||||
try {
|
||||
fs.statSync(path);
|
||||
safePaths.push(path);
|
||||
}
|
||||
catch {}
|
||||
} catch {}
|
||||
}
|
||||
return safePaths;
|
||||
};
|
||||
|
||||
@@ -18,7 +18,7 @@ const logger = createLogger('webpack');
|
||||
* @param {any} config
|
||||
* @return {WebpackCompiler}
|
||||
*/
|
||||
export const createCompiler = async options => {
|
||||
export const createCompiler = async (options) => {
|
||||
const compiler = new WebpackCompiler();
|
||||
await compiler.setup(options);
|
||||
return compiler;
|
||||
@@ -57,7 +57,7 @@ class WebpackCompiler {
|
||||
logger.log('compiling');
|
||||
});
|
||||
// Start reloading when it's finished
|
||||
compiler.hooks.done.tap('tgui-dev-server', async stats => {
|
||||
compiler.hooks.done.tap('tgui-dev-server', async (stats) => {
|
||||
// Load source maps
|
||||
await loadSourceMaps(this.bundleDir);
|
||||
// Reload cache
|
||||
@@ -77,7 +77,7 @@ class WebpackCompiler {
|
||||
stats
|
||||
.toString(this.config.devServer.stats)
|
||||
.split('\n')
|
||||
.forEach(line => logger.log(line));
|
||||
.forEach((line) => logger.log(line));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,17 +30,14 @@ export const regQuery = async (path, key) => {
|
||||
logger.error('could not find the end of the line');
|
||||
return null;
|
||||
}
|
||||
const indexOfValue = stdout.indexOf(
|
||||
' ',
|
||||
indexOfKey + keyPattern.length);
|
||||
const indexOfValue = stdout.indexOf(' ', indexOfKey + keyPattern.length);
|
||||
if (indexOfValue === -1) {
|
||||
logger.error('could not find the start of the key value');
|
||||
return null;
|
||||
}
|
||||
const value = stdout.substring(indexOfValue + 4, indexOfEol);
|
||||
return value;
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
(function (window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.7.3';
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
var saveClones =
|
||||
/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
@@ -34,30 +35,31 @@
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = 'hidden' in a;
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
supportsUnknownElements =
|
||||
a.childNodes.length == 1 ||
|
||||
(function () {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
document.createElement('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
})();
|
||||
} catch (e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
})();
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -70,7 +72,7 @@
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
@@ -94,17 +96,17 @@
|
||||
*/
|
||||
function addElements(newElements, ownerDocument) {
|
||||
var elements = html5.elements;
|
||||
if(typeof elements != 'string'){
|
||||
if (typeof elements != 'string') {
|
||||
elements = elements.join(' ');
|
||||
}
|
||||
if(typeof newElements != 'string'){
|
||||
if (typeof newElements != 'string') {
|
||||
newElements = newElements.join(' ');
|
||||
}
|
||||
html5.elements = elements +' '+ newElements;
|
||||
html5.elements = elements + ' ' + newElements;
|
||||
shivDocument(ownerDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
@@ -113,10 +115,10 @@
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -128,24 +130,24 @@
|
||||
* @param {Document|DocumentFragment} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
function createElement(nodeName, ownerDocument, data) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
if (supportsUnknownElements) {
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
@@ -164,20 +166,20 @@
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
function createDocumentFragment(ownerDocument, data) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
if (supportsUnknownElements) {
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for (; i < l; i++) {
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
@@ -190,31 +192,34 @@
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
ownerDocument.createElement = function (nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
ownerDocument.createDocumentFragment = Function(
|
||||
'h,f',
|
||||
'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
getElements()
|
||||
.join()
|
||||
.replace(/[\w\-:]+/g, function (nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
@@ -228,18 +233,19 @@
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
data.hasCSS = !!addStyleSheet(
|
||||
ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
@@ -260,13 +266,14 @@
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
|
||||
'elements':
|
||||
options.elements ||
|
||||
'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
@@ -278,7 +285,7 @@
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
'shivCSS': options.shivCSS !== false,
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
@@ -293,7 +300,7 @@
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
'shivMethods': options.shivMethods !== false,
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
@@ -312,7 +319,7 @@
|
||||
createDocumentFragment: createDocumentFragment,
|
||||
|
||||
//extends list of elements
|
||||
addElements: addElements
|
||||
addElements: addElements,
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -323,8 +330,7 @@
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
if(typeof module == 'object' && module.exports){
|
||||
if (typeof module == 'object' && module.exports) {
|
||||
module.exports = html5;
|
||||
}
|
||||
|
||||
}(window, document));
|
||||
})(window, document);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
(function(Proto) {
|
||||
(function (Proto) {
|
||||
'use strict';
|
||||
|
||||
if (typeof Proto.setAttribute !== 'undefined') {
|
||||
@@ -40,5 +40,4 @@
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
})(CSSStyleDeclaration.prototype);
|
||||
|
||||
@@ -9,23 +9,24 @@
|
||||
'use strict';
|
||||
|
||||
// Necessary polyfill to make Webpack code splitting work on IE8
|
||||
if (!Function.prototype.bind) (function () {
|
||||
var slice = Array.prototype.slice;
|
||||
Function.prototype.bind = function () {
|
||||
var thatFunc = this, thatArg = arguments[0];
|
||||
var args = slice.call(arguments, 1);
|
||||
if (typeof thatFunc !== 'function') {
|
||||
// closest thing possible to the ECMAScript 5
|
||||
// internal IsCallable function
|
||||
throw new TypeError('Function.prototype.bind - ' +
|
||||
'what is trying to be bound is not callable');
|
||||
}
|
||||
return function () {
|
||||
var funcArgs = args.concat(slice.call(arguments))
|
||||
return thatFunc.apply(thatArg, funcArgs);
|
||||
if (!Function.prototype.bind)
|
||||
(function () {
|
||||
var slice = Array.prototype.slice;
|
||||
Function.prototype.bind = function () {
|
||||
var thatFunc = this,
|
||||
thatArg = arguments[0];
|
||||
var args = slice.call(arguments, 1);
|
||||
if (typeof thatFunc !== 'function') {
|
||||
// closest thing possible to the ECMAScript 5
|
||||
// internal IsCallable function
|
||||
throw new TypeError('Function.prototype.bind - ' + 'what is trying to be bound is not callable');
|
||||
}
|
||||
return function () {
|
||||
var funcArgs = args.concat(slice.call(arguments));
|
||||
return thatFunc.apply(thatArg, funcArgs);
|
||||
};
|
||||
};
|
||||
};
|
||||
})();
|
||||
})();
|
||||
|
||||
if (!Array.prototype['forEach']) {
|
||||
Array.prototype.forEach = function (callback, thisArg) {
|
||||
@@ -35,7 +36,7 @@
|
||||
var T, k;
|
||||
var O = Object(this);
|
||||
var len = O.length >>> 0;
|
||||
if (typeof callback !== "function") {
|
||||
if (typeof callback !== 'function') {
|
||||
throw new TypeError(callback + ' is not a function');
|
||||
}
|
||||
if (arguments.length > 1) {
|
||||
@@ -57,5 +58,4 @@
|
||||
if (!window.Int32Array) {
|
||||
window.Int32Array = Array;
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
const EXCLUDED_PATTERNS = [/v4shim/i];
|
||||
const loadedMappings = {};
|
||||
|
||||
export const resolveAsset = name => (
|
||||
loadedMappings[name] || name
|
||||
);
|
||||
export const resolveAsset = (name) => loadedMappings[name] || name;
|
||||
|
||||
export const assetMiddleware = store => next => action => {
|
||||
export const assetMiddleware = (store) => (next) => (action) => {
|
||||
const { type, payload } = action;
|
||||
if (type === 'asset/stylesheet') {
|
||||
Byond.loadCss(payload);
|
||||
@@ -20,7 +18,7 @@ export const assetMiddleware = store => next => action => {
|
||||
if (type === 'asset/mappings') {
|
||||
for (let name of Object.keys(payload)) {
|
||||
// Skip anything that matches excluded patterns
|
||||
if (EXCLUDED_PATTERNS.some(regex => regex.test(name))) {
|
||||
if (EXCLUDED_PATTERNS.some((regex) => regex.test(name))) {
|
||||
continue;
|
||||
}
|
||||
const url = payload[name];
|
||||
|
||||
@@ -62,8 +62,7 @@ export const backendReducer = (state = initialState, action) => {
|
||||
const value = payload.shared[key];
|
||||
if (value === '') {
|
||||
shared[key] = undefined;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
shared[key] = JSON.parse(value);
|
||||
}
|
||||
}
|
||||
@@ -115,11 +114,11 @@ export const backendReducer = (state = initialState, action) => {
|
||||
return state;
|
||||
};
|
||||
|
||||
export const backendMiddleware = store => {
|
||||
export const backendMiddleware = (store) => {
|
||||
let fancyState;
|
||||
let suspendInterval;
|
||||
|
||||
return next => action => {
|
||||
return (next) => (action) => {
|
||||
const { suspended } = selectBackend(store.getState());
|
||||
const { type, payload } = action;
|
||||
|
||||
@@ -196,8 +195,7 @@ export const backendMiddleware = store => {
|
||||
});
|
||||
perf.mark('resume/finish');
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
logger.log('visible in',
|
||||
perf.measure('render/finish', 'resume/finish'));
|
||||
logger.log('visible in', perf.measure('render/finish', 'resume/finish'));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -212,9 +210,7 @@ export const backendMiddleware = store => {
|
||||
*/
|
||||
export const sendAct = (action: string, payload: object = {}) => {
|
||||
// Validate that payload is an object
|
||||
const isObject = typeof payload === 'object'
|
||||
&& payload !== null
|
||||
&& !Array.isArray(payload);
|
||||
const isObject = typeof payload === 'object' && payload !== null && !Array.isArray(payload);
|
||||
if (!isObject) {
|
||||
logger.error(`Payload for act() must be an object, got this:`, payload);
|
||||
return;
|
||||
@@ -224,38 +220,36 @@ export const sendAct = (action: string, payload: object = {}) => {
|
||||
|
||||
type BackendState<TData> = {
|
||||
config: {
|
||||
title: string,
|
||||
status: number,
|
||||
interface: string,
|
||||
refreshing: boolean,
|
||||
title: string;
|
||||
status: number;
|
||||
interface: string;
|
||||
refreshing: boolean;
|
||||
window: {
|
||||
key: string,
|
||||
size: [number, number],
|
||||
fancy: boolean,
|
||||
locked: boolean,
|
||||
},
|
||||
key: string;
|
||||
size: [number, number];
|
||||
fancy: boolean;
|
||||
locked: boolean;
|
||||
};
|
||||
client: {
|
||||
ckey: string,
|
||||
address: string,
|
||||
computer_id: string,
|
||||
},
|
||||
ckey: string;
|
||||
address: string;
|
||||
computer_id: string;
|
||||
};
|
||||
user: {
|
||||
name: string,
|
||||
observer: number,
|
||||
},
|
||||
},
|
||||
data: TData,
|
||||
shared: Record<string, any>,
|
||||
suspending: boolean,
|
||||
suspended: boolean,
|
||||
name: string;
|
||||
observer: number;
|
||||
};
|
||||
};
|
||||
data: TData;
|
||||
shared: Record<string, any>;
|
||||
suspending: boolean;
|
||||
suspended: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects a backend-related slice of Redux state
|
||||
*/
|
||||
export const selectBackend = <TData>(state: any): BackendState<TData> => (
|
||||
state.backend || {}
|
||||
);
|
||||
export const selectBackend = <TData>(state: any): BackendState<TData> => state.backend || {};
|
||||
|
||||
/**
|
||||
* Get data from tgui backend.
|
||||
@@ -289,28 +283,20 @@ type StateWithSetter<T> = [T, (nextState: T) => void];
|
||||
* @param key Key which uniquely identifies this state in Redux store.
|
||||
* @param initialState Initializes your global variable with this value.
|
||||
*/
|
||||
export const useLocalState = <T>(
|
||||
context: any,
|
||||
key: string,
|
||||
initialState: T,
|
||||
): StateWithSetter<T> => {
|
||||
export const useLocalState = <T>(context: any, key: string, initialState: T): StateWithSetter<T> => {
|
||||
const { store } = context;
|
||||
const state = selectBackend(store.getState());
|
||||
const sharedStates = state.shared ?? {};
|
||||
const sharedState = (key in sharedStates)
|
||||
? sharedStates[key]
|
||||
: initialState;
|
||||
const sharedState = key in sharedStates ? sharedStates[key] : initialState;
|
||||
return [
|
||||
sharedState,
|
||||
nextState => {
|
||||
store.dispatch(backendSetSharedState({
|
||||
key,
|
||||
nextState: (
|
||||
typeof nextState === 'function'
|
||||
? nextState(sharedState)
|
||||
: nextState
|
||||
),
|
||||
}));
|
||||
(nextState) => {
|
||||
store.dispatch(
|
||||
backendSetSharedState({
|
||||
key,
|
||||
nextState: typeof nextState === 'function' ? nextState(sharedState) : nextState,
|
||||
})
|
||||
);
|
||||
},
|
||||
];
|
||||
};
|
||||
@@ -329,28 +315,18 @@ export const useLocalState = <T>(
|
||||
* @param key Key which uniquely identifies this state in Redux store.
|
||||
* @param initialState Initializes your global variable with this value.
|
||||
*/
|
||||
export const useSharedState = <T>(
|
||||
context: any,
|
||||
key: string,
|
||||
initialState: T,
|
||||
): StateWithSetter<T> => {
|
||||
export const useSharedState = <T>(context: any, key: string, initialState: T): StateWithSetter<T> => {
|
||||
const { store } = context;
|
||||
const state = selectBackend(store.getState());
|
||||
const sharedStates = state.shared ?? {};
|
||||
const sharedState = (key in sharedStates)
|
||||
? sharedStates[key]
|
||||
: initialState;
|
||||
const sharedState = key in sharedStates ? sharedStates[key] : initialState;
|
||||
return [
|
||||
sharedState,
|
||||
nextState => {
|
||||
(nextState) => {
|
||||
Byond.sendMessage({
|
||||
type: 'setSharedState',
|
||||
key,
|
||||
value: JSON.stringify(
|
||||
typeof nextState === 'function'
|
||||
? nextState(sharedState)
|
||||
: nextState
|
||||
) || '',
|
||||
value: JSON.stringify(typeof nextState === 'function' ? nextState(sharedState) : nextState) || '',
|
||||
});
|
||||
},
|
||||
];
|
||||
|
||||
@@ -10,10 +10,8 @@ import { Component } from 'inferno';
|
||||
const FPS = 20;
|
||||
const Q = 0.5;
|
||||
|
||||
const isSafeNumber = value => {
|
||||
return typeof value === 'number'
|
||||
&& Number.isFinite(value)
|
||||
&& !Number.isNaN(value);
|
||||
const isSafeNumber = (value) => {
|
||||
return typeof value === 'number' && Number.isFinite(value) && !Number.isNaN(value);
|
||||
};
|
||||
|
||||
export class AnimatedNumber extends Component {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, createRef } from "inferno";
|
||||
import { Component, createRef } from 'inferno';
|
||||
|
||||
export class Autofocus extends Component {
|
||||
ref = createRef<HTMLDivElement>();
|
||||
|
||||
@@ -12,10 +12,7 @@ export class Blink extends Component {
|
||||
}
|
||||
|
||||
createTimer() {
|
||||
const {
|
||||
interval = DEFAULT_BLINKING_INTERVAL,
|
||||
time = DEFAULT_BLINKING_TIME,
|
||||
} = this.props;
|
||||
const { interval = DEFAULT_BLINKING_INTERVAL, time = DEFAULT_BLINKING_TIME } = this.props;
|
||||
|
||||
clearInterval(this.interval);
|
||||
clearTimeout(this.timer);
|
||||
@@ -42,8 +39,7 @@ export class Blink extends Component {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.interval !== this.props.interval
|
||||
|| prevProps.time !== this.props.time) {
|
||||
if (prevProps.interval !== this.props.interval || prevProps.time !== this.props.time) {
|
||||
this.createTimer();
|
||||
}
|
||||
}
|
||||
@@ -55,9 +51,10 @@ export class Blink extends Component {
|
||||
|
||||
render(props) {
|
||||
return (
|
||||
<span style={{
|
||||
visibility: this.state.hidden ? "hidden" : "visible",
|
||||
}}>
|
||||
<span
|
||||
style={{
|
||||
visibility: this.state.hidden ? 'hidden' : 'visible',
|
||||
}}>
|
||||
{props.children}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -7,14 +7,7 @@
|
||||
import { classes } from 'common/react';
|
||||
import { Box } from './Box';
|
||||
|
||||
export const BlockQuote = props => {
|
||||
export const BlockQuote = (props) => {
|
||||
const { className, ...rest } = props;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'BlockQuote',
|
||||
className,
|
||||
])}
|
||||
{...rest} />
|
||||
);
|
||||
return <Box className={classes(['BlockQuote', className])} {...rest} />;
|
||||
};
|
||||
|
||||
@@ -60,17 +60,17 @@ export interface BoxProps {
|
||||
backgroundColor?: string | BooleanLike;
|
||||
// VOREStation Addition Start
|
||||
// Flex props
|
||||
order?: string | BooleanLike,
|
||||
flexDirection?: string | BooleanLike,
|
||||
flexGrow?: string | BooleanLike,
|
||||
flexShrink?: string | BooleanLike,
|
||||
flexWrap?: string | BooleanLike,
|
||||
flexFlow?: string | BooleanLike,
|
||||
flexBasis?: string | BooleanLike,
|
||||
flex?: string | BooleanLike,
|
||||
alignItems?: string | BooleanLike,
|
||||
justifyContent?: string | BooleanLike,
|
||||
alignSelf?: string | BooleanLike,
|
||||
order?: string | BooleanLike;
|
||||
flexDirection?: string | BooleanLike;
|
||||
flexGrow?: string | BooleanLike;
|
||||
flexShrink?: string | BooleanLike;
|
||||
flexWrap?: string | BooleanLike;
|
||||
flexFlow?: string | BooleanLike;
|
||||
flexBasis?: string | BooleanLike;
|
||||
flex?: string | BooleanLike;
|
||||
alignItems?: string | BooleanLike;
|
||||
justifyContent?: string | BooleanLike;
|
||||
alignSelf?: string | BooleanLike;
|
||||
// VOREStation Addition End
|
||||
fillPositionedParent?: boolean;
|
||||
}
|
||||
@@ -109,10 +109,10 @@ export const halfUnit = (value: unknown): string | undefined => {
|
||||
const isColorCode = (str: unknown) => !isColorClass(str);
|
||||
|
||||
const isColorClass = (str: unknown): boolean => {
|
||||
return typeof str === "string" && CSS_COLORS.includes(str);
|
||||
return typeof str === 'string' && CSS_COLORS.includes(str);
|
||||
};
|
||||
|
||||
const mapRawPropTo = attrName => (style, value) => {
|
||||
const mapRawPropTo = (attrName) => (style, value) => {
|
||||
if (typeof value === 'number' || typeof value === 'string') {
|
||||
style[attrName] = value;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ const mapDirectionalUnitPropTo = (attrName, unit, dirs) => (style, value) => {
|
||||
}
|
||||
};
|
||||
|
||||
const mapColorPropTo = attrName => (style, value) => {
|
||||
const mapColorPropTo = (attrName) => (style, value) => {
|
||||
if (isColorCode(value)) {
|
||||
style[attrName] = value;
|
||||
}
|
||||
@@ -165,8 +165,7 @@ const styleMapperByPropName = {
|
||||
lineHeight: (style, value) => {
|
||||
if (typeof value === 'number') {
|
||||
style['line-height'] = value;
|
||||
}
|
||||
else if (typeof value === 'string') {
|
||||
} else if (typeof value === 'string') {
|
||||
style['line-height'] = unit(value);
|
||||
}
|
||||
},
|
||||
@@ -182,29 +181,17 @@ const styleMapperByPropName = {
|
||||
nowrap: mapBooleanPropTo('white-space', 'nowrap'),
|
||||
preserveWhitespace: mapBooleanPropTo('white-space', 'pre-wrap'),
|
||||
// Margins
|
||||
m: mapDirectionalUnitPropTo('margin', halfUnit, [
|
||||
'top', 'bottom', 'left', 'right',
|
||||
]),
|
||||
mx: mapDirectionalUnitPropTo('margin', halfUnit, [
|
||||
'left', 'right',
|
||||
]),
|
||||
my: mapDirectionalUnitPropTo('margin', halfUnit, [
|
||||
'top', 'bottom',
|
||||
]),
|
||||
m: mapDirectionalUnitPropTo('margin', halfUnit, ['top', 'bottom', 'left', 'right']),
|
||||
mx: mapDirectionalUnitPropTo('margin', halfUnit, ['left', 'right']),
|
||||
my: mapDirectionalUnitPropTo('margin', halfUnit, ['top', 'bottom']),
|
||||
mt: mapUnitPropTo('margin-top', halfUnit),
|
||||
mb: mapUnitPropTo('margin-bottom', halfUnit),
|
||||
ml: mapUnitPropTo('margin-left', halfUnit),
|
||||
mr: mapUnitPropTo('margin-right', halfUnit),
|
||||
// Margins
|
||||
p: mapDirectionalUnitPropTo('padding', halfUnit, [
|
||||
'top', 'bottom', 'left', 'right',
|
||||
]),
|
||||
px: mapDirectionalUnitPropTo('padding', halfUnit, [
|
||||
'left', 'right',
|
||||
]),
|
||||
py: mapDirectionalUnitPropTo('padding', halfUnit, [
|
||||
'top', 'bottom',
|
||||
]),
|
||||
p: mapDirectionalUnitPropTo('padding', halfUnit, ['top', 'bottom', 'left', 'right']),
|
||||
px: mapDirectionalUnitPropTo('padding', halfUnit, ['left', 'right']),
|
||||
py: mapDirectionalUnitPropTo('padding', halfUnit, ['top', 'bottom']),
|
||||
pt: mapUnitPropTo('padding-top', halfUnit),
|
||||
pb: mapUnitPropTo('padding-bottom', halfUnit),
|
||||
pl: mapUnitPropTo('padding-left', halfUnit),
|
||||
@@ -256,8 +243,7 @@ export const computeBoxProps = (props: BoxProps) => {
|
||||
const mapPropToStyle = styleMapperByPropName[propName];
|
||||
if (mapPropToStyle) {
|
||||
mapPropToStyle(computedStyles, propValue);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
computedProps[propName] = propValue;
|
||||
}
|
||||
}
|
||||
@@ -289,19 +275,13 @@ export const computeBoxClassName = (props: BoxProps) => {
|
||||
};
|
||||
|
||||
export const Box: SFC<BoxProps> = (props: BoxProps) => {
|
||||
const {
|
||||
as = 'div',
|
||||
className,
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
const { as = 'div', className, children, ...rest } = props;
|
||||
// Render props
|
||||
if (typeof children === 'function') {
|
||||
return children(computeBoxProps(props));
|
||||
}
|
||||
const computedClassName = typeof className === 'string'
|
||||
? className + ' ' + computeBoxClassName(rest)
|
||||
: computeBoxClassName(rest);
|
||||
const computedClassName =
|
||||
typeof className === 'string' ? className + ' ' + computeBoxClassName(rest) : computeBoxClassName(rest);
|
||||
const computedProps = computeBoxProps(rest);
|
||||
// Render a wrapper element
|
||||
return createVNode(
|
||||
@@ -311,7 +291,7 @@ export const Box: SFC<BoxProps> = (props: BoxProps) => {
|
||||
children,
|
||||
ChildFlags.UnknownChildren,
|
||||
computedProps,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Tooltip } from './Tooltip';
|
||||
|
||||
const logger = createLogger('Button');
|
||||
|
||||
export const Button = props => {
|
||||
export const Button = (props) => {
|
||||
const {
|
||||
className,
|
||||
fluid,
|
||||
@@ -42,12 +42,13 @@ export const Button = props => {
|
||||
// A warning about the lowercase onclick
|
||||
if (onclick) {
|
||||
logger.warn(
|
||||
`Lowercase 'onclick' is not supported on Button and lowercase`
|
||||
+ ` prop names are discouraged in general. Please use a camelCase`
|
||||
+ `'onClick' instead and read: `
|
||||
+ `https://infernojs.org/docs/guides/event-handling`);
|
||||
`Lowercase 'onclick' is not supported on Button and lowercase` +
|
||||
` prop names are discouraged in general. Please use a camelCase` +
|
||||
`'onClick' instead and read: ` +
|
||||
`https://infernojs.org/docs/guides/event-handling`
|
||||
);
|
||||
}
|
||||
rest.onClick = e => {
|
||||
rest.onClick = (e) => {
|
||||
if (!disabled && onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
@@ -68,14 +69,12 @@ export const Button = props => {
|
||||
circular && 'Button--circular',
|
||||
compact && 'Button--compact',
|
||||
iconPosition && 'Button--iconPosition--' + iconPosition,
|
||||
(color && typeof color === 'string')
|
||||
? 'Button--color--' + color
|
||||
: 'Button--color--default',
|
||||
color && typeof color === 'string' ? 'Button--color--' + color : 'Button--color--default',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
tabIndex={!disabled && '0'}
|
||||
onKeyDown={e => {
|
||||
onKeyDown={(e) => {
|
||||
if (props.captureKeys === false) {
|
||||
return;
|
||||
}
|
||||
@@ -96,16 +95,12 @@ export const Button = props => {
|
||||
}
|
||||
}}
|
||||
{...computeBoxProps(rest)}>
|
||||
{(icon && iconPosition !== 'right') && (
|
||||
<Icon
|
||||
name={icon}
|
||||
color={iconColor}
|
||||
rotation={iconRotation}
|
||||
spin={iconSpin} />
|
||||
{icon && iconPosition !== 'right' && (
|
||||
<Icon name={icon} color={iconColor} rotation={iconRotation} spin={iconSpin} />
|
||||
)}
|
||||
{content}
|
||||
{children}
|
||||
{(icon && iconPosition === 'right') && (
|
||||
{icon && iconPosition === 'right' && (
|
||||
<Icon
|
||||
name={icon}
|
||||
color={iconColor}
|
||||
@@ -130,15 +125,9 @@ export const Button = props => {
|
||||
|
||||
Button.defaultHooks = pureComponentHooks;
|
||||
|
||||
export const ButtonCheckbox = props => {
|
||||
export const ButtonCheckbox = (props) => {
|
||||
const { checked, ...rest } = props;
|
||||
return (
|
||||
<Button
|
||||
color="transparent"
|
||||
icon={checked ? 'check-square-o' : 'square-o'}
|
||||
selected={checked}
|
||||
{...rest} />
|
||||
);
|
||||
return <Button color="transparent" icon={checked ? 'check-square-o' : 'square-o'} selected={checked} {...rest} />;
|
||||
};
|
||||
|
||||
Button.Checkbox = ButtonCheckbox;
|
||||
@@ -162,16 +151,15 @@ export class ButtonConfirm extends Component {
|
||||
});
|
||||
if (clickedOnce) {
|
||||
setTimeout(() => window.addEventListener('click', this.handleClick));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
window.removeEventListener('click', this.handleClick);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
confirmContent = "Confirm?",
|
||||
confirmColor = "bad",
|
||||
confirmContent = 'Confirm?',
|
||||
confirmColor = 'bad',
|
||||
confirmIcon,
|
||||
icon,
|
||||
color,
|
||||
@@ -184,9 +172,7 @@ export class ButtonConfirm extends Component {
|
||||
content={this.state.clickedOnce ? confirmContent : content}
|
||||
icon={this.state.clickedOnce ? confirmIcon : icon}
|
||||
color={this.state.clickedOnce ? confirmColor : color}
|
||||
onClick={() => this.state.clickedOnce
|
||||
? onClick()
|
||||
: this.setClickedOnce(true)}
|
||||
onClick={() => (this.state.clickedOnce ? onClick() : this.setClickedOnce(true))}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
@@ -211,12 +197,11 @@ export class ButtonInput extends Component {
|
||||
if (this.inputRef) {
|
||||
const input = this.inputRef.current;
|
||||
if (inInput) {
|
||||
input.value = this.props.currentValue || "";
|
||||
input.value = this.props.currentValue || '';
|
||||
try {
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
catch {}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +209,7 @@ export class ButtonInput extends Component {
|
||||
commitResult(e) {
|
||||
if (this.inputRef) {
|
||||
const input = this.inputRef.current;
|
||||
const hasValue = (input.value !== "");
|
||||
const hasValue = input.value !== '';
|
||||
if (hasValue) {
|
||||
this.props.onCommit(e, input.value);
|
||||
return;
|
||||
@@ -254,19 +239,11 @@ export class ButtonInput extends Component {
|
||||
|
||||
let buttonContent = (
|
||||
<Box
|
||||
className={classes([
|
||||
'Button',
|
||||
fluid && 'Button--fluid',
|
||||
'Button--color--' + color,
|
||||
])}
|
||||
className={classes(['Button', fluid && 'Button--fluid', 'Button--color--' + color])}
|
||||
{...rest}
|
||||
onClick={() => this.setInInput(true)}>
|
||||
{icon && (
|
||||
<Icon name={icon} rotation={iconRotation} spin={iconSpin} />
|
||||
)}
|
||||
<div>
|
||||
{content}
|
||||
</div>
|
||||
{icon && <Icon name={icon} rotation={iconRotation} spin={iconSpin} />}
|
||||
<div>{content}</div>
|
||||
<input
|
||||
ref={this.inputRef}
|
||||
className="NumberInput__input"
|
||||
@@ -274,14 +251,14 @@ export class ButtonInput extends Component {
|
||||
'display': !this.state.inInput ? 'none' : undefined,
|
||||
'text-align': 'left',
|
||||
}}
|
||||
onBlur={e => {
|
||||
onBlur={(e) => {
|
||||
if (!this.state.inInput) {
|
||||
return;
|
||||
}
|
||||
this.setInInput(false);
|
||||
this.commitResult(e);
|
||||
}}
|
||||
onKeyDown={e => {
|
||||
onKeyDown={(e) => {
|
||||
if (e.keyCode === KEY_ENTER) {
|
||||
this.setInInput(false);
|
||||
this.commitResult(e);
|
||||
@@ -297,10 +274,7 @@ export class ButtonInput extends Component {
|
||||
|
||||
if (tooltip) {
|
||||
buttonContent = (
|
||||
<Tooltip
|
||||
content={tooltip}
|
||||
position={tooltipPosition}
|
||||
>
|
||||
<Tooltip content={tooltip} position={tooltipPosition}>
|
||||
{buttonContent}
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ const logger = createLogger('ByondUi');
|
||||
// Stack of currently allocated BYOND UI element ids.
|
||||
const byondUiStack = [];
|
||||
|
||||
const createByondUiElement = elementId => {
|
||||
const createByondUiElement = (elementId) => {
|
||||
// Reserve an index in the stack
|
||||
const index = byondUiStack.length;
|
||||
byondUiStack.push(null);
|
||||
@@ -24,7 +24,7 @@ const createByondUiElement = elementId => {
|
||||
logger.log(`allocated '${id}'`);
|
||||
// Return a control structure
|
||||
return {
|
||||
render: params => {
|
||||
render: (params) => {
|
||||
logger.log(`rendering '${id}'`);
|
||||
byondUiStack[index] = id;
|
||||
Byond.winset(id, params);
|
||||
@@ -56,18 +56,12 @@ window.addEventListener('beforeunload', () => {
|
||||
/**
|
||||
* Get the bounding box of the DOM element in display-pixels.
|
||||
*/
|
||||
const getBoundingBox = element => {
|
||||
const getBoundingBox = (element) => {
|
||||
const pixelRatio = window.devicePixelRatio ?? 1;
|
||||
const rect = element.getBoundingClientRect();
|
||||
return {
|
||||
pos: [
|
||||
rect.left * pixelRatio,
|
||||
rect.top * pixelRatio,
|
||||
],
|
||||
size: [
|
||||
(rect.right - rect.left) * pixelRatio,
|
||||
(rect.bottom - rect.top) * pixelRatio,
|
||||
],
|
||||
pos: [rect.left * pixelRatio, rect.top * pixelRatio],
|
||||
size: [(rect.right - rect.left) * pixelRatio, (rect.bottom - rect.top) * pixelRatio],
|
||||
};
|
||||
};
|
||||
|
||||
@@ -82,16 +76,9 @@ export class ByondUi extends Component {
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const {
|
||||
params: prevParams = {},
|
||||
...prevRest
|
||||
} = this.props;
|
||||
const {
|
||||
params: nextParams = {},
|
||||
...nextRest
|
||||
} = nextProps;
|
||||
return shallowDiffers(prevParams, nextParams)
|
||||
|| shallowDiffers(prevRest, nextRest);
|
||||
const { params: prevParams = {}, ...prevRest } = this.props;
|
||||
const { params: nextParams = {}, ...nextRest } = nextProps;
|
||||
return shallowDiffers(prevParams, nextParams) || shallowDiffers(prevRest, nextRest);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -109,9 +96,7 @@ export class ByondUi extends Component {
|
||||
if (Byond.IS_LTE_IE10) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
params = {},
|
||||
} = this.props;
|
||||
const { params = {} } = this.props;
|
||||
const box = getBoundingBox(this.containerRef.current);
|
||||
logger.debug('bounding box', box);
|
||||
this.byondUiElement.render({
|
||||
@@ -134,9 +119,7 @@ export class ByondUi extends Component {
|
||||
render() {
|
||||
const { params, ...rest } = this.props;
|
||||
return (
|
||||
<div
|
||||
ref={this.containerRef}
|
||||
{...computeBoxProps(rest)}>
|
||||
<div ref={this.containerRef} {...computeBoxProps(rest)}>
|
||||
{/* Filler */}
|
||||
<div style={{ 'min-height': '22px' }} />
|
||||
</div>
|
||||
|
||||
+7
-6
@@ -23,15 +23,15 @@ const normalizeData = (data, scale, rangeX, rangeY) => {
|
||||
min[1] = rangeY[0];
|
||||
max[1] = rangeY[1];
|
||||
}
|
||||
const normalized = map(point => {
|
||||
const normalized = map((point) => {
|
||||
return zipWith((value, min, max, scale) => {
|
||||
return (value - min) / (max - min) * scale;
|
||||
return ((value - min) / (max - min)) * scale;
|
||||
})(point, min, max, scale);
|
||||
})(data);
|
||||
return normalized;
|
||||
};
|
||||
|
||||
const dataToPolylinePoints = data => {
|
||||
const dataToPolylinePoints = (data) => {
|
||||
let points = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const point = data[i];
|
||||
@@ -89,7 +89,7 @@ class LineChart extends Component {
|
||||
const points = dataToPolylinePoints(normalized);
|
||||
return (
|
||||
<Box position="relative" {...rest}>
|
||||
{props => (
|
||||
{(props) => (
|
||||
<div ref={this.ref} {...props}>
|
||||
<svg
|
||||
viewBox={`0 0 ${viewBox[0]} ${viewBox[1]}`}
|
||||
@@ -107,7 +107,8 @@ class LineChart extends Component {
|
||||
fill={fillColor}
|
||||
stroke={strokeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
points={points} />
|
||||
points={points}
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
@@ -118,7 +119,7 @@ class LineChart extends Component {
|
||||
|
||||
LineChart.defaultHooks = pureComponentHooks;
|
||||
|
||||
const Stub = props => null;
|
||||
const Stub = (props) => null;
|
||||
|
||||
// IE8: No inline svg support
|
||||
export const Chart = {
|
||||
|
||||
@@ -20,13 +20,7 @@ export class Collapsible extends Component {
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { open } = this.state;
|
||||
const {
|
||||
children,
|
||||
color = 'default',
|
||||
title,
|
||||
buttons,
|
||||
...rest
|
||||
} = props;
|
||||
const { children, color = 'default', title, buttons, ...rest } = props;
|
||||
return (
|
||||
<Box mb={1}>
|
||||
<div className="Table">
|
||||
@@ -40,17 +34,9 @@ export class Collapsible extends Component {
|
||||
{title}
|
||||
</Button>
|
||||
</div>
|
||||
{buttons && (
|
||||
<div className="Table__cell Table__cell--collapsing">
|
||||
{buttons}
|
||||
</div>
|
||||
)}
|
||||
{buttons && <div className="Table__cell Table__cell--collapsing">{buttons}</div>}
|
||||
</div>
|
||||
{open && (
|
||||
<Box mt={1}>
|
||||
{children}
|
||||
</Box>
|
||||
)}
|
||||
{open && <Box mt={1}>{children}</Box>}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,25 +7,12 @@
|
||||
import { classes, pureComponentHooks } from 'common/react';
|
||||
import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
|
||||
export const ColorBox = props => {
|
||||
const {
|
||||
content,
|
||||
children,
|
||||
className,
|
||||
color,
|
||||
backgroundColor,
|
||||
...rest
|
||||
} = props;
|
||||
export const ColorBox = (props) => {
|
||||
const { content, children, className, color, backgroundColor, ...rest } = props;
|
||||
rest.color = content ? null : 'transparent';
|
||||
rest.backgroundColor = color || backgroundColor;
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
'ColorBox',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
{...computeBoxProps(rest)}>
|
||||
<div className={classes(['ColorBox', className, computeBoxClassName(rest)])} {...computeBoxProps(rest)}>
|
||||
{content || '.'}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,18 +7,11 @@
|
||||
import { classes } from 'common/react';
|
||||
import { Box } from './Box';
|
||||
|
||||
export const Dimmer = props => {
|
||||
export const Dimmer = (props) => {
|
||||
const { className, children, ...rest } = props;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'Dimmer',
|
||||
...className,
|
||||
])}
|
||||
{...rest}>
|
||||
<div className="Dimmer__inner">
|
||||
{children}
|
||||
</div>
|
||||
<Box className={classes(['Dimmer', ...className])} {...rest}>
|
||||
<div className="Dimmer__inner">{children}</div>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,19 +6,15 @@
|
||||
|
||||
import { classes } from 'common/react';
|
||||
|
||||
export const Divider = props => {
|
||||
const {
|
||||
vertical,
|
||||
hidden,
|
||||
} = props;
|
||||
export const Divider = (props) => {
|
||||
const { vertical, hidden } = props;
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
'Divider',
|
||||
hidden && 'Divider--hidden',
|
||||
vertical
|
||||
? 'Divider--vertical'
|
||||
: 'Divider--horizontal',
|
||||
])} />
|
||||
vertical ? 'Divider--vertical' : 'Divider--horizontal',
|
||||
])}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,17 +40,18 @@ export class DraggableControl extends Component {
|
||||
suppressingFlicker: true,
|
||||
});
|
||||
clearTimeout(this.flickerTimer);
|
||||
this.flickerTimer = setTimeout(() => this.setState({
|
||||
suppressingFlicker: false,
|
||||
}), suppressFlicker);
|
||||
this.flickerTimer = setTimeout(
|
||||
() =>
|
||||
this.setState({
|
||||
suppressingFlicker: false,
|
||||
}),
|
||||
suppressFlicker
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
this.handleDragStart = e => {
|
||||
const {
|
||||
value,
|
||||
dragMatrix,
|
||||
} = this.props;
|
||||
this.handleDragStart = (e) => {
|
||||
const { value, dragMatrix } = this.props;
|
||||
const { editing } = this.state;
|
||||
if (editing) {
|
||||
return;
|
||||
@@ -79,54 +80,33 @@ export class DraggableControl extends Component {
|
||||
document.addEventListener('mouseup', this.handleDragEnd);
|
||||
};
|
||||
|
||||
this.handleDragMove = e => {
|
||||
const {
|
||||
minValue,
|
||||
maxValue,
|
||||
step,
|
||||
stepPixelSize,
|
||||
dragMatrix,
|
||||
} = this.props;
|
||||
this.setState(prevState => {
|
||||
this.handleDragMove = (e) => {
|
||||
const { minValue, maxValue, step, stepPixelSize, dragMatrix } = this.props;
|
||||
this.setState((prevState) => {
|
||||
const state = { ...prevState };
|
||||
const offset = getScalarScreenOffset(e, dragMatrix) - state.origin;
|
||||
if (prevState.dragging) {
|
||||
const stepOffset = Number.isFinite(minValue)
|
||||
? minValue % step
|
||||
: 0;
|
||||
const stepOffset = Number.isFinite(minValue) ? minValue % step : 0;
|
||||
// Translate mouse movement to value
|
||||
// Give it some headroom (by increasing clamp range by 1 step)
|
||||
state.internalValue = clamp(
|
||||
state.internalValue
|
||||
+ offset * step / stepPixelSize,
|
||||
state.internalValue + (offset * step) / stepPixelSize,
|
||||
minValue - step,
|
||||
maxValue + step);
|
||||
maxValue + step
|
||||
);
|
||||
// Clamp the final value
|
||||
state.value = clamp(
|
||||
state.internalValue
|
||||
- state.internalValue % step
|
||||
+ stepOffset,
|
||||
minValue,
|
||||
maxValue);
|
||||
state.value = clamp(state.internalValue - (state.internalValue % step) + stepOffset, minValue, maxValue);
|
||||
state.origin = getScalarScreenOffset(e, dragMatrix);
|
||||
}
|
||||
else if (Math.abs(offset) > 4) {
|
||||
} else if (Math.abs(offset) > 4) {
|
||||
state.dragging = true;
|
||||
}
|
||||
return state;
|
||||
});
|
||||
};
|
||||
|
||||
this.handleDragEnd = e => {
|
||||
const {
|
||||
onChange,
|
||||
onDrag,
|
||||
} = this.props;
|
||||
const {
|
||||
dragging,
|
||||
value,
|
||||
internalValue,
|
||||
} = this.state;
|
||||
this.handleDragEnd = (e) => {
|
||||
const { onChange, onDrag } = this.props;
|
||||
const { dragging, value, internalValue } = this.state;
|
||||
document.body.style['pointer-events'] = 'auto';
|
||||
clearTimeout(this.timer);
|
||||
clearInterval(this.dragInterval);
|
||||
@@ -145,8 +125,7 @@ export class DraggableControl extends Component {
|
||||
if (onDrag) {
|
||||
onDrag(e, value);
|
||||
}
|
||||
}
|
||||
else if (this.inputRef) {
|
||||
} else if (this.inputRef) {
|
||||
const input = this.inputRef.current;
|
||||
input.value = internalValue;
|
||||
// IE8: Dies when trying to focus a hidden element
|
||||
@@ -154,19 +133,13 @@ export class DraggableControl extends Component {
|
||||
try {
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
catch {}
|
||||
} catch {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
dragging,
|
||||
editing,
|
||||
value: intermediateValue,
|
||||
suppressingFlicker,
|
||||
} = this.state;
|
||||
const { dragging, editing, value: intermediateValue, suppressingFlicker } = this.state;
|
||||
const {
|
||||
animated,
|
||||
value,
|
||||
@@ -190,22 +163,14 @@ export class DraggableControl extends Component {
|
||||
// Setup a display element
|
||||
// Shows a formatted number based on what we are currently doing
|
||||
// with the draggable surface.
|
||||
const renderDisplayElement = value => (
|
||||
value + (unit ? ' ' + unit : '')
|
||||
);
|
||||
const displayElement = (
|
||||
animated && !dragging && !suppressingFlicker && (
|
||||
<AnimatedNumber
|
||||
value={displayValue}
|
||||
format={format}>
|
||||
const renderDisplayElement = (value) => value + (unit ? ' ' + unit : '');
|
||||
const displayElement =
|
||||
(animated && !dragging && !suppressingFlicker && (
|
||||
<AnimatedNumber value={displayValue} format={format}>
|
||||
{renderDisplayElement}
|
||||
</AnimatedNumber>
|
||||
) || (
|
||||
renderDisplayElement(format
|
||||
? format(displayValue)
|
||||
: displayValue)
|
||||
)
|
||||
);
|
||||
)) ||
|
||||
renderDisplayElement(format ? format(displayValue) : displayValue);
|
||||
// Setup an input element
|
||||
// Handles direct input via the keyboard
|
||||
const inputElement = (
|
||||
@@ -218,19 +183,15 @@ export class DraggableControl extends Component {
|
||||
'line-height': lineHeight,
|
||||
'font-size': fontSize,
|
||||
}}
|
||||
onBlur={e => {
|
||||
onBlur={(e) => {
|
||||
if (!editing) {
|
||||
return;
|
||||
}
|
||||
let value;
|
||||
if (unclamped) {
|
||||
value = parseFloat(e.target.value);
|
||||
}
|
||||
else {
|
||||
value = clamp(
|
||||
parseFloat(e.target.value),
|
||||
minValue,
|
||||
maxValue);
|
||||
} else {
|
||||
value = clamp(parseFloat(e.target.value), minValue, maxValue);
|
||||
}
|
||||
if (Number.isNaN(value)) {
|
||||
this.setState({
|
||||
@@ -250,17 +211,13 @@ export class DraggableControl extends Component {
|
||||
onDrag(e, value);
|
||||
}
|
||||
}}
|
||||
onKeyDown={e => {
|
||||
onKeyDown={(e) => {
|
||||
if (e.keyCode === 13) {
|
||||
let value;
|
||||
if (unclamped) {
|
||||
value = parseFloat(e.target.value);
|
||||
}
|
||||
else {
|
||||
value = clamp(
|
||||
parseFloat(e.target.value),
|
||||
minValue,
|
||||
maxValue);
|
||||
} else {
|
||||
value = clamp(parseFloat(e.target.value), minValue, maxValue);
|
||||
}
|
||||
if (Number.isNaN(value)) {
|
||||
this.setState({
|
||||
@@ -287,7 +244,8 @@ export class DraggableControl extends Component {
|
||||
});
|
||||
return;
|
||||
}
|
||||
}} />
|
||||
}}
|
||||
/>
|
||||
);
|
||||
// Return a part of the state for higher-level components to use.
|
||||
return children({
|
||||
|
||||
@@ -32,8 +32,7 @@ export class Dropdown extends Component {
|
||||
if (open) {
|
||||
setTimeout(() => window.addEventListener('click', this.handleClick));
|
||||
this.menuRef.focus();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
window.removeEventListener('click', this.handleClick);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +47,7 @@ export class Dropdown extends Component {
|
||||
|
||||
buildMenu() {
|
||||
const { options = [], placeholder } = this.props; // VOREStation edit
|
||||
const ops = options.map(option => (
|
||||
const ops = options.map((option) => (
|
||||
<Box
|
||||
key={option}
|
||||
className="Dropdown__menuentry"
|
||||
@@ -60,7 +59,7 @@ export class Dropdown extends Component {
|
||||
));
|
||||
// VOREStation addition start
|
||||
if (placeholder) {
|
||||
ops.unshift((
|
||||
ops.unshift(
|
||||
<div
|
||||
key={placeholder}
|
||||
className="Dropdown__menuentry"
|
||||
@@ -69,7 +68,7 @@ export class Dropdown extends Component {
|
||||
}}>
|
||||
-- {placeholder} --
|
||||
</div>
|
||||
));
|
||||
);
|
||||
}
|
||||
// VOREStation addition end
|
||||
return ops.length ? ops : 'No Options Found';
|
||||
@@ -93,24 +92,20 @@ export class Dropdown extends Component {
|
||||
placeholder, // VOREStation Addition
|
||||
...boxProps
|
||||
} = props;
|
||||
const {
|
||||
className,
|
||||
...rest
|
||||
} = boxProps;
|
||||
const { className, ...rest } = boxProps;
|
||||
|
||||
const adjustedOpen = over ? !this.state.open : this.state.open;
|
||||
|
||||
const menu = this.state.open ? (
|
||||
<div
|
||||
ref={menu => { this.menuRef = menu; }}
|
||||
ref={(menu) => {
|
||||
this.menuRef = menu;
|
||||
}}
|
||||
tabIndex="-1"
|
||||
style={{
|
||||
'width': width,
|
||||
}}
|
||||
className={classes([
|
||||
noscroll && 'Dropdown__menu-noscroll' || 'Dropdown__menu',
|
||||
over && 'Dropdown__over',
|
||||
])}>
|
||||
className={classes([(noscroll && 'Dropdown__menu-noscroll') || 'Dropdown__menu', over && 'Dropdown__over'])}>
|
||||
{this.buildMenu()}
|
||||
</div>
|
||||
) : null;
|
||||
@@ -133,15 +128,9 @@ export class Dropdown extends Component {
|
||||
}
|
||||
this.setOpen(!this.state.open);
|
||||
}}>
|
||||
{icon && (
|
||||
<Icon
|
||||
name={icon}
|
||||
rotation={iconRotation}
|
||||
spin={iconSpin}
|
||||
mr={1} />
|
||||
)}
|
||||
{icon && <Icon name={icon} rotation={iconRotation} spin={iconSpin} mr={1} />}
|
||||
<span className="Dropdown__selected-text">
|
||||
{displayText ? displayText : (this.state.selected || placeholder) /* VOREStation Edit */ }
|
||||
{displayText ? displayText : this.state.selected || placeholder /* VOREStation Edit */}
|
||||
</span>
|
||||
{!!nochevron || (
|
||||
<span className="Dropdown__arrow-button">
|
||||
|
||||
@@ -50,17 +50,9 @@ export const computeFlexProps = (props: FlexProps) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const Flex = props => {
|
||||
export const Flex = (props) => {
|
||||
const { className, ...rest } = props;
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
className,
|
||||
computeFlexClassName(rest),
|
||||
])}
|
||||
{...computeFlexProps(rest)}
|
||||
/>
|
||||
);
|
||||
return <div className={classes([className, computeFlexClassName(rest)])} {...computeFlexProps(rest)} />;
|
||||
};
|
||||
|
||||
Flex.defaultHooks = pureComponentHooks;
|
||||
@@ -74,11 +66,7 @@ export type FlexItemProps = BoxProps & {
|
||||
};
|
||||
|
||||
export const computeFlexItemClassName = (props: FlexItemProps) => {
|
||||
return classes([
|
||||
'Flex__item',
|
||||
Byond.IS_LTE_IE10 && 'Flex__item--iefix',
|
||||
computeBoxClassName(props),
|
||||
]);
|
||||
return classes(['Flex__item', Byond.IS_LTE_IE10 && 'Flex__item--iefix', computeBoxClassName(props)]);
|
||||
};
|
||||
|
||||
export const computeFlexItemProps = (props: FlexItemProps) => {
|
||||
@@ -107,15 +95,11 @@ export const computeFlexItemProps = (props: FlexItemProps) => {
|
||||
});
|
||||
};
|
||||
|
||||
const FlexItem = props => {
|
||||
const FlexItem = (props) => {
|
||||
const { className, ...rest } = props;
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
className,
|
||||
computeFlexItemClassName(props),
|
||||
computeBoxClassName(props),
|
||||
])}
|
||||
className={classes([className, computeFlexItemClassName(props), computeBoxClassName(props)])}
|
||||
{...computeFlexItemProps(rest)}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -8,13 +8,11 @@ import { Table } from './Table';
|
||||
import { pureComponentHooks } from 'common/react';
|
||||
|
||||
/** @deprecated */
|
||||
export const Grid = props => {
|
||||
export const Grid = (props) => {
|
||||
const { children, ...rest } = props;
|
||||
return (
|
||||
<Table {...rest}>
|
||||
<Table.Row>
|
||||
{children}
|
||||
</Table.Row>
|
||||
<Table.Row>{children}</Table.Row>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
@@ -22,7 +20,7 @@ export const Grid = props => {
|
||||
Grid.defaultHooks = pureComponentHooks;
|
||||
|
||||
/** @deprecated */
|
||||
export const GridColumn = props => {
|
||||
export const GridColumn = (props) => {
|
||||
const { size = 1, style, ...rest } = props;
|
||||
return (
|
||||
<Table.Cell
|
||||
@@ -30,7 +28,8 @@ export const GridColumn = props => {
|
||||
width: size + '%',
|
||||
...style,
|
||||
}}
|
||||
{...rest} />
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,22 +11,14 @@ import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
|
||||
const FA_OUTLINE_REGEX = /-o$/;
|
||||
|
||||
export const Icon = props => {
|
||||
const {
|
||||
name,
|
||||
size,
|
||||
spin,
|
||||
className,
|
||||
rotation,
|
||||
inverse,
|
||||
...rest
|
||||
} = props;
|
||||
export const Icon = (props) => {
|
||||
const { name, size, spin, className, rotation, inverse, ...rest } = props;
|
||||
|
||||
if (size) {
|
||||
if (!rest.style) {
|
||||
rest.style = {};
|
||||
}
|
||||
rest.style['font-size'] = (size * 100) + '%';
|
||||
rest.style['font-size'] = size * 100 + '%';
|
||||
}
|
||||
if (typeof rotation === 'number') {
|
||||
if (!rest.style) {
|
||||
@@ -37,44 +29,25 @@ export const Icon = props => {
|
||||
|
||||
const boxProps = computeBoxProps(rest);
|
||||
|
||||
let iconClass = "";
|
||||
if (name.startsWith("tg-")) {
|
||||
let iconClass = '';
|
||||
if (name.startsWith('tg-')) {
|
||||
// tgfont icon
|
||||
iconClass = name;
|
||||
} else {
|
||||
// font awesome icon
|
||||
const faRegular = FA_OUTLINE_REGEX.test(name);
|
||||
const faName = name.replace(FA_OUTLINE_REGEX, '');
|
||||
iconClass = (faRegular ? 'far ' : 'fas ') + 'fa-'+ faName + (spin ? " fa-spin" : "");
|
||||
iconClass = (faRegular ? 'far ' : 'fas ') + 'fa-' + faName + (spin ? ' fa-spin' : '');
|
||||
}
|
||||
return (
|
||||
<i
|
||||
className={classes([
|
||||
'Icon',
|
||||
iconClass,
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
{...boxProps} />
|
||||
);
|
||||
return <i className={classes(['Icon', iconClass, className, computeBoxClassName(rest)])} {...boxProps} />;
|
||||
};
|
||||
|
||||
Icon.defaultHooks = pureComponentHooks;
|
||||
|
||||
export const IconStack = props => {
|
||||
const {
|
||||
className,
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
export const IconStack = (props) => {
|
||||
const { className, children, ...rest } = props;
|
||||
return (
|
||||
<span
|
||||
class={classes([
|
||||
'IconStack',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
{...computeBoxProps(rest)}>
|
||||
<span class={classes(['IconStack', className, computeBoxClassName(rest)])} {...computeBoxProps(rest)}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { computeBoxProps } from "./Box";
|
||||
import { Stack } from "./Stack";
|
||||
import { ProgressBar } from "./ProgressBar";
|
||||
import { Button } from "./Button";
|
||||
import { computeBoxProps } from './Box';
|
||||
import { Stack } from './Stack';
|
||||
import { ProgressBar } from './ProgressBar';
|
||||
import { Button } from './Button';
|
||||
import { Component } from 'inferno';
|
||||
|
||||
const ZOOM_MIN_VAL = 0.5;
|
||||
@@ -33,19 +33,19 @@ export class InfinitePlane extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener("mouseup", this.onMouseUp);
|
||||
window.addEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
window.addEventListener("mousedown", this.doOffsetMouse);
|
||||
window.addEventListener("mousemove", this.doOffsetMouse);
|
||||
window.addEventListener("mouseup", this.doOffsetMouse);
|
||||
window.addEventListener('mousedown', this.doOffsetMouse);
|
||||
window.addEventListener('mousemove', this.doOffsetMouse);
|
||||
window.addEventListener('mouseup', this.doOffsetMouse);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("mouseup", this.onMouseUp);
|
||||
window.removeEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
window.removeEventListener("mousedown", this.doOffsetMouse);
|
||||
window.removeEventListener("mousemove", this.doOffsetMouse);
|
||||
window.removeEventListener("mouseup", this.doOffsetMouse);
|
||||
window.removeEventListener('mousedown', this.doOffsetMouse);
|
||||
window.removeEventListener('mousemove', this.doOffsetMouse);
|
||||
window.removeEventListener('mouseup', this.doOffsetMouse);
|
||||
}
|
||||
|
||||
doOffsetMouse(event) {
|
||||
@@ -82,17 +82,8 @@ export class InfinitePlane extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
backgroundImage,
|
||||
imageWidth,
|
||||
...rest
|
||||
} = this.props;
|
||||
const {
|
||||
left,
|
||||
top,
|
||||
zoom,
|
||||
} = this.state;
|
||||
const { children, backgroundImage, imageWidth, ...rest } = this.props;
|
||||
const { left, top, zoom } = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -101,65 +92,60 @@ export class InfinitePlane extends Component {
|
||||
...rest,
|
||||
style: {
|
||||
...rest.style,
|
||||
overflow: "hidden",
|
||||
position: "relative",
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
},
|
||||
})}
|
||||
>
|
||||
})}>
|
||||
<div
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseMove={this.handleMouseMove}
|
||||
style={{
|
||||
"position": "fixed",
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"background-image": `url("${backgroundImage}")`,
|
||||
"background-position": `${left}px ${top}px`,
|
||||
"background-repeat": "repeat",
|
||||
"background-size": `${zoom*imageWidth}px`,
|
||||
'position': 'fixed',
|
||||
'height': '100%',
|
||||
'width': '100%',
|
||||
'background-image': `url("${backgroundImage}")`,
|
||||
'background-position': `${left}px ${top}px`,
|
||||
'background-repeat': 'repeat',
|
||||
'background-size': `${zoom * imageWidth}px`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseMove={this.handleMouseMove}
|
||||
style={{
|
||||
"position": "fixed",
|
||||
"transform": `translate(${left}px, ${top}px) scale(${zoom})`,
|
||||
"transform-origin": "top left",
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}}
|
||||
>
|
||||
'position': 'fixed',
|
||||
'transform': `translate(${left}px, ${top}px) scale(${zoom})`,
|
||||
'transform-origin': 'top left',
|
||||
'height': '100%',
|
||||
'width': '100%',
|
||||
}}>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
<Stack
|
||||
position="absolute"
|
||||
width="100%"
|
||||
>
|
||||
<Stack position="absolute" width="100%">
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="minus"
|
||||
onClick={() => this.setState({
|
||||
zoom: Math.max(zoom-ZOOM_INCREMENT, ZOOM_MIN_VAL),
|
||||
})}
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
zoom: Math.max(zoom - ZOOM_INCREMENT, ZOOM_MIN_VAL),
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow={1}>
|
||||
<ProgressBar
|
||||
minValue={ZOOM_MIN_VAL}
|
||||
value={zoom}
|
||||
maxValue={ZOOM_MAX_VAL}
|
||||
>
|
||||
<ProgressBar minValue={ZOOM_MIN_VAL} value={zoom} maxValue={ZOOM_MAX_VAL}>
|
||||
{zoom}x
|
||||
</ProgressBar>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="plus"
|
||||
onClick={() => this.setState({
|
||||
zoom: Math.min(zoom+ZOOM_INCREMENT, ZOOM_MAX_VAL),
|
||||
})}
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
zoom: Math.min(zoom + ZOOM_INCREMENT, ZOOM_MAX_VAL),
|
||||
})
|
||||
}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
|
||||
@@ -9,11 +9,7 @@ import { Component, createRef } from 'inferno';
|
||||
import { Box } from './Box';
|
||||
import { KEY_ESCAPE, KEY_ENTER } from 'common/keycodes';
|
||||
|
||||
export const toInputValue = value => (
|
||||
typeof value !== 'number' && typeof value !== 'string'
|
||||
? ''
|
||||
: String(value)
|
||||
);
|
||||
export const toInputValue = (value) => (typeof value !== 'number' && typeof value !== 'string' ? '' : String(value));
|
||||
|
||||
export class Input extends Component {
|
||||
constructor() {
|
||||
@@ -22,7 +18,7 @@ export class Input extends Component {
|
||||
this.state = {
|
||||
editing: false,
|
||||
};
|
||||
this.handleInput = e => {
|
||||
this.handleInput = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onInput } = this.props;
|
||||
if (!editing) {
|
||||
@@ -32,7 +28,7 @@ export class Input extends Component {
|
||||
onInput(e, e.target.value);
|
||||
}
|
||||
};
|
||||
this.handleFocus = e => {
|
||||
this.handleFocus = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { autoSelect } = this.props;
|
||||
if (!editing) {
|
||||
@@ -42,7 +38,7 @@ export class Input extends Component {
|
||||
e.target.select();
|
||||
}
|
||||
};
|
||||
this.handleBlur = e => {
|
||||
this.handleBlur = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onChange } = this.props;
|
||||
if (editing) {
|
||||
@@ -52,7 +48,7 @@ export class Input extends Component {
|
||||
}
|
||||
}
|
||||
};
|
||||
this.handleKeyDown = e => {
|
||||
this.handleKeyDown = (e) => {
|
||||
const { onInput, onChange, onEnter } = this.props;
|
||||
if (e.keyCode === KEY_ENTER) {
|
||||
this.setEditing(false);
|
||||
@@ -121,35 +117,14 @@ export class Input extends Component {
|
||||
render() {
|
||||
const { props } = this;
|
||||
// Input only props
|
||||
const {
|
||||
selfClear,
|
||||
onInput,
|
||||
onChange,
|
||||
onEnter,
|
||||
value,
|
||||
maxLength,
|
||||
placeholder,
|
||||
...boxProps
|
||||
} = props;
|
||||
const { selfClear, onInput, onChange, onEnter, value, maxLength, placeholder, ...boxProps } = props;
|
||||
// Box props
|
||||
const {
|
||||
className,
|
||||
fluid,
|
||||
monospace,
|
||||
...rest
|
||||
} = boxProps;
|
||||
const { className, fluid, monospace, ...rest } = boxProps;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'Input',
|
||||
fluid && 'Input--fluid',
|
||||
monospace && 'Input--monospace',
|
||||
className,
|
||||
])}
|
||||
className={classes(['Input', fluid && 'Input--fluid', monospace && 'Input--monospace', className])}
|
||||
{...rest}>
|
||||
<div className="Input__baseline">
|
||||
.
|
||||
</div>
|
||||
<div className="Input__baseline">.</div>
|
||||
<input
|
||||
ref={this.inputRef}
|
||||
className="Input__input"
|
||||
@@ -158,7 +133,8 @@ export class Input extends Component {
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
maxLength={maxLength} />
|
||||
maxLength={maxLength}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Component } from "inferno";
|
||||
import { KeyEvent } from "../events";
|
||||
import { listenForKeyEvents } from "../hotkeys";
|
||||
import { Component } from 'inferno';
|
||||
import { KeyEvent } from '../events';
|
||||
import { listenForKeyEvents } from '../hotkeys';
|
||||
|
||||
type KeyListenerProps = Partial<{
|
||||
onKey: (key: KeyEvent) => void,
|
||||
onKeyDown: (key: KeyEvent) => void,
|
||||
onKeyUp: (key: KeyEvent) => void,
|
||||
onKey: (key: KeyEvent) => void;
|
||||
onKeyDown: (key: KeyEvent) => void;
|
||||
onKeyUp: (key: KeyEvent) => void;
|
||||
}>;
|
||||
|
||||
export class KeyListener extends Component<KeyListenerProps> {
|
||||
@@ -14,7 +14,7 @@ export class KeyListener extends Component<KeyListenerProps> {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.dispose = listenForKeyEvents(key => {
|
||||
this.dispose = listenForKeyEvents((key) => {
|
||||
if (this.props.onKey) {
|
||||
this.props.onKey(key);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,11 @@ import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
import { DraggableControl } from './DraggableControl';
|
||||
import { NumberInput } from './NumberInput';
|
||||
|
||||
export const Knob = props => {
|
||||
export const Knob = (props) => {
|
||||
// IE8: I don't want to support a yet another component on IE8.
|
||||
// IE8: It also can't handle SVG.
|
||||
if (Byond.IS_LTE_IE8) {
|
||||
return (
|
||||
<NumberInput {...props} />
|
||||
);
|
||||
return <NumberInput {...props} />;
|
||||
}
|
||||
const {
|
||||
// Draggable props (passthrough)
|
||||
@@ -60,27 +58,11 @@ export const Knob = props => {
|
||||
unit,
|
||||
value,
|
||||
}}>
|
||||
{control => {
|
||||
const {
|
||||
dragging,
|
||||
editing,
|
||||
value,
|
||||
displayValue,
|
||||
displayElement,
|
||||
inputElement,
|
||||
handleDragStart,
|
||||
} = control;
|
||||
const scaledFillValue = scale(
|
||||
fillValue ?? displayValue,
|
||||
minValue,
|
||||
maxValue);
|
||||
const scaledDisplayValue = scale(
|
||||
displayValue,
|
||||
minValue,
|
||||
maxValue);
|
||||
const effectiveColor = color
|
||||
|| keyOfMatchingRange(fillValue ?? value, ranges)
|
||||
|| 'default';
|
||||
{(control) => {
|
||||
const { dragging, editing, value, displayValue, displayElement, inputElement, handleDragStart } = control;
|
||||
const scaledFillValue = scale(fillValue ?? displayValue, minValue, maxValue);
|
||||
const scaledDisplayValue = scale(displayValue, minValue, maxValue);
|
||||
const effectiveColor = color || keyOfMatchingRange(fillValue ?? value, ranges) || 'default';
|
||||
const rotation = Math.min((scaledDisplayValue - 0.5) * 270, 225);
|
||||
return (
|
||||
<div
|
||||
@@ -108,34 +90,20 @@ export const Knob = props => {
|
||||
<div className="Knob__cursor" />
|
||||
</div>
|
||||
</div>
|
||||
{dragging && (
|
||||
<div className="Knob__popupValue">
|
||||
{displayElement}
|
||||
</div>
|
||||
)}
|
||||
<svg
|
||||
className="Knob__ring Knob__ringTrackPivot"
|
||||
viewBox="0 0 100 100">
|
||||
<circle
|
||||
className="Knob__ringTrack"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="50" />
|
||||
{dragging && <div className="Knob__popupValue">{displayElement}</div>}
|
||||
<svg className="Knob__ring Knob__ringTrackPivot" viewBox="0 0 100 100">
|
||||
<circle className="Knob__ringTrack" cx="50" cy="50" r="50" />
|
||||
</svg>
|
||||
<svg
|
||||
className="Knob__ring Knob__ringFillPivot"
|
||||
viewBox="0 0 100 100">
|
||||
<svg className="Knob__ring Knob__ringFillPivot" viewBox="0 0 100 100">
|
||||
<circle
|
||||
className="Knob__ringFill"
|
||||
style={{
|
||||
'stroke-dashoffset': (
|
||||
Math.max(((bipolar ? 2.75 : 2.00) - scaledFillValue * 1.5)
|
||||
* Math.PI * 50, 0)
|
||||
),
|
||||
'stroke-dashoffset': Math.max(((bipolar ? 2.75 : 2.0) - scaledFillValue * 1.5) * Math.PI * 50, 0),
|
||||
}}
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="50" />
|
||||
r="50"
|
||||
/>
|
||||
</svg>
|
||||
{inputElement}
|
||||
</div>
|
||||
|
||||
@@ -6,47 +6,23 @@
|
||||
|
||||
import { Flex } from './Flex';
|
||||
|
||||
export const LabeledControls = props => {
|
||||
const {
|
||||
children,
|
||||
wrap,
|
||||
...rest
|
||||
} = props;
|
||||
export const LabeledControls = (props) => {
|
||||
const { children, wrap, ...rest } = props;
|
||||
return (
|
||||
<Flex
|
||||
mx={-0.5}
|
||||
wrap={wrap}
|
||||
align="stretch"
|
||||
justify="space-between"
|
||||
{...rest}>
|
||||
<Flex mx={-0.5} wrap={wrap} align="stretch" justify="space-between" {...rest}>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
const LabeledControlsItem = props => {
|
||||
const {
|
||||
label,
|
||||
children,
|
||||
mx = 1,
|
||||
...rest
|
||||
} = props;
|
||||
const LabeledControlsItem = (props) => {
|
||||
const { label, children, mx = 1, ...rest } = props;
|
||||
return (
|
||||
<Flex.Item mx={mx}>
|
||||
<Flex
|
||||
height="100%"
|
||||
direction="column"
|
||||
align="center"
|
||||
textAlign="center"
|
||||
justify="space-between"
|
||||
{...rest}>
|
||||
<Flex height="100%" direction="column" align="center" textAlign="center" justify="space-between" {...rest}>
|
||||
<Flex.Item />
|
||||
<Flex.Item>
|
||||
{children}
|
||||
</Flex.Item>
|
||||
<Flex.Item color="label">
|
||||
{label}
|
||||
</Flex.Item>
|
||||
<Flex.Item>{children}</Flex.Item>
|
||||
<Flex.Item color="label">{label}</Flex.Item>
|
||||
</Flex>
|
||||
</Flex.Item>
|
||||
);
|
||||
|
||||
@@ -15,11 +15,7 @@ type LabeledListProps = {
|
||||
|
||||
export const LabeledList = (props: LabeledListProps) => {
|
||||
const { children } = props;
|
||||
return (
|
||||
<table className="LabeledList">
|
||||
{children}
|
||||
</table>
|
||||
);
|
||||
return <table className="LabeledList">{children}</table>;
|
||||
};
|
||||
|
||||
LabeledList.defaultHooks = pureComponentHooks;
|
||||
@@ -31,9 +27,9 @@ type LabeledListItemProps = {
|
||||
color?: string | BooleanLike;
|
||||
textAlign?: string | BooleanLike;
|
||||
verticalAlign?: string | BooleanLike; // VOREStation Addition
|
||||
buttons?: InfernoNode,
|
||||
buttons?: InfernoNode;
|
||||
/** @deprecated */
|
||||
content?: any,
|
||||
content?: any;
|
||||
children?: InfernoNode;
|
||||
};
|
||||
|
||||
@@ -51,19 +47,12 @@ const LabeledListItem = (props: LabeledListItemProps) => {
|
||||
...rest // VOREStation Addition
|
||||
} = props;
|
||||
return (
|
||||
<tr
|
||||
className={classes([
|
||||
'LabeledList__row',
|
||||
className,
|
||||
])}>
|
||||
<tr className={classes(['LabeledList__row', className])}>
|
||||
<Box
|
||||
as="td"
|
||||
verticalAlign={verticalAlign} // VOREStation Addition
|
||||
color={labelColor}
|
||||
className={classes([
|
||||
'LabeledList__cell',
|
||||
'LabeledList__label',
|
||||
])}>
|
||||
className={classes(['LabeledList__cell', 'LabeledList__label'])}>
|
||||
{label ? label + ':' : null}
|
||||
</Box>
|
||||
<Box
|
||||
@@ -71,20 +60,14 @@ const LabeledListItem = (props: LabeledListItemProps) => {
|
||||
color={color}
|
||||
textAlign={textAlign}
|
||||
verticalAlign={verticalAlign} // VOREStation Addition
|
||||
className={classes([
|
||||
'LabeledList__cell',
|
||||
'LabeledList__content',
|
||||
])}
|
||||
className={classes(['LabeledList__cell', 'LabeledList__content'])}
|
||||
colSpan={buttons ? undefined : 2}
|
||||
{...rest} /* VOREStation Addition*/>
|
||||
{...rest} /* VOREStation Addition*/
|
||||
>
|
||||
{content}
|
||||
{children}
|
||||
</Box>
|
||||
{buttons && (
|
||||
<td className="LabeledList__cell LabeledList__buttons">
|
||||
{buttons}
|
||||
</td>
|
||||
)}
|
||||
{buttons && <td className="LabeledList__cell LabeledList__buttons">{buttons}</td>}
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
@@ -96,9 +79,7 @@ type LabeledListDividerProps = {
|
||||
};
|
||||
|
||||
const LabeledListDivider = (props: LabeledListDividerProps) => {
|
||||
const padding = props.size
|
||||
? unit(Math.max(0, props.size - 1))
|
||||
: 0;
|
||||
const padding = props.size ? unit(Math.max(0, props.size - 1)) : 0;
|
||||
return (
|
||||
<tr className="LabeledList__row">
|
||||
<td
|
||||
|
||||
@@ -8,7 +8,7 @@ import { classes } from 'common/react';
|
||||
import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
import { Dimmer } from './Dimmer';
|
||||
|
||||
export const Modal = props => {
|
||||
export const Modal = (props) => {
|
||||
const {
|
||||
className,
|
||||
children,
|
||||
@@ -18,7 +18,7 @@ export const Modal = props => {
|
||||
// VOREStation Addition Start
|
||||
let handleKeyDown;
|
||||
if (onEnter) {
|
||||
handleKeyDown = e => {
|
||||
handleKeyDown = (e) => {
|
||||
let key = e.which || e.keyCode;
|
||||
if (key === 13) {
|
||||
onEnter(e);
|
||||
@@ -27,15 +27,8 @@ export const Modal = props => {
|
||||
}
|
||||
// VOREStation Addition End
|
||||
return (
|
||||
<Dimmer
|
||||
onKeyDown={handleKeyDown /* VOREStation Edit */}>
|
||||
<div
|
||||
className={classes([
|
||||
'Modal',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
{...computeBoxProps(rest)}>
|
||||
<Dimmer onKeyDown={handleKeyDown /* VOREStation Edit */}>
|
||||
<div className={classes(['Modal', className, computeBoxClassName(rest)])} {...computeBoxProps(rest)}>
|
||||
{children}
|
||||
</div>
|
||||
</Dimmer>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { Component } from 'inferno';
|
||||
import { Box, Button, Icon, Tooltip, LabeledList, Slider } from '.';
|
||||
import { useBackend } from "../backend";
|
||||
import { useBackend } from '../backend';
|
||||
|
||||
const pauseEvent = e => {
|
||||
if (e.stopPropagation) { e.stopPropagation(); }
|
||||
if (e.preventDefault) { e.preventDefault(); }
|
||||
const pauseEvent = (e) => {
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
e.cancelBubble = true;
|
||||
e.returnValue = false;
|
||||
return false;
|
||||
@@ -17,8 +21,8 @@ export class NanoMap extends Component {
|
||||
super(props);
|
||||
|
||||
// Auto center based on window size
|
||||
const Xcenter = (window.innerWidth / 2) - 256;
|
||||
const Ycenter = (window.innerHeight / 2) - 256;
|
||||
const Xcenter = window.innerWidth / 2 - 256;
|
||||
const Ycenter = window.innerHeight / 2 - 256;
|
||||
|
||||
this.state = {
|
||||
offsetX: Xcenter,
|
||||
@@ -31,7 +35,7 @@ export class NanoMap extends Component {
|
||||
};
|
||||
|
||||
// Dragging
|
||||
this.handleDragStart = e => {
|
||||
this.handleDragStart = (e) => {
|
||||
this.ref = e.target;
|
||||
this.setState({
|
||||
dragging: false,
|
||||
@@ -43,8 +47,8 @@ export class NanoMap extends Component {
|
||||
pauseEvent(e);
|
||||
};
|
||||
|
||||
this.handleDragMove = e => {
|
||||
this.setState(prevState => {
|
||||
this.handleDragMove = (e) => {
|
||||
this.setState((prevState) => {
|
||||
const state = { ...prevState };
|
||||
const newOffsetX = e.screenX - state.originX;
|
||||
const newOffsetY = e.screenY - state.originY;
|
||||
@@ -61,7 +65,7 @@ export class NanoMap extends Component {
|
||||
pauseEvent(e);
|
||||
};
|
||||
|
||||
this.handleDragEnd = e => {
|
||||
this.handleDragEnd = (e) => {
|
||||
this.setState({
|
||||
dragging: false,
|
||||
originX: null,
|
||||
@@ -72,30 +76,38 @@ export class NanoMap extends Component {
|
||||
pauseEvent(e);
|
||||
};
|
||||
|
||||
this.handleOnClick = e => {
|
||||
let byondX = (e.offsetX/this.state.zoom)/zoomScale;
|
||||
let byondY = 1-(e.offsetY/this.state.zoom)/zoomScale; // Byond origin is bottom left, this is top left
|
||||
|
||||
this.handleOnClick = (e) => {
|
||||
let byondX = e.offsetX / this.state.zoom / zoomScale;
|
||||
let byondY = 1 - e.offsetY / this.state.zoom / zoomScale; // Byond origin is bottom left, this is top left
|
||||
|
||||
e.byondX = byondX;
|
||||
e.byondY = byondY;
|
||||
if (typeof(this.props.onClick) === "function") {
|
||||
if (typeof this.props.onClick === 'function') {
|
||||
this.props.onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.handleZoom = (_e, value) => {
|
||||
this.setState(state => {
|
||||
this.setState((state) => {
|
||||
const newZoom = Math.min(Math.max(value, 1), 8);
|
||||
let zoomDiff = (newZoom - state.zoom) * 1.5;
|
||||
state.zoom = newZoom;
|
||||
|
||||
let newOffsetX = state.offsetX - 262 * zoomDiff;
|
||||
if (newOffsetX < -500) { newOffsetX = -500; }
|
||||
if (newOffsetX > 500) { newOffsetX = 500; }
|
||||
|
||||
if (newOffsetX < -500) {
|
||||
newOffsetX = -500;
|
||||
}
|
||||
if (newOffsetX > 500) {
|
||||
newOffsetX = 500;
|
||||
}
|
||||
|
||||
let newOffsetY = state.offsetY - 256 * zoomDiff;
|
||||
if (newOffsetY < -200) { newOffsetY = -200; }
|
||||
if (newOffsetY > 200) { newOffsetY = 200; }
|
||||
if (newOffsetY < -200) {
|
||||
newOffsetY = -200;
|
||||
}
|
||||
if (newOffsetY > 200) {
|
||||
newOffsetY = 200;
|
||||
}
|
||||
|
||||
state.offsetX = newOffsetX;
|
||||
state.offsetY = newOffsetY;
|
||||
@@ -105,41 +117,34 @@ export class NanoMap extends Component {
|
||||
return state;
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const { config } = useBackend(this.context);
|
||||
const { dragging, offsetX, offsetY, zoom = 1 } = this.state;
|
||||
const { children } = this.props;
|
||||
|
||||
const mapUrl = config.map + "_nanomap_z" + config.mapZLevel + ".png";
|
||||
|
||||
const mapUrl = config.map + '_nanomap_z' + config.mapZLevel + '.png';
|
||||
// (x * zoom), x Needs to be double the turf- map size. (for virgo, 140x140)
|
||||
const mapSize = (zoomScale * zoom) + 'px';
|
||||
const mapSize = zoomScale * zoom + 'px';
|
||||
const newStyle = {
|
||||
width: mapSize,
|
||||
height: mapSize,
|
||||
"margin-top": offsetY + "px",
|
||||
"margin-left": offsetX + "px",
|
||||
"overflow": "hidden",
|
||||
"position": "relative",
|
||||
"background-image": "url(" + mapUrl + ")",
|
||||
"background-size": "cover",
|
||||
"background-repeat": "no-repeat",
|
||||
"text-align": "center",
|
||||
"cursor": dragging ? "move" : "auto",
|
||||
'margin-top': offsetY + 'px',
|
||||
'margin-left': offsetX + 'px',
|
||||
'overflow': 'hidden',
|
||||
'position': 'relative',
|
||||
'background-image': 'url(' + mapUrl + ')',
|
||||
'background-size': 'cover',
|
||||
'background-repeat': 'no-repeat',
|
||||
'text-align': 'center',
|
||||
'cursor': dragging ? 'move' : 'auto',
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className="NanoMap__container">
|
||||
<Box
|
||||
style={newStyle}
|
||||
textAlign="center"
|
||||
onMouseDown={this.handleDragStart}
|
||||
onClick={this.handleOnClick}>
|
||||
<Box>
|
||||
{children}
|
||||
</Box>
|
||||
<Box style={newStyle} textAlign="center" onMouseDown={this.handleDragStart} onClick={this.handleOnClick}>
|
||||
<Box>{children}</Box>
|
||||
</Box>
|
||||
<NanoMapZoomer zoom={zoom} onZoom={this.handleZoom} />
|
||||
</Box>
|
||||
@@ -148,39 +153,27 @@ export class NanoMap extends Component {
|
||||
}
|
||||
|
||||
const NanoMapMarker = (props, context) => {
|
||||
const {
|
||||
x,
|
||||
y,
|
||||
zoom = 1,
|
||||
icon,
|
||||
tooltip,
|
||||
color,
|
||||
onClick,
|
||||
} = props;
|
||||
const { x, y, zoom = 1, icon, tooltip, color, onClick } = props;
|
||||
|
||||
const handleOnClick = e => {
|
||||
const handleOnClick = (e) => {
|
||||
pauseEvent(e);
|
||||
if (onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
};
|
||||
|
||||
const rx = ((x * 2 * zoom) - zoom) - 3;
|
||||
const ry = ((y * 2 * zoom) - zoom) - 3;
|
||||
const rx = x * 2 * zoom - zoom - 3;
|
||||
const ry = y * 2 * zoom - zoom - 3;
|
||||
return (
|
||||
<div>
|
||||
<Box
|
||||
position="absolute"
|
||||
className="NanoMap__marker"
|
||||
lineHeight="0"
|
||||
bottom={ry + "px"}
|
||||
left={rx + "px"}
|
||||
bottom={ry + 'px'}
|
||||
left={rx + 'px'}
|
||||
onMouseDown={handleOnClick}>
|
||||
<Icon
|
||||
name={icon}
|
||||
color={color}
|
||||
fontSize="6px"
|
||||
/>
|
||||
<Icon name={icon} color={color} fontSize="6px" />
|
||||
<Tooltip content={tooltip} />
|
||||
</Box>
|
||||
</div>
|
||||
@@ -199,7 +192,7 @@ const NanoMapZoomer = (props, context) => {
|
||||
minValue="1"
|
||||
maxValue="8"
|
||||
stepPixelSize="10"
|
||||
format={v => v + "x"}
|
||||
format={(v) => v + 'x'}
|
||||
value={props.zoom}
|
||||
onDrag={(e, v) => props.onZoom(e, v)}
|
||||
/>
|
||||
@@ -207,14 +200,15 @@ const NanoMapZoomer = (props, context) => {
|
||||
<LabeledList.Item label="Z-Level">
|
||||
{data.map_levels
|
||||
.sort((a, b) => Number(a) - Number(b))
|
||||
.map(level => (
|
||||
.map((level) => (
|
||||
<Button
|
||||
key={level}
|
||||
selected={~~level === ~~config.mapZLevel}
|
||||
content={level}
|
||||
onClick={() => {
|
||||
act("setZLevel", { "mapZLevel": level });
|
||||
}} />
|
||||
act('setZLevel', { 'mapZLevel': level });
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
|
||||
@@ -7,16 +7,8 @@
|
||||
import { classes, pureComponentHooks } from 'common/react';
|
||||
import { Box } from './Box';
|
||||
|
||||
export const NoticeBox = props => {
|
||||
const {
|
||||
className,
|
||||
color,
|
||||
info,
|
||||
warning,
|
||||
success,
|
||||
danger,
|
||||
...rest
|
||||
} = props;
|
||||
export const NoticeBox = (props) => {
|
||||
const { className, color, info, warning, success, danger, ...rest } = props;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
@@ -27,7 +19,8 @@ export const NoticeBox = props => {
|
||||
danger && 'NoticeBox--type--danger',
|
||||
className,
|
||||
])}
|
||||
{...rest} />
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -35,13 +35,17 @@ export class NumberInput extends Component {
|
||||
suppressingFlicker: true,
|
||||
});
|
||||
clearTimeout(this.flickerTimer);
|
||||
this.flickerTimer = setTimeout(() => this.setState({
|
||||
suppressingFlicker: false,
|
||||
}), suppressFlicker);
|
||||
this.flickerTimer = setTimeout(
|
||||
() =>
|
||||
this.setState({
|
||||
suppressingFlicker: false,
|
||||
}),
|
||||
suppressFlicker
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
this.handleDragStart = e => {
|
||||
this.handleDragStart = (e) => {
|
||||
const { value } = this.props;
|
||||
const { editing } = this.state;
|
||||
if (editing) {
|
||||
@@ -71,38 +75,31 @@ export class NumberInput extends Component {
|
||||
document.addEventListener('mouseup', this.handleDragEnd);
|
||||
};
|
||||
|
||||
this.handleDragMove = e => {
|
||||
this.handleDragMove = (e) => {
|
||||
const { minValue, maxValue, step, stepPixelSize } = this.props;
|
||||
this.setState(prevState => {
|
||||
this.setState((prevState) => {
|
||||
const state = { ...prevState };
|
||||
const offset = state.origin - e.screenY;
|
||||
if (prevState.dragging) {
|
||||
const stepOffset = Number.isFinite(minValue)
|
||||
? minValue % step
|
||||
: 0;
|
||||
const stepOffset = Number.isFinite(minValue) ? minValue % step : 0;
|
||||
// Translate mouse movement to value
|
||||
// Give it some headroom (by increasing clamp range by 1 step)
|
||||
state.internalValue = clamp(
|
||||
state.internalValue + offset * step / stepPixelSize,
|
||||
state.internalValue + (offset * step) / stepPixelSize,
|
||||
minValue - step,
|
||||
maxValue + step);
|
||||
maxValue + step
|
||||
);
|
||||
// Clamp the final value
|
||||
state.value = clamp(
|
||||
state.internalValue
|
||||
- state.internalValue % step
|
||||
+ stepOffset,
|
||||
minValue,
|
||||
maxValue);
|
||||
state.value = clamp(state.internalValue - (state.internalValue % step) + stepOffset, minValue, maxValue);
|
||||
state.origin = e.screenY;
|
||||
}
|
||||
else if (Math.abs(offset) > 4) {
|
||||
} else if (Math.abs(offset) > 4) {
|
||||
state.dragging = true;
|
||||
}
|
||||
return state;
|
||||
});
|
||||
};
|
||||
|
||||
this.handleDragEnd = e => {
|
||||
this.handleDragEnd = (e) => {
|
||||
const { onChange, onDrag } = this.props;
|
||||
const { dragging, value, internalValue } = this.state;
|
||||
document.body.style['pointer-events'] = 'auto';
|
||||
@@ -123,8 +120,7 @@ export class NumberInput extends Component {
|
||||
if (onDrag) {
|
||||
onDrag(e, value);
|
||||
}
|
||||
}
|
||||
else if (this.inputRef) {
|
||||
} else if (this.inputRef) {
|
||||
const input = this.inputRef.current;
|
||||
input.value = internalValue;
|
||||
// IE8: Dies when trying to focus a hidden element
|
||||
@@ -132,19 +128,13 @@ export class NumberInput extends Component {
|
||||
try {
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
catch {}
|
||||
} catch {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
dragging,
|
||||
editing,
|
||||
value: intermediateValue,
|
||||
suppressingFlicker,
|
||||
} = this.state;
|
||||
const { dragging, editing, value: intermediateValue, suppressingFlicker } = this.state;
|
||||
const {
|
||||
className,
|
||||
fluid,
|
||||
@@ -166,29 +156,21 @@ export class NumberInput extends Component {
|
||||
displayValue = intermediateValue;
|
||||
}
|
||||
// IE8: Use an "unselectable" prop because "user-select" doesn't work.
|
||||
const renderContentElement = value => (
|
||||
<div
|
||||
className="NumberInput__content"
|
||||
unselectable={Byond.IS_LTE_IE8}>
|
||||
const renderContentElement = (value) => (
|
||||
<div className="NumberInput__content" unselectable={Byond.IS_LTE_IE8}>
|
||||
{value + (unit ? ' ' + unit : '')}
|
||||
</div>
|
||||
);
|
||||
const contentElement = (animated && !dragging && !suppressingFlicker && (
|
||||
<AnimatedNumber
|
||||
value={displayValue}
|
||||
format={format}>
|
||||
{renderContentElement}
|
||||
</AnimatedNumber>
|
||||
) || (
|
||||
renderContentElement(format ? format(displayValue) : displayValue)
|
||||
));
|
||||
const contentElement =
|
||||
(animated && !dragging && !suppressingFlicker && (
|
||||
<AnimatedNumber value={displayValue} format={format}>
|
||||
{renderContentElement}
|
||||
</AnimatedNumber>
|
||||
)) ||
|
||||
renderContentElement(format ? format(displayValue) : displayValue);
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'NumberInput',
|
||||
fluid && 'NumberInput--fluid',
|
||||
className,
|
||||
])}
|
||||
className={classes(['NumberInput', fluid && 'NumberInput--fluid', className])}
|
||||
minWidth={width}
|
||||
minHeight={height}
|
||||
lineHeight={lineHeight}
|
||||
@@ -198,10 +180,9 @@ export class NumberInput extends Component {
|
||||
<div
|
||||
className="NumberInput__bar"
|
||||
style={{
|
||||
height: clamp(
|
||||
(displayValue - minValue) / (maxValue - minValue) * 100,
|
||||
0, 100) + '%',
|
||||
}} />
|
||||
height: clamp(((displayValue - minValue) / (maxValue - minValue)) * 100, 0, 100) + '%',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{contentElement}
|
||||
<input
|
||||
@@ -213,14 +194,11 @@ export class NumberInput extends Component {
|
||||
'line-height': lineHeight,
|
||||
'font-size': fontSize,
|
||||
}}
|
||||
onBlur={e => {
|
||||
onBlur={(e) => {
|
||||
if (!editing) {
|
||||
return;
|
||||
}
|
||||
const value = clamp(
|
||||
parseFloat(e.target.value),
|
||||
minValue,
|
||||
maxValue);
|
||||
const value = clamp(parseFloat(e.target.value), minValue, maxValue);
|
||||
if (Number.isNaN(value)) {
|
||||
this.setState({
|
||||
editing: false,
|
||||
@@ -239,12 +217,9 @@ export class NumberInput extends Component {
|
||||
onDrag(e, value);
|
||||
}
|
||||
}}
|
||||
onKeyDown={e => {
|
||||
onKeyDown={(e) => {
|
||||
if (e.keyCode === 13) {
|
||||
const value = clamp(
|
||||
parseFloat(e.target.value),
|
||||
minValue,
|
||||
maxValue);
|
||||
const value = clamp(parseFloat(e.target.value), minValue, maxValue);
|
||||
if (Number.isNaN(value)) {
|
||||
this.setState({
|
||||
editing: false,
|
||||
@@ -270,7 +245,8 @@ export class NumberInput extends Component {
|
||||
});
|
||||
return;
|
||||
}
|
||||
}} />
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -47,11 +47,7 @@ export class Popper extends Component<PopperProps> {
|
||||
return;
|
||||
}
|
||||
|
||||
this.popperInstance = createPopper(
|
||||
domNode,
|
||||
this.renderedContent,
|
||||
options
|
||||
);
|
||||
this.popperInstance = createPopper(domNode, this.renderedContent, options);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,12 +65,7 @@ export class Popper extends Component<PopperProps> {
|
||||
renderPopperContent(callback: () => void) {
|
||||
// `render` errors when given false, so we convert it to `null`,
|
||||
// which is supported.
|
||||
render(
|
||||
this.props.popperContent || null,
|
||||
this.renderedContent,
|
||||
callback,
|
||||
this.context,
|
||||
);
|
||||
render(this.props.popperContent || null, this.renderedContent, callback, this.context);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -8,22 +8,11 @@ import { clamp01, scale, keyOfMatchingRange, toFixed } from 'common/math';
|
||||
import { classes, pureComponentHooks } from 'common/react';
|
||||
import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
|
||||
export const ProgressBar = props => {
|
||||
const {
|
||||
className,
|
||||
value,
|
||||
minValue = 0,
|
||||
maxValue = 1,
|
||||
color,
|
||||
ranges = {},
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
export const ProgressBar = (props) => {
|
||||
const { className, value, minValue = 0, maxValue = 1, color, ranges = {}, children, ...rest } = props;
|
||||
const scaledValue = scale(value, minValue, maxValue);
|
||||
const hasContent = children !== undefined;
|
||||
const effectiveColor = color
|
||||
|| keyOfMatchingRange(value, ranges)
|
||||
|| 'default';
|
||||
const effectiveColor = color || keyOfMatchingRange(value, ranges) || 'default';
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
@@ -37,12 +26,9 @@ export const ProgressBar = props => {
|
||||
className="ProgressBar__fill ProgressBar__fill--animated"
|
||||
style={{
|
||||
width: clamp01(scaledValue) * 100 + '%',
|
||||
}} />
|
||||
<div className="ProgressBar__content">
|
||||
{hasContent
|
||||
? children
|
||||
: toFixed(scaledValue * 100) + '%'}
|
||||
</div>
|
||||
}}
|
||||
/>
|
||||
<div className="ProgressBar__content">{hasContent ? children : toFixed(scaledValue * 100) + '%'}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -131,12 +131,7 @@ export class RestrictedInput extends Component {
|
||||
const { className, fluid, monospace, ...rest } = boxProps;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'Input',
|
||||
fluid && 'Input--fluid',
|
||||
monospace && 'Input--monospace',
|
||||
className,
|
||||
])}
|
||||
className={classes(['Input', fluid && 'Input--fluid', monospace && 'Input--monospace', className])}
|
||||
{...rest}>
|
||||
<div className="Input__baseline">.</div>
|
||||
<input
|
||||
|
||||
@@ -9,41 +9,23 @@ import { classes } from 'common/react';
|
||||
import { AnimatedNumber } from './AnimatedNumber';
|
||||
import { Box, computeBoxClassName, computeBoxProps } from './Box';
|
||||
|
||||
export const RoundGauge = props => {
|
||||
export const RoundGauge = (props) => {
|
||||
// Support for IE8 is for losers sorry B)
|
||||
if (Byond.IS_LTE_IE8) {
|
||||
return (
|
||||
<AnimatedNumber {...props} />
|
||||
);
|
||||
return <AnimatedNumber {...props} />;
|
||||
}
|
||||
|
||||
const {
|
||||
value,
|
||||
minValue = 1,
|
||||
maxValue = 1,
|
||||
ranges,
|
||||
alertAfter,
|
||||
format,
|
||||
size = 1,
|
||||
className,
|
||||
style,
|
||||
...rest
|
||||
} = props;
|
||||
const { value, minValue = 1, maxValue = 1, ranges, alertAfter, format, size = 1, className, style, ...rest } = props;
|
||||
|
||||
const scaledValue = scale(
|
||||
value,
|
||||
minValue,
|
||||
maxValue);
|
||||
const scaledValue = scale(value, minValue, maxValue);
|
||||
const clampedValue = clamp01(scaledValue);
|
||||
let scaledRanges = ranges ? {} : { "primary": [0, 1] };
|
||||
if (ranges)
|
||||
{ Object.keys(ranges).forEach(x => {
|
||||
const range = ranges[x];
|
||||
scaledRanges[x] = [
|
||||
scale(range[0], minValue, maxValue),
|
||||
scale(range[1], minValue, maxValue),
|
||||
];
|
||||
}); }
|
||||
let scaledRanges = ranges ? {} : { 'primary': [0, 1] };
|
||||
if (ranges) {
|
||||
Object.keys(ranges).forEach((x) => {
|
||||
const range = ranges[x];
|
||||
scaledRanges[x] = [scale(range[0], minValue, maxValue), scale(range[1], minValue, maxValue)];
|
||||
});
|
||||
}
|
||||
|
||||
let alertColor = null;
|
||||
if (alertAfter < value) {
|
||||
@@ -53,11 +35,7 @@ export const RoundGauge = props => {
|
||||
return (
|
||||
<Box inline>
|
||||
<div
|
||||
className={classes([
|
||||
'RoundGauge',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
className={classes(['RoundGauge', className, computeBoxClassName(rest)])}
|
||||
{...computeBoxProps({
|
||||
style: {
|
||||
'font-size': size + 'em',
|
||||
@@ -65,22 +43,14 @@ export const RoundGauge = props => {
|
||||
},
|
||||
...rest,
|
||||
})}>
|
||||
<svg
|
||||
viewBox="0 0 100 50">
|
||||
<svg viewBox="0 0 100 50">
|
||||
{alertAfter && (
|
||||
<g className={classes([
|
||||
'RoundGauge__alert',
|
||||
alertColor ? `active RoundGauge__alert--${alertColor}` : '',
|
||||
])}>
|
||||
<g className={classes(['RoundGauge__alert', alertColor ? `active RoundGauge__alert--${alertColor}` : ''])}>
|
||||
<path d="M48.211,14.578C48.55,13.9 49.242,13.472 50,13.472C50.758,13.472 51.45,13.9 51.789,14.578C54.793,20.587 60.795,32.589 63.553,38.106C63.863,38.726 63.83,39.462 63.465,40.051C63.101,40.641 62.457,41 61.764,41C55.996,41 44.004,41 38.236,41C37.543,41 36.899,40.641 36.535,40.051C36.17,39.462 36.137,38.726 36.447,38.106C39.205,32.589 45.207,20.587 48.211,14.578ZM50,34.417C51.426,34.417 52.583,35.574 52.583,37C52.583,38.426 51.426,39.583 50,39.583C48.574,39.583 47.417,38.426 47.417,37C47.417,35.574 48.574,34.417 50,34.417ZM50,32.75C50,32.75 53,31.805 53,22.25C53,20.594 51.656,19.25 50,19.25C48.344,19.25 47,20.594 47,22.25C47,31.805 50,32.75 50,32.75Z" />
|
||||
</g>
|
||||
)}
|
||||
<g>
|
||||
<circle
|
||||
className="RoundGauge__ringTrack"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="45" />
|
||||
<circle className="RoundGauge__ringTrack" cx="50" cy="50" r="45" />
|
||||
</g>
|
||||
<g>
|
||||
{Object.keys(scaledRanges).map((x, i) => {
|
||||
@@ -90,36 +60,23 @@ export const RoundGauge = props => {
|
||||
className={`RoundGauge__ringFill RoundGauge--color--${x}`}
|
||||
key={i}
|
||||
style={{
|
||||
'stroke-dashoffset': (
|
||||
Math.max((2.0 - (col_ranges[1] - col_ranges[0]))
|
||||
* Math.PI * 50, 0)
|
||||
),
|
||||
'stroke-dashoffset': Math.max((2.0 - (col_ranges[1] - col_ranges[0])) * Math.PI * 50, 0),
|
||||
}}
|
||||
transform={`rotate(${180 + 180 * col_ranges[0]} 50 50)`}
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="45" />
|
||||
r="45"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</g>
|
||||
<g
|
||||
className="RoundGauge__needle"
|
||||
transform={`rotate(${clampedValue * 180 - 90} 50 50)`}>
|
||||
<polygon
|
||||
className="RoundGauge__needleLine"
|
||||
points="46,50 50,0 54,50" />
|
||||
<circle
|
||||
className="RoundGauge__needleMiddle"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="8" />
|
||||
<g className="RoundGauge__needle" transform={`rotate(${clampedValue * 180 - 90} 50 50)`}>
|
||||
<polygon className="RoundGauge__needleLine" points="46,50 50,0 54,50" />
|
||||
<circle className="RoundGauge__needleMiddle" cx="50" cy="50" r="8" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<AnimatedNumber
|
||||
value={value}
|
||||
format={format}
|
||||
size={size} />
|
||||
<AnimatedNumber value={value} format={format} size={size} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -84,21 +84,19 @@ export class Section extends Component<SectionProps> {
|
||||
{...computeBoxProps(rest)}>
|
||||
{hasTitle && (
|
||||
<div className="Section__title">
|
||||
<span className="Section__titleText">
|
||||
{title}
|
||||
</span>
|
||||
<div className="Section__buttons">
|
||||
{buttons}
|
||||
</div>
|
||||
<span className="Section__titleText">{title}</span>
|
||||
<div className="Section__buttons">{buttons}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="Section__rest">
|
||||
{/* Vorestation Edit Start */}
|
||||
<div ref={this.scrollableRef} className={classes([
|
||||
"Section__content",
|
||||
!!stretchContents && "Section__content--stretchContents",
|
||||
!!noTopPadding && "Section__content--noTopPadding",
|
||||
])}>
|
||||
<div
|
||||
ref={this.scrollableRef}
|
||||
className={classes([
|
||||
'Section__content',
|
||||
!!stretchContents && 'Section__content--stretchContents',
|
||||
!!noTopPadding && 'Section__content--noTopPadding',
|
||||
])}>
|
||||
{children}
|
||||
</div>
|
||||
{/* Vorestation Edit End */}
|
||||
|
||||
@@ -10,12 +10,10 @@ import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
import { DraggableControl } from './DraggableControl';
|
||||
import { NumberInput } from './NumberInput';
|
||||
|
||||
export const Slider = props => {
|
||||
export const Slider = (props) => {
|
||||
// IE8: I don't want to support a yet another component on IE8.
|
||||
if (Byond.IS_LTE_IE8) {
|
||||
return (
|
||||
<NumberInput {...props} />
|
||||
);
|
||||
return <NumberInput {...props} />;
|
||||
}
|
||||
const {
|
||||
// Draggable props (passthrough)
|
||||
@@ -55,33 +53,13 @@ export const Slider = props => {
|
||||
unit,
|
||||
value,
|
||||
}}>
|
||||
{control => {
|
||||
const {
|
||||
dragging,
|
||||
editing,
|
||||
value,
|
||||
displayValue,
|
||||
displayElement,
|
||||
inputElement,
|
||||
handleDragStart,
|
||||
} = control;
|
||||
const hasFillValue = fillValue !== undefined
|
||||
&& fillValue !== null;
|
||||
const scaledValue = scale(
|
||||
value,
|
||||
minValue,
|
||||
maxValue);
|
||||
const scaledFillValue = scale(
|
||||
fillValue ?? displayValue,
|
||||
minValue,
|
||||
maxValue);
|
||||
const scaledDisplayValue = scale(
|
||||
displayValue,
|
||||
minValue,
|
||||
maxValue);
|
||||
const effectiveColor = color
|
||||
|| keyOfMatchingRange(fillValue ?? value, ranges)
|
||||
|| 'default';
|
||||
{(control) => {
|
||||
const { dragging, editing, value, displayValue, displayElement, inputElement, handleDragStart } = control;
|
||||
const hasFillValue = fillValue !== undefined && fillValue !== null;
|
||||
const scaledValue = scale(value, minValue, maxValue);
|
||||
const scaledFillValue = scale(fillValue ?? displayValue, minValue, maxValue);
|
||||
const scaledDisplayValue = scale(displayValue, minValue, maxValue);
|
||||
const effectiveColor = color || keyOfMatchingRange(fillValue ?? value, ranges) || 'default';
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
@@ -94,20 +72,18 @@ export const Slider = props => {
|
||||
{...computeBoxProps(rest)}
|
||||
onMouseDown={handleDragStart}>
|
||||
<div
|
||||
className={classes([
|
||||
'ProgressBar__fill',
|
||||
hasFillValue && 'ProgressBar__fill--animated',
|
||||
])}
|
||||
className={classes(['ProgressBar__fill', hasFillValue && 'ProgressBar__fill--animated'])}
|
||||
style={{
|
||||
width: clamp01(scaledFillValue) * 100 + '%',
|
||||
opacity: 0.4,
|
||||
}} />
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="ProgressBar__fill"
|
||||
style={{
|
||||
width: clamp01(Math.min(scaledFillValue, scaledDisplayValue))
|
||||
* 100 + '%',
|
||||
}} />
|
||||
width: clamp01(Math.min(scaledFillValue, scaledDisplayValue)) * 100 + '%',
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="Slider__cursorOffset"
|
||||
style={{
|
||||
@@ -115,17 +91,9 @@ export const Slider = props => {
|
||||
}}>
|
||||
<div className="Slider__cursor" />
|
||||
<div className="Slider__pointer" />
|
||||
{dragging && (
|
||||
<div className="Slider__popupValue">
|
||||
{displayElement}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="ProgressBar__content">
|
||||
{hasContent
|
||||
? children
|
||||
: displayElement}
|
||||
{dragging && <div className="Slider__popupValue">{displayElement}</div>}
|
||||
</div>
|
||||
<div className="ProgressBar__content">{hasContent ? children : displayElement}</div>
|
||||
{inputElement}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -20,31 +20,22 @@ export const Stack = (props: StackProps) => {
|
||||
className={classes([
|
||||
'Stack',
|
||||
fill && 'Stack--fill',
|
||||
vertical
|
||||
? 'Stack--vertical'
|
||||
: 'Stack--horizontal',
|
||||
vertical ? 'Stack--vertical' : 'Stack--horizontal',
|
||||
className,
|
||||
])}
|
||||
direction={vertical ? 'column' : 'row'}
|
||||
{...rest} />
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
type StackItemProps = FlexProps & {
|
||||
innerRef?: RefObject<HTMLDivElement>,
|
||||
innerRef?: RefObject<HTMLDivElement>;
|
||||
};
|
||||
|
||||
const StackItem = (props: StackItemProps) => {
|
||||
const { className, innerRef, ...rest } = props;
|
||||
return (
|
||||
<Flex.Item
|
||||
className={classes([
|
||||
'Stack__item',
|
||||
className,
|
||||
])}
|
||||
ref={innerRef}
|
||||
{...rest} />
|
||||
);
|
||||
return <Flex.Item className={classes(['Stack__item', className])} ref={innerRef} {...rest} />;
|
||||
};
|
||||
|
||||
Stack.Item = StackItem;
|
||||
@@ -57,13 +48,9 @@ const StackDivider = (props: StackDividerProps) => {
|
||||
const { className, hidden, ...rest } = props;
|
||||
return (
|
||||
<Flex.Item
|
||||
className={classes([
|
||||
'Stack__item',
|
||||
'Stack__divider',
|
||||
hidden && 'Stack__divider--hidden',
|
||||
className,
|
||||
])}
|
||||
{...rest} />
|
||||
className={classes(['Stack__item', 'Stack__divider', hidden && 'Stack__divider--hidden', className])}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -7,58 +7,33 @@
|
||||
import { classes, pureComponentHooks } from 'common/react';
|
||||
import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
|
||||
export const Table = props => {
|
||||
const {
|
||||
className,
|
||||
collapsing,
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
export const Table = (props) => {
|
||||
const { className, collapsing, children, ...rest } = props;
|
||||
return (
|
||||
<table
|
||||
className={classes([
|
||||
'Table',
|
||||
collapsing && 'Table--collapsing',
|
||||
className,
|
||||
computeBoxClassName(rest),
|
||||
])}
|
||||
className={classes(['Table', collapsing && 'Table--collapsing', className, computeBoxClassName(rest)])}
|
||||
{...computeBoxProps(rest)}>
|
||||
<tbody>
|
||||
{children}
|
||||
</tbody>
|
||||
<tbody>{children}</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
Table.defaultHooks = pureComponentHooks;
|
||||
|
||||
export const TableRow = props => {
|
||||
const {
|
||||
className,
|
||||
header,
|
||||
...rest
|
||||
} = props;
|
||||
export const TableRow = (props) => {
|
||||
const { className, header, ...rest } = props;
|
||||
return (
|
||||
<tr
|
||||
className={classes([
|
||||
'Table__row',
|
||||
header && 'Table__row--header',
|
||||
className,
|
||||
computeBoxClassName(props),
|
||||
])}
|
||||
{...computeBoxProps(rest)} />
|
||||
className={classes(['Table__row', header && 'Table__row--header', className, computeBoxClassName(props)])}
|
||||
{...computeBoxProps(rest)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
TableRow.defaultHooks = pureComponentHooks;
|
||||
|
||||
export const TableCell = props => {
|
||||
const {
|
||||
className,
|
||||
collapsing,
|
||||
header,
|
||||
...rest
|
||||
} = props;
|
||||
export const TableCell = (props) => {
|
||||
const { className, collapsing, header, ...rest } = props;
|
||||
return (
|
||||
<td
|
||||
className={classes([
|
||||
@@ -68,7 +43,8 @@ export const TableCell = props => {
|
||||
className,
|
||||
computeBoxClassName(props),
|
||||
])}
|
||||
{...computeBoxProps(rest)} />
|
||||
{...computeBoxProps(rest)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -8,22 +8,13 @@ import { canRender, classes } from 'common/react';
|
||||
import { computeBoxClassName, computeBoxProps } from './Box';
|
||||
import { Icon } from './Icon';
|
||||
|
||||
export const Tabs = props => {
|
||||
const {
|
||||
className,
|
||||
vertical,
|
||||
fill,
|
||||
fluid,
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
export const Tabs = (props) => {
|
||||
const { className, vertical, fill, fluid, children, ...rest } = props;
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
'Tabs',
|
||||
vertical
|
||||
? 'Tabs--vertical'
|
||||
: 'Tabs--horizontal',
|
||||
vertical ? 'Tabs--vertical' : 'Tabs--horizontal',
|
||||
fill && 'Tabs--fill',
|
||||
fluid && 'Tabs--fluid',
|
||||
className,
|
||||
@@ -35,17 +26,8 @@ export const Tabs = props => {
|
||||
);
|
||||
};
|
||||
|
||||
const Tab = props => {
|
||||
const {
|
||||
className,
|
||||
selected,
|
||||
color,
|
||||
icon,
|
||||
leftSlot,
|
||||
rightSlot,
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
const Tab = (props) => {
|
||||
const { className, selected, color, icon, leftSlot, rightSlot, children, ...rest } = props;
|
||||
return (
|
||||
<div
|
||||
className={classes([
|
||||
@@ -57,23 +39,14 @@ const Tab = props => {
|
||||
...computeBoxClassName(rest),
|
||||
])}
|
||||
{...computeBoxProps(rest)}>
|
||||
{canRender(leftSlot) && (
|
||||
<div className="Tab__left">
|
||||
{leftSlot}
|
||||
</div>
|
||||
) || !!icon && (
|
||||
<div className="Tab__left">
|
||||
<Icon name={icon} />
|
||||
</div>
|
||||
)}
|
||||
<div className="Tab__text">
|
||||
{children}
|
||||
</div>
|
||||
{canRender(rightSlot) && (
|
||||
<div className="Tab__right">
|
||||
{rightSlot}
|
||||
</div>
|
||||
)}
|
||||
{(canRender(leftSlot) && <div className="Tab__left">{leftSlot}</div>) ||
|
||||
(!!icon && (
|
||||
<div className="Tab__left">
|
||||
<Icon name={icon} />
|
||||
</div>
|
||||
))}
|
||||
<div className="Tab__text">{children}</div>
|
||||
{canRender(rightSlot) && <div className="Tab__right">{rightSlot}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,10 +19,8 @@ export class TextArea extends Component {
|
||||
this.state = {
|
||||
editing: false,
|
||||
};
|
||||
const {
|
||||
dontUseTabForIndent = false,
|
||||
} = props;
|
||||
this.handleOnInput = e => {
|
||||
const { dontUseTabForIndent = false } = props;
|
||||
this.handleOnInput = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onInput } = this.props;
|
||||
if (!editing) {
|
||||
@@ -32,7 +30,7 @@ export class TextArea extends Component {
|
||||
onInput(e, e.target.value);
|
||||
}
|
||||
};
|
||||
this.handleOnChange = e => {
|
||||
this.handleOnChange = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onChange } = this.props;
|
||||
if (editing) {
|
||||
@@ -42,7 +40,7 @@ export class TextArea extends Component {
|
||||
onChange(e, e.target.value);
|
||||
}
|
||||
};
|
||||
this.handleKeyPress = e => {
|
||||
this.handleKeyPress = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onKeyPress } = this.props;
|
||||
if (!editing) {
|
||||
@@ -52,7 +50,7 @@ export class TextArea extends Component {
|
||||
onKeyPress(e, e.target.value);
|
||||
}
|
||||
};
|
||||
this.handleKeyDown = e => {
|
||||
this.handleKeyDown = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onChange, onInput, onEnter, onKeyDown } = this.props;
|
||||
if (e.keyCode === KEY_ENTER) {
|
||||
@@ -96,21 +94,18 @@ export class TextArea extends Component {
|
||||
if (keyCode === KEY_TAB) {
|
||||
e.preventDefault();
|
||||
const { value, selectionStart, selectionEnd } = e.target;
|
||||
e.target.value = (
|
||||
value.substring(0, selectionStart) + "\t"
|
||||
+ value.substring(selectionEnd)
|
||||
);
|
||||
e.target.value = value.substring(0, selectionStart) + '\t' + value.substring(selectionEnd);
|
||||
e.target.selectionEnd = selectionStart + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
this.handleFocus = e => {
|
||||
this.handleFocus = (e) => {
|
||||
const { editing } = this.state;
|
||||
if (!editing) {
|
||||
this.setEditing(true);
|
||||
}
|
||||
};
|
||||
this.handleBlur = e => {
|
||||
this.handleBlur = (e) => {
|
||||
const { editing } = this.state;
|
||||
const { onChange } = this.props;
|
||||
if (editing) {
|
||||
@@ -137,7 +132,7 @@ export class TextArea extends Component {
|
||||
const prevValue = prevProps.value;
|
||||
const nextValue = this.props.value;
|
||||
const input = this.textareaRef.current;
|
||||
if (input && typeof nextValue === "string" && prevValue !== nextValue) {
|
||||
if (input && typeof nextValue === 'string' && prevValue !== nextValue) {
|
||||
input.value = toInputValue(nextValue);
|
||||
}
|
||||
}
|
||||
@@ -166,19 +161,9 @@ export class TextArea extends Component {
|
||||
...boxProps
|
||||
} = this.props;
|
||||
// Box props
|
||||
const {
|
||||
className,
|
||||
fluid,
|
||||
...rest
|
||||
} = boxProps;
|
||||
const { className, fluid, ...rest } = boxProps;
|
||||
return (
|
||||
<Box
|
||||
className={classes([
|
||||
'TextArea',
|
||||
fluid && 'TextArea--fluid',
|
||||
className,
|
||||
])}
|
||||
{...rest}>
|
||||
<Box className={classes(['TextArea', fluid && 'TextArea--fluid', className])} {...rest}>
|
||||
<textarea
|
||||
ref={this.textareaRef}
|
||||
className="TextArea__textarea"
|
||||
@@ -189,7 +174,8 @@ export class TextArea extends Component {
|
||||
onInput={this.handleOnInput}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleBlur}
|
||||
maxLength={maxLength} />
|
||||
maxLength={maxLength}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ import { formatTime } from '../format';
|
||||
import { Component } from 'inferno';
|
||||
|
||||
// AnimatedNumber Copypaste
|
||||
const isSafeNumber = value => {
|
||||
return typeof value === 'number'
|
||||
&& Number.isFinite(value)
|
||||
&& !Number.isNaN(value);
|
||||
const isSafeNumber = (value) => {
|
||||
return typeof value === 'number' && Number.isFinite(value) && !Number.isNaN(value);
|
||||
};
|
||||
|
||||
export class TimeDisplay extends Component {
|
||||
@@ -36,7 +34,7 @@ export class TimeDisplay extends Component {
|
||||
this.last_seen_value = this.props.value;
|
||||
current = this.props.value;
|
||||
}
|
||||
const mod = this.props.auto === "up" ? 10 : -10; // Time down by default.
|
||||
const mod = this.props.auto === 'up' ? 10 : -10; // Time down by default.
|
||||
const value = Math.max(0, current + mod); // one sec tick
|
||||
this.setState({ value });
|
||||
}
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
|
||||
import { Placement } from '@popperjs/core';
|
||||
import { Component, findDOMfromVNode, InfernoNode } from 'inferno';
|
||||
import { Popper } from "./Popper";
|
||||
import { Popper } from './Popper';
|
||||
|
||||
const DEFAULT_PLACEMENT = "top";
|
||||
const DEFAULT_PLACEMENT = 'top';
|
||||
|
||||
type TooltipProps = {
|
||||
children?: InfernoNode;
|
||||
content: InfernoNode;
|
||||
position?: Placement,
|
||||
position?: Placement;
|
||||
};
|
||||
|
||||
type TooltipState = {
|
||||
hovered: boolean;
|
||||
};
|
||||
|
||||
const DISABLE_EVENT_LISTENERS = [{
|
||||
name: "eventListeners",
|
||||
enabled: false,
|
||||
}];
|
||||
const DISABLE_EVENT_LISTENERS = [
|
||||
{
|
||||
name: 'eventListeners',
|
||||
enabled: false,
|
||||
},
|
||||
];
|
||||
|
||||
export class Tooltip extends Component<TooltipProps, TooltipState> {
|
||||
state = {
|
||||
@@ -40,13 +41,13 @@ export class Tooltip extends Component<TooltipProps, TooltipState> {
|
||||
return;
|
||||
}
|
||||
|
||||
domNode.addEventListener("mouseenter", () => {
|
||||
domNode.addEventListener('mouseenter', () => {
|
||||
this.setState({
|
||||
hovered: true,
|
||||
});
|
||||
});
|
||||
|
||||
domNode.addEventListener("mouseleave", () => {
|
||||
domNode.addEventListener('mouseleave', () => {
|
||||
this.setState({
|
||||
hovered: false,
|
||||
});
|
||||
@@ -57,7 +58,7 @@ export class Tooltip extends Component<TooltipProps, TooltipState> {
|
||||
return (
|
||||
<Popper
|
||||
options={{
|
||||
placement: this.props.position || "auto",
|
||||
placement: this.props.position || 'auto',
|
||||
modifiers: DISABLE_EVENT_LISTENERS,
|
||||
}}
|
||||
popperContent={
|
||||
@@ -70,8 +71,8 @@ export class Tooltip extends Component<TooltipProps, TooltipState> {
|
||||
</div>
|
||||
}
|
||||
additionalStyles={{
|
||||
"pointer-events": "none",
|
||||
"z-index": 2,
|
||||
'pointer-events': 'none',
|
||||
'z-index': 2,
|
||||
}}>
|
||||
{this.props.children}
|
||||
</Popper>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, createRef } from "inferno";
|
||||
import { Component, createRef } from 'inferno';
|
||||
|
||||
export class TrackOutsideClicks extends Component<{
|
||||
onOutsideClick: () => void,
|
||||
onOutsideClick: () => void;
|
||||
}> {
|
||||
ref = createRef<HTMLDivElement>();
|
||||
|
||||
@@ -10,11 +10,11 @@ export class TrackOutsideClicks extends Component<{
|
||||
|
||||
this.handleOutsideClick = this.handleOutsideClick.bind(this);
|
||||
|
||||
document.addEventListener("click", this.handleOutsideClick);
|
||||
document.addEventListener('click', this.handleOutsideClick);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener("click", this.handleOutsideClick);
|
||||
document.removeEventListener('click', this.handleOutsideClick);
|
||||
}
|
||||
|
||||
handleOutsideClick(event: MouseEvent) {
|
||||
@@ -28,10 +28,6 @@ export class TrackOutsideClicks extends Component<{
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div ref={this.ref}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
return <div ref={this.ref}>{this.props.children}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,16 +25,16 @@ export const COLORS = {
|
||||
},
|
||||
// VOREStation Addition begin
|
||||
manifest: {
|
||||
command: "#3333FF",
|
||||
security: "#8e0000",
|
||||
medical: "#006600",
|
||||
engineering: "#b27300",
|
||||
science: "#a65ba6",
|
||||
cargo: "#bb9040",
|
||||
planetside: "#555555",
|
||||
civilian: "#a32800",
|
||||
miscellaneous: "#666666",
|
||||
silicon: "#222222",
|
||||
command: '#3333FF',
|
||||
security: '#8e0000',
|
||||
medical: '#006600',
|
||||
engineering: '#b27300',
|
||||
science: '#a65ba6',
|
||||
cargo: '#bb9040',
|
||||
planetside: '#555555',
|
||||
civilian: '#a32800',
|
||||
miscellaneous: '#666666',
|
||||
silicon: '#222222',
|
||||
},
|
||||
// VOREStation Addition end
|
||||
// Damage type colors
|
||||
@@ -46,8 +46,8 @@ export const COLORS = {
|
||||
},
|
||||
// reagent / chemistry related colours
|
||||
reagent: {
|
||||
acidicbuffer: "#fbc314",
|
||||
basicbuffer: "#3853a4",
|
||||
acidicbuffer: '#fbc314',
|
||||
basicbuffer: '#3853a4',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -78,94 +78,94 @@ export const CSS_COLORS = [
|
||||
// go use /client/verb/generate_tgui_radio_constants() in communications.dm.
|
||||
export const RADIO_CHANNELS = [
|
||||
{
|
||||
"name": "Mercenary",
|
||||
"freq": 1213,
|
||||
"color": "#6D3F40",
|
||||
'name': 'Mercenary',
|
||||
'freq': 1213,
|
||||
'color': '#6D3F40',
|
||||
},
|
||||
{
|
||||
"name": "Raider",
|
||||
"freq": 1277,
|
||||
"color": "#6D3F40",
|
||||
'name': 'Raider',
|
||||
'freq': 1277,
|
||||
'color': '#6D3F40',
|
||||
},
|
||||
{
|
||||
"name": "Special Ops",
|
||||
"freq": 1341,
|
||||
"color": "#5C5C8A",
|
||||
'name': 'Special Ops',
|
||||
'freq': 1341,
|
||||
'color': '#5C5C8A',
|
||||
},
|
||||
{
|
||||
"name": "AI Private",
|
||||
"freq": 1343,
|
||||
"color": "#FF00FF",
|
||||
'name': 'AI Private',
|
||||
'freq': 1343,
|
||||
'color': '#FF00FF',
|
||||
},
|
||||
{
|
||||
"name": "Response Team",
|
||||
"freq": 1345,
|
||||
"color": "#5C5C8A",
|
||||
'name': 'Response Team',
|
||||
'freq': 1345,
|
||||
'color': '#5C5C8A',
|
||||
},
|
||||
{
|
||||
"name": "Supply",
|
||||
"freq": 1347,
|
||||
"color": "#5F4519",
|
||||
'name': 'Supply',
|
||||
'freq': 1347,
|
||||
'color': '#5F4519',
|
||||
},
|
||||
{
|
||||
"name": "Service",
|
||||
"freq": 1349,
|
||||
"color": "#6eaa2c",
|
||||
'name': 'Service',
|
||||
'freq': 1349,
|
||||
'color': '#6eaa2c',
|
||||
},
|
||||
{
|
||||
"name": "Science",
|
||||
"freq": 1351,
|
||||
"color": "#993399",
|
||||
'name': 'Science',
|
||||
'freq': 1351,
|
||||
'color': '#993399',
|
||||
},
|
||||
{
|
||||
"name": "Command",
|
||||
"freq": 1353,
|
||||
"color": "#193A7A",
|
||||
'name': 'Command',
|
||||
'freq': 1353,
|
||||
'color': '#193A7A',
|
||||
},
|
||||
{
|
||||
"name": "Medical",
|
||||
"freq": 1355,
|
||||
"color": "#008160",
|
||||
'name': 'Medical',
|
||||
'freq': 1355,
|
||||
'color': '#008160',
|
||||
},
|
||||
{
|
||||
"name": "Engineering",
|
||||
"freq": 1357,
|
||||
"color": "#A66300",
|
||||
'name': 'Engineering',
|
||||
'freq': 1357,
|
||||
'color': '#A66300',
|
||||
},
|
||||
{
|
||||
"name": "Security",
|
||||
"freq": 1359,
|
||||
"color": "#A30000",
|
||||
'name': 'Security',
|
||||
'freq': 1359,
|
||||
'color': '#A30000',
|
||||
},
|
||||
{
|
||||
"name": "Explorer",
|
||||
"freq": 1361,
|
||||
"color": "#555555",
|
||||
'name': 'Explorer',
|
||||
'freq': 1361,
|
||||
'color': '#555555',
|
||||
},
|
||||
{
|
||||
"name": "Talon",
|
||||
"freq": 1363,
|
||||
"color": "#555555",
|
||||
'name': 'Talon',
|
||||
'freq': 1363,
|
||||
'color': '#555555',
|
||||
},
|
||||
{
|
||||
"name": "Common",
|
||||
"freq": 1459,
|
||||
"color": "#008000",
|
||||
'name': 'Common',
|
||||
'freq': 1459,
|
||||
'color': '#008000',
|
||||
},
|
||||
{
|
||||
"name": "Entertainment",
|
||||
"freq": 1461,
|
||||
"color": "#339966",
|
||||
'name': 'Entertainment',
|
||||
'freq': 1461,
|
||||
'color': '#339966',
|
||||
},
|
||||
{
|
||||
"name": "Security(I)",
|
||||
"freq": 1475,
|
||||
"color": "#008000",
|
||||
'name': 'Security(I)',
|
||||
'freq': 1475,
|
||||
'color': '#008000',
|
||||
},
|
||||
{
|
||||
"name": "Medical(I)",
|
||||
"freq": 1485,
|
||||
"color": "#008000",
|
||||
'name': 'Medical(I)',
|
||||
'freq': 1485,
|
||||
'color': '#008000',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -278,22 +278,17 @@ const GASES = [
|
||||
|
||||
export const getGasLabel = (gasId, fallbackValue) => {
|
||||
const gasSearchString = String(gasId).toLowerCase();
|
||||
const gas = GASES.find(gas => gas.id === gasSearchString
|
||||
|| gas.name.toLowerCase() === gasSearchString);
|
||||
return gas && gas.label
|
||||
|| fallbackValue
|
||||
|| gasId;
|
||||
const gas = GASES.find((gas) => gas.id === gasSearchString || gas.name.toLowerCase() === gasSearchString);
|
||||
return (gas && gas.label) || fallbackValue || gasId;
|
||||
};
|
||||
|
||||
export const getGasColor = gasId => {
|
||||
export const getGasColor = (gasId) => {
|
||||
const gasSearchString = String(gasId).toLowerCase();
|
||||
const gas = GASES.find(gas => gas.id === gasSearchString
|
||||
|| gas.name.toLowerCase() === gasSearchString);
|
||||
const gas = GASES.find((gas) => gas.id === gasSearchString || gas.name.toLowerCase() === gasSearchString);
|
||||
return gas && gas.color;
|
||||
};
|
||||
|
||||
|
||||
// VOREStation Addition start
|
||||
/** 0.0 Degrees Celsius in Kelvin */
|
||||
export const T0C = 273.15;
|
||||
// VOREStation Addition end
|
||||
// VOREStation Addition end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user