diff --git a/tgui/.eslintignore b/tgui/.eslintignore index aa593384cc..624fdbd8b6 100644 --- a/tgui/.eslintignore +++ b/tgui/.eslintignore @@ -4,5 +4,17 @@ /**/*.chunk.* /**/*.hot-update.* +**.lock +**.log +**.json +**.svg +**.scss +**.md +**.css +**.txt +**.woff2 +**.eot +**.ttf + # CHOMPEdit - Until removed /packages/tgui_ch/** diff --git a/tgui/.eslintrc-harder.yml b/tgui/.eslintrc-harder.yml deleted file mode 100644 index d466125967..0000000000 --- a/tgui/.eslintrc-harder.yml +++ /dev/null @@ -1,43 +0,0 @@ -rules: - ## Enforce a maximum cyclomatic complexity allowed in a program - # complexity: [warn, { max: 25 }] - ## Enforce consistent brace style for blocks - # brace-style: [warn, stroustrup, { allowSingleLine: false }] - ## Enforce the consistent use of either backticks, double, or single quotes - # quotes: [warn, single, { - # avoidEscape: true, - # allowTemplateLiterals: true, - # }] - # react/jsx-closing-bracket-location: [warn, { - # selfClosing: after-props, - # nonEmpty: after-props, - # }] - # react/display-name: warn - - ## Radar - ## ------------------------------------------------------ - # radar/cognitive-complexity: warn - radar/max-switch-cases: warn - radar/no-all-duplicated-branches: warn - radar/no-collapsible-if: warn - radar/no-collection-size-mischeck: warn - radar/no-duplicate-string: warn - radar/no-duplicated-branches: warn - radar/no-element-overwrite: warn - radar/no-extra-arguments: warn - radar/no-identical-conditions: warn - radar/no-identical-expressions: warn - radar/no-identical-functions: warn - radar/no-inverted-boolean-check: warn - radar/no-one-iteration-loop: warn - radar/no-redundant-boolean: warn - radar/no-redundant-jump: warn - radar/no-same-line-conditional: warn - radar/no-small-switch: warn - radar/no-unused-collection: warn - radar/no-use-of-empty-return-value: warn - radar/no-useless-catch: warn - radar/prefer-immediate-return: warn - radar/prefer-object-literal: warn - radar/prefer-single-boolean-return: warn - radar/prefer-while: warn diff --git a/tgui/.eslintrc-sonar.yml b/tgui/.eslintrc-sonar.yml new file mode 100644 index 0000000000..ebc57f72c0 --- /dev/null +++ b/tgui/.eslintrc-sonar.yml @@ -0,0 +1 @@ +extends: 'plugin:sonarjs/recommended' diff --git a/tgui/.eslintrc.yml b/tgui/.eslintrc.yml index c1bc184189..e53c0d5133 100644 --- a/tgui/.eslintrc.yml +++ b/tgui/.eslintrc.yml @@ -11,14 +11,14 @@ env: browser: true node: true plugins: - - radar + - sonarjs - react - unused-imports + - simple-import-sort settings: react: - version: '16.10' + version: '18.2' rules: - ## Possible Errors ## ---------------------------------------- ## Enforce “for” loop update clause moving the counter in the right @@ -309,13 +309,16 @@ rules: ## Enforce or disallow capitalization of the first letter of a comment # capitalized-comments: error ## Require or disallow trailing commas - comma-dangle: [error, { - arrays: always-multiline, - objects: always-multiline, - imports: always-multiline, - exports: always-multiline, - functions: only-multiline, ## Optional on functions - }] + comma-dangle: [ + error, + { + arrays: always-multiline, + objects: always-multiline, + imports: always-multiline, + exports: always-multiline, + functions: only-multiline, ## Optional on functions + }, + ] ## Enforce consistent spacing before and after commas comma-spacing: [error, { before: false, after: true }] ## Enforce consistent comma style @@ -350,15 +353,15 @@ rules: ## Enforce the location of arrow function bodies # implicit-arrow-linebreak: error ## Enforce consistent indentation - # indent: [warn, 2, { SwitchCase: 1 }] + # indent: [error, 2, { SwitchCase: 1 }] ## Enforce the consistent use of either double or single quotes in JSX ## attributes - # jsx-quotes: [warn, prefer-double] + # jsx-quotes: [error, prefer-double] ## Enforce consistent spacing between keys and values in object literal ## properties - # key-spacing: [warn, { beforeColon: false, afterColon: true }] + # key-spacing: [error, { beforeColon: false, afterColon: true }] ## Enforce consistent spacing before and after keywords - # keyword-spacing: [warn, { before: true, after: true }] + # keyword-spacing: [error, { before: true, after: true }] ## Enforce position of line comments # line-comment-position: error ## Enforce consistent linebreak style @@ -370,8 +373,8 @@ rules: ## Enforce a maximum depth that blocks can be nested # max-depth: error ## Enforce a maximum line length - # max-len: [warn, { - # code: 120, + # max-len: [error, { + # code: 80, # ## Ignore imports # ignorePattern: '^(import\s.+\sfrom\s|.*require\()', # ignoreUrls: true, @@ -415,7 +418,7 @@ rules: ## Disallow mixed binary operators # no-mixed-operators: error ## Disallow mixed spaces and tabs for indentation - no-mixed-spaces-and-tabs: warn + # no-mixed-spaces-and-tabs: error ## Disallow use of chained assignment expressions # no-multi-assign: error ## Disallow multiple empty lines @@ -441,7 +444,7 @@ rules: ## Disallow ternary operators when simpler alternatives exist # no-unneeded-ternary: error ## Disallow whitespace before properties - # no-whitespace-before-property: warn + # no-whitespace-before-property: error ## Enforce the location of single-line statements # nonblock-statement-body-position: error ## Enforce consistent line breaks inside braces @@ -458,7 +461,7 @@ rules: ## Require or disallow assignment operator shorthand where possible # operator-assignment: error ## Enforce consistent linebreak style for operators - # operator-linebreak: [warn, before] + # operator-linebreak: [error, before] ## Require or disallow padding within blocks # padded-blocks: error ## Require or disallow padding lines between statements @@ -483,7 +486,7 @@ rules: ## Enforce consistent spacing before blocks space-before-blocks: [error, always] ## Enforce consistent spacing before function definition opening parenthesis - # space-before-function-paren: [warn, { + # space-before-function-paren: [error, { # anonymous: always, # named: never, # asyncArrow: always, @@ -696,7 +699,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: warn + # react/jsx-curly-newline: error ## Enforce or disallow spaces inside of curly braces in JSX attributes and ## expressions (fixable) react/jsx-curly-spacing: error @@ -709,13 +712,13 @@ rules: ## Enforce event handler naming conventions in JSX react/jsx-handler-names: error ## Validate JSX indentation (fixable) - # react/jsx-indent: [warn, 2, { + # react/jsx-indent: [error, 2, { # checkAttributes: true, # }] ## Validate props indentation in JSX (fixable) - # react/jsx-indent-props: [warn, 2] + # react/jsx-indent-props: [error, 2] ## Validate JSX has key prop when in array or iterator - # react/jsx-key: warn + react/jsx-key: error ## Validate JSX maximum depth react/jsx-max-depth: [error, { max: 10 }] ## Generous ## Limit maximum of props on a single line in JSX (fixable) @@ -762,3 +765,6 @@ rules: ## Prevents the use of unused imports. ## This could be done by enabling no-unused-vars, but we're doing this for now unused-imports/no-unused-imports: error + ## https://github.com/lydell/eslint-plugin-simple-import-sort/ + simple-import-sort/imports: error + simple-import-sort/exports: error diff --git a/tgui/.gitignore b/tgui/.gitignore index 7214051f09..eb4f718b1b 100644 --- a/tgui/.gitignore +++ b/tgui/.gitignore @@ -17,6 +17,7 @@ package-lock.json /public/*.map /public/tgui-bench.bundle.js /public/tgui-bench.bundle.css +/coverage ## Previously ignored locations that are kept to avoid confusing git ## while transitioning to a new project structure. diff --git a/tgui/.swcrc b/tgui/.swcrc new file mode 100644 index 0000000000..c0402a41f0 --- /dev/null +++ b/tgui/.swcrc @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/swcrc", + "jsc": { + "loose": true, + "parser": { + "syntax": "typescript", + "tsx": true + }, + "transform": { + "react": { + "runtime": "automatic" + } + } + } +} diff --git a/tgui/docs/component-reference.md b/tgui/docs/component-reference.md index 91462ed63f..98e03d1be6 100644 --- a/tgui/docs/component-reference.md +++ b/tgui/docs/component-reference.md @@ -740,9 +740,10 @@ Popper lets you position elements so that they don't go out of the bounds of the **Props:** -- `popperContent: ReactNode` - The content that will be put inside the popper. -- `options?: { ... }` - An object of options to pass to `createPopper`. See [https://popper.js.org/docs/v2/constructors/#options], but the one you want most is `placement`. Valid placements are "bottom", "top", "left", and "right". You can affix "-start" and "-end" to achieve something like top left or top right respectively. You can also use "auto" (with an optional "-start" or "-end"), where a best fit will be chosen. -- `additionalStyles: { ... }` - A map of CSS styles to add to the element that will contain the popper. +- `content: ReactNode` - The content that will be put inside the popper. +- `isOpen: boolean` - Whether or not the popper is open. +- `onClickOutside?: (e) => void` - A function that will be called when the user clicks outside of the popper. +- `placement?: string` - The placement of the popper. See [https://popper.js.org/docs/v2/constructors/#placement] ### `ProgressBar` diff --git a/tgui/jest.config.js b/tgui/jest.config.js index 8b78818004..d8b4ac3e41 100644 --- a/tgui/jest.config.js +++ b/tgui/jest.config.js @@ -8,7 +8,7 @@ module.exports = { testEnvironment: 'jsdom', testRunner: require.resolve('jest-circus/runner'), transform: { - '^.+\\.(js|cjs|ts|tsx)$': require.resolve('babel-jest'), + '^.+\\.(js|cjs|ts|tsx)$': require.resolve('@swc/jest'), }, moduleFileExtensions: ['js', 'cjs', 'ts', 'tsx', 'json'], resetMocks: true, diff --git a/tgui/package.json b/tgui/package.json index 5f1b0c51b3..4c9f50f979 100644 --- a/tgui/package.json +++ b/tgui/package.json @@ -9,41 +9,33 @@ "scripts": { "tgui:analyze": "webpack --analyze", "tgui:bench": "webpack --env TGUI_BENCH=1 && node packages/tgui-bench/index.js", - "tgui:build": "webpack", + "tgui:build": "BROWSERSLIST_IGNORE_OLD_DATA=true 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:sonar": "eslint packages -c .eslintrc-sonar.yml", "tgui:test": "jest --watch", "tgui:test-simple": "CI=true jest --color", "tgui:test-ci": "CI=true jest --color --collect-coverage", "tgui:tsc": "tsc" }, "dependencies": { - "@babel/core": "^7.23.3", - "@babel/eslint-parser": "^7.23.3", - "@babel/plugin-transform-class-properties": "^7.23.3", - "@babel/plugin-transform-jscript": "^7.23.3", - "@babel/preset-env": "^7.23.3", - "@babel/preset-react": "^7.23.3", - "@babel/preset-typescript": "^7.23.3", + "@swc/core": "^1.3.100", + "@swc/jest": "^0.2.29", "@types/jest": "^29.5.10", "@types/jsdom": "^21.1.6", "@types/node": "^14.x", "@types/webpack": "^5.28.5", "@types/webpack-env": "^1.18.4", - "@typescript-eslint/parser": "^5.62.0", - "babel-jest": "^29.7.0", - "babel-loader": "^8.3.0", - "babel-plugin-transform-remove-console": "^6.9.4", - "common": "workspace:*", + "@typescript-eslint/parser": "^6.14.0", "css-loader": "^6.8.1", "esbuild-loader": "^4.0.2", - "eslint": "^7.32.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-radar": "^0.2.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-react": "^7.33.2", - "eslint-plugin-unused-imports": "^1.1.5", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-sonarjs": "^0.23.0", + "eslint-plugin-unused-imports": "^3.0.0", "file-loader": "^6.2.0", "jest": "^29.7.0", "jest-circus": "^29.7.0", @@ -54,6 +46,7 @@ "sass": "^1.69.5", "sass-loader": "^13.3.2", "style-loader": "^3.3.3", + "swc-loader": "^0.2.3", "typescript": "^4.9.4", "url-loader": "^4.1.1", "webpack": "^5.89.0", diff --git a/tgui/packages/common/redux.test.ts b/tgui/packages/common/redux.test.ts index af4e5d4e73..2657d7b800 100644 --- a/tgui/packages/common/redux.test.ts +++ b/tgui/packages/common/redux.test.ts @@ -1,4 +1,4 @@ -import { Action, Reducer, applyMiddleware, combineReducers, createAction, createStore } from './redux'; +import { Action, applyMiddleware, combineReducers, createAction, createStore, Reducer } from './redux'; // Dummy Reducer const counterReducer: Reducer> = (state = 0, action) => { diff --git a/tgui/packages/tgui-bench/entrypoint.tsx b/tgui/packages/tgui-bench/entrypoint.tsx index a6eb7a91d6..b160d320b5 100644 --- a/tgui/packages/tgui-bench/entrypoint.tsx +++ b/tgui/packages/tgui-bench/entrypoint.tsx @@ -4,8 +4,10 @@ * @license MIT */ -import { setupGlobalEvents } from 'tgui/events'; import 'tgui/styles/main.scss'; + +import { setupGlobalEvents } from 'tgui/events'; + import Benchmark from './lib/benchmark'; const sendMessage = (obj: any) => { diff --git a/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx b/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx index c212ace895..03e4232733 100644 --- a/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx +++ b/tgui/packages/tgui-bench/tests/DisposalBin.test.tsx @@ -1,8 +1,7 @@ -import { configureStore } from 'tgui/store'; - -import { DisposalBin } from 'tgui/interfaces/DisposalBin'; import { backendUpdate, setGlobalStore } from 'tgui/backend'; +import { DisposalBin } from 'tgui/interfaces/DisposalBin'; import { createRenderer } from 'tgui/renderer'; +import { configureStore } from 'tgui/store'; const store = configureStore({ sideEffects: false }); diff --git a/tgui/packages/tgui-dev-server/dreamseeker.js b/tgui/packages/tgui-dev-server/dreamseeker.js index c81f51e35c..a5ace7f6b2 100644 --- a/tgui/packages/tgui-dev-server/dreamseeker.js +++ b/tgui/packages/tgui-dev-server/dreamseeker.js @@ -6,8 +6,9 @@ import { exec } from 'child_process'; import { promisify } from 'util'; -import { createLogger } from './logging'; -import { require } from './require'; + +import { createLogger } from './logging.js'; +import { require } from './require.js'; const axios = require('axios'); const logger = createLogger('dreamseeker'); diff --git a/tgui/packages/tgui-dev-server/index.js b/tgui/packages/tgui-dev-server/index.js index 460b15d99a..85489ebb04 100644 --- a/tgui/packages/tgui-dev-server/index.js +++ b/tgui/packages/tgui-dev-server/index.js @@ -4,8 +4,8 @@ * @license MIT */ -import { createCompiler } from './webpack'; -import { reloadByondCache } from './reloader'; +import { reloadByondCache } from './reloader.js'; +import { createCompiler } from './webpack.js'; const noHot = process.argv.includes('--no-hot'); const noTmp = process.argv.includes('--no-tmp'); diff --git a/tgui/packages/tgui-dev-server/link/client.cjs b/tgui/packages/tgui-dev-server/link/client.cjs index 1e21d42ce8..b0e6f7bc9d 100644 --- a/tgui/packages/tgui-dev-server/link/client.cjs +++ b/tgui/packages/tgui-dev-server/link/client.cjs @@ -31,11 +31,9 @@ const ensureConnection = () => { }; } } -}; -if (process.env.NODE_ENV !== 'production') { window.onunload = () => socket && socket.close(); -} +}; const subscribe = (fn) => subscribers.push(fn); @@ -136,38 +134,38 @@ const sendLogEntry = (level, ns, ...args) => { const setupHotReloading = () => { if ( - // prettier-ignore - process.env.NODE_ENV !== 'production' - && process.env.WEBPACK_HMR_ENABLED - && window.WebSocket + 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) => { - const { type } = msg; - sendLogEntry(0, null, 'received', type); - if (type === 'hotUpdate') { - const status = module.hot.status(); - if (status !== 'idle') { - sendLogEntry(0, null, 'hot reload status:', status); - return; - } - module.hot - .check({ - ignoreUnaccepted: true, - ignoreDeclined: true, - ignoreErrored: true, - }) - .then((modules) => { - sendLogEntry(0, null, 'outdated modules', modules); - }) - .catch((err) => { - sendLogEntry(0, null, 'reload error', err); - }); + return; + } + if (module.hot) { + ensureConnection(); + sendLogEntry(0, null, 'setting up hot reloading'); + subscribe((msg) => { + const { type } = msg; + sendLogEntry(0, null, 'received', type); + if (type === 'hotUpdate') { + const status = module.hot.status(); + if (status !== 'idle') { + sendLogEntry(0, null, 'hot reload status:', status); + return; } - }); - } + module.hot + .check({ + ignoreUnaccepted: true, + ignoreDeclined: true, + ignoreErrored: true, + }) + .then((modules) => { + sendLogEntry(0, null, 'outdated modules', modules); + }) + .catch((err) => { + sendLogEntry(0, null, 'reload error', err); + }); + } + }); } }; diff --git a/tgui/packages/tgui-dev-server/link/retrace.js b/tgui/packages/tgui-dev-server/link/retrace.js index 949835c700..cc7e242b75 100644 --- a/tgui/packages/tgui-dev-server/link/retrace.js +++ b/tgui/packages/tgui-dev-server/link/retrace.js @@ -6,9 +6,10 @@ import fs from 'fs'; import { basename } from 'path'; -import { createLogger } from '../logging'; -import { require } from '../require'; -import { resolveGlob } from '../util'; + +import { createLogger } from '../logging.js'; +import { require } from '../require.js'; +import { resolveGlob } from '../util.js'; const SourceMap = require('source-map'); const { parse: parseStackTrace } = require('stacktrace-parser'); diff --git a/tgui/packages/tgui-dev-server/link/server.js b/tgui/packages/tgui-dev-server/link/server.js index f0c0d153d3..2a1f551bf6 100644 --- a/tgui/packages/tgui-dev-server/link/server.js +++ b/tgui/packages/tgui-dev-server/link/server.js @@ -6,9 +6,10 @@ import http from 'http'; import { inspect } from 'util'; -import { createLogger, directLog } from '../logging'; -import { require } from '../require'; -import { loadSourceMaps, retrace } from './retrace'; + +import { createLogger, directLog } from '../logging.js'; +import { require } from '../require.js'; +import { loadSourceMaps, retrace } from './retrace.js'; const WebSocket = require('ws'); diff --git a/tgui/packages/tgui-dev-server/reloader.js b/tgui/packages/tgui-dev-server/reloader.js index aed9a7dcd7..6ef7e03f6b 100644 --- a/tgui/packages/tgui-dev-server/reloader.js +++ b/tgui/packages/tgui-dev-server/reloader.js @@ -7,10 +7,11 @@ import fs from 'fs'; import os from 'os'; import { basename } from 'path'; -import { DreamSeeker } from './dreamseeker'; -import { createLogger } from './logging'; -import { resolveGlob, resolvePath } from './util'; -import { regQuery } from './winreg'; + +import { DreamSeeker } from './dreamseeker.js'; +import { createLogger } from './logging.js'; +import { resolveGlob, resolvePath } from './util.js'; +import { regQuery } from './winreg.js'; const logger = createLogger('reloader'); diff --git a/tgui/packages/tgui-dev-server/util.js b/tgui/packages/tgui-dev-server/util.js index d60ebb212f..79190fe189 100644 --- a/tgui/packages/tgui-dev-server/util.js +++ b/tgui/packages/tgui-dev-server/util.js @@ -6,7 +6,8 @@ import fs from 'fs'; import path from 'path'; -import { require } from './require'; + +import { require } from './require.js'; const globPkg = require('glob'); diff --git a/tgui/packages/tgui-dev-server/webpack.js b/tgui/packages/tgui-dev-server/webpack.js index 1c16345a89..e4fbdeb9f1 100644 --- a/tgui/packages/tgui-dev-server/webpack.js +++ b/tgui/packages/tgui-dev-server/webpack.js @@ -7,10 +7,11 @@ import fs from 'fs'; import { createRequire } from 'module'; import { dirname } from 'path'; -import { loadSourceMaps, setupLink } from './link/server'; -import { createLogger } from './logging'; -import { reloadByondCache } from './reloader'; -import { resolveGlob } from './util'; + +import { loadSourceMaps, setupLink } from './link/server.js'; +import { createLogger } from './logging.js'; +import { reloadByondCache } from './reloader.js'; +import { resolveGlob } from './util.js'; const logger = createLogger('webpack'); diff --git a/tgui/packages/tgui-dev-server/winreg.js b/tgui/packages/tgui-dev-server/winreg.js index d7408b5c39..43a4170190 100644 --- a/tgui/packages/tgui-dev-server/winreg.js +++ b/tgui/packages/tgui-dev-server/winreg.js @@ -8,7 +8,8 @@ import { exec } from 'child_process'; import { promisify } from 'util'; -import { createLogger } from './logging'; + +import { createLogger } from './logging.js'; const logger = createLogger('winreg'); @@ -35,8 +36,8 @@ export const regQuery = async (path, key) => { logger.error('could not find the start of the key value'); return null; } - const value = stdout.substring(indexOfValue + 4, indexOfEol); - return value; + + return stdout.substring(indexOfValue + 4, indexOfEol); } catch (err) { logger.error(err); return null; diff --git a/tgui/packages/tgui-panel/Panel.tsx b/tgui/packages/tgui-panel/Panel.tsx index 0f47336cba..10088e0954 100644 --- a/tgui/packages/tgui-panel/Panel.tsx +++ b/tgui/packages/tgui-panel/Panel.tsx @@ -6,6 +6,7 @@ import { Button, Section, Stack } from 'tgui/components'; import { Pane } from 'tgui/layouts'; + import { NowPlayingWidget, useAudio } from './audio'; import { ChatPanel, ChatTabs } from './chat'; import { useGame } from './game'; diff --git a/tgui/packages/tgui-panel/audio/hooks.ts b/tgui/packages/tgui-panel/audio/hooks.ts index 1286754a37..2e9d830cb7 100644 --- a/tgui/packages/tgui-panel/audio/hooks.ts +++ b/tgui/packages/tgui-panel/audio/hooks.ts @@ -4,7 +4,8 @@ * @license MIT */ -import { useSelector, useDispatch } from 'tgui/backend'; +import { useDispatch, useSelector } from 'tgui/backend'; + import { selectAudio } from './selectors'; export const useAudio = () => { diff --git a/tgui/packages/tgui-panel/chat/actions.js b/tgui/packages/tgui-panel/chat/actions.js index 37fb48cc81..0f87a8b0e2 100644 --- a/tgui/packages/tgui-panel/chat/actions.js +++ b/tgui/packages/tgui-panel/chat/actions.js @@ -5,6 +5,7 @@ */ import { createAction } from 'common/redux'; + import { createPage } from './model'; export const loadChat = createAction('chat/load'); diff --git a/tgui/packages/tgui-panel/chat/middleware.js b/tgui/packages/tgui-panel/chat/middleware.js index 7c90df4410..f7d68ba011 100644 --- a/tgui/packages/tgui-panel/chat/middleware.js +++ b/tgui/packages/tgui-panel/chat/middleware.js @@ -4,11 +4,12 @@ * @license MIT */ -import DOMPurify from 'dompurify'; import { storage } from 'common/storage'; -import { loadSettings, updateSettings, addHighlightSetting, removeHighlightSetting, updateHighlightSetting } from '../settings/actions'; +import DOMPurify from 'dompurify'; + +import { addHighlightSetting, loadSettings, removeHighlightSetting, updateHighlightSetting, updateSettings } from '../settings/actions'; import { selectSettings } from '../settings/selectors'; -import { addChatPage, changeChatPage, changeScrollTracking, loadChat, rebuildChat, moveChatPageLeft, moveChatPageRight, removeChatPage, saveChatToDisk, purgeChatMessageArchive, toggleAcceptedType, updateMessageCount } from './actions'; +import { addChatPage, changeChatPage, changeScrollTracking, loadChat, moveChatPageLeft, moveChatPageRight, purgeChatMessageArchive, rebuildChat, removeChatPage, saveChatToDisk, toggleAcceptedType, updateMessageCount } from './actions'; import { MESSAGE_SAVE_INTERVAL } from './constants'; import { createMessage, serializeMessage } from './model'; import { chatRenderer } from './renderer'; diff --git a/tgui/packages/tgui-panel/chat/model.js b/tgui/packages/tgui-panel/chat/model.js index e544ebfddd..5f8a96227d 100644 --- a/tgui/packages/tgui-panel/chat/model.js +++ b/tgui/packages/tgui-panel/chat/model.js @@ -5,7 +5,8 @@ */ import { createUuid } from 'common/uuid'; -import { MESSAGE_TYPES, MESSAGE_TYPE_INTERNAL } from './constants'; + +import { MESSAGE_TYPE_INTERNAL, MESSAGE_TYPES } from './constants'; export const canPageAcceptType = (page, type) => type.startsWith(MESSAGE_TYPE_INTERNAL) || page.acceptedTypes[type]; diff --git a/tgui/packages/tgui-panel/chat/reducer.js b/tgui/packages/tgui-panel/chat/reducer.js index 488bd99320..034ccefec4 100644 --- a/tgui/packages/tgui-panel/chat/reducer.js +++ b/tgui/packages/tgui-panel/chat/reducer.js @@ -4,7 +4,7 @@ * @license MIT */ -import { addChatPage, changeChatPage, loadChat, removeChatPage, moveChatPageLeft, moveChatPageRight, toggleAcceptedType, updateChatPage, updateMessageCount, changeScrollTracking } from './actions'; +import { addChatPage, changeChatPage, changeScrollTracking, loadChat, moveChatPageLeft, moveChatPageRight, removeChatPage, toggleAcceptedType, updateChatPage, updateMessageCount } from './actions'; import { canPageAcceptType, createMainPage } from './model'; const mainPage = createMainPage(); diff --git a/tgui/packages/tgui-panel/game/hooks.ts b/tgui/packages/tgui-panel/game/hooks.ts index c3e7c06284..40a74ff44a 100644 --- a/tgui/packages/tgui-panel/game/hooks.ts +++ b/tgui/packages/tgui-panel/game/hooks.ts @@ -5,6 +5,7 @@ */ import { useSelector } from 'tgui/backend'; + import { selectGame } from './selectors'; export const useGame = () => { diff --git a/tgui/packages/tgui-panel/game/middleware.js b/tgui/packages/tgui-panel/game/middleware.js index 53dd45bb46..1cf80a7ac6 100644 --- a/tgui/packages/tgui-panel/game/middleware.js +++ b/tgui/packages/tgui-panel/game/middleware.js @@ -6,8 +6,8 @@ import { pingSoft, pingSuccess } from '../ping/actions'; import { connectionLost, connectionRestored, roundRestarted } from './actions'; -import { selectGame } from './selectors'; import { CONNECTION_LOST_AFTER } from './constants'; +import { selectGame } from './selectors'; const withTimestamp = (action) => ({ ...action, diff --git a/tgui/packages/tgui-panel/index.tsx b/tgui/packages/tgui-panel/index.tsx index e2f3794fff..a458c6f350 100644 --- a/tgui/packages/tgui-panel/index.tsx +++ b/tgui/packages/tgui-panel/index.tsx @@ -11,11 +11,13 @@ import './styles/themes/vchatdark.scss'; import { perf } from 'common/perf'; import { combineReducers } from 'common/redux'; -import { setupHotReloading } from 'tgui-dev-server/link/client.cjs'; +import { setGlobalStore } from 'tgui/backend'; import { setupGlobalEvents } from 'tgui/events'; import { captureExternalLinks } from 'tgui/links'; import { createRenderer } from 'tgui/renderer'; import { configureStore } from 'tgui/store'; +import { setupHotReloading } from 'tgui-dev-server/link/client.cjs'; + import { audioMiddleware, audioReducer } from './audio'; import { chatMiddleware, chatReducer } from './chat'; import { gameMiddleware, gameReducer } from './game'; @@ -23,7 +25,6 @@ import { setupPanelFocusHacks } from './panelFocus'; import { pingMiddleware, pingReducer } from './ping'; import { settingsMiddleware, settingsReducer } from './settings'; import { telemetryMiddleware } from './telemetry'; -import { setGlobalStore } from 'tgui/backend'; perf.mark('inception', window.performance?.timing?.navigationStart); perf.mark('init'); diff --git a/tgui/packages/tgui-panel/ping/reducer.ts b/tgui/packages/tgui-panel/ping/reducer.ts index fcab775548..5d38e939d2 100644 --- a/tgui/packages/tgui-panel/ping/reducer.ts +++ b/tgui/packages/tgui-panel/ping/reducer.ts @@ -5,6 +5,7 @@ */ import { clamp01, scale } from 'common/math'; + import { pingFail, pingSuccess } from './actions'; import { PING_MAX_FAILS, PING_ROUNDTRIP_BEST, PING_ROUNDTRIP_WORST } from './constants'; diff --git a/tgui/packages/tgui-panel/reconnect.tsx b/tgui/packages/tgui-panel/reconnect.tsx index 6793125be2..4674aa8e22 100644 --- a/tgui/packages/tgui-panel/reconnect.tsx +++ b/tgui/packages/tgui-panel/reconnect.tsx @@ -1,5 +1,6 @@ -import { Button } from 'tgui/components'; import { useDispatch } from 'tgui/backend'; +import { Button } from 'tgui/components'; + import { dismissWarning } from './game/actions'; let url: string | null = null; diff --git a/tgui/packages/tgui-panel/settings/actions.ts b/tgui/packages/tgui-panel/settings/actions.ts index 1550bef80b..f4b31565c2 100644 --- a/tgui/packages/tgui-panel/settings/actions.ts +++ b/tgui/packages/tgui-panel/settings/actions.ts @@ -5,6 +5,7 @@ */ import { createAction } from 'common/redux'; + import { createHighlightSetting } from './model'; export const updateSettings = createAction('settings/update'); diff --git a/tgui/packages/tgui-panel/settings/hooks.ts b/tgui/packages/tgui-panel/settings/hooks.ts index 5ea91c8606..b37b49a22c 100644 --- a/tgui/packages/tgui-panel/settings/hooks.ts +++ b/tgui/packages/tgui-panel/settings/hooks.ts @@ -5,7 +5,8 @@ */ import { useDispatch, useSelector } from 'tgui/backend'; -import { updateSettings, toggleSettings } from './actions'; + +import { toggleSettings, updateSettings } from './actions'; import { selectSettings } from './selectors'; export const useSettings = () => { diff --git a/tgui/packages/tgui-panel/settings/middleware.js b/tgui/packages/tgui-panel/settings/middleware.js index cef082213d..8518f15d2a 100644 --- a/tgui/packages/tgui-panel/settings/middleware.js +++ b/tgui/packages/tgui-panel/settings/middleware.js @@ -5,10 +5,11 @@ */ import { storage } from 'common/storage'; + import { setClientTheme } from '../themes'; -import { loadSettings, updateSettings, addHighlightSetting, removeHighlightSetting, updateHighlightSetting } from './actions'; -import { selectSettings } from './selectors'; +import { addHighlightSetting, loadSettings, removeHighlightSetting, updateHighlightSetting, updateSettings } from './actions'; import { FONTS_DISABLED } from './constants'; +import { selectSettings } from './selectors'; let overrideRule = null; let overrideFontFamily = null; diff --git a/tgui/packages/tgui-panel/settings/reducer.js b/tgui/packages/tgui-panel/settings/reducer.js index af0ca15190..036c15a5c7 100644 --- a/tgui/packages/tgui-panel/settings/reducer.js +++ b/tgui/packages/tgui-panel/settings/reducer.js @@ -4,9 +4,9 @@ * @license MIT */ -import { changeSettingsTab, loadSettings, openChatSettings, toggleSettings, updateSettings, addHighlightSetting, removeHighlightSetting, updateHighlightSetting } from './actions'; +import { addHighlightSetting, changeSettingsTab, loadSettings, openChatSettings, removeHighlightSetting, toggleSettings, updateHighlightSetting, updateSettings } from './actions'; +import { FONTS, MAX_HIGHLIGHT_SETTINGS, SETTINGS_TABS } from './constants'; import { createDefaultHighlightSetting } from './model'; -import { SETTINGS_TABS, FONTS, MAX_HIGHLIGHT_SETTINGS } from './constants'; const defaultHighlightSetting = createDefaultHighlightSetting(); diff --git a/tgui/packages/tgui/assets.ts b/tgui/packages/tgui/assets.ts index e519d0c2f7..f62bf652de 100644 --- a/tgui/packages/tgui/assets.ts +++ b/tgui/packages/tgui/assets.ts @@ -4,10 +4,10 @@ * @license MIT */ -import { Action, AnyAction, Middleware } from '../common/redux'; - import { Dispatch } from 'common/redux'; +import { Action, AnyAction, Middleware } from '../common/redux'; + const EXCLUDED_PATTERNS = [/v4shim/i]; const loadedMappings: Record = {}; diff --git a/tgui/packages/tgui/backend.ts b/tgui/packages/tgui/backend.ts index 1ae81246cd..0d872aefd7 100644 --- a/tgui/packages/tgui/backend.ts +++ b/tgui/packages/tgui/backend.ts @@ -13,6 +13,7 @@ import { perf } from 'common/perf'; import { createAction } from 'common/redux'; + import { setupDrag } from './drag'; import { globalEvents } from './events'; import { focusMap } from './focus'; diff --git a/tgui/packages/tgui/components/BodyZoneSelector.tsx b/tgui/packages/tgui/components/BodyZoneSelector.tsx index 0fe3bcbe5a..ca9f76016b 100644 --- a/tgui/packages/tgui/components/BodyZoneSelector.tsx +++ b/tgui/packages/tgui/components/BodyZoneSelector.tsx @@ -1,4 +1,5 @@ import { Component, createRef } from 'react'; + import { resolveAsset } from '../assets'; import { Box } from './Box'; diff --git a/tgui/packages/tgui/components/Box.tsx b/tgui/packages/tgui/components/Box.tsx index 39913f65e0..8b0468aaae 100644 --- a/tgui/packages/tgui/components/Box.tsx +++ b/tgui/packages/tgui/components/Box.tsx @@ -6,6 +6,7 @@ import { BooleanLike, classes } from 'common/react'; import { createElement, ReactNode } from 'react'; + import { CSS_COLORS } from '../constants'; export type BoxProps = { diff --git a/tgui/packages/tgui/components/Chart.tsx b/tgui/packages/tgui/components/Chart.tsx index 795475d7c8..0b6ed9b298 100644 --- a/tgui/packages/tgui/components/Chart.tsx +++ b/tgui/packages/tgui/components/Chart.tsx @@ -6,6 +6,7 @@ import { map, zipWith } from 'common/collections'; import { Component, createRef, RefObject } from 'react'; + import { Box, BoxProps } from './Box'; type Props = { diff --git a/tgui/packages/tgui/components/Dropdown.tsx b/tgui/packages/tgui/components/Dropdown.tsx index 444c96bab9..407a08e750 100644 --- a/tgui/packages/tgui/components/Dropdown.tsx +++ b/tgui/packages/tgui/components/Dropdown.tsx @@ -1,337 +1,177 @@ -import { createPopper, VirtualElement } from '@popperjs/core'; import { classes } from 'common/react'; -import { Component, ReactNode } from 'react'; -import { findDOMNode, render } from 'react-dom'; -import { Box, BoxProps } from './Box'; +import { ReactNode, useCallback, useEffect, useRef, useState } from 'react'; + +import { BoxProps, unit } from './Box'; import { Button } from './Button'; import { Icon } from './Icon'; -import { Stack } from './Stack'; +import { Popper } from './Popper'; -export interface DropdownEntry { - displayText: string | number | ReactNode; - value: string | number | Enumerator; +type DropdownEntry = { + displayText: ReactNode; + value: string | number; +}; + +type DropdownOption = string | DropdownEntry; + +type Props = { + /** An array of strings which will be displayed in the + dropdown when open. See Dropdown.tsx for more advanced usage with DropdownEntry */ + options: DropdownOption[]; + /** Called when a value is picked from the list, `value` is the value that was picked */ + onSelected: (value: any) => void; +} & Partial<{ + /** Whether to display previous / next buttons */ + buttons: boolean; + /** Whether to clip the selected text */ + clipSelectedText: boolean; + /** Color of dropdown button */ + color: string; + /** Disables the dropdown */ + disabled: boolean; + /** Text to always display in place of the selected text */ + displayText: ReactNode; + /** Icon to display in dropdown button */ + icon: string; + /** Angle of the icon */ + iconRotation: number; + /** Whether or not the icon should spin */ + iconSpin: boolean; + /** Width of the dropdown menu. Default: 15rem */ + menuWidth: string; + /** Whether or not the arrow on the right hand side of the dropdown button is visible */ + noChevron: boolean; + /** Called when dropdown button is clicked */ + onClick: (event) => void; + /** Dropdown renders over instead of below */ + over: boolean; + /** Currently selected entry */ + selected: string | number; +}> & + BoxProps; + +function getOptionValue(option: DropdownOption) { + return typeof option === 'string' ? option : option.value; } -type DropdownUniqueProps = { options: string[] | DropdownEntry[] } & Partial<{ - buttons: boolean; - clipSelectedText: boolean; - color: string; - disabled: boolean; - displayText: string | number | ReactNode; - dropdownStyle: any; - icon: string; - iconRotation: number; - iconSpin: boolean; - menuWidth: string; - nochevron: boolean; - onClick: (event) => void; - onSelected: (selected: any) => void; - over: boolean; - // you freaks really are just doing anything with this shit - selected: any; - width: string; -}>; +export function Dropdown(props: Props) { + const { + buttons, + className, + clipSelectedText = true, + color = 'default', + disabled, + displayText, + icon, + iconRotation, + iconSpin, + menuWidth = '15rem', + noChevron, + onClick, + onSelected, + options = [], + over, + selected, + width, + } = props; -export type DropdownProps = BoxProps & DropdownUniqueProps; + const [open, setOpen] = useState(false); + const adjustedOpen = over ? !open : open; + const innerRef = useRef(null); -const DEFAULT_OPTIONS = { - placement: 'left-start', - modifiers: [ - { - name: 'eventListeners', - enabled: false, - }, - ], -}; -const NULL_RECT: DOMRect = { - width: 0, - height: 0, - top: 0, - right: 0, - bottom: 0, - left: 0, - x: 0, - y: 0, - toJSON: () => null, -} as const; - -type DropdownState = { - selected?: string; - open: boolean; -}; - -const DROPDOWN_DEFAULT_CLASSNAMES = 'Layout Dropdown__menu'; -const DROPDOWN_SCROLL_CLASSNAMES = 'Layout Dropdown__menu-scroll'; - -export class Dropdown extends Component { - static renderedMenu: HTMLDivElement | undefined; - static singletonPopper: ReturnType | undefined; - static currentOpenMenu: Element | undefined; - static virtualElement: VirtualElement = { - getBoundingClientRect: () => - Dropdown.currentOpenMenu?.getBoundingClientRect() ?? NULL_RECT, - }; - menuContents: any; - state: DropdownState = { - open: false, - selected: this.props.selected, - }; - - handleClick = () => { - if (this.state.open) { - this.setOpen(false); - } - }; - - getDOMNode() { - // eslint-disable-next-line react/no-find-dom-node - return findDOMNode(this) as Element; - } - - componentDidMount() { - const domNode = this.getDOMNode(); - - if (!domNode) { - return; - } - } - - openMenu() { - let renderedMenu = Dropdown.renderedMenu; - if (renderedMenu === undefined) { - renderedMenu = document.createElement('div'); - renderedMenu.className = DROPDOWN_DEFAULT_CLASSNAMES; - document.body.appendChild(renderedMenu); - Dropdown.renderedMenu = renderedMenu; - } - - const domNode = this.getDOMNode()!; - Dropdown.currentOpenMenu = domNode; - - renderedMenu.scrollTop = 0; - renderedMenu.style.width = this.props.menuWidth || '10rem'; - renderedMenu.style.opacity = '1'; - renderedMenu.style.pointerEvents = 'auto'; - - // ie hack - // ie has this bizarre behavior where focus just silently fails if the - // element being targeted "isn't ready" - // 400 is probably way too high, but the lack of hotloading is testing my - // patience on tuning it - // I'm beyond giving a shit at this point it fucking works whatever - setTimeout(() => { - Dropdown.renderedMenu?.focus(); - }, 400); - this.renderMenuContent(); - } - - closeMenu() { - if (Dropdown.currentOpenMenu !== this.getDOMNode()) { - return; - } - - Dropdown.currentOpenMenu = undefined; - Dropdown.renderedMenu!.style.opacity = '0'; - Dropdown.renderedMenu!.style.pointerEvents = 'none'; - } - - componentWillUnmount() { - this.closeMenu(); - this.setOpen(false); - } - - renderMenuContent() { - const renderedMenu = Dropdown.renderedMenu; - if (!renderedMenu) { - return; - } - if (renderedMenu.offsetHeight > 200) { - renderedMenu.className = DROPDOWN_SCROLL_CLASSNAMES; - } else { - renderedMenu.className = DROPDOWN_DEFAULT_CLASSNAMES; - } - - const { options = [] } = this.props; - const ops = options.map((option) => { - let value, displayText; - - if (typeof option === 'string') { - displayText = option; - value = option; - } else if (option !== null) { - displayText = option.displayText; - value = option.value; + /** Update the selected value when clicking the left/right buttons */ + const updateSelected = useCallback( + (direction: 'previous' | 'next') => { + if (options.length < 1 || disabled) { + return; } + const startIndex = 0; + const endIndex = options.length - 1; - return ( -
{ - this.setSelected(value); - }}> - {displayText} -
+ let selectedIndex = options.findIndex( + (option) => getOptionValue(option) === selected ); - }); - const to_render = ops.length ? ops : 'No Options Found'; - - render(
{to_render}
, renderedMenu, () => { - let singletonPopper = Dropdown.singletonPopper; - if (singletonPopper === undefined) { - singletonPopper = createPopper(Dropdown.virtualElement, renderedMenu!, { - ...DEFAULT_OPTIONS, - placement: 'bottom-start', - }); - - Dropdown.singletonPopper = singletonPopper; - } else { - singletonPopper.setOptions({ - ...DEFAULT_OPTIONS, - placement: 'bottom-start', - }); - - singletonPopper.update(); + if (selectedIndex < 0) { + selectedIndex = direction === 'next' ? endIndex : startIndex; } - }); - } - setOpen(open: boolean) { - this.setState((state) => ({ - ...state, - open, - })); - if (open) { - setTimeout(() => { - this.openMenu(); - window.addEventListener('click', this.handleClick); - }); - } else { - this.closeMenu(); - window.removeEventListener('click', this.handleClick); - } - } + let newIndex = selectedIndex; + if (direction === 'next') { + newIndex = selectedIndex === endIndex ? startIndex : selectedIndex++; + } else { + newIndex = selectedIndex === startIndex ? endIndex : selectedIndex--; + } - setSelected(selected: string) { - this.setState((state) => ({ - ...state, - selected, - })); - this.setOpen(false); - if (this.props.onSelected) { - this.props.onSelected(selected); - } - } + onSelected?.(getOptionValue(options[newIndex])); + }, + [disabled, onSelected, options, selected] + ); - getOptionValue(option): string { - return typeof option === 'string' ? option : option.value; - } + /** Allows the menu to be scrollable on open */ + useEffect(() => { + if (!open) return; - getSelectedIndex(): number { - const selected = this.state.selected || this.props.selected; - const { options = [] } = this.props; + innerRef.current?.focus(); + }, [open]); - return options.findIndex((option) => { - return this.getOptionValue(option) === selected; - }); - } + return ( + setOpen(false)} + placement={over ? 'top-start' : 'bottom-start'} + content={ +
+ {options.length === 0 && ( +
No options
+ )} - toPrevious(): void { - if (this.props.options.length < 1) { - return; - } + {options.map((option, index) => { + const value = getOptionValue(option); - let selectedIndex = this.getSelectedIndex(); - const startIndex = 0; - const endIndex = this.props.options.length - 1; - - const hasSelected = selectedIndex >= 0; - if (!hasSelected) { - selectedIndex = startIndex; - } - - const previousIndex = - selectedIndex === startIndex ? endIndex : selectedIndex - 1; - - this.setSelected(this.getOptionValue(this.props.options[previousIndex])); - } - - toNext(): void { - if (this.props.options.length < 1) { - return; - } - - let selectedIndex = this.getSelectedIndex(); - const startIndex = 0; - const endIndex = this.props.options.length - 1; - - const hasSelected = selectedIndex >= 0; - if (!hasSelected) { - selectedIndex = endIndex; - } - - const nextIndex = - selectedIndex === endIndex ? startIndex : selectedIndex + 1; - - this.setSelected(this.getOptionValue(this.props.options[nextIndex])); - } - - render() { - const { props } = this; - const { - icon, - iconRotation, - iconSpin, - clipSelectedText = true, - color = 'default', - dropdownStyle, - over, - nochevron, - width, - onClick, - onSelected, - selected, - disabled, - displayText, - buttons, - ...boxProps - } = props; - const { className, ...rest } = boxProps; - - const adjustedOpen = over ? !this.state.open : this.state.open; - - return ( - - - { + setOpen(false); + onSelected?.(value); + }}> + {typeof option === 'string' ? option : option.displayText} +
+ ); + })} + + }> +
+
+
{ - if (disabled && !this.state.open) { + if (disabled && !open) { return; } - this.setOpen(!this.state.open); - if (onClick) { - onClick(event); - } - }} - {...rest}> + setOpen(!open); + onClick?.(event); + }}> {icon && ( )} { style={{ overflow: clipSelectedText ? 'hidden' : 'visible', }}> - {displayText || this.state.selected} + {displayText || selected} - {nochevron || ( + {!noChevron && ( )} - - - {buttons && ( - <> - +
+ {buttons && ( + <>
+
+
+ ); } diff --git a/tgui/packages/tgui/components/Flex.tsx b/tgui/packages/tgui/components/Flex.tsx index da063f0296..50dba27795 100644 --- a/tgui/packages/tgui/components/Flex.tsx +++ b/tgui/packages/tgui/components/Flex.tsx @@ -5,6 +5,7 @@ */ import { classes } from 'common/react'; + import { BoxProps, computeBoxClassName, computeBoxProps, unit } from './Box'; export type FlexProps = Partial<{ diff --git a/tgui/packages/tgui/components/Icon.tsx b/tgui/packages/tgui/components/Icon.tsx index 02f07bea09..9a54426828 100644 --- a/tgui/packages/tgui/components/Icon.tsx +++ b/tgui/packages/tgui/components/Icon.tsx @@ -8,6 +8,7 @@ import { classes } from 'common/react'; import { ReactNode } from 'react'; + import { BoxProps, computeBoxClassName, computeBoxProps } from './Box'; const FA_OUTLINE_REGEX = /-o$/; diff --git a/tgui/packages/tgui/components/KeyListener.tsx b/tgui/packages/tgui/components/KeyListener.tsx index d401642a3c..566026f0cb 100644 --- a/tgui/packages/tgui/components/KeyListener.tsx +++ b/tgui/packages/tgui/components/KeyListener.tsx @@ -1,4 +1,5 @@ import { Component } from 'react'; + import { KeyEvent } from '../events'; import { listenForKeyEvents } from '../hotkeys'; diff --git a/tgui/packages/tgui/components/MenuBar.tsx b/tgui/packages/tgui/components/MenuBar.tsx index 6547973a70..40a2027f26 100644 --- a/tgui/packages/tgui/components/MenuBar.tsx +++ b/tgui/packages/tgui/components/MenuBar.tsx @@ -6,8 +6,9 @@ import { classes } from 'common/react'; import { Component, createRef, ReactNode, RefObject } from 'react'; -import { Box } from './Box'; + import { logger } from '../logging'; +import { Box } from './Box'; import { Icon } from './Icon'; type MenuProps = { diff --git a/tgui/packages/tgui/components/Popper.tsx b/tgui/packages/tgui/components/Popper.tsx index 4875aaa4e6..b3907e59e4 100644 --- a/tgui/packages/tgui/components/Popper.tsx +++ b/tgui/packages/tgui/components/Popper.tsx @@ -1,82 +1,88 @@ -import { createPopper } from '@popperjs/core'; -import { ArgumentsOf } from 'common/types'; -import { Component, CSSProperties, JSXElementConstructor, PropsWithChildren, ReactElement, RefObject } from 'react'; -import { findDOMNode, render } from 'react-dom'; +import { Placement } from '@popperjs/core'; +import { PropsWithChildren, ReactNode, useEffect, useRef, useState } from 'react'; +import { usePopper } from 'react-popper'; -type PopperProps = { - popperContent: ReactElement>; - options?: ArgumentsOf[2]; - additionalStyles?: CSSProperties; -} & PropsWithChildren; +type RequiredProps = { + /** The content to display in the popper */ + content: ReactNode; + /** Whether the popper is open */ + isOpen: boolean; +}; -export class Popper extends Component { - static id: number = 0; - popperRef: RefObject; +type OptionalProps = Partial<{ + /** Called when the user clicks outside the popper */ + onClickOutside: () => void; + /** Where to place the popper relative to the reference element */ + placement: Placement; +}>; - renderedContent: HTMLDivElement; - popperInstance: ReturnType; +type Props = RequiredProps & OptionalProps; - constructor(props) { - super(props); +/** + * ## Popper + * Popper lets you position elements so that they don't go out of the bounds of the window. + * @url https://popper.js.org/react-popper/ for more information. + */ +export function Popper(props: PropsWithChildren) { + const { children, content, isOpen, onClickOutside, placement } = props; - Popper.id += 1; + const [referenceElement, setReferenceElement] = + useState(null); + const [popperElement, setPopperElement] = useState( + null + ); + + // One would imagine we could just use useref here, but it's against react-popper documentation and causes a positioning bug + // We still need them to call focus and clickoutside events :( + const popperRef = useRef(null); + const parentRef = useRef(null); + + const { styles, attributes } = usePopper(referenceElement, popperElement, { + placement, + }); + + /** Close the popper when the user clicks outside */ + function handleClickOutside(event: MouseEvent) { + if ( + !popperRef.current?.contains(event.target as Node) && + !parentRef.current?.contains(event.target as Node) + ) { + onClickOutside?.(); + } } - componentDidMount() { - const { additionalStyles, options } = this.props; - - this.renderedContent = document.createElement('div'); - - if (additionalStyles) { - for (const [attribute, value] of Object.entries(additionalStyles)) { - this.renderedContent.style[attribute] = value; - } + useEffect(() => { + if (isOpen) { + document.addEventListener('mousedown', handleClickOutside); + } else { + document.removeEventListener('mousedown', handleClickOutside); } - this.renderPopperContent(() => { - document.body.appendChild(this.renderedContent); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [isOpen]); - // HACK: We don't want to create a wrapper, as it could break the layout - // of consumers, so we use findDOMNode. - // This is usually bad as refs are usually better, but refs did - // not work in this case, as they weren't propagating correctly. - // A previous attempt was made as a render prop that passed an ID, - // but this made consuming use too unwieldly. - // Because this component is written in TypeScript, we will know - // immediately if this internal variable is removed. - // - // eslint-disable-next-line react/no-find-dom-node - const domNode = findDOMNode(this) as Element; - if (!domNode) { - return; - } - - this.popperInstance = createPopper( - domNode, - this.renderedContent, - options - ); - }); - } - - componentDidUpdate() { - this.renderPopperContent(() => this.popperInstance?.update()); - } - - componentWillUnmount() { - this.popperInstance?.destroy(); - render(<> , this.renderedContent, () => { - this.renderedContent.remove(); - }); - } - - 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); - } - - render() { - return this.props.children; - } + return ( + <> +
{ + setReferenceElement(node); + parentRef.current = node; + }}> + {children} +
+ {isOpen && ( +
{ + setPopperElement(node); + popperRef.current = node; + }} + style={{ ...styles.popper, zIndex: 5 }} + {...attributes.popper}> + {content} +
+ )} + + ); } diff --git a/tgui/packages/tgui/components/ProgressBar.tsx b/tgui/packages/tgui/components/ProgressBar.tsx index 23eef869df..9cb442479e 100644 --- a/tgui/packages/tgui/components/ProgressBar.tsx +++ b/tgui/packages/tgui/components/ProgressBar.tsx @@ -4,12 +4,13 @@ * @license MIT */ -import { clamp01, scale, keyOfMatchingRange, toFixed } from 'common/math'; +import { clamp01, keyOfMatchingRange, scale, toFixed } from 'common/math'; import { classes } from 'common/react'; -import { BoxProps, computeBoxClassName, computeBoxProps } from './Box'; -import { CSS_COLORS } from '../constants'; import { PropsWithChildren } from 'react'; +import { CSS_COLORS } from '../constants'; +import { BoxProps, computeBoxClassName, computeBoxProps } from './Box'; + type Props = { value: number; } & Partial<{ diff --git a/tgui/packages/tgui/components/Section.tsx b/tgui/packages/tgui/components/Section.tsx index 878d30e15b..17c00f2dcf 100644 --- a/tgui/packages/tgui/components/Section.tsx +++ b/tgui/packages/tgui/components/Section.tsx @@ -5,7 +5,8 @@ */ import { canRender, classes } from 'common/react'; -import { ReactNode, RefObject, createRef, useEffect } from 'react'; +import { createRef, ReactNode, RefObject, useEffect } from 'react'; + import { addScrollableNode, removeScrollableNode } from '../events'; import { BoxProps, computeBoxClassName, computeBoxProps } from './Box'; diff --git a/tgui/packages/tgui/components/Stack.tsx b/tgui/packages/tgui/components/Stack.tsx index b72222cdfa..e12c2ed76a 100644 --- a/tgui/packages/tgui/components/Stack.tsx +++ b/tgui/packages/tgui/components/Stack.tsx @@ -6,6 +6,7 @@ import { classes } from 'common/react'; import { RefObject } from 'react'; + import { computeFlexClassName, computeFlexItemClassName, computeFlexItemProps, computeFlexProps, FlexItemProps, FlexProps } from './Flex'; type Props = Partial<{ diff --git a/tgui/packages/tgui/components/StyleableSection.tsx b/tgui/packages/tgui/components/StyleableSection.tsx index 8a1ea48edb..53b193707f 100644 --- a/tgui/packages/tgui/components/StyleableSection.tsx +++ b/tgui/packages/tgui/components/StyleableSection.tsx @@ -1,4 +1,5 @@ import { PropsWithChildren, ReactNode } from 'react'; + import { Box } from './Box'; type Props = Partial<{ diff --git a/tgui/packages/tgui/components/Tabs.tsx b/tgui/packages/tgui/components/Tabs.tsx index 9080a9904e..0e0bbf9852 100644 --- a/tgui/packages/tgui/components/Tabs.tsx +++ b/tgui/packages/tgui/components/Tabs.tsx @@ -6,6 +6,7 @@ import { canRender, classes } from 'common/react'; import { PropsWithChildren, ReactNode } from 'react'; + import { BoxProps, computeBoxClassName, computeBoxProps } from './Box'; import { Icon } from './Icon'; diff --git a/tgui/packages/tgui/components/Tooltip.tsx b/tgui/packages/tgui/components/Tooltip.tsx index 1075339425..ee7b40e0b8 100644 --- a/tgui/packages/tgui/components/Tooltip.tsx +++ b/tgui/packages/tgui/components/Tooltip.tsx @@ -1,3 +1,5 @@ +/* eslint-disable react/no-deprecated */ +// TODO: Rewrite as an FC, remove this lint disable import { createPopper, Placement, VirtualElement } from '@popperjs/core'; import { Component, ReactNode } from 'react'; import { findDOMNode, render } from 'react-dom'; diff --git a/tgui/packages/tgui/components/index.ts b/tgui/packages/tgui/components/index.ts index fa613161ea..41e83ceb17 100644 --- a/tgui/packages/tgui/components/index.ts +++ b/tgui/packages/tgui/components/index.ts @@ -14,12 +14,13 @@ export { ByondUi } from './ByondUi'; export { Chart } from './Chart'; export { Collapsible } from './Collapsible'; export { ColorBox } from './ColorBox'; +export { Dialog } from './Dialog'; export { Dimmer } from './Dimmer'; export { Divider } from './Divider'; export { DraggableControl } from './DraggableControl'; export { Dropdown } from './Dropdown'; -export { Flex } from './Flex'; export { FitText } from './FitText'; +export { Flex } from './Flex'; export { Grid } from './Grid'; export { Icon } from './Icon'; export { InfinitePlane } from './InfinitePlane'; @@ -32,18 +33,17 @@ export { MenuBar } from './MenuBar'; export { Modal } from './Modal'; export { NoticeBox } from './NoticeBox'; export { NumberInput } from './NumberInput'; -export { ProgressBar } from './ProgressBar'; export { Popper } from './Popper'; +export { ProgressBar } from './ProgressBar'; export { RestrictedInput } from './RestrictedInput'; export { RoundGauge } from './RoundGauge'; export { Section } from './Section'; export { Slider } from './Slider'; -export { StyleableSection } from './StyleableSection'; export { Stack } from './Stack'; +export { StyleableSection } from './StyleableSection'; export { Table } from './Table'; export { Tabs } from './Tabs'; export { TextArea } from './TextArea'; export { TimeDisplay } from './TimeDisplay'; -export { TrackOutsideClicks } from './TrackOutsideClicks'; export { Tooltip } from './Tooltip'; -export { Dialog } from './Dialog'; +export { TrackOutsideClicks } from './TrackOutsideClicks'; diff --git a/tgui/packages/tgui/debug/middleware.js b/tgui/packages/tgui/debug/middleware.js index 75687f2541..519d8b5272 100644 --- a/tgui/packages/tgui/debug/middleware.js +++ b/tgui/packages/tgui/debug/middleware.js @@ -5,6 +5,7 @@ */ import { KEY_BACKSPACE, KEY_F10, KEY_F11, KEY_F12 } from 'common/keycodes'; + import { globalEvents } from '../events'; import { acquireHotKey } from '../hotkeys'; import { openExternalBrowser, toggleDebugLayout, toggleKitchenSink } from './actions'; diff --git a/tgui/packages/tgui/drag.ts b/tgui/packages/tgui/drag.ts index a34c49ac46..c26df518b7 100644 --- a/tgui/packages/tgui/drag.ts +++ b/tgui/packages/tgui/drag.ts @@ -4,10 +4,10 @@ * @license MIT */ +import { storage } from 'common/storage'; import { vecAdd, vecMultiply, vecScale, vecSubtract } from 'common/vector'; import { createLogger } from './logging'; -import { storage } from 'common/storage'; const logger = createLogger('drag'); const pixelRatio = window.devicePixelRatio ?? 1; diff --git a/tgui/packages/tgui/events.test.ts b/tgui/packages/tgui/events.test.ts index 8f3e8e3109..5acee62cba 100644 --- a/tgui/packages/tgui/events.test.ts +++ b/tgui/packages/tgui/events.test.ts @@ -1,4 +1,4 @@ -import { KeyEvent, addScrollableNode, canStealFocus, removeScrollableNode, setupGlobalEvents } from './events'; +import { addScrollableNode, canStealFocus, KeyEvent, removeScrollableNode, setupGlobalEvents } from './events'; describe('focusEvents', () => { afterEach(() => { diff --git a/tgui/packages/tgui/events.ts b/tgui/packages/tgui/events.ts index 670f03e808..62aca2046b 100644 --- a/tgui/packages/tgui/events.ts +++ b/tgui/packages/tgui/events.ts @@ -6,9 +6,8 @@ * @license MIT */ -import { KEY_ALT, KEY_CTRL, KEY_F1, KEY_F12, KEY_SHIFT } from 'common/keycodes'; - import { EventEmitter } from 'common/events'; +import { KEY_ALT, KEY_CTRL, KEY_F1, KEY_F12, KEY_SHIFT } from 'common/keycodes'; export const globalEvents = new EventEmitter(); let ignoreWindowFocus = false; diff --git a/tgui/packages/tgui/hotkeys.ts b/tgui/packages/tgui/hotkeys.ts index f7176bd003..be3121bf54 100644 --- a/tgui/packages/tgui/hotkeys.ts +++ b/tgui/packages/tgui/hotkeys.ts @@ -5,6 +5,7 @@ */ import * as keycodes from 'common/keycodes'; + import { globalEvents, KeyEvent } from './events'; import { createLogger } from './logging'; diff --git a/tgui/packages/tgui/index.tsx b/tgui/packages/tgui/index.tsx index b1e6635d35..9f97a52d67 100644 --- a/tgui/packages/tgui/index.tsx +++ b/tgui/packages/tgui/index.tsx @@ -19,15 +19,15 @@ import './styles/themes/syndicate.scss'; import './styles/themes/wizard.scss'; import './styles/themes/abstract.scss'; -import { configureStore } from './store'; - -import { captureExternalLinks } from './links'; -import { createRenderer } from './renderer'; import { perf } from 'common/perf'; +import { setupHotReloading } from 'tgui-dev-server/link/client.cjs'; + +import { setGlobalStore } from './backend'; import { setupGlobalEvents } from './events'; import { setupHotKeys } from './hotkeys'; -import { setupHotReloading } from 'tgui-dev-server/link/client.cjs'; -import { setGlobalStore } from './backend'; +import { captureExternalLinks } from './links'; +import { createRenderer } from './renderer'; +import { configureStore } from './store'; perf.mark('inception', window.performance?.timing?.navigationStart); perf.mark('init'); diff --git a/tgui/packages/tgui/interfaces/AdminShuttleController.tsx b/tgui/packages/tgui/interfaces/AdminShuttleController.tsx index eda0459404..1509fb0538 100644 --- a/tgui/packages/tgui/interfaces/AdminShuttleController.tsx +++ b/tgui/packages/tgui/interfaces/AdminShuttleController.tsx @@ -1,4 +1,5 @@ import { sortBy } from 'common/collections'; + import { useBackend } from '../backend'; import { Button, Section, Table } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/AdminTicketPanel.tsx b/tgui/packages/tgui/interfaces/AdminTicketPanel.tsx index 651c7549c0..4a36b5e0a8 100644 --- a/tgui/packages/tgui/interfaces/AdminTicketPanel.tsx +++ b/tgui/packages/tgui/interfaces/AdminTicketPanel.tsx @@ -73,8 +73,8 @@ export const AdminTicketPanel = (props) => {
- {Object.keys(log).map((L) => ( -
+ {Object.keys(log).map((L, i) => ( +
))} diff --git a/tgui/packages/tgui/interfaces/AgentCard.tsx b/tgui/packages/tgui/interfaces/AgentCard.tsx index d10dbf6af3..0d543b917e 100644 --- a/tgui/packages/tgui/interfaces/AgentCard.tsx +++ b/tgui/packages/tgui/interfaces/AgentCard.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Button, Section, Table } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/AlertModal.tsx b/tgui/packages/tgui/interfaces/AlertModal.tsx index 60f60c94c5..3fd218e30e 100644 --- a/tgui/packages/tgui/interfaces/AlertModal.tsx +++ b/tgui/packages/tgui/interfaces/AlertModal.tsx @@ -1,8 +1,8 @@ -import { Loader } from './common/Loader'; -import { useBackend, useLocalState } from '../backend'; import { KEY_ENTER, KEY_ESCAPE, KEY_LEFT, KEY_RIGHT, KEY_SPACE, KEY_TAB } from '../../common/keycodes'; +import { useBackend, useLocalState } from '../backend'; import { Autofocus, Box, Button, Flex, Section, Stack } from '../components'; import { Window } from '../layouts'; +import { Loader } from './common/Loader'; type AlertModalData = { autofocus: boolean; diff --git a/tgui/packages/tgui/interfaces/AssemblyInfrared.tsx b/tgui/packages/tgui/interfaces/AssemblyInfrared.tsx index c76e252bd6..9bac5050bf 100644 --- a/tgui/packages/tgui/interfaces/AssemblyInfrared.tsx +++ b/tgui/packages/tgui/interfaces/AssemblyInfrared.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/CheckboxInput.tsx b/tgui/packages/tgui/interfaces/CheckboxInput.tsx index bd327e0f65..652e5ffdf8 100644 --- a/tgui/packages/tgui/interfaces/CheckboxInput.tsx +++ b/tgui/packages/tgui/interfaces/CheckboxInput.tsx @@ -1,11 +1,11 @@ +import { createSearch, decodeHtmlEntities } from 'common/string'; + +import { useBackend, useLocalState } from '../backend'; import { Button, Icon, Input, NoticeBox, Section, Stack, Table, Tooltip } from '../components'; import { TableCell, TableRow } from '../components/Table'; -import { createSearch, decodeHtmlEntities } from 'common/string'; -import { useBackend, useLocalState } from '../backend'; - +import { Window } from '../layouts'; import { InputButtons } from './common/InputButtons'; import { Loader } from './common/Loader'; -import { Window } from '../layouts'; type Data = { items: string[]; diff --git a/tgui/packages/tgui/interfaces/ColorMate.tsx b/tgui/packages/tgui/interfaces/ColorMate.tsx index c75aa407e4..edb0e774e7 100644 --- a/tgui/packages/tgui/interfaces/ColorMate.tsx +++ b/tgui/packages/tgui/interfaces/ColorMate.tsx @@ -1,4 +1,5 @@ import { Fragment } from 'react'; + import { useBackend } from '../backend'; import { Box, Button, Flex, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/Communicator.tsx b/tgui/packages/tgui/interfaces/Communicator.tsx index bd3fbc03ec..cc450bb00a 100644 --- a/tgui/packages/tgui/interfaces/Communicator.tsx +++ b/tgui/packages/tgui/interfaces/Communicator.tsx @@ -2,8 +2,9 @@ import { filter } from 'common/collections'; import { BooleanLike } from 'common/react'; import { decodeHtmlEntities, toTitleCase } from 'common/string'; import { Fragment } from 'react'; + import { useBackend, useLocalState } from '../backend'; -import { Box, ByondUi, Button, Flex, Icon, LabeledList, Input, Section, Table } from '../components'; +import { Box, Button, ByondUi, Flex, Icon, Input, LabeledList, Section, Table } from '../components'; import { Window } from '../layouts'; import { CrewManifestContent } from './CrewManifest'; diff --git a/tgui/packages/tgui/interfaces/CrewManifest.tsx b/tgui/packages/tgui/interfaces/CrewManifest.tsx index a11cbe62ff..4040eae963 100644 --- a/tgui/packages/tgui/interfaces/CrewManifest.tsx +++ b/tgui/packages/tgui/interfaces/CrewManifest.tsx @@ -1,8 +1,9 @@ +import { decodeHtmlEntities } from 'common/string'; + import { useBackend } from '../backend'; import { Box, Section, Table } from '../components'; -import { Window } from '../layouts'; import { COLORS } from '../constants'; -import { decodeHtmlEntities } from 'common/string'; +import { Window } from '../layouts'; /* * Shared by the following templates (and used individually too) diff --git a/tgui/packages/tgui/interfaces/DisposalBin.tsx b/tgui/packages/tgui/interfaces/DisposalBin.tsx index 212f32e49b..d799789b75 100644 --- a/tgui/packages/tgui/interfaces/DisposalBin.tsx +++ b/tgui/packages/tgui/interfaces/DisposalBin.tsx @@ -1,6 +1,7 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; -import { Button, LabeledList, Section, Box, ProgressBar } from '../components'; +import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/EntityNarrate.tsx b/tgui/packages/tgui/interfaces/EntityNarrate.tsx index f69f77e932..e4fea4ff0f 100644 --- a/tgui/packages/tgui/interfaces/EntityNarrate.tsx +++ b/tgui/packages/tgui/interfaces/EntityNarrate.tsx @@ -1,6 +1,7 @@ import { BooleanLike } from 'common/react'; + import { useBackend, useLocalState } from '../backend'; -import { Flex, Tabs, Section, Button, Box, TextArea, Divider } from '../components'; +import { Box, Button, Divider, Flex, Section, Tabs, TextArea } from '../components'; import { Window } from '../layouts'; type data = { diff --git a/tgui/packages/tgui/interfaces/ExonetNode.tsx b/tgui/packages/tgui/interfaces/ExonetNode.tsx index def5845bf8..6be90d498f 100644 --- a/tgui/packages/tgui/interfaces/ExonetNode.tsx +++ b/tgui/packages/tgui/interfaces/ExonetNode.tsx @@ -1,6 +1,7 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; -import { Button, Box, Flex, LabeledList, Section } from '../components'; +import { Box, Button, Flex, LabeledList, Section } from '../components'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/ExosuitFabricator.jsx b/tgui/packages/tgui/interfaces/ExosuitFabricator.jsx index bbf34fb5ca..6cd0efe418 100644 --- a/tgui/packages/tgui/interfaces/ExosuitFabricator.jsx +++ b/tgui/packages/tgui/interfaces/ExosuitFabricator.jsx @@ -2,7 +2,8 @@ import { classes } from 'common/react'; import { uniqBy } from 'common/collections'; import { useBackend, useSharedState } from '../backend'; import { formatSiUnit, formatMoney } from '../format'; -import { Flex, Section, Tabs, Box, Button, Fragment, ProgressBar, NumberInput, Icon, Input, Tooltip } from '../components'; +import { Flex, Section, Tabs, Box, Button, ProgressBar, NumberInput, Icon, Input, Tooltip } from '../components'; +import { Fragment } from 'react'; import { Window } from '../layouts'; import { createSearch, toTitleCase } from 'common/string'; import { toFixed } from 'common/math'; diff --git a/tgui/packages/tgui/interfaces/GyrotronControl.tsx b/tgui/packages/tgui/interfaces/GyrotronControl.tsx index a2d08bb601..0e25da3e14 100644 --- a/tgui/packages/tgui/interfaces/GyrotronControl.tsx +++ b/tgui/packages/tgui/interfaces/GyrotronControl.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; -import { Window } from '../layouts'; -import { Button, Section, Table, Knob } from '../components'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, Knob, Section, Table } from '../components'; +import { Window } from '../layouts'; + export const GyrotronControl = () => ( diff --git a/tgui/packages/tgui/interfaces/InventoryPanel.tsx b/tgui/packages/tgui/interfaces/InventoryPanel.tsx index 1918a6a8df..ee21777411 100644 --- a/tgui/packages/tgui/interfaces/InventoryPanel.tsx +++ b/tgui/packages/tgui/interfaces/InventoryPanel.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/ListInputModal.tsx b/tgui/packages/tgui/interfaces/ListInputModal.tsx index 01d98cc4fe..cd2a9df490 100644 --- a/tgui/packages/tgui/interfaces/ListInputModal.tsx +++ b/tgui/packages/tgui/interfaces/ListInputModal.tsx @@ -1,9 +1,9 @@ -import { Loader } from './common/Loader'; -import { InputButtons } from './common/InputButtons'; -import { Button, Input, Section, Stack } from '../components'; +import { KEY_A, KEY_DOWN, KEY_ENTER, KEY_ESCAPE, KEY_UP, KEY_Z } from '../../common/keycodes'; import { useBackend, useLocalState } from '../backend'; -import { KEY_A, KEY_DOWN, KEY_ESCAPE, KEY_ENTER, KEY_UP, KEY_Z } from '../../common/keycodes'; +import { Button, Input, Section, Stack } from '../components'; import { Window } from '../layouts'; +import { InputButtons } from './common/InputButtons'; +import { Loader } from './common/Loader'; type ListInputData = { init_value: string; diff --git a/tgui/packages/tgui/interfaces/MentorTicketPanel.tsx b/tgui/packages/tgui/interfaces/MentorTicketPanel.tsx index 72aea768de..d94f4345ba 100644 --- a/tgui/packages/tgui/interfaces/MentorTicketPanel.tsx +++ b/tgui/packages/tgui/interfaces/MentorTicketPanel.tsx @@ -72,8 +72,8 @@ export const MentorTicketPanel = (props) => {
- {Object.keys(log).map((L) => ( -
+ {Object.keys(log).map((L, i) => ( +
))} diff --git a/tgui/packages/tgui/interfaces/MuleBot.tsx b/tgui/packages/tgui/interfaces/MuleBot.tsx index 45aabb8efe..760c67b945 100644 --- a/tgui/packages/tgui/interfaces/MuleBot.tsx +++ b/tgui/packages/tgui/interfaces/MuleBot.tsx @@ -1,5 +1,6 @@ import { BooleanLike } from 'common/react'; import { Fragment } from 'react'; + import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/NoticeBoard.tsx b/tgui/packages/tgui/interfaces/NoticeBoard.tsx index 3df50546fe..7499ebbb2a 100644 --- a/tgui/packages/tgui/interfaces/NoticeBoard.tsx +++ b/tgui/packages/tgui/interfaces/NoticeBoard.tsx @@ -1,5 +1,6 @@ import { BooleanLike } from 'common/react'; import { Fragment } from 'react'; + import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/NtosAccessDecrypter.tsx b/tgui/packages/tgui/interfaces/NtosAccessDecrypter.tsx index c81452709e..1fbb9b7657 100644 --- a/tgui/packages/tgui/interfaces/NtosAccessDecrypter.tsx +++ b/tgui/packages/tgui/interfaces/NtosAccessDecrypter.tsx @@ -1,8 +1,9 @@ +import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; +import { Box, Button, NoticeBox, Section } from '../components'; import { NtosWindow } from '../layouts'; import { IdentificationComputerRegions } from './IdentificationComputer'; -import { NoticeBox, Box, Section, Button } from '../components'; -import { BooleanLike } from 'common/react'; type Data = { message: string; diff --git a/tgui/packages/tgui/interfaces/NtosRevelation.tsx b/tgui/packages/tgui/interfaces/NtosRevelation.tsx index 9e5217e117..5839e3cc96 100644 --- a/tgui/packages/tgui/interfaces/NtosRevelation.tsx +++ b/tgui/packages/tgui/interfaces/NtosRevelation.tsx @@ -1,8 +1,9 @@ -import { Section, Button, LabeledList } from '../components'; -import { useBackend } from '../backend'; -import { NtosWindow } from '../layouts'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, LabeledList, Section } from '../components'; +import { NtosWindow } from '../layouts'; + type Data = { armed: BooleanLike; }; diff --git a/tgui/packages/tgui/interfaces/NumberInputModal.tsx b/tgui/packages/tgui/interfaces/NumberInputModal.tsx index e2f280a606..24867108d8 100644 --- a/tgui/packages/tgui/interfaces/NumberInputModal.tsx +++ b/tgui/packages/tgui/interfaces/NumberInputModal.tsx @@ -1,9 +1,9 @@ -import { Loader } from './common/Loader'; -import { InputButtons } from './common/InputButtons'; import { KEY_ENTER, KEY_ESCAPE } from '../../common/keycodes'; import { useBackend, useLocalState } from '../backend'; import { Box, Button, RestrictedInput, Section, Stack } from '../components'; import { Window } from '../layouts'; +import { InputButtons } from './common/InputButtons'; +import { Loader } from './common/Loader'; type NumberInputData = { init_value: number; diff --git a/tgui/packages/tgui/interfaces/OmniFilter.tsx b/tgui/packages/tgui/interfaces/OmniFilter.tsx index e094472b86..af93651f69 100644 --- a/tgui/packages/tgui/interfaces/OmniFilter.tsx +++ b/tgui/packages/tgui/interfaces/OmniFilter.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; +import { BooleanLike } from 'common/react'; import { Fragment } from 'react'; + +import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; -import { BooleanLike } from 'common/react'; const getStatusText = (port) => { if (port.input) { diff --git a/tgui/packages/tgui/interfaces/OmniMixer.tsx b/tgui/packages/tgui/interfaces/OmniMixer.tsx index 264347731e..04ed8103ed 100644 --- a/tgui/packages/tgui/interfaces/OmniMixer.tsx +++ b/tgui/packages/tgui/interfaces/OmniMixer.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; +import { BooleanLike } from 'common/react'; import { Fragment } from 'react'; + +import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section, Table } from '../components'; import { Window } from '../layouts'; -import { BooleanLike } from 'common/react'; const getStatusText = (port) => { if (port.input) { diff --git a/tgui/packages/tgui/interfaces/OvermapNavigation.tsx b/tgui/packages/tgui/interfaces/OvermapNavigation.tsx index 0df93fbe6b..5682145137 100644 --- a/tgui/packages/tgui/interfaces/OvermapNavigation.tsx +++ b/tgui/packages/tgui/interfaces/OvermapNavigation.tsx @@ -1,5 +1,6 @@ import { BooleanLike } from 'common/react'; import { Fragment } from 'react'; + import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/ParticleAccelerator.tsx b/tgui/packages/tgui/interfaces/ParticleAccelerator.tsx index 015b63bc0e..a41d30e125 100644 --- a/tgui/packages/tgui/interfaces/ParticleAccelerator.tsx +++ b/tgui/packages/tgui/interfaces/ParticleAccelerator.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/PointDefenseControl.tsx b/tgui/packages/tgui/interfaces/PointDefenseControl.tsx index 8d58188770..4e2bfc5dfb 100644 --- a/tgui/packages/tgui/interfaces/PointDefenseControl.tsx +++ b/tgui/packages/tgui/interfaces/PointDefenseControl.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Box, Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/PortableScrubber.tsx b/tgui/packages/tgui/interfaces/PortableScrubber.tsx index e1aa693b17..42ff9143e1 100644 --- a/tgui/packages/tgui/interfaces/PortableScrubber.tsx +++ b/tgui/packages/tgui/interfaces/PortableScrubber.tsx @@ -1,5 +1,5 @@ import { useBackend } from '../backend'; -import { Slider, Section, LabeledList } from '../components'; +import { LabeledList, Section, Slider } from '../components'; import { Window } from '../layouts'; import { PortableBasicInfo } from './common/PortableAtmos'; diff --git a/tgui/packages/tgui/interfaces/PowerMonitor.jsx b/tgui/packages/tgui/interfaces/PowerMonitor.jsx index 0e43747a02..3e28b4b955 100644 --- a/tgui/packages/tgui/interfaces/PowerMonitor.jsx +++ b/tgui/packages/tgui/interfaces/PowerMonitor.jsx @@ -1,8 +1,6 @@ import { map, sortBy } from 'common/collections'; import { flow } from 'common/fp'; import { toFixed } from 'common/math'; -import { pureComponentHooks } from 'common/react'; -import { Fragment } from 'react'; import { useBackend, useLocalState } from '../backend'; import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components'; import { Window } from '../layouts'; @@ -254,8 +252,6 @@ export const AreaCharge = (props) => { ); }; -AreaCharge.defaultHooks = pureComponentHooks; - const AreaStatusColorBox = (props) => { const { status } = props; const power = Boolean(status & 2); @@ -269,5 +265,3 @@ const AreaStatusColorBox = (props) => { /> ); }; - -AreaStatusColorBox.defaultHooks = pureComponentHooks; diff --git a/tgui/packages/tgui/interfaces/RustCoreMonitor.tsx b/tgui/packages/tgui/interfaces/RustCoreMonitor.tsx index eaac993847..1277b3f00f 100644 --- a/tgui/packages/tgui/interfaces/RustCoreMonitor.tsx +++ b/tgui/packages/tgui/interfaces/RustCoreMonitor.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; -import { Window } from '../layouts'; -import { Button, Section, Table, Knob } from '../components'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, Knob, Section, Table } from '../components'; +import { Window } from '../layouts'; + export const RustCoreMonitor = () => ( diff --git a/tgui/packages/tgui/interfaces/RustFuelControl.tsx b/tgui/packages/tgui/interfaces/RustFuelControl.tsx index 0a714a55ab..4af6790d69 100644 --- a/tgui/packages/tgui/interfaces/RustFuelControl.tsx +++ b/tgui/packages/tgui/interfaces/RustFuelControl.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; -import { Window } from '../layouts'; -import { Button, Section, Table } from '../components'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, Section, Table } from '../components'; +import { Window } from '../layouts'; + export const RustFuelControl = () => ( diff --git a/tgui/packages/tgui/interfaces/Signaler.tsx b/tgui/packages/tgui/interfaces/Signaler.tsx index e686cc9aeb..ef7902dcfe 100644 --- a/tgui/packages/tgui/interfaces/Signaler.tsx +++ b/tgui/packages/tgui/interfaces/Signaler.tsx @@ -1,4 +1,5 @@ import { toFixed } from 'common/math'; + import { useBackend } from '../backend'; import { Button, Grid, NumberInput, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/SpaceHeater.tsx b/tgui/packages/tgui/interfaces/SpaceHeater.tsx index bb76486b2f..6aac59315b 100644 --- a/tgui/packages/tgui/interfaces/SpaceHeater.tsx +++ b/tgui/packages/tgui/interfaces/SpaceHeater.tsx @@ -1,9 +1,10 @@ -import { T0C } from '../constants'; -import { useBackend } from '../backend'; -import { Button, Knob, Section, LabeledControls, LabeledList } from '../components'; -import { Window } from '../layouts'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, Knob, LabeledControls, LabeledList, Section } from '../components'; +import { T0C } from '../constants'; +import { Window } from '../layouts'; + type Data = { temp: number; minTemp: number; diff --git a/tgui/packages/tgui/interfaces/Teleporter.tsx b/tgui/packages/tgui/interfaces/Teleporter.tsx index f99b4c17c1..353085b65a 100644 --- a/tgui/packages/tgui/interfaces/Teleporter.tsx +++ b/tgui/packages/tgui/interfaces/Teleporter.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/TextInputModal.tsx b/tgui/packages/tgui/interfaces/TextInputModal.tsx index 836ab8a167..60b682e1dc 100644 --- a/tgui/packages/tgui/interfaces/TextInputModal.tsx +++ b/tgui/packages/tgui/interfaces/TextInputModal.tsx @@ -1,9 +1,9 @@ -import { Loader } from './common/Loader'; -import { InputButtons } from './common/InputButtons'; -import { useBackend, useLocalState } from '../backend'; import { KEY_ENTER, KEY_ESCAPE } from '../../common/keycodes'; // CHOMPedit +import { useBackend, useLocalState } from '../backend'; import { Box, Section, Stack, TextArea } from '../components'; import { Window } from '../layouts'; +import { InputButtons } from './common/InputButtons'; +import { Loader } from './common/Loader'; type TextInputData = { large_buttons: boolean; diff --git a/tgui/packages/tgui/interfaces/TraitTutorial.tsx b/tgui/packages/tgui/interfaces/TraitTutorial.tsx index 4c366dbd22..0cdd0e2ae8 100644 --- a/tgui/packages/tgui/interfaces/TraitTutorial.tsx +++ b/tgui/packages/tgui/interfaces/TraitTutorial.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/no-danger */ import { useBackend } from '../backend'; -import { Stack, Tabs, Section, Box } from '../components'; +import { Box, Section, Stack, Tabs } from '../components'; import { Window } from '../layouts'; type data = { diff --git a/tgui/packages/tgui/interfaces/TransferValve.tsx b/tgui/packages/tgui/interfaces/TransferValve.tsx index 8e5390adc2..4ae6cc10ac 100644 --- a/tgui/packages/tgui/interfaces/TransferValve.tsx +++ b/tgui/packages/tgui/interfaces/TransferValve.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Button, LabeledList, NoticeBox, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/VolumePanel.tsx b/tgui/packages/tgui/interfaces/VolumePanel.tsx index 5a14ce83b0..97912319b2 100644 --- a/tgui/packages/tgui/interfaces/VolumePanel.tsx +++ b/tgui/packages/tgui/interfaces/VolumePanel.tsx @@ -1,5 +1,5 @@ import { useBackend } from '../backend'; -import { Button, LabeledList, Slider, Section } from '../components'; +import { Button, LabeledList, Section, Slider } from '../components'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/VorePanelExport.tsx b/tgui/packages/tgui/interfaces/VorePanelExport.tsx index 4931e40f75..7f249ebb2b 100644 --- a/tgui/packages/tgui/interfaces/VorePanelExport.tsx +++ b/tgui/packages/tgui/interfaces/VorePanelExport.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; -import { Window } from '../layouts'; -import { Button, Section } from '../components'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Button, Section } from '../components'; +import { Window } from '../layouts'; + const ModeSpan = { 'Hold': 'Hold', 'Digest': 'Digest', diff --git a/tgui/packages/tgui/interfaces/XenoarchArtifactAnalyzer.tsx b/tgui/packages/tgui/interfaces/XenoarchArtifactAnalyzer.tsx index bb31c5d5df..6f9c959c01 100644 --- a/tgui/packages/tgui/interfaces/XenoarchArtifactAnalyzer.tsx +++ b/tgui/packages/tgui/interfaces/XenoarchArtifactAnalyzer.tsx @@ -1,8 +1,9 @@ -import { useBackend } from '../backend'; -import { Window } from '../layouts'; -import { Box, Button, Section } from '../components'; import { BooleanLike } from 'common/react'; +import { useBackend } from '../backend'; +import { Box, Button, Section } from '../components'; +import { Window } from '../layouts'; + export const XenoarchArtifactAnalyzer = () => { return ( diff --git a/tgui/packages/tgui/interfaces/XenoarchHandheldPowerUtilizer.tsx b/tgui/packages/tgui/interfaces/XenoarchHandheldPowerUtilizer.tsx index bf4c1d1100..551404efdf 100644 --- a/tgui/packages/tgui/interfaces/XenoarchHandheldPowerUtilizer.tsx +++ b/tgui/packages/tgui/interfaces/XenoarchHandheldPowerUtilizer.tsx @@ -1,6 +1,7 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; -import { Box, Button, LabeledList, NumberInput, Section, ProgressBar } from '../components'; +import { Box, Button, LabeledList, NumberInput, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; type Data = { diff --git a/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx b/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx index 6e16f97de3..2a0b62ea37 100644 --- a/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx +++ b/tgui/packages/tgui/interfaces/XenoarchSuspension.tsx @@ -1,5 +1,6 @@ import { BooleanLike } from 'common/react'; import { Fragment } from 'react'; + import { useBackend } from '../backend'; import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/interfaces/chompstation/Ticket.tsx b/tgui/packages/tgui/interfaces/chompstation/Ticket.tsx index ef129f3c24..607803d27b 100644 --- a/tgui/packages/tgui/interfaces/chompstation/Ticket.tsx +++ b/tgui/packages/tgui/interfaces/chompstation/Ticket.tsx @@ -106,8 +106,8 @@ export const Ticket = (props) => { {Object.keys(log) .slice(0) - .map((L) => ( -
+ .map((L, i) => ( +
))} diff --git a/tgui/packages/tgui/interfaces/chompstation/TicketChat.tsx b/tgui/packages/tgui/interfaces/chompstation/TicketChat.tsx index 63b7367ddf..34bb628334 100644 --- a/tgui/packages/tgui/interfaces/chompstation/TicketChat.tsx +++ b/tgui/packages/tgui/interfaces/chompstation/TicketChat.tsx @@ -57,8 +57,8 @@ export const TicketChat = (props) => { {Object.keys(log) .slice(0) - .map((L) => ( -
+ .map((L, i) => ( +
))} diff --git a/tgui/packages/tgui/interfaces/chompstation/TicketsPanel.tsx b/tgui/packages/tgui/interfaces/chompstation/TicketsPanel.tsx index e71d3d7208..81e735db0f 100644 --- a/tgui/packages/tgui/interfaces/chompstation/TicketsPanel.tsx +++ b/tgui/packages/tgui/interfaces/chompstation/TicketsPanel.tsx @@ -219,8 +219,9 @@ export const TicketsPanel = (props) => { {Object.keys(selected_ticket.log) .slice(0) - .map((L) => ( + .map((L, i) => (
Hold', 'Digest': 'Digest', diff --git a/tgui/packages/tgui/interfaces/common/InputButtons.tsx b/tgui/packages/tgui/interfaces/common/InputButtons.tsx index b26a586174..8d774d9e29 100644 --- a/tgui/packages/tgui/interfaces/common/InputButtons.tsx +++ b/tgui/packages/tgui/interfaces/common/InputButtons.tsx @@ -1,6 +1,5 @@ -import { Box, Button, Flex } from '../../components'; - import { useBackend } from '../../backend'; +import { Box, Button, Flex } from '../../components'; type InputButtonsData = { large_buttons: boolean; diff --git a/tgui/packages/tgui/interfaces/common/Loader.tsx b/tgui/packages/tgui/interfaces/common/Loader.tsx index 7f758a94ad..bf0f432d05 100644 --- a/tgui/packages/tgui/interfaces/common/Loader.tsx +++ b/tgui/packages/tgui/interfaces/common/Loader.tsx @@ -1,6 +1,7 @@ -import { Box } from '../../components'; import { clamp01 } from 'common/math'; +import { Box } from '../../components'; + export const Loader = (props) => { const { value } = props; diff --git a/tgui/packages/tgui/interfaces/pAIInterface.tsx b/tgui/packages/tgui/interfaces/pAIInterface.tsx index 655bd28e65..d02c4c0af0 100644 --- a/tgui/packages/tgui/interfaces/pAIInterface.tsx +++ b/tgui/packages/tgui/interfaces/pAIInterface.tsx @@ -1,4 +1,5 @@ import { BooleanLike } from 'common/react'; + import { useBackend } from '../backend'; import { Button, LabeledList, Section } from '../components'; import { Window } from '../layouts'; diff --git a/tgui/packages/tgui/layouts/Window.tsx b/tgui/packages/tgui/layouts/Window.tsx index 658c21bff5..0ebd93d299 100644 --- a/tgui/packages/tgui/layouts/Window.tsx +++ b/tgui/packages/tgui/layouts/Window.tsx @@ -6,16 +6,17 @@ import { classes } from 'common/react'; import { decodeHtmlEntities, toTitleCase } from 'common/string'; +import { PropsWithChildren, ReactNode, useEffect } from 'react'; + import { backendSuspendStart, useBackend } from '../backend'; +import { globalStore } from '../backend'; import { Icon } from '../components'; +import { BoxProps } from '../components/Box'; import { UI_DISABLED, UI_INTERACTIVE, UI_UPDATE } from '../constants'; import { toggleKitchenSink } from '../debug/actions'; import { dragStartHandler, recallWindowGeometry, resizeStartHandler, setWindowKey } from '../drag'; import { createLogger } from '../logging'; import { Layout } from './Layout'; -import { globalStore } from '../backend'; -import { PropsWithChildren, ReactNode, useEffect } from 'react'; -import { BoxProps } from '../components/Box'; const logger = createLogger('Window'); diff --git a/tgui/packages/tgui/package.json b/tgui/packages/tgui/package.json index b59766c04b..03b997b7d2 100644 --- a/tgui/packages/tgui/package.json +++ b/tgui/packages/tgui/package.json @@ -15,6 +15,7 @@ "marked": "^4.2.12", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-popper": "^2.3.0", "tgui-dev-server": "workspace:*", "tgui-polyfill": "workspace:*" } diff --git a/tgui/packages/tgui/renderer.ts b/tgui/packages/tgui/renderer.ts index 4478cedc76..26ff4e35ec 100644 --- a/tgui/packages/tgui/renderer.ts +++ b/tgui/packages/tgui/renderer.ts @@ -1,10 +1,12 @@ import { perf } from 'common/perf'; -import { render } from 'react-dom'; +import { ReactNode } from 'react'; +import { createRoot, Root } from 'react-dom/client'; + import { createLogger } from './logging'; const logger = createLogger('renderer'); -let reactRoot: any; +let reactRoot: Root; let initialRender: string | boolean = true; let suspended = false; @@ -19,23 +21,29 @@ export const suspendRenderer = () => { }; type CreateRenderer = ( - getVNode?: (...args: T) => any + getVNode?: (...args: T) => ReactNode ) => (...args: T) => void; +enum Render { + Start = 'render/start', + Finish = 'render/finish', +} + // prettier-ignore export const createRenderer: CreateRenderer = (getVNode) => (...args) => { - perf.mark('render/start'); + perf.mark(Render.Start); // Start rendering if (!reactRoot) { - reactRoot = document.getElementById('react-root'); + const element = document.getElementById('react-root'); + reactRoot = createRoot(element!); } if (getVNode) { - render(getVNode(...args), reactRoot); + reactRoot.render(getVNode(...args)); } else { - render(args[0] as any, reactRoot); + reactRoot.render(args[0] as any); } - perf.mark('render/finish'); + perf.mark(Render.Finish); if (suspended) { return; } @@ -43,22 +51,22 @@ export const createRenderer: CreateRenderer = (getVNode) => (...args) => { if (process.env.NODE_ENV !== 'production') { if (initialRender === 'resumed') { logger.log('rendered in', - perf.measure('render/start', 'render/finish')); + perf.measure(Render.Start, Render.Finish)); } else if (initialRender) { logger.debug('serving from:', location.href); logger.debug('bundle entered in', perf.measure('inception', 'init')); logger.debug('initialized in', - perf.measure('init', 'render/start')); + perf.measure('init', Render.Start)); logger.log('rendered in', - perf.measure('render/start', 'render/finish')); + perf.measure(Render.Start, Render.Finish)); logger.log('fully loaded in', - perf.measure('inception', 'render/finish')); + perf.measure('inception', Render.Finish)); } else { logger.debug('rendered in', - perf.measure('render/start', 'render/finish')); + perf.measure(Render.Start, Render.Finish)); } } if (initialRender) { diff --git a/tgui/packages/tgui/routes.tsx b/tgui/packages/tgui/routes.tsx index 31ec045e8f..1731cee4f8 100644 --- a/tgui/packages/tgui/routes.tsx +++ b/tgui/packages/tgui/routes.tsx @@ -4,10 +4,9 @@ * @license MIT */ -import { Icon, Section, Stack } from './components'; - -import { Window } from './layouts'; import { useBackend } from './backend'; +import { Icon, Section, Stack } from './components'; +import { Window } from './layouts'; const requireInterface = require.context('./interfaces'); diff --git a/tgui/packages/tgui/store.ts b/tgui/packages/tgui/store.ts index 4b1455b902..36289f3478 100644 --- a/tgui/packages/tgui/store.ts +++ b/tgui/packages/tgui/store.ts @@ -4,13 +4,13 @@ * @license MIT */ -import { Middleware, Reducer, Store, applyMiddleware, combineReducers, createStore } from 'common/redux'; -import { backendMiddleware, backendReducer } from './backend'; -import { debugMiddleware, debugReducer, relayMiddleware } from './debug'; +import { flow } from 'common/fp'; +import { applyMiddleware, combineReducers, createStore, Middleware, Reducer, Store } from 'common/redux'; import { assetMiddleware } from './assets'; +import { backendMiddleware, backendReducer } from './backend'; +import { debugMiddleware, debugReducer, relayMiddleware } from './debug'; import { createLogger } from './logging'; -import { flow } from 'common/fp'; type ConfigureStoreOptions = { sideEffects?: boolean; diff --git a/tgui/packages/tgui/stories/Popper.stories.js b/tgui/packages/tgui/stories/Popper.stories.js index 08fd430fb2..07b6c52394 100644 --- a/tgui/packages/tgui/stories/Popper.stories.js +++ b/tgui/packages/tgui/stories/Popper.stories.js @@ -9,7 +9,8 @@ const Story = () => { return ( <> { Loogatme! } - options={{ - placement: 'bottom', - }}> + placement="bottom"> { { I am on the right! } - options={{ - placement: 'right', - }}> + placement="right"> r}return!1}function O(t,r,u,S,A,L,K){this.acceptsBooleans=r===2||r===3||r===4,this.attributeName=S,this.attributeNamespace=A,this.mustUseProperty=u,this.propertyName=t,this.type=r,this.sanitizeURL=L,this.removeEmptyString=K}var C={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(t){C[t]=new O(t,0,!1,t,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(t){var r=t[0];C[r]=new O(r,1,!1,t[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(t){C[t]=new O(t,2,!1,t.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(t){C[t]=new O(t,2,!1,t,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(t){C[t]=new O(t,3,!1,t.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(t){C[t]=new O(t,3,!0,t,null,!1,!1)}),["capture","download"].forEach(function(t){C[t]=new O(t,4,!1,t,null,!1,!1)}),["cols","rows","size","span"].forEach(function(t){C[t]=new O(t,6,!1,t,null,!1,!1)}),["rowSpan","start"].forEach(function(t){C[t]=new O(t,5,!1,t.toLowerCase(),null,!1,!1)});var R=/[\-:]([a-z])/g;function M(t){return t[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(t){var r=t.replace(R,M);C[r]=new O(r,1,!1,t,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(t){var r=t.replace(R,M);C[r]=new O(r,1,!1,t,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(t){var r=t.replace(R,M);C[r]=new O(r,1,!1,t,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(t){C[t]=new O(t,1,!1,t.toLowerCase(),null,!1,!1)}),C.xlinkHref=new O("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(t){C[t]=new O(t,1,!1,t.toLowerCase(),null,!0,!0)});function w(t,r,u,S){var A=C.hasOwnProperty(r)?C[r]:null;(A!==null?A.type!==0:S||!(2Q||A[K]!==L[Q]){var de="\n"+A[K].replace(" at new "," at ");return t.displayName&&de.includes("")&&(de=de.replace("",t.displayName)),de}while(1<=K&&0<=Q);break}}}finally{ie=!1,Error.prepareStackTrace=u}return(t=t?t.displayName||t.name:"")?J(t):""}function X(t){switch(t.tag){case 5:return J(t.type);case 16:return J("Lazy");case 13:return J("Suspense");case 19:return J("SuspenseList");case 0:case 2:case 15:return t=le(t.type,!1),t;case 11:return t=le(t.type.render,!1),t;case 1:return t=le(t.type,!0),t;default:return""}}function ee(t){if(t==null)return null;if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t;switch(t){case b:return"Fragment";case P:return"Portal";case D:return"Profiler";case N:return"StrictMode";case G:return"Suspense";case z:return"SuspenseList"}if(typeof t=="object")switch(t.$$typeof){case B:return(t.displayName||"Context")+".Consumer";case j:return(t._context.displayName||"Context")+".Provider";case k:var r=t.render;return t=t.displayName,t||(t=r.displayName||r.name||"",t=t!==""?"ForwardRef("+t+")":"ForwardRef"),t;case V:return r=t.displayName||null,r!==null?r:ee(t.type)||"Memo";case F:r=t._payload,t=t._init;try{return ee(t(r))}catch(u){}}return null}function _(t){var r=t.type;switch(t.tag){case 24:return"Cache";case 9:return(r.displayName||"Context")+".Consumer";case 10:return(r._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return t=r.render,t=t.displayName||t.name||"",r.displayName||(t!==""?"ForwardRef("+t+")":"ForwardRef");case 7:return"Fragment";case 5:return r;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return ee(r);case 8:return r===N?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof r=="function")return r.displayName||r.name||null;if(typeof r=="string")return r}return null}function se(t){switch(typeof t){case"boolean":case"number":case"string":case"undefined":return t;case"object":return t;default:return""}}function ge(t){var r=t.type;return(t=t.nodeName)&&t.toLowerCase()==="input"&&(r==="checkbox"||r==="radio")}function we(t){var r=ge(t)?"checked":"value",u=Object.getOwnPropertyDescriptor(t.constructor.prototype,r),S=""+t[r];if(!t.hasOwnProperty(r)&&typeof u!="undefined"&&typeof u.get=="function"&&typeof u.set=="function"){var A=u.get,L=u.set;return Object.defineProperty(t,r,{configurable:!0,get:function(){function K(){return A.call(this)}return K}(),set:function(){function K(Q){S=""+Q,L.call(this,Q)}return K}()}),Object.defineProperty(t,r,{enumerable:u.enumerable}),{getValue:function(){function K(){return S}return K}(),setValue:function(){function K(Q){S=""+Q}return K}(),stopTracking:function(){function K(){t._valueTracker=null,delete t[r]}return K}()}}}function Ae(t){t._valueTracker||(t._valueTracker=we(t))}function De(t){if(!t)return!1;var r=t._valueTracker;if(!r)return!0;var u=r.getValue(),S="";return t&&(S=ge(t)?t.checked?"true":"false":t.value),t=S,t!==u?(r.setValue(t),!0):!1}function Re(t){if(t=t||(typeof document!="undefined"?document:void 0),typeof t=="undefined")return null;try{return t.activeElement||t.body}catch(r){return t.body}}function Se(t,r){var u=r.checked;return W({},r,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:u!=null?u:t._wrapperState.initialChecked})}function Ee(t,r){var u=r.defaultValue==null?"":r.defaultValue,S=r.checked!=null?r.checked:r.defaultChecked;u=se(r.value!=null?r.value:u),t._wrapperState={initialChecked:S,initialValue:u,controlled:r.type==="checkbox"||r.type==="radio"?r.checked!=null:r.value!=null}}function oe(t,r){r=r.checked,r!=null&&w(t,"checked",r,!1)}function ue(t,r){oe(t,r);var u=se(r.value),S=r.type;if(u!=null)S==="number"?(u===0&&t.value===""||t.value!=u)&&(t.value=""+u):t.value!==""+u&&(t.value=""+u);else if(S==="submit"||S==="reset"){t.removeAttribute("value");return}r.hasOwnProperty("value")?ne(t,r.type,u):r.hasOwnProperty("defaultValue")&&ne(t,r.type,se(r.defaultValue)),r.checked==null&&r.defaultChecked!=null&&(t.defaultChecked=!!r.defaultChecked)}function fe(t,r,u){if(r.hasOwnProperty("value")||r.hasOwnProperty("defaultValue")){var S=r.type;if(!(S!=="submit"&&S!=="reset"||r.value!==void 0&&r.value!==null))return;r=""+t._wrapperState.initialValue,u||r===t.value||(t.value=r),t.defaultValue=r}u=t.name,u!==""&&(t.name=""),t.defaultChecked=!!t._wrapperState.initialChecked,u!==""&&(t.name=u)}function ne(t,r,u){(r!=="number"||Re(t.ownerDocument)!==t)&&(u==null?t.defaultValue=""+t._wrapperState.initialValue:t.defaultValue!==""+u&&(t.defaultValue=""+u))}var re=Array.isArray;function Z(t,r,u,S){if(t=t.options,r){r={};for(var A=0;A"+r.valueOf().toString()+"",r=Ye.firstChild;t.firstChild;)t.removeChild(t.firstChild);for(;r.firstChild;)t.appendChild(r.firstChild)}});function ze(t,r){if(r){var u=t.firstChild;if(u&&u===t.lastChild&&u.nodeType===3){u.nodeValue=r;return}}t.textContent=r}var Ke={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Ce=["Webkit","ms","Moz","O"];Object.keys(Ke).forEach(function(t){Ce.forEach(function(r){r=r+t.charAt(0).toUpperCase()+t.substring(1),Ke[r]=Ke[t]})});function Te(t,r,u){return r==null||typeof r=="boolean"||r===""?"":u||typeof r!="number"||r===0||Ke.hasOwnProperty(t)&&Ke[t]?(""+r).trim():r+"px"}function ye(t,r){t=t.style;for(var u in r)if(r.hasOwnProperty(u)){var S=u.indexOf("--")===0,A=Te(u,r[u],S);u==="float"&&(u="cssFloat"),S?t.setProperty(u,A):t[u]=A}}var Ne=W({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Be(t,r){if(r){if(Ne[t]&&(r.children!=null||r.dangerouslySetInnerHTML!=null))throw Error(a(137,t));if(r.dangerouslySetInnerHTML!=null){if(r.children!=null)throw Error(a(60));if(typeof r.dangerouslySetInnerHTML!="object"||!("__html"in r.dangerouslySetInnerHTML))throw Error(a(61))}if(r.style!=null&&typeof r.style!="object")throw Error(a(62))}}function Ue(t,r){if(t.indexOf("-")===-1)return typeof r.is=="string";switch(t){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var qe=null;function tt(t){return t=t.target||t.srcElement||window,t.correspondingUseElement&&(t=t.correspondingUseElement),t.nodeType===3?t.parentNode:t}var nt=null,at=null,ut=null;function yt(t){if(t=Do(t)){if(typeof nt!="function")throw Error(a(280));var r=t.stateNode;r&&(r=pi(r),nt(t.stateNode,t.type,r))}}function Br(t){at?ut?ut.push(t):ut=[t]:at=t}function gr(){if(at){var t=at,r=ut;if(ut=at=null,yt(t),r)for(t=0;t>>=0,t===0?32:31-(Eo(t)/yr|0)|0}var ln=64,Sr=4194304;function Qn(t){switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return t&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return t}}function Er(t,r){var u=t.pendingLanes;if(u===0)return 0;var S=0,A=t.suspendedLanes,L=t.pingedLanes,K=u&268435455;if(K!==0){var Q=K&~A;Q!==0?S=Qn(Q):(L&=K,L!==0&&(S=Qn(L)))}else K=u&~A,K!==0?S=Qn(K):L!==0&&(S=Qn(L));if(S===0)return 0;if(r!==0&&r!==S&&!(r&A)&&(A=S&-S,L=r&-r,A>=L||A===16&&(L&4194240)!==0))return r;if(S&4&&(S|=u&16),r=t.entangledLanes,r!==0)for(t=t.entanglements,r&=S;0u;u++)r.push(t);return r}function qt(t,r,u){t.pendingLanes|=r,r!==536870912&&(t.suspendedLanes=0,t.pingedLanes=0),t=t.eventTimes,r=31-Vt(r),t[r]=u}function Oo(t,r){var u=t.pendingLanes&~r;t.pendingLanes=r,t.suspendedLanes=0,t.pingedLanes=0,t.expiredLanes&=r,t.mutableReadLanes&=r,t.entangledLanes&=r,r=t.entanglements;var S=t.eventTimes;for(t=t.expirationTimes;0=Co),Lu=" ",ju=!1;function Du(t,r){switch(t){case"keyup":return cc.indexOf(r.keyCode)!==-1;case"keydown":return r.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Bu(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Hr=!1;function dc(t,r){switch(t){case"compositionend":return Bu(r);case"keypress":return r.which!==32?null:(ju=!0,Lu);case"textInput":return t=r.data,t===Lu&&ju?null:t;default:return null}}function vc(t,r){if(Hr)return t==="compositionend"||!sa&&Du(t,r)?(t=xt(),Ln=Ot=ct=null,Hr=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(r.ctrlKey||r.altKey||r.metaKey)||r.ctrlKey&&r.altKey){if(r.char&&1=r)return{node:u,offset:r-t};t=S}e:{for(;u;){if(u.nextSibling){u=u.nextSibling;break e}u=u.parentNode}u=void 0}u=zu(u)}}function Yu(t,r){return t&&r?t===r?!0:t&&t.nodeType===3?!1:r&&r.nodeType===3?Yu(t,r.parentNode):"contains"in t?t.contains(r):t.compareDocumentPosition?!!(t.compareDocumentPosition(r)&16):!1:!1}function Hu(){for(var t=window,r=Re();r instanceof t.HTMLIFrameElement;){try{var u=typeof r.contentWindow.location.href=="string"}catch(S){u=!1}if(u)t=r.contentWindow;else break;r=Re(t.document)}return r}function fa(t){var r=t&&t.nodeName&&t.nodeName.toLowerCase();return r&&(r==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||r==="textarea"||t.contentEditable==="true")}function Oc(t){var r=Hu(),u=t.focusedElem,S=t.selectionRange;if(r!==u&&u&&u.ownerDocument&&Yu(u.ownerDocument.documentElement,u)){if(S!==null&&fa(u)){if(r=S.start,t=S.end,t===void 0&&(t=r),"selectionStart"in u)u.selectionStart=r,u.selectionEnd=Math.min(t,u.value.length);else if(t=(r=u.ownerDocument||document)&&r.defaultView||window,t.getSelection){t=t.getSelection();var A=u.textContent.length,L=Math.min(S.start,A);S=S.end===void 0?L:Math.min(S.end,A),!t.extend&&L>S&&(A=S,S=L,L=A),A=$u(u,L);var K=$u(u,S);A&&K&&(t.rangeCount!==1||t.anchorNode!==A.node||t.anchorOffset!==A.offset||t.focusNode!==K.node||t.focusOffset!==K.offset)&&(r=r.createRange(),r.setStart(A.node,A.offset),t.removeAllRanges(),L>S?(t.addRange(r),t.extend(K.node,K.offset)):(r.setEnd(K.node,K.offset),t.addRange(r)))}}for(r=[],t=u;t=t.parentNode;)t.nodeType===1&&r.push({element:t,left:t.scrollLeft,top:t.scrollTop});for(typeof u.focus=="function"&&u.focus(),u=0;u=document.documentMode,Vr=null,da=null,Ro=null,va=!1;function Vu(t,r,u){var S=u.window===u?u.document:u.nodeType===9?u:u.ownerDocument;va||Vr==null||Vr!==Re(S)||(S=Vr,"selectionStart"in S&&fa(S)?S={start:S.selectionStart,end:S.selectionEnd}:(S=(S.ownerDocument&&S.ownerDocument.defaultView||window).getSelection(),S={anchorNode:S.anchorNode,anchorOffset:S.anchorOffset,focusNode:S.focusNode,focusOffset:S.focusOffset}),Ro&&Mo(Ro,S)||(Ro=S,S=vi(da,"onSelect"),0_r||(t.current=wa[_r],wa[_r]=null,_r--)}function lt(t,r){_r++,wa[_r]=t.current,t.current=r}var or={},Dt=rr(or),Kt=rr(!1),wr=or;function qr(t,r){var u=t.type.contextTypes;if(!u)return or;var S=t.stateNode;if(S&&S.__reactInternalMemoizedUnmaskedChildContext===r)return S.__reactInternalMemoizedMaskedChildContext;var A={},L;for(L in u)A[L]=r[L];return S&&(t=t.stateNode,t.__reactInternalMemoizedUnmaskedChildContext=r,t.__reactInternalMemoizedMaskedChildContext=A),A}function Wt(t){return t=t.childContextTypes,t!=null}function mi(){dt(Kt),dt(Dt)}function ss(t,r,u){if(Dt.current!==or)throw Error(a(168));lt(Dt,r),lt(Kt,u)}function ls(t,r,u){var S=t.stateNode;if(r=r.childContextTypes,typeof S.getChildContext!="function")return u;S=S.getChildContext();for(var A in S)if(!(A in r))throw Error(a(108,_(t)||"Unknown",A));return W({},u,S)}function yi(t){return t=(t=t.stateNode)&&t.__reactInternalMemoizedMergedChildContext||or,wr=Dt.current,lt(Dt,t),lt(Kt,Kt.current),!0}function cs(t,r,u){var S=t.stateNode;if(!S)throw Error(a(169));u?(t=ls(t,r,wr),S.__reactInternalMemoizedMergedChildContext=t,dt(Kt),dt(Dt),lt(Dt,t)):dt(Kt),lt(Kt,u)}var Dn=null,Si=!1,Ca=!1;function fs(t){Dn===null?Dn=[t]:Dn.push(t)}function jc(t){Si=!0,fs(t)}function ir(){if(!Ca&&Dn!==null){Ca=!0;var t=0,r=it;try{var u=Dn;for(it=1;t>=K,A-=K,Bn=1<<32-Vt(r)+A|u<_e?(Rt=Je,Je=null):Rt=Je.sibling;var ot=be(me,Je,xe[_e],Fe);if(ot===null){Je===null&&(Je=Rt);break}t&&Je&&ot.alternate===null&&r(me,Je),ve=L(ot,ve,_e),Ze===null?Qe=ot:Ze.sibling=ot,Ze=ot,Je=Rt}if(_e===xe.length)return u(me,Je),gt&&Pr(me,_e),Qe;if(Je===null){for(;_e_e?(Rt=Je,Je=null):Rt=Je.sibling;var hr=be(me,Je,ot.value,Fe);if(hr===null){Je===null&&(Je=Rt);break}t&&Je&&hr.alternate===null&&r(me,Je),ve=L(hr,ve,_e),Ze===null?Qe=hr:Ze.sibling=hr,Ze=hr,Je=Rt}if(ot.done)return u(me,Je),gt&&Pr(me,_e),Qe;if(Je===null){for(;!ot.done;_e++,ot=xe.next())ot=Le(me,ot.value,Fe),ot!==null&&(ve=L(ot,ve,_e),Ze===null?Qe=ot:Ze.sibling=ot,Ze=ot);return gt&&Pr(me,_e),Qe}for(Je=S(me,Je);!ot.done;_e++,ot=xe.next())ot=We(Je,me,_e,ot.value,Fe),ot!==null&&(t&&ot.alternate!==null&&Je.delete(ot.key===null?_e:ot.key),ve=L(ot,ve,_e),Ze===null?Qe=ot:Ze.sibling=ot,Ze=ot);return t&&Je.forEach(function(gf){return r(me,gf)}),gt&&Pr(me,_e),Qe}function It(me,ve,xe,Fe){if(typeof xe=="object"&&xe!==null&&xe.type===b&&xe.key===null&&(xe=xe.props.children),typeof xe=="object"&&xe!==null){switch(xe.$$typeof){case I:e:{for(var Qe=xe.key,Ze=ve;Ze!==null;){if(Ze.key===Qe){if(Qe=xe.type,Qe===b){if(Ze.tag===7){u(me,Ze.sibling),ve=A(Ze,xe.props.children),ve.return=me,me=ve;break e}}else if(Ze.elementType===Qe||typeof Qe=="object"&&Qe!==null&&Qe.$$typeof===F&&ws(Qe)===Ze.type){u(me,Ze.sibling),ve=A(Ze,xe.props),ve.ref=Bo(me,Ze,xe),ve.return=me,me=ve;break e}u(me,Ze);break}else r(me,Ze);Ze=Ze.sibling}xe.type===b?(ve=Dr(xe.props.children,me.mode,Fe,xe.key),ve.return=me,me=ve):(Fe=Vi(xe.type,xe.key,xe.props,null,me.mode,Fe),Fe.ref=Bo(me,ve,xe),Fe.return=me,me=Fe)}return K(me);case P:e:{for(Ze=xe.key;ve!==null;){if(ve.key===Ze)if(ve.tag===4&&ve.stateNode.containerInfo===xe.containerInfo&&ve.stateNode.implementation===xe.implementation){u(me,ve.sibling),ve=A(ve,xe.children||[]),ve.return=me,me=ve;break e}else{u(me,ve);break}else r(me,ve);ve=ve.sibling}ve=xu(xe,me.mode,Fe),ve.return=me,me=ve}return K(me);case F:return Ze=xe._init,It(me,ve,Ze(xe._payload),Fe)}if(re(xe))return He(me,ve,xe,Fe);if(U(xe))return Ve(me,ve,xe,Fe);Ai(me,xe)}return typeof xe=="string"&&xe!==""||typeof xe=="number"?(xe=""+xe,ve!==null&&ve.tag===6?(u(me,ve.sibling),ve=A(ve,xe),ve.return=me,me=ve):(u(me,ve),ve=Ou(xe,me.mode,Fe),ve.return=me,me=ve),K(me)):u(me,ve)}return It}var io=Cs(!0),Ps=Cs(!1),Fo={},wn=rr(Fo),ko=rr(Fo),Uo=rr(Fo);function Mr(t){if(t===Fo)throw Error(a(174));return t}function Ga(t,r){switch(lt(Uo,r),lt(ko,t),lt(wn,Fo),t=r.nodeType,t){case 9:case 11:r=(r=r.documentElement)?r.namespaceURI:Me(null,"");break;default:t=t===8?r.parentNode:r,r=t.namespaceURI||null,t=t.tagName,r=Me(r,t)}dt(wn),lt(wn,r)}function ao(){dt(wn),dt(ko),dt(Uo)}function As(t){Mr(Uo.current);var r=Mr(wn.current),u=Me(r,t.type);r!==u&&(lt(ko,t),lt(wn,u))}function Ka(t){ko.current===t&&(dt(wn),dt(ko))}var pt=rr(0);function Mi(t){for(var r=t;r!==null;){if(r.tag===13){var u=r.memoizedState;if(u!==null&&(u=u.dehydrated,u===null||u.data==="$?"||u.data==="$!"))return r}else if(r.tag===19&&r.memoizedProps.revealOrder!==void 0){if(r.flags&128)return r}else if(r.child!==null){r.child.return=r,r=r.child;continue}if(r===t)break;for(;r.sibling===null;){if(r.return===null||r.return===t)return null;r=r.return}r.sibling.return=r.return,r=r.sibling}return null}var Wa=[];function za(){for(var t=0;tu?u:4,t(!0);var S=$a.transition;$a.transition={};try{t(!1),r()}finally{it=u,$a.transition=S}}function Hs(){return on().memoizedState}function kc(t,r,u){var S=fr(t);if(u={lane:S,action:u,hasEagerState:!1,eagerState:null,next:null},Vs(t))Qs(r,u);else if(u=ms(t,r,u,S),u!==null){var A=Gt();yn(u,t,S,A),Xs(u,r,S)}}function Uc(t,r,u){var S=fr(t),A={lane:S,action:u,hasEagerState:!1,eagerState:null,next:null};if(Vs(t))Qs(r,A);else{var L=t.alternate;if(t.lanes===0&&(L===null||L.lanes===0)&&(L=r.lastRenderedReducer,L!==null))try{var K=r.lastRenderedState,Q=L(K,u);if(A.hasEagerState=!0,A.eagerState=Q,vn(Q,K)){var de=r.interleaved;de===null?(A.next=A,Ba(r)):(A.next=de.next,de.next=A),r.interleaved=A;return}}catch(Ie){}finally{}u=ms(t,r,A,S),u!==null&&(A=Gt(),yn(u,t,S,A),Xs(u,r,S))}}function Vs(t){var r=t.alternate;return t===mt||r!==null&&r===mt}function Qs(t,r){Go=Ni=!0;var u=t.pending;u===null?r.next=r:(r.next=u.next,u.next=r),t.pending=r}function Xs(t,r,u){if(u&4194240){var S=r.lanes;S&=t.pendingLanes,u|=S,r.lanes=u,Or(t,u)}}var ji={readContext:rn,useCallback:Bt,useContext:Bt,useEffect:Bt,useImperativeHandle:Bt,useInsertionEffect:Bt,useLayoutEffect:Bt,useMemo:Bt,useReducer:Bt,useRef:Bt,useState:Bt,useDebugValue:Bt,useDeferredValue:Bt,useTransition:Bt,useMutableSource:Bt,useSyncExternalStore:Bt,useId:Bt,unstable_isNewReconciler:!1},Gc={readContext:rn,useCallback:function(){function t(r,u){return Cn().memoizedState=[r,u===void 0?null:u],r}return t}(),useContext:rn,useEffect:ks,useImperativeHandle:function(){function t(r,u,S){return S=S!=null?S.concat([r]):null,bi(4194308,4,Ks.bind(null,u,r),S)}return t}(),useLayoutEffect:function(){function t(r,u){return bi(4194308,4,r,u)}return t}(),useInsertionEffect:function(){function t(r,u){return bi(4,2,r,u)}return t}(),useMemo:function(){function t(r,u){var S=Cn();return u=u===void 0?null:u,r=r(),S.memoizedState=[r,u],r}return t}(),useReducer:function(){function t(r,u,S){var A=Cn();return u=S!==void 0?S(u):u,A.memoizedState=A.baseState=u,r={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:r,lastRenderedState:u},A.queue=r,r=r.dispatch=kc.bind(null,mt,r),[A.memoizedState,r]}return t}(),useRef:function(){function t(r){var u=Cn();return r={current:r},u.memoizedState=r}return t}(),useState:Bs,useDebugValue:Ja,useDeferredValue:function(){function t(r){return Cn().memoizedState=r}return t}(),useTransition:function(){function t(){var r=Bs(!1),u=r[0];return r=Fc.bind(null,r[1]),Cn().memoizedState=r,[u,r]}return t}(),useMutableSource:function(){function t(){}return t}(),useSyncExternalStore:function(){function t(r,u,S){var A=mt,L=Cn();if(gt){if(S===void 0)throw Error(a(407));S=S()}else{if(S=u(),Mt===null)throw Error(a(349));Rr&30||Ns(A,u,S)}L.memoizedState=S;var K={value:S,getSnapshot:u};return L.queue=K,ks(Ls.bind(null,A,K,r),[r]),A.flags|=2048,zo(9,bs.bind(null,A,K,S,u),void 0,null),S}return t}(),useId:function(){function t(){var r=Cn(),u=Mt.identifierPrefix;if(gt){var S=Fn,A=Bn;S=(A&~(1<<32-Vt(A)-1)).toString(32)+S,u=":"+u+"R"+S,S=Ko++,0<\/script>",t=t.removeChild(t.firstChild)):typeof S.is=="string"?t=K.createElement(u,{is:S.is}):(t=K.createElement(u),u==="select"&&(K=t,S.multiple?K.multiple=!0:S.size&&(K.size=S.size))):t=K.createElementNS(t,u),t[In]=r,t[jo]=S,dl(t,r,!1,!1),r.stateNode=t;e:{switch(K=Ue(u,S),u){case"dialog":ft("cancel",t),ft("close",t),A=S;break;case"iframe":case"object":case"embed":ft("load",t),A=S;break;case"video":case"audio":for(A=0;Aco&&(r.flags|=128,S=!0,$o(L,!1),r.lanes=4194304)}else{if(!S)if(t=Mi(K),t!==null){if(r.flags|=128,S=!0,u=t.updateQueue,u!==null&&(r.updateQueue=u,r.flags|=4),$o(L,!0),L.tail===null&&L.tailMode==="hidden"&&!K.alternate&&!gt)return Ft(r),null}else 2*ht()-L.renderingStartTime>co&&u!==1073741824&&(r.flags|=128,S=!0,$o(L,!1),r.lanes=4194304);L.isBackwards?(K.sibling=r.child,r.child=K):(u=L.last,u!==null?u.sibling=K:r.child=K,L.last=K)}return L.tail!==null?(r=L.tail,L.rendering=r,L.tail=r.sibling,L.renderingStartTime=ht(),r.sibling=null,u=pt.current,lt(pt,S?u&1|2:u&1),r):(Ft(r),null);case 22:case 23:return Su(),S=r.memoizedState!==null,t!==null&&t.memoizedState!==null!==S&&(r.flags|=8192),S&&r.mode&1?_t&1073741824&&(Ft(r),r.subtreeFlags&6&&(r.flags|=8192)):Ft(r),null;case 24:return null;case 25:return null}throw Error(a(156,r.tag))}function Qc(t,r){switch(Aa(r),r.tag){case 1:return Wt(r.type)&&mi(),t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 3:return ao(),dt(Kt),dt(Dt),za(),t=r.flags,t&65536&&!(t&128)?(r.flags=t&-65537|128,r):null;case 5:return Ka(r),null;case 13:if(dt(pt),t=r.memoizedState,t!==null&&t.dehydrated!==null){if(r.alternate===null)throw Error(a(340));no()}return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 19:return dt(pt),null;case 4:return ao(),null;case 10:return ja(r.type._context),null;case 22:case 23:return Su(),null;case 24:return null;default:return null}}var Fi=!1,kt=!1,Xc=typeof WeakSet=="function"?WeakSet:Set,$e=null;function so(t,r){var u=t.ref;if(u!==null)if(typeof u=="function")try{u(null)}catch(S){St(t,r,S)}else u.current=null}function uu(t,r,u){try{u()}catch(S){St(t,r,S)}}var gl=!1;function Zc(t,r){if(Sa=$r,t=Hu(),fa(t)){if("selectionStart"in t)var u={start:t.selectionStart,end:t.selectionEnd};else e:{u=(u=t.ownerDocument)&&u.defaultView||window;var S=u.getSelection&&u.getSelection();if(S&&S.rangeCount!==0){u=S.anchorNode;var A=S.anchorOffset,L=S.focusNode;S=S.focusOffset;try{u.nodeType,L.nodeType}catch(Fe){u=null;break e}var K=0,Q=-1,de=-1,Ie=0,Pe=0,Le=t,be=null;t:for(;;){for(var We;Le!==u||A!==0&&Le.nodeType!==3||(Q=K+A),Le!==L||S!==0&&Le.nodeType!==3||(de=K+S),Le.nodeType===3&&(K+=Le.nodeValue.length),(We=Le.firstChild)!==null;)be=Le,Le=We;for(;;){if(Le===t)break t;if(be===u&&++Ie===A&&(Q=K),be===L&&++Pe===S&&(de=K),(We=Le.nextSibling)!==null)break;Le=be,be=Le.parentNode}Le=We}u=Q===-1||de===-1?null:{start:Q,end:de}}else u=null}u=u||{start:0,end:0}}else u=null;for(Ea={focusedElem:t,selectionRange:u},$r=!1,$e=r;$e!==null;)if(r=$e,t=r.child,(r.subtreeFlags&1028)!==0&&t!==null)t.return=r,$e=t;else for(;$e!==null;){r=$e;try{var He=r.alternate;if(r.flags&1024)switch(r.tag){case 0:case 11:case 15:break;case 1:if(He!==null){var Ve=He.memoizedProps,It=He.memoizedState,me=r.stateNode,ve=me.getSnapshotBeforeUpdate(r.elementType===r.type?Ve:gn(r.type,Ve),It);me.__reactInternalSnapshotBeforeUpdate=ve}break;case 3:var xe=r.stateNode.containerInfo;xe.nodeType===1?xe.textContent="":xe.nodeType===9&&xe.documentElement&&xe.removeChild(xe.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(a(163))}}catch(Fe){St(r,r.return,Fe)}if(t=r.sibling,t!==null){t.return=r.return,$e=t;break}$e=r.return}return He=gl,gl=!1,He}function Yo(t,r,u){var S=r.updateQueue;if(S=S!==null?S.lastEffect:null,S!==null){var A=S=S.next;do{if((A.tag&t)===t){var L=A.destroy;A.destroy=void 0,L!==void 0&&uu(r,u,L)}A=A.next}while(A!==S)}}function ki(t,r){if(r=r.updateQueue,r=r!==null?r.lastEffect:null,r!==null){var u=r=r.next;do{if((u.tag&t)===t){var S=u.create;u.destroy=S()}u=u.next}while(u!==r)}}function su(t){var r=t.ref;if(r!==null){var u=t.stateNode;switch(t.tag){case 5:t=u;break;default:t=u}typeof r=="function"?r(t):r.current=t}}function pl(t){var r=t.alternate;r!==null&&(t.alternate=null,pl(r)),t.child=null,t.deletions=null,t.sibling=null,t.tag===5&&(r=t.stateNode,r!==null&&(delete r[In],delete r[jo],delete r[Ia],delete r[bc],delete r[Lc])),t.stateNode=null,t.return=null,t.dependencies=null,t.memoizedProps=null,t.memoizedState=null,t.pendingProps=null,t.stateNode=null,t.updateQueue=null}function ml(t){return t.tag===5||t.tag===3||t.tag===4}function yl(t){e:for(;;){for(;t.sibling===null;){if(t.return===null||ml(t.return))return null;t=t.return}for(t.sibling.return=t.return,t=t.sibling;t.tag!==5&&t.tag!==6&&t.tag!==18;){if(t.flags&2||t.child===null||t.tag===4)continue e;t.child.return=t,t=t.child}if(!(t.flags&2))return t.stateNode}}function lu(t,r,u){var S=t.tag;if(S===5||S===6)t=t.stateNode,r?u.nodeType===8?u.parentNode.insertBefore(t,r):u.insertBefore(t,r):(u.nodeType===8?(r=u.parentNode,r.insertBefore(t,u)):(r=u,r.appendChild(t)),u=u._reactRootContainer,u!=null||r.onclick!==null||(r.onclick=gi));else if(S!==4&&(t=t.child,t!==null))for(lu(t,r,u),t=t.sibling;t!==null;)lu(t,r,u),t=t.sibling}function cu(t,r,u){var S=t.tag;if(S===5||S===6)t=t.stateNode,r?u.insertBefore(t,r):u.appendChild(t);else if(S!==4&&(t=t.child,t!==null))for(cu(t,r,u),t=t.sibling;t!==null;)cu(t,r,u),t=t.sibling}var bt=null,pn=!1;function sr(t,r,u){for(u=u.child;u!==null;)Sl(t,r,u),u=u.sibling}function Sl(t,r,u){if(Ht&&typeof Ht.onCommitFiberUnmount=="function")try{Ht.onCommitFiberUnmount(Mn,u)}catch(Q){}switch(u.tag){case 5:kt||so(u,r);case 6:var S=bt,A=pn;bt=null,sr(t,r,u),bt=S,pn=A,bt!==null&&(pn?(t=bt,u=u.stateNode,t.nodeType===8?t.parentNode.removeChild(u):t.removeChild(u)):bt.removeChild(u.stateNode));break;case 18:bt!==null&&(pn?(t=bt,u=u.stateNode,t.nodeType===8?xa(t.parentNode,u):t.nodeType===1&&xa(t,u),qn(t)):xa(bt,u.stateNode));break;case 4:S=bt,A=pn,bt=u.stateNode.containerInfo,pn=!0,sr(t,r,u),bt=S,pn=A;break;case 0:case 11:case 14:case 15:if(!kt&&(S=u.updateQueue,S!==null&&(S=S.lastEffect,S!==null))){A=S=S.next;do{var L=A,K=L.destroy;L=L.tag,K!==void 0&&(L&2||L&4)&&uu(u,r,K),A=A.next}while(A!==S)}sr(t,r,u);break;case 1:if(!kt&&(so(u,r),S=u.stateNode,typeof S.componentWillUnmount=="function"))try{S.props=u.memoizedProps,S.state=u.memoizedState,S.componentWillUnmount()}catch(Q){St(u,r,Q)}sr(t,r,u);break;case 21:sr(t,r,u);break;case 22:u.mode&1?(kt=(S=kt)||u.memoizedState!==null,sr(t,r,u),kt=S):sr(t,r,u);break;default:sr(t,r,u)}}function El(t){var r=t.updateQueue;if(r!==null){t.updateQueue=null;var u=t.stateNode;u===null&&(u=t.stateNode=new Xc),r.forEach(function(S){var A=af.bind(null,t,S);u.has(S)||(u.add(S),S.then(A,A))})}}function mn(t,r){var u=r.deletions;if(u!==null)for(var S=0;SA&&(A=K),S&=~L}if(S=A,S=ht()-S,S=(120>S?120:480>S?480:1080>S?1080:1920>S?1920:3e3>S?3e3:4320>S?4320:1960*_c(S/1960))-S,10t?16:t,cr===null)var S=!1;else{if(t=cr,cr=null,zi=0,rt&6)throw Error(a(331));var A=rt;for(rt|=4,$e=t.current;$e!==null;){var L=$e,K=L.child;if($e.flags&16){var Q=L.deletions;if(Q!==null){for(var de=0;deht()-vu?Lr(t,0):du|=u),Yt(t,r)}function Ll(t,r){r===0&&(t.mode&1?(r=Sr,Sr<<=1,!(Sr&130023424)&&(Sr=4194304)):r=1);var u=Gt();t=kn(t,r),t!==null&&(qt(t,r,u),Yt(t,u))}function of(t){var r=t.memoizedState,u=0;r!==null&&(u=r.retryLane),Ll(t,u)}function af(t,r){var u=0;switch(t.tag){case 13:var S=t.stateNode,A=t.memoizedState;A!==null&&(u=A.retryLane);break;case 19:S=t.stateNode;break;default:throw Error(a(314))}S!==null&&S.delete(r),Ll(t,u)}var jl;jl=function(r,u,S){if(r!==null)if(r.memoizedProps!==u.pendingProps||Kt.current)zt=!0;else{if(!(r.lanes&S)&&!(u.flags&128))return zt=!1,Hc(r,u,S);zt=!!(r.flags&131072)}else zt=!1,gt&&u.flags&1048576&&ds(u,Ti,u.index);switch(u.lanes=0,u.tag){case 2:var A=u.type;Bi(r,u),r=u.pendingProps;var L=qr(u,Dt.current);oo(u,S),L=Ha(null,u,A,r,L,S);var K=Va();return u.flags|=1,typeof L=="object"&&L!==null&&typeof L.render=="function"&&L.$$typeof===void 0?(u.tag=1,u.memoizedState=null,u.updateQueue=null,Wt(A)?(K=!0,yi(u)):K=!1,u.memoizedState=L.state!==null&&L.state!==void 0?L.state:null,Fa(u),L.updater=Pi,u.stateNode=L,L._reactInternals=u,Ua(u,A,r,S),u=tu(null,u,A,!0,K,S)):(u.tag=0,gt&&K&&Pa(u),Ut(null,u,L,S),u=u.child),u;case 16:A=u.elementType;e:{switch(Bi(r,u),r=u.pendingProps,L=A._init,A=L(A._payload),u.type=A,L=u.tag=sf(A),r=gn(A,r),L){case 0:u=eu(null,u,A,r,S);break e;case 1:u=al(null,u,A,r,S);break e;case 11:u=tl(null,u,A,r,S);break e;case 14:u=nl(null,u,A,gn(A.type,r),S);break e}throw Error(a(306,A,""))}return u;case 0:return A=u.type,L=u.pendingProps,L=u.elementType===A?L:gn(A,L),eu(r,u,A,L,S);case 1:return A=u.type,L=u.pendingProps,L=u.elementType===A?L:gn(A,L),al(r,u,A,L,S);case 3:e:{if(ul(u),r===null)throw Error(a(387));A=u.pendingProps,K=u.memoizedState,L=K.element,ys(r,u),Ci(u,A,null,S);var Q=u.memoizedState;if(A=Q.element,K.isDehydrated)if(K={element:A,isDehydrated:!1,cache:Q.cache,pendingSuspenseBoundaries:Q.pendingSuspenseBoundaries,transitions:Q.transitions},u.updateQueue.baseState=K,u.memoizedState=K,u.flags&256){L=uo(Error(a(423)),u),u=sl(r,u,A,S,L);break e}else if(A!==L){L=uo(Error(a(424)),u),u=sl(r,u,A,S,L);break e}else for(Jt=nr(u.stateNode.containerInfo.firstChild),Zt=u,gt=!0,hn=null,S=Ps(u,null,A,S),u.child=S;S;)S.flags=S.flags&-3|4096,S=S.sibling;else{if(no(),A===L){u=Gn(r,u,S);break e}Ut(r,u,A,S)}u=u.child}return u;case 5:return As(u),r===null&&Ra(u),A=u.type,L=u.pendingProps,K=r!==null?r.memoizedProps:null,Q=L.children,Ta(A,L)?Q=null:K!==null&&Ta(A,K)&&(u.flags|=32),il(r,u),Ut(r,u,Q,S),u.child;case 6:return r===null&&Ra(u),null;case 13:return ll(r,u,S);case 4:return Ga(u,u.stateNode.containerInfo),A=u.pendingProps,r===null?u.child=io(u,null,A,S):Ut(r,u,A,S),u.child;case 11:return A=u.type,L=u.pendingProps,L=u.elementType===A?L:gn(A,L),tl(r,u,A,L,S);case 7:return Ut(r,u,u.pendingProps,S),u.child;case 8:return Ut(r,u,u.pendingProps.children,S),u.child;case 12:return Ut(r,u,u.pendingProps.children,S),u.child;case 10:e:{if(A=u.type._context,L=u.pendingProps,K=u.memoizedProps,Q=L.value,lt(xi,A._currentValue),A._currentValue=Q,K!==null)if(vn(K.value,Q)){if(K.children===L.children&&!Kt.current){u=Gn(r,u,S);break e}}else for(K=u.child,K!==null&&(K.return=u);K!==null;){var de=K.dependencies;if(de!==null){Q=K.child;for(var Ie=de.firstContext;Ie!==null;){if(Ie.context===A){if(K.tag===1){Ie=Un(-1,S&-S),Ie.tag=2;var Pe=K.updateQueue;if(Pe!==null){Pe=Pe.shared;var Le=Pe.pending;Le===null?Ie.next=Ie:(Ie.next=Le.next,Le.next=Ie),Pe.pending=Ie}}K.lanes|=S,Ie=K.alternate,Ie!==null&&(Ie.lanes|=S),Da(K.return,S,u),de.lanes|=S;break}Ie=Ie.next}}else if(K.tag===10)Q=K.type===u.type?null:K.child;else if(K.tag===18){if(Q=K.return,Q===null)throw Error(a(341));Q.lanes|=S,de=Q.alternate,de!==null&&(de.lanes|=S),Da(Q,S,u),Q=K.sibling}else Q=K.child;if(Q!==null)Q.return=K;else for(Q=K;Q!==null;){if(Q===u){Q=null;break}if(K=Q.sibling,K!==null){K.return=Q.return,Q=K;break}Q=Q.return}K=Q}Ut(r,u,L.children,S),u=u.child}return u;case 9:return L=u.type,A=u.pendingProps.children,oo(u,S),L=rn(L),A=A(L),u.flags|=1,Ut(r,u,A,S),u.child;case 14:return A=u.type,L=gn(A,u.pendingProps),L=gn(A.type,L),nl(r,u,A,L,S);case 15:return rl(r,u,u.type,u.pendingProps,S);case 17:return A=u.type,L=u.pendingProps,L=u.elementType===A?L:gn(A,L),Bi(r,u),u.tag=1,Wt(A)?(r=!0,yi(u)):r=!1,oo(u,S),xs(u,A,L),Ua(u,A,L,S),tu(null,u,A,!0,r,S);case 19:return fl(r,u,S);case 22:return ol(r,u,S)}throw Error(a(156,u.tag))};function Dl(t,r){return Gr(t,r)}function uf(t,r,u,S){this.tag=t,this.key=u,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=r,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=S,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function un(t,r,u,S){return new uf(t,r,u,S)}function Tu(t){return t=t.prototype,!(!t||!t.isReactComponent)}function sf(t){if(typeof t=="function")return Tu(t)?1:0;if(t!=null){if(t=t.$$typeof,t===k)return 11;if(t===V)return 14}return 2}function vr(t,r){var u=t.alternate;return u===null?(u=un(t.tag,r,t.key,t.mode),u.elementType=t.elementType,u.type=t.type,u.stateNode=t.stateNode,u.alternate=t,t.alternate=u):(u.pendingProps=r,u.type=t.type,u.flags=0,u.subtreeFlags=0,u.deletions=null),u.flags=t.flags&14680064,u.childLanes=t.childLanes,u.lanes=t.lanes,u.child=t.child,u.memoizedProps=t.memoizedProps,u.memoizedState=t.memoizedState,u.updateQueue=t.updateQueue,r=t.dependencies,u.dependencies=r===null?null:{lanes:r.lanes,firstContext:r.firstContext},u.sibling=t.sibling,u.index=t.index,u.ref=t.ref,u}function Vi(t,r,u,S,A,L){var K=2;if(S=t,typeof t=="function")Tu(t)&&(K=1);else if(typeof t=="string")K=5;else e:switch(t){case b:return Dr(u.children,A,L,r);case N:K=8,A|=8;break;case D:return t=un(12,u,r,A|2),t.elementType=D,t.lanes=L,t;case G:return t=un(13,u,r,A),t.elementType=G,t.lanes=L,t;case z:return t=un(19,u,r,A),t.elementType=z,t.lanes=L,t;case $:return Qi(u,A,L,r);default:if(typeof t=="object"&&t!==null)switch(t.$$typeof){case j:K=10;break e;case B:K=9;break e;case k:K=11;break e;case V:K=14;break e;case F:K=16,S=null;break e}throw Error(a(130,t==null?t:typeof t,""))}return r=un(K,u,r,A),r.elementType=t,r.type=S,r.lanes=L,r}function Dr(t,r,u,S){return t=un(7,t,S,r),t.lanes=u,t}function Qi(t,r,u,S){return t=un(22,t,S,r),t.elementType=$,t.lanes=u,t.stateNode={isHidden:!1},t}function Ou(t,r,u){return t=un(6,t,null,r),t.lanes=u,t}function xu(t,r,u){return r=un(4,t.children!==null?t.children:[],t.key,r),r.lanes=u,r.stateNode={containerInfo:t.containerInfo,pendingChildren:null,implementation:t.implementation},r}function lf(t,r,u,S,A){this.tag=r,this.containerInfo=t,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Qt(0),this.expirationTimes=Qt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Qt(0),this.identifierPrefix=S,this.onRecoverableError=A,this.mutableSourceEagerHydrationData=null}function Iu(t,r,u,S,A,L,K,Q,de){return t=new lf(t,r,u,Q,de),r===1?(r=1,L===!0&&(r|=8)):r=0,L=un(3,null,null,r),t.current=L,L.stateNode=t,L.memoizedState={element:S,isDehydrated:u,cache:null,transitions:null,pendingSuspenseBoundaries:null},Fa(L),t}function cf(t,r,u){var S=30&&(0,i.round)(c.width)/f.offsetWidth||1,d=f.offsetHeight>0&&(0,i.round)(c.height)/f.offsetHeight||1);var y=(0,o.isElement)(f)?(0,a.default)(f):window,h=y.visualViewport,E=!(0,s.default)()&&g,O=(c.left+(E&&h?h.offsetLeft:0))/p,C=(c.top+(E&&h?h.offsetTop:0))/d,R=c.width/p,M=c.height/d;return{width:R,height:M,top:C,right:O+R,bottom:C+M,left:O,x:O,y:C}}},20148:function(x,n,e){"use strict";n.__esModule=!0,n.default=M;var o=e(54803),i=E(e(18872)),a=E(e(48523)),s=E(e(72476)),l=E(e(70216)),v=E(e(57544)),f=E(e(25640)),m=e(43744),g=E(e(42560)),c=E(e(35640)),p=E(e(61104)),d=E(e(70032)),y=E(e(75092)),h=e(13312);function E(w){return w&&w.__esModule?w:{default:w}}function O(w,T){var I=(0,g.default)(w,!1,T==="fixed");return I.top=I.top+w.clientTop,I.left=I.left+w.clientLeft,I.bottom=I.top+w.clientHeight,I.right=I.left+w.clientWidth,I.width=w.clientWidth,I.height=w.clientHeight,I.x=I.left,I.y=I.top,I}function C(w,T,I){return T===o.viewport?(0,y.default)((0,i.default)(w,I)):(0,m.isElement)(T)?O(T,I):(0,y.default)((0,a.default)((0,v.default)(w)))}function R(w){var T=(0,s.default)((0,c.default)(w)),I=["absolute","fixed"].indexOf((0,f.default)(w).position)>=0,P=I&&(0,m.isHTMLElement)(w)?(0,l.default)(w):w;return(0,m.isElement)(P)?T.filter(function(b){return(0,m.isElement)(b)&&(0,p.default)(b,P)&&(0,d.default)(b)!=="body"}):[]}function M(w,T,I,P){var b=T==="clippingParents"?R(w):[].concat(T),N=[].concat(b,[I]),D=N[0],j=N.reduce(function(B,k){var G=C(w,k,P);return B.top=(0,h.max)(G.top,B.top),B.right=(0,h.min)(G.right,B.right),B.bottom=(0,h.min)(G.bottom,B.bottom),B.left=(0,h.max)(G.left,B.left),B},C(w,D,P));return j.width=j.right-j.left,j.height=j.bottom-j.top,j.x=j.left,j.y=j.top,j}},70275:function(x,n,e){"use strict";n.__esModule=!0,n.default=p;var o=g(e(42560)),i=g(e(76112)),a=g(e(70032)),s=e(43744),l=g(e(37040)),v=g(e(57544)),f=g(e(90600)),m=e(13312);function g(d){return d&&d.__esModule?d:{default:d}}function c(d){var y=d.getBoundingClientRect(),h=(0,m.round)(y.width)/d.offsetWidth||1,E=(0,m.round)(y.height)/d.offsetHeight||1;return h!==1||E!==1}function p(d,y,h){h===void 0&&(h=!1);var E=(0,s.isHTMLElement)(y),O=(0,s.isHTMLElement)(y)&&c(y),C=(0,v.default)(y),R=(0,o.default)(d,O,h),M={scrollLeft:0,scrollTop:0},w={x:0,y:0};return(E||!E&&!h)&&(((0,a.default)(y)!=="body"||(0,f.default)(C))&&(M=(0,i.default)(y)),(0,s.isHTMLElement)(y)?(w=(0,o.default)(y,!0),w.x+=y.clientLeft,w.y+=y.clientTop):C&&(w.x=(0,l.default)(C))),{x:R.left+M.scrollLeft-w.x,y:R.top+M.scrollTop-w.y,width:R.width,height:R.height}}},25640:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(67652));function i(s){return s&&s.__esModule?s:{default:s}}function a(s){return(0,o.default)(s).getComputedStyle(s)}},57544:function(x,n,e){"use strict";n.__esModule=!0,n.default=i;var o=e(43744);function i(a){return(((0,o.isElement)(a)?a.ownerDocument:a.document)||window.document).documentElement}},48523:function(x,n,e){"use strict";n.__esModule=!0,n.default=f;var o=v(e(57544)),i=v(e(25640)),a=v(e(37040)),s=v(e(49988)),l=e(13312);function v(m){return m&&m.__esModule?m:{default:m}}function f(m){var g,c=(0,o.default)(m),p=(0,s.default)(m),d=(g=m.ownerDocument)==null?void 0:g.body,y=(0,l.max)(c.scrollWidth,c.clientWidth,d?d.scrollWidth:0,d?d.clientWidth:0),h=(0,l.max)(c.scrollHeight,c.clientHeight,d?d.scrollHeight:0,d?d.clientHeight:0),E=-p.scrollLeft+(0,a.default)(m),O=-p.scrollTop;return(0,i.default)(d||c).direction==="rtl"&&(E+=(0,l.max)(c.clientWidth,d?d.clientWidth:0)-y),{width:y,height:h,x:E,y:O}}},58080:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){return{scrollLeft:o.scrollLeft,scrollTop:o.scrollTop}}},2696:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(42560));function i(s){return s&&s.__esModule?s:{default:s}}function a(s){var l=(0,o.default)(s),v=s.offsetWidth,f=s.offsetHeight;return Math.abs(l.width-v)<=1&&(v=l.width),Math.abs(l.height-f)<=1&&(f=l.height),{x:s.offsetLeft,y:s.offsetTop,width:v,height:f}}},70032:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){return o?(o.nodeName||"").toLowerCase():null}},76112:function(x,n,e){"use strict";n.__esModule=!0,n.default=v;var o=l(e(49988)),i=l(e(67652)),a=e(43744),s=l(e(58080));function l(f){return f&&f.__esModule?f:{default:f}}function v(f){return f===(0,i.default)(f)||!(0,a.isHTMLElement)(f)?(0,o.default)(f):(0,s.default)(f)}},70216:function(x,n,e){"use strict";n.__esModule=!0,n.default=p;var o=m(e(67652)),i=m(e(70032)),a=m(e(25640)),s=e(43744),l=m(e(73028)),v=m(e(35640)),f=m(e(49856));function m(d){return d&&d.__esModule?d:{default:d}}function g(d){return!(0,s.isHTMLElement)(d)||(0,a.default)(d).position==="fixed"?null:d.offsetParent}function c(d){var y=/firefox/i.test((0,f.default)()),h=/Trident/i.test((0,f.default)());if(h&&(0,s.isHTMLElement)(d)){var E=(0,a.default)(d);if(E.position==="fixed")return null}var O=(0,v.default)(d);for((0,s.isShadowRoot)(O)&&(O=O.host);(0,s.isHTMLElement)(O)&&["html","body"].indexOf((0,i.default)(O))<0;){var C=(0,a.default)(O);if(C.transform!=="none"||C.perspective!=="none"||C.contain==="paint"||["transform","perspective"].indexOf(C.willChange)!==-1||y&&C.willChange==="filter"||y&&C.filter&&C.filter!=="none")return O;O=O.parentNode}return null}function p(d){for(var y=(0,o.default)(d),h=g(d);h&&(0,l.default)(h)&&(0,a.default)(h).position==="static";)h=g(h);return h&&((0,i.default)(h)==="html"||(0,i.default)(h)==="body"&&(0,a.default)(h).position==="static")?y:h||c(d)||y}},35640:function(x,n,e){"use strict";n.__esModule=!0,n.default=l;var o=s(e(70032)),i=s(e(57544)),a=e(43744);function s(v){return v&&v.__esModule?v:{default:v}}function l(v){return(0,o.default)(v)==="html"?v:v.assignedSlot||v.parentNode||((0,a.isShadowRoot)(v)?v.host:null)||(0,i.default)(v)}},54828:function(x,n,e){"use strict";n.__esModule=!0,n.default=v;var o=l(e(35640)),i=l(e(90600)),a=l(e(70032)),s=e(43744);function l(f){return f&&f.__esModule?f:{default:f}}function v(f){return["html","body","#document"].indexOf((0,a.default)(f))>=0?f.ownerDocument.body:(0,s.isHTMLElement)(f)&&(0,i.default)(f)?f:v((0,o.default)(f))}},18872:function(x,n,e){"use strict";n.__esModule=!0,n.default=v;var o=l(e(67652)),i=l(e(57544)),a=l(e(37040)),s=l(e(14092));function l(f){return f&&f.__esModule?f:{default:f}}function v(f,m){var g=(0,o.default)(f),c=(0,i.default)(f),p=g.visualViewport,d=c.clientWidth,y=c.clientHeight,h=0,E=0;if(p){d=p.width,y=p.height;var O=(0,s.default)();(O||!O&&m==="fixed")&&(h=p.offsetLeft,E=p.offsetTop)}return{width:d,height:y,x:h+(0,a.default)(f),y:E}}},67652:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){if(o==null)return window;if(o.toString()!=="[object Window]"){var i=o.ownerDocument;return i&&i.defaultView||window}return o}},49988:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(67652));function i(s){return s&&s.__esModule?s:{default:s}}function a(s){var l=(0,o.default)(s),v=l.pageXOffset,f=l.pageYOffset;return{scrollLeft:v,scrollTop:f}}},37040:function(x,n,e){"use strict";n.__esModule=!0,n.default=l;var o=s(e(42560)),i=s(e(57544)),a=s(e(49988));function s(v){return v&&v.__esModule?v:{default:v}}function l(v){return(0,o.default)((0,i.default)(v)).left+(0,a.default)(v).scrollLeft}},43744:function(x,n,e){"use strict";n.__esModule=!0,n.isElement=a,n.isHTMLElement=s,n.isShadowRoot=l;var o=i(e(67652));function i(v){return v&&v.__esModule?v:{default:v}}function a(v){var f=(0,o.default)(v).Element;return v instanceof f||v instanceof Element}function s(v){var f=(0,o.default)(v).HTMLElement;return v instanceof f||v instanceof HTMLElement}function l(v){if(typeof ShadowRoot=="undefined")return!1;var f=(0,o.default)(v).ShadowRoot;return v instanceof f||v instanceof ShadowRoot}},14092:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(49856));function i(s){return s&&s.__esModule?s:{default:s}}function a(){return!/^((?!chrome|android).)*safari/i.test((0,o.default)())}},90600:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(25640));function i(s){return s&&s.__esModule?s:{default:s}}function a(s){var l=(0,o.default)(s),v=l.overflow,f=l.overflowX,m=l.overflowY;return/auto|scroll|overlay|hidden/.test(v+m+f)}},73028:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(70032));function i(s){return s&&s.__esModule?s:{default:s}}function a(s){return["table","td","th"].indexOf((0,o.default)(s))>=0}},72476:function(x,n,e){"use strict";n.__esModule=!0,n.default=v;var o=l(e(54828)),i=l(e(35640)),a=l(e(67652)),s=l(e(90600));function l(f){return f&&f.__esModule?f:{default:f}}function v(f,m){var g;m===void 0&&(m=[]);var c=(0,o.default)(f),p=c===((g=f.ownerDocument)==null?void 0:g.body),d=(0,a.default)(c),y=p?[d].concat(d.visualViewport||[],(0,s.default)(c)?c:[]):c,h=m.concat(y);return p?h:h.concat(v((0,i.default)(y)))}},54803:function(x,n){"use strict";n.__esModule=!0,n.write=n.viewport=n.variationPlacements=n.top=n.start=n.right=n.reference=n.read=n.popper=n.placements=n.modifierPhases=n.main=n.left=n.end=n.clippingParents=n.bottom=n.beforeWrite=n.beforeRead=n.beforeMain=n.basePlacements=n.auto=n.afterWrite=n.afterRead=n.afterMain=void 0;var e=n.top="top",o=n.bottom="bottom",i=n.right="right",a=n.left="left",s=n.auto="auto",l=n.basePlacements=[e,o,i,a],v=n.start="start",f=n.end="end",m=n.clippingParents="clippingParents",g=n.viewport="viewport",c=n.popper="popper",p=n.reference="reference",d=n.variationPlacements=l.reduce(function(b,N){return b.concat([N+"-"+v,N+"-"+f])},[]),y=n.placements=[].concat(l,[s]).reduce(function(b,N){return b.concat([N,N+"-"+v,N+"-"+f])},[]),h=n.beforeRead="beforeRead",E=n.read="read",O=n.afterRead="afterRead",C=n.beforeMain="beforeMain",R=n.main="main",M=n.afterMain="afterMain",w=n.beforeWrite="beforeWrite",T=n.write="write",I=n.afterWrite="afterWrite",P=n.modifierPhases=[h,E,O,C,R,M,w,T,I]},31955:function(x,n,e){"use strict";n.__esModule=!0;var o={popperGenerator:!0,detectOverflow:!0,createPopperBase:!0,createPopper:!0,createPopperLite:!0};n.popperGenerator=n.detectOverflow=n.createPopperLite=n.createPopperBase=n.createPopper=void 0;var i=e(54803);Object.keys(i).forEach(function(f){f==="default"||f==="__esModule"||Object.prototype.hasOwnProperty.call(o,f)||f in n&&n[f]===i[f]||(n[f]=i[f])});var a=e(85640);Object.keys(a).forEach(function(f){f==="default"||f==="__esModule"||Object.prototype.hasOwnProperty.call(o,f)||f in n&&n[f]===a[f]||(n[f]=a[f])});var s=e(43128);n.popperGenerator=s.popperGenerator,n.detectOverflow=s.detectOverflow,n.createPopperBase=s.createPopper;var l=e(84160);n.createPopper=l.createPopper;var v=e(29120);n.createPopperLite=v.createPopper},42516:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=a(e(70032)),i=e(43744);function a(f){return f&&f.__esModule?f:{default:f}}function s(f){var m=f.state;Object.keys(m.elements).forEach(function(g){var c=m.styles[g]||{},p=m.attributes[g]||{},d=m.elements[g];!(0,i.isHTMLElement)(d)||!(0,o.default)(d)||(Object.assign(d.style,c),Object.keys(p).forEach(function(y){var h=p[y];h===!1?d.removeAttribute(y):d.setAttribute(y,h===!0?"":h)}))})}function l(f){var m=f.state,g={popper:{position:m.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(m.elements.popper.style,g.popper),m.styles=g,m.elements.arrow&&Object.assign(m.elements.arrow.style,g.arrow),function(){Object.keys(m.elements).forEach(function(c){var p=m.elements[c],d=m.attributes[c]||{},y=Object.keys(m.styles.hasOwnProperty(c)?m.styles[c]:g[c]),h=y.reduce(function(E,O){return E[O]="",E},{});!(0,i.isHTMLElement)(p)||!(0,o.default)(p)||(Object.assign(p.style,h),Object.keys(d).forEach(function(E){p.removeAttribute(E)}))})}}var v=n.default={name:"applyStyles",enabled:!0,phase:"write",fn:s,effect:l,requires:["computeStyles"]}},52408:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=c(e(72496)),i=c(e(2696)),a=c(e(61104)),s=c(e(70216)),l=c(e(62600)),v=e(74756),f=c(e(19428)),m=c(e(27856)),g=e(54803);function c(E){return E&&E.__esModule?E:{default:E}}var p=function(){function E(O,C){return O=typeof O=="function"?O(Object.assign({},C.rects,{placement:C.placement})):O,(0,f.default)(typeof O!="number"?O:(0,m.default)(O,g.basePlacements))}return E}();function d(E){var O,C=E.state,R=E.name,M=E.options,w=C.elements.arrow,T=C.modifiersData.popperOffsets,I=(0,o.default)(C.placement),P=(0,l.default)(I),b=[g.left,g.right].indexOf(I)>=0,N=b?"height":"width";if(!(!w||!T)){var D=p(M.padding,C),j=(0,i.default)(w),B=P==="y"?g.top:g.left,k=P==="y"?g.bottom:g.right,G=C.rects.reference[N]+C.rects.reference[P]-T[P]-C.rects.popper[N],z=T[P]-C.rects.reference[P],V=(0,s.default)(w),F=V?P==="y"?V.clientHeight||0:V.clientWidth||0:0,$=G/2-z/2,Y=D[B],U=F-j[N]-D[k],W=F/2-j[N]/2+$,H=(0,v.within)(Y,W,U),J=P;C.modifiersData[R]=(O={},O[J]=H,O.centerOffset=H-W,O)}}function y(E){var O=E.state,C=E.options,R=C.element,M=R===void 0?"[data-popper-arrow]":R;M!=null&&(typeof M=="string"&&(M=O.elements.popper.querySelector(M),!M)||(0,a.default)(O.elements.popper,M)&&(O.elements.arrow=M))}var h=n.default={name:"arrow",enabled:!0,phase:"main",fn:d,effect:y,requires:["popperOffsets"],requiresIfExists:["preventOverflow"]}},43024:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0,n.mapToStyles=d;var o=e(54803),i=g(e(70216)),a=g(e(67652)),s=g(e(57544)),l=g(e(25640)),v=g(e(72496)),f=g(e(76088)),m=e(13312);function g(E){return E&&E.__esModule?E:{default:E}}var c={top:"auto",right:"auto",bottom:"auto",left:"auto"};function p(E,O){var C=E.x,R=E.y,M=O.devicePixelRatio||1;return{x:(0,m.round)(C*M)/M||0,y:(0,m.round)(R*M)/M||0}}function d(E){var O,C=E.popper,R=E.popperRect,M=E.placement,w=E.variation,T=E.offsets,I=E.position,P=E.gpuAcceleration,b=E.adaptive,N=E.roundOffsets,D=E.isFixed,j=T.x,B=j===void 0?0:j,k=T.y,G=k===void 0?0:k,z=typeof N=="function"?N({x:B,y:G}):{x:B,y:G};B=z.x,G=z.y;var V=T.hasOwnProperty("x"),F=T.hasOwnProperty("y"),$=o.left,Y=o.top,U=window;if(b){var W=(0,i.default)(C),H="clientHeight",J="clientWidth";if(W===(0,a.default)(C)&&(W=(0,s.default)(C),(0,l.default)(W).position!=="static"&&I==="absolute"&&(H="scrollHeight",J="scrollWidth")),W=W,M===o.top||(M===o.left||M===o.right)&&w===o.end){Y=o.bottom;var ie=D&&W===U&&U.visualViewport?U.visualViewport.height:W[H];G-=ie-R.height,G*=P?1:-1}if(M===o.left||(M===o.top||M===o.bottom)&&w===o.end){$=o.right;var le=D&&W===U&&U.visualViewport?U.visualViewport.width:W[J];B-=le-R.width,B*=P?1:-1}}var X=Object.assign({position:I},b&&c),ee=N===!0?p({x:B,y:G},(0,a.default)(C)):{x:B,y:G};if(B=ee.x,G=ee.y,P){var _;return Object.assign({},X,(_={},_[Y]=F?"0":"",_[$]=V?"0":"",_.transform=(U.devicePixelRatio||1)<=1?"translate("+B+"px, "+G+"px)":"translate3d("+B+"px, "+G+"px, 0)",_))}return Object.assign({},X,(O={},O[Y]=F?G+"px":"",O[$]=V?B+"px":"",O.transform="",O))}function y(E){var O=E.state,C=E.options,R=C.gpuAcceleration,M=R===void 0?!0:R,w=C.adaptive,T=w===void 0?!0:w,I=C.roundOffsets,P=I===void 0?!0:I,b={placement:(0,v.default)(O.placement),variation:(0,f.default)(O.placement),popper:O.elements.popper,popperRect:O.rects.popper,gpuAcceleration:M,isFixed:O.options.strategy==="fixed"};O.modifiersData.popperOffsets!=null&&(O.styles.popper=Object.assign({},O.styles.popper,d(Object.assign({},b,{offsets:O.modifiersData.popperOffsets,position:O.options.strategy,adaptive:T,roundOffsets:P})))),O.modifiersData.arrow!=null&&(O.styles.arrow=Object.assign({},O.styles.arrow,d(Object.assign({},b,{offsets:O.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:P})))),O.attributes.popper=Object.assign({},O.attributes.popper,{"data-popper-placement":O.placement})}var h=n.default={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:y,data:{}}},2292:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=i(e(67652));function i(v){return v&&v.__esModule?v:{default:v}}var a={passive:!0};function s(v){var f=v.state,m=v.instance,g=v.options,c=g.scroll,p=c===void 0?!0:c,d=g.resize,y=d===void 0?!0:d,h=(0,o.default)(f.elements.popper),E=[].concat(f.scrollParents.reference,f.scrollParents.popper);return p&&E.forEach(function(O){O.addEventListener("scroll",m.update,a)}),y&&h.addEventListener("resize",m.update,a),function(){p&&E.forEach(function(O){O.removeEventListener("scroll",m.update,a)}),y&&h.removeEventListener("resize",m.update,a)}}var l=n.default={name:"eventListeners",enabled:!0,phase:"write",fn:function(){function v(){}return v}(),effect:s,data:{}}},75964:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=m(e(42584)),i=m(e(72496)),a=m(e(29088)),s=m(e(18408)),l=m(e(51732)),v=e(54803),f=m(e(76088));function m(d){return d&&d.__esModule?d:{default:d}}function g(d){if((0,i.default)(d)===v.auto)return[];var y=(0,o.default)(d);return[(0,a.default)(d),y,(0,a.default)(y)]}function c(d){var y=d.state,h=d.options,E=d.name;if(!y.modifiersData[E]._skip){for(var O=h.mainAxis,C=O===void 0?!0:O,R=h.altAxis,M=R===void 0?!0:R,w=h.fallbackPlacements,T=h.padding,I=h.boundary,P=h.rootBoundary,b=h.altBoundary,N=h.flipVariations,D=N===void 0?!0:N,j=h.allowedAutoPlacements,B=y.options.placement,k=(0,i.default)(B),G=k===B,z=w||(G||!D?[(0,o.default)(B)]:g(B)),V=[B].concat(z).reduce(function(Ee,oe){return Ee.concat((0,i.default)(oe)===v.auto?(0,l.default)(y,{placement:oe,boundary:I,rootBoundary:P,padding:T,flipVariations:D,allowedAutoPlacements:j}):oe)},[]),F=y.rects.reference,$=y.rects.popper,Y=new Map,U=!0,W=V[0],H=0;H=0,ee=X?"width":"height",_=(0,s.default)(y,{placement:J,boundary:I,rootBoundary:P,altBoundary:b,padding:T}),se=X?le?v.right:v.left:le?v.bottom:v.top;F[ee]>$[ee]&&(se=(0,o.default)(se));var ge=(0,o.default)(se),we=[];if(C&&we.push(_[ie]<=0),M&&we.push(_[se]<=0,_[ge]<=0),we.every(function(Ee){return Ee})){W=J,U=!1;break}Y.set(J,we)}if(U)for(var Ae=D?3:1,De=function(){function Ee(oe){var ue=V.find(function(fe){var ne=Y.get(fe);if(ne)return ne.slice(0,oe).every(function(re){return re})});if(ue)return W=ue,"break"}return Ee}(),Re=Ae;Re>0;Re--){var Se=De(Re);if(Se==="break")break}y.placement!==W&&(y.modifiersData[E]._skip=!0,y.placement=W,y.reset=!0)}}var p=n.default={name:"flip",enabled:!0,phase:"main",fn:c,requiresIfExists:["offset"],data:{_skip:!1}}},24816:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=e(54803),i=a(e(18408));function a(m){return m&&m.__esModule?m:{default:m}}function s(m,g,c){return c===void 0&&(c={x:0,y:0}),{top:m.top-g.height-c.y,right:m.right-g.width+c.x,bottom:m.bottom-g.height+c.y,left:m.left-g.width-c.x}}function l(m){return[o.top,o.right,o.bottom,o.left].some(function(g){return m[g]>=0})}function v(m){var g=m.state,c=m.name,p=g.rects.reference,d=g.rects.popper,y=g.modifiersData.preventOverflow,h=(0,i.default)(g,{elementContext:"reference"}),E=(0,i.default)(g,{altBoundary:!0}),O=s(h,p),C=s(E,d,y),R=l(O),M=l(C);g.modifiersData[c]={referenceClippingOffsets:O,popperEscapeOffsets:C,isReferenceHidden:R,hasPopperEscaped:M},g.attributes.popper=Object.assign({},g.attributes.popper,{"data-popper-reference-hidden":R,"data-popper-escaped":M})}var f=n.default={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:v}},85640:function(x,n,e){"use strict";n.__esModule=!0,n.preventOverflow=n.popperOffsets=n.offset=n.hide=n.flip=n.eventListeners=n.computeStyles=n.arrow=n.applyStyles=void 0;var o=c(e(42516));n.applyStyles=o.default;var i=c(e(52408));n.arrow=i.default;var a=c(e(43024));n.computeStyles=a.default;var s=c(e(2292));n.eventListeners=s.default;var l=c(e(75964));n.flip=l.default;var v=c(e(24816));n.hide=v.default;var f=c(e(63672));n.offset=f.default;var m=c(e(68568));n.popperOffsets=m.default;var g=c(e(87176));n.preventOverflow=g.default;function c(p){return p&&p.__esModule?p:{default:p}}},63672:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0,n.distanceAndSkiddingToXY=s;var o=a(e(72496)),i=e(54803);function a(f){return f&&f.__esModule?f:{default:f}}function s(f,m,g){var c=(0,o.default)(f),p=[i.left,i.top].indexOf(c)>=0?-1:1,d=typeof g=="function"?g(Object.assign({},m,{placement:f})):g,y=d[0],h=d[1];return y=y||0,h=(h||0)*p,[i.left,i.right].indexOf(c)>=0?{x:h,y:y}:{x:y,y:h}}function l(f){var m=f.state,g=f.options,c=f.name,p=g.offset,d=p===void 0?[0,0]:p,y=i.placements.reduce(function(C,R){return C[R]=s(R,m.rects,d),C},{}),h=y[m.placement],E=h.x,O=h.y;m.modifiersData.popperOffsets!=null&&(m.modifiersData.popperOffsets.x+=E,m.modifiersData.popperOffsets.y+=O),m.modifiersData[c]=y}var v=n.default={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:l}},68568:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=i(e(96759));function i(l){return l&&l.__esModule?l:{default:l}}function a(l){var v=l.state,f=l.name;v.modifiersData[f]=(0,o.default)({reference:v.rects.reference,element:v.rects.popper,strategy:"absolute",placement:v.placement})}var s=n.default={name:"popperOffsets",enabled:!0,phase:"read",fn:a,data:{}}},87176:function(x,n,e){"use strict";n.__esModule=!0,n.default=void 0;var o=e(54803),i=d(e(72496)),a=d(e(62600)),s=d(e(74808)),l=e(74756),v=d(e(2696)),f=d(e(70216)),m=d(e(18408)),g=d(e(76088)),c=d(e(82988)),p=e(13312);function d(E){return E&&E.__esModule?E:{default:E}}function y(E){var O=E.state,C=E.options,R=E.name,M=C.mainAxis,w=M===void 0?!0:M,T=C.altAxis,I=T===void 0?!1:T,P=C.boundary,b=C.rootBoundary,N=C.altBoundary,D=C.padding,j=C.tether,B=j===void 0?!0:j,k=C.tetherOffset,G=k===void 0?0:k,z=(0,m.default)(O,{boundary:P,rootBoundary:b,padding:D,altBoundary:N}),V=(0,i.default)(O.placement),F=(0,g.default)(O.placement),$=!F,Y=(0,a.default)(V),U=(0,s.default)(Y),W=O.modifiersData.popperOffsets,H=O.rects.reference,J=O.rects.popper,ie=typeof G=="function"?G(Object.assign({},O.rects,{placement:O.placement})):G,le=typeof ie=="number"?{mainAxis:ie,altAxis:ie}:Object.assign({mainAxis:0,altAxis:0},ie),X=O.modifiersData.offset?O.modifiersData.offset[O.placement]:null,ee={x:0,y:0};if(W){if(w){var _,se=Y==="y"?o.top:o.left,ge=Y==="y"?o.bottom:o.right,we=Y==="y"?"height":"width",Ae=W[Y],De=Ae+z[se],Re=Ae-z[ge],Se=B?-J[we]/2:0,Ee=F===o.start?H[we]:J[we],oe=F===o.start?-J[we]:-H[we],ue=O.elements.arrow,fe=B&&ue?(0,v.default)(ue):{width:0,height:0},ne=O.modifiersData["arrow#persistent"]?O.modifiersData["arrow#persistent"].padding:(0,c.default)(),re=ne[se],Z=ne[ge],ce=(0,l.within)(0,H[we],fe[we]),te=$?H[we]/2-Se-ce-re-le.mainAxis:Ee-ce-re-le.mainAxis,q=$?-H[we]/2+Se+ce+Z+le.mainAxis:oe+ce+Z+le.mainAxis,pe=O.elements.arrow&&(0,f.default)(O.elements.arrow),Oe=pe?Y==="y"?pe.clientTop||0:pe.clientLeft||0:0,Me=(_=X==null?void 0:X[Y])!=null?_:0,Ye=Ae+te-Me-Oe,Xe=Ae+q-Me,ze=(0,l.within)(B?(0,p.min)(De,Ye):De,Ae,B?(0,p.max)(Re,Xe):Re);W[Y]=ze,ee[Y]=ze-Ae}if(I){var Ke,Ce=Y==="x"?o.top:o.left,Te=Y==="x"?o.bottom:o.right,ye=W[U],Ne=U==="y"?"height":"width",Be=ye+z[Ce],Ue=ye-z[Te],qe=[o.top,o.left].indexOf(V)!==-1,tt=(Ke=X==null?void 0:X[U])!=null?Ke:0,nt=qe?Be:ye-H[Ne]-J[Ne]-tt+le.altAxis,at=qe?ye+H[Ne]+J[Ne]-tt-le.altAxis:Ue,ut=B&&qe?(0,l.withinMaxClamp)(nt,ye,at):(0,l.within)(B?nt:Be,ye,B?at:Ue);W[U]=ut,ee[U]=ut-ye}O.modifiersData[R]=ee}}var h=n.default={name:"preventOverflow",enabled:!0,phase:"main",fn:y,requiresIfExists:["offset"]}},29120:function(x,n,e){"use strict";n.__esModule=!0,n.defaultModifiers=n.createPopper=void 0;var o=e(43128);n.popperGenerator=o.popperGenerator,n.detectOverflow=o.detectOverflow;var i=v(e(2292)),a=v(e(68568)),s=v(e(43024)),l=v(e(42516));function v(g){return g&&g.__esModule?g:{default:g}}var f=n.defaultModifiers=[i.default,a.default,s.default,l.default],m=n.createPopper=(0,o.popperGenerator)({defaultModifiers:f})},84160:function(x,n,e){"use strict";n.__esModule=!0;var o={createPopper:!0,createPopperLite:!0,defaultModifiers:!0,popperGenerator:!0,detectOverflow:!0};n.defaultModifiers=n.createPopperLite=n.createPopper=void 0;var i=e(43128);n.popperGenerator=i.popperGenerator,n.detectOverflow=i.detectOverflow;var a=h(e(2292)),s=h(e(68568)),l=h(e(43024)),v=h(e(42516)),f=h(e(63672)),m=h(e(75964)),g=h(e(87176)),c=h(e(52408)),p=h(e(24816)),d=e(29120);n.createPopperLite=d.createPopper;var y=e(85640);Object.keys(y).forEach(function(C){C==="default"||C==="__esModule"||Object.prototype.hasOwnProperty.call(o,C)||C in n&&n[C]===y[C]||(n[C]=y[C])});function h(C){return C&&C.__esModule?C:{default:C}}var E=n.defaultModifiers=[a.default,s.default,l.default,v.default,f.default,m.default,g.default,c.default,p.default],O=n.createPopperLite=n.createPopper=(0,i.popperGenerator)({defaultModifiers:E})},51732:function(x,n,e){"use strict";n.__esModule=!0,n.default=v;var o=l(e(76088)),i=e(54803),a=l(e(18408)),s=l(e(72496));function l(f){return f&&f.__esModule?f:{default:f}}function v(f,m){m===void 0&&(m={});var g=m,c=g.placement,p=g.boundary,d=g.rootBoundary,y=g.padding,h=g.flipVariations,E=g.allowedAutoPlacements,O=E===void 0?i.placements:E,C=(0,o.default)(c),R=C?h?i.variationPlacements:i.variationPlacements.filter(function(T){return(0,o.default)(T)===C}):i.basePlacements,M=R.filter(function(T){return O.indexOf(T)>=0});M.length===0&&(M=R);var w=M.reduce(function(T,I){return T[I]=(0,a.default)(f,{placement:I,boundary:p,rootBoundary:d,padding:y})[(0,s.default)(I)],T},{});return Object.keys(w).sort(function(T,I){return w[T]-w[I]})}},96759:function(x,n,e){"use strict";n.__esModule=!0,n.default=v;var o=l(e(72496)),i=l(e(76088)),a=l(e(62600)),s=e(54803);function l(f){return f&&f.__esModule?f:{default:f}}function v(f){var m=f.reference,g=f.element,c=f.placement,p=c?(0,o.default)(c):null,d=c?(0,i.default)(c):null,y=m.x+m.width/2-g.width/2,h=m.y+m.height/2-g.height/2,E;switch(p){case s.top:E={x:y,y:m.y-g.height};break;case s.bottom:E={x:y,y:m.y+m.height};break;case s.right:E={x:m.x+m.width,y:h};break;case s.left:E={x:m.x-g.width,y:h};break;default:E={x:m.x,y:m.y}}var O=p?(0,a.default)(p):null;if(O!=null){var C=O==="y"?"height":"width";switch(d){case s.start:E[O]=E[O]-(m[C]/2-g[C]/2);break;case s.end:E[O]=E[O]+(m[C]/2-g[C]/2);break;default:}}return E}},34056:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){var i;return function(){return i||(i=new Promise(function(a){Promise.resolve().then(function(){i=void 0,a(o())})})),i}}},18408:function(x,n,e){"use strict";n.__esModule=!0,n.default=p;var o=c(e(20148)),i=c(e(57544)),a=c(e(42560)),s=c(e(96759)),l=c(e(75092)),v=e(54803),f=e(43744),m=c(e(19428)),g=c(e(27856));function c(d){return d&&d.__esModule?d:{default:d}}function p(d,y){y===void 0&&(y={});var h=y,E=h.placement,O=E===void 0?d.placement:E,C=h.strategy,R=C===void 0?d.strategy:C,M=h.boundary,w=M===void 0?v.clippingParents:M,T=h.rootBoundary,I=T===void 0?v.viewport:T,P=h.elementContext,b=P===void 0?v.popper:P,N=h.altBoundary,D=N===void 0?!1:N,j=h.padding,B=j===void 0?0:j,k=(0,m.default)(typeof B!="number"?B:(0,g.default)(B,v.basePlacements)),G=b===v.popper?v.reference:v.popper,z=d.rects.popper,V=d.elements[D?G:b],F=(0,o.default)((0,f.isElement)(V)?V:V.contextElement||(0,i.default)(d.elements.popper),w,I,R),$=(0,a.default)(d.elements.reference),Y=(0,s.default)({reference:$,element:z,strategy:"absolute",placement:O}),U=(0,l.default)(Object.assign({},z,Y)),W=b===v.popper?U:$,H={top:F.top-W.top+k.top,bottom:W.bottom-F.bottom+k.bottom,left:F.left-W.left+k.left,right:W.right-F.right+k.right},J=d.modifiersData.offset;if(b===v.popper&&J){var ie=J[O];Object.keys(H).forEach(function(le){var X=[v.right,v.bottom].indexOf(le)>=0?1:-1,ee=[v.top,v.bottom].indexOf(le)>=0?"y":"x";H[le]+=ie[ee]*X})}return H}},27856:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o,i){return i.reduce(function(a,s){return a[s]=o,a},{})}},74808:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){return o==="x"?"y":"x"}},72496:function(x,n,e){"use strict";n.__esModule=!0,n.default=i;var o=e(54803);function i(a){return a.split("-")[0]}},82988:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(){return{top:0,right:0,bottom:0,left:0}}},62600:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){return["top","bottom"].indexOf(o)>=0?"x":"y"}},42584:function(x,n){"use strict";n.__esModule=!0,n.default=o;var e={left:"right",right:"left",bottom:"top",top:"bottom"};function o(i){return i.replace(/left|right|bottom|top/g,function(a){return e[a]})}},29088:function(x,n){"use strict";n.__esModule=!0,n.default=o;var e={start:"end",end:"start"};function o(i){return i.replace(/start|end/g,function(a){return e[a]})}},76088:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){return o.split("-")[1]}},13312:function(x,n){"use strict";n.__esModule=!0,n.round=n.min=n.max=void 0;var e=n.max=Math.max,o=n.min=Math.min,i=n.round=Math.round},35264:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){var i=o.reduce(function(a,s){var l=a[s.name];return a[s.name]=l?Object.assign({},l,s,{options:Object.assign({},l.options,s.options),data:Object.assign({},l.data,s.data)}):s,a},{});return Object.keys(i).map(function(a){return i[a]})}},19428:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=i(e(82988));function i(s){return s&&s.__esModule?s:{default:s}}function a(s){return Object.assign({},(0,o.default)(),s)}},90384:function(x,n,e){"use strict";n.__esModule=!0,n.default=a;var o=e(54803);function i(s){var l=new Map,v=new Set,f=[];s.forEach(function(g){l.set(g.name,g)});function m(g){v.add(g.name);var c=[].concat(g.requires||[],g.requiresIfExists||[]);c.forEach(function(p){if(!v.has(p)){var d=l.get(p);d&&m(d)}}),f.push(g)}return s.forEach(function(g){v.has(g.name)||m(g)}),f}function a(s){var l=i(s);return o.modifierPhases.reduce(function(v,f){return v.concat(l.filter(function(m){return m.phase===f}))},[])}},75092:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(o){return Object.assign({},o,{left:o.x,top:o.y,right:o.x+o.width,bottom:o.y+o.height})}},49856:function(x,n){"use strict";n.__esModule=!0,n.default=e;function e(){var o=navigator.userAgentData;return o!=null&&o.brands&&Array.isArray(o.brands)?o.brands.map(function(i){return i.brand+"/"+i.version}).join(" "):navigator.userAgent}},74756:function(x,n,e){"use strict";n.__esModule=!0,n.within=i,n.withinMaxClamp=a;var o=e(13312);function i(s,l,v){return(0,o.max)(s,(0,o.min)(l,v))}function a(s,l,v){var f=i(s,l,v);return f>v?v:f}},59048:function(x){"use strict";/*! @license DOMPurify 2.4.7 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.4.7/LICENSE */(function(n,e){x.exports=e()})(void 0,function(){"use strict";function n(te){"@babel/helpers - typeof";return n=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(q){return typeof q}:function(q){return q&&typeof Symbol=="function"&&q.constructor===Symbol&&q!==Symbol.prototype?"symbol":typeof q},n(te)}function e(te,q){return e=Object.setPrototypeOf||function(){function pe(Oe,Me){return Oe.__proto__=Me,Oe}return pe}(),e(te,q)}function o(){if(typeof Reflect=="undefined"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(te){return!1}}function i(te,q,pe){return o()?i=Reflect.construct:i=function(){function Oe(Me,Ye,Xe){var ze=[null];ze.push.apply(ze,Ye);var Ke=Function.bind.apply(Me,ze),Ce=new Ke;return Xe&&e(Ce,Xe.prototype),Ce}return Oe}(),i.apply(null,arguments)}function a(te){return s(te)||l(te)||v(te)||m()}function s(te){if(Array.isArray(te))return f(te)}function l(te){if(typeof Symbol!="undefined"&&te[Symbol.iterator]!=null||te["@@iterator"]!=null)return Array.from(te)}function v(te,q){if(te){if(typeof te=="string")return f(te,q);var pe=Object.prototype.toString.call(te).slice(8,-1);if(pe==="Object"&&te.constructor&&(pe=te.constructor.name),pe==="Map"||pe==="Set")return Array.from(te);if(pe==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(pe))return f(te,q)}}function f(te,q){(q==null||q>te.length)&&(q=te.length);for(var pe=0,Oe=new Array(q);pe1?pe-1:0),Me=1;Me/gm),De=E(/\${[\w\W]*}/gm),Re=E(/^data-[\-\w.\u00B7-\uFFFF]/),Se=E(/^aria-[\-\w]+$/),Ee=E(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),oe=E(/^(?:\w+script|data):/i),ue=E(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),fe=E(/^html$/i),ne=function(){function te(){return typeof window=="undefined"?null:window}return te}(),re=function(){function te(q,pe){if(n(q)!=="object"||typeof q.createPolicy!="function")return null;var Oe=null,Me="data-tt-policy-suffix";pe.currentScript&&pe.currentScript.hasAttribute(Me)&&(Oe=pe.currentScript.getAttribute(Me));var Ye="dompurify"+(Oe?"#"+Oe:"");try{return q.createPolicy(Ye,{createHTML:function(){function Xe(ze){return ze}return Xe}(),createScriptURL:function(){function Xe(ze){return ze}return Xe}()})}catch(Xe){return null}}return te}();function Z(){var te=arguments.length>0&&arguments[0]!==void 0?arguments[0]:ne(),q=function(){function Ge(he){return Z(he)}return Ge}();if(q.version="2.4.7",q.removed=[],!te||!te.document||te.document.nodeType!==9)return q.isSupported=!1,q;var pe=te.document,Oe=te.document,Me=te.DocumentFragment,Ye=te.HTMLTemplateElement,Xe=te.Node,ze=te.Element,Ke=te.NodeFilter,Ce=te.NamedNodeMap,Te=Ce===void 0?te.NamedNodeMap||te.MozNamedAttrMap:Ce,ye=te.HTMLFormElement,Ne=te.DOMParser,Be=te.trustedTypes,Ue=ze.prototype,qe=Y(Ue,"cloneNode"),tt=Y(Ue,"nextSibling"),nt=Y(Ue,"childNodes"),at=Y(Ue,"parentNode");if(typeof Ye=="function"){var ut=Oe.createElement("template");ut.content&&ut.content.ownerDocument&&(Oe=ut.content.ownerDocument)}var yt=re(Be,pe),Br=yt?yt.createHTML(""):"",gr=Oe,Fr=gr.implementation,Zo=gr.createNodeIterator,vo=gr.createDocumentFragment,Jo=gr.getElementsByTagName,pr=pe.importNode,kr={};try{kr=$(Oe).documentMode?Oe.documentMode:{}}catch(Ge){}var jt={};q.isSupported=typeof at=="function"&&Fr&&Fr.createHTMLDocument!==void 0&&kr!==9;var ho=we,An=Ae,Wn=De,Ur=Re,go=Se,ta=oe,_o=ue,po=Ee,st=null,mo=F({},[].concat(a(U),a(W),a(H),a(ie),a(X))),Et=null,qo=F({},[].concat(a(ee),a(_),a(se),a(ge))),vt=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),zn=null,Gr=null,yo=!0,So=!0,ei=!1,ht=!0,$n=!1,sn=!1,Kr=!1,Yn=!1,Hn=!1,mr=!1,Mn=!1,Ht=!0,ti=!1,Vt="user-content-",Eo=!0,yr=!1,Vn={},ln=null,Sr=F({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),Qn=null,Er=F({},["audio","video","img","source","image","track"]),To=null,ni=F({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Xn="http://www.w3.org/1998/Math/MathML",Tr="http://www.w3.org/2000/svg",Qt="http://www.w3.org/1999/xhtml",qt=Qt,Oo=!1,Or=null,it=F({},[Xn,Tr,Qt],b),Sn,ri=["application/xhtml+xml","text/html"],xo="text/html",Tt,Rn=null,oi=Oe.createElement("form"),Wr=function(){function Ge(he){return he instanceof RegExp||he instanceof Function}return Ge}(),Zn=function(){function Ge(he){Rn&&Rn===he||((!he||n(he)!=="object")&&(he={}),he=$(he),Sn=ri.indexOf(he.PARSER_MEDIA_TYPE)===-1?Sn=xo:Sn=he.PARSER_MEDIA_TYPE,Tt=Sn==="application/xhtml+xml"?b:P,st="ALLOWED_TAGS"in he?F({},he.ALLOWED_TAGS,Tt):mo,Et="ALLOWED_ATTR"in he?F({},he.ALLOWED_ATTR,Tt):qo,Or="ALLOWED_NAMESPACES"in he?F({},he.ALLOWED_NAMESPACES,b):it,To="ADD_URI_SAFE_ATTR"in he?F($(ni),he.ADD_URI_SAFE_ATTR,Tt):ni,Qn="ADD_DATA_URI_TAGS"in he?F($(Er),he.ADD_DATA_URI_TAGS,Tt):Er,ln="FORBID_CONTENTS"in he?F({},he.FORBID_CONTENTS,Tt):Sr,zn="FORBID_TAGS"in he?F({},he.FORBID_TAGS,Tt):{},Gr="FORBID_ATTR"in he?F({},he.FORBID_ATTR,Tt):{},Vn="USE_PROFILES"in he?he.USE_PROFILES:!1,yo=he.ALLOW_ARIA_ATTR!==!1,So=he.ALLOW_DATA_ATTR!==!1,ei=he.ALLOW_UNKNOWN_PROTOCOLS||!1,ht=he.ALLOW_SELF_CLOSE_IN_ATTR!==!1,$n=he.SAFE_FOR_TEMPLATES||!1,sn=he.WHOLE_DOCUMENT||!1,Hn=he.RETURN_DOM||!1,mr=he.RETURN_DOM_FRAGMENT||!1,Mn=he.RETURN_TRUSTED_TYPE||!1,Yn=he.FORCE_BODY||!1,Ht=he.SANITIZE_DOM!==!1,ti=he.SANITIZE_NAMED_PROPS||!1,Eo=he.KEEP_CONTENT!==!1,yr=he.IN_PLACE||!1,po=he.ALLOWED_URI_REGEXP||po,qt=he.NAMESPACE||Qt,vt=he.CUSTOM_ELEMENT_HANDLING||{},he.CUSTOM_ELEMENT_HANDLING&&Wr(he.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(vt.tagNameCheck=he.CUSTOM_ELEMENT_HANDLING.tagNameCheck),he.CUSTOM_ELEMENT_HANDLING&&Wr(he.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(vt.attributeNameCheck=he.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),he.CUSTOM_ELEMENT_HANDLING&&typeof he.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(vt.allowCustomizedBuiltInElements=he.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),$n&&(So=!1),mr&&(Hn=!0),Vn&&(st=F({},a(X)),Et=[],Vn.html===!0&&(F(st,U),F(Et,ee)),Vn.svg===!0&&(F(st,W),F(Et,_),F(Et,ge)),Vn.svgFilters===!0&&(F(st,H),F(Et,_),F(Et,ge)),Vn.mathMl===!0&&(F(st,ie),F(Et,se),F(Et,ge))),he.ADD_TAGS&&(st===mo&&(st=$(st)),F(st,he.ADD_TAGS,Tt)),he.ADD_ATTR&&(Et===qo&&(Et=$(Et)),F(Et,he.ADD_ATTR,Tt)),he.ADD_URI_SAFE_ATTR&&F(To,he.ADD_URI_SAFE_ATTR,Tt),he.FORBID_CONTENTS&&(ln===Sr&&(ln=$(ln)),F(ln,he.FORBID_CONTENTS,Tt)),Eo&&(st["#text"]=!0),sn&&F(st,["html","head","body"]),st.table&&(F(st,["tbody"]),delete zn.tbody),h&&h(he),Rn=he)}return Ge}(),cn=F({},["mi","mo","mn","ms","mtext"]),fn=F({},["foreignobject","desc","title","annotation-xml"]),En=F({},["title","style","font","a","script"]),Tn=F({},W);F(Tn,H),F(Tn,J);var Nn=F({},ie);F(Nn,le);var On=function(){function Ge(he){var je=at(he);(!je||!je.tagName)&&(je={namespaceURI:qt,tagName:"template"});var ke=P(he.tagName),et=P(je.tagName);return Or[he.namespaceURI]?he.namespaceURI===Tr?je.namespaceURI===Qt?ke==="svg":je.namespaceURI===Xn?ke==="svg"&&(et==="annotation-xml"||cn[et]):!!Tn[ke]:he.namespaceURI===Xn?je.namespaceURI===Qt?ke==="math":je.namespaceURI===Tr?ke==="math"&&fn[et]:!!Nn[ke]:he.namespaceURI===Qt?je.namespaceURI===Tr&&!fn[et]||je.namespaceURI===Xn&&!cn[et]?!1:!Nn[ke]&&(En[ke]||!Tn[ke]):!!(Sn==="application/xhtml+xml"&&Or[he.namespaceURI]):!1}return Ge}(),dn=function(){function Ge(he){I(q.removed,{element:he});try{he.parentNode.removeChild(he)}catch(je){try{he.outerHTML=Br}catch(ke){he.remove()}}}return Ge}(),zr=function(){function Ge(he,je){try{I(q.removed,{attribute:je.getAttributeNode(he),from:je})}catch(ke){I(q.removed,{attribute:null,from:je})}if(je.removeAttribute(he),he==="is"&&!Et[he])if(Hn||mr)try{dn(je)}catch(ke){}else try{je.setAttribute(he,"")}catch(ke){}}return Ge}(),Jn=function(){function Ge(he){var je,ke;if(Yn)he=""+he;else{var et=N(he,/^[\r\n\t ]+/);ke=et&&et[0]}Sn==="application/xhtml+xml"&&qt===Qt&&(he=''+he+"");var Nt=yt?yt.createHTML(he):he;if(qt===Qt)try{je=new Ne().parseFromString(Nt,Sn)}catch(Ot){}if(!je||!je.documentElement){je=Fr.createDocument(qt,"template",null);try{je.documentElement.innerHTML=Oo?Br:Nt}catch(Ot){}}var ct=je.body||je.documentElement;return he&&ke&&ct.insertBefore(Oe.createTextNode(ke),ct.childNodes[0]||null),qt===Qt?Jo.call(je,sn?"html":"body")[0]:sn?je.documentElement:ct}return Ge}(),ii=function(){function Ge(he){return Zo.call(he.ownerDocument||he,he,Ke.SHOW_ELEMENT|Ke.SHOW_COMMENT|Ke.SHOW_TEXT,null,!1)}return Ge}(),ai=function(){function Ge(he){return he instanceof ye&&(typeof he.nodeName!="string"||typeof he.textContent!="string"||typeof he.removeChild!="function"||!(he.attributes instanceof Te)||typeof he.removeAttribute!="function"||typeof he.setAttribute!="function"||typeof he.namespaceURI!="string"||typeof he.insertBefore!="function"||typeof he.hasChildNodes!="function")}return Ge}(),xn=function(){function Ge(he){return n(Xe)==="object"?he instanceof Xe:he&&n(he)==="object"&&typeof he.nodeType=="number"&&typeof he.nodeName=="string"}return Ge}(),en=function(){function Ge(he,je,ke){jt[he]&&w(jt[he],function(et){et.call(q,je,ke,Rn)})}return Ge}(),ui=function(){function Ge(he){var je;if(en("beforeSanitizeElements",he,null),ai(he)||k(/[\u0080-\uFFFF]/,he.nodeName))return dn(he),!0;var ke=Tt(he.nodeName);if(en("uponSanitizeElement",he,{tagName:ke,allowedTags:st}),he.hasChildNodes()&&!xn(he.firstElementChild)&&(!xn(he.content)||!xn(he.content.firstElementChild))&&k(/<[/\w]/g,he.innerHTML)&&k(/<[/\w]/g,he.textContent)||ke==="select"&&k(/