diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 0ec29ce36..ea4819430 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,22 +1,43 @@ 'use strict'; module.exports = { - extends: ['airbnb', 'airbnb/hooks'], + extends: ['airbnb', 'airbnb/hooks', 'plugin:import/typescript'], plugins: ['compat', 'react-hooks'], parserOptions: { ecmaVersion: 2022, - ecmaFeatures: { - // Ideally this would only be done for .jsx files, but eslint-plugin-import - // has trouble with the overrides? - jsx: true, - }, }, rules: { 'arrow-body-style': 'off', 'no-underscore-dangle': ['error', { allow: ['_id'] }], + // Modify eslint-config-airbnb's rule to allow ForOfStatement + 'no-restricted-syntax': [ + 'error', + { + selector: 'ForInStatement', + message: 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.', + }, + { + selector: 'LabeledStatement', + message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.', + }, + { + selector: 'WithStatement', + message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.', + }, + ], + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + 'import/extensions': ['error', 'ignorePackages', { + js: 'never', + mjs: 'never', + jsx: 'never', + ts: 'never', + tsx: 'never', + }], + // Not true anymore + 'react/react-in-jsx-scope': 'off', 'react/no-unused-prop-types': ['error', { skipShapeProps: true }], 'react/forbid-prop-types': 'off', 'react/jsx-props-no-spreading': 'off', @@ -27,6 +48,13 @@ module.exports = { namedComponents: 'function-declaration', unnamedComponents: 'arrow-function', }], + 'react/jsx-filename-extension': ['error', { extensions: ['.jsx', '.tsx'] }], + + 'jsx-a11y/control-has-associated-label': [ + 'warn', + require('eslint-config-airbnb/rules/react-a11y') + .rules['jsx-a11y/control-has-associated-label'][1], + ], }, settings: { @@ -47,6 +75,25 @@ module.exports = { }, overrides: [ + { + files: ['**/*.{ts,tsx}'], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + extends: ['plugin:@typescript-eslint/recommended'], + }, + + { + files: ['src/reducers/*'], + rules: { + // Reducers use default params differently + 'default-param-last': 'off', + 'no-param-reassign': ['error', { + props: true, + ignorePropertyModificationsFor: ['state'], + }], + }, + }, + { files: ['src/**/*.{js,jsx}'], rules: { @@ -65,8 +112,8 @@ module.exports = { }, { files: ['**/__tests__/**/*.{js,jsx}'], - plugins: ['eslint-plugin-jest', 'eslint-plugin-jest-dom', 'eslint-plugin-testing-library'], - extends: ['plugin:jest/recommended', 'plugin:jest-dom/recommended', 'plugin:testing-library/react'], + plugins: ['eslint-plugin-vitest', 'eslint-plugin-jest-dom', 'eslint-plugin-testing-library'], + extends: ['plugin:vitest/recommended', 'plugin:jest-dom/recommended', 'plugin:testing-library/react'], env: { jest: true, }, diff --git a/babel.config.cjs b/babel.config.cjs deleted file mode 100644 index d6d55860a..000000000 --- a/babel.config.cjs +++ /dev/null @@ -1,124 +0,0 @@ -'use strict'; - -const pkg = require('./package.json'); - -// Replaces import.meta.url with a CommonJS equivalent, and import.meta.* with `undefined`. -function importMetaToCommonJs() { - return { - visitor: { - MetaProperty(path) { - if (path.node.property.name !== 'meta') { - return; - } - const parent = path.parentPath; - if (!parent.isMemberExpression()) { - return; - } - - if (parent.node.property.name === 'url') { - parent.replaceWithSourceString('require("url").pathToFileURL(__filename)'); - } else { - parent.replaceWithSourceString('undefined'); - } - }, - }, - }; -} - -module.exports = (api, envOverride) => { - const env = envOverride || process.env.BABEL_ENV || process.env.NODE_ENV || 'development'; - // Command-line version override. - const browsers = process.env.BROWSERSLIST; - - api.cache(() => `${env}${browsers || ''}`); - - // When the caller is @babel/register, we expect to immediately run the output, in the current - // Node.js version. - const callerIsNode = api.caller((caller) => caller && (caller.name === '@babel/register' || caller.name === 'babel-jest')); - // When the target is `node`, we're doing a webpack build for server-side code. The output will - // run in any Node.js version supported by our public API. - const targetIsNode = api.caller((caller) => caller && caller.target === 'node'); - // Check if our output should support older browsers. - const targetIsLegacy = api.caller((caller) => caller && caller.compiler === 'app-legacy'); - - let browserslistEnv = 'production'; - let targets; - if (callerIsNode) { - targets = { node: 'current', browsers: '' }; - } else if (targetIsNode) { - targets = { node: '12.0.0', browsers: '' }; - } - - if (targetIsLegacy) { - browserslistEnv = 'legacy'; - } - - const reactConfig = { - test: /\.jsx$/, - presets: [ - ['@babel/preset-react', { - development: env === 'development', - runtime: 'automatic', - }], - ], - plugins: [], - }; - - const config = { - browserslistEnv, - assumptions: { - constantSuper: true, - noClassCalls: true, - noDocumentAll: true, - noNewArrows: true, - privateFieldsAsProperties: true, - }, - presets: [ - ['@babel/preset-env', { - modules: false, - bugfixes: true, - }], - ], - plugins: [ - ['@babel/plugin-transform-runtime', { - version: pkg.dependencies['@babel/runtime'], - // When targeting Node.js for any reason, dependencies are external to the webpack bundle, - // and must be `require()`-able. - useESModules: !callerIsNode && !targetIsNode, - corejs: false, - }], - ], - - overrides: [reactConfig], - }; - - if (targets) { - config.targets = targets; - } - - if (callerIsNode) { - config.plugins.push( - '@babel/plugin-transform-modules-commonjs', - ); - } - - if (env === 'production') { - reactConfig.plugins.push( - '@babel/plugin-transform-react-constant-elements', - '@babel/plugin-transform-react-inline-elements', - ['transform-react-remove-prop-types', { mode: 'remove' }], - ); - } - - if (env === 'development' && !targetIsNode && !callerIsNode) { - reactConfig.plugins.push( - 'module:react-refresh/babel', - ); - } - - if (callerIsNode) { - config.plugins.push(importMetaToCommonJs); - } - - return config; -}; diff --git a/jest.config.mjs b/jest.config.mjs deleted file mode 100644 index 2d94c28bf..000000000 --- a/jest.config.mjs +++ /dev/null @@ -1,12 +0,0 @@ -export default { - testEnvironment: 'jsdom', - transform: { - '\\.ya?ml$': '<rootDir>/test/yaml-transform.mjs', - '\\.jsx?$': 'babel-jest', - }, - moduleNameMapper: { - // Prevent jest from picking up the ESM version. - '^uuid$': '<rootDir>/node_modules/uuid/dist/index.js', - }, - setupFilesAfterEnv: ['@testing-library/jest-dom'], -}; diff --git a/npm/package.json b/npm/package.json index 46dc7f195..5958ea7c1 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,6 +1,6 @@ { "name": "u-wave-web", - "version": "2.0.0-alpha.24", + "version": "2.0.0-alpha.28", "description": "Web client for üWave servers.", "author": "Renée Kooi <renee@kooi.me>", "license": "MIT", diff --git a/package-lock.json b/package-lock.json index c479cd4fc..edec3b049 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,14 @@ { "name": "u-wave-web-build", - "version": "2.0.0-alpha.24", + "version": "2.0.0-alpha.28", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "u-wave-web-build", - "version": "2.0.0-alpha.24", + "version": "2.0.0-alpha.28", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.20.13", "@emotion/cache": "^11.6.0", "@emotion/core": "^11.0.0", "@emotion/react": "^11.7.0", @@ -20,7 +19,8 @@ "@mui/system": "^5.11.5", "@mui/utils": "^5.2.2", "@openfonts/open-sans_all": "^1.44.2", - "@tanstack/react-virtual": "3.0.0-beta.54", + "@reduxjs/toolkit": "^1.9.3", + "@tanstack/react-virtual": "3.0.0-beta.68", "@u-wave/react-server-list": "5.0.0-beta.3", "@u-wave/react-translate": "^2.0.2", "@u-wave/react-youtube": "^1.0.0-alpha.3", @@ -30,14 +30,14 @@ "array.from": "^1.1.3", "array.prototype.find": "^2.2.0", "array.prototype.findindex": "^2.2.0", - "clsx": "^1.2.0", + "clsx": "^2.0.0", "css.escape": "^1.5.1", "deepmerge": "^4.3.0", "dlv": "^1.1.3", "dset": "^3.0.0", "es6-promise": "^4.2.8", "es6-symbol": "^3.1.3", - "escape-string-regexp": "^4.0.0", + "escape-string-regexp": "^5.0.0", "event-source-polyfill": "^1.0.24", "express": "^4.18.2", "flash-document-title": "^1.0.0", @@ -80,53 +80,48 @@ "splitargs": "0.0.7", "string.prototype.includes": "^2.0.0", "swr": "^2.1.0", - "u-wave-parse-chat-markup": "^2.4.0", + "u-wave-parse-chat-markup": "^2.5.0", "url-polyfill": "^1.1.11", "use-debounce": "^9.0.3", "uuid": "^9.0.0", "whatwg-fetch": "^3.4.0" }, "devDependencies": { - "@babel/core": "^7.20.12", - "@babel/plugin-transform-modules-commonjs": "^7.14.0", - "@babel/plugin-transform-react-constant-elements": "^7.13.13", - "@babel/plugin-transform-react-inline-elements": "^7.12.13", - "@babel/plugin-transform-runtime": "^7.17.0", - "@babel/preset-env": "^7.14.0", - "@babel/preset-react": "^7.13.13", - "@babel/register": "^7.13.8", "@emotion/css": "^11.10.5", "@emotion/server": "^11.0.0", "@rollup/plugin-yaml": "^4.0.1", - "@testing-library/jest-dom": "^5.16.5", + "@testing-library/jest-dom": "^6.1.4", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", - "@vitejs/plugin-react": "^3.1.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "emojibase-data": "^7.0.0", - "eslint": "^8.34.0", + "@types/uuid": "^9.0.1", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "@vitejs/plugin-react": "^4.0.0", + "@vitest/coverage-v8": "^0.34.2", + "emojibase-data": "^15.0.0", + "eslint": "^8.36.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-compat": "^4.1.0", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^27.2.1", - "eslint-plugin-jest-dom": "^4.0.0", + "eslint-plugin-jest-dom": "^5.0.1", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-testing-library": "^5.10.0", - "get-port": "^6.1.2", - "jest": "^29.5.0", - "jest-environment-jsdom": "^29.5.0", - "jest-fetch-mock": "^3.0.3", - "js-yaml": "^4.1.0", - "p-map": "^5.4.0", + "eslint-plugin-testing-library": "^6.2.0", + "eslint-plugin-vitest": "^0.3.10", + "get-port": "^7.0.0", + "jsdom": "^23.0.1", + "jsonapi-typescript": "^0.1.3", + "p-map": "^6.0.0", "postcss": "^8.4.21", - "postcss-preset-env": "^8.0.1", - "rimraf": "^4.1.1", + "postcss-preset-env": "^9.0.0", + "rimraf": "^5.0.0", "stylelint": "^15.1.0", - "stylelint-config-standard": "^31.0.0", + "stylelint-config-standard": "^34.0.0", "twemoji-emojis": "^14.1.0", - "vite": "^4.0.4" + "typescript": "^5.0.2", + "vite": "^5.0.2", + "vitest": "^0.34.2" }, "engines": { "node": ">= 14", @@ -139,6 +134,15 @@ ] } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@adobe/css-tools": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.2.tgz", @@ -146,12 +150,12 @@ "dev": true }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -159,315 +163,231 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", - "dev": true, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=4" } }, - "node_modules/@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", - "dev": true, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "@babel/types": "^7.21.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "color-name": "1.1.3" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=6.9.0" + "node": ">=0.8.0" } }, - "node_modules/@babel/helper-builder-react-jsx": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.19.0.tgz", - "integrity": "sha512-xvrbORmJ13lWrqyMErk4vczhXNNWdOSg1BZ+R/7D34SjDjToR5g3M5UpD6MyUekstI50qAHLWA1j7w5o1WK2Pw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/types": "^7.19.0" - }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dev": true, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=4" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", - "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", - "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", + "node_modules/@babel/core": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", + "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "engines": { - "node": ">=6.9.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "node_modules/@babel/generator": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", + "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.23.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "dependencies": { - "@babel/types": "^7.21.0" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -476,229 +396,174 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.20.0" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", + "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", - "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=4" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", - "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", - "dev": true, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-proposal-optional-chaining": "^7.20.7" - }, + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "node": ">=0.8.0" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=4" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=4" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", - "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", + "node_modules/@babel/parser": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-class-static-block": "^7.14.5" + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz", + "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -707,14 +572,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz", + "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -723,1939 +587,2154 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, + "node_modules/@babel/runtime": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", + "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", - "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + "node_modules/@babel/traverse": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", + "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.5", + "@babel/types": "^7.23.5", + "debug": "^4.1.0", + "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, + "node_modules/@babel/types": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", + "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.5.tgz", + "integrity": "sha512-v/5ODKNBMfBl0us/WQjlfsvSlYxfZLhNMVIsuCPib2ulTwGKYbKJbwqw671+qH9Y4wvWVnu7LBChvml/wBKjFg==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "node_modules/@csstools/color-helpers": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-3.0.2.tgz", + "integrity": "sha512-NMVs/l7Y9eIKL5XjbCHEgGcG8LOUT2qVcRjX6EzkCdlvftHVKr2tHIPzHavfrULRZ5Q2gxrJ9f44dAlj6fX97Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14 || ^16 || >=18" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "node_modules/@csstools/css-calc": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.1.4.tgz", + "integrity": "sha512-ZV1TSmToiNcQL1P3hfzlzZzA02mmVkVmXGaUDUqpYUG84PmLhVSZpKX+KfxAuOcK7de04UXSQPBrAvaya6iiGg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" } }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "node_modules/@csstools/css-color-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-1.4.0.tgz", + "integrity": "sha512-SlGd8E6ron24JYQPQAIzu5tvmWi1H4sDKTdA7UDnwF45oJv7AVESbOlOO1YjfBhrQFuvLWUgKiOY9DwGoAxwTA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@csstools/color-helpers": "^3.0.2", + "@csstools/css-calc": "^1.1.4" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", - "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.2.tgz", + "integrity": "sha512-sLYGdAdEY2x7TSw9FtmdaTrh2wFtRJO5VMbBrA8tEqEod7GEggFmxTSK9XqExib3yMuYNcvcTdCZIP6ukdjAIA==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-tokenizer": "^2.2.1" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "node_modules/@csstools/css-tokenizer": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.1.tgz", + "integrity": "sha512-Zmsf2f/CaEPWEVgw29odOj+WEVoiJy9s9NOv5GgNY9mZ1CZ7394By6wONrONrTsnNDv6F9hR02nvFihrGVGHBg==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^14 || ^16 || >=18" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.5.tgz", + "integrity": "sha512-IxVBdYzR8pYe89JiyXQuYk4aVVoCPhMJkz6ElRwlVysjwURTsTk/bmY/z4FfeRE+CRBMlykPwXEVUg8lThv7AQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "node_modules/@csstools/postcss-cascade-layers": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-4.0.1.tgz", + "integrity": "sha512-UYFuFL9GgVnftg9v7tBvVEBRLaBeAD66euD+yYy5fYCUld9ZIWTJNCE30hm6STMEdt6FL5xzeVw1lAZ1tpvUEg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@csstools/selector-specificity": "^3.0.0", + "postcss-selector-parser": "^6.0.13" + }, + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@csstools/postcss-color-function": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-3.0.7.tgz", + "integrity": "sha512-/PIB20G1TPCXmQlaJLWIYzTZRZpj6csT4ijgnshIj/kcmniIRroAfDa0xSWnfuO1eNo0NptIaPU7jzUukWn55Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/postcss-progressive-custom-properties": "^3.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@csstools/postcss-color-mix-function": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-2.0.7.tgz", + "integrity": "sha512-57/g8aGo5eKFjEeJMiRKh8Qq43K2rCyk5ZZTvJ34TNl4zUtYU5DvLkIkOnhCtL8/a4z9oMA42aOnFPddRrScUQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/postcss-progressive-custom-properties": "^3.0.2" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@csstools/postcss-exponential-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-1.0.1.tgz", + "integrity": "sha512-ZLK2iSK4DUxeypGce2PnQSdYugUqDTwxnhNiq1o6OyKMNYgYs4eKbvEhFG8JKr1sJWbeqBi5jRr0017l2EWVvg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@csstools/css-calc": "^1.1.4", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" + }, + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-3.0.0.tgz", + "integrity": "sha512-ntkGj+1uDa/u6lpjPxnkPcjJn7ChO/Kcy08YxctOZI7vwtrdYvFhmE476dq8bj1yna306+jQ9gzXIG/SWfOaRg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", - "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "node_modules/@csstools/postcss-gamut-mapping": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-1.0.0.tgz", + "integrity": "sha512-6UQyK8l9YaG5Ao5rBDcCnKHrLsHiQ1E0zeFQuqDJqEtinVzAPb/MwSw3TenZXL1Rnd7th3tb+4CBFHBXdW5tbQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "2.3.2", + "@csstools/css-tokenizer": "^2.2.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "node_modules/@csstools/postcss-gradients-interpolation-method": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-4.0.7.tgz", + "integrity": "sha512-GT1CzE/Tyr/ei4j5BwKESkHAgg+Gzys/0mAY7W+UiR+XrcYk5hDbOrE/YJIx1rflfO/7La1bDoZtA0YnLl4qNA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/postcss-progressive-custom-properties": "^3.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "node_modules/@csstools/postcss-hwb-function": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-3.0.6.tgz", + "integrity": "sha512-uQgWt2Ho2yy2S6qthWY7mD5v57NKxi6dD1NB8nAybU5bJSsm+hLXRGm3/zbOH4xNrqO3Cl60DFSNlSrUME3Xjg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" + }, + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "node_modules/@csstools/postcss-ic-unit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-3.0.2.tgz", + "integrity": "sha512-n28Er7W9qc48zNjJnvTKuVHY26/+6YlA9WzJRksIHiAWOMxSH5IksXkw7FpkIOd+jLi59BMrX/BWrZMgjkLBHg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@csstools/postcss-progressive-custom-properties": "^3.0.2", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/@csstools/postcss-initial": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-initial/-/postcss-initial-1.0.0.tgz", + "integrity": "sha512-1l7iHHjIl5qmVeGItugr4ZOlCREDP71mNKqoEyxlosIoiu3Os1nPWMHpuCvDLCLiWI/ONTOg3nzJh7gwHOrqUA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-4.0.3.tgz", + "integrity": "sha512-/dt5M9Ty/x3Yiq0Nm/5PJJzwkVFchJgdjKVnryBPtoMCb9ohb/nDIJOwr/Wr3hK3FDs1EA1GE6PyRYsUmQPS8Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@csstools/selector-specificity": "^3.0.0", + "postcss-selector-parser": "^6.0.13" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-2.0.0.tgz", + "integrity": "sha512-Wki4vxsF6icRvRz8eF9bPpAvwaAt0RHwhVOyzfoFg52XiIMjb6jcbHkGxwpJXP4DVrnFEwpwmrz5aTRqOW82kg==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "node_modules/@csstools/postcss-logical-overflow": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overflow/-/postcss-logical-overflow-1.0.0.tgz", + "integrity": "sha512-cIrZ8f7bGGvr+W53nEuMspcwaeaI2YTmz6LZ4yiAO5z14/PQgOOv+Pn+qjvPOPoadeY2BmpaoTzZKvdAQuM17w==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "node_modules/@csstools/postcss-logical-overscroll-behavior": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-overscroll-behavior/-/postcss-logical-overscroll-behavior-1.0.0.tgz", + "integrity": "sha512-e89S2LWjnxf0SB2wNUAbqDyFb/Fow/tlOe1XqOLbNx4rf3LrQokM9qldVx7sarnddml3ORE5LDUmlKpPOOeJTA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "node_modules/@csstools/postcss-logical-resize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-2.0.0.tgz", + "integrity": "sha512-lCQ1aX8c5+WI4t5EoYf3alTzJNNocMqTb+u1J9CINdDhFh1fjovqK+0aHalUHsNstZmzFPNzIkU4Mb3eM9U8SA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-2.0.3.tgz", + "integrity": "sha512-xeVxqND5rlQyqLGdH7rX34sIm/JbbQKxpKQP8oD1YQqUHHCLQR9NUS57WqJKajxKN6AcNAMWJhb5LUH5RfPcyA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@csstools/css-tokenizer": "^2.2.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "node_modules/@csstools/postcss-media-minmax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-minmax/-/postcss-media-minmax-1.1.0.tgz", + "integrity": "sha512-t5Li/DPC5QmW/6VFLfUvsw/4dNYYseWR0tOXDeJg/9EKUodBgNawz5tuk5vYKtNvoj+Q08odMuXcpS5YJj0AFA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@csstools/css-calc": "^1.1.4", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/media-query-list-parser": "^2.1.5" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-2.0.3.tgz", + "integrity": "sha512-IPL8AvnwMYW+cWtp+j8cW3MFN0RyXNT4hLOvs6Rf2N+NcbvXhSyKxZuE3W9Cv4KjaNoNoGx1d0UhT6tktq6tUw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/media-query-list-parser": "^2.1.5" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", + "node_modules/@csstools/postcss-nested-calc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-3.0.0.tgz", + "integrity": "sha512-HsB66aDWAouOwD/GcfDTS0a7wCuVWaTpXcjl5VKP0XvFxDiU+r0T8FG7xgb6ovZNZ+qzvGIwRM+CLHhDgXrYgQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-3.0.1.tgz", + "integrity": "sha512-nUvRxI+ALJwkxZdPU4EDyuM380vP91sAGvI3jAOHs/sr3jfcCOzLkY6xKI1Mr526kZ3RivmMoYM/xq+XFyE/bw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "node_modules/@csstools/postcss-oklab-function": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-3.0.7.tgz", + "integrity": "sha512-vBFTQD3CARB3u/XIGO44wWbcO7xG/4GsYqJlcPuUGRSK8mtxes6n4vvNFlIByyAZy2k4d4RY63nyvTbMpeNTaQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/postcss-progressive-custom-properties": "^3.0.2" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-3.0.2.tgz", + "integrity": "sha512-YEvTozk1SxnV/PGL5DllBVDuLQ+jiQhyCSQiZJ6CwBMU5JQ9hFde3i1qqzZHuclZfptjrU0JjlX4ePsOhxNzHw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "node_modules/@csstools/postcss-relative-color-syntax": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-2.0.7.tgz", + "integrity": "sha512-2AiFbJSVF4EyymLxme4JzSrbXykHolx8DdZECHjYKMhoulhKLltx5ccYgtrK3BmXGd3v3nJrWFCc8JM8bjuiOg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/postcss-progressive-custom-properties": "^3.0.2" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", - "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-3.0.0.tgz", + "integrity": "sha512-GFNVsD97OuEcfHmcT0/DAZWAvTM/FFBDQndIOLawNc1Wq8YqpZwBdHa063Lq+Irk7azygTT+Iinyg3Lt76p7rg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "postcss-selector-parser": "^6.0.13" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-3.0.2.tgz", + "integrity": "sha512-I3wX44MZVv+tDuWfrd3BTvRB/YRIM2F5v1MBtTI89sxpFn47mNpTwpPYUOGPVCgKlRDfZSlxIUYhUQmqRQZZFQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@csstools/css-calc": "^1.1.4", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-3.0.3.tgz", + "integrity": "sha512-d5J9m49HhqXRcw1S6vTZuviHi/iknUKGjBpChiNK1ARg9sSa3b8m5lsWz5Izs8ISORZdv2bZRwbw5Z2R6gQ9kQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@csstools/color-helpers": "^3.0.2", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-3.0.2.tgz", + "integrity": "sha512-AwzNhF4QOKaLOKvMljwwFkeYXwufhRO15G+kKohHkyoNOL75xWkN+W2Y9ik9tSeAyDv+cYNlYaF+o/a79WjVjg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@csstools/css-calc": "^1.1.4", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" }, "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "node_modules/@csstools/postcss-unset-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-3.0.0.tgz", + "integrity": "sha512-P0JD1WHh3avVyKKRKjd0dZIjCEeaBer8t1BbwGMUDtSZaLhXlLNBqZ8KkqHzYWXOJgHleXAny2/sx8LYl6qhEA==", "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss": "^8.4" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "node_modules/@csstools/selector-specificity": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz", + "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=6.9.0" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss-selector-parser": "^6.0.13" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { - "node": ">=6.9.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", - "dev": true, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "dependencies": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "node_modules/@emotion/core": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz", + "integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA==" + }, + "node_modules/@emotion/css": { + "version": "11.11.2", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.11.2.tgz", + "integrity": "sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==", "dev": true, "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emotion/memoize": "^0.8.1" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", - "dev": true, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz", + "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, + "node_modules/@emotion/serialize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "node_modules/@emotion/server": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.11.0.tgz", + "integrity": "sha512-6q89fj2z8VBTx9w93kJ5n51hsmtYuFPtZgnc1L8VzRx9ti4EU6EyvF6Nn1H1x3vcCQCF7u2dB2lY4AYJwUW4PA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" + "@emotion/utils": "^1.2.1", + "html-tokenize": "^2.0.0", + "multipipe": "^1.0.2", + "through": "^2.3.8" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emotion/css": "^11.0.0-rc.0" + }, + "peerDependenciesMeta": { + "@emotion/css": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", - "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", - "dev": true, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, + "node_modules/@emotion/styled": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", + "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "peerDependencies": { - "@babel/core": "^7.0.0-0" + "react": ">=16.8.0" } }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz", - "integrity": "sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g==", + "node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.8.tgz", + "integrity": "sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", - "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz", + "integrity": "sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-inline-elements": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.21.0.tgz", - "integrity": "sha512-lOSFD/67qxOwQ7q6KpkAbBFeGI5xy1Oya2zipYxPSmG2C210CRJyQdzOl1A368J1nv2gOFTgRXdsRjb83jioLw==", + "node_modules/@esbuild/android-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.8.tgz", + "integrity": "sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-builder-react-jsx": "^7.19.0", - "@babel/helper-plugin-utils": "^7.20.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz", - "integrity": "sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz", + "integrity": "sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.21.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", - "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz", + "integrity": "sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.18.6" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.21.0.tgz", - "integrity": "sha512-f/Eq+79JEu+KUANFks9UZCcvydOOGMgF7jBrcwjHa5jTZD8JivnhCJYvmlhR/WTXBWonDExPoW0eO/CR4QJirA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz", + "integrity": "sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.19.6.tgz", - "integrity": "sha512-RpAi004QyMNisst/pvSanoRdJ4q+jMCWyk9zdw/CyLB9j8RXEahodR6l2GyttDRyEVWZtbN+TpLiHJ3t34LbsQ==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz", + "integrity": "sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", - "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "node_modules/@esbuild/linux-arm": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz", + "integrity": "sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz", + "integrity": "sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz", + "integrity": "sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz", - "integrity": "sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz", + "integrity": "sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "semver": "^6.3.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz", + "integrity": "sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz", + "integrity": "sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz", + "integrity": "sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz", + "integrity": "sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "node_modules/@esbuild/linux-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz", + "integrity": "sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz", + "integrity": "sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz", + "integrity": "sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz", + "integrity": "sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz", + "integrity": "sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@babel/preset-react": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", - "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz", + "integrity": "sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-pure-annotations": "^7.18.6" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/register": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.21.0.tgz", - "integrity": "sha512-9nKsPmYDi5DidAqJaQooxIhsLJiNMkGr8ypQ8Uic7cIox7UCDsM7HuUGxdGT7mSDTYbqzIdsOWzfBton/YJrMw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz", + "integrity": "sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.5", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", - "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.2", - "@babel/types": "^7.21.2", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/types": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", - "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz", + "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==", + "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@csstools/cascade-layer-name-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.1.tgz", - "integrity": "sha512-SAAi5DpgJJWkfTvWSaqkgyIsTawa83hMwKrktkj6ra2h+q6ZN57vOGZ6ySHq6RSo+CbP64fA3aPChPBRDDUgtw==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.0.0", - "@csstools/css-tokenizer": "^2.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@csstools/color-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-1.0.0.tgz", - "integrity": "sha512-tgqtiV8sU/VaWYjOB3O7PWs7HR/MmOLl2kTYRW2qSsTSEniJq7xmyAYFB1LPpXvvQcE5u2ih2dK9fyc8BnrAGQ==", + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@csstools/css-calc": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.0.0.tgz", - "integrity": "sha512-Xw0b/Jr+vLGGYD8cxsGWPaY5n1GtVC6G4tcga+eZPXZzRjjZHorPwW739UgtXzL2Da1RLxNE73c0r/KvmizPsw==", + "node_modules/@eslint/js": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz", + "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@f/cookies-enabled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@f/cookies-enabled/-/cookies-enabled-1.1.1.tgz", + "integrity": "sha512-7QSJQAFje3K8NluCwcs+txJhe5AhZDViG0OrJK4yfuFJw/kw+oha5hp3KZ/DFyNYde2O2oEeDX6kA5p7FEPZ+w==", + "dependencies": { + "@f/is-undefined": "^1.0.0" + } + }, + "node_modules/@f/is-undefined": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@f/is-undefined/-/is-undefined-1.1.1.tgz", + "integrity": "sha512-i92CKmXRvw/skYbwBE9eHdwNGbJshI/kwQMJ65ktMtAsRWNMuQis1BSsnpaGZaFEANI1L1o90YKh6g+YI/aB/Q==" + }, + "node_modules/@floating-ui/core": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.1.tgz", + "integrity": "sha512-QgcKYwzcc8vvZ4n/5uklchy8KVdjJwcOeI+HnnTNclJjs2nYsy23DOCf+sSV1kBwD9yDAoVKCkv/gEPzgQU3Pw==", + "dependencies": { + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", + "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "dependencies": { + "@floating-ui/core": "^1.4.2", + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.4.tgz", + "integrity": "sha512-CF8k2rgKeh/49UrnIBs4BdxPUV6vize/Db1d/YbCLyp9GiVZ0BEwf5AiDSxJRCr6yOkGqTFHtmrULxkEfYZ7dQ==", + "dependencies": { + "@floating-ui/dom": "^1.5.1" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.0.1", - "@csstools/css-tokenizer": "^2.0.1" + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.0.1.tgz", - "integrity": "sha512-B9/8PmOtU6nBiibJg0glnNktQDZ3rZnGn/7UmDfrm2vMtrdlXO3p7ErE95N0up80IRk9YEtB5jyj/TmQ1WH3dw==", + "node_modules/@floating-ui/utils": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", + "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, - "peerDependencies": { - "@csstools/css-tokenizer": "^2.0.0" + "engines": { + "node": ">=10.10.0" } }, - "node_modules/@csstools/css-tokenizer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.1.0.tgz", - "integrity": "sha512-dtqFyoJBHUxGi9zPZdpCKP1xk8tq6KPHJ/NY4qWXiYo6IcSGwzk3L8x2XzZbbyOyBs9xQARoGveU2AsgLj6D2A==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.22" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@csstools/media-query-list-parser": { + "node_modules/@humanwhocodes/object-schema": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.1.tgz", - "integrity": "sha512-X2/OuzEbjaxhzm97UJ+95GrMeT29d1Ib+Pu+paGLuRWZnWRK9sI9r3ikmKXPWGA1C4y4JEdBEFpp9jEqCvLeRA==", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.0.0", - "@csstools/css-tokenizer": "^2.0.0" + "engines": { + "node": ">=12" } }, - "node_modules/@csstools/postcss-cascade-layers": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-3.0.1.tgz", - "integrity": "sha512-dD8W98dOYNOH/yX4V4HXOhfCOnvVAg8TtsL+qCGNoKXuq5z2C/d026wGWgySgC8cajXXo/wNezS31Glj5GcqrA==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@csstools/postcss-color-function": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-2.1.0.tgz", - "integrity": "sha512-XBoCClLyWchlYGHGlmMOa6M2UXZNrZm63HVfsvgD/z1RPm/s3+FhHyT6VkDo+OvEBPhCgn6xz4IeCu4pRctKDQ==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "@csstools/color-helpers": "^1.0.0", - "@csstools/postcss-progressive-custom-properties": "^2.0.0", - "postcss-value-parser": "^4.2.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@csstools/postcss-font-format-keywords": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-2.0.2.tgz", - "integrity": "sha512-iKYZlIs6JsNT7NKyRjyIyezTCHLh4L4BBB3F5Nx7Dc4Z/QmBgX+YJFuUSar8IM6KclGiAUFGomXFdYxAwJydlA==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=8" } }, - "node_modules/@csstools/postcss-hwb-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-2.1.1.tgz", - "integrity": "sha512-XijKzdxBdH2hU6IcPWmnaU85FKEF1XE5hGy0d6dQC6XznFUIRu1T4uebL3krayX40m4xIcxfCBsQm5zphzVrtg==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "@csstools/color-helpers": "^1.0.0", - "postcss-value-parser": "^4.2.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@csstools/postcss-ic-unit": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-2.0.2.tgz", - "integrity": "sha512-N84qGTJkfLTPj2qOG5P4CIqGjpZBbjOEMKMn+UjO5wlb9lcBTfBsxCF0lQsFdWJUzBHYFOz19dL66v71WF3Pig==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^2.0.0", - "postcss-value-parser": "^4.2.0" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=6.0.0" } }, - "node_modules/@csstools/postcss-is-pseudo-class": { + "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-3.1.1.tgz", - "integrity": "sha512-hhiacuby4YdUnnxfCYCRMBIobyJImozf0u+gHSbQ/tNOdwvmrZtVROvgW7zmfYuRkHVDNZJWZslq2v5jOU+j/A==", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=6.0.0" } }, - "node_modules/@csstools/postcss-logical-float-and-clear": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-1.0.1.tgz", - "integrity": "sha512-eO9z2sMLddvlfFEW5Fxbjyd03zaO7cJafDurK4rCqyRt9P7aaWwha0LcSzoROlcZrw1NBV2JAp2vMKfPMQO1xw==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=6.0.0" } }, - "node_modules/@csstools/postcss-logical-resize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-1.0.1.tgz", - "integrity": "sha512-x1ge74eCSvpBkDDWppl+7FuD2dL68WP+wwP2qvdUcKY17vJksz+XoE1ZRV38uJgS6FNUwC0AxrPW5gy3MxsDHQ==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdi/js": { + "version": "7.3.67", + "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.3.67.tgz", + "integrity": "sha512-MnRjknFqpTC6FifhGHjZ0+QYq2bAkZFQqIj8JA2AdPZbBxUvr8QSgB2yPAJ8/ob/XkR41xlg5majDR3c1JP1hw==" + }, + "node_modules/@mdn/browser-compat-data": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.4.2.tgz", + "integrity": "sha512-KuBlKNjbZyU3jCTNGsJl+accdAZRUVVyMBeIXAUT+oMUQ64Uq2mxKajzonFJOXkhaAvTac+sDtJSLhaOzKIo2Q==", + "dev": true + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.25", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.25.tgz", + "integrity": "sha512-Iiv+IcappRRv6IBlknIVmLkXxfp51NEX1+l9f+dIbBuPU4PaRULegr1lCeHKsC45KU5ruxM5xMg4R/de03aJQg==", + "dependencies": { + "@babel/runtime": "^7.23.4", + "@floating-ui/react-dom": "^2.0.4", + "@mui/types": "^7.2.10", + "@mui/utils": "^5.14.19", + "@popperjs/core": "^2.11.8", + "clsx": "^2.0.0", + "prop-types": "^15.8.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "postcss": "^8.4" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@csstools/postcss-logical-viewport-units": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-1.0.2.tgz", - "integrity": "sha512-nnKFywBqRMYjv5jyjSplD/nbAnboUEGFfdxKw1o34Y1nvycgqjQavhKkmxbORxroBBIDwC5y6SfgENcPPUcOxQ==", - "dev": true, - "dependencies": { - "@csstools/css-tokenizer": "^2.0.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.19.tgz", + "integrity": "sha512-y4JseIen5pmZs1n9hHy95HKKioKco8f6N2lford2AmjJigVJOv0KsU0qryiCpyuEUZmi/xCduVilHsK9DSkPcA==", "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "url": "https://opencollective.com/mui-org" } }, - "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-1.0.1.tgz", - "integrity": "sha512-V9yQqXdje6OfqDf6EL5iGOpi6N0OEczwYK83rql9UapQwFEryXlAehR5AqH8QqLYb6+y31wUXK6vMxCp0920Zg==", - "dev": true, - "dependencies": { - "@csstools/css-parser-algorithms": "^2.0.0", - "@csstools/css-tokenizer": "^2.0.0", - "@csstools/media-query-list-parser": "^2.0.0" + "node_modules/@mui/material": { + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.19.tgz", + "integrity": "sha512-jSPLXst/YPgDGolhiu4rbethKjLVrI1IkoK8YrFUv8ygxDuhQdsE6+ZqjSSRXk3ytTMf6ghPnQ88OFRk4XjpNw==", + "dependencies": { + "@babel/runtime": "^7.23.4", + "@mui/base": "5.0.0-beta.25", + "@mui/core-downloads-tracker": "^5.14.19", + "@mui/system": "^5.14.19", + "@mui/types": "^7.2.10", + "@mui/utils": "^5.14.19", + "@types/react-transition-group": "^4.4.9", + "clsx": "^2.0.0", + "csstype": "^3.1.2", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "postcss": "^8.4" + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } } }, - "node_modules/@csstools/postcss-nested-calc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-2.0.2.tgz", - "integrity": "sha512-jbwrP8rN4e7LNaRcpx3xpMUjhtt34I9OV+zgbcsYAAk6k1+3kODXJBf95/JMYWhu9g1oif7r06QVUgfWsKxCFw==", - "dev": true, + "node_modules/@mui/private-theming": { + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.19.tgz", + "integrity": "sha512-U9w39VpXLGVM8wZlUU/47YGTsBSk60ZQRRxQZtdqPfN1N7OVllQeN4cEKZKR8PjqqR3aYRcSciQ4dc6CttRoXQ==", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@babel/runtime": "^7.23.4", + "@mui/utils": "^5.14.19", + "prop-types": "^15.8.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "postcss": "^8.4" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@csstools/postcss-normalize-display-values": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-2.0.1.tgz", - "integrity": "sha512-TQT5g3JQ5gPXC239YuRK8jFceXF9d25ZvBkyjzBGGoW5st5sPXFVQS8OjYb9IJ/K3CdfK4528y483cgS2DJR/w==", - "dev": true, + "node_modules/@mui/styled-engine": { + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.19.tgz", + "integrity": "sha512-jtj/Pyn/bS8PM7NXdFNTHWZfE3p+vItO4/HoQbUeAv3u+cnWXcTBGHHY/xdIn446lYGFDczTh1YyX8G4Ts0Rtg==", "dependencies": { - "postcss-value-parser": "^4.2.0" + "@babel/runtime": "^7.23.4", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "postcss": "^8.4" + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } } }, - "node_modules/@csstools/postcss-oklab-function": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-2.1.0.tgz", - "integrity": "sha512-U/odSNjOVhagNRu+RDaNVbn8vaqA9GyCOoneQA2je7697KOrtRDc7/POrYsP7QioO2aaezDzKNX02wBzc99fkQ==", - "dev": true, - "dependencies": { - "@csstools/color-helpers": "^1.0.0", - "@csstools/postcss-progressive-custom-properties": "^2.0.0", - "postcss-value-parser": "^4.2.0" + "node_modules/@mui/system": { + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.19.tgz", + "integrity": "sha512-4e3Q+2nx+vgEsd0h5ftxlZGB7XtkkPos/zWqCqnxUs1l/T70s0lF2YNrWHHdSQ7LgtBu0eQ0qweZG2pR7KwkAw==", + "dependencies": { + "@babel/runtime": "^7.23.4", + "@mui/private-theming": "^5.14.19", + "@mui/styled-engine": "^5.14.19", + "@mui/types": "^7.2.10", + "@mui/utils": "^5.14.19", + "clsx": "^2.0.0", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "postcss": "^8.4" + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } } }, - "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-2.1.0.tgz", - "integrity": "sha512-tRX1rinsXajZlc4WiU7s9Y6O9EdSHScT997zDsvDUjQ1oZL2nvnL6Bt0s9KyQZZTdC3lrG2PIdBqdOIWXSEPlQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, + "node_modules/@mui/types": { + "version": "7.2.10", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.10.tgz", + "integrity": "sha512-wX1vbDC+lzF7FlhT6A3ffRZgEoKWPF8VqRoTu4lZwouFX2t90KyCMsgepMw5DxLak1BSp/KP86CmtZttikb/gQ==", "peerDependencies": { - "postcss": "^8.4" + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@csstools/postcss-scope-pseudo-class": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-2.0.2.tgz", - "integrity": "sha512-6Pvo4uexUCXt+Hz5iUtemQAcIuCYnL+ePs1khFR6/xPgC92aQLJ0zGHonWoewiBE+I++4gXK3pr+R1rlOFHe5w==", - "dev": true, + "node_modules/@mui/utils": { + "version": "5.14.19", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.19.tgz", + "integrity": "sha512-qAHvTXzk7basbyqPvhgWqN6JbmI2wLB/mf97GkSlz5c76MiKYV6Ffjvw9BjKZQ1YRb8rDX9kgdjRezOcoB91oQ==", "dependencies": { - "postcss-selector-parser": "^6.0.10" + "@babel/runtime": "^7.23.4", + "@types/prop-types": "^15.7.11", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" }, "engines": { - "node": "^14 || ^16 || >=18" + "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "postcss": "^8.4" + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-2.1.0.tgz", - "integrity": "sha512-CkEo9BF8fQeMoXW3biXjlgTLY7PA4UFihn6leq7hPoRzIguLUI0WZIVgsITGXfX8LXmkhCSTjXO2DLYu/LUixQ==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "@csstools/css-calc": "^1.0.0", - "@csstools/css-parser-algorithms": "^2.0.1", - "@csstools/css-tokenizer": "^2.0.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">= 8" } }, - "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-2.2.1.tgz", - "integrity": "sha512-Ow6/cWWdjjVvA83mkm3kLRvvWsbzoe1AbJCxkpC+c9ibUjyS8pifm+LpZslQUKcxRVQ69ztKHDBEbFGTDhNeUw==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "dependencies": { - "@csstools/color-helpers": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">= 8" } }, - "node_modules/@csstools/postcss-trigonometric-functions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-2.0.1.tgz", - "integrity": "sha512-uGmmVWGHozyWe6+I4w321fKUC034OB1OYW0ZP4ySHA23n+r9y93K+1yrmW+hThpSfApKhaWySoD4I71LLlFUYQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "postcss-value-parser": "^4.2.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">= 8" } }, - "node_modules/@csstools/postcss-unset-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-2.0.1.tgz", - "integrity": "sha512-oJ9Xl29/yU8U7/pnMJRqAZd4YXNCfGEdcP4ywREuqm/xMqcgDNDppYRoCGDt40aaZQIEKBS79LytUDN/DHf0Ew==", + "node_modules/@openfonts/open-sans_all": { + "version": "1.44.2", + "resolved": "https://registry.npmjs.org/@openfonts/open-sans_all/-/open-sans_all-1.44.2.tgz", + "integrity": "sha512-SuLQ9tKnow0+ur62tHif7/HQ530h0EkxJuwPFngP2xLJb+hrGqF6OZGjXCZSSbEEsTbk3VxgY+fSbdaOWUP9Yw==" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "optional": true, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" + "node": ">=14" } }, - "node_modules/@csstools/selector-specificity": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz", - "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18" - }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "funding": { "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4", - "postcss-selector-parser": "^6.0.10" - } - }, - "node_modules/@emotion/babel-plugin": { - "version": "11.10.6", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", - "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/serialize": "^1.1.1", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.1.3" - } - }, - "node_modules/@emotion/cache": { - "version": "11.10.5", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", - "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", - "dependencies": { - "@emotion/memoize": "^0.8.0", - "@emotion/sheet": "^1.2.1", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "stylis": "4.1.3" - } - }, - "node_modules/@emotion/core": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@emotion/core/-/core-11.0.0.tgz", - "integrity": "sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA==" - }, - "node_modules/@emotion/css": { - "version": "11.10.6", - "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.10.6.tgz", - "integrity": "sha512-88Sr+3heKAKpj9PCqq5A1hAmAkoSIvwEq1O2TwDij7fUtsJpdkV4jMTISSTouFeRvsGvXIpuSuDQ4C1YdfNGXw==", - "dev": true, - "dependencies": { - "@emotion/babel-plugin": "^11.10.6", - "@emotion/cache": "^11.10.5", - "@emotion/serialize": "^1.1.1", - "@emotion/sheet": "^1.2.1", - "@emotion/utils": "^1.2.0" + "url": "https://opencollective.com/popperjs" } }, - "node_modules/@emotion/hash": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", - "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + "node_modules/@react-dnd/asap": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", + "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", - "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", - "dependencies": { - "@emotion/memoize": "^0.8.0" - } + "node_modules/@react-dnd/invariant": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", + "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" }, - "node_modules/@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + "node_modules/@react-dnd/shallowequal": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", + "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, - "node_modules/@emotion/react": { - "version": "11.10.6", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", - "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "node_modules/@reduxjs/toolkit": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz", + "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==", "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.10.6", - "@emotion/cache": "^11.10.5", - "@emotion/serialize": "^1.1.1", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "hoist-non-react-statics": "^3.3.1" + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" }, "peerDependencies": { - "react": ">=16.8.0" + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" }, "peerDependenciesMeta": { - "@types/react": { + "react": { + "optional": true + }, + "react-redux": { "optional": true } } }, - "node_modules/@emotion/serialize": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", - "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", - "dependencies": { - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/unitless": "^0.8.0", - "@emotion/utils": "^1.2.0", - "csstype": "^3.0.2" - } - }, - "node_modules/@emotion/server": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.10.0.tgz", - "integrity": "sha512-MTvJ21JPo9aS02GdjFW4nhdwOi2tNNpMmAM/YED0pkxzjDNi5WbiTwXqaCnvLc2Lr8NFtjhT0az1vTJyLIHYcw==", + "node_modules/@rollup/plugin-yaml": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-yaml/-/plugin-yaml-4.1.2.tgz", + "integrity": "sha512-RpupciIeZMUqhgFE97ba0s98mOFS7CWzN3EJNhJkqSv9XLlWYtwVdtE6cDw6ASOF/sZVFS7kRJXftaqM2Vakdw==", "dev": true, "dependencies": { - "@emotion/utils": "^1.2.0", - "html-tokenize": "^2.0.0", - "multipipe": "^1.0.2", - "through": "^2.3.8" + "@rollup/pluginutils": "^5.0.1", + "js-yaml": "^4.1.0", + "tosource": "^2.0.0-alpha.3" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "@emotion/css": "^11.0.0-rc.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { - "@emotion/css": { + "rollup": { "optional": true } } }, - "node_modules/@emotion/sheet": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", - "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" - }, - "node_modules/@emotion/styled": { - "version": "11.10.6", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", - "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.10.6", - "@emotion/is-prop-valid": "^1.2.0", - "@emotion/serialize": "^1.1.1", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@emotion/utils": "^1.2.0" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { - "@types/react": { + "rollup": { "optional": true } } }, - "node_modules/@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", - "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emotion/utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", - "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", - "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" - }, - "node_modules/@esbuild/android-arm": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", - "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.6.1.tgz", + "integrity": "sha512-0WQ0ouLejaUCRsL93GD4uft3rOmB8qoQMU05Kb8CmMtMBe7XUDLAltxVZI1q6byNqEtU7N1ZX1Vw5lIpgulLQA==", "cpu": [ "arm" ], @@ -2663,15 +2742,12 @@ "optional": true, "os": [ "android" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/android-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", - "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.6.1.tgz", + "integrity": "sha512-1TKm25Rn20vr5aTGGZqo6E4mzPicCUD79k17EgTLAsXc1zysyi4xXKACfUbwyANEPAEIxkzwue6JZ+stYzWUTA==", "cpu": [ "arm64" ], @@ -2679,31 +2755,12 @@ "optional": true, "os": [ "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", - "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", - "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.6.1.tgz", + "integrity": "sha512-cEXJQY/ZqMACb+nxzDeX9IPLAg7S94xouJJCNVE5BJM8JUEP4HeTF+ti3cmxWeSJo+5D+o8Tc0UAWUkfENdeyw==", "cpu": [ "arm64" ], @@ -2711,15 +2768,12 @@ "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", - "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.6.1.tgz", + "integrity": "sha512-LoSU9Xu56isrkV2jLldcKspJ7sSXmZWkAxg7sW/RfF7GS4F5/v4EiqKSMCFbZtDu2Nc1gxxFdQdKwkKS4rwxNg==", "cpu": [ "x64" ], @@ -2727,47 +2781,12 @@ "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", - "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", - "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-arm": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", - "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.6.1.tgz", + "integrity": "sha512-EfI3hzYAy5vFNDqpXsNxXcgRDcFHUWSx5nnRSCKwXuQlI5J9dD84g2Usw81n3FLBNsGCegKGwwTVsSKK9cooSQ==", "cpu": [ "arm" ], @@ -2775,15 +2794,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", - "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.6.1.tgz", + "integrity": "sha512-9lhc4UZstsegbNLhH0Zu6TqvDfmhGzuCWtcTFXY10VjLLUe4Mr0Ye2L3rrtHaDd/J5+tFMEuo5LTCSCMXWfUKw==", "cpu": [ "arm64" ], @@ -2791,2659 +2807,2460 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", - "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.6.1.tgz", + "integrity": "sha512-FfoOK1yP5ksX3wwZ4Zk1NgyGHZyuRhf99j64I5oEmirV8EFT7+OhUZEnP+x17lcP/QHJNWGsoJwrz4PJ9fBEXw==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", - "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.6.1.tgz", + "integrity": "sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==", "cpu": [ - "loong64" + "x64" ], "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", - "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.6.1.tgz", + "integrity": "sha512-RkJVNVRM+piYy87HrKmhbexCHg3A6Z6MU0W9GHnJwBQNBeyhCJG9KDce4SAMdicQnpURggSvtbGo9xAWOfSvIQ==", "cpu": [ - "mips64el" + "x64" ], "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", - "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.6.1.tgz", + "integrity": "sha512-v2FVT6xfnnmTe3W9bJXl6r5KwJglMK/iRlkKiIFfO6ysKs0rDgz7Cwwf3tjldxQUrHL9INT/1r4VA0n9L/F1vQ==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", - "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.6.1.tgz", + "integrity": "sha512-YEeOjxRyEjqcWphH9dyLbzgkF8wZSKAKUkldRY6dgNR5oKs2LZazqGB41cWJ4Iqqcy9/zqYgmzBkRoVz3Q9MLw==", "cpu": [ - "riscv64" + "ia32" ], "dev": true, "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", - "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.6.1.tgz", + "integrity": "sha512-0zfTlFAIhgz8V2G8STq8toAjsYYA6eci1hnXuyOTUFnymrtJwnS6uGKiv3v5UrPZkBlamLvrLV2iiaeqCKzb0A==", "cpu": [ - "s390x" + "x64" ], "dev": true, "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/@esbuild/linux-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", - "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", - "cpu": [ - "x64" - ], + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", - "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", - "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", - "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", - "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/@tanstack/react-virtual": { + "version": "3.0.0-beta.68", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.0-beta.68.tgz", + "integrity": "sha512-YEFNCf+N3ZlNou2r4qnh+GscMe24foYEjTL05RS0ZHvah2RoUDPGuhnuedTv0z66dO2vIq6+Bl4TXatht5T7GQ==", + "dependencies": { + "@tanstack/virtual-core": "3.0.0-beta.68" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", - "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/@tanstack/virtual-core": { + "version": "3.0.0-beta.68", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0-beta.68.tgz", + "integrity": "sha512-CnvsEJWK7cugigckt13AeY80FMzH+OMdEP0j0bS3/zjs44NiRe49x8FZC6R9suRXGMVMXtUHet0zbTp/Ec9Wfg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", - "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", - "cpu": [ - "x64" - ], + "node_modules/@testing-library/dom": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz", + "integrity": "sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", - "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "node_modules/@testing-library/jest-dom": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.1.5.tgz", + "integrity": "sha512-3y04JLW+EceVPy2Em3VwNr95dOKqA8DhR0RJHhHKDZNYXcVXnEK7WIrpj4eYU8SVt/qYZ2aRWt/WgQ+grNES8g==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@adobe/css-tools": "^4.3.1", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "@jest/globals": ">= 28", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/@testing-library/react": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.1.2.tgz", + "integrity": "sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": ">=8" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@testing-library/user-event": { + "version": "14.5.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.1.tgz", + "integrity": "sha512-UCcUKrUYGj7ClomOo2SpNVvx4/fkd/2BbIHDCle8A0ax+P3bU7yJwDBDrS6ZwdTMARWTGODX1hEsCcO+7beJjg==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12", + "npm": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/@f/cookies-enabled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@f/cookies-enabled/-/cookies-enabled-1.1.1.tgz", - "integrity": "sha512-7QSJQAFje3K8NluCwcs+txJhe5AhZDViG0OrJK4yfuFJw/kw+oha5hp3KZ/DFyNYde2O2oEeDX6kA5p7FEPZ+w==", + "node_modules/@types/babel__generator": { + "version": "7.6.7", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.7.tgz", + "integrity": "sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==", + "dev": true, "dependencies": { - "@f/is-undefined": "^1.0.0" + "@babel/types": "^7.0.0" } }, - "node_modules/@f/is-undefined": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@f/is-undefined/-/is-undefined-1.1.1.tgz", - "integrity": "sha512-i92CKmXRvw/skYbwBE9eHdwNGbJshI/kwQMJ65ktMtAsRWNMuQis1BSsnpaGZaFEANI1L1o90YKh6g+YI/aB/Q==" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@types/babel__traverse": { + "version": "7.20.4", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz", + "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==", "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "dependencies": { + "@babel/types": "^7.20.7" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "node_modules/@types/chai": { + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", + "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", "dev": true }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@types/chai-subset": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz", + "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==", "dev": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" + "@types/chai": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dependencies": { - "sprintf-js": "~1.0.2" + "@types/ms": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, + "node_modules/@types/hast": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.8.tgz", + "integrity": "sha512-aMIqAlFd2wTIDZuvLbhUT+TGvMxrNC8ECUIVtH6xxy0sQLs3iu6NO8Kp/VT5je7i5ufnebXzdV1dNDMnvaH6IQ==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "@types/unist": "^2" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "@types/unist": "^2" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, - "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", - "dev": true, + "node_modules/@types/node": { + "version": "20.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz", + "integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==", + "devOptional": true, "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "undici-types": "~5.26.4" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/parse5": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", + "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + }, + "node_modules/@types/react": { + "version": "18.2.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.39.tgz", + "integrity": "sha512-Oiw+ppED6IremMInLV4HXGbfbG6GyziY3kqAwJYOR0PNbkYDmLWQA3a95EhdSmamsvbkJN96ZNN+YD+fGjzSBA==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/@types/react-dom": { + "version": "18.2.17", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.17.tgz", + "integrity": "sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==", + "devOptional": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@types/react": "*" } }, - "node_modules/@jest/console/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/@types/react-transition-group": { + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.9.tgz", + "integrity": "sha512-ZVNmWumUIh5NhH8aMD9CR2hdW0fNuYInlocZHaZ+dgk/1K49j1w/HoAuK1ki+pgscQrOFRTlXeoURtuzEkV3dg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@types/react": "*" } }, - "node_modules/@jest/console/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, - "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, + "node_modules/@types/youtube": { + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/@types/youtube/-/youtube-0.0.46.tgz", + "integrity": "sha512-Yf1Y4bDj/QIn8v+zdy0l7+OW6s1uoUvzVn5cGqPNCsL4iUW4gYUlIdQIRtH9NOHVgwZNLbVeeRDEn6N4RMq6Nw==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", + "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/type-utils": "6.13.1", + "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "node-notifier": { + "typescript": { "optional": true } } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@typescript-eslint/parser": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", + "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", + "debug": "^4.3.4" }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", + "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1" }, "engines": { - "node": ">=10" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", + "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/utils": "6.13.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=7.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@typescript-eslint/types": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", + "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", "dev": true, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", + "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/visitor-keys": "6.13.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@typescript-eslint/utils": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", + "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.13.1", + "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.1", + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", + "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0" + "@typescript-eslint/types": "6.13.1", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", - "dev": true, - "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "node": "^16.0.0 || >=18.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", - "dev": true, + "node_modules/@u-wave/react-server-list": { + "version": "5.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@u-wave/react-server-list/-/react-server-list-5.0.0-beta.3.tgz", + "integrity": "sha512-9pGeEofmAfs60tlDvigYjFCFHbJ+ok0xGaP99TF9arNQJfLWv+gEWJBilWgp+gUxRBD2eLtzwCT2eIff30cflA==", "dependencies": { - "jest-get-type": "^29.4.3" + "@babel/runtime": "^7.13.10", + "@mui/material": "^5.0.0", + "ms": "3.0.0-canary.1", + "node-fetch": "^3.0.0", + "prop-types": "^15.7.2", + "react-markdown": "^8.0.2", + "strip-indent": "^4.0.0", + "swr": "^1.0.0" }, + "peerDependencies": { + "react": "^16.14.0 || >= 17.0.0" + } + }, + "node_modules/@u-wave/react-server-list/node_modules/ms": { + "version": "3.0.0-canary.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-3.0.0-canary.1.tgz", + "integrity": "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.13" } }, - "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", - "dev": true, + "node_modules/@u-wave/react-server-list/node_modules/swr": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz", + "integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==", + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@u-wave/react-translate": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@u-wave/react-translate/-/react-translate-2.0.2.tgz", + "integrity": "sha512-ddgZEF6L1cdPmnLBnm8BGIuvuU2RMxd1N9JT9FAoIOFyttgOKx0goI7s79JmYbn/+MGnSinSOGMQnXtLdW2zoA==", "dependencies": { - "@jest/types": "^29.5.0", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "prop-types": "^15.7.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" } }, - "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", - "dev": true, + "node_modules/@u-wave/react-youtube": { + "version": "1.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@u-wave/react-youtube/-/react-youtube-1.0.0-alpha.4.tgz", + "integrity": "sha512-xW+psfEfmCWtWqZlQlTuQpNkxBrtpy8oK7X+u+0m4piMw4dS9hQpRVxdWxEcDPAS0TWKRKURjwlbxH8fHkfZaA==", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@types/react": "^17.0.0 || ^18.0.0", + "@types/youtube": "0.0.46", + "prop-types": "^15.7.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" } }, - "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "node_modules/@u-wave/translate": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@u-wave/translate/-/translate-1.1.1.tgz", + "integrity": "sha512-+YE7AYk/6e7aDWeIc67HJHSU1duiJ28eyvktfjJhXz6SzLMBUaJ7etjvs/ZkBLAJPHCIF9uc8jCCJnNboPJNog==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.0.tgz", + "integrity": "sha512-+MHTH/e6H12kRp5HUkzOGqPMksezRMmW+TNzlh/QXfI8rRf6l2Z2yH/v12no1UvTwhZgEDMuQ7g7rrfMseU6FQ==", "dev": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "@babel/core": "^7.23.3", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.4", + "react-refresh": "^0.14.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "vite": "^4.2.0 || ^5.0.0" } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@vitest/coverage-v8": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.6.tgz", + "integrity": "sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.1.5", + "magic-string": "^0.30.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": ">=0.32.0 <1" } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@vitest/expect": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/vitest" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@vitest/runner": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/reporters/node_modules/has-flag": { + "node_modules/@vitest/runner/node_modules/p-limit": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.25.16" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "node_modules/@vitest/snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "node_modules/@vitest/snapshot/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "slash": "^3.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", "dev": true, "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "tinyspy": "^2.1.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/vitest" } }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=7.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "node_modules/abortcontroller-polyfill": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", + "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==" }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.4.0" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "debug": "^4.3.4" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 14" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "node_modules/archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "file-type": "^4.2.0" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/archive-type/node_modules/file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "deep-equal": "^2.0.5" } }, - "node_modules/@mdi/js": { - "version": "7.1.96", - "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.1.96.tgz", - "integrity": "sha512-wlrJs6Ryhaa5CqhK3FjTfMRnb/s7HeLkKMFqwQySkK86cdN1TGdzpSM3O4tsmzCA1dYBeTbXvOwSE/Y42cUrvA==" + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@mdn/browser-compat-data": { - "version": "5.2.41", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.2.41.tgz", - "integrity": "sha512-AVSFtoO5nyuxcDethZZOrlT87wkBY7A9BCAHRLxb2ARIdglSlAbQDXSg1yVHRFf/8ORWs2cbmKK4c6keRJWagw==", - "dev": true + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/@mui/base": { - "version": "5.0.0-alpha.119", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.119.tgz", - "integrity": "sha512-XA5zhlYfXi67u613eIF0xRmktkatx6ERy3h+PwrMN5IcWFbgiL1guz8VpdXON+GWb8+G7B8t5oqTFIaCqaSAeA==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "@emotion/is-prop-valid": "^1.2.0", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.11", - "@popperjs/core": "^2.11.6", - "clsx": "^1.2.1", - "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/core-downloads-tracker": { - "version": "5.11.12", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.12.tgz", - "integrity": "sha512-LHh8HZQ5nPVcW5QnyLwkAZ40txc/S2bzKMQ3bTO+5mjuwAJ2AzQrjZINLVy1geY7ei1pHXVqO1hcWHg/QdT44w==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@mui/material": { - "version": "5.11.12", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.12.tgz", - "integrity": "sha512-M6BiIeJjySeEzWeiFJQ9pIjJy6mx5mHPWeMT99wjQdAmA2GxCQhE9A0fh6jQP4jMmYzxhOIhjsGcp0vSdpseXg==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "@mui/base": "5.0.0-alpha.119", - "@mui/core-downloads-tracker": "^5.11.12", - "@mui/system": "^5.11.12", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.12", - "@types/react-transition-group": "^4.4.5", - "clsx": "^1.2.1", - "csstype": "^3.1.1", - "prop-types": "^15.8.1", - "react-is": "^18.2.0", - "react-transition-group": "^4.4.5" - }, - "engines": { - "node": ">=12.0.0" + "node_modules/array.from": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/array.from/-/array.from-1.1.5.tgz", + "integrity": "sha512-o+V2b5T8GQ3sudAlmezn/PujHjzDIMd/dQy/WKPK0nL0TIlhUFvXCwsyUpaUMAjldyWapDk0ZnIegxnDpc0PBw==", + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "node_modules/array.prototype.find": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.2.tgz", + "integrity": "sha512-DRumkfW97iZGOfn+lIXbkVrXL04sfYKX+EfOodo8XboR5sxPDVvOjZTF/rysusa9lmhmSOeD6Vp6RKQP+eP4Tg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/private-theming": { - "version": "5.11.12", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.12.tgz", - "integrity": "sha512-hnJ0svNI1TPeWZ18E6DvES8PB4NyMLwal6EyXf69rTrYqT6wZPLjB+HiCYfSOCqU/fwArhupSqIIkQpDs8CkAw==", + "node_modules/array.prototype.findindex": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findindex/-/array.prototype.findindex-2.2.2.tgz", + "integrity": "sha512-fnTMT+Xq/VloVDsroPW9JLL1M5UxNTVfoNxU4KeyDcH5C/Jmjikf5+KDH5207wWMC8MBlSOn7kZkkys8XnqWNg==", "dependencies": { - "@babel/runtime": "^7.21.0", - "@mui/utils": "^5.11.12", - "prop-types": "^15.8.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/styled-engine": { - "version": "5.11.11", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.11.tgz", - "integrity": "sha512-wV0UgW4lN5FkDBXefN8eTYeuE9sjyQdg5h94vtwZCUamGQEzmCOtir4AakgmbWMy0x8OLjdEUESn9wnf5J9MOg==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.21.0", - "@emotion/cache": "^11.10.5", - "csstype": "^3.1.1", - "prop-types": "^15.8.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/system": { - "version": "5.11.12", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.12.tgz", - "integrity": "sha512-sYjsXkiwKpZDC3aS6O/6KTjji0jGINLQcrD5EJ5NTkIDiLf19I4HJhnufgKqlTWNfoDBlRohuTf3TzfM06c4ug==", - "dependencies": { - "@babel/runtime": "^7.21.0", - "@mui/private-theming": "^5.11.12", - "@mui/styled-engine": "^5.11.11", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.12", - "clsx": "^1.2.1", - "csstype": "^3.1.1", - "prop-types": "^15.8.1" + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/types": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.3.tgz", - "integrity": "sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==", - "peerDependencies": { - "@types/react": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/array.prototype.tosorted": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", + "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" } }, - "node_modules/@mui/utils": { - "version": "5.11.12", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.12.tgz", - "integrity": "sha512-5vH9B/v8pzkpEPO2HvGM54ToXV6cFdAn8UrvdN8TMEEwpn/ycW0jLiyBcgUlPsQ+xha7hqXCPQYHaYFDIcwaiw==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", "dependencies": { - "@babel/runtime": "^7.21.0", - "@types/prop-types": "^15.7.5", - "@types/react-is": "^16.7.1 || ^17.0.0", - "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "engines": { - "node": ">= 8" + "node": "*" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/ast-metadata-inferer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz", + "integrity": "sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" + "@mdn/browser-compat-data": "^5.2.34" } }, - "node_modules/@openfonts/open-sans_all": { - "version": "1.44.2", - "resolved": "https://registry.npmjs.org/@openfonts/open-sans_all/-/open-sans_all-1.44.2.tgz", - "integrity": "sha512-SuLQ9tKnow0+ur62tHif7/HQ530h0EkxJuwPFngP2xLJb+hrGqF6OZGjXCZSSbEEsTbk3VxgY+fSbdaOWUP9Yw==" + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true }, - "node_modules/@popperjs/core": { - "version": "2.11.6", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", - "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/@react-dnd/asap": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", - "integrity": "sha512-WLyfoHvxhs0V9U+GTsGilGgf2QsPl6ZZ44fnv0/b8T3nQyvzxidxsg/ZltbWssbsRDlYW8UKSQMTGotuTotZ6A==" - }, - "node_modules/@react-dnd/invariant": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@react-dnd/invariant/-/invariant-4.0.2.tgz", - "integrity": "sha512-xKCTqAK/FFauOM9Ta2pswIyT3D8AQlfrYdOi/toTPEhqCuAs1v5tcJ3Y08Izh1cJ5Jchwy9SeAXmMg6zrKs2iw==" + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } }, - "node_modules/@react-dnd/shallowequal": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-4.0.2.tgz", - "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, - "node_modules/@rollup/plugin-yaml": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-yaml/-/plugin-yaml-4.0.1.tgz", - "integrity": "sha512-eyftkLWrwaGhgad+gXmisPYXeW3hP1s+lz63mgbur+F/8aKZhPG1Bf8RFNnz0Vhnf3uBimFebZBDwwz6X4KqUQ==", + "node_modules/autoprefixer": { + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "js-yaml": "^4.1.0", - "tosource": "^2.0.0-alpha.3" + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" }, "engines": { - "node": ">=14.0.0" + "node": "^10 || ^12 || >=14" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "postcss": "^8.1.0" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true - }, - "node_modules/@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "dequal": "^2.0.3" } }, - "node_modules/@tanstack/react-virtual": { - "version": "3.0.0-beta.54", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.0-beta.54.tgz", - "integrity": "sha512-D1mDMf4UPbrtHRZZriCly5bXTBMhylslm4dhcHqTtDJ6brQcgGmk8YD9JdWBGWfGSWPKoh2x1H3e7eh+hgPXtQ==", + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", "dependencies": { - "@tanstack/virtual-core": "3.0.0-beta.54" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "engines": { + "node": ">=10", + "npm": ">=6" } }, - "node_modules/@tanstack/virtual-core": { - "version": "3.0.0-beta.54", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0-beta.54.tgz", - "integrity": "sha512-jtkwqdP2rY2iCCDVAFuaNBH3fiEi29aTn2RhtIoky8DTTiCdc48plpHHreLwmv1PICJ4AJUUESaq3xa8fZH8+g==", + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "funding": { "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/@testing-library/dom": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.0.1.tgz", - "integrity": "sha512-fTOVsMY9QLFCCXRHG3Ese6cMH5qIWwSbgxZsgeF5TNsy81HKaZ4kgehnSF8FsR3OF+numlIV2YcU79MzbnhSig==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" } }, - "node_modules/@testing-library/dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/@testing-library/dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "safe-buffer": "~5.1.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/@testing-library/dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } }, - "node_modules/@testing-library/dom/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@testing-library/dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/@testing-library/jest-dom": { - "version": "5.16.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", - "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "@adobe/css-tools": "^4.0.1", - "@babel/runtime": "^7.9.2", - "@types/testing-library__jest-dom": "^5.9.1", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.5.6", - "lodash": "^4.17.15", - "redent": "^3.0.0" + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" }, "engines": { - "node": ">=8", - "npm": ">=6", - "yarn": ">=1" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" } }, - "node_modules/@testing-library/jest-dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": "*" } }, - "node_modules/@testing-library/jest-dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", "dev": true }, - "node_modules/@testing-library/jest-dom/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/buffer-from": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", + "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", + "dev": true + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/@testing-library/jest-dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/@testing-library/react": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz", - "integrity": "sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==", + "node_modules/cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" } }, - "node_modules/@testing-library/user-event": { - "version": "14.4.3", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", - "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", "dev": true, "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" + "node": ">=4" } }, - "node_modules/@types/aria-query": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", - "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", + "node_modules/cacheable-request/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", "dev": true }, - "node_modules/@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "node_modules/cacheable-request/node_modules/keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", "dev": true, "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "json-buffer": "3.0.0" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==", "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "@babel/types": "^7.3.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, "dependencies": { - "@types/ms": "*" + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/estree": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", - "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==", - "dev": true + "node_modules/caniuse-lite": { + "version": "1.0.30001565", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz", + "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", "dev": true, "dependencies": { - "@types/node": "*" + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@types/unist": "*" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "dependencies": { - "@types/istanbul-lib-coverage": "*" + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, - "node_modules/@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", "dev": true, "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "mimic-response": "^1.0.0" } }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6" } }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@types/jsdom": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", - "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" + "node": ">=7.0.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, - "node_modules/@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { - "@types/unist": "*" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "node_modules/@types/node": { - "version": "18.15.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.1.tgz", - "integrity": "sha512-U2TWca8AeHSmbpi314QBESRk7oPjSZjDsR+c+H4ECC1l+kFgpZf8Ydhv3SJpPy51VyZHHqxlb6mTTqYNNRVAIw==", - "devOptional": true + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" - }, - "node_modules/@types/parse5": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", - "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" - }, - "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true }, - "node_modules/@types/react": { - "version": "18.0.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", - "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/react-dom": { - "version": "18.0.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", - "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", - "devOptional": true, - "dependencies": { - "@types/react": "*" + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/react-is": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", - "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", - "dependencies": { - "@types/react": "*" - } + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "node_modules/@types/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", - "dependencies": { - "@types/react": "*" + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, - "node_modules/@types/testing-library__jest-dom": { - "version": "5.14.5", - "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", - "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", - "dev": true, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dependencies": { - "@types/jest": "*" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", - "dev": true - }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" - }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", - "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" - }, - "node_modules/@types/yargs": { - "version": "17.0.22", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", - "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@types/youtube": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/@types/youtube/-/youtube-0.0.46.tgz", - "integrity": "sha512-Yf1Y4bDj/QIn8v+zdy0l7+OW6s1uoUvzVn5cGqPNCsL4iUW4gYUlIdQIRtH9NOHVgwZNLbVeeRDEn6N4RMq6Nw==" - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz", - "integrity": "sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==", + "node_modules/css-blank-pseudo": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-6.0.0.tgz", + "integrity": "sha512-VbfLlOWO7sBHBTn6pwDQzc07Z0SDydgDBfNfCE0nvrehdBNv9RKsuupIRa/qal0+fBZhAALyQDPMKz5lnvcchw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/visitor-keys": "5.54.1" + "postcss-selector-parser": "^6.0.13" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz", - "integrity": "sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==", + "node_modules/css-functions-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=12 || >=16" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz", - "integrity": "sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==", + "node_modules/css-has-pseudo": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-6.0.0.tgz", + "integrity": "sha512-X+r+JBuoO37FBOWVNhVJhxtSBUFHgHbrcc0CjFT28JEdOw1qaDwABv/uunyodUuSy2hMPe9j/HjssxSlvUmKjg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/visitor-keys": "5.54.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@csstools/selector-specificity": "^3.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^14 || ^16 || >=18" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/css-prefers-color-scheme": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-9.0.0.tgz", + "integrity": "sha512-03QGAk/FXIRseDdLb7XAiu6gidQ0Nd8945xuM7VFVPpc6goJsG9uIO8xQjTxwbPdPIIV4o4AJoOJyt8gwDl67g==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { - "node": ">=10" + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">=10" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz", - "integrity": "sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.54.1", - "@typescript-eslint/types": "5.54.1", - "@typescript-eslint/typescript-estree": "5.54.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, + "node_modules/css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + "node_modules/cssdb": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.9.0.tgz", + "integrity": "sha512-WPMT9seTQq6fPAa1yN4zjgZZeoTriSN2LqW9C+otjar12DQIWA4LuSfFrvFJiKp4oD0xIk1vumDLw8K9ur4NBw==", "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, "engines": { - "node": ">=4.0" + "node": ">=4" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/cssstyle": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-3.0.0.tgz", + "integrity": "sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "rrweb-cssom": "^0.6.0" }, "engines": { - "node": ">=10" + "node": ">=14" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz", - "integrity": "sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==", + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.54.1", - "eslint-visitor-keys": "^3.3.0" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=18" } }, - "node_modules/@u-wave/react-server-list": { - "version": "5.0.0-beta.3", - "resolved": "https://registry.npmjs.org/@u-wave/react-server-list/-/react-server-list-5.0.0-beta.3.tgz", - "integrity": "sha512-9pGeEofmAfs60tlDvigYjFCFHbJ+ok0xGaP99TF9arNQJfLWv+gEWJBilWgp+gUxRBD2eLtzwCT2eIff30cflA==", + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "@babel/runtime": "^7.13.10", - "@mui/material": "^5.0.0", - "ms": "3.0.0-canary.1", - "node-fetch": "^3.0.0", - "prop-types": "^15.7.2", - "react-markdown": "^8.0.2", - "strip-indent": "^4.0.0", - "swr": "^1.0.0" + "ms": "2.1.2" }, - "peerDependencies": { - "react": "^16.14.0 || >= 17.0.0" - } - }, - "node_modules/@u-wave/react-server-list/node_modules/ms": { - "version": "3.0.0-canary.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-3.0.0-canary.1.tgz", - "integrity": "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==", "engines": { - "node": ">=12.13" - } - }, - "node_modules/@u-wave/react-server-list/node_modules/swr": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz", - "integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==", - "peerDependencies": { - "react": "^16.11.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@u-wave/react-translate": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@u-wave/react-translate/-/react-translate-2.0.2.tgz", - "integrity": "sha512-ddgZEF6L1cdPmnLBnm8BGIuvuU2RMxd1N9JT9FAoIOFyttgOKx0goI7s79JmYbn/+MGnSinSOGMQnXtLdW2zoA==", - "dependencies": { - "prop-types": "^15.7.2" + "node": ">=6.0" }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@u-wave/react-youtube": { - "version": "1.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/@u-wave/react-youtube/-/react-youtube-1.0.0-alpha.4.tgz", - "integrity": "sha512-xW+psfEfmCWtWqZlQlTuQpNkxBrtpy8oK7X+u+0m4piMw4dS9hQpRVxdWxEcDPAS0TWKRKURjwlbxH8fHkfZaA==", - "dependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "@types/youtube": "0.0.46", - "prop-types": "^15.7.2" + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "engines": { + "node": ">=10" }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@u-wave/translate": { + "node_modules/decamelize-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@u-wave/translate/-/translate-1.1.1.tgz", - "integrity": "sha512-+YE7AYk/6e7aDWeIc67HJHSU1duiJ28eyvktfjJhXz6SzLMBUaJ7etjvs/ZkBLAJPHCIF9uc8jCCJnNboPJNog==" - }, - "node_modules/@vitejs/plugin-react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz", - "integrity": "sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "dependencies": { - "@babel/core": "^7.20.12", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", - "@babel/plugin-transform-react-jsx-source": "^7.19.6", - "magic-string": "^0.27.0", - "react-refresh": "^0.14.0" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=0.10.0" }, - "peerDependencies": { - "vite": "^4.1.0-beta.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "node_modules/abortcontroller-polyfill": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz", - "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/acorn-globals": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", - "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", - "dev": true, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", "dependencies": { - "acorn": "^8.1.0", - "acorn-walk": "^8.0.2" + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "engines": { + "node": ">=0.10" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", "dev": true, + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=4" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", "dev": true, "dependencies": { - "debug": "4" + "mimic-response": "^1.0.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=4" } }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", "dev": true, "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/decompress-tar/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=4" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" }, "engines": { "node": ">=4" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/decompress-targz/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "node_modules/archive-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", - "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==", + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", "dev": true, "dependencies": { - "file-type": "^4.2.0" + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" }, "engines": { "node": ">=4" } }, - "node_modules/archive-type/node_modules/file-type": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "node_modules/decompress-unzip/node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "node_modules/decompress-unzip/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "node_modules/decompress/node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" + "pify": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/decompress/node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/array.from": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.from/-/array.from-1.1.4.tgz", - "integrity": "sha512-EM9PLfGiBB4Qo5QKJ/Fy0n/2eC5dyAKI+/KqPPK+Ojzdb1TgDNzZBnDHFrfNVU9Uq2CIIWQaVmaS7O0Nkjr7AA==", + "node_modules/decompress/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, "dependencies": { - "define-properties": "^1.2.0", - "es-abstract": "^1.21.1" + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/array.prototype.find": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.1.tgz", - "integrity": "sha512-I2ri5Z9uMpMvnsNrHre9l3PaX+z9D0/z6F7Yt2u15q7wt0I62g5kX6xUKR1SJiefgG+u2/gJUmM8B47XRvQR6w==", + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.findindex": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/array.prototype.findindex/-/array.prototype.findindex-2.2.1.tgz", - "integrity": "sha512-tMj4uTmGpaGUh4XFMUh3H7KYAIqlygrlXchOEVTiICbTwRwMhDqtzsOwvtI+WAf1GdjJBeIP3Bu92Qg0SnXdtA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -5452,3894 +5269,451 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/ast-metadata-inferer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.7.0.tgz", - "integrity": "sha512-OkMLzd8xelb3gmnp6ToFvvsHLtS6CbagTkFQvQ+ZYFe3/AIl9iKikNR9G7pY3GfOR/2Xc222hwBjzI7HLkE76Q==", - "dev": true, - "dependencies": { - "@mdn/browser-compat-data": "^3.3.14" + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" } }, - "node_modules/ast-metadata-inferer/node_modules/@mdn/browser-compat-data": { - "version": "3.3.14", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-3.3.14.tgz", - "integrity": "sha512-n2RC9d6XatVbWFdHLimzzUJxJ1KY8LdjqrW6YvGPiRmsHkhOUx74/Ct10x5Yo7bC/Jvqx7cDEW8IMPv/+vwEzA==", - "dev": true + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", - "dev": true + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "engines": { + "node": ">=0.3.1" + } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/autoprefixer": { - "version": "10.4.14", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", - "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], "dependencies": { - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001464", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" + "path-type": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=8" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "dependencies": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" } }, - "node_modules/axe-core": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", - "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "dependencies": { - "deep-equal": "^2.0.5" + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" } }, - "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", - "dev": true, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dependencies": { - "@jest/transform": "^29.5.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "domelementtype": "^2.2.0" }, "engines": { - "node": ">=10" + "node": ">= 4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/babel-jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dependencies": { - "color-name": "~1.1.4" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/babel-jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/download": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/download/-/download-8.0.0.tgz", + "integrity": "sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "archive-type": "^4.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.2.1", + "ext-name": "^5.0.0", + "file-type": "^11.1.0", + "filenamify": "^3.0.0", + "get-stream": "^4.1.0", + "got": "^8.3.1", + "make-dir": "^2.1.0", + "p-event": "^2.1.0", + "pify": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/download/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "node_modules/download/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "semver": "bin/semver" } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, + "node_modules/dset": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", "engines": { - "node": ">=10", - "npm": ">=6" + "node": ">=4" } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "readable-stream": "^2.0.2" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/babel-plugin-transform-react-remove-prop-types": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", - "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "safe-buffer": "~5.1.0" } }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bl/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/bl/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", - "dev": true - }, - "node_modules/buffer-from": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-request": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", - "integrity": "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==", - "dev": true, - "dependencies": { - "clone-response": "1.0.2", - "get-stream": "3.0.0", - "http-cache-semantics": "3.8.1", - "keyv": "3.0.0", - "lowercase-keys": "1.0.0", - "normalize-url": "2.0.1", - "responselike": "1.0.2" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001465", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001465.tgz", - "integrity": "sha512-HvjgL3MYAJjceTDCcjRnQGjwUz/5qec9n7JPOzUursUoOTIsYCSDOb1l7RsnZE8mjbxG78zVRCKfrBXyvChBag==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/core-js-compat": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.1.tgz", - "integrity": "sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/cross-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/cross-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/cross-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-blank-pseudo": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-5.0.2.tgz", - "integrity": "sha512-aCU4AZ7uEcVSUzagTlA9pHciz7aWPKA/YzrEkpdSopJ2pvhIxiQ5sYeMz1/KByxlIo4XBdvMNJAVKMg/GRnhfw==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-functions-list": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", - "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", - "dev": true, - "engines": { - "node": ">=12.22" - } - }, - "node_modules/css-has-pseudo": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-5.0.2.tgz", - "integrity": "sha512-q+U+4QdwwB7T9VEW/LyO6CFrLAeLqOykC5mDqJXc7aKZAhDbq7BvGT13VGJe+IwBfdN2o3Xdw2kJ5IxwV1Sc9Q==", - "dev": true, - "dependencies": { - "@csstools/selector-specificity": "^2.0.1", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-prefers-color-scheme": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-8.0.2.tgz", - "integrity": "sha512-OvFghizHJ45x7nsJJUSYLyQNTzsCU8yWjxAc/nhPQg1pbs18LMoET8N3kOweFDPy0JV0OSXN2iqRFhPBHYOeMA==", - "dev": true, - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "node_modules/cssdb": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.4.1.tgz", - "integrity": "sha512-0Q8NOMpXJ3iTDDbUv9grcmQAfdDx4qz+fN/+Md2FGbevT+6+bJNQ2LjB2YIUlLbpBTM32idU1Sb+tb/uGt6/XQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", - "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", - "dev": true, - "dependencies": { - "decompress-tar": "^4.0.0", - "decompress-tarbz2": "^4.0.0", - "decompress-targz": "^4.0.0", - "decompress-unzip": "^4.0.1", - "graceful-fs": "^4.1.10", - "make-dir": "^1.0.0", - "pify": "^2.3.0", - "strip-dirs": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", - "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", - "dev": true, - "dependencies": { - "file-type": "^5.2.0", - "is-stream": "^1.1.0", - "tar-stream": "^1.5.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tar/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-tarbz2": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", - "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", - "dev": true, - "dependencies": { - "decompress-tar": "^4.1.0", - "file-type": "^6.1.0", - "is-stream": "^1.1.0", - "seek-bzip": "^1.0.5", - "unbzip2-stream": "^1.0.9" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tarbz2/node_modules/file-type": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", - "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-tarbz2/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-targz": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", - "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", - "dev": true, - "dependencies": { - "decompress-tar": "^4.1.1", - "file-type": "^5.2.0", - "is-stream": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-targz/node_modules/file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-targz/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-unzip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", - "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", - "dev": true, - "dependencies": { - "file-type": "^3.8.0", - "get-stream": "^2.2.0", - "pify": "^2.3.0", - "yauzl": "^2.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress-unzip/node_modules/file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-unzip/node_modules/get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", - "dev": true, - "dependencies": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-unzip/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress/node_modules/make-dir/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/decompress/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/dnd-core": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", - "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", - "dependencies": { - "@react-dnd/asap": "^5.0.1", - "@react-dnd/invariant": "^4.0.1", - "redux": "^4.2.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "dev": true, - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/dotenv-expand": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-9.0.0.tgz", - "integrity": "sha512-uW8Hrhp5ammm9x7kBLR6jDfujgaDarNA02tprvZdyrJ7MpdzD1KyrIHG4l+YoC2fJ2UcdFdNWNWIjt+sexBHJw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/download": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/download/-/download-8.0.0.tgz", - "integrity": "sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==", - "dev": true, - "dependencies": { - "archive-type": "^4.0.0", - "content-disposition": "^0.5.2", - "decompress": "^4.2.1", - "ext-name": "^5.0.0", - "file-type": "^11.1.0", - "filenamify": "^3.0.0", - "get-stream": "^4.1.0", - "got": "^8.3.1", - "make-dir": "^2.1.0", - "p-event": "^2.1.0", - "pify": "^4.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/download/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dset": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", - "integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexer2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexer2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.328", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.328.tgz", - "integrity": "sha512-DE9tTy2PNmy1v55AZAO542ui+MLC2cvINMK4P2LXGsJdput/ThVG9t+QGecPuAZZSgC8XoI+Jh9M1OG9IoNSCw==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/emojibase": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz", - "integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ==", - "dev": true, - "peer": true, - "funding": { - "type": "ko-fi", - "url": "https://ko-fi.com/milesjohnson" - } - }, - "node_modules/emojibase-data": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-7.0.1.tgz", - "integrity": "sha512-BLZpOdwyFpZ7lzBWyDtnxmKVm/SJMYgAfp1if3o6n1TVUMSXAf0nikONXl90LZuJ/m3XWPBkkubgCet2BsCGGQ==", - "dev": true, - "funding": { - "type": "ko-fi", - "url": "https://ko-fi.com/milesjohnson" - }, - "peerDependencies": { - "emojibase": "*" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-schema": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/env-schema/-/env-schema-5.2.0.tgz", - "integrity": "sha512-36/6cZ+zIbcPA2ANrzp7vTz2bS8/zdZaq2RPFqJVtCGJ4P55EakgJ1BeKP8RMvEmM7ndrnHdJXzL3J1dHrEm1w==", - "dependencies": { - "ajv": "^8.0.0", - "dotenv": "^16.0.0", - "dotenv-expand": "^9.0.0" - } - }, - "node_modules/env-schema/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/env-schema/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/esbuild": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", - "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.16.17", - "@esbuild/android-arm64": "0.16.17", - "@esbuild/android-x64": "0.16.17", - "@esbuild/darwin-arm64": "0.16.17", - "@esbuild/darwin-x64": "0.16.17", - "@esbuild/freebsd-arm64": "0.16.17", - "@esbuild/freebsd-x64": "0.16.17", - "@esbuild/linux-arm": "0.16.17", - "@esbuild/linux-arm64": "0.16.17", - "@esbuild/linux-ia32": "0.16.17", - "@esbuild/linux-loong64": "0.16.17", - "@esbuild/linux-mips64el": "0.16.17", - "@esbuild/linux-ppc64": "0.16.17", - "@esbuild/linux-riscv64": "0.16.17", - "@esbuild/linux-s390x": "0.16.17", - "@esbuild/linux-x64": "0.16.17", - "@esbuild/netbsd-x64": "0.16.17", - "@esbuild/openbsd-x64": "0.16.17", - "@esbuild/sunos-x64": "0.16.17", - "@esbuild/win32-arm64": "0.16.17", - "@esbuild/win32-ia32": "0.16.17", - "@esbuild/win32-x64": "0.16.17" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", - "dev": true, - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "engines": { - "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-compat": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.1.2.tgz", - "integrity": "sha512-DNrQgDi5L4mAL4FdFboKBlSRg6MWfd75eA7K91lMjtP5ryN+O11qT2FDn7Z6zqy6sZ4sJawUR5V75qzB6l0CBg==", - "dev": true, - "dependencies": { - "@mdn/browser-compat-data": "^5.2.34", - "ast-metadata-inferer": "^0.7.0", - "browserslist": "^4.21.5", - "caniuse-lite": "^1.0.30001451", - "find-up": "^5.0.0", - "lodash.memoize": "4.1.2", - "semver": "7.3.8" - }, - "engines": { - "node": ">=16.x" - }, - "peerDependencies": { - "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-compat/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-compat/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-plugin-compat/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-jest": { - "version": "27.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz", - "integrity": "sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jest-dom": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-4.0.3.tgz", - "integrity": "sha512-9j+n8uj0+V0tmsoS7bYC7fLhQmIvjRqRYEcbDSi+TKPsTThLLXCyj5swMSSf/hTleeMktACnn+HFqXBr5gbcbA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.16.3", - "@testing-library/dom": "^8.11.1", - "requireindex": "^1.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6", - "yarn": ">=1" - }, - "peerDependencies": { - "eslint": "^6.8.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-jest-dom/node_modules/@testing-library/dom": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", - "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/eslint-plugin-jest-dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint-plugin-jest-dom/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint-plugin-jest-dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-jest-dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint-plugin-jest-dom/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-jest-dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-testing-library": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.2.tgz", - "integrity": "sha512-f1DmDWcz5SDM+IpCkEX0lbFqrrTs8HRsEElzDEqN/EBI0hpRj8Cns5+IVANXswE8/LeybIJqPAOQIFu2j5Y5sw==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.43.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" - }, - "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-source-polyfill": { - "version": "1.0.31", - "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz", - "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==" - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", - "dev": true, - "dependencies": { - "mime-db": "^1.28.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", - "dev": true, - "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-type": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-11.1.0.tgz", - "integrity": "sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-3.0.0.tgz", - "integrity": "sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g==", - "dev": true, - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flash-document-title": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flash-document-title/-/flash-document-title-1.0.0.tgz", - "integrity": "sha512-H5SNzpSuWC/1M4tSq3qSzJiAOVVb3mr5Cnv1DBD1cCtV7gQUfJ2SrEPmfN0l1RsQSLp6i9UJdXauqWhcMwENPw==" - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/format-duration": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/format-duration/-/format-duration-3.0.2.tgz", - "integrity": "sha512-pKzJDSRgK2lqAiPW3uizDaIJaJnataZclsahz25UMwfdryBGDa+1HlbXGjzpMvX/2kMh4O0sNevFXKaEfCjHsA==" - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "node_modules/from2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/from2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/from2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/from2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-port": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", - "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, - "node_modules/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "node_modules/electron-to-chromium": { + "version": "1.4.600", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.600.tgz", + "integrity": "sha512-KD6CWjf1BnQG+NsXuyiTDDT1eV13sKuYsOUioXkQweYTQIbgHkXPry9K7M+7cKtYHnSUPitVaLrXYB1jTkkYrw==", "dev": true }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojibase": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-15.2.0.tgz", + "integrity": "sha512-gB6rIVtyJPersQvAo4nOGYPeILMhlcfZdiwCWVeRAtkJ7sm0tExZETGyLhrTQcHvZQhDEYI1vlCeqUhn5gZkQA==", + "dev": true, + "peer": true, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "ko-fi", + "url": "https://ko-fi.com/milesjohnson" } }, - "node_modules/got": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", - "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "node_modules/emojibase-data": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-15.2.0.tgz", + "integrity": "sha512-hDiw4ugxnI4pcVQO+73NlKx6aZP/A+BAPfDgK/3A83RVbHZa0Ut6GHpd5r5XUV9G7BZhKejlIRuxhXialpbt6Q==", "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.7.0", - "cacheable-request": "^2.1.1", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "into-stream": "^3.1.0", - "is-retry-allowed": "^1.1.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "mimic-response": "^1.0.0", - "p-cancelable": "^0.4.0", - "p-timeout": "^2.0.1", - "pify": "^3.0.0", - "safe-buffer": "^5.1.1", - "timed-out": "^4.0.1", - "url-parse-lax": "^3.0.0", - "url-to-options": "^1.0.1" + "funding": { + "type": "ko-fi", + "url": "https://ko-fi.com/milesjohnson" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "emojibase": "*" } }, - "node_modules/got/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/got/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "once": "^1.4.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/env-schema": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/env-schema/-/env-schema-5.2.1.tgz", + "integrity": "sha512-gWMNrQ3dVHAZcCx7epiFwgXcyfBh4heD/6+OK3bEbke3uL+KqwYA9nUOwzJyRZh1cJOFcwdPuY1n0GKSFlSWAg==", "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" + "ajv": "^8.0.0", + "dotenv": "^16.0.0", + "dotenv-expand": "^10.0.0" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "node_modules/env-schema/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/has-property-descriptors": { + "node_modules/env-schema/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "is-arrayish": "^0.2.1" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "node_modules/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, "engines": { "node": ">= 0.4" }, @@ -9347,1753 +5721,1716 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "node_modules/es-iterator-helpers": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", + "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", "dev": true, "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.0.1" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dependencies": { - "has-symbols": "^1.0.2" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hast-util-from-parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", - "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", - "hastscript": "^7.0.0", - "property-information": "^6.0.0", - "vfile": "^5.0.0", - "vfile-location": "^4.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "hasown": "^2.0.0" } }, - "node_modules/hast-util-parse-selector": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", - "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dependencies": { - "@types/hast": "^2.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", - "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", - "dependencies": { - "@types/hast": "^2.0.0", - "@types/parse5": "^6.0.0", - "hast-util-from-parse5": "^7.0.0", - "hast-util-to-parse5": "^7.0.0", - "html-void-elements": "^2.0.0", - "parse5": "^6.0.0", - "unist-util-position": "^4.0.0", - "unist-util-visit": "^4.0.0", - "vfile": "^5.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hast-util-raw/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/hast-util-to-parse5": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", - "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "hasInstallScript": true, "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", - "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=0.10" } }, - "node_modules/hastscript": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", - "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^3.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", "dependencies": { - "react-is": "^16.7.0" + "d": "^1.0.1", + "ext": "^1.1.2" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "node_modules/esbuild": { + "version": "0.19.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.8.tgz", + "integrity": "sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.8", + "@esbuild/android-arm64": "0.19.8", + "@esbuild/android-x64": "0.19.8", + "@esbuild/darwin-arm64": "0.19.8", + "@esbuild/darwin-x64": "0.19.8", + "@esbuild/freebsd-arm64": "0.19.8", + "@esbuild/freebsd-x64": "0.19.8", + "@esbuild/linux-arm": "0.19.8", + "@esbuild/linux-arm64": "0.19.8", + "@esbuild/linux-ia32": "0.19.8", + "@esbuild/linux-loong64": "0.19.8", + "@esbuild/linux-mips64el": "0.19.8", + "@esbuild/linux-ppc64": "0.19.8", + "@esbuild/linux-riscv64": "0.19.8", + "@esbuild/linux-s390x": "0.19.8", + "@esbuild/linux-x64": "0.19.8", + "@esbuild/netbsd-x64": "0.19.8", + "@esbuild/openbsd-x64": "0.19.8", + "@esbuild/sunos-x64": "0.19.8", + "@esbuild/win32-arm64": "0.19.8", + "@esbuild/win32-ia32": "0.19.8", + "@esbuild/win32-x64": "0.19.8" } }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, - "node_modules/hstream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/hstream/-/hstream-3.1.1.tgz", - "integrity": "sha512-VFACykA8S81r/iof6wvLbn2ZXuvHSd2B8H2fMb8C0Ri2NkutXSwftK+bxxP8lbMp+TFZ8Z1Xupdm0ttS+r5IpQ==", - "dependencies": { - "css-what": "^5.0.1", - "htmlparser2": "^6.0.0", - "through2": "^4.0.2" - }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "engines": { - "node": ">= 8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hstream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz", + "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==", + "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.3", + "@eslint/js": "8.54.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/hstream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/hstream/node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dependencies": { - "readable-stream": "3" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/html-encoding-sniffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", - "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", "dev": true, "dependencies": { - "whatwg-encoding": "^2.0.0" + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" }, "engines": { - "node": ">=12" + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" } }, - "node_modules/html-tokenize": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz", - "integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==", + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "buffer-from": "~0.1.1", - "inherits": "~2.0.1", - "minimist": "~1.2.5", - "readable-stream": "~1.0.27-1", - "through2": "~0.4.1" - }, "bin": { - "html-tokenize": "bin/cmd.js" - } - }, - "node_modules/html-void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", - "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "semver": "bin/semver.js" } }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" + "ms": "^2.1.1" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "debug": "^3.2.7" }, "engines": { - "node": ">= 6" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" + "ms": "^2.1.1" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/eslint-plugin-compat": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz", + "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==", "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@mdn/browser-compat-data": "^5.3.13", + "ast-metadata-inferer": "^0.8.0", + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001524", + "find-up": "^5.0.0", + "lodash.memoize": "^4.1.2", + "semver": "^7.5.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.x" + }, + "peerDependencies": { + "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "node_modules/eslint-plugin-import": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz", + "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==", "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" }, "engines": { - "node": ">=6" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "esutils": "^2.0.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/import-local/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/import-local/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/eslint-plugin-jest-dom": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest-dom/-/eslint-plugin-jest-dom-5.1.0.tgz", + "integrity": "sha512-JIXZp+E/h/aGlP/rQc4tuOejiHlZXg65qw8JAJMIJA5VsdjOkss/SYcRSqBrQuEOytEM8JvngUjcz31d1RrCrA==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "@babel/runtime": "^7.16.3", + "requireindex": "^1.2.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@testing-library/dom": "^8.0.0 || ^9.0.0", + "eslint": "^6.8.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@testing-library/dom": { + "optional": true + } } - }, - "node_modules/import-local/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" }, "engines": { - "node": ">=6" + "node": ">=4.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/import-local/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "dequal": "^2.0.3" } }, - "node_modules/import-local/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", "dev": true, "dependencies": { - "find-up": "^4.0.0" + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" }, "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "dev": true, "engines": { - "node": ">=12" + "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "esutils": "^2.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/into-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", - "integrity": "sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, "dependencies": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">=4" + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/eslint-plugin-testing-library": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz", + "integrity": "sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@typescript-eslint/utils": "^5.58.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true } - ], - "engines": { - "node": ">=4" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dependencies": { - "has": "^1.0.3" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/eslint-plugin-testing-library/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/eslint-plugin-testing-library/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=4.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/eslint-plugin-vitest": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.10.tgz", + "integrity": "sha512-08lj4rdhZHYyHk+Py2nJ7SlE6arP8GNfGXl9jVqhe9s5JoZIGiBpIkLGX+VNBiB6vXTn56H6Ant7Koc6XzRjtQ==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "@typescript-eslint/utils": "^6.11.0" }, "engines": { - "node": ">=0.10.0" + "node": "14.x || >= 16" + }, + "peerDependencies": { + "eslint": ">=8.0.0", + "vitest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-natural-number": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==", - "dev": true - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/eslint/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "engines": { + "node": ">=10" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4.0" } }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/event-source-polyfill": { + "version": "1.0.31", + "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz", + "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA==" + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "call-bind": "^1.0.2" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.10.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "^2.7.2" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "mime-db": "^1.28.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8.6.0" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "is-glob": "^4.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 6" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 4.9.1" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "pend": "~1.2.0" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" }, "engines": { - "node": ">=8" + "node": "^12.20 || >= 14.13" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/file-type": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-11.1.0.tgz", + "integrity": "sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-3.0.0.tgz", + "integrity": "sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g==", "dev": true, "dependencies": { - "semver": "^6.0.0" + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/flash-document-title": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flash-document-title/-/flash-document-title-1.0.0.tgz", + "integrity": "sha512-H5SNzpSuWC/1M4tSq3qSzJiAOVVb3mr5Cnv1DBD1cCtV7gQUfJ2SrEPmfN0l1RsQSLp6i9UJdXauqWhcMwENPw==" }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 4" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/item-selection": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/item-selection/-/item-selection-1.2.2.tgz", - "integrity": "sha512-1nT1eQuDvFL6J8qWWZKw4Ks+D2Jwn2wvl0f7pC58lyantKs0TMU+mBV5MV0DYCAMipstKloWajttYDLpyHmfIg==" - }, - "node_modules/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", - "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "glob": "^7.1.3" }, "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "rimraf": "bin.js" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true }, - "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", - "dev": true, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "is-callable": "^1.1.3" } }, - "node_modules/jest-circus/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-circus/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 6" } }, - "node_modules/jest-circus/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/format-duration": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/format-duration/-/format-duration-3.0.2.tgz", + "integrity": "sha512-pKzJDSRgK2lqAiPW3uizDaIJaJnataZclsahz25UMwfdryBGDa+1HlbXGjzpMvX/2kMh4O0sNevFXKaEfCjHsA==" + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "dependencies": { - "color-name": "~1.1.4" + "fetch-blob": "^3.1.2" }, "engines": { - "node": ">=7.0.0" + "node": ">=12.20.0" } }, - "node_modules/jest-circus/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-circus/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/jest-circus/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "engines": { + "node": "*" }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.6" } }, - "node_modules/jest-circus/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, - "node_modules/jest-circus/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "node_modules/from2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dependencies": { - "color-convert": "^2.0.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-cli/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" } }, - "node_modules/jest-cli/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-cli/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/jest-cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "has-flag": "^4.0.0" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "node_modules/get-port": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.0.0.tgz", + "integrity": "sha512-mDHFgApoQd+azgMdwylJrv2DX47ywGq1i5VFJE7fZ0dttNq3iQMfsU4IvEgBHojA3KqEudyu7Vq+oN8kNaNkWw==", "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">=16" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-config/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "pump": "^3.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6" } }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-config/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-config/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-config/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-config/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "global-prefix": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6" } }, - "node_modules/jest-diff/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=6" } }, - "node_modules/jest-diff/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/jest-diff/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/jest-diff/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "detect-newline": "^3.0.0" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "node_modules/got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/got/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/got/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" } }, - "node_modules/jest-each/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=6" } }, - "node_modules/jest-each/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/jest-each/node_modules/has-flag": { + "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -11102,1282 +7439,1089 @@ "node": ">=8" } }, - "node_modules/jest-each/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "get-intrinsic": "^1.2.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/jest-environment-jsdom": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.5.0.tgz", - "integrity": "sha512-/KG8yEK4aN8ak56yFVdqFDzKNHgF4BAymCx2LbPNPsUshUlfAl0eX402Xm1pt+eoG9SLZEUVifqXtX8SK74KCw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/jsdom": "^20.0.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0", - "jsdom": "^20.0.0" - }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "canvas": "^2.5.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "has-symbol-support-x": "^1.4.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/jest-fetch-mock": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", - "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", - "dev": true, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { - "cross-fetch": "^3.0.4", - "promise-polyfill": "^8.1.3" - } - }, - "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", - "dev": true, + "has-symbols": "^1.0.2" + }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", "dependencies": { - "@jest/types": "^29.5.0", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" + "function-bind": "^1.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", + "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "hastscript": "^7.0.0", + "property-information": "^6.0.0", + "vfile": "^5.0.0", + "vfile-location": "^4.0.0", + "web-namespaces": "^2.0.0" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", - "dev": true, + "node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "@types/hast": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-leak-detector/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" + "node_modules/hast-util-raw": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", + "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/parse5": "^6.0.0", + "hast-util-from-parse5": "^7.0.0", + "hast-util-to-parse5": "^7.0.0", + "html-void-elements": "^2.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^4.0.0", + "unist-util-visit": "^4.0.0", + "vfile": "^5.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-leak-detector/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "node_modules/hast-util-raw/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, - "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", - "dev": true, + "node_modules/hast-util-to-parse5": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", + "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, + "node_modules/hast-util-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-matcher-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "react-is": "^16.7.0" } }, - "node_modules/jest-matcher-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-matcher-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/jest-matcher-utils/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "lru-cache": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-matcher-utils/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/hstream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hstream/-/hstream-3.1.1.tgz", + "integrity": "sha512-VFACykA8S81r/iof6wvLbn2ZXuvHSd2B8H2fMb8C0Ri2NkutXSwftK+bxxP8lbMp+TFZ8Z1Xupdm0ttS+r5IpQ==", "dependencies": { - "has-flag": "^4.0.0" + "css-what": "^5.0.1", + "htmlparser2": "^6.0.0", + "through2": "^4.0.2" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", - "dev": true, + "node_modules/hstream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/hstream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "safe-buffer": "~5.2.0" } }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/hstream/node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "readable-stream": "3" } }, - "node_modules/jest-message-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=18" } }, - "node_modules/jest-message-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-message-util/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/html-tokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz", + "integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "buffer-from": "~0.1.1", + "inherits": "~2.0.1", + "minimist": "~1.2.5", + "readable-stream": "~1.0.27-1", + "through2": "~0.4.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "html-tokenize": "bin/cmd.js" } }, - "node_modules/jest-message-util/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, + "node_modules/html-void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", + "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "has-flag": "^4.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "jest-util": "^29.5.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 14" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 14" } }, - "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", - "dev": true, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, - "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 4" } }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/immer" } }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-resolve/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-resolve/node_modules/has-flag": { + "node_modules/import-lazy": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/jest-resolve/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=0.8.19" } }, - "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-runner/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/jest-runner/node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, + "node_modules/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/jest-runner/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runner/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runner/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/jest-runner/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-runner/node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "node": ">= 0.10" } }, - "node_modules/jest-runner/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "has-bigints": "^1.0.1" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dependencies": { - "color-name": "~1.1.4" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/jest-runtime/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.5.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dependencies": { + "hasown": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dependencies": { - "color-convert": "^2.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/jest-snapshot/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-snapshot/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/jest-snapshot/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-snapshot/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", "dev": true, - "engines": { - "node": ">=10" - }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" }, "engines": { - "node": ">=10" - } - }, - "node_modules/jest-snapshot/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==", "dev": true }, - "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, - "dependencies": { - "@jest/types": "^29.5.0", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "leven": "^3.1.0", - "pretty-format": "^29.5.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-validate/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "color-convert": "^2.0.1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dependencies": { - "color-name": "~1.1.4" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-validate/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/jest-validate/node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dependencies": { - "@jest/schemas": "^29.4.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dependencies": { - "has-flag": "^4.0.0" + "which-typed-array": "^1.1.11" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.5.0", - "string-length": "^4.0.1" + "call-bind": "^1.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-watcher/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-watcher/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" } }, - "node_modules/jest-watcher/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-watcher/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/jest-watcher/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", "dev": true, "dependencies": { - "@types/node": "*", - "jest-util": "^29.5.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 4" } }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/item-selection": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/item-selection/-/item-selection-1.2.2.tgz", + "integrity": "sha512-1nT1eQuDvFL6J8qWWZKw4Ks+D2Jwn2wvl0f7pC58lyantKs0TMU+mBV5MV0DYCAMipstKloWajttYDLpyHmfIg==" + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-tokens": { @@ -12398,43 +8542,38 @@ } }, "node_modules/jsdom": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", - "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.6", - "acorn": "^8.8.1", - "acorn-globals": "^7.0.0", - "cssom": "^0.5.0", - "cssstyle": "^2.3.0", - "data-urls": "^3.0.2", - "decimal.js": "^10.4.2", - "domexception": "^4.0.0", - "escodegen": "^2.0.0", + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-23.0.1.tgz", + "integrity": "sha512-2i27vgvlUsGEBO9+/kJQRbtqtm+191b5zAZrU/UezVmnC2dlDAFLgDYJvAEi94T4kjsRKkezEtLQTgsNEsW2lQ==", + "dev": true, + "dependencies": { + "cssstyle": "^3.0.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", "form-data": "^4.0.0", - "html-encoding-sniffer": "^3.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.2", - "parse5": "^7.1.1", + "nwsapi": "^2.2.7", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.6.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.2", - "w3c-xmlserializer": "^4.0.0", + "tough-cookie": "^4.1.3", + "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^2.0.0", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0", - "ws": "^8.11.0", - "xml-name-validator": "^4.0.0" + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.14.2", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { - "canvas": "^2.5.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -12455,9 +8594,9 @@ } }, "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, "node_modules/json-parse-even-better-errors": { @@ -12477,6 +8616,12 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-typescript": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/json-typescript/-/json-typescript-1.1.2.tgz", + "integrity": "sha512-Np07MUsYMKbB0nNlw/MMIRjUK7ehO48LA4FsrzrhCfTUxMKbvOBAo0sc0b4nQ80ge9d32sModCunCgoyUojgUA==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -12489,14 +8634,31 @@ "node": ">=6" } }, + "node_modules/jsonapi-typescript": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/jsonapi-typescript/-/jsonapi-typescript-0.1.3.tgz", + "integrity": "sha512-uPcPS01GeM+4HIyn18s7l1yD2S3uLZy2TX1UkQffCM0bLb3TMwudXUyVXPHTMZ4vdZT8MqKqN2vjB5PogTAdFQ==", + "dev": true, + "dependencies": { + "json-typescript": "^1.0.0" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/jsx-ast-utils": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", - "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, "dependencies": { - "array-includes": "^3.1.5", - "object.assign": "^4.1.3" + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" }, "engines": { "node": ">=4.0" @@ -12523,12 +8685,12 @@ "integrity": "sha512-Js7+HxDOGcB3RhI38Mird/RgyMf3t0DAJFda1QWqqlAKTa36NeSYIufJXxrZUbysFTRcTOFcoMCiFK5FwCoI7Q==" }, "node_modules/keyv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "node_modules/kind-of": { @@ -12541,18 +8703,17 @@ } }, "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "engines": { "node": ">=6" } }, "node_modules/known-css-properties": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", - "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", "dev": true }, "node_modules/language-subtag-registry": { @@ -12562,21 +8723,15 @@ "dev": true }, "node_modules/language-tags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", - "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", "dev": true, "dependencies": { - "language-subtag-registry": "~0.3.2" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, + "language-subtag-registry": "^0.3.20" + }, "engines": { - "node": ">=6" + "node": ">=0.10" } }, "node_modules/levn": { @@ -12597,6 +8752,18 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -12618,12 +8785,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -12653,6 +8814,15 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -12681,46 +8851,30 @@ } }, "node_modules/magic-string": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", - "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "version": "0.30.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", + "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { "node": ">=12" } }, "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/map-obj": { @@ -12769,9 +8923,9 @@ } }, "node_modules/mdast-util-from-markdown": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz", - "integrity": "sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", + "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", @@ -12811,9 +8965,9 @@ } }, "node_modules/mdast-util-to-string": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.1.tgz", - "integrity": "sha512-tGvhT94e+cVnQt8JWE9/b3cUQZWS732TJxXHktvP+BYo62PpYD53Ls/6cC60rW21dW+txxiM4zMdc6abASvZKA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", "dependencies": { "@types/mdast": "^3.0.0" }, @@ -12837,38 +8991,54 @@ } }, "node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", "dev": true, "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" }, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "node_modules/meow/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12879,12 +9049,6 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -12903,9 +9067,9 @@ } }, "node_modules/micromark": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.1.0.tgz", - "integrity": "sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", + "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", "funding": [ { "type": "GitHub Sponsors", @@ -12937,9 +9101,9 @@ } }, "node_modules/micromark-core-commonmark": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz", - "integrity": "sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", + "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", "funding": [ { "type": "GitHub Sponsors", @@ -12970,9 +9134,9 @@ } }, "node_modules/micromark-factory-destination": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz", - "integrity": "sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", + "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", "funding": [ { "type": "GitHub Sponsors", @@ -12990,9 +9154,9 @@ } }, "node_modules/micromark-factory-label": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz", - "integrity": "sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", + "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", "funding": [ { "type": "GitHub Sponsors", @@ -13011,9 +9175,9 @@ } }, "node_modules/micromark-factory-space": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz", - "integrity": "sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13030,9 +9194,9 @@ } }, "node_modules/micromark-factory-title": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz", - "integrity": "sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", + "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13047,14 +9211,13 @@ "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" + "micromark-util-types": "^1.0.0" } }, "node_modules/micromark-factory-whitespace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz", - "integrity": "sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", + "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13073,9 +9236,9 @@ } }, "node_modules/micromark-util-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz", - "integrity": "sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", "funding": [ { "type": "GitHub Sponsors", @@ -13092,9 +9255,9 @@ } }, "node_modules/micromark-util-chunked": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz", - "integrity": "sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", + "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13110,9 +9273,9 @@ } }, "node_modules/micromark-util-classify-character": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz", - "integrity": "sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", + "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", "funding": [ { "type": "GitHub Sponsors", @@ -13130,9 +9293,9 @@ } }, "node_modules/micromark-util-combine-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz", - "integrity": "sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", + "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", "funding": [ { "type": "GitHub Sponsors", @@ -13149,9 +9312,9 @@ } }, "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz", - "integrity": "sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", + "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", "funding": [ { "type": "GitHub Sponsors", @@ -13167,9 +9330,9 @@ } }, "node_modules/micromark-util-decode-string": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz", - "integrity": "sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", + "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", "funding": [ { "type": "GitHub Sponsors", @@ -13188,9 +9351,9 @@ } }, "node_modules/micromark-util-encode": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz", - "integrity": "sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", + "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", "funding": [ { "type": "GitHub Sponsors", @@ -13203,9 +9366,9 @@ ] }, "node_modules/micromark-util-html-tag-name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz", - "integrity": "sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", + "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", "funding": [ { "type": "GitHub Sponsors", @@ -13218,9 +9381,9 @@ ] }, "node_modules/micromark-util-normalize-identifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz", - "integrity": "sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", + "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", "funding": [ { "type": "GitHub Sponsors", @@ -13236,9 +9399,9 @@ } }, "node_modules/micromark-util-resolve-all": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz", - "integrity": "sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", + "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", "funding": [ { "type": "GitHub Sponsors", @@ -13254,9 +9417,9 @@ } }, "node_modules/micromark-util-sanitize-uri": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz", - "integrity": "sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", + "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", "funding": [ { "type": "GitHub Sponsors", @@ -13274,9 +9437,9 @@ } }, "node_modules/micromark-util-subtokenize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz", - "integrity": "sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", + "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", "funding": [ { "type": "GitHub Sponsors", @@ -13295,9 +9458,9 @@ } }, "node_modules/micromark-util-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz", - "integrity": "sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", "funding": [ { "type": "GitHub Sponsors", @@ -13310,9 +9473,9 @@ ] }, "node_modules/micromark-util-types": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.2.tgz", - "integrity": "sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", "funding": [ { "type": "GitHub Sponsors", @@ -13367,15 +9530,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -13428,12 +9582,12 @@ } }, "node_modules/minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/mitt": { @@ -13441,6 +9595,18 @@ "resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz", "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==" }, + "node_modules/mlly": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.2.tgz", + "integrity": "sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==", + "dev": true, + "dependencies": { + "acorn": "^8.10.0", + "pathe": "^1.1.1", + "pkg-types": "^1.0.3", + "ufo": "^1.3.0" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -13465,10 +9631,16 @@ } }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -13513,9 +9685,9 @@ } }, "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -13529,66 +9701,27 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" }, "engines": { "node": ">=10" } }, - "node_modules/normalize-package-data/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -13626,18 +9759,6 @@ "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz", "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==" }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/number.isfinite": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number.isfinite/-/number.isfinite-1.0.1.tgz", @@ -13651,9 +9772,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", - "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", "dev": true }, "node_modules/object-assign": { @@ -13665,9 +9786,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13696,12 +9817,12 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -13713,28 +9834,28 @@ } }, "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -13743,27 +9864,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", "dev": true, "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -13792,33 +9925,18 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -13894,15 +10012,12 @@ } }, "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-6.0.0.tgz", + "integrity": "sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==", "dev": true, - "dependencies": { - "aggregate-error": "^4.0.0" - }, "engines": { - "node": ">=12" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13920,15 +10035,6 @@ "node": ">=4" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -14010,28 +10116,28 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.1.tgz", - "integrity": "sha512-OW+5s+7cw6253Q4E+8qQ/u1fVvcJQCJo/VFD8pje+dbJCF1n5ZRMV2AEHbGp+5Q7jxQIYJxkHopnj6nzdGeZLA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, "dependencies": { - "lru-cache": "^7.14.1", - "minipass": "^4.0.2" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=14" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", "dev": true, "engines": { - "node": ">=12" + "node": "14 || >=16.14" } }, "node_modules/path-to-regexp": { @@ -14047,6 +10153,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", + "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -14101,92 +10222,21 @@ "node": ">=0.10.0" } }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" } }, "node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -14196,10 +10246,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -14242,20 +10296,27 @@ } }, "node_modules/postcss-color-functional-notation": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-5.0.2.tgz", - "integrity": "sha512-M6ygxWOyd6eWf3sd1Lv8xi4SeF4iBPfJvkfMU4ITh8ExJc1qhbvh/U8Cv/uOvBgUVOMDdScvCdlg8+hREQzs7w==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-6.0.2.tgz", + "integrity": "sha512-FsjSmlSufuiFBsIqQ++VxFmvX7zKndZpBkHmfXr4wqhvzM92FTEkAh703iqWTl1U3faTgqioIqCbfqdWiFVwtw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^3.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } @@ -14280,162 +10341,210 @@ } }, "node_modules/postcss-color-rebeccapurple": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-8.0.2.tgz", - "integrity": "sha512-xWf/JmAxVoB5bltHpXk+uGRoGFwu4WDAR7210el+iyvTdqiKpDhtcT8N3edXMoVJY0WHFMrKMUieql/wRNiXkw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-9.0.1.tgz", + "integrity": "sha512-ds4cq5BjRieizVb2PnvbJ0omg9VCo2/KzluvoFZbxuGpsGJ5BQSD93CHBooinEtangCM5YqUOerGDl4xGmOb6Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-custom-media": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-9.1.2.tgz", - "integrity": "sha512-osM9g4UKq4XKimAC7RAXroqi3BXpxfwTswAJQiZdrBjWGFGEyxQrY5H2eDWI8F+MEvEUfYDxA8scqi3QWROCSw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-10.0.2.tgz", + "integrity": "sha512-zcEFNRmDm2fZvTPdI1pIW3W//UruMcLosmMiCdpQnrCsTRzWlKQPYMa1ud9auL0BmrryKK1+JjIGn19K0UjO/w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.0", - "@csstools/css-parser-algorithms": "^2.0.0", - "@csstools/css-tokenizer": "^2.0.0", - "@csstools/media-query-list-parser": "^2.0.0" + "@csstools/cascade-layer-name-parser": "^1.0.5", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/media-query-list-parser": "^2.1.5" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-custom-properties": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.1.4.tgz", - "integrity": "sha512-iSAdaZrM3KMec8cOSzeTUNXPYDlhqsMJHpt62yrjwG6nAnMtRHPk5JdMzGosBJtqEahDolvD5LNbcq+EZ78o5g==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.3.2.tgz", + "integrity": "sha512-2Coszybpo8lpLY24vy2CYv9AasiZ39/bs8Imv0pWMq55Gl8NWzfc24OAo3zIX7rc6uUJAqESnVOMZ6V6lpMjJA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.0", - "@csstools/css-parser-algorithms": "^2.0.0", - "@csstools/css-tokenizer": "^2.0.0", + "@csstools/cascade-layer-name-parser": "^1.0.5", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-custom-selectors": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.2.tgz", - "integrity": "sha512-jX7VlE3jrgfBIOfxiGNRFq81xUoHSZhvxhQurzE7ZFRv+bUmMwB7/XnA0nNlts2CwNtbXm4Ozy0ZAYKHlCRmBQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.6.tgz", + "integrity": "sha512-svsjWRaxqL3vAzv71dV0/65P24/FB8TbPX+lWyyf9SZ7aZm4S4NhCn7N3Bg+Z5sZunG3FS8xQ80LrCU9hb37cw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@csstools/cascade-layer-name-parser": "^1.0.0", - "@csstools/css-parser-algorithms": "^2.0.0", - "@csstools/css-tokenizer": "^2.0.0", - "postcss-selector-parser": "^6.0.4" + "@csstools/cascade-layer-name-parser": "^1.0.5", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "postcss-selector-parser": "^6.0.13" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-dir-pseudo-class": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-7.0.2.tgz", - "integrity": "sha512-cMnslilYxBf9k3qejnovrUONZx1rXeUZJw06fgIUBzABJe3D2LiLL5WAER7Imt3nrkaIgG05XZBztueLEf5P8w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-8.0.0.tgz", + "integrity": "sha512-Oy5BBi0dWPwij/IA+yDYj+/OBMQ9EPqAzTHeSNUYrUWdll/PRJmcbiUj0MNcsBi681I1gcSTLvMERPaXzdbvJg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "postcss-selector-parser": "^6.0.10" + "postcss-selector-parser": "^6.0.13" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-double-position-gradients": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-4.0.2.tgz", - "integrity": "sha512-GXL1RmFREDK4Q9aYvI2RhVrA6a6qqSMQQ5ke8gSH1xgV6exsqbcJpIumC7AOgooH6/WIG3/K/T8xxAiVHy/tJg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-5.0.2.tgz", + "integrity": "sha512-KTbvdOOy8z8zb0BTkEg4/1vqlRlApdvjw8/pFoehgQl0WVO+fezDGlvo0B8xRA+XccA7ohkQCULKNsiNOx70Cw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "@csstools/postcss-progressive-custom-properties": "^3.0.2", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-focus-visible": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-8.0.2.tgz", - "integrity": "sha512-f/Vd+EC/GaKElknU59esVcRYr/Y3t1ZAQyL4u2xSOgkDy4bMCmG7VP5cGvj3+BTLNE9ETfEuz2nnt4qkZwTTeA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-9.0.0.tgz", + "integrity": "sha512-zA4TbVaIaT8npZBEROhZmlc+GBKE8AELPHXE7i4TmIUEQhw/P/mSJfY9t6tBzpQ1rABeGtEOHYrW4SboQeONMQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "postcss-selector-parser": "^6.0.10" + "postcss-selector-parser": "^6.0.13" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-focus-within": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-7.0.2.tgz", - "integrity": "sha512-AHAJ89UQBcqBvFgQJE9XasGuwMNkKsGj4D/f9Uk60jFmEBHpAL14DrnSk3Rj+SwZTr/WUG+mh+Rvf8fid/346w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-8.0.0.tgz", + "integrity": "sha512-E7+J9nuQzZaA37D/MUZMX1K817RZGDab8qw6pFwzAkDd/QtlWJ9/WTKmzewNiuxzeq6WWY7ATiRePVoDKp+DnA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "postcss-selector-parser": "^6.0.10" + "postcss-selector-parser": "^6.0.13" }, "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { "postcss": "^8.4" @@ -14451,131 +10560,135 @@ } }, "node_modules/postcss-gap-properties": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-4.0.1.tgz", - "integrity": "sha512-V5OuQGw4lBumPlwHWk/PRfMKjaq/LTGR4WDTemIMCaMevArVfCCA9wBJiL1VjDAd+rzuCIlkRoRvDsSiAaZ4Fg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-5.0.0.tgz", + "integrity": "sha512-YjsEEL6890P7MCv6fch6Am1yq0EhQCJMXyT4LBohiu87+4/WqR7y5W3RIv53WdA901hhytgRvjlrAhibhW4qsA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-image-set-function": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-5.0.2.tgz", - "integrity": "sha512-Sszjwo0ubETX0Fi5MvpYzsONwrsjeabjMoc5YqHvURFItXgIu3HdCjcVuVKGMPGzKRhgaknmdM5uVWInWPJmeg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-6.0.1.tgz", + "integrity": "sha512-VlZncC9hhZ5tg0JllY4g6Z28BeoPO8DIkelioEEkXL0AA0IORlqYpTi2L8TUnl4YQrlwvBgxVy+mdZJw5R/cIQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "dev": true, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, "node_modules/postcss-lab-function": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-5.1.0.tgz", - "integrity": "sha512-iZApRTNcpc71uTn7PkzjHtj5cmuZpvu6okX4jHnM5OFi2fG97sodjxkq6SpL65xhW0NviQrAMSX97ntyGVRV0w==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.7.tgz", + "integrity": "sha512-4d1lhDVPukHFqkMv4G5vVcK+tgY52vwb5uR1SWKOaO5389r2q8fMxBWuXSW+YtbCOEGP0/X9KERi9E9le2pJuw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@csstools/color-helpers": "^1.0.0", - "@csstools/postcss-progressive-custom-properties": "^2.0.0", - "postcss-value-parser": "^4.2.0" + "@csstools/css-color-parser": "^1.4.0", + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1", + "@csstools/postcss-progressive-custom-properties": "^3.0.2" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-logical": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-6.1.0.tgz", - "integrity": "sha512-qb1+LpClhYjxac8SfOcWotnY3unKZesDqIOm+jnGt8rTl7xaIWpE2bPGZHxflOip1E/4ETo79qlJyRL3yrHn1g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-7.0.0.tgz", + "integrity": "sha512-zYf3vHkoW82f5UZTEXChTJvH49Yl9X37axTZsJGxrCG2kOUwtaAoz9E7tqYg0lsIoJLybaL8fk/2mOi81zVIUw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, - "node_modules/postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true - }, "node_modules/postcss-nesting": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-11.2.1.tgz", - "integrity": "sha512-E6Jq74Jo/PbRAtZioON54NPhUNJYxVWhwxbweYl1vAoBYuGlDIts5yhtKiZFLvkvwT73e/9nFrW3oMqAtgG+GQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.0.1.tgz", + "integrity": "sha512-6LCqCWP9pqwXw/njMvNK0hGY44Fxc4B2EsGbn6xDcxbNRzP8GYoxT7yabVVMLrX3quqOJ9hg2jYMsnkedOf8pA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" + "@csstools/selector-specificity": "^3.0.0", + "postcss-selector-parser": "^6.0.13" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-opacity-percentage": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", - "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-2.0.0.tgz", + "integrity": "sha512-lyDrCOtntq5Y1JZpBFzIWm2wG9kbEdujpNt4NLannF+J9c8CgFIzPa80YQfdza+Y+yFfzbYj/rfoOsYsooUWTQ==", "dev": true, "funding": [ { @@ -14588,27 +10701,33 @@ } ], "engines": { - "node": "^12 || ^14 || >=16" + "node": "^14 || ^16 || >=18" }, "peerDependencies": { "postcss": "^8.2" } }, "node_modules/postcss-overflow-shorthand": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-4.0.1.tgz", - "integrity": "sha512-HQZ0qi/9iSYHW4w3ogNqVNr2J49DHJAl7r8O2p0Meip38jsdnRPgiDW7r/LlLrrMBMe3KHkvNtAV2UmRVxzLIg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-5.0.0.tgz", + "integrity": "sha512-2rlxDyeSics/hC2FuMdPnWiP9WUPZ5x7FTuArXLFVpaSQ2woPSfZS4RD59HuEokbZhs/wPUQJ1E3MT6zVv94MQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } @@ -14623,110 +10742,135 @@ } }, "node_modules/postcss-place": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-8.0.1.tgz", - "integrity": "sha512-Ow2LedN8sL4pq8ubukO77phSVt4QyCm35ZGCYXKvRFayAwcpgB0sjNJglDoTuRdUL32q/ZC1VkPBo0AOEr4Uiw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-9.0.0.tgz", + "integrity": "sha512-qLEPD9VPH5opDVemwmRaujODF9nExn24VOC3ghgVLEvfYN7VZLwJHes0q/C9YR5hI2UC3VgBE8Wkdp1TxCXhtg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-preset-env": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-8.0.1.tgz", - "integrity": "sha512-IUbymw0JlUbyVG+I85963PNWgPp3KhnFa1sxU7M/2dGthxV8e297P0VV5W9XcyypoH4hirH2fp1c6fmqh6YnSg==", - "dev": true, - "dependencies": { - "@csstools/postcss-cascade-layers": "^3.0.0", - "@csstools/postcss-color-function": "^2.0.0", - "@csstools/postcss-font-format-keywords": "^2.0.0", - "@csstools/postcss-hwb-function": "^2.0.0", - "@csstools/postcss-ic-unit": "^2.0.0", - "@csstools/postcss-is-pseudo-class": "^3.0.0", - "@csstools/postcss-logical-float-and-clear": "^1.0.0", - "@csstools/postcss-logical-resize": "^1.0.0", - "@csstools/postcss-logical-viewport-units": "^1.0.0", - "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.0", - "@csstools/postcss-nested-calc": "^2.0.0", - "@csstools/postcss-normalize-display-values": "^2.0.0", - "@csstools/postcss-oklab-function": "^2.0.0", - "@csstools/postcss-progressive-custom-properties": "^2.0.0", - "@csstools/postcss-scope-pseudo-class": "^2.0.0", - "@csstools/postcss-stepped-value-functions": "^2.0.0", - "@csstools/postcss-text-decoration-shorthand": "^2.0.0", - "@csstools/postcss-trigonometric-functions": "^2.0.0", - "@csstools/postcss-unset-value": "^2.0.0", - "autoprefixer": "^10.4.13", - "browserslist": "^4.21.4", - "css-blank-pseudo": "^5.0.0", - "css-has-pseudo": "^5.0.0", - "css-prefers-color-scheme": "^8.0.0", - "cssdb": "^7.4.0", - "postcss-attribute-case-insensitive": "^6.0.0", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-9.3.0.tgz", + "integrity": "sha512-ycw6doPrqV6QxDCtgiyGDef61bEfiSc59HGM4gOw/wxQxmKnhuEery61oOC/5ViENz/ycpRsuhTexs1kUBTvVw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "dependencies": { + "@csstools/postcss-cascade-layers": "^4.0.1", + "@csstools/postcss-color-function": "^3.0.7", + "@csstools/postcss-color-mix-function": "^2.0.7", + "@csstools/postcss-exponential-functions": "^1.0.1", + "@csstools/postcss-font-format-keywords": "^3.0.0", + "@csstools/postcss-gamut-mapping": "^1.0.0", + "@csstools/postcss-gradients-interpolation-method": "^4.0.7", + "@csstools/postcss-hwb-function": "^3.0.6", + "@csstools/postcss-ic-unit": "^3.0.2", + "@csstools/postcss-initial": "^1.0.0", + "@csstools/postcss-is-pseudo-class": "^4.0.3", + "@csstools/postcss-logical-float-and-clear": "^2.0.0", + "@csstools/postcss-logical-overflow": "^1.0.0", + "@csstools/postcss-logical-overscroll-behavior": "^1.0.0", + "@csstools/postcss-logical-resize": "^2.0.0", + "@csstools/postcss-logical-viewport-units": "^2.0.3", + "@csstools/postcss-media-minmax": "^1.1.0", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^2.0.3", + "@csstools/postcss-nested-calc": "^3.0.0", + "@csstools/postcss-normalize-display-values": "^3.0.1", + "@csstools/postcss-oklab-function": "^3.0.7", + "@csstools/postcss-progressive-custom-properties": "^3.0.2", + "@csstools/postcss-relative-color-syntax": "^2.0.7", + "@csstools/postcss-scope-pseudo-class": "^3.0.0", + "@csstools/postcss-stepped-value-functions": "^3.0.2", + "@csstools/postcss-text-decoration-shorthand": "^3.0.3", + "@csstools/postcss-trigonometric-functions": "^3.0.2", + "@csstools/postcss-unset-value": "^3.0.0", + "autoprefixer": "^10.4.16", + "browserslist": "^4.22.1", + "css-blank-pseudo": "^6.0.0", + "css-has-pseudo": "^6.0.0", + "css-prefers-color-scheme": "^9.0.0", + "cssdb": "^7.9.0", + "postcss-attribute-case-insensitive": "^6.0.2", "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^5.0.0", - "postcss-color-hex-alpha": "^9.0.0", - "postcss-color-rebeccapurple": "^8.0.0", - "postcss-custom-media": "^9.1.0", - "postcss-custom-properties": "^13.1.0", - "postcss-custom-selectors": "^7.1.0", - "postcss-dir-pseudo-class": "^7.0.0", - "postcss-double-position-gradients": "^4.0.0", - "postcss-focus-visible": "^8.0.0", - "postcss-focus-within": "^7.0.0", + "postcss-color-functional-notation": "^6.0.2", + "postcss-color-hex-alpha": "^9.0.2", + "postcss-color-rebeccapurple": "^9.0.1", + "postcss-custom-media": "^10.0.2", + "postcss-custom-properties": "^13.3.2", + "postcss-custom-selectors": "^7.1.6", + "postcss-dir-pseudo-class": "^8.0.0", + "postcss-double-position-gradients": "^5.0.2", + "postcss-focus-visible": "^9.0.0", + "postcss-focus-within": "^8.0.0", "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^4.0.0", - "postcss-image-set-function": "^5.0.0", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^5.0.0", - "postcss-logical": "^6.0.0", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^11.0.0", - "postcss-opacity-percentage": "^1.1.3", - "postcss-overflow-shorthand": "^4.0.0", + "postcss-gap-properties": "^5.0.0", + "postcss-image-set-function": "^6.0.1", + "postcss-lab-function": "^6.0.7", + "postcss-logical": "^7.0.0", + "postcss-nesting": "^12.0.1", + "postcss-opacity-percentage": "^2.0.0", + "postcss-overflow-shorthand": "^5.0.0", "postcss-page-break": "^3.0.4", - "postcss-place": "^8.0.0", - "postcss-pseudo-class-any-link": "^8.0.0", + "postcss-place": "^9.0.0", + "postcss-pseudo-class-any-link": "^9.0.0", "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^7.0.0", + "postcss-selector-not": "^7.0.1", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } }, "node_modules/postcss-pseudo-class-any-link": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-8.0.2.tgz", - "integrity": "sha512-FYTIuRE07jZ2CW8POvctRgArQJ43yxhr5vLmImdKUvjFCkR09kh8pIdlCwdx/jbFm7MiW4QP58L4oOUv3grQYA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-9.0.0.tgz", + "integrity": "sha512-QNCYIL98VKFKY6HGDEJpF6+K/sg9bxcUYnOmNHJxZS5wsFDFaVoPeG68WAuhsqwbIBSo/b9fjEnTwY2mTSD+uA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "dependencies": { - "postcss-selector-parser": "^6.0.10" + "postcss-selector-parser": "^6.0.13" }, "engines": { "node": "^14 || ^16 || >=18" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, "peerDependencies": { "postcss": "^8.4" } @@ -14782,9 +10926,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -14856,20 +11000,16 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/promise-polyfill": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", - "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", - "dev": true - }, "node_modules/promise.prototype.finally": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.4.tgz", - "integrity": "sha512-nNc3YbgMfLzqtqvO/q5DP6RR0SiHI9pUPGzyDf1q+usTwCN2kjvAnJkBb7bHe3o+fFSBPpsGMoYtaSi+LTNqng==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.7.tgz", + "integrity": "sha512-iL9OcJRUZcCE5xn6IwhZxO+eMM0VEXjkETHy+Nk+d9q3s7kxVtPg+mBlMO+ZGxNKNMODyKmy/bOyt/yhxTnvEw==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -14878,19 +11018,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -14907,9 +11034,9 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/property-information": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz", - "integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.0.tgz", + "integrity": "sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -14944,29 +11071,13 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } }, - "node_modules/pure-rand": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", - "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -15027,12 +11138,15 @@ ] }, "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/range-parser": { @@ -15177,9 +11291,9 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/react-markdown": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.5.tgz", - "integrity": "sha512-jGJolWWmOWAvzf+xMdB9zwStViODyyFQhNB/bwCerbBKmrTmgmA599CGiOlP58OId1IMoIRsA8UdI1Lod4zb5A==", + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz", + "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==", "dependencies": { "@types/hast": "^2.0.0", "@types/prop-types": "^15.0.0", @@ -15207,9 +11321,9 @@ } }, "node_modules/react-redux": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", - "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", + "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==", "dependencies": { "@babel/runtime": "^7.12.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -15224,7 +11338,7 @@ "react": "^16.8 || ^17.0 || ^18.0", "react-dom": "^16.8 || ^17.0 || ^18.0", "react-native": ">=0.59", - "redux": "^4" + "redux": "^4 || ^5.0.0-beta.0" }, "peerDependenciesMeta": { "@types/react": { @@ -15269,132 +11383,38 @@ } }, "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", "dev": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/readable-stream": { @@ -15428,15 +11448,6 @@ "node": ">=8" } }, - "node_modules/redent/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/redent/node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -15465,46 +11476,39 @@ "redux": "^4" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", "dev": true, "dependencies": { - "regenerate": "^1.4.2" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" }, "engines": { "node": ">= 0.4" @@ -15513,44 +11517,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, "node_modules/rehype-raw": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz", @@ -15566,9 +11532,9 @@ } }, "node_modules/remark-parse": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", - "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", "dependencies": { "@types/mdast": "^3.0.0", "mdast-util-from-markdown": "^1.0.0", @@ -15599,15 +11565,6 @@ "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -15632,16 +11589,16 @@ "dev": true }, "node_modules/reselect": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", - "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -15652,27 +11609,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -15681,15 +11617,6 @@ "node": ">=4" } }, - "node_modules/resolve.exports": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.1.tgz", - "integrity": "sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -15710,15 +11637,15 @@ } }, "node_modules/rimraf": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", - "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "dev": true, "dependencies": { - "glob": "^9.2.0" + "glob": "^10.3.7" }, "bin": { - "rimraf": "dist/cjs/src/bin.js" + "rimraf": "dist/esm/bin.mjs" }, "engines": { "node": ">=14" @@ -15727,61 +11654,31 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.2.1.tgz", - "integrity": "sha512-Pxxgq3W0HyA3XUvSXcFhRSs+43Jsx0ddxcFrbjxNGkL2Ak5BAUBxLqI5G6ADDeCHLfzzXFhe0b1yYcctGmytMA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", - "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.19.1.tgz", - "integrity": "sha512-lAbrdN7neYCg/8WaoWn/ckzCtz+jr70GFfYdlf50OF7387HTg+wiuiqJRFYawwSPpqfqDNYqK7smY/ks2iAudg==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.6.1.tgz", + "integrity": "sha512-jZHaZotEHQaHLgKr8JnQiDT1rmatjgKlMekyksz+yk9jt/8z9quNjnKNRoaM0wd9DC2QKXjmWWuDYtM3jfF8pQ==", "dev": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.6.1", + "@rollup/rollup-android-arm64": "4.6.1", + "@rollup/rollup-darwin-arm64": "4.6.1", + "@rollup/rollup-darwin-x64": "4.6.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.6.1", + "@rollup/rollup-linux-arm64-gnu": "4.6.1", + "@rollup/rollup-linux-arm64-musl": "4.6.1", + "@rollup/rollup-linux-x64-gnu": "4.6.1", + "@rollup/rollup-linux-x64-musl": "4.6.1", + "@rollup/rollup-win32-arm64-msvc": "4.6.1", + "@rollup/rollup-win32-ia32-msvc": "4.6.1", + "@rollup/rollup-win32-x64-msvc": "4.6.1", "fsevents": "~2.3.2" } }, @@ -15820,6 +11717,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -15854,6 +11757,23 @@ "node": ">=6" } }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -15936,14 +11856,38 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -15994,23 +11938,38 @@ "node": ">= 0.8.0" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", "dependencies": { - "kind-of": "^6.0.2" + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -16033,9 +11992,9 @@ } }, "node_modules/shorten-url": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shorten-url/-/shorten-url-1.0.0.tgz", - "integrity": "sha512-dqMa3Vppygf1xo20oxJv3l1z46fpTXg+TlqnfE+4iN3l8DQ51BTVqmoMmZ+7ra+6lUfYNZeSmTjW27nVf9B3mw==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shorten-url/-/shorten-url-1.1.0.tgz", + "integrity": "sha512-mROquyw2ltrorK2YwdUpmFRvpK0iCdURPzyQ/+00jIRn+uBn9v3Ly4aOUJwRIsyHy/2lcRSYxtznUAedmaZ2DA==" }, "node_modules/side-channel": { "version": "1.0.4", @@ -16050,17 +12009,23 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/slash": { "version": "3.0.0", @@ -16088,39 +12053,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", @@ -16174,31 +12106,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -16235,9 +12142,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", "dev": true }, "node_modules/splitargs": { @@ -16245,33 +12152,12 @@ "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", "integrity": "sha512-UUFYD2oWbNwULH6WoVtLUOw8ch586B+HUqcsAjjjeoBQAM1bD4wZRXu01koaxyd8UeYpybWqW4h+lO1Okv40Tg==" }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -16280,6 +12166,12 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.6.0.tgz", + "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", + "dev": true + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -16307,20 +12199,25 @@ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width": { + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -16334,12 +12231,39 @@ "node": ">=8" } }, - "node_modules/string-width/node_modules/emoji-regex": { + "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", @@ -16350,18 +12274,19 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", "side-channel": "^1.0.4" }, "funding": { @@ -16369,13 +12294,13 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -16385,26 +12310,26 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16422,15 +12347,28 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -16440,15 +12378,6 @@ "is-natural-number": "^4.0.1" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/strip-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", @@ -16475,6 +12404,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", + "dev": true, + "dependencies": { + "acorn": "^8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/strip-outer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", @@ -16503,51 +12444,50 @@ "dev": true }, "node_modules/style-to-object": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", - "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", "dependencies": { "inline-style-parser": "0.1.1" } }, "node_modules/stylelint": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.3.0.tgz", - "integrity": "sha512-9UYBYk7K9rtlKcTUDZrtntE840sZM00qyYBQHHe7tjwMNUsPsGvR6Fd43IxHEAhRrDLzpy3TVaHb6CReBB3eFg==", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz", + "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", "dev": true, "dependencies": { - "@csstools/css-parser-algorithms": "^2.0.1", - "@csstools/css-tokenizer": "^2.1.0", - "@csstools/media-query-list-parser": "^2.0.1", - "@csstools/selector-specificity": "^2.1.1", + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0", + "@csstools/media-query-list-parser": "^2.1.4", + "@csstools/selector-specificity": "^3.0.0", "balanced-match": "^2.0.0", "colord": "^2.9.3", - "cosmiconfig": "^8.1.0", - "css-functions-list": "^3.1.0", + "cosmiconfig": "^8.2.0", + "css-functions-list": "^3.2.1", "css-tree": "^2.3.1", "debug": "^4.3.4", - "fast-glob": "^3.2.12", + "fast-glob": "^3.3.1", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^7.0.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.2.0", + "html-tags": "^3.3.1", "ignore": "^5.2.4", "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.27.0", + "known-css-properties": "^0.29.0", "mathml-tag-names": "^2.1.3", - "meow": "^9.0.0", + "meow": "^10.1.5", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.21", - "postcss-media-query-parser": "^0.2.3", + "postcss": "^8.4.28", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.11", + "postcss-selector-parser": "^6.0.13", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", "string-width": "^4.2.3", @@ -16556,11 +12496,10 @@ "supports-hyperlinks": "^3.0.0", "svg-tags": "^1.0.0", "table": "^6.8.1", - "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^5.0.0" + "write-file-atomic": "^5.0.1" }, "bin": { - "stylelint": "bin/stylelint.js" + "stylelint": "bin/stylelint.mjs" }, "engines": { "node": "^14.13.1 || >=16.0.0" @@ -16571,24 +12510,30 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-11.0.0.tgz", - "integrity": "sha512-SoGIHNI748OCZn6BxFYT83ytWoYETCINVHV3LKScVAWQQauWdvmdDqJC5YXWjpBbxg2E761Tg5aUGKLFOVhEkA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", + "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", "dev": true, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, "peerDependencies": { - "stylelint": "^15.3.0" + "stylelint": "^15.10.0" } }, "node_modules/stylelint-config-standard": { - "version": "31.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-31.0.0.tgz", - "integrity": "sha512-CUGAmtROCvX0YgMY2+6P9tqSkHj5z/75XxrQ8bGxvkCa1xYdGDx4poM0pa7cXc3s74/PZLJH/okxZZouRfOSGw==", + "version": "34.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", + "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", "dev": true, "dependencies": { - "stylelint-config-recommended": "^11.0.0" + "stylelint-config-recommended": "^13.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" }, "peerDependencies": { - "stylelint": "^15.3.0" + "stylelint": "^15.10.0" } }, "node_modules/stylelint/node_modules/balanced-match": { @@ -16598,14 +12543,14 @@ "dev": true }, "node_modules/stylelint/node_modules/cosmiconfig": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.0.tgz", - "integrity": "sha512-0tLZ9URlPGU7JsKq0DQOQ3FoRsYX8xDZ7xMiATQfaiGMz7EHowNkbU9u1coAOmnh9p/1ySpm0RB3JNWRXM5GCg==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "dependencies": { - "import-fresh": "^3.2.1", + "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", + "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "engines": { @@ -16613,15 +12558,32 @@ }, "funding": { "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/stylelint/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/stylelint/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", + "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", "dev": true, + "dependencies": { + "flat-cache": "^3.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" } }, "node_modules/stylelint/node_modules/resolve-from": { @@ -16633,33 +12595,35 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/write-file-atomic": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz", - "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==", + "node_modules/stylelint/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" } }, "node_modules/stylis": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", - "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-hyperlinks": { @@ -16675,27 +12639,6 @@ "node": ">=14.18" } }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -16714,15 +12657,13 @@ "dev": true }, "node_modules/swr": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz", - "integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.4.tgz", + "integrity": "sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==", "dependencies": { + "client-only": "^0.0.1", "use-sync-external-store": "^1.2.0" }, - "engines": { - "pnpm": "7" - }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0" } @@ -16765,12 +12706,32 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/table/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/table/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -16848,6 +12809,26 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -16879,12 +12860,30 @@ "node": ">=0.10.0" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "node_modules/tinybench": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.1.tgz", + "integrity": "sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==", "dev": true }, + "node_modules/tinypool": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", + "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -16944,15 +12943,15 @@ } }, "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, "dependencies": { - "punycode": "^2.1.1" + "punycode": "^2.3.1" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/trim-lines": { @@ -16965,12 +12964,15 @@ } }, "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/trim-repeated": { @@ -17003,6 +13005,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -17027,15 +13041,6 @@ "json5": "lib/cli.js" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -17094,27 +13099,75 @@ } }, "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typed-array-length": { @@ -17131,23 +13184,22 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/u-wave-parse-chat-markup": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/u-wave-parse-chat-markup/-/u-wave-parse-chat-markup-2.4.0.tgz", - "integrity": "sha512-jy3BGi0k4kUnu6o1LoL6tlmubMQ9ZSkDk9btrwz4mMMvnjN41v2lCaw8ytSSh4+JwlMgS0MxzpCZWLEYvWlOVw==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/u-wave-parse-chat-markup/-/u-wave-parse-chat-markup-2.5.0.tgz", + "integrity": "sha512-0ZkSm8nhjFwY8Yhx/O58bybyxtFQonOXfxwjbBNnypskCjX+2DDlA0w55ICxjnYghrxe8KhgOJx01mJDnhvJgQ==" }, "node_modules/u-wave-web": { "resolved": "npm", @@ -17157,6 +13209,12 @@ "resolved": "", "link": true }, + "node_modules/ufo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.2.tgz", + "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -17181,45 +13239,11 @@ "through": "^2.3.8" } }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true }, "node_modules/unified": { "version": "10.1.2", @@ -17340,9 +13364,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "dev": true, "funding": [ { @@ -17352,6 +13376,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -17359,7 +13387,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -17410,9 +13438,9 @@ } }, "node_modules/use-debounce": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.3.tgz", - "integrity": "sha512-FhtlbDtDXILJV7Lix5OZj5yX/fW1tzq+VrvK1fnT2bUrPOGruU9Rw8NCEn+UI9wopfERBEZAOQ8lfeCJPllgnw==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz", + "integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==", "engines": { "node": ">= 10.0.0" }, @@ -17442,9 +13470,13 @@ } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -17466,34 +13498,26 @@ "node": ">=8" } }, - "node_modules/uvu/node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -17554,28 +13578,31 @@ } }, "node_modules/vite": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.4.tgz", - "integrity": "sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.4.tgz", + "integrity": "sha512-RzAr8LSvM8lmhB4tQ5OPcBhpjOZRZjuxv9zO5UcxeoY2bd3kP3Ticd40Qma9/BqZ8JS96Ll/jeBX9u+LJZrhVg==", "dev": true, "dependencies": { - "esbuild": "^0.16.14", - "postcss": "^8.4.21", - "resolve": "^1.22.1", - "rollup": "^3.10.0" + "esbuild": "^0.19.3", + "postcss": "^8.4.31", + "rollup": "^4.2.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", + "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", @@ -17588,6 +13615,9 @@ "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, @@ -17602,25 +13632,116 @@ } } }, - "node_modules/w3c-xmlserializer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", - "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "node_modules/vite-node": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", + "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", "dev": true, "dependencies": { - "xml-name-validator": "^4.0.0" + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.4.0", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" }, "engines": { - "node": ">=14" + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/vitest": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", + "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.5", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.34.6", + "@vitest/runner": "0.34.6", + "@vitest/snapshot": "0.34.6", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "acorn": "^8.9.0", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.7.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", + "vite-node": "0.34.6", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "dependencies": { - "makeerror": "1.0.12" + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/web-namespaces": { @@ -17650,15 +13771,15 @@ } }, "node_modules/whatwg-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", - "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "dependencies": { "iconv-lite": "0.6.3" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-encoding/node_modules/iconv-lite": { @@ -17674,30 +13795,30 @@ } }, "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + "version": "3.6.19", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", + "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==" }, "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "dependencies": { - "tr46": "^3.0.0", + "tr46": "^5.0.0", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/which": { @@ -17730,6 +13851,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-collection": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", @@ -17746,16 +13893,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -17764,16 +13910,41 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -17790,39 +13961,65 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -17830,22 +14027,22 @@ "dev": true }, "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.14.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", + "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", "dev": true, "engines": { "node": ">=10.0.0" @@ -17864,12 +14061,12 @@ } }, "node_modules/xml-name-validator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", - "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/xmlchars": { @@ -17896,15 +14093,6 @@ "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==", "dev": true }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -17919,24 +14107,6 @@ "node": ">= 6" } }, - "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", @@ -17946,15 +14116,6 @@ "node": ">=10" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -17988,7 +14149,7 @@ }, "npm": { "name": "u-wave-web", - "version": "2.0.0-alpha.24", + "version": "2.0.0-alpha.28", "license": "MIT", "dependencies": { "env-schema": "^5.0.0", diff --git a/package.json b/package.json index 28017eba0..4ade88245 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,10 @@ { "name": "u-wave-web-build", "description": "Web client for üWave servers.", - "version": "2.0.0-alpha.24", + "version": "2.0.0-alpha.28", "author": "Renée Kooi <renee@kooi.me>", "type": "module", "dependencies": { - "@babel/runtime": "^7.20.13", "@emotion/cache": "^11.6.0", "@emotion/core": "^11.0.0", "@emotion/react": "^11.7.0", @@ -16,7 +15,8 @@ "@mui/system": "^5.11.5", "@mui/utils": "^5.2.2", "@openfonts/open-sans_all": "^1.44.2", - "@tanstack/react-virtual": "3.0.0-beta.54", + "@reduxjs/toolkit": "^1.9.3", + "@tanstack/react-virtual": "3.0.0-beta.68", "@u-wave/react-server-list": "5.0.0-beta.3", "@u-wave/react-translate": "^2.0.2", "@u-wave/react-youtube": "^1.0.0-alpha.3", @@ -26,14 +26,14 @@ "array.from": "^1.1.3", "array.prototype.find": "^2.2.0", "array.prototype.findindex": "^2.2.0", - "clsx": "^1.2.0", + "clsx": "^2.0.0", "css.escape": "^1.5.1", "deepmerge": "^4.3.0", "dlv": "^1.1.3", "dset": "^3.0.0", "es6-promise": "^4.2.8", "es6-symbol": "^3.1.3", - "escape-string-regexp": "^4.0.0", + "escape-string-regexp": "^5.0.0", "event-source-polyfill": "^1.0.24", "express": "^4.18.2", "flash-document-title": "^1.0.0", @@ -76,53 +76,48 @@ "splitargs": "0.0.7", "string.prototype.includes": "^2.0.0", "swr": "^2.1.0", - "u-wave-parse-chat-markup": "^2.4.0", + "u-wave-parse-chat-markup": "^2.5.0", "url-polyfill": "^1.1.11", "use-debounce": "^9.0.3", "uuid": "^9.0.0", "whatwg-fetch": "^3.4.0" }, "devDependencies": { - "@babel/core": "^7.20.12", - "@babel/plugin-transform-modules-commonjs": "^7.14.0", - "@babel/plugin-transform-react-constant-elements": "^7.13.13", - "@babel/plugin-transform-react-inline-elements": "^7.12.13", - "@babel/plugin-transform-runtime": "^7.17.0", - "@babel/preset-env": "^7.14.0", - "@babel/preset-react": "^7.13.13", - "@babel/register": "^7.13.8", "@emotion/css": "^11.10.5", "@emotion/server": "^11.0.0", "@rollup/plugin-yaml": "^4.0.1", - "@testing-library/jest-dom": "^5.16.5", + "@testing-library/jest-dom": "^6.1.4", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", - "@vitejs/plugin-react": "^3.1.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "emojibase-data": "^7.0.0", - "eslint": "^8.34.0", + "@types/uuid": "^9.0.1", + "@typescript-eslint/eslint-plugin": "^6.12.0", + "@typescript-eslint/parser": "^6.12.0", + "@vitejs/plugin-react": "^4.0.0", + "@vitest/coverage-v8": "^0.34.2", + "emojibase-data": "^15.0.0", + "eslint": "^8.36.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-compat": "^4.1.0", "eslint-plugin-import": "^2.27.5", - "eslint-plugin-jest": "^27.2.1", - "eslint-plugin-jest-dom": "^4.0.0", + "eslint-plugin-jest-dom": "^5.0.1", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-testing-library": "^5.10.0", - "get-port": "^6.1.2", - "jest": "^29.5.0", - "jest-environment-jsdom": "^29.5.0", - "jest-fetch-mock": "^3.0.3", - "js-yaml": "^4.1.0", - "p-map": "^5.4.0", + "eslint-plugin-testing-library": "^6.2.0", + "eslint-plugin-vitest": "^0.3.10", + "get-port": "^7.0.0", + "jsdom": "^23.0.1", + "jsonapi-typescript": "^0.1.3", + "p-map": "^6.0.0", "postcss": "^8.4.21", - "postcss-preset-env": "^8.0.1", - "rimraf": "^4.1.1", + "postcss-preset-env": "^9.0.0", + "rimraf": "^5.0.0", "stylelint": "^15.1.0", - "stylelint-config-standard": "^31.0.0", + "stylelint-config-standard": "^34.0.0", "twemoji-emojis": "^14.1.0", - "vite": "^4.0.4" + "typescript": "^5.0.2", + "vite": "^5.0.2", + "vitest": "^0.34.2" }, "engines": { "node": ">= 14", @@ -145,7 +140,8 @@ "serve": "u-wave-web", "start": "npm run dev", "test": "npm run tests-only && npm run lint", - "tests-only": "jest src" + "typecheck": "tsc", + "tests-only": "vitest run" }, "workspaces": { "packages": [ diff --git a/src/Uwave.jsx b/src/Uwave.tsx similarity index 59% rename from src/Uwave.jsx rename to src/Uwave.tsx index 27bc1ae7c..52b45e799 100644 --- a/src/Uwave.jsx +++ b/src/Uwave.tsx @@ -7,64 +7,59 @@ import createCache from '@emotion/cache'; import AppContainer from './containers/App'; import { get as readSession } from './utils/Session'; import configureStore from './redux/configureStore'; -import { initState, socketConnect, setSessionToken } from './actions/LoginActionCreators'; +import { socketConnect, setSessionToken } from './actions/LoginActionCreators'; import { loadCurrentLanguage } from './actions/LocaleActionCreators'; +import { MediaSource } from './context/MediaSourceContext'; +import { initState } from './reducers/auth'; -/** - * @typedef {object} UwaveOptions - * @prop {string} [apiBase] - * @prop {string} [socketUrl] - * @prop {Record<string, string>} [emoji] - * @prop {{ name: string, url: string }[]} [serverEmotes] - */ +interface UwaveOptions { + apiUrl?: string; + socketUrl?: string; + emoji?: Record<string, string>; +} export default class Uwave { - /** @type {UwaveOptions} */ - options = {}; + options: UwaveOptions = {}; - #sources = {}; + #sources: Record<string, MediaSource<Record<string, unknown>>> = {}; - #sessionToken = null; + #sessionToken: string | null = null; - #renderTarget = null; + #renderTarget: Element | null = null; - #aboutPageComponent = null; + #aboutPageComponent: React.ComponentType | null = null; #emotionCache = createCache({ key: 'emc', prepend: true, }); - #resolveReady; + #resolveReady: null | (() => void) = null; + + store?: ReturnType<typeof configureStore>; - ready = new Promise((resolve) => { + ready = new Promise<void>((resolve) => { this.#resolveReady = resolve; }); - /** - * @param {UwaveOptions} [options] - */ - constructor(options = {}, session = readSession()) { + constructor(options: UwaveOptions = {}, session = readSession()) { this.options = options; this.#sessionToken = session; } - use(plugin) { + use(plugin: (uw: this) => void) { plugin(this); return this; } - source(sourcePlugin, opts = {}) { - const sourceFactory = sourcePlugin.default ?? sourcePlugin; - - const type = typeof sourceFactory; - if (type !== 'function' && type !== 'object') { - throw new TypeError(`Source plugin should be a function, got ${type}`); + source(sourcePlugin: MediaSource | ((uw: this, opts: object) => MediaSource), opts = {}) { + if (typeof sourcePlugin !== 'function' && typeof sourcePlugin !== 'object') { + throw new TypeError(`Source plugin should be a function, got ${typeof sourcePlugin}`); } - const source = type === 'function' - ? sourceFactory(this, opts) - : sourceFactory; + const source = typeof sourcePlugin === 'function' + ? sourcePlugin(this, opts) + : sourcePlugin; if (typeof source.name !== 'string') { throw new TypeError('Source plugin did not provide a name'); @@ -75,7 +70,7 @@ export default class Uwave { return source; } - setAboutPageComponent(AboutPageComponent) { + setAboutPageComponent(AboutPageComponent: React.ComponentType) { this.#aboutPageComponent = AboutPageComponent; } @@ -95,15 +90,21 @@ export default class Uwave { } this.store.dispatch(socketConnect()); - await Promise.all([ - this.store.dispatch(loadCurrentLanguage()), + const [initResult] = await Promise.all([ this.store.dispatch(initState()), + this.store.dispatch(loadCurrentLanguage()), ]); - this.#resolveReady(); + this.#resolveReady?.(); + if ('error' in initResult) { + throw Object.assign(new Error(initResult.error.message), initResult.error); + } } - /** @private */ - getComponent() { + private getComponent() { + if (!this.store) { + throw new Error('Uwave not initialized'); + } + return ( <Provider store={this.store}> <StyledEngineProvider injectFirst> @@ -118,7 +119,7 @@ export default class Uwave { ); } - renderToDOM(target) { + renderToDOM(target: Element) { if (!this.store) { this.build(); } diff --git a/src/actions/BoothActionCreators.js b/src/actions/BoothActionCreators.js index 7a7222b6f..9484d6748 100644 --- a/src/actions/BoothActionCreators.js +++ b/src/actions/BoothActionCreators.js @@ -1,51 +1,33 @@ -import { - ADVANCE, - BOOTH_SKIP, - LOAD_HISTORY_START, LOAD_HISTORY_COMPLETE, -} from '../constants/ActionTypes'; +import { mutate } from 'swr'; +import { BOOTH_SKIP } from '../constants/ActionTypes'; import { flattenPlaylistItem } from './PlaylistActionCreators'; -import { get, post } from './RequestActionCreators'; -import { historyIDSelector, isCurrentDJSelector } from '../selectors/boothSelectors'; -import { currentPlaySelector } from '../selectors/roomHistorySelectors'; +import { post } from './RequestActionCreators'; +import { isCurrentDJSelector, currentPlaySelector } from '../selectors/boothSelectors'; import { usersSelector } from '../selectors/userSelectors'; -import mergeIncludedModels from '../utils/mergeIncludedModels'; - -export function advanceToEmpty() { - return (dispatch, getState) => { - dispatch({ - type: ADVANCE, - payload: null, - meta: { previous: currentPlaySelector(getState()) }, - }); - }; -} +import * as actions from '../reducers/booth'; /** * Set the current song and DJ. */ export function advance(nextBooth) { - if (!nextBooth || !nextBooth.historyID) { - return advanceToEmpty(); - } - const { - media, userID, historyID, playlistID, playedAt, - } = nextBooth; return (dispatch, getState) => { - const user = usersSelector(getState())[userID]; - dispatch({ - type: ADVANCE, - payload: { - userID, - historyID, - playlistID, + let payload = null; + if (nextBooth && nextBooth.historyID) { + // TODO this should be done in the reducer? + const user = usersSelector(getState())[nextBooth.userID]; + payload = { + userID: nextBooth.userID, + historyID: nextBooth.historyID, + playlistID: nextBooth.playlistID, user, - media: flattenPlaylistItem(media), - timestamp: playedAt, - }, - meta: { - previous: currentPlaySelector(getState()), - }, - }); + media: flattenPlaylistItem(nextBooth.media), + timestamp: nextBooth.playedAt, + }; + } + + dispatch(actions.advance(payload, currentPlaySelector(getState()))); + + mutate('/booth/history'); }; } @@ -73,33 +55,3 @@ export function skipped({ userID, moderatorID, reason }) { }); }; } - -export function loadHistoryStart() { - return { type: LOAD_HISTORY_START }; -} - -export function loadHistoryComplete(response) { - return (dispatch, getState) => { - const currentHistoryID = historyIDSelector(getState()); - const { meta } = response; - let playHistory = mergeIncludedModels(response); - if (playHistory[0] && playHistory[0]._id === currentHistoryID) { - playHistory = playHistory.slice(1); - } - dispatch({ - type: LOAD_HISTORY_COMPLETE, - payload: playHistory, - meta: { - page: Math.floor(meta.offset / meta.pageSize), - size: meta.pageSize, - }, - }); - }; -} - -export function loadHistory() { - return get('/booth/history', { - onStart: loadHistoryStart, - onComplete: loadHistoryComplete, - }); -} diff --git a/src/actions/ChatActionCreators.js b/src/actions/ChatActionCreators.js deleted file mode 100644 index 7ffa3fedc..000000000 --- a/src/actions/ChatActionCreators.js +++ /dev/null @@ -1,235 +0,0 @@ -import ms from 'ms'; -import parseChatMarkup from 'u-wave-parse-chat-markup'; -import flashDocumentTitle from 'flash-document-title'; -import { v4 as randomUUID } from 'uuid'; -import playMentionSound from '../utils/playMentionSound'; -import { - RECEIVE_MOTD, - SET_MOTD_START, - SET_MOTD_COMPLETE, - SEND_MESSAGE, - RECEIVE_MESSAGE, - LOG, - REMOVE_MESSAGE, - REMOVE_USER_MESSAGES, - REMOVE_ALL_MESSAGES, - MUTE_USER, - UNMUTE_USER, - LOAD_EMOTES, -} from '../constants/ActionTypes'; -import { get, put } from './RequestActionCreators'; -import { - muteTimeoutsSelector, - mutedUserIDsSelector, - currentUserMuteSelector, -} from '../selectors/chatSelectors'; -import { settingsSelector } from '../selectors/settingSelectors'; -import { - currentUserSelector, - userListSelector, - userHasRoleSelector, - currentUserHasRoleSelector, -} from '../selectors/userSelectors'; -import { currentTimeSelector } from '../selectors/timeSelectors'; -import { - getAvailableGroupMentions, - resolveMentions, - hasMention, -} from '../utils/chatMentions'; - -export function receiveMotd(text) { - return { - type: RECEIVE_MOTD, - payload: text, - }; -} - -export function log(text) { - return { - type: LOG, - payload: { - _id: randomUUID(), - text, - }, - }; -} - -export function prepareMessage(state, user, text, parseOpts = {}) { - const parsed = parseChatMarkup(text, parseOpts); - resolveMentions(parsed, state); - return { - type: SEND_MESSAGE, - payload: { - user, - message: text, - parsed, - }, - }; -} - -export function sendChat(text) { - return (dispatch, getState) => { - const state = getState(); - const sender = currentUserSelector(state); - const hasRole = currentUserHasRoleSelector(state); - const mute = currentUserMuteSelector(state); - if (mute) { - const timeLeft = ms(mute.expiresAt - Date.now(), { long: true }); - dispatch(log(`You have been muted, and cannot chat for another ${timeLeft}.`)); - return; - } - - const users = userListSelector(state); - const message = prepareMessage(state, sender, text, { - mentions: [ - ...users.map((user) => user.username), - ...getAvailableGroupMentions(hasRole), - ], - }); - dispatch(message); - }; -} - -function isMuted(state, userID) { - return mutedUserIDsSelector(state).includes(userID); -} - -export function receive(message) { - return (dispatch, getState) => { - const state = getState(); - const settings = settingsSelector(state); - const currentUser = currentUserSelector(state); - const users = userListSelector(state); - const sender = users.find((user) => user._id === message.userID); - const senderHasRole = userHasRoleSelector(state)(sender); - const mentions = [ - ...users.map((user) => user.username), - ...getAvailableGroupMentions((mention) => senderHasRole(`chat.mention.${mention}`)), - ]; - - if (isMuted(state, message.userID)) { - return; - } - - const parsed = parseChatMarkup(message.text, { mentions }); - resolveMentions(parsed, state); - - const isMention = currentUser ? hasMention(parsed, currentUser._id) : false; - - dispatch({ - type: RECEIVE_MESSAGE, - payload: { - message: { - ...message, - user: sender, - }, - isMention, - parsed, - }, - }); - - if (isMention) { - if (settings.mentionSound) { - playMentionSound(); - } - flashDocumentTitle(`💬 ${sender.username}`); - } - }; -} - -export function removeMessage(id) { - return { - type: REMOVE_MESSAGE, - payload: { _id: id }, - }; -} - -export function removeMessagesByUser(userID) { - return { - type: REMOVE_USER_MESSAGES, - payload: { userID }, - }; -} - -export function removeAllMessages() { - return { - type: REMOVE_ALL_MESSAGES, - }; -} - -function expireMute(userID) { - return { - type: UNMUTE_USER, - payload: { userID }, - }; -} - -export function muteUser(userID, { moderatorID, expiresAt }) { - return (dispatch, getState) => { - const currentTime = currentTimeSelector(getState()); - const expireIn = expiresAt - currentTime; - - dispatch({ - type: MUTE_USER, - payload: { - userID, - moderatorID, - expiresAt, - expirationTimer: expireIn > 0 - ? setTimeout(() => dispatch(expireMute(userID)), expireIn) : null, - }, - }); - }; -} - -export function unmuteUser(userID, { moderatorID }) { - return (dispatch, getState) => { - const muteTimeouts = muteTimeoutsSelector(getState()); - if (muteTimeouts && muteTimeouts[userID]) { - clearTimeout(muteTimeouts[userID]); - } - dispatch({ - type: UNMUTE_USER, - payload: { userID, moderatorID }, - }); - }; -} - -export function setMotdStart(motd) { - return { - type: SET_MOTD_START, - payload: motd, - }; -} - -export function setMotdComplete(motd) { - return { - type: SET_MOTD_COMPLETE, - payload: motd, - }; -} - -export function setMotd(text) { - return put('/motd', { motd: text }, { - onStart: () => setMotdStart(text), - onComplete: ({ data }) => (dispatch) => { - dispatch(setMotdComplete(data.motd)); - dispatch(log(`Message of the Day is now: ${data.motd}`)); - }, - onError: (error) => ({ - type: SET_MOTD_COMPLETE, - error: true, - payload: error, - }), - }); -} - -export function loadEmotes() { - return async (dispatch) => { - const emotes = await dispatch(get('/emotes')); - dispatch({ - type: LOAD_EMOTES, - payload: { emotes: emotes.data }, - }); - }; -} diff --git a/src/actions/ChatActionCreators.ts b/src/actions/ChatActionCreators.ts new file mode 100644 index 000000000..d95f26501 --- /dev/null +++ b/src/actions/ChatActionCreators.ts @@ -0,0 +1,122 @@ +import type { AnyAction } from 'redux'; +import type { ThunkAction } from 'redux-thunk'; +import ms from 'ms'; +import parseChatMarkup from 'u-wave-parse-chat-markup'; +import flashDocumentTitle from 'flash-document-title'; +import playMentionSound from '../utils/playMentionSound'; +import { + mutedUserIDsSelector, + currentUserMuteSelector, +} from '../selectors/chatSelectors'; +import { + currentUserSelector, + userListSelector, + userHasRoleSelector, + currentUserHasRoleSelector, +} from '../selectors/userSelectors'; +import { + getAvailableGroupMentions, + resolveMentions, + hasMention, +} from '../utils/chatMentions'; +import * as actions from '../reducers/chat'; +import { mentionSoundEnabledSelector } from '../reducers/settings'; +import type { StoreState } from '../redux/configureStore'; +import type { User } from '../reducers/users'; + +type Thunk = ThunkAction<unknown, StoreState, never, AnyAction>; + +export function log(text: string) { + return actions.log(text); +} + +export function prepareMessage(state: StoreState, user: User, text: string, parseOpts = {}) { + const parsed = parseChatMarkup(text, parseOpts); + resolveMentions(parsed, state); + return actions.sendMessage({ + user, + message: text, + parsed, + }); +} + +export function sendChat(text: string): Thunk { + return (dispatch, getState) => { + const state = getState(); + const sender = currentUserSelector(state); + const hasRole = currentUserHasRoleSelector(state); + const mute = currentUserMuteSelector(state); + if (mute) { + const timeLeft = ms(mute.expiresAt - Date.now(), { long: true }); + dispatch(log(`You have been muted, and cannot chat for another ${timeLeft}.`)); + return; + } + + // Shouldn't really happen + if (!sender) { + return; + } + + const users = userListSelector(state); + const message = prepareMessage(state, sender, text, { + mentions: [ + ...users.map((user) => user.username), + ...getAvailableGroupMentions(hasRole), + ], + }); + dispatch(message); + }; +} + +function isMuted(state: StoreState, userID: string) { + return mutedUserIDsSelector(state).includes(userID); +} + +export function receive(message: { + _id: string, + userID: string, + text: string, + timestamp: number, +}): Thunk { + return (dispatch, getState) => { + const state = getState(); + const mentionSoundEnabled = mentionSoundEnabledSelector(state); + const currentUser = currentUserSelector(state); + const users = userListSelector(state); + const sender = users.find((user) => user._id === message.userID); + if (!sender) { + // TODO we should find the user somehow? + return; + } + const senderHasRole = userHasRoleSelector(state)(sender); + const mentions = [ + ...users.map((user) => user.username), + ...getAvailableGroupMentions((mention) => senderHasRole(`chat.mention.${mention}`)), + ]; + + if (isMuted(state, message.userID)) { + return; + } + + const parsed = parseChatMarkup(message.text, { mentions }); + resolveMentions(parsed, state); + + const isMention = currentUser ? hasMention(parsed, currentUser._id) : false; + + dispatch(actions.receiveMessage({ + message: { + ...message, + user: sender, + }, + isMention, + parsed, + })); + + if (isMention) { + if (mentionSoundEnabled) { + playMentionSound(); + } + flashDocumentTitle(`💬 ${sender.username}`); + } + }; +} diff --git a/src/actions/ImportActionCreators.js b/src/actions/ImportActionCreators.js index b695f04ba..6c1a8b95e 100644 --- a/src/actions/ImportActionCreators.js +++ b/src/actions/ImportActionCreators.js @@ -1,16 +1,9 @@ import { - SHOW_IMPORT_PANEL, HIDE_IMPORT_PANEL, SHOW_IMPORT_SOURCE_PANEL, HIDE_IMPORT_SOURCE_PANEL, } from '../constants/ActionTypes'; -export function showImportPanel() { - return { - type: SHOW_IMPORT_PANEL, - }; -} - export function hideImportPanel() { return { type: HIDE_IMPORT_PANEL, diff --git a/src/actions/LocaleActionCreators.js b/src/actions/LocaleActionCreators.js index 6e4012c54..3cccfb663 100644 --- a/src/actions/LocaleActionCreators.js +++ b/src/actions/LocaleActionCreators.js @@ -4,7 +4,7 @@ import { LOAD_LANGUAGE_COMPLETE, } from '../constants/ActionTypes'; import { loadedLanguagesSelector } from '../selectors/localeSelectors'; -import { languageSelector as currentLanguageSelector } from '../selectors/settingSelectors'; +import { languageSelector as currentLanguageSelector } from '../reducers/settings'; import { resources } from '../locales'; const inFlight = {}; diff --git a/src/actions/LoginActionCreators.js b/src/actions/LoginActionCreators.js index 7a7120cac..f32cfe72f 100644 --- a/src/actions/LoginActionCreators.js +++ b/src/actions/LoginActionCreators.js @@ -1,8 +1,6 @@ import { - INIT_STATE, SOCKET_CONNECT, SOCKET_RECONNECT, - AUTH_STRATEGIES, REGISTER_START, REGISTER_COMPLETE, LOGIN_START, @@ -11,16 +9,10 @@ import { LOGOUT_START, LOGOUT_COMPLETE, RESET_PASSWORD_COMPLETE, - LOAD_ALL_PLAYLISTS_START, } from '../constants/ActionTypes'; import * as Session from '../utils/Session'; import { get, post, del } from './RequestActionCreators'; -import { loadHistory } from './BoothActionCreators'; -import { setPlaylists, loadPlaylist } from './PlaylistActionCreators'; -import { syncTimestamps } from './TickerActionCreators'; -import { closeLoginDialog } from './DialogActionCreators'; -import { loadEmotes } from './ChatActionCreators'; -import { tokenSelector } from '../selectors/userSelectors'; +import { initState } from '../reducers/auth'; export function socketConnect() { return { type: SOCKET_CONNECT }; @@ -30,62 +22,6 @@ export function socketReconnect() { return { type: SOCKET_RECONNECT }; } -export function setAuthenticationStrategies(strategies) { - return { - type: AUTH_STRATEGIES, - payload: { strategies }, - }; -} - -export function loginComplete({ token, socketToken, user }) { - return (dispatch) => { - dispatch({ - type: LOGIN_COMPLETE, - payload: { - token, - socketToken, - user, - }, - }); - dispatch(closeLoginDialog()); - }; -} - -export function loadedState(state) { - return (dispatch, getState) => { - dispatch({ - type: INIT_STATE, - payload: state, - }); - if (state.user) { - const token = tokenSelector(getState()); - dispatch(loginComplete({ - token, - socketToken: state.socketToken, - user: state.user, - })); - } - if (state.activePlaylist) { - dispatch(loadPlaylist(state.activePlaylist)); - } - }; -} - -export function initState() { - const beforeTime = Date.now(); - - return get('/now', { - onStart: () => ({ type: LOAD_ALL_PLAYLISTS_START }), - onComplete: (state) => (dispatch) => { - dispatch(syncTimestamps(beforeTime, state.time)); - dispatch(loadedState(state)); - dispatch(loadHistory()); - dispatch(loadEmotes()); - return state; - }, - }); -} - export function setSessionToken(token) { return { type: SET_TOKEN, @@ -146,10 +82,7 @@ function logoutStart() { } function logoutComplete() { - return (dispatch) => { - dispatch({ type: LOGOUT_COMPLETE }); - dispatch(setPlaylists([])); - }; + return { type: LOGOUT_COMPLETE }; } export function logout() { diff --git a/src/actions/ModerationActionCreators.js b/src/actions/ModerationActionCreators.js index 4d91b731b..33343f687 100644 --- a/src/actions/ModerationActionCreators.js +++ b/src/actions/ModerationActionCreators.js @@ -10,7 +10,6 @@ import { ADD_USER_ROLES_START, ADD_USER_ROLES_COMPLETE, REMOVE_USER_ROLES_START, REMOVE_USER_ROLES_COMPLETE, } from '../constants/ActionTypes'; -import { removeMessage, removeMessagesByUser, removeAllMessages } from './ChatActionCreators'; export function skipCurrentDJ(reason = '', shouldRemove = false) { return (dispatch, getState) => { @@ -145,7 +144,6 @@ export function removeUserRole(user, role) { export function deleteChatMessage(id) { return del(`/chat/${id}`, {}, { - onStart: () => removeMessage(id), onError: (error) => ({ type: undefined, error: true, @@ -157,7 +155,6 @@ export function deleteChatMessage(id) { export function deleteChatMessagesByUser(userID) { return del(`/chat/user/${userID}`, {}, { - onComplete: () => removeMessagesByUser(userID), onError: (error) => ({ type: undefined, error: true, @@ -169,7 +166,6 @@ export function deleteChatMessagesByUser(userID) { export function deleteAllChatMessages() { return del('/chat', {}, { - onComplete: removeAllMessages, onError: (error) => ({ type: undefined, error: true, diff --git a/src/actions/OverlayActionCreators.js b/src/actions/OverlayActionCreators.js deleted file mode 100644 index 5a7db148d..000000000 --- a/src/actions/OverlayActionCreators.js +++ /dev/null @@ -1,39 +0,0 @@ -import { OPEN_OVERLAY, CLOSE_OVERLAY, TOGGLE_OVERLAY } from '../constants/ActionTypes'; - -export function openOverlay(overlay) { - return { - type: OPEN_OVERLAY, - payload: { overlay }, - }; -} - -export function toggleOverlay(overlay) { - return { - type: TOGGLE_OVERLAY, - payload: { overlay }, - }; -} - -export function toggleRoomHistory() { - return toggleOverlay('roomHistory'); -} - -export function togglePlaylistManager() { - return toggleOverlay('playlistManager'); -} - -export function toggleSettings() { - return toggleOverlay('settings'); -} - -export function toggleAbout() { - return toggleOverlay('about'); -} - -export function toggleAdmin() { - return toggleOverlay('admin'); -} - -export function closeAll() { - return { type: CLOSE_OVERLAY }; -} diff --git a/src/actions/PlaybackActionCreators.js b/src/actions/PlaybackActionCreators.js index 4718ba2a0..df10773ae 100644 --- a/src/actions/PlaybackActionCreators.js +++ b/src/actions/PlaybackActionCreators.js @@ -1,37 +1,4 @@ -import { set } from './SettingsActionCreators'; -import { settingsSelector } from '../selectors/settingSelectors'; -import { - ENTER_FULLSCREEN, - EXIT_FULLSCREEN, -} from '../constants/ActionTypes'; - -export function setVolume(volume) { - return set('volume', volume); -} - -export function mute() { - return set('muted', true); -} - -export function unmute() { - return set('muted', false); -} - -export function setVideoSize(size) { - return set('videoSize', size); -} - -const nextVideoSize = { - large: 'small', - small: 'large', -}; -export function toggleVideoSize() { - return (dispatch, getState) => { - const current = settingsSelector(getState()).videoSize; - const other = nextVideoSize[current]; - dispatch(setVideoSize(other)); - }; -} +import { ENTER_FULLSCREEN, EXIT_FULLSCREEN } from '../constants/ActionTypes'; export function enterFullscreen() { return { type: ENTER_FULLSCREEN }; diff --git a/src/actions/PlaylistActionCreators.js b/src/actions/PlaylistActionCreators.js index c6ce39c8f..9e0c3001c 100644 --- a/src/actions/PlaylistActionCreators.js +++ b/src/actions/PlaylistActionCreators.js @@ -1,18 +1,9 @@ import { - LOAD_ALL_PLAYLISTS_START, LOAD_ALL_PLAYLISTS_COMPLETE, LOAD_PLAYLIST_START, LOAD_PLAYLIST_COMPLETE, FILTER_PLAYLIST_ITEMS, FILTER_PLAYLIST_ITEMS_START, FILTER_PLAYLIST_ITEMS_COMPLETE, PLAYLIST_CYCLED, - SELECT_PLAYLIST, - ACTIVATE_PLAYLIST_START, ACTIVATE_PLAYLIST_COMPLETE, - CREATE_PLAYLIST_START, CREATE_PLAYLIST_COMPLETE, - RENAME_PLAYLIST_START, RENAME_PLAYLIST_COMPLETE, DELETE_PLAYLIST_START, DELETE_PLAYLIST_COMPLETE, - OPEN_ADD_MEDIA_MENU, CLOSE_ADD_MEDIA_MENU, - ADD_MEDIA_START, ADD_MEDIA_COMPLETE, - REMOVE_MEDIA_START, REMOVE_MEDIA_COMPLETE, - MOVE_MEDIA_START, MOVE_MEDIA_COMPLETE, UPDATE_MEDIA_START, UPDATE_MEDIA_COMPLETE, SHUFFLE_PLAYLIST_START, SHUFFLE_PLAYLIST_COMPLETE, } from '../constants/ActionTypes'; @@ -21,8 +12,6 @@ import { del, get, post, put, } from './RequestActionCreators'; import { - playlistsSelector, - playlistItemsSelector, playlistItemFilterSelector, activePlaylistIDSelector, selectedPlaylistIDSelector, @@ -30,16 +19,10 @@ import { selectedPlaylistSelector, } from '../selectors/playlistSelectors'; import mergeIncludedModels from '../utils/mergeIncludedModels'; +import { selectPlaylist } from '../reducers/playlists'; const MEDIA_PAGE_SIZE = 50; -export function setPlaylists(playlists) { - return { - type: LOAD_ALL_PLAYLISTS_COMPLETE, - payload: { playlists }, - }; -} - // TODO It would be good to get rid of this export function flattenPlaylistItem(item) { return { @@ -141,19 +124,6 @@ export function filterPlaylistItems(playlistID, filter) { }; } -export function selectPlaylist(playlistID) { - return (dispatch) => { - dispatch({ - type: SELECT_PLAYLIST, - payload: { playlistID }, - }); - - if (playlistID) { - dispatch(loadPlaylist(playlistID)); - } - }; -} - export function playlistCycled(playlistID) { return { type: PLAYLIST_CYCLED, @@ -199,116 +169,6 @@ export function cyclePlaylist(playlistID) { }; } -export function activatePlaylistStart(playlistID) { - return { - type: ACTIVATE_PLAYLIST_START, - payload: { playlistID }, - }; -} - -export function activatePlaylistComplete(playlistID) { - return { - type: ACTIVATE_PLAYLIST_COMPLETE, - payload: { playlistID }, - }; -} - -export function activatePlaylist(playlistID) { - return put(`/playlists/${playlistID}/activate`, {}, { - onStart: () => activatePlaylistStart(playlistID), - onComplete: () => activatePlaylistComplete(playlistID), - onError: (error) => ({ - type: ACTIVATE_PLAYLIST_COMPLETE, - error: true, - payload: error, - meta: { playlistID }, - }), - }); -} - -export function loadPlaylistsStart() { - return { type: LOAD_ALL_PLAYLISTS_START }; -} - -export function loadPlaylistsComplete(playlists) { - return { - type: LOAD_ALL_PLAYLISTS_COMPLETE, - payload: { playlists }, - }; -} - -export function loadPlaylists() { - return get('/playlists', { - onStart: loadPlaylistsStart, - onComplete: (res) => loadPlaylistsComplete(res.data), - onError: (error) => ({ - type: LOAD_ALL_PLAYLISTS_COMPLETE, - error: true, - payload: error, - }), - }); -} - -export function createPlaylistStart(props, tempId) { - return { - type: CREATE_PLAYLIST_START, - payload: props, - meta: { tempId }, - }; -} - -export function createPlaylistComplete(playlist, tempId) { - return { - type: CREATE_PLAYLIST_COMPLETE, - payload: { playlist }, - meta: { tempId }, - }; -} - -export function createPlaylist(name) { - const tempId = -Date.now(); - const description = ''; - const shared = false; - - return post('/playlists', { name, description, shared }, { - onStart: () => createPlaylistStart({ name, description, shared }, tempId), - onComplete: (res) => (dispatch) => { - const playlist = res.data; - const { active } = res.meta; - dispatch(createPlaylistComplete(playlist, tempId)); - if (active) { - dispatch(activatePlaylistComplete(playlist._id)); - } - return playlist; - }, - onError: (error) => ({ - type: CREATE_PLAYLIST_COMPLETE, - error: true, - payload: error, - meta: { tempId }, - }), - }); -} - -export function renamePlaylist(playlistID, name) { - return put(`/playlists/${playlistID}/rename`, { name }, { - onStart: () => ({ - type: RENAME_PLAYLIST_START, - payload: { playlistID, name }, - }), - onComplete: ({ data }) => ({ - type: RENAME_PLAYLIST_COMPLETE, - payload: { playlistID, name: data.name }, - }), - onError: (error) => ({ - type: RENAME_PLAYLIST_COMPLETE, - error: true, - payload: error, - meta: { playlistID, name }, - }), - }); -} - /** * Select or activate a different playlist than the one given. * @return Promise @@ -372,104 +232,6 @@ export function deletePlaylist(playlistID) { }; } -/** - * @param {PlaylistItemDesc[]} items - The items to add. - * @param {{ x: number, y: number }} position - Where to show the menu. - */ -export function addMediaMenu(items, position) { - return (dispatch, getState) => { - const playlists = playlistsSelector(getState()); - dispatch({ - type: OPEN_ADD_MEDIA_MENU, - payload: { - media: items, - }, - meta: { - playlists, - position, - type: 'add', - }, - }); - }; -} - -export function closeAddMediaMenu() { - return { type: CLOSE_ADD_MEDIA_MENU }; -} - -export function addMediaStart(playlistID, media, location) { - return { - type: ADD_MEDIA_START, - payload: { playlistID, media, location }, - }; -} - -export function addMediaComplete(playlistID, newSize, insert) { - return { - type: ADD_MEDIA_COMPLETE, - payload: { - playlistID, - newSize, - afterID: insert.afterID, - appendedMedia: insert.media, - }, - }; -} - -/** - * @typedef {{ - * sourceType: string, - * sourceID: string, - * artist?: string, - * title?: string, - * start?: number, - * end?: number, - * }} PlaylistItemDesc - */ - -/** - * Keep only the playlist item properties that are necessary to add an item to - * a playlist. The rest ("thumbnail" etc) is left out for smaller payloads. - * - * @param {PlaylistItemDesc} item - */ -function minimizePlaylistItem(item) { - return { - sourceType: item.sourceType, - sourceID: item.sourceID, - artist: item.artist, - title: item.title, - start: item.start, - end: item.end, - }; -} - -/** - * @param {{ _id: string }} playlist - * @param {PlaylistItemDesc[]} items - * @param {string|null} [afterID] - */ -export function addMedia(playlist, items, afterID = null) { - const payload = { - items: items.map(minimizePlaylistItem), - after: afterID, - }; - - return post(`/playlists/${playlist._id}/media`, payload, { - onStart: () => addMediaStart(playlist._id, items, afterID), - onComplete: (res) => addMediaComplete( - playlist._id, - res.meta.playlistSize, - { afterID, media: mergeIncludedModels(res).map(flattenPlaylistItem) }, - ), - onError: (error) => ({ - type: ADD_MEDIA_COMPLETE, - error: true, - payload: error, - }), - }); -} - export function editMedia(playlistID, media) { return openEditMediaDialog(playlistID, media); } @@ -501,95 +263,6 @@ export function updateMedia(playlistID, mediaID, props) { }); } -export function removeMediaStart(playlistID, items) { - return { - type: REMOVE_MEDIA_START, - payload: { playlistID, medias: items }, - }; -} - -export function removeMediaComplete(playlistID, newSize, removedMedia) { - return { - type: REMOVE_MEDIA_COMPLETE, - payload: { - playlistID, - newSize, - removedMedia, - }, - }; -} - -export function removeMedia(playlistID, items) { - const itemIDs = items.map((media) => media._id); - return del(`/playlists/${playlistID}/media`, { items: itemIDs }, { - onStart: () => removeMediaStart(playlistID, items), - onComplete: ({ meta }) => removeMediaComplete( - playlistID, - meta.playlistSize, - items, - ), - onError: (error) => ({ - type: REMOVE_MEDIA_COMPLETE, - error: true, - payload: error, - }), - }); -} - -export function moveMediaStart(playlistID, items, location) { - return { - type: MOVE_MEDIA_START, - payload: { playlistID, location, medias: items }, - }; -} - -export function moveMediaComplete(playlistID, items, location) { - return { - type: MOVE_MEDIA_COMPLETE, - payload: { playlistID, location, medias: items }, - }; -} - -function resolveMoveOptions(playlist = [], opts = {}) { - if (opts.after) { - return { after: opts.after }; - } - if (opts.before) { - for (let i = 0, l = playlist.length; i < l; i += 1) { - if (playlist[i] && playlist[i]._id === opts.before) { - if (i === 0) { - return { at: 'start' }; - } - return { after: playlist[i - 1]._id }; - } - } - } - if (opts.at) { - return { at: opts.at }; - } - return null; -} - -export function moveMedia(playlistID, medias, opts) { - return (dispatch, getState) => { - const playlistItems = playlistItemsSelector(getState())[playlistID]; - const location = resolveMoveOptions(playlistItems, opts); - - const items = medias.map((media) => media._id); - - return dispatch(put(`/playlists/${playlistID}/move`, { items, ...location }, { - onStart: () => moveMediaStart(playlistID, medias, location), - onComplete: () => moveMediaComplete(playlistID, medias, location), - onError: (error) => ({ - type: MOVE_MEDIA_COMPLETE, - error: true, - payload: error, - meta: { playlistID, medias, location }, - }), - })); - }; -} - export function shufflePlaylistStart(playlistID) { return { type: SHUFFLE_PLAYLIST_START, diff --git a/src/actions/SearchActionCreators.js b/src/actions/SearchActionCreators.js deleted file mode 100644 index 9992eb543..000000000 --- a/src/actions/SearchActionCreators.js +++ /dev/null @@ -1,9 +0,0 @@ -import { SHOW_SEARCH_RESULTS, HIDE_SEARCH_RESULTS } from '../constants/ActionTypes'; - -export function showSearchResults() { - return { type: SHOW_SEARCH_RESULTS }; -} - -export function hideSearchResults() { - return { type: HIDE_SEARCH_RESULTS }; -} diff --git a/src/actions/SettingsActionCreators.js b/src/actions/SettingsActionCreators.js deleted file mode 100644 index 81900abdb..000000000 --- a/src/actions/SettingsActionCreators.js +++ /dev/null @@ -1,25 +0,0 @@ -import { dset } from 'dset'; -import { - LOAD_SETTINGS, - CHANGE_SETTING, -} from '../constants/ActionTypes'; - -export function loadSettings(obj) { - return { - type: LOAD_SETTINGS, - payload: obj, - }; -} - -export function set(name, value) { - const changeset = {}; - dset(changeset, name, value); - return { - type: CHANGE_SETTING, - payload: changeset, - }; -} - -export function setLanguage(lang) { - return set('language', lang); -} diff --git a/src/actions/ThemeActionCreators.js b/src/actions/ThemeActionCreators.js deleted file mode 100644 index 69921bfb5..000000000 --- a/src/actions/ThemeActionCreators.js +++ /dev/null @@ -1,9 +0,0 @@ -import { RESET_THEME, APPLY_THEME } from '../constants/ActionTypes'; - -export function debugResetTheme() { - return { type: RESET_THEME }; -} - -export function debugApplyTheme(newValues) { - return { type: APPLY_THEME, payload: newValues }; -} diff --git a/src/actions/UserActionCreators.js b/src/actions/UserActionCreators.js deleted file mode 100644 index 2008e26d6..000000000 --- a/src/actions/UserActionCreators.js +++ /dev/null @@ -1,124 +0,0 @@ -import { put } from './RequestActionCreators'; -import { - LOAD_ONLINE_USERS, - USER_JOIN, - USER_LEAVE, - CHANGE_USERNAME, - USER_ADD_ROLES, - USER_REMOVE_ROLES, - - RECEIVE_GUEST_COUNT, - - DO_CHANGE_USERNAME_START, - DO_CHANGE_USERNAME_COMPLETE, -} from '../constants/ActionTypes'; -import { - currentUserSelector, - usersSelector, -} from '../selectors/userSelectors'; - -export function setUsers(users) { - return { - type: LOAD_ONLINE_USERS, - payload: { users }, - }; -} - -export function receiveGuestCount(guests) { - return { - type: RECEIVE_GUEST_COUNT, - payload: { guests }, - }; -} - -export function join(user) { - return { - type: USER_JOIN, - payload: { - user, - timestamp: Date.now(), - }, - }; -} - -export function leave(id) { - return (dispatch, getState) => { - const user = usersSelector(getState())[id]; - return dispatch({ - type: USER_LEAVE, - payload: { - user, - userID: id, - timestamp: Date.now(), - }, - }); - }; -} - -export function changeUsername(userID, username) { - return (dispatch, getState) => { - const user = usersSelector(getState())[userID]; - return dispatch({ - type: CHANGE_USERNAME, - payload: { - user, - userID, - username, - timestamp: Date.now(), - }, - }); - }; -} - -export function doChangeUsername(username) { - return (dispatch, getState) => { - const user = currentUserSelector(getState()); - - return dispatch(put(`/users/${user._id}/username`, { username }, { - onStart: () => ({ - type: DO_CHANGE_USERNAME_START, - payload: { username }, - }), - onComplete: ({ data }) => ({ - type: DO_CHANGE_USERNAME_COMPLETE, - payload: { username: data.username }, - }), - onError: (error) => ({ - type: DO_CHANGE_USERNAME_COMPLETE, - error: true, - payload: error, - meta: { username }, - }), - })); - }; -} - -export function addUserRoles(userID, roles) { - return (dispatch, getState) => { - const user = usersSelector(getState())[userID]; - return dispatch({ - type: USER_ADD_ROLES, - payload: { - user, - userID, - roles, - timestamp: Date.now(), - }, - }); - }; -} - -export function removeUserRoles(userID, roles) { - return (dispatch, getState) => { - const user = usersSelector(getState())[userID]; - return dispatch({ - type: USER_REMOVE_ROLES, - payload: { - user, - userID, - roles, - timestamp: Date.now(), - }, - }); - }; -} diff --git a/src/actions/VoteActionCreators.js b/src/actions/VoteActionCreators.js index 5447b4127..88f55f9e5 100644 --- a/src/actions/VoteActionCreators.js +++ b/src/actions/VoteActionCreators.js @@ -1,9 +1,6 @@ import { put, post } from './RequestActionCreators'; import { historyIDSelector } from '../selectors/boothSelectors'; -import { playlistsSelector } from '../selectors/playlistSelectors'; import { - OPEN_ADD_MEDIA_MENU, - LOAD_VOTES, FAVORITE, UPVOTE, DOWNVOTE, DO_FAVORITE_START, DO_FAVORITE_COMPLETE, DO_UPVOTE, DO_DOWNVOTE, @@ -11,17 +8,10 @@ import { import mergeIncludedModels from '../utils/mergeIncludedModels'; import { flattenPlaylistItem } from './PlaylistActionCreators'; -export function setVoteStats(voteStats) { - return { - type: LOAD_VOTES, - payload: voteStats, - }; -} - -export function favorited({ userID, historyID }) { +export function favorited({ userID }) { return { type: FAVORITE, - payload: { userID, historyID }, + payload: { userID }, }; } @@ -57,22 +47,6 @@ export function doDownvote() { }; } -export function openFavoriteMenu(position) { - return (dispatch, getState) => { - const playlists = playlistsSelector(getState()); - const historyID = historyIDSelector(getState()); - dispatch({ - type: OPEN_ADD_MEDIA_MENU, - payload: { historyID }, - meta: { - playlists, - position, - type: 'favorite', - }, - }); - }; -} - export function favoriteMediaStart(playlistID, historyID) { return { type: DO_FAVORITE_START, diff --git a/src/actions/WaitlistActionCreators.js b/src/actions/WaitlistActionCreators.js index 509edc465..6bb58bdf7 100644 --- a/src/actions/WaitlistActionCreators.js +++ b/src/actions/WaitlistActionCreators.js @@ -1,12 +1,5 @@ import { del, post, put } from './RequestActionCreators'; import { - WAITLIST_LOAD, - WAITLIST_LOCK, - WAITLIST_CLEAR, - WAITLIST_UPDATE, - WAITLIST_JOIN, - WAITLIST_LEAVE, - WAITLIST_MOVE, DO_JOIN_START, DO_JOIN_COMPLETE, DO_LEAVE_START, DO_LEAVE_COMPLETE, DO_LOCK_START, DO_LOCK_COMPLETE, @@ -14,36 +7,6 @@ import { } from '../constants/ActionTypes'; import { currentUserSelector } from '../selectors/userSelectors'; -export function setWaitList(data) { - return { - type: WAITLIST_LOAD, - payload: { - waitlist: data.waitlist, - locked: data.locked, - }, - }; -} - -export function setLocked(lock) { - return { - type: WAITLIST_LOCK, - payload: { - locked: lock, - }, - }; -} - -export function clearWaitlist() { - return { type: WAITLIST_CLEAR }; -} - -export function updatedWaitlist(waitlist) { - return { - type: WAITLIST_UPDATE, - payload: { waitlist }, - }; -} - // TODO split joining the waitlist and adding another user to the waitlist // into two different actions. export function joinWaitlist(otherUser) { @@ -65,13 +28,6 @@ export function joinWaitlist(otherUser) { }; } -export function joinedWaitlist({ userID, waitlist }) { - return { - type: WAITLIST_JOIN, - payload: { userID, waitlist }, - }; -} - export function leaveWaitlist(otherUser) { return (dispatch, getState) => { const user = otherUser ?? currentUserSelector(getState()); @@ -91,26 +47,6 @@ export function leaveWaitlist(otherUser) { }; } -export function leftWaitlist({ userID, waitlist }) { - return { - type: WAITLIST_LEAVE, - payload: { userID, waitlist }, - }; -} - -export function movedInWaitlist({ - userID, moderatorID, position, waitlist, -}) { - return (dispatch) => { - dispatch({ - type: WAITLIST_MOVE, - payload: { userID, position }, - meta: { moderatorID }, - }); - dispatch(updatedWaitlist(waitlist)); - }; -} - function putLock(status) { return put('/waitlist/lock', { lock: status, clear: false }, { onStart: () => ({ diff --git a/src/admin/components/AdminApp/index.css b/src/admin/components/AdminApp/index.css index f7336f0c3..a71068582 100644 --- a/src/admin/components/AdminApp/index.css +++ b/src/admin/components/AdminApp/index.css @@ -20,10 +20,7 @@ .AdminApp-page { position: absolute; - right: 0; - top: 0; - bottom: 0; - left: 250px; + inset: 0 0 0 250px; padding: 20px; overflow-y: scroll; } diff --git a/src/admin/components/Motd/index.jsx b/src/admin/components/Motd/index.jsx index 6f51471b5..1fb87b315 100644 --- a/src/admin/components/Motd/index.jsx +++ b/src/admin/components/Motd/index.jsx @@ -10,7 +10,7 @@ import Collapse from '@mui/material/Collapse'; import { mdiPencil } from '@mdi/js'; import parse from 'u-wave-parse-chat-markup'; import SvgIcon from '../../../components/SvgIcon'; -import compile from '../../../components/Chat/Markup/compile'; +import Markup from '../../../components/Chat/Markup'; const { useCallback, @@ -28,15 +28,12 @@ function Motd({ }) { const [newMotd, setMotd] = useState(initialMotd); const [expanded, setExpanded] = useState(false); - const parsedMotd = useMemo( - () => { - if (newMotd == null) { - return null; - } - return compile(parse(newMotd), compileOptions); - }, - [newMotd, compileOptions], - ); + const parsedMotd = useMemo(() => { + if (newMotd == null) { + return null; + } + return parse(newMotd); + }, [newMotd]); const onExpand = useCallback(() => { setExpanded(!expanded); }, [expanded]); @@ -65,7 +62,9 @@ function Motd({ </IconButton> )} /> - <CardContent>{parsedMotd}</CardContent> + <CardContent> + {parsedMotd ? <Markup tree={parsedMotd} compileOptions={compileOptions} /> : null} + </CardContent> <Collapse in={expanded} unmountOnExit> <form onSubmit={onSubmit}> <CardContent style={{ paddingTop: 0 }}> diff --git a/src/admin/containers/AdminApp.jsx b/src/admin/containers/AdminApp.jsx index bf9e8f80a..0e130b229 100644 --- a/src/admin/containers/AdminApp.jsx +++ b/src/admin/containers/AdminApp.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import { useDispatch } from 'react-redux'; import { SWRConfig } from 'swr'; +import { useDispatch } from '../../hooks/useRedux'; import AdminApp from '../components/AdminApp'; import { get } from '../../actions/RequestActionCreators'; diff --git a/src/admin/containers/BansList.jsx b/src/admin/containers/BansList.jsx index 5a42577b8..62234802c 100644 --- a/src/admin/containers/BansList.jsx +++ b/src/admin/containers/BansList.jsx @@ -1,7 +1,7 @@ import React from 'react'; import useSWR from 'swr'; import { useAsyncCallback } from 'react-async-hook'; -import { useDispatch } from 'react-redux'; +import { useDispatch } from '../../hooks/useRedux'; import { unbanUser } from '../actions/bans'; import BansList from '../components/BansList'; import mergeIncludedModels from '../../utils/mergeIncludedModels'; diff --git a/src/admin/containers/Motd.js b/src/admin/containers/Motd.js index ce50e2725..3371b6d45 100644 --- a/src/admin/containers/Motd.js +++ b/src/admin/containers/Motd.js @@ -1,7 +1,7 @@ import { createStructuredSelector } from 'reselect'; import { connect } from 'react-redux'; import Motd from '../components/Motd'; -import { setMotd } from '../../actions/ChatActionCreators'; +import { setMotd } from '../../reducers/chat'; import { rawMotdSelector, markupCompilerOptionsSelector, diff --git a/src/admin/containers/ServerConfig.jsx b/src/admin/containers/ServerConfig.jsx index cc6eebe9d..5a01e9279 100644 --- a/src/admin/containers/ServerConfig.jsx +++ b/src/admin/containers/ServerConfig.jsx @@ -1,6 +1,6 @@ import React from 'react'; import useSWR from 'swr'; -import { useDispatch } from 'react-redux'; +import { useDispatch } from '../../hooks/useRedux'; import { put } from '../../actions/RequestActionCreators'; import ServerConfig from '../components/ServerConfig'; diff --git a/src/components/AddToPlaylistMenu/PlaylistsMenu.jsx b/src/components/AddToPlaylistMenu/PlaylistsMenu.jsx index 640dce821..e53363fa8 100644 --- a/src/components/AddToPlaylistMenu/PlaylistsMenu.jsx +++ b/src/components/AddToPlaylistMenu/PlaylistsMenu.jsx @@ -9,17 +9,19 @@ import MenuItem from '@mui/material/MenuItem'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import SvgIcon from '../SvgIcon'; +import { useSelector } from '../../hooks/useRedux'; +import { playlistsSelector } from '../../selectors/playlistSelectors'; const { useCallback } = React; function PlaylistsMenu({ - playlists, position, onClose, onCreatePlaylist, onSelect, }) { const { t } = useTranslator(); + const playlists = useSelector(playlistsSelector); const handleSelect = useCallback((e, playlistID) => { onClose(); onSelect(playlists.find((pl) => pl._id === playlistID)); @@ -65,7 +67,6 @@ PlaylistsMenu.propTypes = { onClose: PropTypes.func.isRequired, onSelect: PropTypes.func.isRequired, onCreatePlaylist: PropTypes.func.isRequired, - playlists: PropTypes.arrayOf(PropTypes.object), position: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number, diff --git a/src/components/AddToPlaylistMenu/index.jsx b/src/components/AddToPlaylistMenu/index.jsx index ae174a134..f00b1dd45 100644 --- a/src/components/AddToPlaylistMenu/index.jsx +++ b/src/components/AddToPlaylistMenu/index.jsx @@ -11,13 +11,12 @@ const { useState, } = React; -function AddToPlaylistMenu(props) { - const { - onClose, - onSelect, - onCreatePlaylist, - } = props; - +function AddToPlaylistMenu({ + onClose, + onSelect, + onCreatePlaylist, + position, +}) { const { t } = useTranslator(); const [creating, setCreating] = useState(false); const handleOpen = useCallback(() => setCreating(true), []); @@ -32,8 +31,10 @@ function AddToPlaylistMenu(props) { <> {!creating && ( <PlaylistsMenu - {...props} + position={position} + onClose={onClose} onCreatePlaylist={handleOpen} + onSelect={onSelect} /> )} <PromptDialog @@ -52,6 +53,10 @@ AddToPlaylistMenu.propTypes = { onClose: PropTypes.func.isRequired, onSelect: PropTypes.func.isRequired, onCreatePlaylist: PropTypes.func.isRequired, + position: PropTypes.shape({ + x: PropTypes.number, + y: PropTypes.number, + }), }; export default AddToPlaylistMenu; diff --git a/src/components/App/index.css b/src/components/App/index.css index 2ad22438e..32fde84f1 100644 --- a/src/components/App/index.css +++ b/src/components/App/index.css @@ -107,7 +107,7 @@ html:not([dir="rtl"]) .u-rtl-only { } /* Make App-level overlays fit in an AppColumn--left */ -@media (min-width: 769px) { +@media (width >= 769px) { .Overlays .Overlay { width: 75%; } diff --git a/src/components/App/index.jsx b/src/components/App/index.jsx index 52c51847f..e964e4165 100644 --- a/src/components/App/index.jsx +++ b/src/components/App/index.jsx @@ -1,4 +1,3 @@ -import React from 'react'; import PropTypes from 'prop-types'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; diff --git a/src/components/Avatar/index.jsx b/src/components/Avatar/index.jsx deleted file mode 100644 index a0e256d2e..000000000 --- a/src/components/Avatar/index.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const Avatar = ({ className, user }) => ( - <div className={cx('Avatar', className)}> - <img - className="Avatar-image" - src={user.avatar ?? `https://sigil.u-wave.net/${encodeURIComponent(user._id)}`} - alt={user.username} - /> - </div> -); - -Avatar.propTypes = { - className: PropTypes.string, - user: PropTypes.object.isRequired, -}; - -export default Avatar; diff --git a/src/components/Avatar/index.tsx b/src/components/Avatar/index.tsx new file mode 100644 index 000000000..115c26b37 --- /dev/null +++ b/src/components/Avatar/index.tsx @@ -0,0 +1,24 @@ +import cx from 'clsx'; + +type AvatarProps = { + className?: string, + user: { + _id: string, + avatar?: string, + username: string, + }, +}; + +function Avatar({ className, user }: AvatarProps) { + return ( + <div className={cx('Avatar', className)}> + <img + className="Avatar-image" + src={user.avatar ?? `https://sigil.u-wave.net/${encodeURIComponent(user._id)}`} + alt={user.username} + /> + </div> + ); +} + +export default Avatar; diff --git a/src/components/Chat/ChatMessages.css b/src/components/Chat/ChatMessages.css index 7d59d921a..013fb599a 100644 --- a/src/components/Chat/ChatMessages.css +++ b/src/components/Chat/ChatMessages.css @@ -29,7 +29,7 @@ margin: auto; margin-top: 55px; - @nest .ChatMessages-scrollDown.is-visible & { + .ChatMessages-scrollDown.is-visible & { transition: margin-top 140ms ease-out; margin-top: 0; } diff --git a/src/components/Chat/ChatMessages.jsx b/src/components/Chat/ChatMessages.tsx similarity index 63% rename from src/components/Chat/ChatMessages.jsx rename to src/components/Chat/ChatMessages.tsx index 3be634a81..f0f919ca2 100644 --- a/src/components/Chat/ChatMessages.jsx +++ b/src/components/Chat/ChatMessages.tsx @@ -1,10 +1,12 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { useListener } from 'react-bus'; +import type { MarkupNode } from 'u-wave-parse-chat-markup'; import Message from './Message'; import Motd from './Motd'; import ScrollDownNotice from './ScrollDownNotice'; import specialMessages from './specialMessages'; +import type { Message as TMessage } from '../../reducers/chat'; +import type { CompileOptions } from './Markup'; const { useCallback, @@ -13,43 +15,47 @@ const { useState, } = React; -function checkIsScrolledToBottom(el) { +function checkIsScrolledToBottom(el: HTMLElement) { const lastMessage = el.lastElementChild; - if (lastMessage) { + if (lastMessage instanceof HTMLElement) { const neededSize = el.scrollTop + el.offsetHeight + lastMessage.offsetHeight; return neededSize >= el.scrollHeight - 20; } return true; } -/** - * @param {React.RefObject<HTMLElement>} ref - * @param {boolean} [initialValue] - * @returns {[boolean, () => void]} - */ -function useScrolledToBottom(ref, initialValue = true) { +function useScrolledToBottom(ref: React.RefObject<HTMLElement>, initialValue = true) { const [isScrolledToBottom, setScrolledToBottom] = useState(initialValue); const update = useCallback(() => { - setScrolledToBottom(checkIsScrolledToBottom(ref.current)); + if (ref.current) { + setScrolledToBottom(checkIsScrolledToBottom(ref.current)); + } }, [ref]); - return [isScrolledToBottom, update]; + return [isScrolledToBottom, update] satisfies [unknown, unknown]; } -function scrollToBottom(el) { +function scrollToBottom(el: HTMLElement) { // eslint-disable-next-line no-param-reassign el.scrollTop = el.scrollHeight; } +type ChatMessagesProps = { + motd: MarkupNode[] | null, + messages: TMessage[], + canDeleteMessages?: boolean, + onDeleteMessage?: (id: string) => void, + compileOptions: CompileOptions, +}; function ChatMessages({ messages, motd, - canDeleteMessages, + canDeleteMessages = false, onDeleteMessage, compileOptions, -}) { - const container = useRef(null); +}: ChatMessagesProps) { + const container = useRef<HTMLDivElement>(null); const [isScrolledToBottom, updateScroll] = useScrolledToBottom(container, true); // Scroll to bottom on window resizes, if we were scrolled to bottom before. @@ -57,7 +63,7 @@ function ChatMessages({ if (typeof window === 'undefined') return undefined; const handleResize = () => { - if (isScrolledToBottom) { + if (isScrolledToBottom && container.current) { scrollToBottom(container.current); } }; @@ -68,7 +74,7 @@ function ChatMessages({ // Scroll to bottom again if the last message changes. const lastMessage = messages.length > 0 ? messages[messages.length - 1] : undefined; useEffect(() => { - if (isScrolledToBottom) { + if (isScrolledToBottom && container.current) { scrollToBottom(container.current); } // We need to scroll to the bottom only if a new message comes in, not when the scroll-to-bottom @@ -78,8 +84,12 @@ function ChatMessages({ // Accept externally controlled scrolling using the global event bus, so the chat input box // can tell us to scroll up or down. - const handleExternalScroll = useCallback((direction) => { - const el = container.ref; + const handleExternalScroll = useCallback((direction?: number | 'start' | 'end') => { + const el = container.current; + if (!el || direction == null) { + return; + } + if (direction === 'start') { el.scrollTop = 0; } else if (direction === 'end') { @@ -91,9 +101,10 @@ function ChatMessages({ useListener('chat:scroll', handleExternalScroll); - function renderMessage(msg) { - const SpecialMessage = specialMessages[msg.type]; - if (SpecialMessage) { + function renderMessage(msg: TMessage) { + if (msg.type !== 'chat') { + // TODO this could just use a switch + const SpecialMessage = specialMessages[msg.type] as React.FC<unknown>; return ( <SpecialMessage key={msg._id} @@ -105,10 +116,16 @@ function ChatMessages({ return ( <Message key={msg._id} + _id={msg._id} + user={msg.user} + text={msg.text} + parsedText={msg.parsedText} + inFlight={msg.inFlight} + isMention={msg.isMention} + timestamp={msg.timestamp} compileOptions={compileOptions} deletable={canDeleteMessages} onDelete={onDeleteMessage} - {...msg} /> ); } @@ -121,7 +138,7 @@ function ChatMessages({ > <ScrollDownNotice show={!isScrolledToBottom} - onClick={() => scrollToBottom(container.current)} + onClick={() => container.current && scrollToBottom(container.current)} /> {motd ? ( <Motd compileOptions={compileOptions}> @@ -133,15 +150,4 @@ function ChatMessages({ ); } -ChatMessages.propTypes = { - messages: PropTypes.array, - motd: PropTypes.array, - canDeleteMessages: PropTypes.bool, - onDeleteMessage: PropTypes.func, - compileOptions: PropTypes.shape({ - availableEmoji: PropTypes.instanceOf(Set), - emojiImages: PropTypes.object, - }), -}; - export default ChatMessages; diff --git a/src/components/Chat/DeleteButton.jsx b/src/components/Chat/DeleteButton.jsx deleted file mode 100644 index 24fcd1a0a..000000000 --- a/src/components/Chat/DeleteButton.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const DeleteButton = ({ onDelete }) => ( - <button - type="button" - className="ChatMessage-delete" - onClick={onDelete} - > - Delete - </button> -); - -DeleteButton.propTypes = { - onDelete: PropTypes.func.isRequired, -}; - -export default DeleteButton; diff --git a/src/components/Chat/Input/EmojiSuggestion.jsx b/src/components/Chat/Input/EmojiSuggestion.jsx index 9cb5addda..ebf58c6a6 100644 --- a/src/components/Chat/Input/EmojiSuggestion.jsx +++ b/src/components/Chat/Input/EmojiSuggestion.jsx @@ -1,7 +1,6 @@ import cx from 'clsx'; -import React from 'react'; import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; +import { useSelector } from '../../../hooks/useRedux'; import emojiUrl from '../../../utils/emojiUrl'; import { customEmojiNamesSelector } from '../../../selectors/configSelectors'; diff --git a/src/components/Chat/Input/Suggestion.css b/src/components/Chat/Input/Suggestion.css index d0db4a988..fec894bd3 100644 --- a/src/components/Chat/Input/Suggestion.css +++ b/src/components/Chat/Input/Suggestion.css @@ -18,6 +18,7 @@ .SuggestionItem-icon { grid-area: icon; } + .SuggestionItem-label { grid-area: label; white-space: nowrap; diff --git a/src/components/Chat/Markup/Emoji.css b/src/components/Chat/Markup.css similarity index 99% rename from src/components/Chat/Markup/Emoji.css rename to src/components/Chat/Markup.css index fafe7749a..fdab99868 100644 --- a/src/components/Chat/Markup/Emoji.css +++ b/src/components/Chat/Markup.css @@ -8,6 +8,7 @@ display: inline-block; position: relative; } + .Emoji--large { height: 2rem; } diff --git a/src/components/Chat/Markup.tsx b/src/components/Chat/Markup.tsx new file mode 100644 index 000000000..dc360cf11 --- /dev/null +++ b/src/components/Chat/Markup.tsx @@ -0,0 +1,159 @@ +import cx from 'clsx'; +import shortenUrl from 'shorten-url'; +import type { MarkupNode, MentionNode } from 'u-wave-parse-chat-markup'; +import Tooltip from '@mui/material/Tooltip'; +import emojiUrl from '../../utils/emojiUrl'; +import { User } from '../../reducers/users'; + +export type CompileOptions = { + availableEmoji?: Set<string>, + customEmojiNames?: Set<string>, + emojiImages?: Record<string, string>, +}; + +type EmoteProps = { + name: string, + image: string, + isCustom: boolean, + isLarge: boolean, +}; +function Emote({ + name, + image, + isCustom, + isLarge, +}: EmoteProps) { + return ( + <Tooltip title={`:${name}:`} placement="top"> + <span className={cx('Emoji', isLarge && 'Emoji--large', isCustom && 'Emoji--custom')} data-emoji={name}> + <img + className="Emoji-img" + src={emojiUrl(image, isCustom).href} + alt={`:${name}:`} + /> + </span> + </Tooltip> + ); +} + +type RenderMarkupProps = { + tree: MarkupNode[], + compileOptions: Required<CompileOptions>, + useLargeEmoji: boolean, +}; +function RenderMarkup({ tree, compileOptions, useLargeEmoji }: RenderMarkupProps) { + const { availableEmoji, customEmojiNames, emojiImages } = compileOptions; + + return ( + <> + {tree.map((node) => { + if (typeof node === 'string') { + return node; + } + + switch (node.type) { + case 'mention': { + const mention = node as MentionNode & { + user?: User, + group?: User[], + }; + return ( + <span className={cx('ChatMention', mention.user ? null : `ChatMention--${mention.mention}`)}> + @{mention.user?.username ?? mention.mention} + </span> + ); + } + case 'link': + return ( + <a + href={node.href} + title={node.href} + target="_blank" + rel="noopener noreferrer" + > + {shortenUrl(node.text, 60)} + </a> + ); + case 'emoji': { + const image = emojiImages[node.name]; + if (availableEmoji.has(node.name) && image != null) { + return ( + <Emote + name={node.name} + image={image} + isCustom={customEmojiNames.has(node.name)} + isLarge={useLargeEmoji} + /> + ); + } + return `:${node.name}:`; + } + case 'italic': + return ( + <em> + <RenderMarkup + tree={node.content} + compileOptions={compileOptions} + useLargeEmoji={useLargeEmoji} + /> + </em> + ); + case 'bold': + return ( + <strong> + <RenderMarkup + tree={node.content} + compileOptions={compileOptions} + useLargeEmoji={useLargeEmoji} + /> + </strong> + ); + case 'code': + return ( + <code>{node.content[0]}</code> + ); + case 'strike': + return ( + <s> + <RenderMarkup + tree={node.content} + compileOptions={compileOptions} + useLargeEmoji={useLargeEmoji} + /> + </s> + ); + default: + return null; + } + })} + </> + ); +} + +type MarkupProps = { + tree: MarkupNode[], + compileOptions: CompileOptions, +}; +function Markup({ tree, compileOptions }: MarkupProps) { + const compileOptionsWithDefaults: Required<CompileOptions> = { + availableEmoji: new Set(), + customEmojiNames: new Set(), + emojiImages: {}, + ...compileOptions, + }; + + // Display large emoji if a message only contains emoji and separating whitespace + const useLargeEmoji = tree.length < 10 && tree.every((node) => ( + (typeof node === 'string' && /^\s*$/.test(node)) || (typeof node !== 'string' && node.type === 'emoji') + )); + + return ( + <RenderMarkup + tree={tree} + compileOptions={compileOptionsWithDefaults} + useLargeEmoji={useLargeEmoji} + /> + ); +} + +export default Markup; diff --git a/src/components/Chat/Markup/Bold.jsx b/src/components/Chat/Markup/Bold.jsx deleted file mode 100644 index 6fe6bc22f..000000000 --- a/src/components/Chat/Markup/Bold.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const Bold = ({ children, ...props }) => <b {...props}>{children}</b>; - -Bold.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default Bold; diff --git a/src/components/Chat/Markup/Code.jsx b/src/components/Chat/Markup/Code.jsx deleted file mode 100644 index 0df83dfe2..000000000 --- a/src/components/Chat/Markup/Code.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const Code = ({ children, ...props }) => <code {...props}>{children}</code>; - -Code.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default Code; diff --git a/src/components/Chat/Markup/Emoji.jsx b/src/components/Chat/Markup/Emoji.jsx deleted file mode 100644 index 69677abe3..000000000 --- a/src/components/Chat/Markup/Emoji.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import Tooltip from '@mui/material/Tooltip'; -import emojiUrl from '../../../utils/emojiUrl'; - -const shortcode = (name) => `:${name}:`; - -function Emoji({ - name, - image, - isCustom, - isLarge = false, -}) { - return ( - <Tooltip title={shortcode(name)} placement="top"> - <span className={cx('Emoji', isLarge && 'Emoji--large', isCustom && 'Emoji--custom')} data-emoji={name}> - <img - className="Emoji-img" - src={emojiUrl(image, isCustom).href} - alt={shortcode(name)} - /> - </span> - </Tooltip> - ); -} - -Emoji.propTypes = { - name: PropTypes.string.isRequired, - image: PropTypes.string.isRequired, - isCustom: PropTypes.bool.isRequired, - isLarge: PropTypes.bool, -}; - -export default Emoji; diff --git a/src/components/Chat/Markup/GroupMention.jsx b/src/components/Chat/Markup/GroupMention.jsx deleted file mode 100644 index c4261cab8..000000000 --- a/src/components/Chat/Markup/GroupMention.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const GroupMention = ({ className, group }) => ( - <span className={cx('ChatMention', `ChatMention--${group}`, className)}> - @{group} - </span> -); - -GroupMention.propTypes = { - className: PropTypes.string, - group: PropTypes.string.isRequired, -}; - -export default GroupMention; diff --git a/src/components/Chat/Markup/Italic.jsx b/src/components/Chat/Markup/Italic.jsx deleted file mode 100644 index 518f90ab4..000000000 --- a/src/components/Chat/Markup/Italic.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const Italic = ({ children, ...props }) => <i {...props}>{children}</i>; - -Italic.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default Italic; diff --git a/src/components/Chat/Markup/Link.jsx b/src/components/Chat/Markup/Link.jsx deleted file mode 100644 index e8f172c8e..000000000 --- a/src/components/Chat/Markup/Link.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import shortenUrl from 'shorten-url'; - -const Link = ({ children, href, ...props }) => ( - <a - href={href} - title={href} - target="_blank" - rel="noopener noreferrer" - {...props} - > - {shortenUrl(children, 60)} - </a> -); - -Link.propTypes = { - children: PropTypes.string.isRequired, - href: PropTypes.string.isRequired, -}; - -export default Link; diff --git a/src/components/Chat/Markup/Mention.jsx b/src/components/Chat/Markup/Mention.jsx deleted file mode 100644 index 9cd6f6d1b..000000000 --- a/src/components/Chat/Markup/Mention.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const Mention = ({ className = undefined, user, ...props }) => ( - <span className={cx('ChatMention', className)} {...props}> - @{user.username} - </span> -); - -Mention.propTypes = { - className: PropTypes.string, - user: PropTypes.shape({ - username: PropTypes.string.isRequired, - }).isRequired, -}; - -export default Mention; diff --git a/src/components/Chat/Markup/StrikeThrough.jsx b/src/components/Chat/Markup/StrikeThrough.jsx deleted file mode 100644 index 466a6aba7..000000000 --- a/src/components/Chat/Markup/StrikeThrough.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const StrikeThrough = ({ children, ...props }) => <s {...props}>{children}</s>; - -StrikeThrough.propTypes = { - children: PropTypes.node.isRequired, -}; - -export default StrikeThrough; diff --git a/src/components/Chat/Markup/compile.jsx b/src/components/Chat/Markup/compile.jsx deleted file mode 100644 index e6fd2b7d3..000000000 --- a/src/components/Chat/Markup/compile.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import Bold from './Bold'; -import Code from './Code'; -import Italic from './Italic'; -import StrikeThrough from './StrikeThrough'; -import Mention from './Mention'; -import GroupMention from './GroupMention'; -import Link from './Link'; -import Emoji from './Emoji'; - -export default function compile(tree, opts = {}) { - const { - availableEmoji = new Set(), - customEmojiNames = new Set(), - emojiImages = {}, - } = opts; - - // Display large emoji if a message only contains emoji and separating whitespace - const useLargeEmoji = tree.length < 10 && tree.every((node) => ( - (typeof node === 'string' && /^\s*$/.test(node)) || node.type === 'emoji' - )); - - return tree.map((node, i) => { - if (typeof node === 'string') { - return node; - } - - /* eslint-disable react/no-array-index-key */ - switch (node.type) { - case 'mention': - return node.user - ? <Mention key={i} user={node.user} /> - : <GroupMention key={i} group={node.mention} users={node.group} />; - case 'link': - return <Link key={i} href={node.href}>{node.text}</Link>; - case 'emoji': - if (availableEmoji.has(node.name) && node.name in emojiImages) { - return ( - <Emoji - key={i} - name={node.name} - image={emojiImages[node.name]} - isCustom={customEmojiNames.has(node.name)} - isLarge={useLargeEmoji} - /> - ); - } - return `:${node.name}:`; - case 'italic': - return <Italic key={i}>{compile(node.content, opts)}</Italic>; - case 'bold': - return <Bold key={i}>{compile(node.content, opts)}</Bold>; - case 'code': - return <Code key={i}>{compile(node.content, opts)}</Code>; - case 'strike': - return <StrikeThrough key={i}>{compile(node.content, opts)}</StrikeThrough>; - default: - return compile(node.content, opts); - } - /* eslint-enable react/no-array-index-key */ - }); -} diff --git a/src/components/Chat/Markup/index.css b/src/components/Chat/Markup/index.css deleted file mode 100644 index d519ea6ff..000000000 --- a/src/components/Chat/Markup/index.css +++ /dev/null @@ -1 +0,0 @@ -@import url("./Emoji.css"); diff --git a/src/components/Chat/Message.jsx b/src/components/Chat/Message.jsx deleted file mode 100644 index 535c5e8fe..000000000 --- a/src/components/Chat/Message.jsx +++ /dev/null @@ -1,99 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import CircularProgress from '@mui/material/CircularProgress'; -import useUserCard from '../../hooks/useUserCard'; -import Avatar from '../Avatar'; -import Username from '../Username'; -import compile from './Markup/compile'; -import DeleteButton from './DeleteButton'; -import MessageTimestamp from './MessageTimestamp'; - -const { - useCallback, -} = React; - -function Message({ - _id: id, - user, - text, - parsedText, - inFlight, - isMention, - timestamp, - compileOptions, - deletable, - onDelete, -}) { - const userCard = useUserCard(user); - const onUsernameClick = useCallback((event) => { - event.preventDefault(); - userCard.open(); - // The `userCard.open` reference never changes. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - let avatar; - if (inFlight) { - avatar = ( - <div className="ChatMessage-avatar"> - <CircularProgress size="100%" /> - </div> - ); - } else { - avatar = ( - <Avatar - className="ChatMessage-avatar" - user={user} - /> - ); - } - - const children = parsedText ? compile(parsedText, compileOptions) : text; - - const date = new Date(timestamp); - - const className = cx( - 'ChatMessage', - inFlight && 'ChatMessage--loading', - isMention && 'ChatMessage--mention', - ); - return ( - <div className={className} ref={userCard.refAnchor}> - {userCard.card} - {avatar} - <div className="ChatMessage-content"> - <div className="ChatMessage-hover"> - {deletable && <DeleteButton onDelete={() => onDelete(id)} />} - <MessageTimestamp date={date} /> - </div> - <button - type="button" - className="ChatMessage-username ChatMessage-cardable" - onClick={onUsernameClick} - > - <Username user={user} /> - </button> - <span className="ChatMessage-text">{children}</span> - </div> - </div> - ); -} - -Message.propTypes = { - _id: PropTypes.string.isRequired, - user: PropTypes.object.isRequired, - text: PropTypes.string.isRequired, - parsedText: PropTypes.array.isRequired, - inFlight: PropTypes.bool, - timestamp: PropTypes.number.isRequired, - isMention: PropTypes.bool.isRequired, - deletable: PropTypes.bool.isRequired, - onDelete: PropTypes.func.isRequired, - compileOptions: PropTypes.shape({ - availableEmoji: PropTypes.instanceOf(Set), - emojiImages: PropTypes.object, - }), -}; - -export default Message; diff --git a/src/components/Chat/Message.tsx b/src/components/Chat/Message.tsx new file mode 100644 index 000000000..18533f3a1 --- /dev/null +++ b/src/components/Chat/Message.tsx @@ -0,0 +1,124 @@ +import cx from 'clsx'; +import { memo, useCallback, useMemo } from 'react'; +import CircularProgress from '@mui/material/CircularProgress'; +import type { MarkupNode } from 'u-wave-parse-chat-markup'; +import type { User } from '../../reducers/users'; +import useUserCard from '../../hooks/useUserCard'; +import useIntl from '../../hooks/useIntl'; +import Avatar from '../Avatar'; +import Username from '../Username'; +import Markup, { CompileOptions } from './Markup'; + +type DeleteButtonProps = { + onDelete: () => void, +}; +function DeleteButton({ onDelete }: DeleteButtonProps) { + return ( + <button + type="button" + className="ChatMessage-delete" + onClick={onDelete} + > + Delete + </button> + ); +} + +type MessageTimestampProps = { + date: Date, +}; +function MessageTimestampImpl({ date }: MessageTimestampProps) { + const { timeFormatter } = useIntl(); + + return ( + <time + className="ChatMessage-timestamp" + dateTime={date.toISOString()} + > + {timeFormatter.format(date)} + </time> + ); +} +const MessageTimestamp = memo(MessageTimestampImpl); + +type ChatMessageProps = { + _id: string, + user: User, + text: string, + parsedText?: MarkupNode[], + inFlight?: boolean, + isMention?: boolean, + timestamp: number, + compileOptions: CompileOptions, + deletable?: boolean, + onDelete?: (id: string) => void, +}; + +function ChatMessage({ + _id: id, + user, + text, + parsedText, + inFlight = false, + isMention = false, + timestamp, + compileOptions, + deletable, + onDelete, +}: ChatMessageProps) { + const userCard = useUserCard(user); + const onUsernameClick = useCallback((event: React.MouseEvent) => { + event.preventDefault(); + userCard.open(); + // The `userCard.open` reference never changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + let avatar: React.ReactNode; + if (inFlight) { + avatar = ( + <div className="ChatMessage-avatar"> + <CircularProgress size="100%" /> + </div> + ); + } else { + avatar = ( + <Avatar + className="ChatMessage-avatar" + user={user} + /> + ); + } + + const children = parsedText ? <Markup tree={parsedText} compileOptions={compileOptions} /> : text; + + const date = useMemo(() => new Date(timestamp), [timestamp]); + + const className = cx({ + ChatMessage: true, + 'ChatMessage--loading': inFlight, + 'ChatMessage--mention': isMention, + }); + return ( + <div className={className} ref={userCard.refAnchor}> + {userCard.card} + {avatar} + <div className="ChatMessage-content"> + <div className="ChatMessage-hover"> + {deletable && <DeleteButton onDelete={() => onDelete?.(id)} />} + <MessageTimestamp date={date} /> + </div> + <button + type="button" + className="ChatMessage-username ChatMessage-cardable" + onClick={onUsernameClick} + > + <Username user={user} /> + </button> + <span className="ChatMessage-text">{children}</span> + </div> + </div> + ); +} + +export default ChatMessage; diff --git a/src/components/Chat/Motd.jsx b/src/components/Chat/Motd.jsx deleted file mode 100644 index 216378d45..000000000 --- a/src/components/Chat/Motd.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import compile from './Markup/compile'; - -const Motd = ({ children, compileOptions }) => ( - <div className="ChatMessage ChatMessage--motd"> - <div className="ChatMessage-content"> - {compile(children, compileOptions)} - </div> - </div> -); - -Motd.propTypes = { - children: PropTypes.array.isRequired, - compileOptions: PropTypes.shape({ - availableEmoji: PropTypes.instanceOf(Set), - emojiImages: PropTypes.object, - }), -}; - -export default React.memo(Motd); diff --git a/src/components/Chat/Motd.tsx b/src/components/Chat/Motd.tsx new file mode 100644 index 000000000..5f4a0c180 --- /dev/null +++ b/src/components/Chat/Motd.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import type { MarkupNode } from 'u-wave-parse-chat-markup'; +import Markup, { type CompileOptions } from './Markup'; + +type MotdProps = { + children: MarkupNode[], + compileOptions: CompileOptions, +}; +function Motd({ children, compileOptions }: MotdProps) { + return ( + <div className="ChatMessage ChatMessage--motd"> + <div className="ChatMessage-content"> + <Markup tree={children} compileOptions={compileOptions} /> + </div> + </div> + ); +} + +export default React.memo(Motd); diff --git a/src/components/Chat/NotificationMessages/NowPlayingMessage.css b/src/components/Chat/NotificationMessages/NowPlayingMessage.css index 5dd4c015b..015845583 100644 --- a/src/components/Chat/NotificationMessages/NowPlayingMessage.css +++ b/src/components/Chat/NotificationMessages/NowPlayingMessage.css @@ -13,7 +13,7 @@ height: 100%; display: none; - @nest .NowPlayingMessage:hover & { + .NowPlayingMessage:hover & { display: block; } } diff --git a/src/components/Chat/ScrollDownNotice.jsx b/src/components/Chat/ScrollDownNotice.tsx similarity index 74% rename from src/components/Chat/ScrollDownNotice.jsx rename to src/components/Chat/ScrollDownNotice.tsx index f357066b1..70f7ad253 100644 --- a/src/components/Chat/ScrollDownNotice.jsx +++ b/src/components/Chat/ScrollDownNotice.tsx @@ -1,12 +1,14 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import { mdiArrowDown } from '@mdi/js'; import Fab from '@mui/material/Fab'; import SvgIcon from '../SvgIcon'; -function ScrollDownNotice({ show, onClick }) { +type ScrollDownNoticeProps = { + show: boolean, + onClick: () => void, +}; +function ScrollDownNotice({ show, onClick }: ScrollDownNoticeProps) { const { t } = useTranslator(); return ( @@ -25,9 +27,4 @@ function ScrollDownNotice({ show, onClick }) { ); } -ScrollDownNotice.propTypes = { - show: PropTypes.bool.isRequired, - onClick: PropTypes.func.isRequired, -}; - export default ScrollDownNotice; diff --git a/src/components/Chat/index.css b/src/components/Chat/index.css index da33fe42c..48e3e827a 100644 --- a/src/components/Chat/index.css +++ b/src/components/Chat/index.css @@ -1,6 +1,6 @@ @import url("./ChatMessages.css"); @import url("./Input/index.css"); -@import url("./Markup/index.css"); +@import url("./Markup.css"); @import url("./NotificationMessages/index.css"); @import url("./LogMessage.css"); @import url("./Message.css"); diff --git a/src/components/Chat/index.jsx b/src/components/Chat/index.jsx deleted file mode 100644 index 9a963da90..000000000 --- a/src/components/Chat/index.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import ChatMessages from '../../containers/ChatMessages'; -import ChatInput from '../../containers/ChatInput'; - -const Chat = () => ( - <div className="ChatContainer"> - <div className="ChatContainer-messages"> - <ChatMessages /> - </div> - <div className="ChatContainer-input ChatInputWrapper"> - <ChatInput /> - </div> - </div> -); - -export default Chat; diff --git a/src/components/Chat/index.tsx b/src/components/Chat/index.tsx new file mode 100644 index 000000000..9fa133e21 --- /dev/null +++ b/src/components/Chat/index.tsx @@ -0,0 +1,17 @@ +import ChatMessages from '../../containers/ChatMessages'; +import ChatInput from '../../containers/ChatInput'; + +function Chat() { + return ( + <div className="ChatContainer"> + <div className="ChatContainer-messages"> + <ChatMessages /> + </div> + <div className="ChatContainer-input ChatInputWrapper"> + <ChatInput /> + </div> + </div> + ); +} + +export default Chat; diff --git a/src/components/ConnectionIndicator/OfflineIcon.jsx b/src/components/ConnectionIndicator/OfflineIcon.jsx deleted file mode 100644 index c3134517b..000000000 --- a/src/components/ConnectionIndicator/OfflineIcon.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import CircularProgress from '@mui/material/CircularProgress'; - -const OfflineIcon = ({ style }) => ( - <div - style={{ - ...style, - width: 32, - height: 32, - display: 'inline-block', - }} - > - <CircularProgress size={32} /> - </div> -); - -OfflineIcon.propTypes = { - style: PropTypes.object, -}; - -export default OfflineIcon; diff --git a/src/components/ConnectionIndicator/index.jsx b/src/components/ConnectionIndicator/index.tsx similarity index 51% rename from src/components/ConnectionIndicator/index.jsx rename to src/components/ConnectionIndicator/index.tsx index 3f0ccd955..d6915980a 100644 --- a/src/components/ConnectionIndicator/index.jsx +++ b/src/components/ConnectionIndicator/index.tsx @@ -1,11 +1,30 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import Card from '@mui/material/Card/Card'; import CardHeader from '@mui/material/CardHeader'; -import OfflineIcon from './OfflineIcon'; +import CircularProgress from '@mui/material/CircularProgress'; -function ConnectionIndicator({ isConnected }) { +type OfflineIconProps = { + style?: React.CSSProperties, +}; +function OfflineIcon({ style }: OfflineIconProps) { + return ( + <div + style={{ + ...style, + width: 32, + height: 32, + display: 'inline-block', + }} + > + <CircularProgress size={32} /> + </div> + ); +} + +type ConnectionIndicatorProps = { + isConnected: boolean, +}; +function ConnectionIndicator({ isConnected }: ConnectionIndicatorProps) { const { t } = useTranslator(); if (isConnected) { @@ -25,8 +44,4 @@ function ConnectionIndicator({ isConnected }) { ); } -ConnectionIndicator.propTypes = { - isConnected: PropTypes.bool.isRequired, -}; - export default ConnectionIndicator; diff --git a/src/components/Dialogs/LoginDialog/SocialLogin.jsx b/src/components/Dialogs/LoginDialog/SocialLogin.jsx index 98363f075..6b72593c2 100644 --- a/src/components/Dialogs/LoginDialog/SocialLogin.jsx +++ b/src/components/Dialogs/LoginDialog/SocialLogin.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; +import { useDispatch } from '../../../hooks/useRedux'; import { loginWithGoogle } from '../../../actions/LoginActionCreators'; const GoogleButton = React.lazy(() => ( diff --git a/src/components/Dialogs/PromptDialog/__tests__/index.jsx b/src/components/Dialogs/PromptDialog/__tests__/index.jsx index 530690df8..ac03fa5b8 100644 --- a/src/components/Dialogs/PromptDialog/__tests__/index.jsx +++ b/src/components/Dialogs/PromptDialog/__tests__/index.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { vi } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import createCache from '@emotion/cache'; @@ -9,10 +9,10 @@ const cache = createCache({ key: 'emc' }); describe('<PromptDialog />', () => { it('should not show if there is no error', async () => { - const onSubmit = jest.fn((value) => { - expect(value).toEqual('test'); + const onSubmit = vi.fn((value) => { + expect(value).toBe('test'); }); - const onCancel = jest.fn(); + const onCancel = vi.fn(); render(( <CacheProvider value={cache}> diff --git a/src/components/ErrorArea/__tests__/index.jsx b/src/components/ErrorArea/__tests__/index.jsx index b61ba8b66..227ee5d4e 100644 --- a/src/components/ErrorArea/__tests__/index.jsx +++ b/src/components/ErrorArea/__tests__/index.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { vi } from 'vitest'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import ErrorArea from '..'; @@ -25,7 +25,7 @@ describe('<ErrorArea />', () => { }); it('closes when user clicks anywhere on the page', async () => { - const spy = jest.fn(); + const spy = vi.fn(); render(( <main> @@ -40,7 +40,7 @@ describe('<ErrorArea />', () => { const snackbar = screen.getByRole('alert'); expect(snackbar).toBeInTheDocument(); - userEvent.click(screen.getByTestId('anywhere-else')); + await userEvent.click(screen.getByTestId('anywhere-else')); await waitFor(() => spy.mock.calls.length > 0); }); diff --git a/src/components/FatalError/index.css b/src/components/FatalError/index.css index 57931913a..a65e2846d 100644 --- a/src/components/FatalError/index.css +++ b/src/components/FatalError/index.css @@ -1,9 +1,6 @@ .FatalError { position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; + inset: 0; display: flex; align-items: center; justify-content: center; diff --git a/src/components/FooterBar/GuestFooterContent.jsx b/src/components/FooterBar/GuestFooterContent.jsx index 3321a2cf5..a58459b5a 100644 --- a/src/components/FooterBar/GuestFooterContent.jsx +++ b/src/components/FooterBar/GuestFooterContent.jsx @@ -1,9 +1,9 @@ import React from 'react'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import Button from '@mui/material/Button'; +import { useDispatch } from '../../hooks/useRedux'; import { openLoginDialog, openRegisterDialog } from '../../actions/DialogActionCreators'; -import { toggleSettings } from '../../actions/OverlayActionCreators'; +import { toggleOverlay } from '../../reducers/activeOverlay'; import SettingsButton from './SettingsButton'; const { @@ -14,7 +14,7 @@ function GuestFooterContent() { const { t } = useTranslator(); const dispatch = useDispatch(); const handleToggleSettings = useCallback(() => { - dispatch(toggleSettings()); + dispatch(toggleOverlay('settings')); }, [dispatch]); const handleOpenLoginDialog = useCallback(() => { dispatch(openLoginDialog()); diff --git a/src/components/FooterBar/UserFooterContent.jsx b/src/components/FooterBar/UserFooterContent.jsx index 3ecbb5d50..3f74a9c3a 100644 --- a/src/components/FooterBar/UserFooterContent.jsx +++ b/src/components/FooterBar/UserFooterContent.jsx @@ -1,17 +1,19 @@ import cx from 'clsx'; import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch, useSelector } from '../../hooks/useRedux'; import useCurrentUser from '../../hooks/useCurrentUser'; import { skipSelf } from '../../actions/BoothActionCreators'; import { skipCurrentDJ as modSkipCurrentDJ } from '../../actions/ModerationActionCreators'; -import { togglePlaylistManager, toggleSettings } from '../../actions/OverlayActionCreators'; +import { toggleOverlay } from '../../reducers/activeOverlay'; import { joinWaitlist, leaveWaitlist } from '../../actions/WaitlistActionCreators'; -import { openFavoriteMenu, doUpvote, doDownvote } from '../../actions/VoteActionCreators'; +import { doUpvote, doDownvote } from '../../actions/VoteActionCreators'; +import { openFavoriteMenu } from '../../reducers/addToPlaylistMenu'; import { djSelector, isCurrentDJSelector, canSkipSelector, endTimeSelector, + historyIDSelector, } from '../../selectors/boothSelectors'; import { activePlaylistSelector, @@ -42,19 +44,20 @@ function UserFooterContent() { const userInWaitlist = useSelector(userInWaitlistSelector); const userIsDJ = useSelector(isCurrentDJSelector); const currentDJ = useSelector(djSelector); + const historyID = useSelector(historyIDSelector); const showSkip = useSelector(canSkipSelector); const waitlistIsLocked = useSelector(isLockedSelector); const voteStats = useSelector(currentVoteStatsSelector); const dispatch = useDispatch(); const handleTogglePlaylistManager = useCallback(() => { - dispatch(togglePlaylistManager()); + dispatch(toggleOverlay('playlistManager')); }, [dispatch]); const handleToggleSettings = useCallback(() => { - dispatch(toggleSettings()); + dispatch(toggleOverlay('settings')); }, [dispatch]); const handleFavorite = useCallback((position) => { - dispatch(openFavoriteMenu(position)); - }, [dispatch]); + dispatch(openFavoriteMenu(historyID, position)); + }, [historyID, dispatch]); const handleUpvote = useCallback(() => { dispatch(doUpvote()); }, [dispatch]); diff --git a/src/components/Form/Button.jsx b/src/components/Form/Button.tsx similarity index 50% rename from src/components/Form/Button.jsx rename to src/components/Form/Button.tsx index 9736f62f9..d0ac12f7d 100644 --- a/src/components/Form/Button.jsx +++ b/src/components/Form/Button.tsx @@ -1,9 +1,7 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import MuiButton from '@mui/material/Button'; +import MuiButton, { ButtonProps } from '@mui/material/Button'; -function Button({ children, className, ...props }) { +function Button({ children, className, ...props }: ButtonProps) { return ( <MuiButton variant="contained" @@ -17,9 +15,4 @@ function Button({ children, className, ...props }) { ); } -Button.propTypes = { - className: PropTypes.string, - children: PropTypes.node, -}; - export default Button; diff --git a/src/components/Form/Group.jsx b/src/components/Form/Group.jsx deleted file mode 100644 index cda159963..000000000 --- a/src/components/Form/Group.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const FormGroup = ({ children, className, ...props }) => ( - <div - className={cx('FormGroup', className)} - {...props} - > - {children} - </div> -); - -FormGroup.propTypes = { - className: PropTypes.string, - children: PropTypes.node.isRequired, -}; - -export default FormGroup; diff --git a/src/components/Form/Group.tsx b/src/components/Form/Group.tsx new file mode 100644 index 000000000..9deac2f00 --- /dev/null +++ b/src/components/Form/Group.tsx @@ -0,0 +1,15 @@ +import cx from 'clsx'; + +type FormGroupProps = { + className?: string, + children: React.ReactNode, +}; +function FormGroup({ children, className }: FormGroupProps) { + return ( + <div className={cx('FormGroup', className)}> + {children} + </div> + ); +} + +export default FormGroup; diff --git a/src/components/Form/TextField.jsx b/src/components/Form/TextField.tsx similarity index 71% rename from src/components/Form/TextField.jsx rename to src/components/Form/TextField.tsx index 69b70be28..42ea013e0 100644 --- a/src/components/Form/TextField.jsx +++ b/src/components/Form/TextField.tsx @@ -1,6 +1,5 @@ import cx from 'clsx'; import React from 'react'; -import PropTypes from 'prop-types'; const { useEffect, @@ -8,16 +7,22 @@ const { useRef, } = React; +interface TextFieldProps extends React.ComponentProps<'input'> { + className?: string, + type?: string, + icon?: React.ReactNode, + autoFocus?: boolean, +} const TextField = React.forwardRef(({ className, type = 'text', icon, autoFocus, ...props -}, ref) => { - const refInput = useRef(null); +}: TextFieldProps, ref) => { + const refInput = useRef<HTMLInputElement>(null); useImperativeHandle(ref, () => ({ - get value() { return refInput.current.value; }, + get value() { return refInput.current?.value; }, })); useEffect(() => { if (autoFocus) { @@ -40,11 +45,4 @@ const TextField = React.forwardRef(({ ); }); -TextField.propTypes = { - className: PropTypes.string, - type: PropTypes.string, - icon: PropTypes.node, - autoFocus: PropTypes.bool, -}; - export default TextField; diff --git a/src/components/Form/index.jsx b/src/components/Form/index.jsx deleted file mode 100644 index 4fa4c66a3..000000000 --- a/src/components/Form/index.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const Form = ({ children, className, ...props }) => ( - <form className={cx('Form', className)} {...props}> - {children} - </form> -); - -Form.propTypes = { - className: PropTypes.string, - children: PropTypes.node.isRequired, -}; - -export default Form; diff --git a/src/components/Form/index.tsx b/src/components/Form/index.tsx new file mode 100644 index 000000000..5f49c6659 --- /dev/null +++ b/src/components/Form/index.tsx @@ -0,0 +1,11 @@ +import cx from 'clsx'; + +function Form({ children, className, ...props }: React.ComponentProps<'form'>) { + return ( + <form className={cx('Form', className)} {...props}> + {children} + </form> + ); +} + +export default Form; diff --git a/src/components/HeaderBar/AppTitle.jsx b/src/components/HeaderBar/AppTitle.jsx deleted file mode 100644 index 32e53d27c..000000000 --- a/src/components/HeaderBar/AppTitle.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import IconButton from '@mui/material/IconButton'; -import { mdiMenuDown } from '@mdi/js'; -import SvgIcon from '../SvgIcon'; -import logo from '../../../assets/img/logo-white.png'; - -const AppTitle = ({ - className, - children, - onClick, -}) => ( - <div className={cx('AppTitle', className)}> - <h1 className="AppTitle-logo"> - <img - className="AppTitle-logoImage" - alt={children} - src={logo} - /> - </h1> - <IconButton className="AppTitle-button" onClick={onClick}> - <SvgIcon path={mdiMenuDown} /> - </IconButton> - </div> -); - -AppTitle.propTypes = { - className: PropTypes.string, - children: PropTypes.string.isRequired, - onClick: PropTypes.func.isRequired, -}; - -export default AppTitle; diff --git a/src/components/HeaderBar/AppTitle.tsx b/src/components/HeaderBar/AppTitle.tsx new file mode 100644 index 000000000..53deebfc8 --- /dev/null +++ b/src/components/HeaderBar/AppTitle.tsx @@ -0,0 +1,34 @@ +import cx from 'clsx'; +import IconButton from '@mui/material/IconButton'; +import { mdiMenuDown } from '@mdi/js'; +import SvgIcon from '../SvgIcon'; +import logo from '../../../assets/img/logo-white.png'; + +type AppTitleTypes = { + className?: string, + children: string, + onClick?: () => void, +}; + +function AppTitle({ + className, + children, + onClick, +}: AppTitleTypes) { + return ( + <div className={cx('AppTitle', className)}> + <h1 className="AppTitle-logo"> + <img + className="AppTitle-logoImage" + alt={children} + src={logo} + /> + </h1> + <IconButton className="AppTitle-button" onClick={onClick}> + <SvgIcon path={mdiMenuDown} /> + </IconButton> + </div> + ); +} + +export default AppTitle; diff --git a/src/components/HeaderBar/Progress.jsx b/src/components/HeaderBar/Progress.jsx index d663a29f4..7868b69f4 100644 --- a/src/components/HeaderBar/Progress.jsx +++ b/src/components/HeaderBar/Progress.jsx @@ -1,7 +1,7 @@ import cx from 'clsx'; import React from 'react'; import PropTypes from 'prop-types'; -import { useStore } from 'react-redux'; +import { useStore } from '../../hooks/useRedux'; import { currentTimeSelector } from '../../selectors/timeSelectors'; const { useEffect, useRef } = React; diff --git a/src/components/LazyOverlay/ErrorBoundary.jsx b/src/components/LazyOverlay/ErrorBoundary.jsx index 6432b3a6a..8f91c4c53 100644 --- a/src/components/LazyOverlay/ErrorBoundary.jsx +++ b/src/components/LazyOverlay/ErrorBoundary.jsx @@ -1,16 +1,16 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import Typography from '@mui/material/Typography'; +import { useDispatch } from '../../hooks/useRedux'; import OverlayContent from '../Overlay/Content'; import OverlayHeader from '../Overlay/Header'; -import { closeAll } from '../../actions/OverlayActionCreators'; +import { closeOverlay } from '../../reducers/activeOverlay'; function ErrorOverlay({ error }) { const dispatch = useDispatch(); - const onCloseOverlay = () => dispatch(closeAll()); + const onCloseOverlay = () => dispatch(closeOverlay()); return ( <> diff --git a/src/components/LazyOverlay/index.jsx b/src/components/LazyOverlay/index.tsx similarity index 67% rename from src/components/LazyOverlay/index.jsx rename to src/components/LazyOverlay/index.tsx index f61e163a6..5b0aaf6d3 100644 --- a/src/components/LazyOverlay/index.jsx +++ b/src/components/LazyOverlay/index.tsx @@ -1,11 +1,11 @@ import React from 'react'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import CircularProgress from '@mui/material/CircularProgress'; +import { useDispatch } from '../../hooks/useRedux'; import Overlay from '../Overlay'; import OverlayContent from '../Overlay/Content'; import OverlayHeader from '../Overlay/Header'; -import { closeAll } from '../../actions/OverlayActionCreators'; +import { closeOverlay } from '../../reducers/activeOverlay'; import ErrorBoundary from './ErrorBoundary'; const { @@ -13,17 +13,19 @@ const { useState, } = React; -export default function createLazyOverlay({ - loader, +function createLazyOverlay<TComponent extends React.ElementType>({ title, OverlayComponent = Overlay, + Component, +}: { + title: (t: (key: string) => string) => string, + OverlayComponent: React.ComponentType<{ children: React.ReactElement }>, + Component: TComponent, }) { - if (typeof loader !== 'function') throw new TypeError('loader must be a function'); - function LoadingOverlay() { const { t } = useTranslator(); const dispatch = useDispatch(); - const onCloseOverlay = () => dispatch(closeAll()); + const onCloseOverlay = () => dispatch(closeOverlay()); // Simulate `pastDelay` from react-loadable const [pastDelay, setPastDelay] = useState(false); @@ -50,14 +52,12 @@ export default function createLazyOverlay({ ); } - const RealOverlay = React.lazy(loader); - - function LazyOverlay(props) { + function LazyOverlay(props: React.ComponentProps<TComponent>) { return ( - <OverlayComponent {...props}> + <OverlayComponent> <ErrorBoundary> - <React.Suspense fallback={<LoadingOverlay {...props} />}> - <RealOverlay {...props} /> + <React.Suspense fallback={<LoadingOverlay />}> + <Component {...props} /> </React.Suspense> </ErrorBoundary> </OverlayComponent> @@ -66,3 +66,5 @@ export default function createLazyOverlay({ return LazyOverlay; } + +export default createLazyOverlay; diff --git a/src/components/LoadingScreen/DesktopSkeleton.jsx b/src/components/LoadingScreen/DesktopSkeleton.tsx similarity index 94% rename from src/components/LoadingScreen/DesktopSkeleton.jsx rename to src/components/LoadingScreen/DesktopSkeleton.tsx index 774bc5614..18531b2f9 100644 --- a/src/components/LoadingScreen/DesktopSkeleton.jsx +++ b/src/components/LoadingScreen/DesktopSkeleton.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import Slider from '@mui/material/Slider'; import Tab from '@mui/material/Tab'; import Tabs from '@mui/material/Tabs'; @@ -10,12 +9,10 @@ import SongTitle from '../SongTitle'; import LoadingIndicator from './LoadingIndicator'; import Filler from './Filler'; -function noop() {} - function FakeVolume() { return ( <div className="VolumeSlider"> - <IconButton onClick={noop}> + <IconButton> <SvgIcon path={mdiVolumeOff} /> </IconButton> <div className="VolumeSlider-slider"> @@ -25,7 +22,6 @@ function FakeVolume() { max={100} step={1} value={0} - onChange={noop} /> </div> </div> @@ -42,7 +38,7 @@ const fakeSongTitle = ( function FakeHeaderBar() { return ( <div className="HeaderBar App-header"> - <AppTitle className="HeaderBar-title" onClick={() => {}}>...</AppTitle> + <AppTitle className="HeaderBar-title">...</AppTitle> <div className="HeaderBar-nowPlaying"> <div className="HeaderBar-media"> {fakeSongTitle} diff --git a/src/components/LoadingScreen/Filler.jsx b/src/components/LoadingScreen/Filler.jsx deleted file mode 100644 index bf707c99d..000000000 --- a/src/components/LoadingScreen/Filler.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -function Filler({ width }) { - const style = { width }; - - return <span className="Filler" style={style} />; -} -Filler.propTypes = { - width: PropTypes.number.isRequired, -}; - -export default Filler; diff --git a/src/components/LoadingScreen/Filler.tsx b/src/components/LoadingScreen/Filler.tsx new file mode 100644 index 000000000..c29b63c27 --- /dev/null +++ b/src/components/LoadingScreen/Filler.tsx @@ -0,0 +1,11 @@ +export type FillerProps = { + width: number, +} + +function Filler({ width }: FillerProps) { + const style = { width }; + + return <span className="Filler" style={style} />; +} + +export default Filler; diff --git a/src/components/LoadingScreen/LoadingIndicator.jsx b/src/components/LoadingScreen/LoadingIndicator.tsx similarity index 95% rename from src/components/LoadingScreen/LoadingIndicator.jsx rename to src/components/LoadingScreen/LoadingIndicator.tsx index 568836cfe..a17c1b64e 100644 --- a/src/components/LoadingScreen/LoadingIndicator.jsx +++ b/src/components/LoadingScreen/LoadingIndicator.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import CircularProgress from '@mui/material/CircularProgress'; import { mdiAlert } from '@mdi/js'; import SvgIcon from '../SvgIcon'; diff --git a/src/components/LoadingScreen/MobileSkeleton.jsx b/src/components/LoadingScreen/MobileSkeleton.tsx similarity index 96% rename from src/components/LoadingScreen/MobileSkeleton.jsx rename to src/components/LoadingScreen/MobileSkeleton.tsx index 03d188126..ce7bb7503 100644 --- a/src/components/LoadingScreen/MobileSkeleton.jsx +++ b/src/components/LoadingScreen/MobileSkeleton.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; @@ -28,7 +27,7 @@ function MobileSkeleton() { <IconButton> <SvgIcon path={mdiHistory} /> </IconButton> - <IconButton style={waitlistIconStyle}> + <IconButton sx={waitlistIconStyle}> <Filler width={20} /> </IconButton> </Toolbar> diff --git a/src/components/LoadingScreen/index.css b/src/components/LoadingScreen/index.css index 1e37f62a1..79ac2dc67 100644 --- a/src/components/LoadingScreen/index.css +++ b/src/components/LoadingScreen/index.css @@ -11,10 +11,7 @@ position: relative; width: 100%; height: 100%; - left: 0; - right: 0; - top: 0; - bottom: 0; + inset: 0; display: flex; flex-direction: column; justify-content: center; @@ -38,7 +35,8 @@ .desktop-only { display: none; } .mobile-only { display: block; } -@media (min-width: 769px) { + +@media (width >= 769px) { .desktop-only { display: block; } .mobile-only { display: none; } } diff --git a/src/components/LoadingScreen/index.jsx b/src/components/LoadingScreen/index.tsx similarity index 92% rename from src/components/LoadingScreen/index.jsx rename to src/components/LoadingScreen/index.tsx index cf2c13188..813596630 100644 --- a/src/components/LoadingScreen/index.jsx +++ b/src/components/LoadingScreen/index.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import DesktopSkeleton from './DesktopSkeleton'; import MobileSkeleton from './MobileSkeleton'; diff --git a/src/components/Markdown/index.jsx b/src/components/Markdown/index.jsx deleted file mode 100644 index b173726bf..000000000 --- a/src/components/Markdown/index.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import BaseMarkdown from 'react-markdown'; - -function Markdown({ source }) { - return ( - <BaseMarkdown>{source}</BaseMarkdown> - ); -} - -Markdown.propTypes = { - source: PropTypes.string.isRequired, -}; - -export default Markdown; diff --git a/src/components/Markdown/index.tsx b/src/components/Markdown/index.tsx new file mode 100644 index 000000000..1363a4955 --- /dev/null +++ b/src/components/Markdown/index.tsx @@ -0,0 +1,12 @@ +import BaseMarkdown from 'react-markdown'; + +type MarkdownProps = { + source: string, +}; +function Markdown({ source }: MarkdownProps) { + return ( + <BaseMarkdown>{source}</BaseMarkdown> + ); +} + +export default Markdown; diff --git a/src/components/MediaList/AddToPlaylistAction.jsx b/src/components/MediaList/AddToPlaylistAction.jsx deleted file mode 100644 index fc33ee1fe..000000000 --- a/src/components/MediaList/AddToPlaylistAction.jsx +++ /dev/null @@ -1,51 +0,0 @@ -import omit from 'just-omit'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; -import { mdiPlus } from '@mdi/js'; -import { addMediaMenu } from '../../actions/PlaylistActionCreators'; -import { useMediaListContext } from './BaseMediaList'; -import SvgIcon from '../SvgIcon'; -import MediaAction from './MediaAction'; - -const { - useCallback, -} = React; - -/** - * @param {object} props - * @param {object} props.media - * @param {boolean} [props.withCustomMeta] - Use the artist/title that is stored on this item. - * Set to false when dealing with eg. search results, to make the server look up a default - * artist/title for this media. - */ -function AddToPlaylistAction({ media, withCustomMeta = true }) { - const { selection } = useMediaListContext(); - - const dispatch = useDispatch(); - const handleClick = useCallback((event) => { - let selectedItems = selection.isSelected(media) ? selection.get() : [media]; - if (!withCustomMeta) { - selectedItems = selectedItems.map((item) => omit(item, ['artist', 'title'])); - } - const rect = event.target.getBoundingClientRect(); - - dispatch(addMediaMenu(selectedItems, { - x: rect.left, - y: rect.top, - })); - }, [dispatch, selection, media, withCustomMeta]); - - return ( - <MediaAction onClick={handleClick}> - <SvgIcon path={mdiPlus} /> - </MediaAction> - ); -} - -AddToPlaylistAction.propTypes = { - media: PropTypes.object.isRequired, - withCustomMeta: PropTypes.bool, -}; - -export default AddToPlaylistAction; diff --git a/src/components/MediaList/AddToPlaylistAction.tsx b/src/components/MediaList/AddToPlaylistAction.tsx new file mode 100644 index 000000000..f6337ea0a --- /dev/null +++ b/src/components/MediaList/AddToPlaylistAction.tsx @@ -0,0 +1,51 @@ +import omit from 'just-omit'; +import { useCallback } from 'react'; +import { mdiPlus } from '@mdi/js'; +import { useDispatch } from '../../hooks/useRedux'; +import { useMediaListContext } from './BaseMediaList'; +import SvgIcon from '../SvgIcon'; +import MediaAction from './MediaAction'; +import { Media } from '../../reducers/booth'; +import { open as addMediaMenu } from '../../reducers/addToPlaylistMenu'; +import { NewPlaylistItem } from '../../reducers/playlists'; + +function filterNulls<T>(array: (T|null)[]): T[] { + return array.filter((item) => item != null) as T[]; +} + +export type AddToPlaylistActionProps = { + media: Media, + /** + * Use the artist/title that is stored on this item. + * Set to false when dealing with eg. search results, to make the server look up a default + * artist/title for this media. + */ + withCustomMeta?: boolean, +}; +function AddToPlaylistAction({ media, withCustomMeta = true }: AddToPlaylistActionProps) { + const { selection } = useMediaListContext(); + + const dispatch = useDispatch(); + const handleClick = useCallback((event: React.MouseEvent) => { + let selectedItems: NewPlaylistItem[] = selection.isSelected(media) + ? filterNulls(selection.get()) : [media]; + if (!withCustomMeta) { + selectedItems = selectedItems.map((item) => omit(item, ['artist', 'title'])); + } + const rect = event.currentTarget.getBoundingClientRect(); + + dispatch(addMediaMenu({ + type: 'add', + position: { x: rect.left, y: rect.top }, + data: { media: selectedItems }, + })); + }, [dispatch, selection, media, withCustomMeta]); + + return ( + <MediaAction onClick={handleClick}> + <SvgIcon path={mdiPlus} /> + </MediaAction> + ); +} + +export default AddToPlaylistAction; diff --git a/src/components/MediaList/BaseMediaList.jsx b/src/components/MediaList/BaseMediaList.tsx similarity index 67% rename from src/components/MediaList/BaseMediaList.jsx rename to src/components/MediaList/BaseMediaList.tsx index bdd32d538..8a45bba7c 100644 --- a/src/components/MediaList/BaseMediaList.jsx +++ b/src/components/MediaList/BaseMediaList.tsx @@ -1,12 +1,11 @@ import cx from 'clsx'; import React from 'react'; -import PropTypes from 'prop-types'; import { useVirtualizer } from '@tanstack/react-virtual'; -import itemSelection from 'item-selection/immutable'; +import itemSelection, { ItemSelection } from 'item-selection/immutable'; import LoadingRow from './LoadingRow'; +import { Media } from '../../reducers/booth'; const { - useCallback, useContext, useEffect, useMemo, @@ -14,9 +13,25 @@ const { useState, } = React; -const MediaListContext = React.createContext(); -export function useMediaListContext() { - return useContext(MediaListContext); +interface Item { + _id: string; + sourceType?: string; + sourceID?: string; +} + +type ContextType< + MediaType extends Item = Media, +> = { + media: (MediaType | null)[], + selection: ItemSelection<MediaType | null>, +} +const MediaListContext = React.createContext<ContextType<Item> | null>(null); +export function useMediaListContext<T extends ContextType = ContextType>() { + const context = useContext(MediaListContext); + if (!context) { + throw new Error('Missing MediaListContext'); + } + return context as T; } /** @@ -26,29 +41,47 @@ export function useMediaListContext() { * the new list has just loaded a page that wasn't loaded in the * previous one, and decide that the list is not really different. */ -function didMediaChange(prev, next) { - return prev.some((item, i) => item && next[i] && item._id !== next[i]._id); +function didMediaChange(prev: (Item | null)[], next: (Item | null)[]) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return prev.some((item, i) => item && next[i] && item._id !== next[i]!._id); } function estimateSize() { return 56; } -function BaseMediaList({ +type RowProps<MediaType extends Item = Media> = { + style: React.CSSProperties, + className: string, + index: number, + media: MediaType, + selected: boolean, + onClick: (event?: React.MouseEvent) => void, +} + +export type BaseMediaListProps<MediaType extends Item = Media> = { + className?: string, + media: (MediaType | null)[], + listComponent: React.ElementType<{ style: React.CSSProperties, children: React.ReactNode }>, + rowComponent: React.ComponentType<RowProps<MediaType>>, + contextProps?: object, + onRequestPage?: (page: number) => Promise<void>, + size?: number, +}; +function BaseMediaList<MediaType extends Item = Media>({ className, media, listComponent: ListComponent, rowComponent: RowComponent, - rowProps = {}, contextProps, onRequestPage, // The `size` property is only necessary for lazy loading. size = media.length, -}) { - const parentRef = useRef(); +}: BaseMediaListProps<MediaType>) { + const parentRef = useRef<HTMLDivElement>(null); const lastMediaRef = useRef(media); const [selection, setSelection] = useState(() => itemSelection(media)); - const inFlightPageRequests = useRef({}); + const inFlightPageRequests = useRef<Record<string, 1>>({}); const context = useMemo(() => ({ media, @@ -56,13 +89,14 @@ function BaseMediaList({ ...contextProps, }), [media, selection, contextProps]); - const itemKey = useCallback((index) => { - if (media[index]) { - const { _id: id, sourceType, sourceID } = media[index]; + const itemKey = (index: number) => { + const item = media[index]; + if (item) { + const { _id: id, sourceType, sourceID } = item; return id ?? `${sourceType}:${sourceID}`; } return `unloaded_${index}`; - }, [media]); + }; useEffect(() => { const lastMedia = lastMediaRef.current; @@ -74,7 +108,7 @@ function BaseMediaList({ } }, [media, selection]); - const selectItem = useCallback((index, event) => { + const selectItem = (index: number, event: React.MouseEvent) => { event.preventDefault(); if (event.shiftKey) { @@ -86,7 +120,7 @@ function BaseMediaList({ } else { setSelection(selection.select(index)); } - }, [selection]); + }; // Potentially interesting to explore is to virtualize entire PAGES at a time. // Then we render in batches of 50, which should be acceptable, and don't @@ -104,8 +138,8 @@ function BaseMediaList({ return; } - const isItemLoaded = (index) => media[index] != null; - const loadMoreItems = (start) => { + const isItemLoaded = (index: number) => media[index] != null; + const loadMoreItems = (start: number) => { const page = Math.floor(start / 50); if (inFlightPageRequests.current[page]) return Promise.resolve(null); inFlightPageRequests.current[page] = 1; @@ -133,29 +167,28 @@ function BaseMediaList({ const list = ( <ListComponent style={{ height: `${virtualizer.getTotalSize()}px`, width: '100%', position: 'relative' }}> {virtualItems.map(({ index, start }) => { + const item = media[index]; const style = { transform: `translateY(${start}px)` }; const selected = selection.isSelectedIndex(index); - if (!media[index]) { + if (!item) { return ( <LoadingRow key={itemKey(index)} className="MediaList-row" style={style} - selected={selected} /> ); } return ( <RowComponent - {...rowProps} key={itemKey(index)} style={style} className="MediaList-row" index={index} - media={media[index]} + media={item} selected={selected} - onClick={(event) => selectItem(index, event)} + onClick={(event?: React.MouseEvent) => event && selectItem(index, event)} /> ); })} @@ -171,18 +204,4 @@ function BaseMediaList({ ); } -BaseMediaList.propTypes = { - className: PropTypes.string, - media: PropTypes.array, - size: PropTypes.number, - onRequestPage: PropTypes.func, - listComponent: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.func, - ]).isRequired, - rowComponent: PropTypes.func.isRequired, - rowProps: PropTypes.object, - contextProps: PropTypes.object, -}; - export default BaseMediaList; diff --git a/src/components/MediaList/LoadingRow.jsx b/src/components/MediaList/LoadingRow.tsx similarity index 75% rename from src/components/MediaList/LoadingRow.jsx rename to src/components/MediaList/LoadingRow.tsx index f5d847b86..fc2a3d7b7 100644 --- a/src/components/MediaList/LoadingRow.jsx +++ b/src/components/MediaList/LoadingRow.tsx @@ -1,9 +1,8 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import MediaLoadingIndicator from './MediaLoadingIndicator'; -function LoadingRow({ className, ...attrs }) { +type LoadingRowProps = React.ComponentProps<'div'>; +function LoadingRow({ className, ...attrs }: LoadingRowProps) { return ( <div className={cx('MediaListRow', 'is-loading', className)} {...attrs}> <MediaLoadingIndicator className="MediaListRow-loader" /> @@ -23,9 +22,4 @@ function LoadingRow({ className, ...attrs }) { ); } -LoadingRow.propTypes = { - className: PropTypes.string, - selected: PropTypes.bool, -}; - export default LoadingRow; diff --git a/src/components/MediaList/MediaAction.jsx b/src/components/MediaList/MediaAction.jsx deleted file mode 100644 index fd3633b38..000000000 --- a/src/components/MediaList/MediaAction.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import IconButton from '@mui/material/IconButton'; - -const Action = ({ children, ...props }) => ( - <IconButton className="MediaActions-action" {...props}> - {children} - </IconButton> -); - -Action.propTypes = { - children: PropTypes.element, -}; - -export default Action; diff --git a/src/components/MediaList/MediaAction.tsx b/src/components/MediaList/MediaAction.tsx new file mode 100644 index 000000000..d734d5c70 --- /dev/null +++ b/src/components/MediaList/MediaAction.tsx @@ -0,0 +1,11 @@ +import IconButton, { IconButtonProps } from '@mui/material/IconButton'; + +function Action({ children, ...props }: IconButtonProps) { + return ( + <IconButton className="MediaActions-action" {...props}> + {children} + </IconButton> + ); +} + +export default Action; diff --git a/src/components/MediaList/MediaActions.jsx b/src/components/MediaList/MediaActions.tsx similarity index 70% rename from src/components/MediaList/MediaActions.jsx rename to src/components/MediaList/MediaActions.tsx index b96674b7f..9123d0cba 100644 --- a/src/components/MediaList/MediaActions.jsx +++ b/src/components/MediaList/MediaActions.tsx @@ -1,14 +1,17 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import AddToPlaylistAction from './AddToPlaylistAction'; import PreviewMediaAction from './PreviewMediaAction'; +import { Media } from '../../reducers/booth'; -function dontBubble(event) { +function dontBubble(event: React.MouseEvent) { event.stopPropagation(); } -function MediaActions({ className, media }) { +type MediaActionsProps = { + className?: string, + media: Media, +}; +function MediaActions({ className, media }: MediaActionsProps) { return ( // eslint-disable-next-line max-len // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions @@ -22,9 +25,4 @@ function MediaActions({ className, media }) { ); } -MediaActions.propTypes = { - className: PropTypes.string, - media: PropTypes.object.isRequired, -}; - export default MediaActions; diff --git a/src/components/MediaList/MediaDuration.js b/src/components/MediaList/MediaDuration.js deleted file mode 100644 index 002777711..000000000 --- a/src/components/MediaList/MediaDuration.js +++ /dev/null @@ -1,22 +0,0 @@ -import formatDuration from 'format-duration'; -import PropTypes from 'prop-types'; - -function MediaDuration({ media }) { - const duration = 'start' in media - // playlist item - ? media.end - media.start - // search result - : media.duration; - - return formatDuration(duration * 1000); -} - -MediaDuration.propTypes = { - media: PropTypes.shape({ - start: PropTypes.number, - end: PropTypes.number, - duration: PropTypes.number, - }).isRequired, -}; - -export default MediaDuration; diff --git a/src/components/MediaList/MediaDuration.tsx b/src/components/MediaList/MediaDuration.tsx new file mode 100644 index 000000000..70e34cb0d --- /dev/null +++ b/src/components/MediaList/MediaDuration.tsx @@ -0,0 +1,24 @@ +import formatDuration from 'format-duration'; + +type MediaDurationProps = { + media: { + duration: number, + } & ({ + start: number, + end: number + } | { + start?: undefined, + end?: undefined, + }) +} +function MediaDuration({ media }: MediaDurationProps) { + const duration = 'start' in media && media.start != null + // playlist item + ? media.end - media.start + // search result + : media.duration; + + return <>{formatDuration(duration * 1000)}</>; +} + +export default MediaDuration; diff --git a/src/components/MediaList/MediaLoadingIndicator.jsx b/src/components/MediaList/MediaLoadingIndicator.jsx deleted file mode 100644 index 6ed3c3717..000000000 --- a/src/components/MediaList/MediaLoadingIndicator.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import CircularProgress from '@mui/material/CircularProgress'; - -const MediaLoadingIndicator = ({ className }) => ( - <div className={cx('MediaLoadingIndicator', className)}> - <CircularProgress className="MediaLoadingIndicator-spinner" /> - </div> -); - -MediaLoadingIndicator.propTypes = { - className: PropTypes.string, -}; - -export default MediaLoadingIndicator; diff --git a/src/components/MediaList/MediaLoadingIndicator.tsx b/src/components/MediaList/MediaLoadingIndicator.tsx new file mode 100644 index 000000000..48624e766 --- /dev/null +++ b/src/components/MediaList/MediaLoadingIndicator.tsx @@ -0,0 +1,15 @@ +import cx from 'clsx'; +import CircularProgress from '@mui/material/CircularProgress'; + +type MediaLoadingIndicatorProps = { + className?: string, +}; +function MediaLoadingIndicator({ className }: MediaLoadingIndicatorProps) { + return ( + <div className={cx('MediaLoadingIndicator', className)}> + <CircularProgress className="MediaLoadingIndicator-spinner" /> + </div> + ); +} + +export default MediaLoadingIndicator; diff --git a/src/components/MediaList/MediaRowBase.jsx b/src/components/MediaList/MediaRowBase.tsx similarity index 71% rename from src/components/MediaList/MediaRowBase.jsx rename to src/components/MediaList/MediaRowBase.tsx index 1016cd11f..34738f8e7 100644 --- a/src/components/MediaList/MediaRowBase.jsx +++ b/src/components/MediaList/MediaRowBase.tsx @@ -1,10 +1,10 @@ import cx from 'clsx'; import React from 'react'; -import PropTypes from 'prop-types'; import { useDrag } from 'react-dnd'; import { getEmptyImage } from 'react-dnd-html5-backend'; import { MEDIA } from '../../constants/DDItemTypes'; import { useMediaListContext } from './BaseMediaList'; +import type { Media } from '../../reducers/booth'; const { useCallback, @@ -12,6 +12,15 @@ const { useRef, } = React; +interface MediaRowBaseProps extends React.ComponentProps<'div'> { + className?: string, + style?: React.CSSProperties, + dragType?: string, + media: Media, + children: React.ReactNode, + onClick?: (event?: React.MouseEvent) => void, + containerRef?: React.RefObject<HTMLDivElement>, +} function MediaRowBase({ className, style, @@ -21,11 +30,11 @@ function MediaRowBase({ children, containerRef, ...props -}) { +}: MediaRowBaseProps) { const { selection } = useMediaListContext(); const selected = selection.isSelected(media); - const localRef = useRef(); + const localRef = useRef<HTMLDivElement>(null); const ref = containerRef ?? localRef; const [, drag, connectDragPreview] = useDrag({ @@ -40,9 +49,9 @@ function MediaRowBase({ connectDragPreview(getEmptyImage()); }, [connectDragPreview]); - const handleKeyPress = useCallback((event) => { + const handleKeyPress = useCallback((event: React.KeyboardEvent) => { if (event.code === 'Space') { - onClick(); + onClick?.(); } }, [onClick]); @@ -64,14 +73,4 @@ function MediaRowBase({ ); } -MediaRowBase.propTypes = { - className: PropTypes.string, - style: PropTypes.object, // from virtual list positioning - dragType: PropTypes.string, - media: PropTypes.object.isRequired, - onClick: PropTypes.func, - children: PropTypes.node.isRequired, - containerRef: PropTypes.any, -}; - export default MediaRowBase; diff --git a/src/components/MediaList/MediaSourceIcon.jsx b/src/components/MediaList/MediaSourceIcon.jsx deleted file mode 100644 index 9b6faf4e0..000000000 --- a/src/components/MediaList/MediaSourceIcon.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useMediaSources } from '../../context/MediaSourceContext'; - -function MediaSourceIcon({ sourceType }) { - const { getMediaSource } = useMediaSources(); - const { icon, name } = getMediaSource(sourceType); - - return ( - <img - height="20dp" - src={icon} - alt={name} - /> - ); -} - -MediaSourceIcon.propTypes = { - sourceType: PropTypes.string.isRequired, -}; - -export default React.memo(MediaSourceIcon); diff --git a/src/components/MediaList/MediaSourceIcon.tsx b/src/components/MediaList/MediaSourceIcon.tsx new file mode 100644 index 000000000..7466f3fca --- /dev/null +++ b/src/components/MediaList/MediaSourceIcon.tsx @@ -0,0 +1,25 @@ +import { memo } from 'react'; +import { useMediaSources } from '../../context/MediaSourceContext'; + +type MediaSourceIconProps = { + sourceType: string, +}; +function MediaSourceIcon({ sourceType }: MediaSourceIconProps) { + const { getMediaSource } = useMediaSources(); + const source = getMediaSource(sourceType); + if (!source) { + return null; + } + + const { icon, name } = source; + + return ( + <img + height="20dp" + src={icon.toString()} + alt={name} + /> + ); +} + +export default memo(MediaSourceIcon); diff --git a/src/components/MediaList/MediaThumbnail.jsx b/src/components/MediaList/MediaThumbnail.jsx deleted file mode 100644 index b8d54190a..000000000 --- a/src/components/MediaList/MediaThumbnail.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -function MediaThumbnail({ url }) { - return ( - <div className="MediaListRow-thumb"> - <img - className="MediaListRow-image" - src={url} - alt="" - loading="lazy" - /> - </div> - ); -} - -MediaThumbnail.propTypes = { - url: PropTypes.string.isRequired, -}; - -export default React.memo(MediaThumbnail); diff --git a/src/components/MediaList/MediaThumbnail.tsx b/src/components/MediaList/MediaThumbnail.tsx new file mode 100644 index 000000000..8e9eed572 --- /dev/null +++ b/src/components/MediaList/MediaThumbnail.tsx @@ -0,0 +1,19 @@ +import { memo } from 'react'; + +type MediaThumbnailProps = { + url: string, +}; +function MediaThumbnail({ url }: MediaThumbnailProps) { + return ( + <div className="MediaListRow-thumb"> + <img + className="MediaListRow-image" + src={url} + alt="" + loading="lazy" + /> + </div> + ); +} + +export default memo(MediaThumbnail); diff --git a/src/components/MediaList/PreviewMediaAction.jsx b/src/components/MediaList/PreviewMediaAction.tsx similarity index 79% rename from src/components/MediaList/PreviewMediaAction.jsx rename to src/components/MediaList/PreviewMediaAction.tsx index 84f1226be..c1e706b00 100644 --- a/src/components/MediaList/PreviewMediaAction.jsx +++ b/src/components/MediaList/PreviewMediaAction.tsx @@ -1,18 +1,17 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; +import { useCallback } from 'react'; +import { useDispatch } from '../../hooks/useRedux'; import { openPreviewMediaDialog } from '../../actions/DialogActionCreators'; import SvgIcon from '../SvgIcon'; import MediaAction from './MediaAction'; - -const { - useCallback, -} = React; +import { Media } from '../../reducers/booth'; // From https://fonts.google.com/icons?selected=Material%20Icons%3Apreview%3A const mdiPreview = 'M19,3H5C3.89,3,3,3.9,3,5v14c0,1.1,0.89,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.11,3,19,3z M19,19H5V7h14V19z M13.5,13 c0,0.83-0.67,1.5-1.5,1.5s-1.5-0.67-1.5-1.5c0-0.83,0.67-1.5,1.5-1.5S13.5,12.17,13.5,13z M12,9c-2.73,0-5.06,1.66-6,4 c0.94,2.34,3.27,4,6,4s5.06-1.66,6-4C17.06,10.66,14.73,9,12,9z M12,15.5c-1.38,0-2.5-1.12-2.5-2.5c0-1.38,1.12-2.5,2.5-2.5 c1.38,0,2.5,1.12,2.5,2.5C14.5,14.38,13.38,15.5,12,15.5z'; -function PreviewMediaAction({ media }) { +type PreviewMediaActionProps = { + media: Media, +}; +function PreviewMediaAction({ media }: PreviewMediaActionProps) { const dispatch = useDispatch(); const handleClick = useCallback(() => { dispatch(openPreviewMediaDialog(media)); @@ -25,8 +24,4 @@ function PreviewMediaAction({ media }) { ); } -PreviewMediaAction.propTypes = { - media: PropTypes.object.isRequired, -}; - export default PreviewMediaAction; diff --git a/src/components/MediaList/Row.jsx b/src/components/MediaList/Row.tsx similarity index 76% rename from src/components/MediaList/Row.jsx rename to src/components/MediaList/Row.tsx index 95ddd2991..01b93678d 100644 --- a/src/components/MediaList/Row.jsx +++ b/src/components/MediaList/Row.tsx @@ -1,29 +1,35 @@ import cx from 'clsx'; import React from 'react'; -import PropTypes from 'prop-types'; import MediaRowBase from './MediaRowBase'; import MediaDuration from './MediaDuration'; import MediaLoadingIndicator from './MediaLoadingIndicator'; import MediaSourceIcon from './MediaSourceIcon'; import MediaThumbnail from './MediaThumbnail'; import MediaActions from './MediaActions'; +import { Media } from '../../reducers/booth'; +type MediaRowProps = { + className?: string, + media: Media, + style: React.CSSProperties, + onClick: (event?: React.MouseEvent) => void, +}; function MediaRow({ className, media, style, onClick, -}) { - const loadingClass = media.loading ? 'is-loading' : ''; +}: MediaRowProps) { + const isLoading = 'loading' in media && typeof media.loading === 'boolean' && media.loading; return ( <MediaRowBase media={media} - className={cx(className, loadingClass)} + className={cx(className, isLoading ? 'is-loading' : '')} style={style} onClick={onClick} > - {media.loading ? ( + {isLoading ? ( <MediaLoadingIndicator className="MediaListRow-loader" /> ) : ( <MediaThumbnail url={media.thumbnail} /> @@ -50,11 +56,4 @@ function MediaRow({ ); } -MediaRow.propTypes = { - className: PropTypes.string, - style: PropTypes.object, // from virtual list positioning - media: PropTypes.object, - onClick: PropTypes.func, -}; - export default React.memo(MediaRow); diff --git a/src/components/MediaList/index.jsx b/src/components/MediaList/index.jsx deleted file mode 100644 index 9d14f6225..000000000 --- a/src/components/MediaList/index.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import Base from './BaseMediaList'; -import Row from './Row'; - -function MediaList(props) { - return ( - <Base - listComponent="div" - rowComponent={Row} - {...props} - /> - ); -} - -export default MediaList; diff --git a/src/components/MediaList/index.tsx b/src/components/MediaList/index.tsx new file mode 100644 index 000000000..dcb9d2993 --- /dev/null +++ b/src/components/MediaList/index.tsx @@ -0,0 +1,16 @@ +import Base, { BaseMediaListProps } from './BaseMediaList'; +import Row from './Row'; + +type MediaListProps = Omit<BaseMediaListProps, 'listComponent' | 'rowComponent'> + & Partial<Pick<BaseMediaListProps, 'listComponent' | 'rowComponent'>>; +function MediaList(props: MediaListProps) { + return ( + <Base + listComponent="div" + rowComponent={Row} + {...props} + /> + ); +} + +export default MediaList; diff --git a/src/components/Overlay/Header/index.css b/src/components/Overlay/Header/index.css index 8db4654d0..e18aa7f52 100644 --- a/src/components/Overlay/Header/index.css +++ b/src/components/Overlay/Header/index.css @@ -15,7 +15,7 @@ text-transform: uppercase; width: 33%; - @media (min-width: 1200px) { + @media (width >= 1200px) { width: 300px; flex-grow: 0; } diff --git a/src/components/Overlay/index.css b/src/components/Overlay/index.css index 2d398b9dc..87265b853 100644 --- a/src/components/Overlay/index.css +++ b/src/components/Overlay/index.css @@ -32,12 +32,9 @@ .Overlay-content { position: absolute; - top: var(--header-height); - bottom: var(--footer-height); - left: 0; - right: 0; + inset: var(--header-height) 0 var(--footer-height) 0; - @media (max-width: 768px) { + @media (width <= 768px) { bottom: 0; } } diff --git a/src/components/Overlay/index.jsx b/src/components/Overlay/index.jsx deleted file mode 100644 index 36700a45a..000000000 --- a/src/components/Overlay/index.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const Overlay = ({ direction = 'bottom', children, className }) => ( - <div - className={cx( - 'Overlay', - `Overlay--from-${direction}`, - )} - > - <div className={cx('Overlay-body', className)}> - {children} - </div> - </div> -); - -Overlay.propTypes = { - children: PropTypes.node.isRequired, - className: PropTypes.string, - direction: PropTypes.string, -}; - -export default Overlay; diff --git a/src/components/Overlay/index.tsx b/src/components/Overlay/index.tsx new file mode 100644 index 000000000..4c20b3c80 --- /dev/null +++ b/src/components/Overlay/index.tsx @@ -0,0 +1,23 @@ +import cx from 'clsx'; + +type OverlayProps = { + className?: string, + children: React.ReactNode, + direction?: 'top' | 'bottom', +}; +function Overlay({ direction = 'bottom', children, className }: OverlayProps) { + return ( + <div + className={cx( + 'Overlay', + `Overlay--from-${direction}`, + )} + > + <div className={cx('Overlay-body', className)}> + {children} + </div> + </div> + ); +} + +export default Overlay; diff --git a/src/components/Player/index.jsx b/src/components/Player/index.tsx similarity index 66% rename from src/components/Player/index.jsx rename to src/components/Player/index.tsx index c2431afb9..58af0c090 100644 --- a/src/components/Player/index.jsx +++ b/src/components/Player/index.tsx @@ -1,19 +1,30 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import { useMediaSources } from '../../context/MediaSourceContext'; +import { Media } from '../../reducers/booth'; +type PlayerProps = { + enabled: boolean, + size: string, + mode?: 'preview' | undefined, + volume: number, + isMuted: boolean, + media: Media, + seek: number, + onPlay?: () => void, +}; function Player({ enabled, size, + mode, volume, isMuted, media, seek, onPlay, -}) { +}: PlayerProps) { const { getAllMediaSources } = useMediaSources(); + // TODO we can probably bail out here if `enabled` is false also if (!media) { return <div className="Player" />; } @@ -22,15 +33,16 @@ function Player({ enabled, media, seek, - mode: size, + mode, volume: isMuted ? 0 : volume, onPlay, + size, }; const sources = getAllMediaSources(); const players = Object.keys(sources).map((sourceType) => { - const SourcePlayer = sources[sourceType].Player; - if (!SourcePlayer) { + const SourcePlayer = sources[sourceType]?.Player; + if (SourcePlayer == null) { return null; } return ( @@ -49,14 +61,4 @@ function Player({ ); } -Player.propTypes = { - enabled: PropTypes.bool, - size: PropTypes.string, - volume: PropTypes.number, - isMuted: PropTypes.bool, - media: PropTypes.object, - seek: PropTypes.number, - onPlay: PropTypes.func, -}; - export default Player; diff --git a/src/components/PlaylistManager/Header/SearchBar.jsx b/src/components/PlaylistManager/Header/SearchBar.jsx index 2d91d7a7e..6ef750116 100644 --- a/src/components/PlaylistManager/Header/SearchBar.jsx +++ b/src/components/PlaylistManager/Header/SearchBar.jsx @@ -1,10 +1,9 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; +import { useDispatch } from '../../../hooks/useRedux'; import BaseSearchBar from '../../SearchBar'; import SourcePicker from './SourcePicker'; -import { showSearchResults } from '../../../actions/SearchActionCreators'; import { useMediaSearchStore } from '../../../stores/MediaSearchStore'; +import { showSearchResults } from '../../../reducers/playlists'; function MediaSearchBar({ className }) { const { diff --git a/src/components/PlaylistManager/Import/index.jsx b/src/components/PlaylistManager/Import/index.jsx index 9d232f0ba..941d1199a 100644 --- a/src/components/PlaylistManager/Import/index.jsx +++ b/src/components/PlaylistManager/Import/index.jsx @@ -44,7 +44,9 @@ const PlaylistImport = ({ return ( <div className="PlaylistImport"> - {forms} + <Suspense fallback={<LoadingPanel />}> + {forms} + </Suspense> </div> ); }; diff --git a/src/components/PlaylistManager/Menu/index.jsx b/src/components/PlaylistManager/Menu/index.jsx index ee883db07..c5efee8e0 100644 --- a/src/components/PlaylistManager/Menu/index.jsx +++ b/src/components/PlaylistManager/Menu/index.jsx @@ -1,29 +1,24 @@ import cx from 'clsx'; -import React from 'react'; import PropTypes from 'prop-types'; import MenuList from '@mui/material/MenuList'; import PlaylistRow from './Row'; import PlaylistCreateRow from './NewPlaylist'; import SearchResultsRow from './SearchResultsRow'; import PlaylistImportRow from './PlaylistImportRow'; +import { importPanelSymbol, searchPanelSymbol } from '../../../reducers/playlists'; function PlaylistMenu({ className, playlists, selected, searchQuery, - showSearchResults, onCreatePlaylist, onSelectPlaylist, onSelectSearchResults, onCloseSearchResults, onAddToPlaylist, - showImportPanel, onShowImportPanel, }) { - const searchIsSelected = showSearchResults ? 'is-selected' : ''; - const importIsSelected = showImportPanel ? 'is-selected' : ''; - const isSelectingPlaylist = selected && !showSearchResults && !showImportPanel; return ( <MenuList className={cx('PlaylistMenu', className)} disablePadding> <PlaylistCreateRow @@ -32,7 +27,7 @@ function PlaylistMenu({ /> {searchQuery && ( <SearchResultsRow - className={cx('PlaylistMenu-row', searchIsSelected)} + className={cx('PlaylistMenu-row', selected === searchPanelSymbol && 'is-selected')} query={searchQuery} onClick={onSelectSearchResults} onClose={onCloseSearchResults} @@ -43,13 +38,13 @@ function PlaylistMenu({ key={pl._id} className="PlaylistMenu-row" playlist={pl} - selected={isSelectingPlaylist && selected._id === pl._id} + selected={selected === pl._id} onClick={() => onSelectPlaylist(pl._id)} onAddToPlaylist={onAddToPlaylist} /> ))} <PlaylistImportRow - className={cx('PlaylistMenu-row', importIsSelected)} + className={cx('PlaylistMenu-row', selected === importPanelSymbol && 'is-selected')} onClick={onShowImportPanel} /> </MenuList> @@ -59,9 +54,10 @@ function PlaylistMenu({ PlaylistMenu.propTypes = { className: PropTypes.string, playlists: PropTypes.arrayOf(PropTypes.object).isRequired, - selected: PropTypes.object, - showSearchResults: PropTypes.bool.isRequired, - showImportPanel: PropTypes.bool.isRequired, + selected: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.symbol, + ]), searchQuery: PropTypes.string, onCreatePlaylist: PropTypes.func.isRequired, onSelectPlaylist: PropTypes.func.isRequired, diff --git a/src/components/PlaylistManager/NoPlaylists/ImportBlock.jsx b/src/components/PlaylistManager/NoPlaylists/ImportBlock.jsx index d0b0f210f..db9f046f5 100644 --- a/src/components/PlaylistManager/NoPlaylists/ImportBlock.jsx +++ b/src/components/PlaylistManager/NoPlaylists/ImportBlock.jsx @@ -1,12 +1,11 @@ -import React from 'react'; -import { useDispatch } from 'react-redux'; +import { useDispatch } from '../../../hooks/useRedux'; import { useMediaSources } from '../../../context/MediaSourceContext'; import { - showImportPanel, hideImportPanel, showImportSourcePanel, hideImportSourcePanel, } from '../../../actions/ImportActionCreators'; +import { showImportPanel } from '../../../reducers/playlists'; function ImportBlock() { const { getAllMediaSources } = useMediaSources(); diff --git a/src/components/PlaylistManager/Panel/DroppablePlaylistItemRow.jsx b/src/components/PlaylistManager/Panel/DroppablePlaylistItemRow.jsx index e74fc9f49..3491e672d 100644 --- a/src/components/PlaylistManager/Panel/DroppablePlaylistItemRow.jsx +++ b/src/components/PlaylistManager/Panel/DroppablePlaylistItemRow.jsx @@ -5,6 +5,7 @@ import { useDrop } from 'react-dnd'; import { MEDIA } from '../../../constants/DDItemTypes'; import isDraggingNearTopOfRow from '../../../utils/isDraggingNearTopOfRow'; import PlaylistItemRow from './PlaylistItemRow'; +import { useMediaListContext } from '../../MediaList/BaseMediaList'; const { useRef, @@ -17,13 +18,13 @@ function DroppablePlaylistItemRow({ index, media, onClick, - onMoveMedia, }) { + const { onMoveMedia } = useMediaListContext(); const [insertingAbove, setInsertAbove] = useState(false); const droppableRef = useRef(null); const [{ isOver }, drop] = useDrop(() => ({ accept: MEDIA, - drop(item, monitor) { + drop(_item, monitor) { const { media: droppedItems } = monitor.getItem(); if (droppedItems) { // Do not attempt to move when the selection is dropped on top of an item @@ -38,7 +39,7 @@ function DroppablePlaylistItemRow({ ); } }, - hover(item, monitor) { + hover(_item, monitor) { setInsertAbove(isDraggingNearTopOfRow(monitor, droppableRef.current)); }, collect(monitor) { @@ -68,7 +69,6 @@ DroppablePlaylistItemRow.propTypes = { index: PropTypes.number.isRequired, media: PropTypes.object.isRequired, onClick: PropTypes.func.isRequired, - onMoveMedia: PropTypes.func.isRequired, }; export default DroppablePlaylistItemRow; diff --git a/src/components/PlaylistManager/Panel/EditMediaAction.jsx b/src/components/PlaylistManager/Panel/EditMediaAction.jsx index 263b26cc0..492562a68 100644 --- a/src/components/PlaylistManager/Panel/EditMediaAction.jsx +++ b/src/components/PlaylistManager/Panel/EditMediaAction.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { mdiPencil } from '@mdi/js'; +import { useDispatch } from '../../../hooks/useRedux'; import SvgIcon from '../../SvgIcon'; import { editMedia } from '../../../actions/PlaylistActionCreators'; import { useMediaListContext } from '../../MediaList/BaseMediaList'; diff --git a/src/components/PlaylistManager/Panel/MoveToFirstAction.jsx b/src/components/PlaylistManager/Panel/MoveToFirstAction.jsx index 588fef750..5001d310b 100644 --- a/src/components/PlaylistManager/Panel/MoveToFirstAction.jsx +++ b/src/components/PlaylistManager/Panel/MoveToFirstAction.jsx @@ -1,11 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { mdiChevronUp } from '@mdi/js'; -import { moveMedia } from '../../../actions/PlaylistActionCreators'; +import { useDispatch } from '../../../hooks/useRedux'; import { useMediaListContext } from '../../MediaList/BaseMediaList'; import SvgIcon from '../../SvgIcon'; import MediaAction from '../../MediaList/MediaAction'; +import { movePlaylistItems } from '../../../reducers/playlists'; const { useCallback, @@ -17,7 +17,11 @@ function MoveToFirstAction({ media }) { const handleClick = useCallback(() => { const selectedItems = selection.isSelected(media) ? selection.get() : [media]; - dispatch(moveMedia(playlist._id, selectedItems, { at: 'start' })); + dispatch(movePlaylistItems({ + playlistID: playlist._id, + medias: selectedItems, + target: { at: 'start' }, + })); }, [dispatch, playlist, media, selection]); return ( diff --git a/src/components/PlaylistManager/Panel/MoveToLastAction.jsx b/src/components/PlaylistManager/Panel/MoveToLastAction.jsx index 106c0c4ae..a2a02c1aa 100644 --- a/src/components/PlaylistManager/Panel/MoveToLastAction.jsx +++ b/src/components/PlaylistManager/Panel/MoveToLastAction.jsx @@ -1,8 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { mdiChevronDown } from '@mdi/js'; -import { moveMedia } from '../../../actions/PlaylistActionCreators'; +import { useDispatch } from '../../../hooks/useRedux'; +import { movePlaylistItems } from '../../../reducers/playlists'; import { useMediaListContext } from '../../MediaList/BaseMediaList'; import SvgIcon from '../../SvgIcon'; import MediaAction from '../../MediaList/MediaAction'; @@ -17,7 +17,11 @@ function MoveToLastAction({ media }) { const handleClick = useCallback(() => { const selectedItems = selection.isSelected(media) ? selection.get() : [media]; - dispatch(moveMedia(playlist._id, selectedItems, { at: 'end' })); + dispatch(movePlaylistItems({ + playlistID: playlist._id, + medias: selectedItems, + target: { at: 'end' }, + })); }, [dispatch, playlist, media, selection]); return ( diff --git a/src/components/PlaylistManager/Panel/RemoveFromPlaylistAction.jsx b/src/components/PlaylistManager/Panel/RemoveFromPlaylistAction.jsx index 1b228e09a..81b926907 100644 --- a/src/components/PlaylistManager/Panel/RemoveFromPlaylistAction.jsx +++ b/src/components/PlaylistManager/Panel/RemoveFromPlaylistAction.jsx @@ -1,11 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { mdiDelete } from '@mdi/js'; -import { removeMedia } from '../../../actions/PlaylistActionCreators'; +import { useDispatch } from '../../../hooks/useRedux'; import { useMediaListContext } from '../../MediaList/BaseMediaList'; import SvgIcon from '../../SvgIcon'; import MediaAction from '../../MediaList/MediaAction'; +import { removePlaylistItems } from '../../../reducers/playlists'; const { useCallback, @@ -18,7 +18,10 @@ function RemoveFromPlaylistAction({ media }) { const handleClick = useCallback(() => { const selectedItems = selection.isSelected(media) ? selection.get() : [media]; - dispatch(removeMedia(playlistID, selectedItems)); + dispatch(removePlaylistItems({ + playlistID, + medias: selectedItems, + })); }, [dispatch, playlistID, media, selection]); return ( diff --git a/src/components/PlaylistManager/Panel/index.jsx b/src/components/PlaylistManager/Panel/index.jsx index 56571d373..fc6ee4c94 100644 --- a/src/components/PlaylistManager/Panel/index.jsx +++ b/src/components/PlaylistManager/Panel/index.jsx @@ -26,6 +26,8 @@ function PlaylistPanel(props) { onMoveMedia, } = props; + const { size } = playlist; + let list; if (loading) { list = ( @@ -33,20 +35,19 @@ function PlaylistPanel(props) { <CircularProgress size="100%" /> </div> ); - } else if (media.length === 0) { - list = isFiltered - ? <PlaylistFilterEmpty /> - : <PlaylistEmpty />; + } else if (isFiltered && media.length === 0) { + list = <PlaylistFilterEmpty />; + } else if (size === 0) { + list = <PlaylistEmpty />; } else { list = ( <BaseMediaList className="PlaylistPanel-media" - size={media.length} + size={size} media={media} listComponent="div" rowComponent={isFiltered ? PlaylistItemRow : DroppablePlaylistItemRow} - rowProps={{ onMoveMedia }} - contextProps={{ playlist, isFiltered }} + contextProps={{ playlist, isFiltered, onMoveMedia }} onRequestPage={onLoadPlaylistPage} /> ); diff --git a/src/components/PlaylistManager/index.css b/src/components/PlaylistManager/index.css index f815d7680..635c35d36 100644 --- a/src/components/PlaylistManager/index.css +++ b/src/components/PlaylistManager/index.css @@ -24,7 +24,7 @@ } /* menu would be larger than 300px */ -@media (min-width: 1200px) { +@media (width >= 1200px) { .PlaylistManager-menu { width: 300px; } diff --git a/src/components/PlaylistManager/index.jsx b/src/components/PlaylistManager/index.tsx similarity index 63% rename from src/components/PlaylistManager/index.jsx rename to src/components/PlaylistManager/index.tsx index 56d441008..62b17d7aa 100644 --- a/src/components/PlaylistManager/index.jsx +++ b/src/components/PlaylistManager/index.tsx @@ -1,6 +1,6 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useCallback } from 'react'; +import { useTranslator } from '@u-wave/react-translate'; import OverlayContent from '../Overlay/Content'; import PlaylistMenu from '../../containers/PlaylistManagerMenu'; import PlaylistPanel from '../../containers/PlaylistManagerPanel'; @@ -9,37 +9,44 @@ import SearchResults from '../../containers/SearchResultsPanel'; import MediaSearchBar from './Header/SearchBar'; import PlaylistHeader from './Header'; import NoPlaylists from './NoPlaylists'; +import { useDispatch, useSelector } from '../../hooks/useRedux'; +import { createPlaylist, importPanelSymbol, searchPanelSymbol } from '../../reducers/playlists'; import './index.css'; -const PlaylistManager = ({ +type PlaylistManagerProps = { + className?: string, + onCloseOverlay: () => void, +}; +function PlaylistManager({ className, - selectedPlaylist, - showSearchResults, - showImportPanel, - onCreatePlaylist, onCloseOverlay, -}) => { +}: PlaylistManagerProps) { + const showPanel = useSelector((state) => state.playlists.selectedPlaylistID); + + const { t } = useTranslator(); + const dispatch = useDispatch(); + const onCreatePlaylist = useCallback(() => ( + dispatch(createPlaylist(t('playlists.defaultName'))) + ), [dispatch, t]); + let panel; let empty = false; - if (showImportPanel) { + if (showPanel === importPanelSymbol) { panel = ( <div className="PlaylistPanel"> <PlaylistImport /> </div> ); - } else if (showSearchResults) { + } else if (showPanel === searchPanelSymbol) { panel = <SearchResults />; - } else if (selectedPlaylist) { - // HACK Give this a key so it's remounted when you switch playlists. + } else if (typeof showPanel === 'string') { + // Give this a key so it's remounted when you switch playlists. // This is because there is some statefulness down the tree, especially // in playlist filters and scroll position. // By forcing a remount using a key we throw away all state and keep it // consistent. - // TODO To *actually* fix playlist filters bleeding across playlist lines, - // we should reset the playlist filter state alone somehow when the - // selected playlist changes. - panel = <PlaylistPanel key={selectedPlaylist._id} />; + panel = <PlaylistPanel key={showPanel} />; } else { empty = true; } @@ -67,15 +74,6 @@ const PlaylistManager = ({ </OverlayContent> </div> ); -}; - -PlaylistManager.propTypes = { - className: PropTypes.string, - selectedPlaylist: PropTypes.object, - showSearchResults: PropTypes.bool.isRequired, - showImportPanel: PropTypes.bool.isRequired, - onCreatePlaylist: PropTypes.func.isRequired, - onCloseOverlay: PropTypes.func, -}; +} export default PlaylistManager; diff --git a/src/components/RoleColor/index.jsx b/src/components/RoleColor/index.jsx deleted file mode 100644 index 65a4b6aae..000000000 --- a/src/components/RoleColor/index.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; -import { roleColorsSelector } from '../../selectors/configSelectors'; - -function RoleColor({ - component = 'span', - role, - roles, - ...props -}) { - const colors = useSelector(roleColorsSelector); - - const roleColor = role - ? colors[role] - : colors[roles.find((r) => colors[r])]; - - const style = { - color: roleColor ?? colors.default, - }; - - const Component = component; - return <Component {...props} style={style} />; -} - -RoleColor.propTypes = { - component: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.func, - ]), - role: PropTypes.string, - roles: PropTypes.arrayOf(PropTypes.string.isRequired), -}; - -export default RoleColor; diff --git a/src/components/RoleColor/index.tsx b/src/components/RoleColor/index.tsx new file mode 100644 index 000000000..3ce566263 --- /dev/null +++ b/src/components/RoleColor/index.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { useSelector } from '../../hooks/useRedux'; +import { roleColorsSelector } from '../../selectors/configSelectors'; + +type RoleColorProps<Base extends React.ElementType = 'span'> = React.ComponentPropsWithoutRef<Base> & { + component?: Base, + roles: string[], +} + +function RoleColor({ + component: Component = 'span', + roles, + ...props +}: RoleColorProps) { + const colors: Record<string, string> = useSelector(roleColorsSelector); + + const firstRoleWithColor = roles.find((r) => colors[r]); + + const style = { + color: colors[firstRoleWithColor ?? 'default'], + }; + + return <Component {...props} style={style} />; +} + +export default RoleColor; diff --git a/src/components/RoomHistory/AddToPlaylistAction.jsx b/src/components/RoomHistory/AddToPlaylistAction.jsx index b6cb0eb7b..261c4ddc5 100644 --- a/src/components/RoomHistory/AddToPlaylistAction.jsx +++ b/src/components/RoomHistory/AddToPlaylistAction.jsx @@ -1,8 +1,8 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { mdiPlus } from '@mdi/js'; -import { addMediaMenu } from '../../actions/PlaylistActionCreators'; +import { useDispatch } from '../../hooks/useRedux'; +import { open as addMediaMenu } from '../../reducers/addToPlaylistMenu'; import { useMediaListContext } from '../MediaList/BaseMediaList'; import MediaAction from '../MediaList/MediaAction'; import SvgIcon from '../SvgIcon'; @@ -25,9 +25,10 @@ function AddToPlaylistAction({ historyEntry }) { const selectedItems = selection.isSelected(historyEntry) ? selection.get() : [historyEntry]; const rect = event.target.getBoundingClientRect(); - dispatch(addMediaMenu(selectedItems.map((entry) => entry.media), { - x: rect.left, - y: rect.top, + dispatch(addMediaMenu({ + type: 'add', + position: { x: rect.left, y: rect.top }, + data: { media: selectedItems.map((entry) => entry.media) }, })); }, [dispatch, selection, historyEntry]); diff --git a/src/components/RoomHistory/HistoryActions.jsx b/src/components/RoomHistory/HistoryActions.jsx index 47daa37ed..de6dd08a5 100644 --- a/src/components/RoomHistory/HistoryActions.jsx +++ b/src/components/RoomHistory/HistoryActions.jsx @@ -1,7 +1,7 @@ import cx from 'clsx'; import React from 'react'; import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; +import { useSelector } from '../../hooks/useRedux'; import { isLoggedInSelector } from '../../selectors/userSelectors'; import PreviewMediaAction from '../MediaList/PreviewMediaAction'; import AddToPlaylistAction from './AddToPlaylistAction'; diff --git a/src/components/RoomHistory/HistoryList.jsx b/src/components/RoomHistory/HistoryList.tsx similarity index 65% rename from src/components/RoomHistory/HistoryList.jsx rename to src/components/RoomHistory/HistoryList.tsx index 86ed2939a..261539813 100644 --- a/src/components/RoomHistory/HistoryList.jsx +++ b/src/components/RoomHistory/HistoryList.tsx @@ -1,14 +1,16 @@ -import React from 'react'; import MediaListBase from '../MediaList/BaseMediaList'; import HistoryRow from './Row'; +import useRoomHistory from '../../hooks/useRoomHistory'; + +function HistoryList() { + const media = useRoomHistory(); -function HistoryList(props) { return ( <MediaListBase className="RoomHistory-list" listComponent="div" rowComponent={HistoryRow} - {...props} + media={media} /> ); } diff --git a/src/components/RoomHistory/Row.jsx b/src/components/RoomHistory/Row.tsx similarity index 86% rename from src/components/RoomHistory/Row.jsx rename to src/components/RoomHistory/Row.tsx index 25753200c..48f796580 100644 --- a/src/components/RoomHistory/Row.jsx +++ b/src/components/RoomHistory/Row.tsx @@ -1,6 +1,5 @@ import cx from 'clsx'; import React from 'react'; -import PropTypes from 'prop-types'; import { HISTORY_ENTRY } from '../../constants/DDItemTypes'; import MediaRowBase from '../MediaList/MediaRowBase'; import MediaSourceIcon from '../MediaList/MediaSourceIcon'; @@ -9,18 +8,25 @@ import SongTitle from '../SongTitle'; import TimeAgo from '../TimeAgo'; import HistoryActions from './HistoryActions'; import HistoryVotes from './Votes'; +import { HistoryEntry } from '../../hooks/useRoomHistory'; const { useCallback, useState, } = React; +type HistoryRowProps = { + className?: string, + style?: React.CSSProperties, + media: HistoryEntry, + onClick?: (event?: React.MouseEvent) => void, +}; function HistoryRow({ className, style, media: historyEntry, onClick, -}) { +}: HistoryRowProps) { const { media, timestamp, user, stats, } = historyEntry; @@ -38,7 +44,7 @@ function HistoryRow({ return ( <MediaRowBase dragType={HISTORY_ENTRY} - media={historyEntry} + media={{ ...media, _id: historyEntry._id }} className={cx('HistoryRow', className)} style={style} onMouseEnter={handleMouseEnter} @@ -73,11 +79,4 @@ function HistoryRow({ ); } -HistoryRow.propTypes = { - className: PropTypes.string, - style: PropTypes.object, // for virtual list positioning - media: PropTypes.object.isRequired, - onClick: PropTypes.func.isRequired, -}; - export default HistoryRow; diff --git a/src/components/RoomHistory/Votes.jsx b/src/components/RoomHistory/Votes.jsx index ce2649189..2b8fa8a8b 100644 --- a/src/components/RoomHistory/Votes.jsx +++ b/src/components/RoomHistory/Votes.jsx @@ -1,14 +1,17 @@ import cx from 'clsx'; -import React from 'react'; import PropTypes from 'prop-types'; import { mdiHeart, mdiHeartOutline, mdiThumbDown, mdiThumbUp, } from '@mdi/js'; import SvgIcon from '../SvgIcon'; +import useCurrentUser from '../../hooks/useCurrentUser'; + +function Votes({ upvotes, downvotes, favorites }) { + const user = useCurrentUser(); + const isUpvote = user ? upvotes.includes(user._id) : false; + const isDownvote = user ? downvotes.includes(user._id) : false; + const isFavorite = user ? favorites.includes(user._id) : false; -function Votes({ - upvotes, downvotes, favorites, isUpvote, isDownvote, isFavorite, -}) { return ( <div className="HistoryVotes AudienceResponse"> <div className="ResponseButton ResponseButton--static"> @@ -40,9 +43,6 @@ Votes.propTypes = { upvotes: PropTypes.array.isRequired, favorites: PropTypes.array.isRequired, downvotes: PropTypes.array.isRequired, - isUpvote: PropTypes.bool.isRequired, - isFavorite: PropTypes.bool.isRequired, - isDownvote: PropTypes.bool.isRequired, }; -export default React.memo(Votes); +export default Votes; diff --git a/src/components/RoomHistory/index.jsx b/src/components/RoomHistory/index.tsx similarity index 69% rename from src/components/RoomHistory/index.jsx rename to src/components/RoomHistory/index.tsx index 778e93235..14aa244ae 100644 --- a/src/components/RoomHistory/index.jsx +++ b/src/components/RoomHistory/index.tsx @@ -1,12 +1,14 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import OverlayHeader from '../Overlay/Header'; import OverlayContent from '../Overlay/Content'; import HistoryList from './HistoryList'; -function RoomHistory({ className, onCloseOverlay, ...props }) { +type RoomHistoryProps = { + className?: string, + onCloseOverlay: () => void, +}; +function RoomHistory({ className, onCloseOverlay }: RoomHistoryProps) { const { t } = useTranslator(); return ( @@ -18,15 +20,10 @@ function RoomHistory({ className, onCloseOverlay, ...props }) { onCloseOverlay={onCloseOverlay} /> <OverlayContent className="RoomHistory-body"> - <HistoryList {...props} /> + <HistoryList /> </OverlayContent> </div> ); } -RoomHistory.propTypes = { - className: PropTypes.string, - onCloseOverlay: PropTypes.func.isRequired, -}; - export default RoomHistory; diff --git a/src/components/RoomUserList/GuestsRow.jsx b/src/components/RoomUserList/GuestsRow.tsx similarity index 68% rename from src/components/RoomUserList/GuestsRow.jsx rename to src/components/RoomUserList/GuestsRow.tsx index 712d6bba7..400463974 100644 --- a/src/components/RoomUserList/GuestsRow.jsx +++ b/src/components/RoomUserList/GuestsRow.tsx @@ -1,11 +1,14 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import { useTranslator } from '@u-wave/react-translate'; -function GuestsRow({ className, guests, style }) { +type GuestsRowProps = { + className?: string, + style?: React.CSSProperties, + guests: number, +}; +function GuestsRow({ className, guests, style }: GuestsRowProps) { const { t } = useTranslator(); return ( @@ -18,10 +21,4 @@ function GuestsRow({ className, guests, style }) { ); } -GuestsRow.propTypes = { - className: PropTypes.string, - guests: PropTypes.number.isRequired, - style: PropTypes.object, -}; - export default GuestsRow; diff --git a/src/components/RoomUserList/Row.jsx b/src/components/RoomUserList/Row.tsx similarity index 50% rename from src/components/RoomUserList/Row.jsx rename to src/components/RoomUserList/Row.tsx index d18bd3d6b..b72ed4fb2 100644 --- a/src/components/RoomUserList/Row.jsx +++ b/src/components/RoomUserList/Row.tsx @@ -1,19 +1,31 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useCallback } from 'react'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemAvatar from '@mui/material/ListItemAvatar'; import ListItemText from '@mui/material/ListItemText'; +import { mdiHeart, mdiThumbDown, mdiThumbUp } from '@mdi/js'; import useUserCard from '../../hooks/useUserCard'; import Avatar from '../Avatar'; import Username from '../Username'; -import Votes from './Votes'; +import SvgIcon from '../SvgIcon'; +import { User } from '../../reducers/users'; -const { useCallback } = React; +export interface RoomUser extends User { + votes: { + upvote: boolean, + downvote: boolean, + favorite: boolean, + }, +} -function RoomUserRow({ className, user, style }) { +type RoomUserRowProps = { + className?: string, + style?: React.CSSProperties, + user: RoomUser, +}; +function RoomUserRow({ className, user, style }: RoomUserRowProps) { const userCard = useUserCard(user); - const onOpenCard = useCallback((event) => { + const onOpenCard = useCallback((event: React.MouseEvent) => { event.preventDefault(); userCard.open(); // The `userCard.open` reference never changes. @@ -35,16 +47,20 @@ function RoomUserRow({ className, user, style }) { <ListItemText> <Username className="UserRow-username" user={user} /> </ListItemText> - <Votes className="UserRow-votes" {...user.votes} /> + <div className="UserRow-votes"> + {user.votes.favorite && ( + <SvgIcon path={mdiHeart} className="UserRow-voteIcon UserRow-voteIcon--favorite" /> + )} + {user.votes.upvote && ( + <SvgIcon path={mdiThumbUp} className="UserRow-voteIcon UserRow-voteIcon--upvote" /> + )} + {user.votes.downvote && ( + <SvgIcon path={mdiThumbDown} className="UserRow-voteIcon UserRow-voteIcon--downvote" /> + )} + </div> </ListItemButton> </> ); } -RoomUserRow.propTypes = { - className: PropTypes.string, - user: PropTypes.object.isRequired, - style: PropTypes.object, -}; - export default RoomUserRow; diff --git a/src/components/RoomUserList/Votes.jsx b/src/components/RoomUserList/Votes.jsx deleted file mode 100644 index 6c1082a8b..000000000 --- a/src/components/RoomUserList/Votes.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { mdiHeart, mdiThumbDown, mdiThumbUp } from '@mdi/js'; -import SvgIcon from '../SvgIcon'; - -const Votes = ({ - upvote, downvote, favorite, ...props -}) => ( - <div {...props}> - {favorite && ( - <SvgIcon path={mdiHeart} className="UserRow-voteIcon UserRow-voteIcon--favorite" /> - )} - {upvote && ( - <SvgIcon path={mdiThumbUp} className="UserRow-voteIcon UserRow-voteIcon--upvote" /> - )} - {downvote && ( - <SvgIcon path={mdiThumbDown} className="UserRow-voteIcon UserRow-voteIcon--downvote" /> - )} - </div> -); - -Votes.propTypes = { - upvote: PropTypes.bool, - downvote: PropTypes.bool, - favorite: PropTypes.bool, -}; - -export default Votes; diff --git a/src/components/RoomUserList/index.jsx b/src/components/RoomUserList/index.tsx similarity index 74% rename from src/components/RoomUserList/index.jsx rename to src/components/RoomUserList/index.tsx index 96153f4aa..f78cd7bf9 100644 --- a/src/components/RoomUserList/index.jsx +++ b/src/components/RoomUserList/index.tsx @@ -1,26 +1,26 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useRef } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; -import RoomUserRow from './Row'; +import RoomUserRow, { RoomUser } from './Row'; import GuestsRow from './GuestsRow'; -const { - useRef, -} = React; - function estimateSize() { return 40; } -function RoomUserList({ className, users, guests }) { - const parentRef = useRef(); +type RoomUserListProps = { + className?: string, + users: RoomUser[], + guests: number, +}; +function RoomUserList({ className, users, guests }: RoomUserListProps) { + const parentRef = useRef<HTMLDivElement>(null); const showGuests = guests > 0; // The "and X guests" row is implemented somewhat hackily as an extra user // row. To render properly at the end of the list, it needs to be rendered as - // an element of the list--so we tell react-list that we have an extra row - // when th guests row is shown. + // an element of the list--so we tell react-virtual that we have an extra row + // when the guests row is shown. const length = users.length + (showGuests ? 1 : 0); const virtualizer = useVirtualizer({ @@ -50,12 +50,14 @@ function RoomUserList({ className, users, guests }) { /> ); } + + const user = users[index]!; return ( <RoomUserRow - key={users[index]._id} + key={user._id} className={rowClass} style={style} - user={users[index]} + user={user} /> ); })} @@ -64,10 +66,4 @@ function RoomUserList({ className, users, guests }) { ); } -RoomUserList.propTypes = { - className: PropTypes.string, - users: PropTypes.arrayOf(PropTypes.object).isRequired, - guests: PropTypes.number.isRequired, -}; - export default RoomUserList; diff --git a/src/components/SearchBar/index.jsx b/src/components/SearchBar/index.tsx similarity index 78% rename from src/components/SearchBar/index.jsx rename to src/components/SearchBar/index.tsx index 7244217e2..0b44a8107 100644 --- a/src/components/SearchBar/index.jsx +++ b/src/components/SearchBar/index.tsx @@ -1,28 +1,32 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { useTranslator } from '@u-wave/react-translate'; -import { mdiMagnify } from '@mdi/js'; -import SvgIcon from '../SvgIcon'; - -const { +import { useCallback, useEffect, useRef, useState, -} = React; +} from 'react'; +import { useTranslator } from '@u-wave/react-translate'; +import { mdiMagnify } from '@mdi/js'; +import SvgIcon from '../SvgIcon'; + +type SearchBarProps = { + children: React.ReactNode, + className?: string, + autoFocus?: boolean, + onSubmit: (value: string) => void, +}; function SearchBar({ children, className, autoFocus, onSubmit, -}) { +}: SearchBarProps) { const { t } = useTranslator(); - const inputRef = useRef(null); + const inputRef = useRef<HTMLInputElement>(null); const [focused, setFocused] = useState(false); const handleFocus = useCallback(() => setFocused(true), [setFocused]); const handleBlur = useCallback(() => setFocused(false), [setFocused]); - const handleKeyDown = useCallback((event) => { + const handleKeyDown = useCallback((event: React.KeyboardEvent<HTMLInputElement>) => { if (event.key === 'Enter') { - onSubmit(event.target.value); + onSubmit(event.currentTarget.value); } }, [onSubmit]); @@ -30,7 +34,6 @@ function SearchBar({ if (autoFocus && inputRef.current) { inputRef.current.focus(); } - return () => null; // `autoFocus` is only checked on mount on purpose. // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -57,11 +60,4 @@ function SearchBar({ ); } -SearchBar.propTypes = { - className: PropTypes.string, - children: PropTypes.node, - autoFocus: PropTypes.bool, - onSubmit: PropTypes.func.isRequired, -}; - export default SearchBar; diff --git a/src/components/SettingsManager/LanguagePicker.jsx b/src/components/SettingsManager/LanguagePicker.jsx index eae109b67..32002f8be 100644 --- a/src/components/SettingsManager/LanguagePicker.jsx +++ b/src/components/SettingsManager/LanguagePicker.jsx @@ -2,7 +2,7 @@ import React from 'react'; import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { useTranslator } from '@u-wave/react-translate'; -import { useSelector } from 'react-redux'; +import { useSelector } from '../../hooks/useRedux'; import { availableLanguagesSelector } from '../../selectors/localeSelectors'; function LanguagePicker(props) { diff --git a/src/components/SettingsManager/NotificationSettings.jsx b/src/components/SettingsManager/NotificationSettings.jsx index a7812cd42..9fe4b792c 100644 --- a/src/components/SettingsManager/NotificationSettings.jsx +++ b/src/components/SettingsManager/NotificationSettings.jsx @@ -4,11 +4,13 @@ import { useTranslator } from '@u-wave/react-translate'; import FormGroup from '@mui/material/FormGroup'; import Switch from '@mui/material/Switch'; import SettingControl from './SettingControl'; +import { useSelector } from '../../hooks/useRedux'; const { useCallback } = React; -function NotificationSettings({ settings, onSettingChange }) { +function NotificationSettings({ onSettingChange }) { const { t } = useTranslator(); + const notifications = useSelector((state) => state.settings.notifications); function useToggleSetting(name) { return useCallback((event) => { @@ -31,28 +33,28 @@ function NotificationSettings({ settings, onSettingChange }) { <SettingControl label={t('settings.notifications.userJoin')}> <Switch color="primary" - checked={settings.notifications.userJoin} + checked={notifications.userJoin} onChange={onToggleUserJoin} /> </SettingControl> <SettingControl label={t('settings.notifications.userLeave')}> <Switch color="primary" - checked={settings.notifications.userLeave} + checked={notifications.userLeave} onChange={onToggleUserLeave} /> </SettingControl> <SettingControl label={t('settings.notifications.userNameChanged')}> <Switch color="primary" - checked={settings.notifications.userNameChanged} + checked={notifications.userNameChanged} onChange={onToggleUserNameChanged} /> </SettingControl> <SettingControl label={t('settings.notifications.skip')}> <Switch color="primary" - checked={settings.notifications.skip} + checked={notifications.skip} onChange={onToggleSkip} /> </SettingControl> @@ -62,7 +64,6 @@ function NotificationSettings({ settings, onSettingChange }) { } NotificationSettings.propTypes = { - settings: PropTypes.object.isRequired, onSettingChange: PropTypes.func.isRequired, }; diff --git a/src/components/SettingsManager/SettingsPanel.jsx b/src/components/SettingsManager/SettingsPanel.jsx index 14a5197a5..f4b322710 100644 --- a/src/components/SettingsManager/SettingsPanel.jsx +++ b/src/components/SettingsManager/SettingsPanel.jsx @@ -1,5 +1,4 @@ import cx from 'clsx'; -import React from 'react'; import PropTypes from 'prop-types'; import { useTranslator } from '@u-wave/react-translate'; import useMediaQuery from '@mui/material/useMediaQuery'; @@ -11,30 +10,49 @@ import LanguagePicker from './LanguagePicker'; import LogoutButton from './LogoutButton'; import NotificationSettings from './NotificationSettings'; import Links from './Links'; +import { useDispatch, useSelector } from '../../hooks/useRedux'; +import { + languageSelector, + mentionSoundEnabledSelector, + videoEnabledSelector, + videoSizeSelector, + setVideoEnabled, + setVideoSize, + setMentionSoundEnabled, + setLanguage, + set, +} from '../../reducers/settings'; +import useCurrentUser from '../../hooks/useCurrentUser'; function SettingsPanel({ className, - settings, - user, - onSettingChange, onChangeUsername, - onChangeLanguage, onLogout, }) { const { t } = useTranslator(); const isWide = useMediaQuery((theme) => theme.breakpoints.up('lg')); + const user = useCurrentUser(); + const dispatch = useDispatch(); + const videoEnabled = useSelector(videoEnabledSelector); + const videoSize = useSelector(videoSizeSelector); + const mentionSoundEnabled = useSelector(mentionSoundEnabledSelector); + const language = useSelector(languageSelector); + const handleVideoEnabledChange = (event) => { - onSettingChange('videoEnabled', event.target.checked); + dispatch(setVideoEnabled(event.target.checked)); }; const handleVideoSizeChange = (event) => { - onSettingChange('videoSize', event.target.checked ? 'large' : 'small'); + dispatch(setVideoSize(event.target.checked ? 'large' : 'small')); }; const handleMentionSoundChange = (event) => { - onSettingChange('mentionSound', event.target.checked); + dispatch(setMentionSoundEnabled(event.target.checked)); }; const handleLanguageChange = (event) => { - onChangeLanguage(event.target.value); + dispatch(setLanguage(event.target.value)); + }; + const handleSettingChange = (name, value) => { + dispatch(set(name, value)); }; const profileSection = user && ( @@ -53,27 +71,27 @@ function SettingsPanel({ > <Switch color="primary" - checked={settings.videoEnabled} + checked={videoEnabled} onChange={handleVideoEnabledChange} /> </SettingControl> <SettingControl label={t('settings.videoSize')}> <Switch color="primary" - checked={settings.videoSize === 'large'} + checked={videoSize === 'large'} onChange={handleVideoSizeChange} /> </SettingControl> <SettingControl label={t('settings.mentionSound')}> <Switch color="primary" - checked={settings.mentionSound} + checked={mentionSoundEnabled} onChange={handleMentionSoundChange} /> </SettingControl> <SettingControl label={t('settings.language')}> <LanguagePicker - value={settings.language} + value={language} onChange={handleLanguageChange} /> </SettingControl> @@ -95,7 +113,7 @@ function SettingsPanel({ const notificationsSection = ( <div key="notifications" className="SettingsPanel-section SettingsPanel-notificationSettings"> - <NotificationSettings settings={settings} onSettingChange={onSettingChange} /> + <NotificationSettings onSettingChange={handleSettingChange} /> </div> ); @@ -130,11 +148,7 @@ function SettingsPanel({ SettingsPanel.propTypes = { className: PropTypes.string, - settings: PropTypes.object.isRequired, - user: PropTypes.object, - onSettingChange: PropTypes.func.isRequired, onChangeUsername: PropTypes.func.isRequired, - onChangeLanguage: PropTypes.func.isRequired, onLogout: PropTypes.func.isRequired, }; diff --git a/src/components/SettingsManager/index.jsx b/src/components/SettingsManager/index.jsx index 3e33d660c..0188ebf54 100644 --- a/src/components/SettingsManager/index.jsx +++ b/src/components/SettingsManager/index.jsx @@ -7,7 +7,7 @@ import OverlayContent from '../Overlay/Content'; import SettingsPanel from './SettingsPanel'; function SettingsManager({ - className, + className = null, onCloseOverlay, onLogout, ...props diff --git a/src/components/SidePanels/index.jsx b/src/components/SidePanels/index.jsx index 8b3b739c8..405bf8534 100644 --- a/src/components/SidePanels/index.jsx +++ b/src/components/SidePanels/index.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import { useSelector } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import Tabs from '@mui/material/Tabs'; import Tab from '@mui/material/Tab'; +import { useSelector } from '../../hooks/useRedux'; import Chat from '../Chat'; import RoomUserList from '../../containers/RoomUserList'; import WaitList from '../../containers/WaitList'; diff --git a/src/components/SongTitle/index.jsx b/src/components/SongTitle/index.jsx deleted file mode 100644 index 80ea417c1..000000000 --- a/src/components/SongTitle/index.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; - -const SongTitle = ({ - className, artist, title, size = 'large', -}) => ( - <div - className={cx('SongTitle', `SongTitle--${size}`, className)} - title={`${artist} – ${title}`} - > - <span className="SongTitle-artist">{artist}</span> - <span className="SongTitle-separator"> – </span> - <span className="SongTitle-title">{title}</span> - </div> -); - -SongTitle.propTypes = { - className: PropTypes.string, - artist: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - size: PropTypes.string, -}; - -export default React.memo(SongTitle); diff --git a/src/components/SongTitle/index.tsx b/src/components/SongTitle/index.tsx new file mode 100644 index 000000000..7d41bbcd7 --- /dev/null +++ b/src/components/SongTitle/index.tsx @@ -0,0 +1,32 @@ +import cx from 'clsx'; +import React from 'react'; + +type SongTitleProps = { + className?: string, + artist: React.ReactNode, + title: React.ReactNode, + size?: 'large' | 'mediaRow', +}; + +function SongTitle({ + className, + artist, + title, + size = 'large', +}: SongTitleProps) { + const hoverTitle = typeof artist === 'string' && typeof title === 'string' + ? `${artist} – ${title}` : undefined; + + return ( + <div + className={cx('SongTitle', `SongTitle--${size}`, className)} + title={hoverTitle} + > + <span className="SongTitle-artist">{artist}</span> + <span className="SongTitle-separator"> – </span> + <span className="SongTitle-title">{title}</span> + </div> + ); +} + +export default React.memo(SongTitle); diff --git a/src/components/SvgIcon/index.css b/src/components/SvgIcon/index.css index f2d7dde2f..778297676 100644 --- a/src/components/SvgIcon/index.css +++ b/src/components/SvgIcon/index.css @@ -2,6 +2,6 @@ display: inline-block; width: 1em; height: 1em; - fill: currentColor; + fill: currentcolor; font-size: 1.5rem; } diff --git a/src/components/SvgIcon/index.jsx b/src/components/SvgIcon/index.tsx similarity index 66% rename from src/components/SvgIcon/index.jsx rename to src/components/SvgIcon/index.tsx index 65bd6e7bb..a8c80edb3 100644 --- a/src/components/SvgIcon/index.jsx +++ b/src/components/SvgIcon/index.tsx @@ -1,13 +1,16 @@ import cx from 'clsx'; import React from 'react'; -import PropTypes from 'prop-types'; + +export interface SvgIconProps extends React.ComponentProps<'svg'> { + path?: string; +} function SvgIcon({ className, children, path, ...props -}) { +}: SvgIconProps) { return ( <svg viewBox="0 0 24 24" className={cx('SvgIcon', className)} {...props}> {children ?? <path d={path} />} @@ -15,10 +18,4 @@ function SvgIcon({ ); } -SvgIcon.propTypes = { - className: PropTypes.string, - path: PropTypes.string, - children: PropTypes.node, -}; - export default React.memo(SvgIcon); diff --git a/src/components/TimeAgo/index.jsx b/src/components/TimeAgo/index.tsx similarity index 70% rename from src/components/TimeAgo/index.jsx rename to src/components/TimeAgo/index.tsx index 1561a283c..fdc8843b6 100644 --- a/src/components/TimeAgo/index.jsx +++ b/src/components/TimeAgo/index.tsx @@ -1,5 +1,3 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import ms from 'ms'; import { useTranslator } from '@u-wave/react-translate'; import useClock from '../../hooks/useClock'; @@ -7,18 +5,21 @@ import useIntl from '../../hooks/useIntl'; // Bit weird to do it like this perhaps, convert to an english string first and // then translate afterwards. -function translateMs(str) { - // `ms` output of the form "3 hours" - const [count, key] = str.split(' '); +function translateMs(str: string) { + // `ms` output always of the form "3 hours" + const [count, key] = str.split(' ') as [string, string]; return { - key: key.replace(/s$/, ''), + key: key.replace(/s$/, '') as 'day' | 'hour' | 'minute' | 'second', count: parseInt(count, 10), }; } -const now = { key: 'seconds', count: 0 }; +const now = { key: 'second' as const, count: 0 }; -function TimeAgo({ timestamp }) { +type TimeAgoProps = { + timestamp: number, +}; +function TimeAgo({ timestamp }: TimeAgoProps) { const { t } = useTranslator(); const { relativeTimeFormatter } = useIntl(); const currentTime = useClock(); @@ -29,26 +30,22 @@ function TimeAgo({ timestamp }) { if (relativeTimeFormatter) { return ( - <span> + <> {relativeTimeFormatter.format(-count, key)} - </span> + </> ); } return ( - <span> + <> {t('timeAgo.format', { time: t(`timeAgo.${key}`, { count, defaultValue: msString, }), })} - </span> + </> ); } -TimeAgo.propTypes = { - timestamp: PropTypes.number.isRequired, -}; - export default TimeAgo; diff --git a/src/components/UserCard/AddToWaitlistButton.jsx b/src/components/UserCard/AddToWaitlistButton.jsx index 7dce2f274..951b78f7c 100644 --- a/src/components/UserCard/AddToWaitlistButton.jsx +++ b/src/components/UserCard/AddToWaitlistButton.jsx @@ -1,10 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import SvgIcon from '../SvgIcon'; +import { useDispatch } from '../../hooks/useRedux'; import { joinWaitlist } from '../../actions/WaitlistActionCreators'; const { useCallback } = React; diff --git a/src/components/UserCard/BanButton.jsx b/src/components/UserCard/BanButton.jsx index fd99512dc..d6772781c 100644 --- a/src/components/UserCard/BanButton.jsx +++ b/src/components/UserCard/BanButton.jsx @@ -1,10 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import { mdiCancel } from '@mdi/js'; +import { useDispatch } from '../../hooks/useRedux'; import SvgIcon from '../SvgIcon'; import { banUser } from '../../actions/ModerationActionCreators'; diff --git a/src/components/UserCard/RemoveFromWaitlistButton.jsx b/src/components/UserCard/RemoveFromWaitlistButton.jsx index f84557c41..77aa3243d 100644 --- a/src/components/UserCard/RemoveFromWaitlistButton.jsx +++ b/src/components/UserCard/RemoveFromWaitlistButton.jsx @@ -1,10 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import SvgIcon from '../SvgIcon'; +import { useDispatch } from '../../hooks/useRedux'; import { removeWaitlistUser } from '../../actions/ModerationActionCreators'; const { useCallback } = React; diff --git a/src/components/UserCard/UserCard.jsx b/src/components/UserCard/UserCard.jsx index 074d65e75..2452258b6 100644 --- a/src/components/UserCard/UserCard.jsx +++ b/src/components/UserCard/UserCard.jsx @@ -1,12 +1,12 @@ import React from 'react'; import cx from 'clsx'; import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; import Typography from '@mui/material/Typography'; import Card from '@mui/material/Card/Card'; import CardHeader from '@mui/material/CardHeader'; import CardActions from '@mui/material/CardActions'; import CardContent from '@mui/material/CardContent'; +import { useSelector } from '../../hooks/useRedux'; import useIntl from '../../hooks/useIntl'; import useHasRole from '../../hooks/useHasRole'; import { djSelector } from '../../selectors/boothSelectors'; diff --git a/src/components/UserList/UserRow.jsx b/src/components/UserList/UserRow.jsx deleted file mode 100644 index 0b4fac613..000000000 --- a/src/components/UserList/UserRow.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import Avatar from '../Avatar'; -import Username from '../Username'; - -const UserRow = ({ className, user }) => ( - <div className={cx('UserRow', className)}> - <Avatar - className="UserRow-avatar" - user={user} - /> - <Username className="UserRow-username" user={user} /> - </div> -); - -UserRow.propTypes = { - className: PropTypes.string, - user: PropTypes.object.isRequired, -}; - -export default UserRow; diff --git a/src/components/UserList/UserRow.tsx b/src/components/UserList/UserRow.tsx new file mode 100644 index 000000000..c14386f29 --- /dev/null +++ b/src/components/UserList/UserRow.tsx @@ -0,0 +1,22 @@ +import cx from 'clsx'; +import Avatar from '../Avatar'; +import Username from '../Username'; +import { User } from '../../reducers/users'; + +type UserRowProps = { + className?: string, + user: User, +}; +function UserRow({ className, user }: UserRowProps) { + return ( + <div className={cx('UserRow', className)}> + <Avatar + className="UserRow-avatar" + user={user} + /> + <Username className="UserRow-username" user={user} /> + </div> + ); +} + +export default UserRow; diff --git a/src/components/UserRole/index.jsx b/src/components/UserRole/index.jsx index 99bf3077a..1e87169a4 100644 --- a/src/components/UserRole/index.jsx +++ b/src/components/UserRole/index.jsx @@ -16,7 +16,7 @@ function UserRole({ roleName }) { } return ( - <RoleColor component="div" className="UserRole" role={roleName}> + <RoleColor component="div" className="UserRole" roles={[roleName]}> {name} </RoleColor> ); diff --git a/src/components/Username/index.jsx b/src/components/Username/index.jsx deleted file mode 100644 index 32ad17aeb..000000000 --- a/src/components/Username/index.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import RoleColor from '../RoleColor'; - -const Username = ({ className, user }) => ( - <RoleColor className={cx('Username', className)} roles={user.roles}> - {user.username} - </RoleColor> -); - -Username.propTypes = { - className: PropTypes.string, - user: PropTypes.shape({ - username: PropTypes.string, - roles: PropTypes.arrayOf(PropTypes.string), - }).isRequired, -}; - -export default React.memo(Username); diff --git a/src/components/Username/index.tsx b/src/components/Username/index.tsx new file mode 100644 index 000000000..1fc4fbe66 --- /dev/null +++ b/src/components/Username/index.tsx @@ -0,0 +1,21 @@ +import cx from 'clsx'; +import React from 'react'; +import RoleColor from '../RoleColor'; + +type UsernameProps = { + className?: string, + user: { + roles: string[], + username: string, + }, +}; + +function Username({ className, user }: UsernameProps) { + return ( + <RoleColor className={cx('Username', className)} roles={user.roles}> + {user.username} + </RoleColor> + ); +} + +export default React.memo(Username); diff --git a/src/components/Video/Player.jsx b/src/components/Video/Player.jsx deleted file mode 100644 index a5a00ee6b..000000000 --- a/src/components/Video/Player.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useMediaSources } from '../../context/MediaSourceContext'; - -const PreviewPlayer = ({ - media, - seek = 0, - ...props -}) => { - const { getMediaSource } = useMediaSources(); - - const { Player } = getMediaSource(media.sourceType); - return ( - <Player - enabled - active - seek={seek} - media={media} - {...props} - /> - ); -}; - -PreviewPlayer.propTypes = { - media: PropTypes.object.isRequired, - seek: PropTypes.number, -}; - -export default PreviewPlayer; diff --git a/src/components/Video/Player.tsx b/src/components/Video/Player.tsx new file mode 100644 index 000000000..c123de379 --- /dev/null +++ b/src/components/Video/Player.tsx @@ -0,0 +1,36 @@ +import { useMediaSources } from '../../context/MediaSourceContext'; +import { Media } from '../../reducers/booth'; + +type PreviewPlayerProps = { + media: Media, + seek?: number, + volume: number, + isMuted: boolean, +}; +function PreviewPlayer({ + media, + seek = 0, + volume, + isMuted, +}: PreviewPlayerProps) { + const { getMediaSource } = useMediaSources(); + const source = getMediaSource(media.sourceType); + if (!source) { + return <p>Player for {media.sourceType} unavailable</p>; + } + + const { Player } = source; + + return ( + <Player + enabled + active + seek={seek} + media={media} + volume={isMuted ? 0 : volume} + mode="preview" + /> + ); +} + +export default PreviewPlayer; diff --git a/src/components/Video/VideoSizeButton.jsx b/src/components/Video/VideoSizeButton.jsx index d0d4fcddb..9d8f751aa 100644 --- a/src/components/Video/VideoSizeButton.jsx +++ b/src/components/Video/VideoSizeButton.jsx @@ -1,11 +1,10 @@ import React from 'react'; import { useTranslator } from '@u-wave/react-translate'; -import { useDispatch, useSelector } from 'react-redux'; import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import SvgIcon from '@mui/material/SvgIcon'; -import { videoSizeSelector } from '../../selectors/settingSelectors'; -import { toggleVideoSize } from '../../actions/PlaybackActionCreators'; +import { useDispatch, useSelector } from '../../hooks/useRedux'; +import { toggleVideoSize, videoSizeSelector } from '../../reducers/settings'; // Stolen from YouTube const paths = { diff --git a/src/components/Video/index.css b/src/components/Video/index.css index 8e89eaf82..76caaf805 100644 --- a/src/components/Video/index.css +++ b/src/components/Video/index.css @@ -14,10 +14,7 @@ } .Video-capture { - top: 0; - right: 0; - left: 0; - bottom: 0; + inset: 0; } .Video-progress { @@ -33,7 +30,7 @@ visibility: hidden; /* Only show the toolbar on hover. */ - @nest .Video:hover & { + .Video:hover & { visibility: visible; } } diff --git a/src/components/Video/index.jsx b/src/components/Video/index.tsx similarity index 76% rename from src/components/Video/index.jsx rename to src/components/Video/index.tsx index 1ad82c918..d36cc26ad 100644 --- a/src/components/Video/index.jsx +++ b/src/components/Video/index.tsx @@ -1,14 +1,14 @@ import cx from 'clsx'; import React from 'react'; -import { useSelector } from 'react-redux'; -import PropTypes from 'prop-types'; import screenfull from 'screenfull'; -import { useMediaSources } from '../../context/MediaSourceContext'; +import { useSelector } from '../../hooks/useRedux'; import VideoBackdrop from './VideoBackdrop'; import VideoProgressBar from './VideoProgressBar'; import VideoToolbar from './VideoToolbar'; import MouseMoveCapture from './VideoMouseMoveCapture'; import Player from '../Player'; +import { selectOverlay } from '../../reducers/activeOverlay'; +import { Media } from '../../reducers/booth'; // Overlays over the video (even tiny in the corner like ours) violate TOS, // so we can not show them. Toggling it off with a conditional for now until @@ -22,9 +22,20 @@ const { useState, } = React; -const defaultSourceTools = () => null; - -function Video(props) { +type VideoProps = { + isFullscreen: boolean, + enabled: boolean, + size: string, + volume: number, + isMuted: boolean, + media: Media, + seek: number, + onFullscreenEnter: () => void, + onFullscreenExit: () => void, +} +// TODO the split between this and Player is a bit weird +// could use a rethink (and a rename) +function Video(props: VideoProps) { const { isFullscreen, enabled, @@ -37,14 +48,13 @@ function Video(props) { onFullscreenExit, } = props; - const { getMediaSource } = useMediaSources(); const [shouldShowToolbar, setShowToolbar] = useState(false); - const activeOverlay = useSelector((state) => state.activeOverlay); - const container = useRef(null); - const timer = useRef(null); + const activeOverlay = useSelector(selectOverlay); + const container = useRef<HTMLDivElement>(null); + const timer = useRef<ReturnType<typeof setTimeout> | null>(null); const handleRequestFullscreenEnter = useCallback(() => { - if (screenfull.isEnabled) { + if (screenfull.isEnabled && container.current) { screenfull.request(container.current); } onFullscreenEnter(); @@ -57,7 +67,9 @@ function Video(props) { }, [onFullscreenExit]); const handleMouseMoveEnd = useCallback(() => { - clearTimeout(timer.current); + if (timer.current) { + clearTimeout(timer.current); + } timer.current = null; setShowToolbar(false); }, []); @@ -97,11 +109,6 @@ function Video(props) { return <div className="Video" />; } - const currentSource = getMediaSource(media.sourceType); - const MediaSourceTools = (currentSource && currentSource.VideoTools) - ? currentSource.VideoTools - : defaultSourceTools; - return ( <div ref={container} @@ -136,9 +143,7 @@ function Video(props) { isFullscreen={isFullscreen} onFullscreenEnter={handleRequestFullscreenEnter} onFullscreenExit={onFullscreenExit} - > - <MediaSourceTools media={media} /> - </VideoToolbar> + /> )} </> )} @@ -146,16 +151,4 @@ function Video(props) { ); } -Video.propTypes = { - isFullscreen: PropTypes.bool, - enabled: PropTypes.bool, - size: PropTypes.string, - volume: PropTypes.number, - isMuted: PropTypes.bool, - media: PropTypes.object, - seek: PropTypes.number, - onFullscreenEnter: PropTypes.func.isRequired, - onFullscreenExit: PropTypes.func.isRequired, -}; - export default Video; diff --git a/src/components/WaitList/ModRow.jsx b/src/components/WaitList/ModRow.tsx similarity index 83% rename from src/components/WaitList/ModRow.jsx rename to src/components/WaitList/ModRow.tsx index 2903aee3e..612c9576f 100644 --- a/src/components/WaitList/ModRow.jsx +++ b/src/components/WaitList/ModRow.tsx @@ -1,6 +1,5 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useCallback, useRef, useState } from 'react'; import { useDrag, useDrop } from 'react-dnd'; import { mdiClose, mdiDragHorizontalVariant } from '@mdi/js'; import { WAITLIST_USER } from '../../constants/DDItemTypes'; @@ -10,12 +9,18 @@ import Avatar from '../Avatar'; import SvgIcon from '../SvgIcon'; import Username from '../Username'; import Position from './Position'; +import { User } from '../../reducers/users'; -const { - useCallback, - useRef, - useState, -} = React; +type DropResult = { position: number }; + +type ModRowProps = { + className?: string, + style?: React.CSSProperties, + position: number, + user: User, + onMoveUser: (position: number) => void, + onRemoveUser: () => void, +}; /** * A Draggable waitlist user row with moderation tools. @@ -27,9 +32,9 @@ function ModRow({ user, onMoveUser, onRemoveUser, -}) { +}: ModRowProps) { const userCard = useUserCard(user); - const onOpenCard = useCallback((event) => { + const onOpenCard = useCallback((event: React.MouseEvent) => { event.preventDefault(); userCard.open(); // The `userCard.open` reference never changes. @@ -37,7 +42,7 @@ function ModRow({ }, []); // Drag-drop interactions - const handleRef = useRef(); + const handleRef = useRef<HTMLDivElement>(null); const [insertAbove, setInsertAbove] = useState(false); const [{ isDragging }, connectDragSource, connectDragPreview] = useDrag({ type: WAITLIST_USER, @@ -45,7 +50,7 @@ function ModRow({ return { user }; }, end(item, monitor) { - const result = monitor.getDropResult(); + const result = monitor.getDropResult<DropResult>(); if (item.user && result) { onMoveUser(result.position); } @@ -56,10 +61,10 @@ function ModRow({ }); const [{ isOver }, connectDropTarget] = useDrop(() => ({ accept: WAITLIST_USER, - hover(item, monitor) { + hover(_item, monitor) { setInsertAbove(isDraggingNearTopOfRow(monitor, userCard.refAnchor.current)); }, - drop(item, monitor) { + drop(_item, monitor): DropResult { const insertAfter = !isDraggingNearTopOfRow(monitor, userCard.refAnchor.current); return { position: insertAfter ? position + 1 : position, @@ -119,13 +124,4 @@ function ModRow({ ); } -ModRow.propTypes = { - className: PropTypes.string, - style: PropTypes.object.isRequired, // from virtual list positioning - position: PropTypes.number.isRequired, - user: PropTypes.object.isRequired, - onMoveUser: PropTypes.func.isRequired, - onRemoveUser: PropTypes.func.isRequired, -}; - export default ModRow; diff --git a/src/components/WaitList/SimpleRow.jsx b/src/components/WaitList/SimpleRow.tsx similarity index 74% rename from src/components/WaitList/SimpleRow.jsx rename to src/components/WaitList/SimpleRow.tsx index b161bcdb7..5ec585711 100644 --- a/src/components/WaitList/SimpleRow.jsx +++ b/src/components/WaitList/SimpleRow.tsx @@ -1,21 +1,25 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useCallback } from 'react'; import useUserCard from '../../hooks/useUserCard'; +import { User } from '../../reducers/users'; import Avatar from '../Avatar'; import Username from '../Username'; import Position from './Position'; -const { useCallback } = React; - +type SimpleRowProps = { + className?: string, + style?: React.CSSProperties, + position: number, + user: User, +}; function SimpleRow({ className, style, position, user, -}) { +}: SimpleRowProps) { const userCard = useUserCard(user); - const onOpenCard = useCallback((event) => { + const onOpenCard = useCallback((event: React.MouseEvent) => { event.preventDefault(); userCard.open(); // The `userCard.open` reference never changes. @@ -47,11 +51,4 @@ function SimpleRow({ ); } -SimpleRow.propTypes = { - className: PropTypes.string, - style: PropTypes.object.isRequired, // from virtual list positioning - position: PropTypes.number.isRequired, - user: PropTypes.object.isRequired, -}; - export default SimpleRow; diff --git a/src/components/WaitList/index.jsx b/src/components/WaitList/index.tsx similarity index 61% rename from src/components/WaitList/index.jsx rename to src/components/WaitList/index.tsx index 3a987d8ba..d8ea7d0b1 100644 --- a/src/components/WaitList/index.jsx +++ b/src/components/WaitList/index.tsx @@ -1,27 +1,30 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import { useRef } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; import ModRow from './ModRow'; import SimpleRow from './SimpleRow'; - -const { - useRef, -} = React; +import { User } from '../../reducers/users'; function estimateSize() { return 40; } +type WaitListProps = { + className?: string, + users: (User | undefined)[], + onMoveUser: (user: User, position: number) => void, + onRemoveUser: (user: User) => void, + canMoveUsers: boolean, +}; function WaitList({ className, users, onMoveUser, onRemoveUser, canMoveUsers, -}) { +}: WaitListProps) { const Row = canMoveUsers ? ModRow : SimpleRow; - const parentRef = useRef(); + const parentRef = useRef<HTMLDivElement>(null); const virtualizer = useVirtualizer({ count: users.length, @@ -43,16 +46,22 @@ function WaitList({ <div style={{ height: `${virtualizer.getTotalSize()}px`, width: '100%', position: 'relative' }}> {virtualizer.getVirtualItems().map(({ index, start }) => { const style = { transform: `translateY(${start}px)` }; + const user = users[index]!; + if (user == null) { + // FIXME this means the waitlist is out of sync with online users state + // Returning null avoids a crash but isn't pretty + return null; + } return ( <Row - key={users[index]._id} + key={user._id} className={cx('UserList-row', index % 2 === 0 && 'UserList-row--alternate')} style={style} position={index} - user={users[index]} - onMoveUser={(position) => onMoveUser(users[index], position)} - onRemoveUser={() => onRemoveUser(users[index])} + user={user} + onMoveUser={(position) => onMoveUser(user, position)} + onRemoveUser={() => onRemoveUser(user)} /> ); })} @@ -61,12 +70,4 @@ function WaitList({ ); } -WaitList.propTypes = { - className: PropTypes.string, - users: PropTypes.arrayOf(PropTypes.object).isRequired, - canMoveUsers: PropTypes.bool.isRequired, - onMoveUser: PropTypes.func.isRequired, - onRemoveUser: PropTypes.func.isRequired, -}; - export default WaitList; diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.ts similarity index 64% rename from src/constants/ActionTypes.js rename to src/constants/ActionTypes.ts index 25cf08fbe..a0dc92753 100644 --- a/src/constants/ActionTypes.js +++ b/src/constants/ActionTypes.ts @@ -6,15 +6,8 @@ export * from './actionTypes/errors'; export * from './actionTypes/imports'; export * from './actionTypes/locales'; export * from './actionTypes/moderation'; -export * from './actionTypes/overlay'; -export * from './actionTypes/panel'; export * from './actionTypes/playlists'; export * from './actionTypes/request'; -export * from './actionTypes/search'; -export * from './actionTypes/settings'; -export * from './actionTypes/theme'; export * from './actionTypes/time'; -export * from './actionTypes/users'; export * from './actionTypes/votes'; export * from './actionTypes/waitlist'; -export const LOAD_EMOTES = 'emotes/LOAD'; diff --git a/src/constants/DDItemTypes.js b/src/constants/DDItemTypes.ts similarity index 100% rename from src/constants/DDItemTypes.js rename to src/constants/DDItemTypes.ts diff --git a/src/constants/LoadingStates.js b/src/constants/LoadingStates.ts similarity index 100% rename from src/constants/LoadingStates.js rename to src/constants/LoadingStates.ts diff --git a/src/constants/actionTypes/auth.js b/src/constants/actionTypes/auth.ts similarity index 86% rename from src/constants/actionTypes/auth.js rename to src/constants/actionTypes/auth.ts index ed2a0bc69..4098223e1 100644 --- a/src/constants/actionTypes/auth.js +++ b/src/constants/actionTypes/auth.ts @@ -1,10 +1,8 @@ -export const INIT_STATE = 'auth/INIT_STATE'; export const SOCKET_CONNECT = 'auth/SOCKET_CONNECT'; export const SOCKET_RECONNECT = 'auth/SOCKET_RECONNECT'; export const SOCKET_CONNECTED = 'auth/SOCKET_CONNECTED'; export const SOCKET_DISCONNECTED = 'auth/SOCKET_DISCONNECTED'; -export const AUTH_STRATEGIES = 'auth/AUTH_STRATEGIES'; export const SET_TOKEN = 'auth/SET_TOKEN'; export const REGISTER_START = 'auth/REGISTER_START'; diff --git a/src/constants/actionTypes/booth.js b/src/constants/actionTypes/booth.js deleted file mode 100644 index 9095fba18..000000000 --- a/src/constants/actionTypes/booth.js +++ /dev/null @@ -1,7 +0,0 @@ -export const ADVANCE = 'booth/ADVANCE'; -export const BOOTH_SKIP = 'booth/SKIP'; -export const LOAD_HISTORY_START = 'booth/LOAD_HISTORY_START'; -export const LOAD_HISTORY_COMPLETE = 'booth/LOAD_HISTORY_COMPLETE'; - -export const ENTER_FULLSCREEN = 'playback/ENTER_FULLSCREEN'; -export const EXIT_FULLSCREEN = 'playback/EXIT_FULLSCREEN'; diff --git a/src/constants/actionTypes/booth.ts b/src/constants/actionTypes/booth.ts new file mode 100644 index 000000000..150720886 --- /dev/null +++ b/src/constants/actionTypes/booth.ts @@ -0,0 +1,4 @@ +export const BOOTH_SKIP = 'booth/SKIP'; + +export const ENTER_FULLSCREEN = 'playback/ENTER_FULLSCREEN'; +export const EXIT_FULLSCREEN = 'playback/EXIT_FULLSCREEN'; diff --git a/src/constants/actionTypes/chat.js b/src/constants/actionTypes/chat.js deleted file mode 100644 index 4f37a69cb..000000000 --- a/src/constants/actionTypes/chat.js +++ /dev/null @@ -1,16 +0,0 @@ -export const RECEIVE_MOTD = 'chat/RECEIVE_MOTD'; -export const SET_MOTD_START = 'chat/SET_MOTD_START'; -export const SET_MOTD_COMPLETE = 'chat/SET_MOTD_COMPLETE'; - -export const RECEIVE_MESSAGE = 'chat/RECEIVE_MESSAGE'; -export const SEND_MESSAGE = 'chat/SEND_MESSAGE'; - -export const NOTIFY = 'chat/NOTIFY'; -export const LOG = 'chat/LOG'; - -export const REMOVE_MESSAGE = 'chat/REMOVE_MESSAGE'; -export const REMOVE_USER_MESSAGES = 'chat/REMOVE_USER_MESSAGES'; -export const REMOVE_ALL_MESSAGES = 'chat/REMOVE_ALL_MESSAGES'; - -export const MUTE_USER = 'chat/MUTE_USER'; -export const UNMUTE_USER = 'chat/UNMUTE_USER'; diff --git a/src/constants/actionTypes/chat.ts b/src/constants/actionTypes/chat.ts new file mode 100644 index 000000000..ee3916f87 --- /dev/null +++ b/src/constants/actionTypes/chat.ts @@ -0,0 +1,2 @@ +export const SET_MOTD_START = 'chat/SET_MOTD_START'; +export const SET_MOTD_COMPLETE = 'chat/SET_MOTD_COMPLETE'; diff --git a/src/constants/actionTypes/dialogs.js b/src/constants/actionTypes/dialogs.ts similarity index 86% rename from src/constants/actionTypes/dialogs.js rename to src/constants/actionTypes/dialogs.ts index 968a3b3bf..055a1a535 100644 --- a/src/constants/actionTypes/dialogs.js +++ b/src/constants/actionTypes/dialogs.ts @@ -7,5 +7,4 @@ export const CLOSE_PREVIEW_MEDIA_DIALOG = 'auth/CLOSE_PREVIEW_MEDIA_DIALOG'; export const OPEN_LOGIN_DIALOG = 'auth/OPEN_LOGIN_DIALOG'; export const CLOSE_LOGIN_DIALOG = 'auth/CLOSE_LOGIN_DIALOG'; -export const OPEN_RESET_PASSWORD_DIALOG = 'auth/OPEN_RESET_PASSWORD_DIALOG'; export const CLOSE_RESET_PASSWORD_DIALOG = 'auth/CLOSE_RESET_PASSWORD_DIALOG'; diff --git a/src/constants/actionTypes/errors.js b/src/constants/actionTypes/errors.ts similarity index 100% rename from src/constants/actionTypes/errors.js rename to src/constants/actionTypes/errors.ts diff --git a/src/constants/actionTypes/imports.js b/src/constants/actionTypes/imports.ts similarity index 77% rename from src/constants/actionTypes/imports.js rename to src/constants/actionTypes/imports.ts index 562f4f0df..06ac0fe4b 100644 --- a/src/constants/actionTypes/imports.js +++ b/src/constants/actionTypes/imports.ts @@ -1,4 +1,3 @@ -export const SHOW_IMPORT_PANEL = 'imports/SHOW_IMPORT_PANEL'; export const HIDE_IMPORT_PANEL = 'imports/HIDE_IMPORT_PANEL'; export const SHOW_IMPORT_SOURCE_PANEL = 'imports/SHOW_IMPORT_SOURCE_PANEL'; export const HIDE_IMPORT_SOURCE_PANEL = 'imports/HIDE_IMPORT_SOURCE_PANEL'; diff --git a/src/constants/actionTypes/locales.js b/src/constants/actionTypes/locales.ts similarity index 100% rename from src/constants/actionTypes/locales.js rename to src/constants/actionTypes/locales.ts diff --git a/src/constants/actionTypes/moderation.js b/src/constants/actionTypes/moderation.ts similarity index 100% rename from src/constants/actionTypes/moderation.js rename to src/constants/actionTypes/moderation.ts diff --git a/src/constants/actionTypes/overlay.js b/src/constants/actionTypes/overlay.js deleted file mode 100644 index d69f1ad8b..000000000 --- a/src/constants/actionTypes/overlay.js +++ /dev/null @@ -1,3 +0,0 @@ -export const OPEN_OVERLAY = 'overlay/OPEN_OVERLAY'; -export const CLOSE_OVERLAY = 'overlay/CLOSE_OVERLAY'; -export const TOGGLE_OVERLAY = 'overlay/TOGGLE_OVERLAY'; diff --git a/src/constants/actionTypes/panel.js b/src/constants/actionTypes/panel.js deleted file mode 100644 index adce8347b..000000000 --- a/src/constants/actionTypes/panel.js +++ /dev/null @@ -1,2 +0,0 @@ -// eslint-disable-next-line import/prefer-default-export -export const SELECT_PANEL = 'panel/SELECT_PANEL'; diff --git a/src/constants/actionTypes/playlists.js b/src/constants/actionTypes/playlists.ts similarity index 76% rename from src/constants/actionTypes/playlists.js rename to src/constants/actionTypes/playlists.ts index ca3f0ddab..5e545e001 100644 --- a/src/constants/actionTypes/playlists.js +++ b/src/constants/actionTypes/playlists.ts @@ -5,14 +5,9 @@ export const FILTER_PLAYLIST_ITEMS_START = 'playlists/FILTER_PLAYLIST_ITEMS_STAR export const FILTER_PLAYLIST_ITEMS_COMPLETE = 'playlists/FILTER_PLAYLIST_ITEMS_COMPLETE'; export const PLAYLIST_CYCLED = 'playlists/PLAYLIST_CYCLED'; -export const SELECT_PLAYLIST = 'playlists/SELECT_PLAYLIST'; - export const ACTIVATE_PLAYLIST_START = 'playlists/ACTIVATE_PLAYLIST_START'; export const ACTIVATE_PLAYLIST_COMPLETE = 'playlists/ACTIVATE_PLAYLIST_COMPLETE'; -export const LOAD_ALL_PLAYLISTS_START = 'playlists/LOAD_ALL_PLAYLISTS_START'; -export const LOAD_ALL_PLAYLISTS_COMPLETE = 'playlists/LOAD_ALL_PLAYLISTS_COMPLETE'; - export const CREATE_PLAYLIST_START = 'playlists/CREATE_PLAYLIST_START'; export const CREATE_PLAYLIST_COMPLETE = 'playlists/CREATE_PLAYLIST_COMPLETE'; @@ -22,11 +17,6 @@ export const RENAME_PLAYLIST_COMPLETE = 'playlists/RENAME_PLAYLIST_COMPLETE'; export const DELETE_PLAYLIST_START = 'playlists/DELETE_PLAYLIST_START'; export const DELETE_PLAYLIST_COMPLETE = 'playlists/DELETE_PLAYLIST_COMPLETE'; -export const OPEN_ADD_MEDIA_MENU = 'playlists/OPEN_ADD_MEDIA_MENU'; -export const CLOSE_ADD_MEDIA_MENU = 'playlists/CLOSE_ADD_MEDIA_MENU'; -export const ADD_MEDIA_START = 'playlists/ADD_MEDIA_START'; -export const ADD_MEDIA_COMPLETE = 'playlists/ADD_MEDIA_COMPLETE'; - export const REMOVE_MEDIA_START = 'playlists/REMOVE_MEDIA_START'; export const REMOVE_MEDIA_COMPLETE = 'playlists/REMOVE_MEDIA_COMPLETE'; diff --git a/src/constants/actionTypes/request.js b/src/constants/actionTypes/request.ts similarity index 100% rename from src/constants/actionTypes/request.js rename to src/constants/actionTypes/request.ts diff --git a/src/constants/actionTypes/search.js b/src/constants/actionTypes/search.js deleted file mode 100644 index 9f816b3b5..000000000 --- a/src/constants/actionTypes/search.js +++ /dev/null @@ -1,2 +0,0 @@ -export const SHOW_SEARCH_RESULTS = 'search/SHOW_SEARCH_RESULTS'; -export const HIDE_SEARCH_RESULTS = 'search/HIDE_SEARCH_RESULTS'; diff --git a/src/constants/actionTypes/settings.js b/src/constants/actionTypes/settings.js deleted file mode 100644 index eb386fe58..000000000 --- a/src/constants/actionTypes/settings.js +++ /dev/null @@ -1,2 +0,0 @@ -export const LOAD_SETTINGS = 'settings/LOAD_SETTINGS'; -export const CHANGE_SETTING = 'settings/CHANGE_SETTING'; diff --git a/src/constants/actionTypes/theme.js b/src/constants/actionTypes/theme.js deleted file mode 100644 index afdbeaff3..000000000 --- a/src/constants/actionTypes/theme.js +++ /dev/null @@ -1,2 +0,0 @@ -export const RESET_THEME = 'uwave/debug/RESET_THEME'; -export const APPLY_THEME = 'uwave/debug/APPLY_THEME'; diff --git a/src/constants/actionTypes/time.js b/src/constants/actionTypes/time.ts similarity index 100% rename from src/constants/actionTypes/time.js rename to src/constants/actionTypes/time.ts diff --git a/src/constants/actionTypes/users.js b/src/constants/actionTypes/users.js deleted file mode 100644 index aaa17f372..000000000 --- a/src/constants/actionTypes/users.js +++ /dev/null @@ -1,11 +0,0 @@ -export const LOAD_ONLINE_USERS = 'users/LOAD'; -export const USER_JOIN = 'users/JOIN'; -export const USER_LEAVE = 'users/LEAVE'; -export const CHANGE_USERNAME = 'users/CHANGE_USERNAME'; -export const USER_ADD_ROLES = 'users/ADD_ROLES'; -export const USER_REMOVE_ROLES = 'users/REMOVE_ROLES'; - -export const RECEIVE_GUEST_COUNT = 'users/RECEIVE_GUEST_COUNT'; - -export const DO_CHANGE_USERNAME_START = 'users/DO_CHANGE_USERNAME_START'; -export const DO_CHANGE_USERNAME_COMPLETE = 'users/DO_CHANGE_USERNAME_COMPLETE'; diff --git a/src/constants/actionTypes/votes.js b/src/constants/actionTypes/votes.ts similarity index 88% rename from src/constants/actionTypes/votes.js rename to src/constants/actionTypes/votes.ts index 89327d133..054930d6a 100644 --- a/src/constants/actionTypes/votes.js +++ b/src/constants/actionTypes/votes.ts @@ -1,4 +1,3 @@ -export const LOAD_VOTES = 'votes/LOAD_VOTES'; export const UPVOTE = 'votes/UPVOTE'; export const DOWNVOTE = 'votes/DOWNVOTE'; export const FAVORITE = 'votes/FAVORITE'; diff --git a/src/constants/actionTypes/waitlist.js b/src/constants/actionTypes/waitlist.ts similarity index 58% rename from src/constants/actionTypes/waitlist.js rename to src/constants/actionTypes/waitlist.ts index 9797f7970..a99a67c2e 100644 --- a/src/constants/actionTypes/waitlist.js +++ b/src/constants/actionTypes/waitlist.ts @@ -1,13 +1,3 @@ -export const WAITLIST_LOAD = 'waitlist/LOAD'; - -export const WAITLIST_LOCK = 'waitlist/LOCK'; -export const WAITLIST_CLEAR = 'waitlist/CLEAR'; - -export const WAITLIST_UPDATE = 'waitlist/UPDATE'; -export const WAITLIST_JOIN = 'waitlist/JOIN'; -export const WAITLIST_LEAVE = 'waitlist/LEAVE'; -export const WAITLIST_MOVE = 'waitlist/MOVE'; - export const DO_JOIN_START = 'waitlist/DO_JOIN_START'; export const DO_JOIN_COMPLETE = 'waitlist/DO_JOIN_COMPLETE'; diff --git a/src/containers/AddToPlaylistMenu.jsx b/src/containers/AddToPlaylistMenu.tsx similarity index 53% rename from src/containers/AddToPlaylistMenu.jsx rename to src/containers/AddToPlaylistMenu.tsx index 8e8bf3516..66e56492b 100644 --- a/src/containers/AddToPlaylistMenu.jsx +++ b/src/containers/AddToPlaylistMenu.tsx @@ -1,39 +1,36 @@ -import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { - createPlaylist, - addMedia, - closeAddMediaMenu, -} from '../actions/PlaylistActionCreators'; +import { useCallback } from 'react'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { favoriteMedia } from '../actions/VoteActionCreators'; import { + close, isFavoriteSelector, isOpenSelector, positionSelector, mediaSelector, historyIDSelector, -} from '../selectors/addToPlaylistMenuSelectors'; -import { playlistsSelector } from '../selectors/playlistSelectors'; +} from '../reducers/addToPlaylistMenu'; import AddToPlaylistMenu from '../components/AddToPlaylistMenu'; - -const { useCallback } = React; +import { addPlaylistItems, createPlaylist, Playlist } from '../reducers/playlists'; function AddToPlaylistMenuContainer() { const dispatch = useDispatch(); const isFavorite = useSelector(isFavoriteSelector); const isOpen = useSelector(isOpenSelector); const position = useSelector(positionSelector); - const playlists = useSelector(playlistsSelector); const media = useSelector(mediaSelector); const historyID = useSelector(historyIDSelector); - const onClose = useCallback(() => dispatch(closeAddMediaMenu()), [dispatch]); - const onCreatePlaylist = useCallback((name) => dispatch(createPlaylist(name)), [dispatch]); - const onSelect = useCallback((playlist) => { + const onClose = useCallback(() => { + dispatch(close()); + }, [dispatch]); + const onCreatePlaylist = useCallback((name: string) => { + dispatch(createPlaylist(name)); + }, [dispatch]); + const onSelect = useCallback((playlist: Playlist) => { if (isFavorite) { - return dispatch(favoriteMedia(playlist, historyID)); + return dispatch(favoriteMedia(playlist, historyID!)); } - return dispatch(addMedia(playlist, media)); + return dispatch(addPlaylistItems({ playlistID: playlist._id, items: media! })); }, [dispatch, isFavorite, historyID, media]); if (!isOpen) { @@ -42,9 +39,7 @@ function AddToPlaylistMenuContainer() { return ( <AddToPlaylistMenu - open={isOpen} position={position} - playlists={playlists} onClose={onClose} onCreatePlaylist={onCreatePlaylist} onSelect={onSelect} diff --git a/src/containers/App.jsx b/src/containers/App.jsx index 3d72d5341..6f7f746d0 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -1,11 +1,11 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useSelector, useDispatch } from 'react-redux'; import useMediaQuery from '@mui/material/useMediaQuery'; import { ThemeProvider } from '@mui/material/styles'; import { Provider as BusProvider } from 'react-bus'; import { TranslateProvider } from '@u-wave/react-translate'; -import { closeAll } from '../actions/OverlayActionCreators'; +import { useSelector, useDispatch } from '../hooks/useRedux'; +import { closeOverlay, selectOverlay } from '../reducers/activeOverlay'; import { themeSelector } from '../selectors/settingSelectors'; import { translatorSelector } from '../selectors/localeSelectors'; import { isConnectedSelector } from '../selectors/serverSelectors'; @@ -16,11 +16,9 @@ import UwaveContext from '../context/UwaveContext'; import { ClockProvider } from '../context/ClockContext'; import MediaSourceContext from '../context/MediaSourceContext'; import { AllStoresProvider } from '../stores'; +import { initState } from '../reducers/auth'; -const { - useCallback, - useEffect, -} = React; +const { useCallback, useEffect, useRef } = React; class ErrorWrapper extends React.Component { static propTypes = { @@ -53,14 +51,26 @@ class ErrorWrapper extends React.Component { } } +function usePageVisibility(fn) { + useEffect(() => { + const handler = () => { + fn(!document.hidden); + }; + window.addEventListener('visibilitychange', handler); + return () => { + window.removeEventListener('visibilitychange', handler); + }; + }, [fn]); +} + function AppContainer({ uwave, mediaSources }) { const isMobile = useMediaQuery('(max-width: 767px)'); - const activeOverlay = useSelector((state) => state.activeOverlay); + const activeOverlay = useSelector(selectOverlay); const isConnected = useSelector(isConnectedSelector); const theme = useSelector(themeSelector); const translator = useSelector(translatorSelector); const dispatch = useDispatch(); - const onCloseOverlay = useCallback(() => dispatch(closeAll()), [dispatch]); + const onCloseOverlay = useCallback(() => dispatch(closeOverlay()), [dispatch]); useEffect(() => { const html = document.documentElement; @@ -72,6 +82,15 @@ function AppContainer({ uwave, mediaSources }) { }); }, [theme]); + const hiddenTime = useRef(0); + usePageVisibility((visible) => { + if (visible && (Date.now() - hiddenTime.current) > 60_000) { + dispatch(initState()); + } else { + hiddenTime.current = Date.now(); + } + }); + const props = { activeOverlay, isConnected, diff --git a/src/containers/ChatInput.jsx b/src/containers/ChatInput.tsx similarity index 73% rename from src/containers/ChatInput.jsx rename to src/containers/ChatInput.tsx index e2e1b6d50..387a14f5f 100644 --- a/src/containers/ChatInput.jsx +++ b/src/containers/ChatInput.tsx @@ -1,22 +1,18 @@ import React from 'react'; -import { useStore, useSelector } from 'react-redux'; import { useBus } from 'react-bus'; import splitargs from 'splitargs'; +import { useDispatch, useStore, useSelector } from '../hooks/useRedux'; import { sendChat } from '../actions/ChatActionCreators'; -import { - availableGroupMentionsSelector, - emojiCompletionsSelector, -} from '../selectors/chatSelectors'; +import { availableGroupMentionsSelector } from '../selectors/chatSelectors'; import { userListSelector, isLoggedInSelector, } from '../selectors/userSelectors'; import commandList from '../utils/commands'; import ChatCommands from '../utils/ChatCommands'; +import useEmotes from '../hooks/useEmotes'; -const ChatInput = React.lazy(() => ( - import(/* webpackPreload: true */ '../components/Chat/Input') -)); +const ChatInput = React.lazy(() => import('../components/Chat/Input')); const { useCallback, @@ -34,11 +30,17 @@ function ChatInputContainer() { const isLoggedIn = useSelector(isLoggedInSelector); const mentionableUsers = useSelector(userListSelector); const mentionableGroups = useSelector(availableGroupMentionsSelector); - const availableEmoji = useSelector(emojiCompletionsSelector); + const emotes = useEmotes(); + const availableEmoji = useMemo(() => { + return Object.entries(emotes).map(([shortcode, url]) => ({ + shortcode, + image: url, + })); + }, [emotes]); + const dispatch = useDispatch(); const store = useStore(); - const { dispatch } = store; const commander = useMemo(() => new ChatCommands(store, commandList), [store]); - const onSend = useCallback((message) => { + const onSend = useCallback((message: string) => { if (message.startsWith('/')) { const [command, ...params] = splitargs(message.slice(1)); if (command) { @@ -53,7 +55,7 @@ function ChatInputContainer() { }, [commander, dispatch]); const bus = useBus(); - const onScroll = useCallback((direction) => { + const onScroll = useCallback((direction: unknown) => { bus.emit('chat:scroll', direction); }, [bus]); diff --git a/src/containers/ChatMessages.js b/src/containers/ChatMessages.js deleted file mode 100644 index 7ffb79f4a..000000000 --- a/src/containers/ChatMessages.js +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import { createStructuredSelector } from 'reselect'; -import { - motdSelector, - messagesSelector, - markupCompilerOptionsSelector, - canDeleteMessagesSelector, -} from '../selectors/chatSelectors'; -import { deleteChatMessage } from '../actions/ModerationActionCreators'; -import ChatMessages from '../components/Chat/ChatMessages'; - -const mapStateToProps = createStructuredSelector({ - motd: motdSelector, - messages: messagesSelector, - compileOptions: markupCompilerOptionsSelector, - canDeleteMessages: canDeleteMessagesSelector, -}); - -const mapDispatchToProps = { - onDeleteMessage: deleteChatMessage, -}; - -const enhance = connect(mapStateToProps, mapDispatchToProps); - -export default enhance(ChatMessages); diff --git a/src/containers/ChatMessages.tsx b/src/containers/ChatMessages.tsx new file mode 100644 index 000000000..88486e065 --- /dev/null +++ b/src/containers/ChatMessages.tsx @@ -0,0 +1,41 @@ +import { useCallback, useMemo } from 'react'; +import { useDispatch, useSelector } from '../hooks/useRedux'; +import { + motdSelector, + messagesSelector, + canDeleteMessagesSelector, +} from '../selectors/chatSelectors'; +import { customEmojiNamesSelector } from '../selectors/configSelectors'; +import { deleteChatMessage } from '../actions/ModerationActionCreators'; +import ChatMessages from '../components/Chat/ChatMessages'; +import useEmotes from '../hooks/useEmotes'; +import { CompileOptions } from '../components/Chat/Markup'; + +function ChatMessagesContainer() { + const dispatch = useDispatch(); + const motd = useSelector(motdSelector); + const messages = useSelector(messagesSelector); + const emotes = useEmotes(); + const customEmojiNames = useSelector(customEmojiNamesSelector); + const compileOptions: CompileOptions = useMemo(() => ({ + availableEmoji: new Set(Object.keys(emotes)), + emojiImages: emotes, + customEmojiNames, + }), [emotes, customEmojiNames]); + const canDeleteMessages = useSelector(canDeleteMessagesSelector); + const onDeleteMessage = useCallback((id: string) => { + dispatch(deleteChatMessage(id)); + }, [dispatch]); + + return ( + <ChatMessages + motd={motd} + messages={messages} + compileOptions={compileOptions} + canDeleteMessages={canDeleteMessages} + onDeleteMessage={onDeleteMessage} + /> + ); +} + +export default ChatMessagesContainer; diff --git a/src/containers/EditMediaDialog.jsx b/src/containers/EditMediaDialog.jsx index 9d707e1a7..ba9930ddf 100644 --- a/src/containers/EditMediaDialog.jsx +++ b/src/containers/EditMediaDialog.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { updateMedia } from '../actions/PlaylistActionCreators'; import { closeEditMediaDialog } from '../actions/DialogActionCreators'; import { editMediaDialogSelector } from '../selectors/dialogSelectors'; diff --git a/src/containers/ErrorArea.jsx b/src/containers/ErrorArea.jsx index e34ab6773..709187c55 100644 --- a/src/containers/ErrorArea.jsx +++ b/src/containers/ErrorArea.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { dismiss } from '../actions/ErrorActionCreators'; import { firstErrorSelector } from '../selectors/errorSelectors'; import ErrorArea from '../components/ErrorArea'; diff --git a/src/containers/HeaderBar.js b/src/containers/HeaderBar.js index 18022d2cd..9c05355bd 100644 --- a/src/containers/HeaderBar.js +++ b/src/containers/HeaderBar.js @@ -1,9 +1,14 @@ import { connect } from 'react-redux'; import { createStructuredSelector } from 'reselect'; -import { setVolume, mute, unmute } from '../actions/PlaybackActionCreators'; -import { toggleRoomHistory, toggleAbout } from '../actions/OverlayActionCreators'; +import { toggleOverlay } from '../reducers/activeOverlay'; import { djSelector, mediaSelector, startTimeSelector } from '../selectors/boothSelectors'; -import { volumeSelector, isMutedSelector } from '../selectors/settingSelectors'; +import { + setVolume, + mute, + unmute, + volumeSelector, + isMutedSelector, +} from '../reducers/settings'; import HeaderBar from '../components/HeaderBar'; const mapStateToProps = createStructuredSelector({ @@ -18,8 +23,8 @@ const mapDispatchToProps = { onVolumeChange: setVolume, onVolumeMute: mute, onVolumeUnmute: unmute, - onToggleRoomHistory: toggleRoomHistory, - onToggleAboutOverlay: toggleAbout, + onToggleRoomHistory: () => toggleOverlay('roomHistory'), + onToggleAboutOverlay: () => toggleOverlay('about'), }; const enhance = connect(mapStateToProps, mapDispatchToProps); diff --git a/src/containers/LoginDialog.js b/src/containers/LoginDialog.js index ab8c3e6ee..181e15fdc 100644 --- a/src/containers/LoginDialog.js +++ b/src/containers/LoginDialog.js @@ -1,8 +1,9 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { - resetPassword, login, register, finishSocialLogin, registerCompleteError, + resetPassword, register, finishSocialLogin, registerCompleteError, } from '../actions/LoginActionCreators'; +import { login } from '../reducers/auth'; import { openResetPasswordDialog, closeLoginDialog } from '../actions/DialogActionCreators'; import { loginDialogSelector } from '../selectors/dialogSelectors'; import LoginDialog from '../components/Dialogs/LoginDialog'; diff --git a/src/containers/PlaylistImportManager.jsx b/src/containers/PlaylistImportManager.jsx index dfdd8ab59..e2fc0bed9 100644 --- a/src/containers/PlaylistImportManager.jsx +++ b/src/containers/PlaylistImportManager.jsx @@ -1,10 +1,10 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { showImportSourcePanel, hideImportSourcePanel, } from '../actions/ImportActionCreators'; -import { selectedSourceTypeSelector } from '../selectors/importSelectors'; +import { selectedSourceTypeSelector } from '../reducers/imports'; import PlaylistImport from '../components/PlaylistManager/Import'; const { useCallback } = React; diff --git a/src/containers/PlaylistManager.jsx b/src/containers/PlaylistManager.jsx index 652a5b58c..56fa7e8d8 100644 --- a/src/containers/PlaylistManager.jsx +++ b/src/containers/PlaylistManager.jsx @@ -1,45 +1,9 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import { useDispatch, useSelector } from 'react-redux'; -import { useTranslator } from '@u-wave/react-translate'; -import { selectedPlaylistSelector } from '../selectors/playlistSelectors'; -import { showSearchResultsSelector } from '../selectors/searchSelectors'; -import { showImportPanelSelector } from '../selectors/importSelectors'; -import { createPlaylist } from '../actions/PlaylistActionCreators'; import createLazyOverlay from '../components/LazyOverlay'; -const { useCallback } = React; - const PlaylistManager = createLazyOverlay({ - loader: () => import('../components/PlaylistManager'), + Component: React.lazy(() => import('../components/PlaylistManager')), title: (t) => t('playlists.title'), }); -function PlaylistManagerContainer({ onCloseOverlay }) { - const { t } = useTranslator(); - - const selectedPlaylist = useSelector(selectedPlaylistSelector); - const showImportPanel = useSelector(showImportPanelSelector); - const showSearchResults = useSelector(showSearchResultsSelector); - const dispatch = useDispatch(); - - const onCreatePlaylist = useCallback(() => ( - dispatch(createPlaylist(t('playlists.defaultName'))) - ), [dispatch, t]); - - return ( - <PlaylistManager - selectedPlaylist={selectedPlaylist} - showImportPanel={showImportPanel} - showSearchResults={showSearchResults} - onCreatePlaylist={onCreatePlaylist} - onCloseOverlay={onCloseOverlay} - /> - ); -} - -PlaylistManagerContainer.propTypes = { - onCloseOverlay: PropTypes.func.isRequired, -}; - -export default PlaylistManagerContainer; +export default PlaylistManager; diff --git a/src/containers/PlaylistManagerMenu.jsx b/src/containers/PlaylistManagerMenu.jsx index 1aa312eb1..70ba48df2 100644 --- a/src/containers/PlaylistManagerMenu.jsx +++ b/src/containers/PlaylistManagerMenu.jsx @@ -1,46 +1,50 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useSelector, useDispatch } from 'react-redux'; -import { - addMedia as addToPlaylist, - createPlaylist, - selectPlaylist, -} from '../actions/PlaylistActionCreators'; -import { showImportPanel } from '../actions/ImportActionCreators'; -import { showSearchResults, hideSearchResults } from '../actions/SearchActionCreators'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { playlistsSelector, - selectedPlaylistSelector, + selectedPlaylistIDSelector, } from '../selectors/playlistSelectors'; -import { showSearchResultsSelector } from '../selectors/searchSelectors'; -import { showImportPanelSelector } from '../selectors/importSelectors'; import { useMediaSearchStore } from '../stores/MediaSearchStore'; import PlaylistsMenu from '../components/PlaylistManager/Menu'; +import { + addPlaylistItems, + createPlaylist, + selectActivePlaylist, + selectPlaylist, + showImportPanel, + showSearchResults, +} from '../reducers/playlists'; const { useCallback } = React; function PlaylistsMenuContainer({ className }) { const playlists = useSelector(playlistsSelector); - const selected = useSelector(selectedPlaylistSelector); + const selected = useSelector(selectedPlaylistIDSelector); const mediaSearch = useMediaSearchStore(); - const isShowSearchResults = useSelector(showSearchResultsSelector); - const isShowImportPanel = useSelector(showImportPanelSelector); const dispatch = useDispatch(); - const onAddToPlaylist = useCallback( - (playlist, items, afterID) => dispatch(addToPlaylist(playlist, items, afterID)), - [dispatch], - ); - const onCreatePlaylist = useCallback((name) => dispatch(createPlaylist(name)), [dispatch]); - const onSelectPlaylist = useCallback((id) => dispatch(selectPlaylist(id)), [dispatch]); - const onSelectSearchResults = useCallback(() => dispatch(showSearchResults()), [dispatch]); + const onAddToPlaylist = useCallback((playlist, items, afterID) => { + dispatch(addPlaylistItems({ playlistID: playlist._id, items, afterID })); + }, [dispatch]); + const onCreatePlaylist = useCallback((name) => { + dispatch(createPlaylist(name)); + }, [dispatch]); + const onSelectPlaylist = useCallback((id) => { + dispatch(selectPlaylist(id)); + }, [dispatch]); + const onSelectSearchResults = useCallback(() => { + dispatch(showSearchResults()); + }, [dispatch]); const onCloseSearchResults = useCallback(() => { mediaSearch.reset(); - dispatch(hideSearchResults()); + dispatch(selectActivePlaylist()); // The `mediaSearch.reset` reference never changes. // eslint-disable-next-line react-hooks/exhaustive-deps }, [dispatch]); - const onShowImportPanel = useCallback(() => dispatch(showImportPanel()), [dispatch]); + const onShowImportPanel = useCallback(() => { + dispatch(showImportPanel()); + }, [dispatch]); return ( <PlaylistsMenu @@ -48,9 +52,7 @@ function PlaylistsMenuContainer({ className }) { playlists={playlists} selected={selected} searchQuery={mediaSearch.query} - showSearchResults={isShowSearchResults} searchResults={mediaSearch.resultsCount} - showImportPanel={isShowImportPanel} onAddToPlaylist={onAddToPlaylist} onCreatePlaylist={onCreatePlaylist} onSelectPlaylist={onSelectPlaylist} diff --git a/src/containers/PlaylistManagerPanel.jsx b/src/containers/PlaylistManagerPanel.jsx index aaf56edf7..142710dfd 100644 --- a/src/containers/PlaylistManagerPanel.jsx +++ b/src/containers/PlaylistManagerPanel.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { selectedPlaylistSelector, filteredSelectedPlaylistItemsSelector, @@ -7,17 +7,19 @@ import { isFilteredSelector, } from '../selectors/playlistSelectors'; import { - moveMedia, filterPlaylistItems, - renamePlaylist, deletePlaylist, cannotDeleteActivePlaylist, shufflePlaylist, - activatePlaylist, loadPlaylist, loadFilteredPlaylistItems, } from '../actions/PlaylistActionCreators'; import PlaylistPanel from '../components/PlaylistManager/Panel'; +import { + renamePlaylist, + activatePlaylist, + movePlaylistItems, +} from '../reducers/playlists'; const { useCallback } = React; @@ -38,7 +40,7 @@ function PlaylistPanelContainer() { [dispatch, playlistID], ); const onRenamePlaylist = useCallback( - (name) => dispatch(renamePlaylist(playlistID, name)), + (name) => dispatch(renamePlaylist({ playlistID, name })), [dispatch, playlistID], ); const onDeletePlaylist = useCallback( @@ -51,7 +53,11 @@ function PlaylistPanelContainer() { ); const onMoveMedia = useCallback( - (media, opts) => dispatch(moveMedia(playlistID, media, opts)), + (media, opts) => dispatch(movePlaylistItems({ + playlistID, + medias: media, + target: opts, + })), [dispatch, playlistID], ); const onLoadPlaylistPage = useCallback((page) => { diff --git a/src/containers/PreviewMediaDialog.jsx b/src/containers/PreviewMediaDialog.jsx index d7de516b6..2289441e2 100644 --- a/src/containers/PreviewMediaDialog.jsx +++ b/src/containers/PreviewMediaDialog.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '../hooks/useRedux'; import { closePreviewMediaDialog } from '../actions/DialogActionCreators'; import { previewMediaDialogSelector } from '../selectors/dialogSelectors'; import PreviewMediaDialog from '../components/Dialogs/PreviewMediaDialog'; diff --git a/src/containers/RoomHistory.jsx b/src/containers/RoomHistory.jsx deleted file mode 100644 index eb0212602..000000000 --- a/src/containers/RoomHistory.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import { useSelector } from 'react-redux'; -import { roomHistoryWithVotesSelector } from '../selectors/roomHistorySelectors'; -import Overlay from '../components/Overlay'; -import createLazyOverlay from '../components/LazyOverlay'; - -function RoomHistoryOverlay(props) { - return <Overlay {...props} direction="top" />; -} - -const RoomHistory = createLazyOverlay({ - loader: () => import('../components/RoomHistory'), - title: (t) => t('history.title'), - OverlayComponent: RoomHistoryOverlay, -}); - -function RoomHistoryContainer(props) { - const media = useSelector(roomHistoryWithVotesSelector); - - return <RoomHistory {...props} media={media} />; -} - -export default RoomHistoryContainer; diff --git a/src/containers/RoomHistory.tsx b/src/containers/RoomHistory.tsx new file mode 100644 index 000000000..8d48fee43 --- /dev/null +++ b/src/containers/RoomHistory.tsx @@ -0,0 +1,19 @@ +import { lazy } from 'react'; +import Overlay from '../components/Overlay'; +import createLazyOverlay from '../components/LazyOverlay'; + +function RoomHistoryOverlay(props: { children: React.ReactNode }) { + return <Overlay {...props} direction="top" />; +} + +const RoomHistory = createLazyOverlay({ + title: (t) => t('history.title'), + OverlayComponent: RoomHistoryOverlay, + Component: lazy(() => import('../components/RoomHistory')), +}); + +function RoomHistoryContainer(props: { onCloseOverlay: () => void }) { + return <RoomHistory {...props} />; +} + +export default RoomHistoryContainer; diff --git a/src/containers/RoomUserList.jsx b/src/containers/RoomUserList.tsx similarity index 68% rename from src/containers/RoomUserList.jsx rename to src/containers/RoomUserList.tsx index 86869e533..4f58ff8bd 100644 --- a/src/containers/RoomUserList.jsx +++ b/src/containers/RoomUserList.tsx @@ -1,16 +1,13 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; -import { - userListSelector, - guestCountSelector, -} from '../selectors/userSelectors'; +import { useMemo } from 'react'; +import { useSelector } from '../hooks/useRedux'; +import { userListSelector, guestCountSelector } from '../selectors/userSelectors'; import { currentVotesSelector } from '../selectors/voteSelectors'; import RoomUserList from '../components/RoomUserList'; -const { useMemo } = React; - -function RoomUserListContainer({ className }) { +type RoomUserListContainerProps = { + className?: string, +}; +function RoomUserListContainer({ className }: RoomUserListContainerProps) { const users = useSelector(userListSelector); const votes = useSelector(currentVotesSelector); const guestCount = useSelector(guestCountSelector); @@ -35,8 +32,4 @@ function RoomUserListContainer({ className }) { ); } -RoomUserListContainer.propTypes = { - className: PropTypes.string, -}; - export default RoomUserListContainer; diff --git a/src/containers/SearchResultsPanel.jsx b/src/containers/SearchResultsPanel.tsx similarity index 52% rename from src/containers/SearchResultsPanel.jsx rename to src/containers/SearchResultsPanel.tsx index 8bf8a67d1..ecc2a3650 100644 --- a/src/containers/SearchResultsPanel.jsx +++ b/src/containers/SearchResultsPanel.tsx @@ -1,25 +1,43 @@ import React from 'react'; -import { useSelector } from 'react-redux'; +import useSWRImmutable from 'swr/immutable'; +import { useSelector } from '../hooks/useRedux'; import { useMediaSearchStore } from '../stores/MediaSearchStore'; import { playlistsByIDSelector } from '../selectors/playlistSelectors'; import SearchResults from '../components/PlaylistManager/SearchResults'; +import { Media } from '../reducers/booth'; +import uwFetch, { ListResponse } from '../utils/fetch'; const { useMemo } = React; +interface SearchResult extends Media { + inPlaylists?: string[]; +} + function SearchResultsContainer() { const { + activeSource, query, - results, - state, } = useMediaSearchStore(); + // Technically this is not immutable but we want to avoid frequent + // search queries that cost a lot of quota + const { data: results, error, isValidating } = useSWRImmutable<ListResponse<SearchResult>>(() => { + if (!query) { + return null; + } + + return [`/search/${encodeURIComponent(activeSource)}`, { + qs: { query, include: 'playlists' }, + }]; + }, uwFetch); + const playlistsByID = useSelector(playlistsByIDSelector); const resultsWithPlaylists = useMemo(() => { - if (!results) { + if (!results || !Array.isArray(results.data)) { return []; } - return results.map((result) => { + return results.data.map((result) => { if (!Array.isArray(result.inPlaylists)) { return result; } @@ -34,9 +52,16 @@ function SearchResultsContainer() { }); }, [results, playlistsByID]); + let state = 'loadingState/IDLE'; + if (results || error) { + state = 'loadingState/LOADED'; + } else if (isValidating) { + state = 'loadingState/LOADING'; + } + return ( <SearchResults - query={query} + query={query ?? ''} results={resultsWithPlaylists} loadingState={state} /> diff --git a/src/containers/SettingsManager.js b/src/containers/SettingsManager.js deleted file mode 100644 index 07b8ead36..000000000 --- a/src/containers/SettingsManager.js +++ /dev/null @@ -1,42 +0,0 @@ -import { connect } from 'react-redux'; -import { createStructuredSelector } from 'reselect'; -import { - set as setSetting, - setLanguage, -} from '../actions/SettingsActionCreators'; -import { changeLanguage } from '../actions/LocaleActionCreators'; -import { doChangeUsername } from '../actions/UserActionCreators'; -import { logout } from '../actions/LoginActionCreators'; -import { currentUserSelector } from '../selectors/userSelectors'; -import { settingsSelector } from '../selectors/settingSelectors'; -import createLazyOverlay from '../components/LazyOverlay'; - -function changeAndSaveLanguage(language) { - return (dispatch) => { - Promise.resolve(dispatch(changeLanguage(language))) - .then(() => { - dispatch(setLanguage(language)); - }); - }; -} - -const mapStateToProps = createStructuredSelector({ - settings: settingsSelector, - user: currentUserSelector, -}); - -const mapDispatchToProps = { - onSettingChange: setSetting, - onChangeUsername: doChangeUsername, - onChangeLanguage: changeAndSaveLanguage, - onLogout: logout, -}; - -const enhance = connect(mapStateToProps, mapDispatchToProps); - -const SettingsManager = createLazyOverlay({ - loader: () => import('../components/SettingsManager'), - title: (t) => t('settings.title'), -}); - -export default enhance(SettingsManager); diff --git a/src/containers/SettingsManager.jsx b/src/containers/SettingsManager.jsx new file mode 100644 index 000000000..3b18710ed --- /dev/null +++ b/src/containers/SettingsManager.jsx @@ -0,0 +1,42 @@ +import PropTypes from 'prop-types'; +import { lazy, useCallback } from 'react'; +import { changeLanguage } from '../actions/LocaleActionCreators'; +import { logout } from '../actions/LoginActionCreators'; +import { changeUsername } from '../reducers/auth'; +import { useDispatch } from '../hooks/useRedux'; +import createLazyOverlay from '../components/LazyOverlay'; + +const SettingsManager = createLazyOverlay({ + Component: lazy(() => import('../components/SettingsManager')), + title: (t) => t('settings.title'), +}); + +function SettingsManagerContainer({ onCloseOverlay }) { + const dispatch = useDispatch(); + const onChangeUsername = useCallback( + (name) => dispatch(changeUsername(name)), + [dispatch], + ); + const onChangeLanguage = useCallback( + (language) => dispatch(changeLanguage(language)), + [dispatch], + ); + const onLogout = useCallback(() => { + dispatch(logout()); + }, [dispatch]); + + return ( + <SettingsManager + onCloseOverlay={onCloseOverlay} + onChangeUsername={onChangeUsername} + onChangeLanguage={onChangeLanguage} + onLogout={onLogout} + /> + ); +} + +SettingsManagerContainer.propTypes = { + onCloseOverlay: PropTypes.func.isRequired, +}; + +export default SettingsManagerContainer; diff --git a/src/containers/Video.jsx b/src/containers/Video.jsx index ab5964f1f..00fafa526 100644 --- a/src/containers/Video.jsx +++ b/src/containers/Video.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch, useSelector } from '../hooks/useRedux'; import useClock from '../hooks/useClock'; import { enterFullscreen, exitFullscreen } from '../actions/PlaybackActionCreators'; import { @@ -12,7 +12,7 @@ import { isMutedSelector, videoSizeSelector, videoEnabledSelector, -} from '../selectors/settingSelectors'; +} from '../reducers/settings'; import Video from '../components/Video'; const { diff --git a/src/containers/WaitList.js b/src/containers/WaitList.js deleted file mode 100644 index f65050e49..000000000 --- a/src/containers/WaitList.js +++ /dev/null @@ -1,23 +0,0 @@ -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; -import { createStructuredSelector } from 'reselect'; - -import { - moveWaitlistUser, - removeWaitlistUser, -} from '../actions/ModerationActionCreators'; -import { waitlistUsersSelector } from '../selectors/waitlistSelectors'; -import { createRoleCheckSelector } from '../selectors/userSelectors'; -import WaitList from '../components/WaitList'; - -const mapStateToProps = createStructuredSelector({ - users: waitlistUsersSelector, - canMoveUsers: createRoleCheckSelector('waitlist.move'), -}); - -const mapDispatchToProps = (dispatch) => bindActionCreators({ - onMoveUser: moveWaitlistUser, - onRemoveUser: removeWaitlistUser, -}, dispatch); - -export default connect(mapStateToProps, mapDispatchToProps)(WaitList); diff --git a/src/containers/WaitList.tsx b/src/containers/WaitList.tsx new file mode 100644 index 000000000..3a97ffddb --- /dev/null +++ b/src/containers/WaitList.tsx @@ -0,0 +1,35 @@ +import { useCallback } from 'react'; +import { useSelector, useDispatch } from '../hooks/useRedux'; +import { + moveWaitlistUser, + removeWaitlistUser, +} from '../actions/ModerationActionCreators'; +import { waitlistUsersSelector } from '../selectors/waitlistSelectors'; +import { createRoleCheckSelector } from '../selectors/userSelectors'; +import WaitList from '../components/WaitList'; +import { User } from '../reducers/users'; + +const canMoveSelector = createRoleCheckSelector('waitlist.move'); + +function WaitListContainer() { + const dispatch = useDispatch(); + const users = useSelector(waitlistUsersSelector); + const canMoveUsers = useSelector(canMoveSelector); + const onMoveUser = useCallback((user: User, position: number) => { + dispatch(moveWaitlistUser(user, position)); + }, [dispatch]); + const onRemoveUser = useCallback((user: User) => { + dispatch(removeWaitlistUser(user)); + }, [dispatch]); + + return ( + <WaitList + users={users} + onMoveUser={onMoveUser} + onRemoveUser={onRemoveUser} + canMoveUsers={canMoveUsers} + /> + ); +} + +export default WaitListContainer; diff --git a/src/context/ClockContext.jsx b/src/context/ClockContext.jsx index b50ec7599..12576f55c 100644 --- a/src/context/ClockContext.jsx +++ b/src/context/ClockContext.jsx @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; +import { useDispatch } from '../hooks/useRedux'; import { createTimer, stopTimer } from '../actions/TickerActionCreators'; const { diff --git a/src/context/MediaSourceContext.jsx b/src/context/MediaSourceContext.jsx deleted file mode 100644 index eeea7ded9..000000000 --- a/src/context/MediaSourceContext.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const { - createContext, - useContext, - useMemo, -} = React; - -const InternalContext = createContext(null); -const { Consumer } = InternalContext; - -function useMediaSources() { - return useContext(InternalContext); -} - -function sourcesApi(sources) { - function getMediaSource(name) { - return sources[name]; - } - - function getAllMediaSources() { - return sources; - } - - return { getMediaSource, getAllMediaSources }; -} - -function Provider({ mediaSources, children }) { - const value = useMemo(() => sourcesApi(mediaSources), [mediaSources]); - return ( - <InternalContext.Provider value={value}> - {children} - </InternalContext.Provider> - ); -} - -Provider.propTypes = { - mediaSources: PropTypes.object.isRequired, - children: PropTypes.node.isRequired, -}; - -export default { Provider, Consumer }; -export { useMediaSources }; diff --git a/src/context/MediaSourceContext.tsx b/src/context/MediaSourceContext.tsx new file mode 100644 index 000000000..eaf172c82 --- /dev/null +++ b/src/context/MediaSourceContext.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import type { AnyAction } from 'redux'; +import { Media } from '../reducers/booth'; + +const { + createContext, + useContext, + useMemo, +} = React; + +export interface MediaSource<State extends object = Record<never, never>> { + name: string; + icon: URL; + logo: URL; + Player: React.ComponentType<{ + active: boolean, + enabled: boolean, + mode?: 'preview' | undefined, + volume: number, + media: Media, + seek: number, + onPlay?: () => void, + }>; + ImportForm?: React.ComponentType<{ + onShowImportPanel: () => void, + onHideImportPanel: () => void, + }>; + ImportPanel?: React.ComponentType<{ + onClosePanel: () => void, + } & State>; + reducer?: (state: State, action: AnyAction) => State; +} + +interface MediaSourceContextApi { + getMediaSource(name: string): MediaSource | undefined; + getAllMediaSources(): Record<string, MediaSource>; +} + +const InternalContext = createContext<MediaSourceContextApi | null>(null); +const { Consumer } = InternalContext; + +function useMediaSources() { + const ctx = useContext(InternalContext); + if (ctx == null) { + throw new Error('Cannot call `useMediaSources` outside a `MediaSourceContext`'); + } + return ctx; +} + +function sourcesApi(sources: Record<string, MediaSource>): MediaSourceContextApi { + function getMediaSource(name: string) { + return sources[name]; + } + + function getAllMediaSources() { + return sources; + } + + return { getMediaSource, getAllMediaSources }; +} + +type ProviderProps = { + mediaSources: Record<string, MediaSource>, + children: React.ReactNode, +}; +function Provider({ mediaSources, children }: ProviderProps) { + const value = useMemo(() => sourcesApi(mediaSources), [mediaSources]); + return ( + <InternalContext.Provider value={value}> + {children} + </InternalContext.Provider> + ); +} + +export default { Provider, Consumer }; +export { useMediaSources }; diff --git a/src/experimentalThemePlugin.js b/src/experimentalThemePlugin.js index 4de9298b2..ad0e4e920 100644 --- a/src/experimentalThemePlugin.js +++ b/src/experimentalThemePlugin.js @@ -1,5 +1,5 @@ import { bindActionCreators } from 'redux'; -import { debugApplyTheme, debugResetTheme } from './actions/ThemeActionCreators'; +import { apply as debugApplyTheme, reset as debugResetTheme } from './reducers/theme'; export default function experimentalThemePlugin(instance) { // `.store` will not yet be available when this is .use()d. diff --git a/src/hooks/useClock.js b/src/hooks/useClock.js index 20bf6aaf2..28fb73efa 100644 --- a/src/hooks/useClock.js +++ b/src/hooks/useClock.js @@ -1,7 +1,7 @@ import React from 'react'; -import { useStore } from 'react-redux'; import { useClock as useClockCallbacks } from '../context/ClockContext'; import { currentTimeSelector } from '../selectors/timeSelectors'; +import { useStore } from './useRedux'; const { useEffect, diff --git a/src/hooks/useCurrentUser.js b/src/hooks/useCurrentUser.js index 7e91345af..a0d539f5a 100644 --- a/src/hooks/useCurrentUser.js +++ b/src/hooks/useCurrentUser.js @@ -1,5 +1,5 @@ -import { useSelector } from 'react-redux'; import { currentUserSelector } from '../selectors/userSelectors'; +import { useSelector } from './useRedux'; export default function useCurrentUser() { return useSelector(currentUserSelector); diff --git a/src/hooks/useEmotes.ts b/src/hooks/useEmotes.ts new file mode 100644 index 000000000..16c3f63b3 --- /dev/null +++ b/src/hooks/useEmotes.ts @@ -0,0 +1,30 @@ +import { useMemo } from 'react'; +import useSWR from 'swr'; +import { useSelector } from './useRedux'; +import defaultEmoji from '../utils/emojiShortcodes'; +import uwFetch, { ListResponse } from '../utils/fetch'; + +type ServerEmote = { + name: string, + url: string, +}; + +function useEmotes() { + const { data: serverEmotes } = useSWR<ListResponse<ServerEmote>>('/emotes', uwFetch, { + revalidateOnFocus: false, + }); + + const configEmoji = useSelector((state) => state.config.emoji); + + const emotes: Record<string, string> = useMemo(() => ({ + ...defaultEmoji, + ...configEmoji, + ...(serverEmotes + ? Object.fromEntries(serverEmotes.data.map(({ name, url }) => [name, url])) + : undefined), + }), [configEmoji, serverEmotes]); + + return emotes; +} + +export default useEmotes; diff --git a/src/hooks/useHasRole.js b/src/hooks/useHasRole.js index d910df276..6a13bcc65 100644 --- a/src/hooks/useHasRole.js +++ b/src/hooks/useHasRole.js @@ -1,5 +1,5 @@ -import { useSelector } from 'react-redux'; import { currentUserHasRoleSelector } from '../selectors/userSelectors'; +import { useSelector } from './useRedux'; /** * Check if the current user has the given role. diff --git a/src/hooks/useIntl.js b/src/hooks/useIntl.js index 8f62ceca7..8d0fe923a 100644 --- a/src/hooks/useIntl.js +++ b/src/hooks/useIntl.js @@ -1,5 +1,5 @@ -import { useSelector } from 'react-redux'; import { createStructuredSelector } from 'reselect'; +import { useSelector } from './useRedux'; import { relativeTimeFormatterSelector, timeFormatterSelector, diff --git a/src/hooks/useRedux.ts b/src/hooks/useRedux.ts new file mode 100644 index 000000000..041ba7b80 --- /dev/null +++ b/src/hooks/useRedux.ts @@ -0,0 +1,11 @@ +import { + useDispatch as useDispatchBase, + useSelector as useSelectorBase, + useStore as useStoreBase, + type TypedUseSelectorHook, +} from 'react-redux'; +import type { AppDispatch, StoreState } from '../redux/configureStore'; + +export const useDispatch = useDispatchBase<AppDispatch>; +export const useSelector: TypedUseSelectorHook<StoreState> = useSelectorBase; +export const useStore = useStoreBase<StoreState>; diff --git a/src/hooks/useRoomHistory.ts b/src/hooks/useRoomHistory.ts new file mode 100644 index 000000000..009fa6098 --- /dev/null +++ b/src/hooks/useRoomHistory.ts @@ -0,0 +1,94 @@ +import useSWR from 'swr'; +import { useMemo } from 'react'; +import { useSelector } from './useRedux'; +import mergeIncludedModels from '../utils/mergeIncludedModels'; +import { currentPlaySelector } from '../selectors/boothSelectors'; +import type { Media } from '../reducers/booth'; +import type { User } from '../reducers/users'; +import uwFetch, { ListResponse } from '../utils/fetch'; + +interface ApiMedia { + _id: string + sourceID: string + sourceType: string + sourceData: object + artist: string + title: string + duration: number + thumbnail: string + createdAt: string + updatedAt: string +} + +interface ApiHistoryEntry { + _id: string, + user: User, + playlist: string, + item: string, + media: { + media: ApiMedia, + artist: string, + title: string, + start: number, + end: number, + sourceData: object, + }, + playedAt: string, + upvotes: string[], + downvotes: string[], + favorites: string[], +} + +export interface HistoryEntry { + _id: string; + user: User, + media: Media, + timestamp: number, + stats: { + upvotes: string[], + downvotes: string[], + favorites: string[], + }, +} + +export function normalizeFromApi(entry: ApiHistoryEntry) { + return { + _id: entry._id, + user: entry.user, + media: { + ...entry.media.media, + ...entry.media, + }, + timestamp: new Date(entry.playedAt).getTime(), + stats: { + upvotes: entry.upvotes ?? [], + downvotes: entry.downvotes ?? [], + favorites: entry.favorites ?? [], + }, + }; +} + +function useRoomHistory() { + const { data } = useSWR('/booth/history', uwFetch<ListResponse<ApiHistoryEntry>>, { + suspense: true, + }); + + const currentPlay = useSelector(currentPlaySelector); + const historyEntries = useMemo(() => { + return data ? mergeIncludedModels(data).map(normalizeFromApi) : []; + }, [data]); + + const media = useMemo(() => { + if (!currentPlay) { + return historyEntries; + } + if (historyEntries[0]._id === currentPlay._id) { + return [currentPlay, ...historyEntries.slice(1)]; + } + return [currentPlay, ...historyEntries]; + }, [currentPlay, historyEntries]); + + return media; +} + +export default useRoomHistory; diff --git a/src/index.jsx b/src/index.tsx similarity index 97% rename from src/index.jsx rename to src/index.tsx index d44fed219..563607653 100644 --- a/src/index.jsx +++ b/src/index.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import favicon from '../assets/favicon.ico'; import LoadingScreen from './components/LoadingScreen'; diff --git a/src/loadingUI.js b/src/loadingUI.js index c9e2bc1b8..5ff425079 100644 --- a/src/loadingUI.js +++ b/src/loadingUI.js @@ -35,6 +35,7 @@ export default async function load(uw) { // eslint-disable-next-line no-param-reassign el.hidden = false; }); + throw err; } finally { clearTimeout(longBuildTimer); } diff --git a/src/markdown.jsx b/src/markdown.tsx similarity index 83% rename from src/markdown.jsx rename to src/markdown.tsx index 4228dfba1..31dd875b1 100644 --- a/src/markdown.jsx +++ b/src/markdown.tsx @@ -1,10 +1,12 @@ import { readFileSync } from 'node:fs'; import React from 'react'; -import PropTypes from 'prop-types'; import Markdown from 'react-markdown'; import rehypeRaw from 'rehype-raw'; -function MarkdownPage({ path }) { +type MarkdownPageProps = { + path: string, +}; +function MarkdownPage({ path }: MarkdownPageProps) { const source = readFileSync(path, 'utf8'); return ( @@ -26,8 +28,4 @@ function MarkdownPage({ path }) { ); } -MarkdownPage.propTypes = { - path: PropTypes.string.isRequired, -}; - export default MarkdownPage; diff --git a/src/mobile/actions/OverlayActionCreators.js b/src/mobile/actions/OverlayActionCreators.js index df2d335fb..c8e7d0162 100644 --- a/src/mobile/actions/OverlayActionCreators.js +++ b/src/mobile/actions/OverlayActionCreators.js @@ -1,9 +1,9 @@ -import { toggleOverlay, togglePlaylistManager } from '../../actions/OverlayActionCreators'; -import { selectPlaylist } from '../../actions/PlaylistActionCreators'; +import { toggleOverlay } from '../../reducers/activeOverlay'; +import { selectPlaylist } from '../../reducers/playlists'; export function openPlaylist(playlistID) { return (dispatch) => { - dispatch(togglePlaylistManager()); + dispatch(toggleOverlay('playlistManager')); dispatch(selectPlaylist(playlistID)); }; } diff --git a/src/mobile/components/App/index.css b/src/mobile/components/App/index.css index 34b074925..86a80ac70 100644 --- a/src/mobile/components/App/index.css +++ b/src/mobile/components/App/index.css @@ -4,10 +4,7 @@ width: 100%; display: block; position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; + inset: 0; } .MobileApp-video { diff --git a/src/mobile/components/App/index.jsx b/src/mobile/components/App/index.jsx index 8e3c046bf..5af854d62 100644 --- a/src/mobile/components/App/index.jsx +++ b/src/mobile/components/App/index.jsx @@ -1,10 +1,10 @@ import cx from 'clsx'; import React from 'react'; import PropTypes from 'prop-types'; -import { useSelector } from 'react-redux'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import Snackbar from '@mui/material/Snackbar'; +import { useSelector } from '../../../hooks/useRedux'; import ErrorArea from '../../../containers/ErrorArea'; import PlaylistManager from '../../containers/PlaylistManager'; import RoomHistory from '../../containers/RoomHistory'; @@ -15,7 +15,7 @@ import DragLayer from '../../../containers/DragLayer'; import MainView from '../../containers/MainView'; import About from '../../containers/About'; import ServerList from '../../containers/ServerList'; -import { videoEnabledSelector } from '../../../selectors/settingSelectors'; +import { videoEnabledSelector } from '../../../reducers/settings'; import Overlays from './Overlays'; const { useState } = React; diff --git a/src/mobile/components/DrawerMenu/index.jsx b/src/mobile/components/DrawerMenu/index.tsx similarity index 65% rename from src/mobile/components/DrawerMenu/index.jsx rename to src/mobile/components/DrawerMenu/index.tsx index 39e1864e5..0ae172c16 100644 --- a/src/mobile/components/DrawerMenu/index.jsx +++ b/src/mobile/components/DrawerMenu/index.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import { useCallback, useMemo } from 'react'; +import useSWR from 'swr'; import { useTranslator } from '@u-wave/react-translate'; import Drawer from '@mui/material/Drawer'; import MenuList from '@mui/material/MenuList'; @@ -11,20 +11,43 @@ import Divider from '@mui/material/Divider'; import { mdiCheck } from '@mdi/js'; import UserCard from '../../../components/UserCard/UserCard'; import SvgIcon from '../../../components/SvgIcon'; - -const { - useCallback, -} = React; +import { useSelector } from '../../../hooks/useRedux'; +import { activePlaylistIDSelector } from '../../../selectors/playlistSelectors'; +import useCurrentUser from '../../../hooks/useCurrentUser'; +import uwFetch, { ListResponse } from '../../../utils/fetch'; const classes = { paper: 'DrawerMenu', }; +interface PlaylistMeta { + _id: string; + name: string; + size: number; +} + +type PlaylistsProps = { + title: React.ReactNode, + onShowPlaylist: (id: string) => void, +}; function Playlists({ title, - playlists, onShowPlaylist, -}) { +}: PlaylistsProps) { + const { data: playlistsFromApi } = useSWR<ListResponse<PlaylistMeta>>('/playlists', uwFetch); + const activePlaylistID = useSelector(activePlaylistIDSelector); + const playlists = useMemo(() => { + return playlistsFromApi?.data.map((playlist) => { + if (playlist._id === activePlaylistID) { + return { + ...playlist, + active: true, + }; + } + return playlist as (typeof playlist & { active?: boolean }); + }); + }, [playlistsFromApi, activePlaylistID]); + const header = ( <ListSubheader> {title} @@ -33,7 +56,7 @@ function Playlists({ return ( <MenuList subheader={header}> - {playlists.map((playlist) => ( + {playlists?.map((playlist) => ( <MenuItem key={playlist._id} onClick={(event) => { @@ -55,15 +78,16 @@ function Playlists({ ); } -Playlists.propTypes = { - title: PropTypes.string.isRequired, - playlists: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string.isRequired })).isRequired, - onShowPlaylist: PropTypes.func.isRequired, +type DrawerMenuProps = { + open: boolean, + hasAboutPage: boolean, + onShowAbout: () => void, + onShowServerList: () => void, + onShowSettings: () => void, + onShowPlaylist: (id: string) => void, + onDrawerClose: () => void, }; - function DrawerMenu({ - user, - playlists, open, hasAboutPage, onShowAbout, @@ -71,7 +95,8 @@ function DrawerMenu({ onShowSettings, onShowPlaylist, onDrawerClose, -}) { +}: DrawerMenuProps) { + const user = useCurrentUser(); const { t } = useTranslator(); const handleShowAbout = useCallback(() => { @@ -86,7 +111,7 @@ function DrawerMenu({ onShowSettings(); onDrawerClose(); }, [onShowSettings, onDrawerClose]); - const handleShowPlaylist = useCallback((id) => { + const handleShowPlaylist = useCallback((id: string) => { onShowPlaylist(id); onDrawerClose(); }, [onShowPlaylist, onDrawerClose]); @@ -112,7 +137,6 @@ function DrawerMenu({ <Divider /> <Playlists title={t('playlists.title')} - playlists={playlists} onShowPlaylist={handleShowPlaylist} /> </> @@ -121,16 +145,4 @@ function DrawerMenu({ ); } -DrawerMenu.propTypes = { - user: PropTypes.object, - playlists: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string.isRequired })), - open: PropTypes.bool.isRequired, - hasAboutPage: PropTypes.bool.isRequired, - onShowAbout: PropTypes.func.isRequired, - onShowServerList: PropTypes.func.isRequired, - onShowSettings: PropTypes.func.isRequired, - onShowPlaylist: PropTypes.func.isRequired, - onDrawerClose: PropTypes.func.isRequired, -}; - export default DrawerMenu; diff --git a/src/mobile/components/MainView/VideoDisabledMessage.css b/src/mobile/components/MainView/VideoDisabledMessage.css index 8a5b34bed..69d83bf29 100644 --- a/src/mobile/components/MainView/VideoDisabledMessage.css +++ b/src/mobile/components/MainView/VideoDisabledMessage.css @@ -1,9 +1,6 @@ .VideoDisabledMessage { position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; + inset: 0; background: rgb(0 0 0 / 30%); color: white; display: flex; diff --git a/src/mobile/components/MainView/index.css b/src/mobile/components/MainView/index.css index 118ae310f..352524878 100644 --- a/src/mobile/components/MainView/index.css +++ b/src/mobile/components/MainView/index.css @@ -21,7 +21,7 @@ height: calc(100% - var(--app-bar-height)); } -@media (min-width: 600px) { +@media (width >= 600px) { .MainView { --app-bar-height: 64px; } diff --git a/src/mobile/components/RoomHistory/HistoryList.jsx b/src/mobile/components/RoomHistory/HistoryList.jsx index 77d41f034..8128e40ef 100644 --- a/src/mobile/components/RoomHistory/HistoryList.jsx +++ b/src/mobile/components/RoomHistory/HistoryList.jsx @@ -1,15 +1,17 @@ -import React from 'react'; import List from '@mui/material/List'; -import Base from '../../../components/MediaList/BaseMediaList'; +import MediaListBase from '../../../components/MediaList/BaseMediaList'; import HistoryRow from './Row'; +import useRoomHistory from '../../../hooks/useRoomHistory'; + +function HistoryList() { + const media = useRoomHistory(); -function HistoryList(props) { return ( - <Base + <MediaListBase className="RoomHistory-list" listComponent={List} rowComponent={HistoryRow} - {...props} + media={media} /> ); } diff --git a/src/mobile/components/RoomHistory/Votes.jsx b/src/mobile/components/RoomHistory/Votes.jsx index 2d435372a..c15d3eed2 100644 --- a/src/mobile/components/RoomHistory/Votes.jsx +++ b/src/mobile/components/RoomHistory/Votes.jsx @@ -1,14 +1,17 @@ import cx from 'clsx'; -import React from 'react'; import PropTypes from 'prop-types'; import { mdiHeart, mdiHeartOutline, mdiThumbDown, mdiThumbUp, } from '@mdi/js'; import SvgIcon from '../../../components/SvgIcon'; +import useCurrentUser from '../../../hooks/useCurrentUser'; + +function Votes({ upvotes, downvotes, favorites }) { + const user = useCurrentUser(); + const isUpvote = user ? upvotes.includes(user._id) : false; + const isDownvote = user ? downvotes.includes(user._id) : false; + const isFavorite = user ? favorites.includes(user._id) : false; -function Votes({ - upvotes, downvotes, favorites, isUpvote, isDownvote, isFavorite, -}) { return ( <div className="MobileHistoryVotes"> <div className="MobileHistoryVotes-vote"> @@ -31,9 +34,6 @@ Votes.propTypes = { upvotes: PropTypes.array.isRequired, favorites: PropTypes.array.isRequired, downvotes: PropTypes.array.isRequired, - isUpvote: PropTypes.bool.isRequired, - isFavorite: PropTypes.bool.isRequired, - isDownvote: PropTypes.bool.isRequired, }; export default Votes; diff --git a/src/mobile/containers/Chat.jsx b/src/mobile/containers/Chat.jsx index e6db710dc..3a50ffe82 100644 --- a/src/mobile/containers/Chat.jsx +++ b/src/mobile/containers/Chat.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import { useSelector } from 'react-redux'; +import { useSelector } from '../../hooks/useRedux'; import { isLoggedInSelector } from '../../selectors/userSelectors'; import ChatMessages from '../../containers/ChatMessages'; import ChatInput from '../../containers/ChatInput'; diff --git a/src/mobile/containers/DrawerMenu.jsx b/src/mobile/containers/DrawerMenu.jsx index b18438c5b..a52b1793b 100644 --- a/src/mobile/containers/DrawerMenu.jsx +++ b/src/mobile/containers/DrawerMenu.jsx @@ -1,8 +1,6 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { currentUserSelector } from '../../selectors/userSelectors'; -import { playlistsSelector } from '../../selectors/playlistSelectors'; -import { toggleSettings, toggleAbout } from '../../actions/OverlayActionCreators'; +import { useSelector, useDispatch } from '../../hooks/useRedux'; +import { toggleOverlay } from '../../reducers/activeOverlay'; import { drawerIsOpenSelector } from '../selectors/drawerSelectors'; import { setDrawer } from '../actions/DrawerActionCreators'; import { toggleServerList, openPlaylist } from '../actions/OverlayActionCreators'; @@ -16,13 +14,11 @@ const { function DrawerMenuContainer() { const uwave = useUwave(); const hasAboutPage = !!(uwave && uwave.getAboutPageComponent()); - const user = useSelector(currentUserSelector); - const playlists = useSelector(playlistsSelector); const open = useSelector(drawerIsOpenSelector); const dispatch = useDispatch(); - const onShowAbout = useCallback(() => dispatch(toggleAbout()), [dispatch]); + const onShowAbout = useCallback(() => dispatch(toggleOverlay('about')), [dispatch]); const onShowServerList = useCallback(() => dispatch(toggleServerList()), [dispatch]); - const onShowSettings = useCallback(() => dispatch(toggleSettings()), [dispatch]); + const onShowSettings = useCallback(() => dispatch(toggleOverlay('settings')), [dispatch]); const onShowPlaylist = useCallback( (playlistID) => dispatch(openPlaylist(playlistID)), [dispatch], @@ -32,8 +28,6 @@ function DrawerMenuContainer() { return ( <DrawerMenu hasAboutPage={hasAboutPage} - user={user} - playlists={playlists} open={open} onShowAbout={onShowAbout} onShowServerList={onShowServerList} diff --git a/src/mobile/containers/LoginButtons.jsx b/src/mobile/containers/LoginButtons.jsx index 569c3e3ca..39a3d73a0 100644 --- a/src/mobile/containers/LoginButtons.jsx +++ b/src/mobile/containers/LoginButtons.jsx @@ -1,7 +1,7 @@ import React from 'react'; -import { useDispatch } from 'react-redux'; import { useTranslator } from '@u-wave/react-translate'; import Button from '@mui/material/Button'; +import { useDispatch } from '../../hooks/useRedux'; import { openLoginDialog, openRegisterDialog } from '../../actions/DialogActionCreators'; const wrapperStyle = { diff --git a/src/mobile/containers/MainView.jsx b/src/mobile/containers/MainView.jsx index 184780a59..d3164fe3a 100644 --- a/src/mobile/containers/MainView.jsx +++ b/src/mobile/containers/MainView.jsx @@ -1,17 +1,13 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { toggleRoomHistory } from '../../actions/OverlayActionCreators'; -import { set } from '../../actions/SettingsActionCreators'; -import { - mediaSelector, - startTimeSelector, -} from '../../selectors/boothSelectors'; +import { useSelector, useDispatch } from '../../hooks/useRedux'; +import { toggleOverlay } from '../../reducers/activeOverlay'; +import { setVideoEnabled, videoEnabledSelector } from '../../reducers/settings'; +import { mediaSelector, startTimeSelector } from '../../selectors/boothSelectors'; import { sizeSelector as waitlistSizeSelector, positionSelector as waitlistPositionSelector, } from '../../selectors/waitlistSelectors'; import { playlistsSelector } from '../../selectors/playlistSelectors'; -import { videoEnabledSelector } from '../../selectors/settingSelectors'; import { openDrawer, openUsersDrawer } from '../actions/DrawerActionCreators'; import MainView from '../components/MainView'; @@ -27,10 +23,10 @@ function MainViewContainer() { const waitlistSize = useSelector(waitlistSizeSelector); const playlists = useSelector(playlistsSelector); const dispatch = useDispatch(); - const onOpenRoomHistory = useCallback(() => dispatch(toggleRoomHistory()), [dispatch]); + const onOpenRoomHistory = useCallback(() => dispatch(toggleOverlay('roomHistory')), [dispatch]); const onOpenDrawer = useCallback(() => dispatch(openDrawer()), [dispatch]); const onOpenWaitlist = useCallback(() => dispatch(openUsersDrawer()), [dispatch]); - const onEnableVideo = useCallback(() => dispatch(set('videoEnabled', true)), [dispatch]); + const onEnableVideo = useCallback(() => dispatch(setVideoEnabled(true)), [dispatch]); return ( <MainView diff --git a/src/mobile/containers/PlaylistManager.jsx b/src/mobile/containers/PlaylistManager.jsx index 403efb09d..dec571466 100644 --- a/src/mobile/containers/PlaylistManager.jsx +++ b/src/mobile/containers/PlaylistManager.jsx @@ -1,37 +1,36 @@ import React from 'react'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch, useSelector } from '../../hooks/useRedux'; import { selectedPlaylistSelector, filteredSelectedPlaylistItemsSelector, + selectedPlaylistIDSelector, } from '../../selectors/playlistSelectors'; -import { showSearchResultsSelector } from '../../selectors/searchSelectors'; -import { showImportPanelSelector } from '../../selectors/importSelectors'; import createLazyOverlay from '../../components/LazyOverlay'; -import { closeAll } from '../../actions/OverlayActionCreators'; +import { closeOverlay } from '../../reducers/activeOverlay'; +import { importPanelSymbol, searchPanelSymbol } from '../../reducers/playlists'; const { useCallback, } = React; const PlaylistManager = createLazyOverlay({ - loader: () => import('../components/PlaylistManager'), + Component: React.lazy(() => import('../components/PlaylistManager')), title: (t) => t('playlists.title'), }); function PlaylistManagerContainer() { + const selectedPlaylistID = useSelector(selectedPlaylistIDSelector); const selectedPlaylist = useSelector(selectedPlaylistSelector); const selectedItems = useSelector(filteredSelectedPlaylistItemsSelector); - const showImportPanel = useSelector(showImportPanelSelector); - const showSearchResults = useSelector(showSearchResultsSelector); const dispatch = useDispatch(); - const onCloseOverlay = useCallback(() => dispatch(closeAll()), [dispatch]); + const onCloseOverlay = useCallback(() => dispatch(closeOverlay()), [dispatch]); return ( <PlaylistManager selectedPlaylist={selectedPlaylist} selectedItems={selectedItems} - showImportPanel={showImportPanel} - showSearchResults={showSearchResults} + showImportPanel={selectedPlaylistID === importPanelSymbol} + showSearchResults={selectedPlaylistID === searchPanelSymbol} onCloseOverlay={onCloseOverlay} /> ); diff --git a/src/mobile/containers/PlaylistPanel.js b/src/mobile/containers/PlaylistPanel.js index c60cbf3d9..c5c7d0e09 100644 --- a/src/mobile/containers/PlaylistPanel.js +++ b/src/mobile/containers/PlaylistPanel.js @@ -8,17 +8,19 @@ import { isFilteredSelector, } from '../../selectors/playlistSelectors'; import { - moveMedia, filterPlaylistItems, - renamePlaylist, deletePlaylist, cannotDeleteActivePlaylist, shufflePlaylist, - activatePlaylist, loadPlaylist, loadFilteredPlaylistItems, } from '../../actions/PlaylistActionCreators'; import PlaylistPanel from '../components/PlaylistManager/PlaylistPanel'; +import { + renamePlaylist, + activatePlaylist, + movePlaylistItems, +} from '../../reducers/playlists'; const mapStateToProps = createStructuredSelector({ playlist: selectedPlaylistSelector, @@ -27,8 +29,8 @@ const mapStateToProps = createStructuredSelector({ isFiltered: isFilteredSelector, }); -const onMoveMedia = (playlist) => (media, opts) => ( - moveMedia(playlist, media, opts) +const onMoveMedia = (playlistID) => (media, opts) => ( + movePlaylistItems({ playlistID, medias: media, target: opts }) ); const onLoadPlaylistPage = ({ isFiltered, playlist }) => (page) => ( isFiltered ? loadFilteredPlaylistItems(playlist._id, page) @@ -51,7 +53,7 @@ const mergeProps = (state, { dispatch }, props) => ({ ...bindActionCreators({ onShufflePlaylist: shufflePlaylist.bind(null, state.playlist._id), onActivatePlaylist: activatePlaylist.bind(null, state.playlist._id), - onRenamePlaylist: renamePlaylist.bind(null, state.playlist._id), + onRenamePlaylist: (name) => renamePlaylist({ playlistID: state.playlist._id, name }), onDeletePlaylist: deletePlaylist.bind(null, state.playlist._id), onNotDeletable: cannotDeleteActivePlaylist, onMoveMedia: onMoveMedia(state.playlist._id), diff --git a/src/mobile/containers/RoomHistory.jsx b/src/mobile/containers/RoomHistory.jsx index 00b575894..b12e7e116 100644 --- a/src/mobile/containers/RoomHistory.jsx +++ b/src/mobile/containers/RoomHistory.jsx @@ -1,24 +1,15 @@ import React from 'react'; -import { connect } from 'react-redux'; -import { createStructuredSelector } from 'reselect'; -import { roomHistoryWithVotesSelector } from '../../selectors/roomHistorySelectors'; import Overlay from '../../components/Overlay'; import createLazyOverlay from '../../components/LazyOverlay'; -const mapStateToProps = createStructuredSelector({ - media: roomHistoryWithVotesSelector, -}); - -const enhance = connect(mapStateToProps); - function RoomHistoryOverlay(props) { return <Overlay {...props} direction="top" />; } const RoomHistory = createLazyOverlay({ - loader: () => import('../components/RoomHistory'), + loader: React.lazy(() => import('../components/RoomHistory')), title: (t) => t('history.title'), OverlayComponent: RoomHistoryOverlay, }); -export default enhance(RoomHistory); +export default RoomHistory; diff --git a/src/mobile/containers/Video.jsx b/src/mobile/containers/Video.jsx index 157603ca8..be68e207e 100644 --- a/src/mobile/containers/Video.jsx +++ b/src/mobile/containers/Video.jsx @@ -1,10 +1,10 @@ import React from 'react'; -import { useSelector, useDispatch } from 'react-redux'; +import { useSelector, useDispatch } from '../../hooks/useRedux'; import useClock from '../../hooks/useClock'; import { - openFavoriteMenu, vote, } from '../../actions/VoteActionCreators'; +import { openFavoriteMenu } from '../../reducers/addToPlaylistMenu'; import { historyIDSelector, mediaSelector, @@ -28,15 +28,15 @@ function VideoContainer(props) { const volume = useSelector(mobilePlaybackVolumeSelector); const voteStats = useSelector(currentVoteStatsSelector); const dispatch = useDispatch(); - const onUpvote = useCallback(() => dispatch(vote({ - historyID, - direction: 1, - })), [dispatch, historyID]); - const onDownvote = useCallback(() => dispatch(vote({ - historyID, - direction: -1, - })), [dispatch, historyID]); - const onFavorite = useCallback((...args) => dispatch(openFavoriteMenu(...args)), [dispatch]); + const onUpvote = useCallback(() => { + dispatch(vote({ historyID, direction: 1 })); + }, [dispatch, historyID]); + const onDownvote = useCallback(() => { + dispatch(vote({ historyID, direction: -1 })); + }, [dispatch, historyID]); + const onFavorite = useCallback((position) => { + dispatch(openFavoriteMenu(historyID, position)); + }, [historyID, dispatch]); return ( <Video diff --git a/src/reducers/__tests__/activeOverlay.js b/src/reducers/__tests__/activeOverlay.js index 55d77c231..670ad9c72 100644 --- a/src/reducers/__tests__/activeOverlay.js +++ b/src/reducers/__tests__/activeOverlay.js @@ -1,55 +1,60 @@ -import { openOverlay, closeAll, toggleOverlay } from '../../actions/OverlayActionCreators'; +import { + openOverlay, + closeOverlay, + toggleOverlay, + selectOverlay, +} from '../activeOverlay'; import createStore from '../../redux/configureStore'; describe('reducers/activeOverlay', () => { it('should not respond to unrelated actions', () => { const { dispatch, getState } = createStore(); - expect(getState().activeOverlay).toBeNull(); + expect(selectOverlay(getState())).toBeNull(); dispatch({ type: 'randomOtherAction', payload: {} }); - expect(getState().activeOverlay).toBeNull(); + expect(selectOverlay(getState())).toBeNull(); }); - describe('action: overlay/OPEN_OVERLAY', () => { + describe('action: openOverlay', () => { it('should set the current overlay', () => { const { dispatch, getState } = createStore(); dispatch(openOverlay('playlistManager')); - expect(getState().activeOverlay).toEqual('playlistManager'); + expect(selectOverlay(getState())).toBe('playlistManager'); dispatch(openOverlay('settings')); - expect(getState().activeOverlay).toEqual('settings'); + expect(selectOverlay(getState())).toBe('settings'); }); }); - describe('action: overlay/CLOSE_OVERLAY', () => { + describe('action: closeOverlay', () => { it('should close the current overlay', () => { const { dispatch, getState } = createStore(); dispatch(openOverlay('playlistManager')); - expect(getState().activeOverlay).toEqual('playlistManager'); - dispatch(closeAll()); - expect(getState().activeOverlay).toBeNull(); + expect(selectOverlay(getState())).toBe('playlistManager'); + dispatch(closeOverlay()); + expect(selectOverlay(getState())).toBeNull(); }); }); - describe('action: overlay/TOGGLE_OVERLAY', () => { + describe('action: toggleOverlay', () => { const { dispatch, getState } = createStore(); it('should open the given overlay if no overlay is open', () => { - expect(getState().activeOverlay).toBeNull(); + expect(selectOverlay(getState())).toBeNull(); dispatch(toggleOverlay('playlistManager')); - expect(getState().activeOverlay).toEqual('playlistManager'); + expect(selectOverlay(getState())).toBe('playlistManager'); }); it('should close the given overlay if it is currently open', () => { - expect(getState().activeOverlay).toEqual('playlistManager'); + expect(selectOverlay(getState())).toBe('playlistManager'); dispatch(toggleOverlay('playlistManager')); - expect(getState().activeOverlay).toBeNull(); + expect(selectOverlay(getState())).toBeNull(); }); it('should switch to the given overlay if another overlay is already open', () => { dispatch(openOverlay('playlistManager')); - expect(getState().activeOverlay).toEqual('playlistManager'); + expect(selectOverlay(getState())).toBe('playlistManager'); dispatch(toggleOverlay('settings')); - expect(getState().activeOverlay).toEqual('settings'); + expect(selectOverlay(getState())).toBe('settings'); }); }); }); diff --git a/src/reducers/__tests__/addToPlaylistMenu.js b/src/reducers/__tests__/addToPlaylistMenu.js index 70a78659b..b796a3ceb 100644 --- a/src/reducers/__tests__/addToPlaylistMenu.js +++ b/src/reducers/__tests__/addToPlaylistMenu.js @@ -1,43 +1,45 @@ import createStore from '../../redux/configureStore'; -import { addMediaMenu, closeAddMediaMenu } from '../../actions/PlaylistActionCreators'; -import * as s from '../../selectors/addToPlaylistMenuSelectors'; +import { + open, + close, + isOpenSelector, + isFavoriteSelector, + positionSelector, + mediaSelector, +} from '../addToPlaylistMenu'; describe('reducers/addToPlaylistMenu', () => { it('should default to a closed context menu', () => { const { getState } = createStore(); - expect(s.addToPlaylistMenuSelector(getState())).toEqual({ - type: null, - open: false, - position: { x: 0, y: 0 }, - playlists: [], - }); + expect(isOpenSelector(getState())).toBe(false); }); - describe('action: playlists/OPEN_ADD_MEDIA_MENU', () => { + describe('action: open', () => { const { dispatch, getState } = createStore(); it('should open the menu at the given position with the given media', () => { - dispatch(addMediaMenu( - [{ _id: 'mmedia' }], - { x: 800, y: 300 }, - )); - expect(s.mediaSelector(getState())).toEqual([{ _id: 'mmedia' }]); - expect(s.isOpenSelector(getState())).toBe(true); - expect(s.isFavoriteSelector(getState())).toBe(false); - expect(s.positionSelector(getState())).toEqual({ x: 800, y: 300 }); + dispatch(open({ + type: 'add', + position: { x: 800, y: 300 }, + data: { media: [{ _id: 'mmedia' }] }, + })); + expect(mediaSelector(getState())).toEqual([{ _id: 'mmedia' }]); + expect(isOpenSelector(getState())).toBe(true); + expect(isFavoriteSelector(getState())).toBe(false); + expect(positionSelector(getState())).toEqual({ x: 800, y: 300 }); }); }); - describe('action: playlists/CLOSE_ADD_MEDIA_MENU', () => { + describe('action: close', () => { const { dispatch, getState } = createStore(); it('should close the menu', () => { - dispatch(addMediaMenu( + dispatch(open( [{ _id: 'mmedia' }], { x: 800, y: 300 }, )); - expect(s.isOpenSelector(getState())).toBe(true); + expect(isOpenSelector(getState())).toBe(true); - dispatch(closeAddMediaMenu()); - expect(s.isOpenSelector(getState())).toBe(false); + dispatch(close()); + expect(isOpenSelector(getState())).toBe(false); }); }); }); diff --git a/src/reducers/__tests__/auth.js b/src/reducers/__tests__/auth.js index c2eeca04c..e3ff47d66 100644 --- a/src/reducers/__tests__/auth.js +++ b/src/reducers/__tests__/auth.js @@ -1,8 +1,6 @@ -import { LOGIN_COMPLETE } from '../../constants/ActionTypes'; import createStore from '../../redux/configureStore'; import * as s from '../../selectors/userSelectors'; -import { loginComplete, setSessionToken } from '../../actions/LoginActionCreators'; -import { setUsers } from '../../actions/UserActionCreators'; +import { setSessionToken } from '../../actions/LoginActionCreators'; describe('reducers/auth', () => { it('should not respond to unrelated actions', () => { @@ -24,25 +22,4 @@ describe('reducers/auth', () => { expect(s.tokenSelector(getState())).toBe('test token'); }); }); - - describe('action: auth/LOGIN_COMPLETE', () => { - const { dispatch, getState } = createStore(); - it('should set the current user if successful', () => { - const userObj = { _id: 'test user' }; - dispatch(setUsers([userObj])); - dispatch(loginComplete({ token: 'test token', user: userObj })); - expect(s.tokenSelector(getState())).toBe('test token'); - expect(s.currentUserSelector(getState())).toEqual(userObj); - }); - - it('should save the error if unsuccessful', () => { - dispatch({ - type: LOGIN_COMPLETE, - payload: new Error('failed'), - error: true, - }); - expect(s.tokenSelector(getState())).toBeNull(); - expect(s.currentUserSelector(getState())).toBeNull(); - }); - }); }); diff --git a/src/reducers/__tests__/booth.js b/src/reducers/__tests__/booth.js index ebf93d674..07c014802 100644 --- a/src/reducers/__tests__/booth.js +++ b/src/reducers/__tests__/booth.js @@ -1,6 +1,4 @@ -import { ADVANCE } from '../../constants/ActionTypes'; -import { advanceToEmpty } from '../../actions/BoothActionCreators'; -import booth from '../booth'; +import booth, { advance } from '../booth'; describe('reducers/booth', () => { const initialState = () => booth(undefined, { type: '@@redux/INIT' }); @@ -26,15 +24,12 @@ describe('reducers/booth', () => { // Weirdly, there are two different advance object formats in use // client-side. // TODO fix that? :P - const state = booth(initialState(), { - type: ADVANCE, - payload: { - historyID: 'someRandomID', - userID: 'seventeen', - media: { artist: 'about tess', title: 'Imaginedit' }, - timestamp: 1449767164107, - }, - }); + const state = booth(initialState(), advance({ + historyID: 'someRandomID', + userID: 'seventeen', + media: { artist: 'about tess', title: 'Imaginedit' }, + timestamp: 1449767164107, + })); expect(state).toEqual({ historyID: 'someRandomID', djID: 'seventeen', @@ -45,7 +40,7 @@ describe('reducers/booth', () => { }); it('should stop playing if there is no next song', () => { - const state = booth(initialState(), advanceToEmpty()); + const state = booth(initialState(), advance(null)); expect(state).toEqual({ historyID: null, djID: null, diff --git a/src/reducers/__tests__/chat.js b/src/reducers/__tests__/chat.js index 06a80d6ec..eb5f65ffb 100644 --- a/src/reducers/__tests__/chat.js +++ b/src/reducers/__tests__/chat.js @@ -1,9 +1,18 @@ +import { vi } from 'vitest'; import createStore from '../../redux/configureStore'; -import { setUsers } from '../../actions/UserActionCreators'; +import * as actions from '../chat'; import * as a from '../../actions/ChatActionCreators'; import * as s from '../../selectors/chatSelectors'; import * as userSelectors from '../../selectors/userSelectors'; +function preloadUsers(users) { + return { + users: { + users: Object.fromEntries(users.map((user) => [user._id, user])), + }, + }; +} + describe('reducers/chat', () => { it('should not respond to unrelated actions', () => { const { dispatch, getState } = createStore(); @@ -30,14 +39,13 @@ describe('reducers/chat', () => { }; it('should add a message to the messages list', () => { - const { dispatch, getState } = createStore(); - dispatch(setUsers([testUser])); + const store = createStore(preloadUsers([testUser])); - expect(s.messagesSelector(getState())).toHaveLength(0); + expect(s.messagesSelector(store.getState())).toHaveLength(0); - dispatch(a.receive(testMessage)); + store.dispatch(a.receive(testMessage)); - expect(s.messagesSelector(getState())[0]).toEqual({ + expect(s.messagesSelector(store.getState())[0]).toEqual({ _id: testMessage._id, type: 'chat', userID: testMessage.userID, @@ -56,10 +64,9 @@ describe('reducers/chat', () => { username: 'SendingUser', }; - jest.spyOn(userSelectors, 'currentUserSelector').mockReturnValue(inFlightUser); + vi.spyOn(userSelectors, 'currentUserSelector').mockReturnValue(inFlightUser); - const { dispatch, getState } = createStore(); - dispatch(setUsers([testUser, inFlightUser])); + const { dispatch, getState } = createStore(preloadUsers([testUser, inFlightUser])); // test setup: start w/ one received message and one that's been sent but // is pending. @@ -102,7 +109,7 @@ describe('reducers/chat', () => { it('should add an in-flight message to the messages list immediately', () => { const { dispatch, getState } = createStore(); - jest.spyOn(userSelectors, 'currentUserSelector').mockReturnValue(testMessage.user); + vi.spyOn(userSelectors, 'currentUserSelector').mockReturnValue(testMessage.user); dispatch(a.sendChat(testMessage.message)); expect(s.messagesSelector(getState())).toHaveLength(1); @@ -123,7 +130,7 @@ describe('reducers/chat', () => { const MESSAGES = 100; const { dispatch, getState } = createStore(); for (let i = 0; i < MESSAGES; i += 1) { - dispatch(a.log(`Test message ${i}`)); + dispatch(actions.log(`Test message ${i}`)); } expect(s.messagesSelector(getState())).toHaveLength(MESSAGES); }); @@ -140,12 +147,12 @@ describe('reducers/chat', () => { ]; beforeEach(() => { - ({ dispatch, getState } = createStore()); - dispatch(setUsers(testUsers)); + ({ dispatch, getState } = createStore(preloadUsers(testUsers))); }); const addTestMute = () => { - dispatch(a.muteUser('1', { + dispatch(actions.muteUser({ + userID: '1', moderatorID: '4', expiresAt: Date.now() + 3000, })); @@ -154,7 +161,8 @@ describe('reducers/chat', () => { it('chat/MUTE_USER should register muted users', () => { expect(s.mutedUsersSelector(getState())).toHaveLength(0); - dispatch(a.muteUser('1', { + dispatch(actions.muteUser({ + userID: '1', moderatorID: '4', expiresAt: Date.now() + 3000, })); @@ -179,7 +187,7 @@ describe('reducers/chat', () => { addTestMute(); expect(s.mutedUsersSelector(getState())).toHaveLength(1); - dispatch(a.unmuteUser('1', { moderatorID: '3' })); + dispatch(actions.unmuteUser({ userID: '1', moderatorID: '3' })); expect(s.mutedUsersSelector(getState())).toHaveLength(0); expect(s.messagesSelector(getState())).toHaveLength(0); diff --git a/src/reducers/__tests__/dialogs.js b/src/reducers/__tests__/dialogs.js index d38508b04..92b0cd2dc 100644 --- a/src/reducers/__tests__/dialogs.js +++ b/src/reducers/__tests__/dialogs.js @@ -6,7 +6,7 @@ import dialogs from '../dialogs'; const closedDialog = { open: false, - payload: {}, + payload: null, }; const initialState = () => dialogs(undefined, { type: '@@redux/INIT' }); @@ -29,7 +29,7 @@ const testDialogClose = (type, prop, text) => { state = dialogs(state, { type }); expect(state[prop]).toEqual({ open: false, - payload: {}, + payload: null, }); }); }; diff --git a/src/reducers/__tests__/playlists.js b/src/reducers/__tests__/playlists.js index df181610d..3ff320129 100644 --- a/src/reducers/__tests__/playlists.js +++ b/src/reducers/__tests__/playlists.js @@ -1,48 +1,47 @@ -import fetch from 'jest-fetch-mock'; import createStore from '../../redux/configureStore'; import * as a from '../../actions/PlaylistActionCreators'; import { favoriteMediaComplete } from '../../actions/VoteActionCreators'; import * as s from '../../selectors/playlistSelectors'; - -fetch.enableMocks(); - -const initialiseStore = a.setPlaylists([ - { _id: 1, name: 'Playlist One', size: 5 }, - { _id: 2, name: 'Playlist Two', size: 0 }, - { _id: 3, name: 'Playlist Three', size: 500 }, - { _id: 4, name: 'Playlist Four', size: 120 }, -]); +import { + activatePlaylist, + addPlaylistItems, + movePlaylistItems, + selectPlaylist, +} from '../playlists'; + +function preloadPlaylists(playlists) { + return { + playlists: { + playlists: Object.fromEntries(playlists.map((playlist) => [playlist._id, playlist])), + playlistItems: {}, + activePlaylistID: null, + selectedPlaylistID: null, + currentFilter: null, + }, + }; +} +const testPlaylists = [ + { _id: 'ZcU_8-UyI10Tx79R4CjRv', name: 'Playlist One', size: 5 }, + { _id: 'rOIrcr6zD06gVH-fg4G4k', name: 'Playlist Two', size: 0 }, + { _id: 'Kzy3kUckOgAV7iwrekHSE', name: 'Playlist Three', size: 500 }, + { _id: 'pKOr6JXTznTa1Y5g99LKH', name: 'Playlist Four', size: 120 }, +]; const initialisePlaylist = (dispatch) => { const items = [ - { _id: 5, artist: 'Taylor Swift', title: 'New Romantics' }, - { _id: 6, artist: 'Swiimers', title: 'Polaris' }, - { _id: 7, artist: 'of Montreal', title: 'Gronlandic Edit' }, - { _id: 8, artist: 'Angel Haze', title: 'A Tribe Called Red' }, - { _id: 9, artist: 'tricot', title: '99.974°C' }, + { _id: 'Cnun9zo6oNr1wMCFRhnaO', artist: 'Taylor Swift', title: 'New Romantics' }, + { _id: 'PD_n42XxNCdQjDy5VB_SE', artist: 'Swiimers', title: 'Polaris' }, + { _id: '66Z6y6JA4m5WmmNF3O7Ii', artist: 'of Montreal', title: 'Gronlandic Edit' }, + { _id: 'NkwUIwNmraSZ4A4eiC3GQ', artist: 'Angel Haze', title: 'A Tribe Called Red' }, + { _id: 'BeevKCM1NnNeW91leyLZu', artist: 'tricot', title: '99.974°C' }, ]; - const playlistID = 1; - dispatch(a.loadPlaylistComplete(playlistID, items, { page: 0, pageSize: 5 })); - dispatch(a.selectPlaylist(playlistID)); + const playlistID = 'ZcU_8-UyI10Tx79R4CjRv'; + dispatch(a.loadPlaylistComplete(playlistID, items, { page: 0, pageSize: 5, total: 5 })); + dispatch(selectPlaylist(playlistID)); return { items, playlistID }; }; describe('reducers/playlists', () => { - beforeEach(() => { - fetch.mockResponse(async (req) => { - if (/\/api\/playlists\/\w+\/media/.test(req.url)) { - return JSON.stringify({ - meta: {}, - data: [], - }); - } - throw new Error('unexpected fetch call'); - }); - }); - afterEach(() => { - fetch.resetMocks(); - }); - it('should not respond to unrelated actions', () => { const { dispatch, getState } = createStore(); expect(s.playlistsSelector(getState())).toEqual([]); @@ -52,157 +51,138 @@ describe('reducers/playlists', () => { describe('action: playlists/SELECT_PLAYLIST', () => { it('sets the given playlist as the current playlist', () => { - const { dispatch, getState } = createStore(); - dispatch(initialiseStore); + const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists)); expect(s.selectedPlaylistIDSelector(getState())).toBeNull(); - dispatch(a.selectPlaylist(1)); - expect(s.selectedPlaylistIDSelector(getState())).toBe(1); - expect(s.selectedPlaylistSelector(getState())).toHaveProperty('_id', 1); + dispatch(selectPlaylist('ZcU_8-UyI10Tx79R4CjRv')); + expect(s.selectedPlaylistIDSelector(getState())).toBe('ZcU_8-UyI10Tx79R4CjRv'); + expect(s.selectedPlaylistSelector(getState())).toHaveProperty('_id', 'ZcU_8-UyI10Tx79R4CjRv'); - dispatch(a.selectPlaylist(3)); - expect(s.selectedPlaylistIDSelector(getState())).toBe(3); - expect(s.selectedPlaylistSelector(getState())).toHaveProperty('_id', 3); + dispatch(selectPlaylist('Kzy3kUckOgAV7iwrekHSE')); + expect(s.selectedPlaylistIDSelector(getState())).toBe('Kzy3kUckOgAV7iwrekHSE'); + expect(s.selectedPlaylistSelector(getState())).toHaveProperty('_id', 'Kzy3kUckOgAV7iwrekHSE'); - dispatch(a.selectPlaylist(null)); + dispatch(selectPlaylist(null)); expect(s.selectedPlaylistIDSelector(getState())).toBeNull(); expect(s.selectedPlaylistSelector(getState())).toBeNull(); }); - - it('loads playlist items for a newly selected playlist', () => { - const { dispatch } = createStore(); - dispatch(initialiseStore); - - dispatch(a.selectPlaylist(1)); - - expect(fetch).toHaveBeenCalled(); - }); - - it('does not attempt to load playlist items when deselecting a playlist', () => { - const { dispatch } = createStore(); - dispatch(initialiseStore); - - dispatch(a.selectPlaylist(1)); - expect(fetch).toHaveBeenCalledTimes(1); - dispatch(a.selectPlaylist(null)); - expect(fetch).toHaveBeenCalledTimes(1); - }); - }); - - describe('action: playlists/LOAD_PLAYLIST', () => { - // Nothing yet }); describe('action: playlists/ADD_MEDIA', () => { it('should insert playlist items in the correct place', () => { - const { dispatch, getState } = createStore(); - dispatch(initialiseStore); + const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists)); dispatch(initialisePlaylist); expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5); - dispatch(a.addMediaComplete(1, 7, { - afterID: 8, - media: [ - { _id: 347, artist: 'The Microphones', title: 'I Want Wind To Blow' }, - { _id: 764, artist: 'Bikini Kill', title: 'Rebel Girl' }, + dispatch(addPlaylistItems.fulfilled({ + playlistSize: 7, + items: [ + { _id: 'VlaaQAxk_Qy5orK1Vcr2C', artist: 'The Microphones', title: 'I Want Wind To Blow' }, + { _id: 'T9sdCu_-3o70qWk0YeDxJ', artist: 'Bikini Kill', title: 'Rebel Girl' }, ], + }, '66Z6y6JA4m5WmmNF3O7Ii', { + playlistID: 'ZcU_8-UyI10Tx79R4CjRv', + afterID: 'NkwUIwNmraSZ4A4eiC3GQ', + items: [], })); const { media } = s.selectedPlaylistSelector(getState()); expect(media).toHaveLength(7); expect(media.map((playlistItem) => playlistItem._id)).toEqual([ - 5, 6, 7, 8, 347, 764, 9, + 'Cnun9zo6oNr1wMCFRhnaO', 'PD_n42XxNCdQjDy5VB_SE', '66Z6y6JA4m5WmmNF3O7Ii', 'NkwUIwNmraSZ4A4eiC3GQ', 'VlaaQAxk_Qy5orK1Vcr2C', 'T9sdCu_-3o70qWk0YeDxJ', 'BeevKCM1NnNeW91leyLZu', ]); }); it('should update the Next Media selector when songs are prepended', () => { - const { dispatch, getState } = createStore(); - dispatch(initialiseStore); + const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists)); const { playlistID } = dispatch(initialisePlaylist); // Test an active, but not selected playlist. - dispatch(a.selectPlaylist(null)); - dispatch(a.activatePlaylistComplete(playlistID)); + dispatch(selectPlaylist(null)); + dispatch(activatePlaylist.fulfilled(null, '', playlistID)); expect(s.activePlaylistSelector(getState()).media).toHaveLength(5); - dispatch(a.addMediaComplete(1, 7, { - afterID: null, - media: [ - { _id: 347, artist: 'The Microphones', title: 'I Want Wind To Blow' }, - { _id: 764, artist: 'Bikini Kill', title: 'Rebel Girl' }, + dispatch(addPlaylistItems.fulfilled({ + playlistSize: 7, + items: [ + { _id: 'VlaaQAxk_Qy5orK1Vcr2C', artist: 'The Microphones', title: 'I Want Wind To Blow' }, + { _id: 'T9sdCu_-3o70qWk0YeDxJ', artist: 'Bikini Kill', title: 'Rebel Girl' }, ], + }, '66Z6y6JA4m5WmmNF3O7Ii', { + playlistID: 'ZcU_8-UyI10Tx79R4CjRv', + afterID: null, + items: [], })); expect(s.activePlaylistSelector(getState()).media).toHaveLength(7); - expect(s.nextMediaSelector(getState())._id).toEqual(347); + expect(s.nextMediaSelector(getState())._id).toBe('VlaaQAxk_Qy5orK1Vcr2C'); }); it('appends favourited items to the end of the playlist', () => { - const { dispatch, getState } = createStore(); - dispatch(initialiseStore); + const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists)); const { playlistID } = dispatch(initialisePlaylist); expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5); - dispatch(favoriteMediaComplete(playlistID, 36425, { + dispatch(favoriteMediaComplete(playlistID, 'vGA5mxhJpYkrsHSfxPcqX', { playlistSize: 6, added: [ - { _id: 1338, artist: 'SHINee', title: 'Odd Eye' }, + { _id: 'RDeVBExmCGXvmT0mN0P3n', artist: 'SHINee', title: 'Odd Eye' }, ], })); const { size, media } = s.selectedPlaylistSelector(getState()); - expect(size).toEqual(6); + expect(size).toBe(6); expect(media).toHaveLength(6); - expect(media[5]._id).toEqual(1338); + expect(media[5]._id).toBe('RDeVBExmCGXvmT0mN0P3n'); }); }); describe('action: playlists/MOVE_MEDIA', () => { it('should move playlist items', () => { - const { dispatch, getState } = createStore(); - dispatch(initialiseStore); + const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists)); const { items } = dispatch(initialisePlaylist); expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5); - dispatch(a.moveMediaComplete( - 1, - [items[1], items[2]], - { after: 8 }, - )); + dispatch(movePlaylistItems.fulfilled({ + location: { after: 'NkwUIwNmraSZ4A4eiC3GQ' }, + }, '', { + playlistID: 'ZcU_8-UyI10Tx79R4CjRv', + medias: [items[1], items[2]], + })); const selectedItemIDs = s.selectedPlaylistSelector(getState()).media .map((playlistItem) => playlistItem._id); - expect(selectedItemIDs).toEqual([5, 8, 6, 7, 9]); + expect(selectedItemIDs).toEqual(['Cnun9zo6oNr1wMCFRhnaO', 'NkwUIwNmraSZ4A4eiC3GQ', 'PD_n42XxNCdQjDy5VB_SE', '66Z6y6JA4m5WmmNF3O7Ii', 'BeevKCM1NnNeW91leyLZu']); }); it('should move playlist items in a sparse playlist', () => { - const { dispatch, getState } = createStore(); - dispatch(initialiseStore); + const { dispatch, getState } = createStore(preloadPlaylists(testPlaylists)); const items = [ - { _id: 5, artist: 'Taylor Swift', title: 'New Romantics' }, - { _id: 6, artist: 'Swiimers', title: 'Polaris' }, + { _id: 'Cnun9zo6oNr1wMCFRhnaO', artist: 'Taylor Swift', title: 'New Romantics' }, + { _id: 'PD_n42XxNCdQjDy5VB_SE', artist: 'Swiimers', title: 'Polaris' }, null, - { _id: 8, artist: 'Angel Haze', title: 'A Tribe Called Red' }, - { _id: 9, artist: 'tricot', title: '99.974°C' }, + { _id: 'NkwUIwNmraSZ4A4eiC3GQ', artist: 'Angel Haze', title: 'A Tribe Called Red' }, + { _id: 'BeevKCM1NnNeW91leyLZu', artist: 'tricot', title: '99.974°C' }, ]; - dispatch(a.loadPlaylistComplete(1, items, { page: 0, pageSize: 5 })); - dispatch(a.selectPlaylist(1)); + dispatch(a.loadPlaylistComplete('ZcU_8-UyI10Tx79R4CjRv', items, { page: 0, pageSize: 5, total: 5 })); + dispatch(selectPlaylist('ZcU_8-UyI10Tx79R4CjRv')); expect(s.selectedPlaylistSelector(getState()).media).toHaveLength(5); - dispatch(a.moveMediaComplete( - 1, - [items[0], items[4]], - { after: 8 }, - )); + dispatch(movePlaylistItems.fulfilled({ + location: { after: 'NkwUIwNmraSZ4A4eiC3GQ' }, + }, '', { + playlistID: 'ZcU_8-UyI10Tx79R4CjRv', + medias: [items[0], items[4]], + })); const getID = (item) => (item ? item._id : null); expect(s.selectedPlaylistSelector(getState()).media.map(getID)).toEqual([ - 6, null, 8, 5, 9, + 'PD_n42XxNCdQjDy5VB_SE', null, 'NkwUIwNmraSZ4A4eiC3GQ', 'Cnun9zo6oNr1wMCFRhnaO', 'BeevKCM1NnNeW91leyLZu', ]); }); }); diff --git a/src/reducers/__tests__/roomHistory.js b/src/reducers/__tests__/roomHistory.js deleted file mode 100644 index f3b58b9f7..000000000 --- a/src/reducers/__tests__/roomHistory.js +++ /dev/null @@ -1,178 +0,0 @@ -import createStore from '../../redux/configureStore'; -import { setUsers } from '../../actions/UserActionCreators'; -import { advance, loadHistoryComplete } from '../../actions/BoothActionCreators'; -import * as s from '../../selectors/roomHistorySelectors'; - -describe('reducers/roomHistory', () => { - it('should default to an empty array', () => { - const { getState } = createStore(); - expect(s.roomHistorySelector(getState())).toEqual([]); - }); - - const userModel = { - _id: '563ba1e3f059363574f4d0d9', - slug: 'narahye', - username: 'Narahye', - }; - - const mediaModel = { - _id: '56b11d3ad6bfe93733bece64', - sourceType: 'youtube', - sourceID: 'B7TlT1O7kjs', - artist: '[ 타블로 디스 ] Superbee (슈퍼비)', - title: '앰뷸런스 Ambulance', - thumbnail: 'https://i.ytimg.com/vi/B7TlT1O7kjs/hqdefault.jpg', - duration: 201, - }; - - const serverHistoryEntry = { - _id: '56b12b90d6bfe93733bece96', - user: userModel._id, - media: { - _id: '56b11d3ad6bfe93733bece65', - media: mediaModel._id, - artist: 'Superbee (슈퍼비)', - title: '앰뷸런스 Ambulance', - end: 201, - start: 0, - }, - playlist: '566b2d496c056392550f182b', - favorites: [], - downvotes: [], - upvotes: [], - playedAt: '2016-02-02T22:20:00.468Z', - }; - - describe('action: LOAD_HISTORY_COMPLETE', () => { - it('should normalize the loaded history entries', () => { - const { dispatch, getState } = createStore(); - dispatch(loadHistoryComplete({ - data: [serverHistoryEntry], - included: { - user: [userModel], - media: [mediaModel], - }, - meta: { - included: { - media: ['media.media'], - user: ['user'], - }, - offset: 0, - total: 1, - }, - })); - expect(s.roomHistorySelector(getState())).toEqual([{ - _id: '56b12b90d6bfe93733bece96', - user: { - _id: '563ba1e3f059363574f4d0d9', - slug: 'narahye', - username: 'Narahye', - }, - media: { - _id: '56b11d3ad6bfe93733bece65', - sourceType: 'youtube', - sourceID: 'B7TlT1O7kjs', - thumbnail: 'https://i.ytimg.com/vi/B7TlT1O7kjs/hqdefault.jpg', - artist: 'Superbee (슈퍼비)', - title: '앰뷸런스 Ambulance', - duration: 201, - start: 0, - end: 201, - // TODO maybe get rid of this? :P - media: { - _id: '56b11d3ad6bfe93733bece64', - sourceType: 'youtube', - sourceID: 'B7TlT1O7kjs', - thumbnail: 'https://i.ytimg.com/vi/B7TlT1O7kjs/hqdefault.jpg', - artist: '[ 타블로 디스 ] Superbee (슈퍼비)', - title: '앰뷸런스 Ambulance', - duration: 201, - }, - }, - stats: { - favorites: [], - downvotes: [], - upvotes: [], - }, - timestamp: new Date('2016-02-02T22:20:00.468Z').getTime(), - }]); - }); - }); - - describe('action: ADVANCE', () => { - it('prepends a new history entry', () => { - const { dispatch, getState } = createStore(); - dispatch(setUsers([{ - _id: '562b748139c99dde22c6a499', - slug: 'reanna', - username: 'ReAnna', - }])); - - dispatch(loadHistoryComplete({ - data: [serverHistoryEntry], - included: { - user: [userModel], - media: [mediaModel], - }, - meta: { - included: { - media: ['media.media'], - user: ['user'], - }, - offset: 0, - total: 1, - }, - })); - expect(s.roomHistorySelector(getState())).toHaveLength(1); - expect(s.roomHistorySelector(getState())[0]._id).toBe('56b12b90d6bfe93733bece96'); - - dispatch(advance({ - historyID: '56b12c59d6bfe93733bece97', - userID: '562b748139c99dde22c6a499', - playlistID: '563f390cf059363574f4d4dd', - playedAt: new Date('2016-02-02T22:23:21.519Z').getTime(), - media: { - media: { - _id: '569ac78a2b029e7d71a2ce43', - sourceType: 'youtube', - sourceID: '7SvxB_NL5cs', - thumbnail: 'https://i.ytimg.com/vi/7SvxB_NL5cs/hqdefault.jpg', - duration: 267, - }, - artist: 'Eleanoora Rosenholm', - title: 'Maailmanloppu', - start: 0, - end: 267, - }, - })); - - expect(s.roomHistoryWithVotesSelector(getState())).toHaveLength(2); - expect(s.roomHistoryWithVotesSelector(getState())[1]._id).toBe('56b12b90d6bfe93733bece96'); - - expect(s.roomHistoryWithVotesSelector(getState())[0]._id).toBe('56b12c59d6bfe93733bece97'); - }); - - it('works with NULL advances', () => { - const { dispatch, getState } = createStore(); - dispatch(loadHistoryComplete({ - data: [serverHistoryEntry], - included: { - user: [userModel], - media: [mediaModel], - }, - meta: { - included: { - media: ['media.media'], - user: ['user'], - }, - offset: 0, - total: 1, - }, - })); - expect(s.roomHistorySelector(getState())).toHaveLength(1); - - dispatch(advance()); - expect(s.roomHistorySelector(getState())).toHaveLength(1); - }); - }); -}); diff --git a/src/reducers/__tests__/settings.js b/src/reducers/__tests__/settings.js index 40c4dbea6..c06696f76 100644 --- a/src/reducers/__tests__/settings.js +++ b/src/reducers/__tests__/settings.js @@ -1,31 +1,24 @@ -import { - LOAD_SETTINGS, - CHANGE_SETTING, -} from '../../constants/ActionTypes'; -import settings from '../settings'; +import reducer, { load, apply } from '../settings'; describe('reducers/settings', () => { - const initialState = () => settings(undefined, { type: '@@redux/INIT' }); + const initialState = () => reducer(undefined, { type: '@@redux/INIT' }); it('should not respond to unrelated actions', () => { let state = { volume: 10 }; - state = settings(state, { type: 'randomOtherAction', payload: {} }); + state = reducer(state, { type: 'randomOtherAction', payload: {} }); expect(state.volume).toBe(10); }); it('should default to a settings object', () => { - const state = settings(undefined, { type: '@@redux/INIT' }); + const state = reducer(undefined, { type: '@@redux/INIT' }); expect(typeof state).toBe('object'); }); describe('action: settings/LOAD_SETTINGS', () => { it('should load all passed in settings', () => { - const state = settings(initialState(), { - type: LOAD_SETTINGS, - payload: { - setting: 'value', - volume: 20, - }, - }); + const state = reducer(initialState(), load({ + setting: 'value', + volume: 20, + })); expect(state.setting).toBe('value'); expect(state.volume).toBe(20); }); @@ -33,10 +26,7 @@ describe('reducers/settings', () => { describe('action: settings/CHANGE_SETTING', () => { it('should set a value', () => { - const state = settings(initialState(), { - type: CHANGE_SETTING, - payload: { volume: 54 }, - }); + const state = reducer(initialState(), apply({ volume: 54 })); expect(state.volume).toBe(54); }); }); diff --git a/src/reducers/__tests__/votes.js b/src/reducers/__tests__/votes.js index 9f7cad0a9..594a0a852 100644 --- a/src/reducers/__tests__/votes.js +++ b/src/reducers/__tests__/votes.js @@ -1,4 +1,5 @@ -import { INIT_STATE, ADVANCE } from '../../constants/ActionTypes'; +import { initState } from '../auth'; +import { advance } from '../booth'; import votes from '../votes'; const EMPTY_STATE = { @@ -10,9 +11,9 @@ const EMPTY_STATE = { describe('reducers/votes', () => { const initialState = () => votes(undefined, { type: '@@redux/INIT' }); it('should not respond to unrelated actions', () => { - let state = { upvotes: [1] }; + let state = { upvotes: ['JL2G9-1Hc8p80_AxlcwZC'] }; state = votes(state, { type: 'randomOtherAction', payload: {} }); - expect(state.upvotes).toEqual([1]); + expect(state.upvotes).toEqual(['JL2G9-1Hc8p80_AxlcwZC']); }); it('should default to empty vote arrays', () => { @@ -24,51 +25,44 @@ describe('reducers/votes', () => { let state = initialState(); it('should load in votes from the init endpoint', () => { - state = votes(state, { - type: INIT_STATE, - payload: { - booth: { - stats: { - upvotes: [1], - downvotes: [], - favorites: [2], - }, + state = votes(state, initState.fulfilled({ + booth: { + stats: { + upvotes: ['JL2G9-1Hc8p80_AxlcwZC'], + downvotes: [], + favorites: ['0slaUXdWdE3Pz4cbjocYV'], }, }, - }); + })); expect(state).toEqual({ - upvotes: [1], + upvotes: ['JL2G9-1Hc8p80_AxlcwZC'], downvotes: [], - favorites: [2], + favorites: ['0slaUXdWdE3Pz4cbjocYV'], }); }); it('should clear votes if init endpoint has empty booth', () => { - state = votes(state, { - type: INIT_STATE, - payload: { booth: null }, - }); + state = votes(state, initState.fulfilled({ + booth: null, + })); expect(state).toEqual(EMPTY_STATE); }); }); - describe('action: booth/ADVANCE', () => { + describe('action: booth/advance', () => { it('should reset votes state', () => { const state = votes({ - upvotes: [3, 4], - downvotes: [5], - favorites: [1, 2], - }, { - type: ADVANCE, - payload: { - historyID: 'someRandomID', - userID: 'seventeen', - media: { artist: 'about tess', title: 'Imaginedit' }, - timestamp: 1449767164107, - }, - }); + upvotes: ['nFy0Ts_UqrsUx8ddipZG9', 'OAxkeiBoNXWnejk9bPjpp'], + downvotes: ['HE1HhtApndA-kpB8KeI6m'], + favorites: ['JL2G9-1Hc8p80_AxlcwZC', '0slaUXdWdE3Pz4cbjocYV'], + }, advance({ + historyID: 'E1YirtFAC9erLKDION4J0', + userID: 'kxZex8C4IQ97YnPuOQezB', + media: { artist: 'about tess', title: 'Imaginedit' }, + timestamp: 1449767164107, + })); expect(state).toEqual(EMPTY_STATE); }); }); diff --git a/src/reducers/activeOverlay.js b/src/reducers/activeOverlay.js deleted file mode 100644 index 02f7776c1..000000000 --- a/src/reducers/activeOverlay.js +++ /dev/null @@ -1,17 +0,0 @@ -import { OPEN_OVERLAY, CLOSE_OVERLAY, TOGGLE_OVERLAY } from '../constants/ActionTypes'; - -const initialState = null; - -export default function reduce(state = initialState, action = {}) { - const { type, payload } = action; - switch (type) { - case OPEN_OVERLAY: - return payload.overlay; - case TOGGLE_OVERLAY: - return state === payload.overlay ? null : payload.overlay; - case CLOSE_OVERLAY: - return null; - default: - return state; - } -} diff --git a/src/reducers/activeOverlay.ts b/src/reducers/activeOverlay.ts new file mode 100644 index 000000000..75fda5aaf --- /dev/null +++ b/src/reducers/activeOverlay.ts @@ -0,0 +1,35 @@ +import { createSlice, type PayloadAction } from '@reduxjs/toolkit'; +import type { StoreState } from '../redux/configureStore'; + +type OverlayName = 'about' | 'admin' | 'playlistManager' | 'roomHistory' | 'settings'; +const initialState: { + current: OverlayName | null, +} = { + current: null, +}; + +const slice = createSlice({ + name: 'activeOverlay', + initialState, + reducers: { + openOverlay(state, action: PayloadAction<OverlayName>) { + state.current = action.payload; + }, + toggleOverlay(state, action: PayloadAction<OverlayName>) { + state.current = state.current === action.payload ? null : action.payload; + }, + closeOverlay: (state) => { + state.current = null; + }, + }, +}); + +export const { + openOverlay, + toggleOverlay, + closeOverlay, +} = slice.actions; + +export const selectOverlay = (state: StoreState) => state.activeOverlay.current; + +export default slice.reducer; diff --git a/src/reducers/addToPlaylistMenu.js b/src/reducers/addToPlaylistMenu.js deleted file mode 100644 index cc9925122..000000000 --- a/src/reducers/addToPlaylistMenu.js +++ /dev/null @@ -1,28 +0,0 @@ -import { OPEN_ADD_MEDIA_MENU, CLOSE_ADD_MEDIA_MENU } from '../constants/ActionTypes'; - -const initialState = { - open: false, - position: { x: 0, y: 0 }, - playlists: [], - type: null, - data: null, -}; - -export default function reduce(state = initialState, action = {}) { - const { type, payload, meta } = action; - switch (type) { - case OPEN_ADD_MEDIA_MENU: - return { - ...state, - open: true, - type: meta.type, - position: meta.position, - playlists: meta.playlists, - data: payload, - }; - case CLOSE_ADD_MEDIA_MENU: - return initialState; - default: - return state; - } -} diff --git a/src/reducers/addToPlaylistMenu.ts b/src/reducers/addToPlaylistMenu.ts new file mode 100644 index 000000000..1b5a9a54b --- /dev/null +++ b/src/reducers/addToPlaylistMenu.ts @@ -0,0 +1,82 @@ +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import type { StoreState } from '../redux/configureStore'; +import type { NewPlaylistItem } from './playlists'; + +interface ClosedState { + type: null, + data: null, +} +interface AddState { + type: 'add', + data: { + media: NewPlaylistItem[], + }, +} +interface FavoriteState { + type: 'favorite', + data: { historyID: string }, +} + +type State = { + open: boolean, + position: { x: number, y: number }, +} & (ClosedState | AddState | FavoriteState); + +const initialState: State = { + open: false, + position: { x: 0, y: 0 }, + type: null, + data: null, +} as State; + +const slice = createSlice({ + name: 'addToPlaylistMenu', + initialState, + reducers: { + open(state, action: PayloadAction<{ + position: { x: number, y: number }, + } & (AddState | FavoriteState)>) { + state.open = true; + Object.assign(state, action.payload); + }, + close() { + return initialState; + }, + }, +}); + +export const { + open, + close, +} = slice.actions; +export function openFavoriteMenu(historyID: string, position: { x: number, y: number }) { + return open({ + type: 'favorite', + position, + data: { historyID }, + }); +} + +export function isOpenSelector(state: StoreState) { + return state.addToPlaylistMenu.open; +} + +export function positionSelector(state: StoreState) { + return state.addToPlaylistMenu.position; +} + +export function isFavoriteSelector(state: StoreState) { + return state.addToPlaylistMenu.type === 'favorite'; +} + +export function mediaSelector(state: StoreState) { + const { open: isOpen, type, data } = state.addToPlaylistMenu; + return isOpen && type === 'add' ? data.media : null; +} + +export function historyIDSelector(state: StoreState) { + const { open: isOpen, type, data } = state.addToPlaylistMenu; + return isOpen && type === 'favorite' ? data.historyID : null; +} + +export default slice.reducer; diff --git a/src/reducers/auth.js b/src/reducers/auth.js deleted file mode 100644 index d2886ce6d..000000000 --- a/src/reducers/auth.js +++ /dev/null @@ -1,63 +0,0 @@ -import { - INIT_STATE, - AUTH_STRATEGIES, - RESET_PASSWORD_COMPLETE, - REGISTER_COMPLETE, - LOGIN_COMPLETE, - SET_TOKEN, - LOGOUT_COMPLETE, -} from '../constants/ActionTypes'; - -const initialState = { - strategies: ['local'], - token: null, - user: null, -}; - -export default function reduce(state = initialState, action = {}) { - const { type, payload, error: isError } = action; - switch (type) { - case INIT_STATE: - return { - ...state, - strategies: payload.authStrategies, - }; - case AUTH_STRATEGIES: - return { - ...state, - strategies: payload.strategies, - }; - case RESET_PASSWORD_COMPLETE: - return { - ...state, - token: payload.token, - user: null, - }; - case SET_TOKEN: - return { - ...state, - token: payload.token, - user: null, - }; - case LOGIN_COMPLETE: - return isError ? { - ...state, - token: null, - user: null, - } : { - ...state, - token: payload.token, - user: payload.user._id, - }; - case REGISTER_COMPLETE: - return { - ...state, - token: null, - user: null, - }; - case LOGOUT_COMPLETE: - return initialState; - default: - return state; - } -} diff --git a/src/reducers/auth.ts b/src/reducers/auth.ts new file mode 100644 index 000000000..b921ceee5 --- /dev/null +++ b/src/reducers/auth.ts @@ -0,0 +1,143 @@ +import type { AnyAction } from 'redux'; +import { createSlice } from '@reduxjs/toolkit'; +import { mutate } from 'swr'; +import { SET_TOKEN } from '../constants/ActionTypes'; +import type { Playlist } from './playlists'; +import type { User } from './users'; +import uwFetch from '../utils/fetch'; +import { createAsyncThunk } from '../redux/api'; +import { currentUserSelector } from '../selectors/userSelectors'; +import { syncTimestamps } from '../actions/TickerActionCreators'; + +interface Media { + media: { + _id: string, + sourceType: string, + sourceID: string, + sourceData: object, + artist: string, + title: string, + duration: number, + thumbnail: string, + }, + artist: string, + title: string, + start: number, + end: number, +} +interface PlaylistItem extends Media { + _id: string, + createdAt: string, + updatedAt: string, +} + +interface State { + strategies: string[]; + token: string | null; + user: string | null; +} + +const initialState: State = { + strategies: ['local'], + token: null, + user: null, +}; + +export type InitialStatePayload = { + motd: string | null, + user: User | null, + users: User[], + guests: number, + roles: Record<string, string[]>, + booth: { + historyID: string, + media: Media, + userID: string, + playedAt: number, + } | null, + waitlist: string[], + waitlistLocked: boolean, + activePlaylist: string | null, + firstActivePlaylistItem: PlaylistItem | null, + playlists: Playlist[] | null, + socketToken: string | null, + authStrategies: string[], + time: number, +}; +export const initState = createAsyncThunk('auth/now', async (_payload: void, api) => { + const beforeTime = Date.now(); + + const state = await uwFetch<InitialStatePayload>(['/now', { signal: api.signal }]); + + mutate('/booth/history'); + api.dispatch(syncTimestamps(beforeTime, state.time)); + + return state; +}); + +type LoginPayload = { email: string, password: string }; +export const login = createAsyncThunk('auth/login', async (payload: LoginPayload, api) => { + const { data, meta } = await uwFetch<{ + data: User, + meta: { jwt: string }, + }>(['/auth/login', { + method: 'post', + qs: { session: 'cookie' }, + data: payload, + signal: api.signal, + }]); + + const now = await api.dispatch(initState()); + const { socketToken } = now.payload as { socketToken: string }; + + return { + user: data, + socketToken, + token: meta.jwt, + }; +}); + +export const changeUsername = createAsyncThunk('auth/changeUsername', async (username: string, api) => { + const user = currentUserSelector(api.getState()); + if (!user) { + throw new Error('Not logged in'); + } + + const { data } = await uwFetch<{ data: User }>([`/users/${user._id}/username/`, { + method: 'put', + data: { username }, + signal: api.signal, + }]); + + return { + user: data, + }; +}); + +const slice = createSlice({ + name: 'auth', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(initState.fulfilled, (state, action) => { + const { payload } = action; + state.strategies = payload.authStrategies; + state.user = payload.user?._id ?? null; + }) + .addCase(SET_TOKEN, (state, action: AnyAction) => { + const { payload } = action; + state.token = payload.token; + }) + .addCase(login.fulfilled, (state, action) => { + state.token = action.payload.token; + state.user = action.payload.user._id; + }) + .addCase(login.rejected, (state) => { + state.token = null; + state.user = null; + }); + }, +}); + +export default slice.reducer; diff --git a/src/reducers/booth.js b/src/reducers/booth.js deleted file mode 100644 index df8310916..000000000 --- a/src/reducers/booth.js +++ /dev/null @@ -1,71 +0,0 @@ -import { - ADVANCE, - INIT_STATE, - ENTER_FULLSCREEN, - EXIT_FULLSCREEN, -} from '../constants/ActionTypes'; - -const initialState = { - historyID: null, - media: null, - djID: null, - startTime: null, - isFullscreen: false, -}; - -export default function reduce(state = initialState, action = {}) { - const { type, payload } = action; - switch (type) { - case ADVANCE: - if (payload) { - return { - ...state, - historyID: payload.historyID, - media: payload.media, - djID: payload.userID, - startTime: payload.timestamp, // TODO change this to playedAt - }; - } - return { - ...state, - historyID: null, - media: null, - djID: null, - startTime: null, - }; - case INIT_STATE: - if (payload.booth) { - return { - ...state, - historyID: payload.booth.historyID, - media: { - ...payload.booth.media, - ...payload.booth.media.media, - }, - djID: payload.booth.userID, - // Depending on the server version, `playedAt` may be a string or a number - // This is what we call "not ideal"… - startTime: new Date(payload.booth.playedAt).getTime(), - }; - } - return { - ...state, - historyID: null, - media: null, - djID: null, - startTime: null, - }; - case ENTER_FULLSCREEN: - return { - ...state, - isFullscreen: true, - }; - case EXIT_FULLSCREEN: - return { - ...state, - isFullscreen: false, - }; - default: - return state; - } -} diff --git a/src/reducers/booth.ts b/src/reducers/booth.ts new file mode 100644 index 000000000..ce272df04 --- /dev/null +++ b/src/reducers/booth.ts @@ -0,0 +1,123 @@ +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import type { User } from './users'; +import { initState } from './auth'; + +export interface Media { + _id: string, + sourceType: string, + sourceID: string, + sourceData: object, + artist: string, + title: string, + thumbnail: string, + duration: number, + start: number, + end: number, +} + +interface PlayingState { + historyID: string, + djID: string, + media: Media, + startTime: number, +} + +interface EmptyState { + historyID: null, + djID: null, + media: null, + startTime: null, +} + +type State = (PlayingState | EmptyState) & { + isFullscreen: boolean, +} + +const initialState = { + historyID: null, + media: null, + djID: null, + startTime: null, + isFullscreen: false, +} as State; + +type AdvancePayload = { historyID: string, media: Media, userID: string, timestamp: number }; +type PreviousBooth = { + _id: string, + user: User, + media: Media, + timestamp: number, + stats: { upvotes: string[], downvotes: string[], favorites: string[] }, +}; + +const slice = createSlice({ + name: 'booth', + initialState, + reducers: { + advance: { + reducer( + state, + action: PayloadAction<AdvancePayload | null>, + ): State { + if (action.payload) { + return { + ...state, + historyID: action.payload.historyID, + media: action.payload.media, + djID: action.payload.userID, + startTime: action.payload.timestamp, + }; + } + return { + ...state, + historyID: null, + media: null, + djID: null, + startTime: null, + }; + }, + prepare(payload: AdvancePayload | null, previous: PreviousBooth | null = null) { + return { payload, meta: { previous } }; + }, + }, + enterFullscreen(state) { + state.isFullscreen = true; + }, + exitFullscreen(state) { + state.isFullscreen = false; + }, + }, + extraReducers(builder) { + builder.addCase(initState.fulfilled, (state, action) => { + const { payload } = action; + if (payload.booth) { + Object.assign(state, { + historyID: payload.booth.historyID, + media: { + ...payload.booth.media.media, + ...payload.booth.media, + }, + djID: payload.booth.userID, + // Depending on the server version, `playedAt` may be a string or a number + // This is what we call "not ideal"… + startTime: new Date(payload.booth.playedAt).getTime(), + }); + } else { + Object.assign(state, { + historyID: null, + media: null, + djID: null, + startTime: null, + }); + } + }); + }, +}); + +export const { + advance, + enterFullscreen, + exitFullscreen, +} = slice.actions; + +export default slice.reducer; diff --git a/src/reducers/chat.js b/src/reducers/chat.js deleted file mode 100644 index 00be60629..000000000 --- a/src/reducers/chat.js +++ /dev/null @@ -1,143 +0,0 @@ -import omit from 'just-omit'; -import { v4 as randomUUID } from 'uuid'; -import { - INIT_STATE, - RECEIVE_MOTD, - RECEIVE_MESSAGE, - SEND_MESSAGE, - LOG, - REMOVE_MESSAGE, - REMOVE_USER_MESSAGES, - REMOVE_ALL_MESSAGES, - MUTE_USER, - UNMUTE_USER, -} from '../constants/ActionTypes'; -import reduceNotifications from './chat/notifications'; - -const initialState = { - /** - * Message of the Day, a message shown at the very top of the Chat box. Can be - * used for announcements, for example, or a welcome message. - */ - motd: null, - /** - * All messages, including log messages and in-flight messages. - */ - messages: [], - /** - * Mutes and their expiration times. - */ - mutedUsers: {}, -}; - -function removeInFlightMessage(messages, remove) { - return messages.filter((message) => ( - // keep if this message is not in flight - !message.inFlight - // or is not the message we're looking for - || message.userID !== remove.userID - || message.text !== remove.text - )); -} - -export default function reduce(state = initialState, action = undefined) { - const { type, payload } = action; - const { messages } = state; - switch (type) { - case INIT_STATE: - return { - ...state, - motd: payload.motd, - }; - case RECEIVE_MOTD: - return { - ...state, - motd: payload, - }; - case SEND_MESSAGE: { - const inFlightMessage = { - _id: randomUUID(), - type: 'chat', - user: payload.user, - userID: payload.user._id, - text: payload.message, - parsedText: payload.parsed, - timestamp: Date.now(), - inFlight: true, - // Will be resolved when the message is received instead. - isMention: false, - }; - return { - ...state, - messages: messages.concat([inFlightMessage]), - }; - } - case RECEIVE_MESSAGE: { - const message = { - ...payload.message, - type: 'chat', - inFlight: false, - parsedText: payload.parsed, - isMention: payload.isMention, - }; - - return { - ...state, - messages: removeInFlightMessage(messages, message).concat([message]), - }; - } - case LOG: { - const logMessage = { - type: 'log', - _id: payload._id, - text: payload.text, - }; - return { - ...state, - messages: messages.concat([logMessage]), - }; - } - - case REMOVE_MESSAGE: - return { - ...state, - messages: state.messages.filter((msg) => msg._id !== payload._id), - }; - case REMOVE_USER_MESSAGES: - return { - ...state, - messages: state.messages.filter((msg) => msg.userID !== payload.userID), - }; - case REMOVE_ALL_MESSAGES: - return { - ...state, - messages: [], - }; - - case MUTE_USER: - return { - ...state, - mutedUsers: { - ...state.mutedUsers, - [payload.userID]: { - mutedBy: payload.moderatorID, - expiresAt: payload.expiresAt, - expirationTimer: payload.expirationTimer, - }, - }, - }; - case UNMUTE_USER: - return { - ...state, - mutedUsers: omit(state.mutedUsers, payload.userID), - }; - - default: { - const nextMessages = reduceNotifications(messages, action); - if (nextMessages !== messages) { - return { ...state, messages: nextMessages }; - } - return state; - } - } -} diff --git a/src/reducers/chat.ts b/src/reducers/chat.ts new file mode 100644 index 000000000..2d4a127c8 --- /dev/null +++ b/src/reducers/chat.ts @@ -0,0 +1,321 @@ +import { AnyAction } from 'redux'; +import { v4 as randomUUID } from 'uuid'; +import { MarkupNode } from 'u-wave-parse-chat-markup'; +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import { BOOTH_SKIP } from '../constants/ActionTypes'; +import { type User, actions as userActions } from './users'; +import { advance } from './booth'; +import { initState } from './auth'; +import { createAsyncThunk } from '../redux/api'; +import uwFetch from '../utils/fetch'; + +export interface ChatMessage { + _id: string; + type: 'chat'; + user: User; + userID: string; + text: string; + parsedText?: MarkupNode[]; + timestamp: number; + inFlight: boolean; + isMention: boolean; +} + +export interface LogMessage { + type: 'log'; + _id: string; + text: string; +} + +export interface UserJoinMessage { + type: 'userJoin', + _id: string, + user: User, + timestamp: number, +} + +export interface UserLeaveMessage { + type: 'userLeave', + _id: string, + user: User, + timestamp: number, +} + +export interface UserNameChangedMessage { + type: 'userNameChanged', + _id: string, + user: User, + newUsername: string, + timestamp: number, +} + +export interface RoleUpdateMessage { + type: 'roleUpdate', + _id: string, + user: User, + updateType: 'add' | 'remove', + roles: string[], + timestamp: number, +} + +export interface NowPlayingMessage { + type: 'nowPlaying', + _id: string, + entry: { + _id: string, + sourceType: string, + sourceID: string, + thumbnail: string, + duration: number, + artist: string, + title: string, + start: number, + end: number, + }, + timestamp: number, +} + +export interface SkipMessage { + type: 'skip', + _id: string, + user: User, + moderator: User, + reason: string, + timestamp: number, +} + +export type Message = + | ChatMessage + | LogMessage + | UserJoinMessage + | UserLeaveMessage + | UserNameChangedMessage + | RoleUpdateMessage + | NowPlayingMessage + | SkipMessage; + +interface State { + /** + * Message of the Day, a message shown at the very top of the Chat box. Can be + * used for announcements, for example, or a welcome message. + */ + motd: string | null; + /** + * All messages, including log messages and in-flight messages. + */ + messages: Message[], + /** + * Mutes and their expiration times. + */ + mutedUsers: Record<string, { + mutedBy: string, + expiresAt: number, + expirationTimer: ReturnType<typeof setTimeout> | null, + }>; +} + +const initialState = { + motd: null, + messages: [], + mutedUsers: {}, +} as State; + +const slice = createSlice({ + name: 'chat', + initialState, + reducers: { + sendMessage(state, { payload }: PayloadAction<{ + user: User, + message: string, + parsed: MarkupNode[], + }>) { + state.messages.push({ + _id: randomUUID(), + type: 'chat', + user: payload.user, + userID: payload.user._id, + text: payload.message, + parsedText: payload.parsed, + timestamp: Date.now(), + inFlight: true, + // Will be resolved when the message is received instead. + isMention: false, + }); + }, + receiveMessage(state, action: PayloadAction<{ + message: { + _id: string, + user: User, + userID: string, + text: string, + timestamp: number, + }, + isMention: boolean, + parsed: MarkupNode[], + }>) { + const index = state.messages.findIndex((message) => { + return message.type === 'chat' + && message.inFlight + // or is not the message we're looking for + && message.userID === action.payload.message.userID + && message.text === action.payload.message.text; + }); + if (index !== -1) { + state.messages.splice(index, 1); + } + + state.messages.push({ + ...action.payload.message, + type: 'chat', + inFlight: false, + parsedText: action.payload.parsed, + isMention: action.payload.isMention, + }); + }, + log: { + reducer(state, { payload }: PayloadAction<{ _id: string, text: string }>) { + state.messages.push({ + type: 'log', + _id: payload._id, + text: payload.text, + }); + }, + prepare(text: string) { + return { + payload: { + _id: randomUUID(), + text, + }, + }; + }, + }, + deleteMessageByID(state, { payload }: PayloadAction<{ _id: string }>) { + const index = state.messages.findIndex((message) => message._id === payload._id); + if (index !== -1) { + state.messages.splice(index, 1); + } + }, + deleteMessagesByUser(state, { payload }: PayloadAction<{ userID: string }>) { + state.messages = state.messages.filter((message) => message.type !== 'chat' || message.userID !== payload.userID); + }, + deleteAllMessages(state) { + state.messages = []; + }, + muteUser(state, { payload }: PayloadAction<{ + moderatorID: string, + userID: string, + expiresAt: number, + expirationTimer: null | ReturnType<typeof setTimeout>, + }>) { + state.mutedUsers[payload.userID] = { + mutedBy: payload.moderatorID, + expiresAt: payload.expiresAt, + expirationTimer: payload.expirationTimer, + }; + }, + unmuteUser(state, { payload }: PayloadAction<{ userID: string, moderatorID?: string }>) { + const muted = state.mutedUsers[payload.userID]; + if (muted?.expirationTimer) { + clearTimeout(muted.expirationTimer); + } + delete state.mutedUsers[payload.userID]; + }, + }, + extraReducers(builder) { + builder + .addCase(initState.fulfilled, (state, action) => { + state.motd = action.payload.motd; + }) + .addCase(userActions.userJoin, (state, action) => { + state.messages.push({ + type: 'userJoin', + _id: randomUUID(), + user: action.payload.user, + timestamp: Date.now(), + }); + }) + .addCase(userActions.userLeave, (state, action) => { + state.messages.push({ + type: 'userLeave', + _id: randomUUID(), + user: action.payload.user, + timestamp: Date.now(), + }); + }) + .addCase(userActions.usernameChanged, (state, action) => { + state.messages.push({ + type: 'userNameChanged', + _id: randomUUID(), + user: action.payload.user, + newUsername: action.payload.username, + timestamp: Date.now(), + }); + }) + .addCase(userActions.addRoles, (state, action) => { + state.messages.push({ + type: 'roleUpdate', + _id: randomUUID(), + user: action.payload.user, + updateType: 'add', + roles: action.payload.roles, + timestamp: Date.now(), + }); + }) + .addCase(userActions.removeRoles, (state, action) => { + state.messages.push({ + type: 'roleUpdate', + _id: randomUUID(), + user: action.payload.user, + updateType: 'remove', + roles: action.payload.roles, + timestamp: Date.now(), + }); + }) + .addCase(advance, (state, action) => { + if (action.payload === null) { + return; + } + + state.messages.push({ + type: 'nowPlaying', + _id: randomUUID(), + entry: action.payload.media, + timestamp: action.payload.timestamp, + }); + }) + .addCase(BOOTH_SKIP, (state, action: AnyAction) => { + state.messages.push({ + type: 'skip', + _id: randomUUID(), + user: action.payload.user, + moderator: action.payload.moderator, + reason: action.payload.reason, + timestamp: action.payload.timestamp, + }); + }); + }, +}); + +export const { + sendMessage, + receiveMessage, + log, + deleteMessageByID, + deleteMessagesByUser, + deleteAllMessages, + muteUser, + unmuteUser, +} = slice.actions; + +export const setMotd = createAsyncThunk('chat/setMotd', async (text: string, api) => { + const { data } = await uwFetch<{ + data: { motd: string }, + }>(['/motd', { + method: 'put', + data: { motd: text }, + }]); + + api.dispatch(log(`Message of the Day is now: ${data.motd}`)); +}); + +export default slice.reducer; diff --git a/src/reducers/chat/notifications.js b/src/reducers/chat/notifications.js deleted file mode 100644 index 0c65b8479..000000000 --- a/src/reducers/chat/notifications.js +++ /dev/null @@ -1,70 +0,0 @@ -import { v4 as randomUUID } from 'uuid'; -import { - ADVANCE, - BOOTH_SKIP, - USER_JOIN, - USER_LEAVE, - CHANGE_USERNAME, - USER_ADD_ROLES, - USER_REMOVE_ROLES, -} from '../../constants/ActionTypes'; - -export default function reduceNotifications(state, { type, payload }) { - switch (type) { - case USER_JOIN: - return state.concat([{ - type: 'userJoin', - _id: randomUUID(), - user: payload.user, - timestamp: payload.timestamp, - }]); - case USER_LEAVE: - return state.concat([{ - type: 'userLeave', - _id: randomUUID(), - user: payload.user, - timestamp: payload.timestamp, - }]); - case CHANGE_USERNAME: - return state.concat([{ - type: 'userNameChanged', - _id: randomUUID(), - user: payload.user, - newUsername: payload.username, - timestamp: payload.timestamp, - }]); - case USER_ADD_ROLES: // fall through - case USER_REMOVE_ROLES: - return state.concat([{ - type: 'roleUpdate', - _id: randomUUID(), - user: payload.user, - updateType: type === USER_ADD_ROLES ? 'add' : 'remove', - roles: payload.roles, - timestamp: payload.timestamp, - }]); - case ADVANCE: { - if (payload === null) { - return state; - } - - return state.concat([{ - type: 'nowPlaying', - _id: randomUUID(), - entry: payload.media, - timestamp: payload.timestamp, - }]); - } - case BOOTH_SKIP: - return state.concat([{ - type: 'skip', - _id: randomUUID(), - user: payload.user, - moderator: payload.moderator, - reason: payload.reason, - timestamp: payload.timestamp, - }]); - default: - return state; - } -} diff --git a/src/reducers/config.js b/src/reducers/config.js deleted file mode 100644 index b5c572a6b..000000000 --- a/src/reducers/config.js +++ /dev/null @@ -1,28 +0,0 @@ -import { INIT_STATE, LOAD_EMOTES } from '../constants/ActionTypes'; - -export const initialState = { - roles: undefined, - emoji: {}, - serverEmotes: [], -}; - -export default function reduce(state = initialState, action = {}) { - const { type, payload } = action; - switch (type) { - case INIT_STATE: - if (payload.roles) { - return { - ...state, - roles: payload.roles, - }; - } - return state; - case LOAD_EMOTES: - return { - ...state, - serverEmotes: payload.emotes, - }; - default: - return state; - } -} diff --git a/src/reducers/config.ts b/src/reducers/config.ts new file mode 100644 index 000000000..1b870c10e --- /dev/null +++ b/src/reducers/config.ts @@ -0,0 +1,30 @@ +import { AnyAction } from 'redux'; +import { initState } from './auth'; + +export interface State { + roles: undefined | Record<string, string[]>; + apiUrl?: string, + socketUrl?: string, + emoji: Record<string, string>, +} + +export const initialState: State = { + roles: undefined, + emoji: {}, +}; + +export default function reduce(state = initialState, action: AnyAction): State { + const { type, payload } = action; + switch (type) { + case initState.fulfilled.type: + if (payload.roles) { + return { + ...state, + roles: payload.roles, + }; + } + return state; + default: + return state; + } +} diff --git a/src/reducers/createSourcesReducer.js b/src/reducers/createSourcesReducer.js deleted file mode 100644 index 17b644a4b..000000000 --- a/src/reducers/createSourcesReducer.js +++ /dev/null @@ -1,22 +0,0 @@ -const initialState = {}; - -// A reducer that calls each known Media Source's reducer. -function reduceSources(state = initialState, action = undefined, sources = {}) { - return Object.keys(sources).reduce((newState, sourceName) => { - const source = sources[sourceName]; - if (!source.reducer) { - return newState; - } - return { - ...newState, - [sourceName]: source.reducer(newState[sourceName], action), - }; - }, state); -} - -export default function createSourcesReducer(options) { - const mediaSources = options.mediaSources ?? {}; - return function reducer(state, action) { - return reduceSources(state, action, mediaSources); - }; -} diff --git a/src/reducers/dialogs.js b/src/reducers/dialogs.ts similarity index 55% rename from src/reducers/dialogs.js rename to src/reducers/dialogs.ts index a994c9cc6..51c6cfdbc 100644 --- a/src/reducers/dialogs.js +++ b/src/reducers/dialogs.ts @@ -1,32 +1,57 @@ +import type { AnyAction } from 'redux'; +import type { Media } from './booth'; import { OPEN_EDIT_MEDIA_DIALOG, CLOSE_EDIT_MEDIA_DIALOG, OPEN_PREVIEW_MEDIA_DIALOG, CLOSE_PREVIEW_MEDIA_DIALOG, OPEN_LOGIN_DIALOG, CLOSE_LOGIN_DIALOG, } from '../constants/ActionTypes'; -const initialState = { +interface EditMediaState { + playlistID: string; + media: Media, +} + +interface PreviewMediaState { + media: Media, +} + +interface LoginState { + show: 'login' | 'register' | 'reset', +} + +type DialogState<T> = + | { open: false, payload: null | T } + | { open: true, payload: T }; + +interface State { + editMedia: DialogState<EditMediaState>, + previewMedia: DialogState<PreviewMediaState>, + login: DialogState<LoginState>, +} + +const initialState: State = { editMedia: { open: false, - payload: {}, + payload: null, }, previewMedia: { open: false, - payload: {}, + payload: null, }, login: { open: false, - payload: {}, + payload: null, }, }; -const openDialog = (state, name, payload, open = true) => ({ +const openDialog = <K extends keyof State>(state: State, name: K, payload: State[K]['payload'], open = true) => ({ ...state, [name]: { open, payload, }, }); -const closeDialog = (state, name) => ({ +const closeDialog = (state: State, name: keyof State) => ({ ...state, [name]: { open: false, @@ -34,7 +59,7 @@ const closeDialog = (state, name) => ({ }, }); -export default function reduce(state = initialState, action = {}) { +export default function reduce(state = initialState, action: AnyAction) { const { type, payload } = action; switch (type) { case OPEN_EDIT_MEDIA_DIALOG: diff --git a/src/reducers/errors.js b/src/reducers/errors.js deleted file mode 100644 index 4ecd52963..000000000 --- a/src/reducers/errors.js +++ /dev/null @@ -1,12 +0,0 @@ -export default function reduce(state = [], action = {}) { - const { type, payload, error } = action; - if (error) { - // Avoid adding the same error over and over - if (state.length === 0 || state[state.length - 1] !== payload.message) { - return [...state, payload.message]; - } - } else if (type === 'errors/DISMISS') { - return state.slice(1); - } - return state; -} diff --git a/src/reducers/errors.ts b/src/reducers/errors.ts new file mode 100644 index 000000000..469970f80 --- /dev/null +++ b/src/reducers/errors.ts @@ -0,0 +1,17 @@ +import type { AnyAction } from 'redux'; + +type State = string[]; + +export default function reduce(state: State = [], action: AnyAction): State { + const { type, payload, error } = action; + if (error) { + const message = (typeof error === 'object' && error?.message) ?? payload?.message ?? 'Unknown error'; + // Avoid adding the same error over and over + if (state.length === 0 || state[state.length - 1] !== message) { + return [...state, message]; + } + } else if (type === 'errors/DISMISS') { + return state.slice(1); + } + return state; +} diff --git a/src/reducers/imports.js b/src/reducers/imports.ts similarity index 52% rename from src/reducers/imports.js rename to src/reducers/imports.ts index e4565d3f2..ce4e22c89 100644 --- a/src/reducers/imports.js +++ b/src/reducers/imports.ts @@ -1,30 +1,21 @@ +import type { AnyAction } from 'redux'; import { - SHOW_IMPORT_PANEL, SHOW_IMPORT_SOURCE_PANEL, HIDE_IMPORT_SOURCE_PANEL, - SELECT_PLAYLIST, - SHOW_SEARCH_RESULTS, } from '../constants/ActionTypes'; +import type { StoreState } from '../redux/configureStore'; -const initialState = { - showPanel: false, +interface State { + sourceType: string | null; +} + +const initialState: State = { sourceType: null, }; -export default function reduce(state = initialState, action = {}) { +function reduce(state = initialState, action: AnyAction): State { const { type, payload } = action; switch (type) { - case SHOW_IMPORT_PANEL: - return { - ...state, - showPanel: true, - }; - case SELECT_PLAYLIST: - case SHOW_SEARCH_RESULTS: - return { - ...state, - showPanel: false, - }; case SHOW_IMPORT_SOURCE_PANEL: return { ...state, @@ -39,3 +30,9 @@ export default function reduce(state = initialState, action = {}) { return state; } } + +export function selectedSourceTypeSelector(state: StoreState) { + return state.imports.sourceType; +} + +export default reduce; diff --git a/src/reducers/index.js b/src/reducers/index.ts similarity index 88% rename from src/reducers/index.js rename to src/reducers/index.ts index f64322b9f..a642bf693 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.ts @@ -8,9 +8,7 @@ import dialogs from './dialogs'; import errors from './errors'; import imports from './imports'; import locales from './locales'; -import mediaSearch from './mediaSearch'; import playlists from './playlists'; -import roomHistory from './roomHistory'; import server from './server'; import settings from './settings'; import theme from './theme'; @@ -31,9 +29,7 @@ export { errors, imports, locales, - mediaSearch, playlists, - roomHistory, server, settings, theme, diff --git a/src/reducers/locales.js b/src/reducers/locales.ts similarity index 75% rename from src/reducers/locales.js rename to src/reducers/locales.ts index acf666ab9..59cd2475f 100644 --- a/src/reducers/locales.js +++ b/src/reducers/locales.ts @@ -1,3 +1,4 @@ +import { AnyAction } from 'redux'; import { CHANGE_LANGUAGE, LOAD_LANGUAGE_START, @@ -5,13 +6,19 @@ import { } from '../constants/ActionTypes'; import en from '../../locale/en.yaml'; -const initialState = { +interface State { + current: string; + loading: string[]; + loaded: Record<string, object>; +} + +const initialState: State = { current: 'en', loading: [], loaded: { en }, }; -export default function reduce(state = initialState, action = undefined) { +export default function reduce(state = initialState, action: AnyAction): State { switch (action.type) { case LOAD_LANGUAGE_START: return { diff --git a/src/reducers/mediaSearch.js b/src/reducers/mediaSearch.js deleted file mode 100644 index 0f89eb6ea..000000000 --- a/src/reducers/mediaSearch.js +++ /dev/null @@ -1,22 +0,0 @@ -import { - HIDE_SEARCH_RESULTS, - SELECT_PLAYLIST, - SHOW_IMPORT_PANEL, - SHOW_SEARCH_RESULTS, -} from '../constants/ActionTypes'; - -const initialState = { showResults: false }; - -export default function reduce(state = initialState, action = {}) { - const { type } = action; - switch (type) { - case SHOW_SEARCH_RESULTS: - return { showResults: true }; - case SELECT_PLAYLIST: - case SHOW_IMPORT_PANEL: - case HIDE_SEARCH_RESULTS: - return { showResults: false }; - default: - return state; - } -} diff --git a/src/reducers/playlists.js b/src/reducers/playlists.js deleted file mode 100644 index a29de77f9..000000000 --- a/src/reducers/playlists.js +++ /dev/null @@ -1,413 +0,0 @@ -import escapeStringRegExp from 'escape-string-regexp'; -import indexBy from 'just-index'; -import mapValues from 'just-map-values'; -import omit from 'just-omit'; -import { flattenPlaylistItem } from '../actions/PlaylistActionCreators'; -import { - INIT_STATE, - - LOAD_ALL_PLAYLISTS_COMPLETE, - LOAD_PLAYLIST_START, - LOAD_PLAYLIST_COMPLETE, - PLAYLIST_CYCLED, - SELECT_PLAYLIST, - ACTIVATE_PLAYLIST_START, - ACTIVATE_PLAYLIST_COMPLETE, - CREATE_PLAYLIST_START, - CREATE_PLAYLIST_COMPLETE, - RENAME_PLAYLIST_COMPLETE, - DELETE_PLAYLIST_START, - DELETE_PLAYLIST_COMPLETE, - ADD_MEDIA_START, - ADD_MEDIA_COMPLETE, - REMOVE_MEDIA_START, - REMOVE_MEDIA_COMPLETE, - MOVE_MEDIA_START, - MOVE_MEDIA_COMPLETE, - UPDATE_MEDIA_START, - UPDATE_MEDIA_COMPLETE, - FILTER_PLAYLIST_ITEMS, - FILTER_PLAYLIST_ITEMS_COMPLETE, - - DO_FAVORITE_COMPLETE, -} from '../constants/ActionTypes'; - -const initialState = { - playlists: {}, - playlistItems: {}, - activePlaylistID: null, - selectedPlaylistID: null, - currentFilter: {}, -}; - -function processInsert(list, insert, position) { - let insertIdx = 0; - if (position.at === 'end') { - insertIdx = list.length; - } else if (position.at === 'start') { - insertIdx = 0; - } else if (position.after != null && position.after !== -1) { - insertIdx = list.findIndex((media) => media !== null && media._id === position.after) + 1; - } - return [ - ...list.slice(0, insertIdx), - ...insert, - ...list.slice(insertIdx), - ]; -} - -// Moves a list of media items to a given position in the playlist. -function processMove(list, movedMedia, location) { - // Take all moved media items out of the playlist… - const wasMoved = indexBy(movedMedia, '_id'); - const newPlaylist = list.filter((media) => media === null || !wasMoved[media._id]); - // …and add them back in at the correct place. - return processInsert(newPlaylist, movedMedia, location); -} - -function updatePlaylist(state, playlistID, modify) { - const playlist = state.playlists[playlistID]; - if (playlist) { - return { - ...state, - playlists: { - ...state.playlists, - [playlistID]: modify(playlist), - }, - }; - } - return state; -} - -// Applies a function to the media list belonging to `playlistID` if it is found -// locally, i.e. in either the active or the selected playlist. -function updatePlaylistItems(state, playlistID, modify) { - const playlist = state.playlists[playlistID]; - const media = state.playlistItems[playlistID]; - if (playlist) { - let nextFilter = state.currentFilter; - if (state.selectedPlaylistID === playlistID && nextFilter) { - nextFilter = { - ...nextFilter, - items: modify(nextFilter.items ?? [], playlist), - }; - } - return { - ...state, - playlistItems: { - ...state.playlistItems, - [playlistID]: modify(media ?? [], playlist), - }, - currentFilter: nextFilter, - }; - } - return state; -} - -function updatePlaylistAndItems(state, playlistID, modifyPlaylist, modifyItems) { - const newState = updatePlaylist(state, playlistID, modifyPlaylist); - return updatePlaylistItems(newState, playlistID, modifyItems); -} - -function setPlaylistLoading(state, id, loading = true) { - return updatePlaylist(state, id, (playlist) => ({ - ...playlist, - loading, - })); -} - -function mergePlaylistPage(size, oldMedia, newMedia, { page, pageSize }) { - const media = Array(size).fill(null); - oldMedia.forEach((item, i) => { - media[i] = item; - }); - newMedia.forEach((item, i) => { - media[(page * pageSize) + i] = item; - }); - return media; -} - -function filterCachedPlaylistItems(state, playlistID, filter) { - const rx = new RegExp(escapeStringRegExp(filter), 'i'); - const playlist = state.playlistItems[playlistID]; - if (playlist) { - return playlist.filter((item) => item && ( - rx.test(item.artist) || rx.test(item.title) - )); - } - return []; -} - -export default function reduce(state = initialState, action = {}) { - const { - type, payload, meta, error, - } = action; - - switch (type) { - case INIT_STATE: - // Probably not signed in. - if (!payload.playlists) return state; - - return { - ...state, - playlists: indexBy(payload.playlists.map((playlist) => ({ - ...playlist, - active: playlist._id === payload.activePlaylist, - })), '_id'), - // Preload the first item in the active playlist so it can be shown in - // the footer bar immediately. Else it would flash "This playlist is empty" - // for a moment. - playlistItems: payload.activePlaylist && payload.firstActivePlaylistItem ? { - ...state.playlistItems, - [payload.activePlaylist]: [flattenPlaylistItem(payload.firstActivePlaylistItem)], - } : state.playlistItems, - activePlaylistID: payload.activePlaylist, - selectedPlaylistID: payload.activePlaylist, - }; - case LOAD_ALL_PLAYLISTS_COMPLETE: - return { - ...state, - playlists: indexBy(payload.playlists, '_id'), - }; - case ACTIVATE_PLAYLIST_START: - // TODO use a different property here so we can show a loading icon on - // the "Active" button only, instead of on top of the entire playlist - return setPlaylistLoading(state, payload.playlistID); - case ACTIVATE_PLAYLIST_COMPLETE: - if (error) { - return setPlaylistLoading(state, meta.playlistID, false); - } - - return { - ...state, - // set `active` property on all playlists - playlists: mapValues(state.playlists, (playlist) => ({ - ...playlist, - loading: playlist._id === payload.playlistID ? false : playlist.loading, - active: playlist._id === payload.playlistID, - })), - activePlaylistID: payload.playlistID, - }; - case SELECT_PLAYLIST: { - const { currentFilter } = state; - const shouldClearFilter = currentFilter && currentFilter.playlistID !== payload.playlistID; - return { - ...state, - currentFilter: shouldClearFilter ? {} : currentFilter, - selectedPlaylistID: payload.playlistID, - }; - } - case LOAD_PLAYLIST_START: { - if (meta.sneaky || meta.page !== 0 || state.playlistItems[payload.playlistID]) { - return state; - } - - // Reserve space in the playlistItems array. - return updatePlaylistItems( - state, - payload.playlistID, - (items, playlist) => Array(playlist.size).fill(null) - .map((item, i) => items[i] ?? item), - ); - } - case LOAD_PLAYLIST_COMPLETE: - if (error) { - return setPlaylistLoading(state, meta.playlistID, false); - } - - return updatePlaylistAndItems( - state, - payload.playlistID, - (playlist) => ({ ...playlist, loading: false }), - (items) => mergePlaylistPage(meta.size, items, payload.media, meta), - ); - - case FILTER_PLAYLIST_ITEMS: - // Only the selected playlist can be filtered. - if (payload.playlistID !== state.selectedPlaylistID) { - return state; - } - if (!payload.filter) { - return { - ...state, - currentFilter: null, - }; - } - return { - ...state, - currentFilter: { - playlistID: payload.playlistID, - filter: payload.filter, - items: filterCachedPlaylistItems(state, payload.playlistID, payload.filter), - }, - }; - case FILTER_PLAYLIST_ITEMS_COMPLETE: { - // Only the selected playlist can be filtered. - if (payload.playlistID !== state.selectedPlaylistID) { - return state; - } - const { currentFilter } = state; - const items = mergePlaylistPage(meta.size, currentFilter.items, payload.media, meta); - return { - ...state, - currentFilter: { ...currentFilter, items }, - }; - } - - case PLAYLIST_CYCLED: - return updatePlaylistItems(state, payload.playlistID, (items, playlist) => { - const newItems = items.slice(1); - newItems[playlist.size - 1] = items[0]; // eslint-disable-line prefer-destructuring - return newItems; - }); - - // here be dragons - // TODO find a simpler way to store this stuff, that doesn't involve keeping - // millions of properties (six properties to be precise) in sync - // Playlists that are being created have a temporary ID that is used until the - // real ID comes back from the server. - case CREATE_PLAYLIST_START: { - const newPlaylist = { - _id: meta.tempId, - name: payload.name, - description: payload.description, - shared: payload.shared, - creating: true, - }; - return { - ...state, - playlists: Object.assign( - state.playlists, - { [meta.tempId]: newPlaylist }, - ), - selectedPlaylistID: meta.tempId, - }; - } - case CREATE_PLAYLIST_COMPLETE: - if (error) { - return { - ...state, - playlists: omit(state.playlists, `${meta.tempId}`), - }; - } - - return { - ...state, - playlists: Object.assign( - omit(state.playlists, `${meta.tempId}`), - { [payload.playlist._id]: payload.playlist }, - ), - selectedPlaylistID: payload.playlist._id, - }; - - case RENAME_PLAYLIST_COMPLETE: { - if (error) { - return state; - } - - const renamedPlaylist = state.playlists[payload.playlistID]; - if (renamedPlaylist) { - return updatePlaylist(state, payload.playlistID, (playlist) => ({ - ...playlist, - name: payload.name, - })); - } - return state; - } - case DELETE_PLAYLIST_START: - return setPlaylistLoading(state, payload.playlistID); - case DELETE_PLAYLIST_COMPLETE: - if (error) { - return setPlaylistLoading(state, meta.playlistID, false); - } - - return { - ...state, - // When deleting the selected playlist, select the active playlist instead. - selectedPlaylistID: state.selectedPlaylistID === payload.playlistID - ? state.activePlaylistID - : state.selectedPlaylistID, - playlists: omit(state.playlists, payload.playlistID), - }; - - case ADD_MEDIA_START: - return setPlaylistLoading(state, payload.playlistID); - case ADD_MEDIA_COMPLETE: - if (error) { - return setPlaylistLoading(state, meta.playlistID, false); - } - - return updatePlaylistAndItems( - state, - payload.playlistID, - (playlist) => ({ - ...playlist, - loading: false, - size: payload.newSize, - }), - (items) => processInsert(items, payload.appendedMedia, { after: payload.afterID }), - ); - case DO_FAVORITE_COMPLETE: - return updatePlaylistAndItems( - state, - payload.playlistID, - (playlist) => ({ - ...playlist, - size: payload.newSize, - }), - (items) => processInsert(items, payload.added, { at: 'end' }), - ); - - case UPDATE_MEDIA_START: - return updatePlaylistItems(state, payload.playlistID, (items) => ( - items.map((media) => ( - media && media._id === payload.mediaID - ? { ...media, loading: true } - : media - )) - )); - case UPDATE_MEDIA_COMPLETE: - return updatePlaylistItems(state, payload.playlistID, (items) => ( - items.map((media) => ( - media && media._id === payload.mediaID - ? { ...media, ...payload.media, loading: false } - : media - )) - )); - - case MOVE_MEDIA_START: { - const isMovingMedia = indexBy(payload.medias, '_id'); - return updatePlaylistItems(state, payload.playlistID, (items) => ( - items.map((media) => media && ({ - ...media, - loading: isMovingMedia[media._id] || media.loading, - })) - )); - } - case MOVE_MEDIA_COMPLETE: - return updatePlaylistItems(state, payload.playlistID, (items) => ( - processMove(items, payload.medias, payload.location) - )); - - case REMOVE_MEDIA_START: { - const isRemovingMedia = indexBy(payload.medias, '_id'); - return updatePlaylistItems(state, payload.playlistID, (items) => ( - items.map((media) => media && ({ - ...media, - loading: isRemovingMedia[media._id] || media.loading, - })) - )); - } - case REMOVE_MEDIA_COMPLETE: { - const isRemovedMedia = indexBy(payload.removedMedia, '_id'); - return updatePlaylistAndItems( - state, - payload.playlistID, - (playlist) => ({ ...playlist, size: payload.newSize }), - (items) => items.filter((media) => media === null || !isRemovedMedia[media._id]), - ); - } - default: - return state; - } -} diff --git a/src/reducers/playlists.ts b/src/reducers/playlists.ts new file mode 100644 index 000000000..5c17b3ac5 --- /dev/null +++ b/src/reducers/playlists.ts @@ -0,0 +1,590 @@ +import type { AnyAction } from 'redux'; +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import escapeStringRegExp from 'escape-string-regexp'; +import indexBy from 'just-index'; +import { createAsyncThunk } from '../redux/api'; +import uwFetch, { ListResponse } from '../utils/fetch'; +import mergeIncludedModels from '../utils/mergeIncludedModels'; +import { + LOAD_PLAYLIST_START, + LOAD_PLAYLIST_COMPLETE, + PLAYLIST_CYCLED, + DELETE_PLAYLIST_START, + DELETE_PLAYLIST_COMPLETE, + UPDATE_MEDIA_START, + UPDATE_MEDIA_COMPLETE, + FILTER_PLAYLIST_ITEMS, + FILTER_PLAYLIST_ITEMS_COMPLETE, + DO_FAVORITE_COMPLETE, + LOGOUT_COMPLETE, +} from '../constants/ActionTypes'; +import type { Media } from './booth'; +import { initState } from './auth'; + +export interface Playlist { + _id: string; + name: string; + loading?: boolean; + active?: boolean; + size: number; +} + +export interface PlaylistItem extends Media { + createdAt: string; + updatedAt: string; + loading?: boolean; +} + +type PlaylistItemList = (PlaylistItem | null)[]; + +export const importPanelSymbol = Symbol('import panel'); +export const searchPanelSymbol = Symbol('search panel'); +interface State { + playlists: Record<string, Playlist>; + playlistItems: Record<string, PlaylistItemList>; + activePlaylistID: string | null; + selectedPlaylistID: (typeof importPanelSymbol) | (typeof searchPanelSymbol) | string | null; + currentFilter: { + playlistID: string, + filter: string, + items: PlaylistItemList, + } | null; +} + +const initialState: State = { + playlists: {}, + playlistItems: {}, + activePlaylistID: null, + selectedPlaylistID: null, + currentFilter: null, +}; + +type InsertPosition = + | { at: 'start', after?: undefined } + | { at: 'end', after?: undefined } + | { at?: undefined, after: null | -1 | string } + +function processInsert(list: PlaylistItemList, insert: PlaylistItem[], position: InsertPosition) { + let insertIdx = 0; + if (position.at === 'end') { + insertIdx = list.length; + } else if (position.at === 'start') { + insertIdx = 0; + } else if (position.after != null && position.after !== -1) { + insertIdx = list.findIndex((media) => media !== null && media._id === position.after) + 1; + } + return [ + ...list.slice(0, insertIdx), + ...insert, + ...list.slice(insertIdx), + ]; +} + +// Moves a list of media items to a given position in the playlist. +function processMove(list: PlaylistItemList, movedMedia: PlaylistItem[], location: InsertPosition) { + // Take all moved media items out of the playlist… + const wasMoved = indexBy(movedMedia, '_id'); + const newPlaylist = list.filter((media) => media === null || !wasMoved[media._id]); + // …and add them back in at the correct place. + return processInsert(newPlaylist, movedMedia, location); +} + +function mergePlaylistPage( + size: number, + oldMedia: PlaylistItemList = [], + newMedia: PlaylistItem[], + { page, pageSize }: { page: number, pageSize: number }, +) { + const media: PlaylistItemList = Array(size).fill(null); + oldMedia.forEach((item, i) => { + media[i] = item; + }); + newMedia.forEach((item, i) => { + media[(page * pageSize) + i] = item; + }); + return media; +} + +function filterCachedPlaylistItems(state: State, playlistID: string, filter: string) { + const rx = new RegExp(escapeStringRegExp(filter), 'i'); + const playlist = state.playlistItems[playlistID]; + if (playlist) { + return playlist.filter((item) => item && ( + rx.test(item.artist) || rx.test(item.title) + )); + } + return []; +} + +const createPlaylist = createAsyncThunk('playlists/create', async (name: string) => { + const response = await uwFetch<{ + data: { + _id: string, + name: string, + author: string, + createdAt: string, + size: number, + }, + }>(['/playlists', { + method: 'post', + data: { name }, + }]); + + return response.data; +}); + +const renamePlaylist = createAsyncThunk('playlists/rename', async ({ playlistID, name }: { + playlistID: string, + name: string, +}) => { + const response = await uwFetch<{ + data: { + _id: string, + name: string, + author: string, + createdAt: string, + size: number, + }, + }>([`/playlists/${playlistID}/rename`, { + method: 'put', + data: { name }, + }]); + + return response.data; +}); + +const activatePlaylist = createAsyncThunk('playlists/activate', async (playlistID: string) => { + await uwFetch([`/playlists/${playlistID}/activate`, { + method: 'put', + data: {}, + }]); +}); + +type InsertTarget = { before: string } | { after: string } | { at: 'start' | 'end' }; +function resolveMoveOptions( + items: (null | { _id: string })[], + opts: InsertTarget, +) { + if ('after' in opts) { + return { after: opts.after }; + } + if ('before' in opts) { + for (let i = 0, l = items.length; i < l; i += 1) { + if (items[i] && items[i]?._id === opts.before) { + if (i === 0) { + return { at: 'start' as const }; + } + return { after: items[i - 1]?._id ?? null }; + } + } + return { at: 'end' as const }; + } + return { at: opts.at }; +} + +export interface NewPlaylistItem { + sourceType: string; + sourceID: string; + /** Leave empty to use global default for this media. */ + artist?: string | undefined; + /** Leave empty to use global default for this media. */ + title?: string | undefined; + start: number; + end: number; +} + +/** + * Keep only the playlist item properties that are necessary to add an item to + * a playlist. The rest ("thumbnail" etc) is left out for smaller payloads. + */ +function minimizePlaylistItem(item: NewPlaylistItem) { + return { + sourceType: item.sourceType, + sourceID: item.sourceID, + artist: item.artist, + title: item.title, + start: item.start, + end: item.end, + }; +} + +const addPlaylistItems = createAsyncThunk('playlists/addPlaylistItems', async ({ + playlistID, + items, + afterID = null, +}: { + playlistID: string, + items: NewPlaylistItem[], + afterID?: string | null, +}) => { + const payload = { + items: items.map(minimizePlaylistItem), + after: afterID, + }; + + const res = await uwFetch<ListResponse<PlaylistItem> & { + meta: { + playlistSize: number, + }, + }>([`/playlists/${playlistID}/media`, { + method: 'post', + data: payload, + }]); + + return { + playlistSize: res.meta.playlistSize, + items: mergeIncludedModels(res), + }; +}); + +const movePlaylistItems = createAsyncThunk('playlists/movePlaylistItems', async ({ playlistID, medias, target }: { + playlistID: string, + medias: PlaylistItem[], + target: InsertTarget, +}, api) => { + const playlistItems = api.getState().playlists.playlistItems[playlistID] ?? []; + const location = resolveMoveOptions(playlistItems, target); + const items = medias.map((media) => media._id); + + await uwFetch([`/playlists/${playlistID}/move`, { + method: 'put', + data: { items, ...location }, + }]); + + return { location }; +}); + +const removePlaylistItems = createAsyncThunk('playlists/removePlaylistItems', async ({ playlistID, medias }: { + playlistID: string, + medias: PlaylistItem[], +}) => { + const items = medias.map((media) => media._id); + + const { meta } = await uwFetch<{ + meta: { playlistSize: number }, + }>([`/playlists/${playlistID}/media`, { + method: 'delete', + data: { items }, + }]); + + return { newSize: meta.playlistSize }; +}); + +const slice = createSlice({ + name: 'playlists', + initialState, + reducers: { + selectActivePlaylist(state) { + if (state.activePlaylistID !== state.selectedPlaylistID) { + state.currentFilter = null; + state.selectedPlaylistID = state.activePlaylistID; + } + }, + selectPlaylist(state, action: PayloadAction<string>) { + if (state.currentFilter && state.currentFilter.playlistID !== action.payload) { + state.currentFilter = null; + } + state.selectedPlaylistID = action.payload; + }, + showImportPanel(state) { + state.selectedPlaylistID = importPanelSymbol; + }, + showSearchResults(state) { + state.selectedPlaylistID = searchPanelSymbol; + }, + }, + extraReducers(builder) { + builder + .addCase(initState.fulfilled, (state, { payload }) => { + if (payload.playlists) { + state.playlists = indexBy(payload.playlists.map((playlist: Playlist) => ({ + ...playlist, + active: playlist._id === payload.activePlaylist, + })), '_id'); + // Preload the first item in the active playlist so it can be shown in + // the footer bar immediately. Else it would flash "This playlist is empty" + // for a moment. + if (payload.activePlaylist && payload.firstActivePlaylistItem) { + const item = { + ...payload.firstActivePlaylistItem.media, + ...payload.firstActivePlaylistItem, + }; + const activePlaylist = state.playlists[payload.activePlaylist]; + // Probably overly defensive, but avoid a crash if we got inconsistent data + const size = activePlaylist ? activePlaylist.size : 1; + const playlistItems = Array(size).fill(null); + playlistItems[0] = item; + state.playlistItems[payload.activePlaylist] = playlistItems; + } + state.activePlaylistID = payload.activePlaylist; + // Select the first playlist by default if there is no active playlist. + state.selectedPlaylistID ??= payload.activePlaylist ?? payload.playlists[0]?._id ?? null; + } + }) + .addCase(LOGOUT_COMPLETE, () => { + return initialState; + }) + .addCase(activatePlaylist.pending, (state, action) => { + // TODO use a different property here so we can show a loading icon on + // the "Active" button only, instead of on top of the entire playlist + const playlist = state.playlists[action.meta.arg]; + if (playlist != null) { + playlist.loading = true; + } + }) + .addCase(activatePlaylist.rejected, (state, action) => { + const playlist = state.playlists[action.meta.arg]; + if (playlist != null) { + playlist.loading = false; + } + }) + .addCase(activatePlaylist.fulfilled, (state, action) => { + // TODO use a different property here so we can show a loading icon on + // the "Active" button only, instead of on top of the entire playlist + const playlist = state.playlists[action.meta.arg]; + if (playlist != null) { + playlist.loading = false; + playlist.active = true; + state.activePlaylistID = action.meta.arg; + } + }) + .addCase(LOAD_PLAYLIST_START, (state, { payload, meta }: AnyAction) => { + const playlist = state.playlists[payload.playlistID]; + if (playlist == null) { + return; + } + // Cases where we don't show a loading anymation + if (meta.sneaky || meta.page !== 0 || state.playlistItems[payload.playlistID]) { + return; + } + + const items = state.playlistItems[payload.playlistID] ?? []; + state.playlistItems[payload.playlistID] = Array(playlist.size).fill(null) + .map((item, index) => items[index] ?? item); + }) + .addCase(LOAD_PLAYLIST_COMPLETE, (state, { payload, meta, error }: AnyAction) => { + const playlist = state.playlists[payload.playlistID]; + + if (playlist == null) { + return; + } + + if (error) { + playlist.loading = false; + return; + } + + playlist.loading = false; + state.playlistItems[payload.playlistID] = mergePlaylistPage( + meta.size ?? playlist.size, + state.playlistItems[payload.playlistID], + payload.media, + meta, + ); + }) + .addCase(FILTER_PLAYLIST_ITEMS, (state, { payload }: AnyAction) => { + // Only the selected playlist can be filtered. + if (payload.playlistID !== state.selectedPlaylistID) { + return; + } + if (!payload.filter) { + state.currentFilter = null; + return; + } + state.currentFilter = { + playlistID: payload.playlistID, + filter: payload.filter, + items: filterCachedPlaylistItems(state, payload.playlistID, payload.filter), + }; + }) + .addCase(FILTER_PLAYLIST_ITEMS_COMPLETE, (state, { payload, meta }: AnyAction) => { + // Only the selected playlist can be filtered. + if (payload.playlistID !== state.selectedPlaylistID || !state.currentFilter) { + return; + } + state.currentFilter.items = mergePlaylistPage( + meta.size, + state.currentFilter.items, + payload.media, + meta, + ); + }) + .addCase(PLAYLIST_CYCLED, (state, { payload }: AnyAction) => { + const playlist = state.playlists[payload.playlistID]; + if (playlist == null) { + return; + } + + const items = state.playlistItems[payload.playlistID] ?? []; + if (items.length > 0) { + const newItems = items.slice(1); + // eslint-disable-next-line prefer-destructuring + newItems[playlist.size - 1] = items[0] ?? null; + state.playlistItems[payload.playlistID] = newItems; + } + }) + .addCase(createPlaylist.pending, (state, action) => { + const id = action.meta.requestId; + const name = action.meta.arg; + + state.playlists[id] = { + _id: id, + name, + size: 0, + }; + }) + .addCase(createPlaylist.rejected, (state, action) => { + delete state.playlists[action.meta.requestId]; + }) + .addCase(createPlaylist.fulfilled, (state, action) => { + delete state.playlists[action.meta.requestId]; + + const playlist = action.payload; + state.playlists[playlist._id] = playlist; + if (state.selectedPlaylistID === action.meta.requestId) { + state.selectedPlaylistID = playlist._id; + } + }) + .addCase(renamePlaylist.fulfilled, (state, action) => { + const playlist = state.playlists[action.payload._id]; + if (playlist) { + playlist.name = action.payload.name; + } + }) + .addCase(DELETE_PLAYLIST_START, (state, { payload }: AnyAction) => { + const playlist = state.playlists[payload.playlistID]; + + if (playlist != null) { + playlist.loading = true; + } + }) + .addCase(DELETE_PLAYLIST_COMPLETE, (state, { payload, error }: AnyAction) => { + const playlist = state.playlists[payload.playlistID]; + if (playlist == null) { + return; + } + + if (error) { + playlist.loading = false; + return; + } + + playlist.loading = false; + delete state.playlists[payload.playlistID]; + delete state.playlistItems[payload.playlistID]; + if (state.selectedPlaylistID === payload.playlistID) { + state.selectedPlaylistID = state.activePlaylistID; + } + }) + .addCase(addPlaylistItems.pending, (state, action) => { + const { playlistID } = action.meta.arg; + const playlist = state.playlists[playlistID]; + + if (playlist != null) { + playlist.loading = true; + } + }) + .addCase(addPlaylistItems.fulfilled, (state, action) => { + const { playlistID, afterID = null } = action.meta.arg; + const { playlistSize, items } = action.payload; + + const playlist = state.playlists[playlistID]; + if (playlist == null) { + return; + } + + playlist.loading = false; + playlist.size = playlistSize; + state.playlistItems[playlistID] = processInsert( + state.playlistItems[playlistID] ?? [], + items, + { after: afterID }, + ); + }) + .addCase(DO_FAVORITE_COMPLETE, (state, { payload }: AnyAction) => { + const playlist = state.playlists[payload.playlistID]; + if (playlist == null) { + return; + } + + playlist.size = payload.newSize; + state.playlistItems[payload.playlistID] = processInsert( + state.playlistItems[payload.playlistID] ?? [], + payload.added, + { at: 'end' }, + ); + }) + .addCase(UPDATE_MEDIA_START, (state, { payload }: AnyAction) => { + for (const item of state.playlistItems[payload.playlistID] ?? []) { + if (item != null && item._id === payload.mediaID) { + item.loading = true; + } + } + }) + .addCase(UPDATE_MEDIA_COMPLETE, (state, { payload }: AnyAction) => { + for (const item of state.playlistItems[payload.playlistID] ?? []) { + if (item != null && item._id === payload.mediaID) { + item.loading = false; + Object.assign(item, payload.media); + } + } + }) + .addCase(movePlaylistItems.pending, (state, action) => { + const { playlistID, medias } = action.meta.arg; + const ids = new Set(medias.map((media) => media._id)); + for (const item of state.playlistItems[playlistID] ?? []) { + if (item != null && ids.has(item._id)) { + item.loading = true; + } + } + }) + .addCase(movePlaylistItems.fulfilled, (state, action) => { + const { playlistID, medias } = action.meta.arg; + const { location } = action.payload; + state.playlistItems[playlistID] = processMove( + state.playlistItems[playlistID] ?? [], + medias, + location, + ); + }) + .addCase(removePlaylistItems.pending, (state, action) => { + const { playlistID, medias } = action.meta.arg; + const ids = new Set(medias.map((media) => media._id)); + for (const item of state.playlistItems[playlistID] ?? []) { + if (item != null && ids.has(item._id)) { + item.loading = true; + } + } + }) + .addCase(removePlaylistItems.fulfilled, (state, action) => { + const { playlistID, medias } = action.meta.arg; + const { newSize } = action.payload; + const playlist = state.playlists[playlistID]; + if (playlist == null) { + return; + } + + const ids = new Set(medias.map((media) => media._id)); + playlist.size = newSize; + state.playlistItems[playlistID] = (state.playlistItems[playlistID] ?? []) + .filter((media) => media === null || !ids.has(media._id)); + }); + }, +}); + +export { + createPlaylist, + renamePlaylist, + activatePlaylist, + addPlaylistItems, + movePlaylistItems, + removePlaylistItems, +}; +export const { + selectPlaylist, + selectActivePlaylist, + showImportPanel, + showSearchResults, +} = slice.actions; + +export default slice.reducer; diff --git a/src/reducers/roomHistory.js b/src/reducers/roomHistory.js deleted file mode 100644 index b28e692e7..000000000 --- a/src/reducers/roomHistory.js +++ /dev/null @@ -1,41 +0,0 @@ -import { ADVANCE, LOAD_HISTORY_COMPLETE } from '../constants/ActionTypes'; - -const initialState = []; - -const normalize = (entry) => ({ - _id: entry._id ?? entry.historyID, - user: entry.user, - media: { - ...entry.media.media, - ...entry.media, - }, - timestamp: new Date(entry.timestamp ?? entry.playedAt).getTime(), - stats: entry.stats ?? { - upvotes: entry.upvotes ?? [], - downvotes: entry.downvotes ?? [], - favorites: entry.favorites ?? [], - }, -}); - -export default function reduce(state = initialState, action = {}) { - const { type, payload, meta } = action; - switch (type) { - case LOAD_HISTORY_COMPLETE: - return payload.map(normalize); - case ADVANCE: { - const mostRecent = state[0]; - // If the currently playing track is already in the history, remove it-- - // it'll be added back on the next advance, and will be handled by the - // roomHistorySelector in the mean time. - if (mostRecent && payload && mostRecent._id === payload.historyID) { - return state.slice(1); - } - if (!meta || !meta.previous) { - return state; - } - return [normalize(meta.previous), ...state]; - } - default: - return state; - } -} diff --git a/src/reducers/server.js b/src/reducers/server.ts similarity index 75% rename from src/reducers/server.js rename to src/reducers/server.ts index a56fa01f5..a71d127fb 100644 --- a/src/reducers/server.js +++ b/src/reducers/server.ts @@ -1,10 +1,15 @@ +import { AnyAction } from 'redux'; import { SOCKET_CONNECTED, SOCKET_DISCONNECTED } from '../constants/ActionTypes'; -const initialState = { +interface State { + connected: boolean; +} + +const initialState: State = { connected: false, }; -export default function serverReducer(state = initialState, action = {}) { +export default function serverReducer(state = initialState, action: AnyAction): State { const { type } = action; switch (type) { diff --git a/src/reducers/settings.js b/src/reducers/settings.js deleted file mode 100644 index 56002beb3..000000000 --- a/src/reducers/settings.js +++ /dev/null @@ -1,54 +0,0 @@ -import merge from 'deepmerge'; -import { - LOAD_SETTINGS, - CHANGE_SETTING, -} from '../constants/ActionTypes'; - -// Some people have >100% volumes stored in their localStorage settings -// because of a bug in üWave 1.4. This ensures that _everyone's_ volume -// is between 0 and 100. -function fixVolume(state) { - if (state.volume < 0) return { ...state, volume: 0 }; - if (state.volume > 100) return { ...state, volume: 100 }; - return state; -} - -const initialState = { - language: null, - mentionSound: true, - muted: false, - videoEnabled: true, - videoSize: 'large', - volume: 0, - notifications: { - userJoin: true, - userLeave: true, - userNameChanged: true, - skip: true, - }, -}; - -function reduce(state = initialState, action = undefined) { - const { type, payload } = action; - switch (type) { - case LOAD_SETTINGS: - // Loading settings defaults to the initial state. - return { - ...initialState, - ...payload, - // Merge notification settings if we have new ones. - // Needed if new notification types were added since the last time - // settings were saved to localStorage. - notifications: payload ? { - ...initialState.notifications, - ...payload.notifications, - } : initialState.notifications, - }; - case CHANGE_SETTING: - return merge(state, payload, { clone: true }); - default: - return state; - } -} - -export default (state, action) => fixVolume(reduce(state, action)); diff --git a/src/reducers/settings.ts b/src/reducers/settings.ts new file mode 100644 index 000000000..8b4d5d309 --- /dev/null +++ b/src/reducers/settings.ts @@ -0,0 +1,122 @@ +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import { dset } from 'dset'; +import deepmerge from 'deepmerge'; +import type { StoreState } from '../redux/configureStore'; +import { availableLanguages } from '../locales'; + +const initialState = { + language: null as null | string, + mentionSound: true, + muted: false, + videoEnabled: true, + videoSize: 'large', + volume: 0, + notifications: { + userJoin: true, + userLeave: true, + userNameChanged: true, + skip: true, + }, +}; + +type State = typeof initialState + +const slice = createSlice({ + name: 'settings', + initialState, + reducers: { + load(_state, { payload }: PayloadAction<Partial<State>>) { + return deepmerge(initialState, payload); + }, + apply(state, { payload }: PayloadAction<Partial<State>>) { + return deepmerge(state, payload); + }, + setLanguage(state, action: PayloadAction<string>) { + state.language = action.payload; + }, + setVolume(state, action: PayloadAction<number>) { + state.volume = action.payload; + }, + mute(state) { + state.muted = true; + }, + unmute(state) { + state.muted = false; + }, + setMentionSoundEnabled(state, action: PayloadAction<boolean>) { + state.mentionSound = action.payload; + }, + setVideoEnabled(state, action: PayloadAction<boolean>) { + state.videoEnabled = action.payload; + }, + setVideoSize(state, action: PayloadAction<'small' | 'large'>) { + state.videoSize = action.payload; + }, + toggleVideoSize(state) { + state.videoSize = state.videoSize === 'large' ? 'small' : 'large'; + }, + }, +}); + +export const { + load, + apply, + setLanguage, + setVolume, + mute, + unmute, + setMentionSoundEnabled, + setVideoEnabled, + setVideoSize, + toggleVideoSize, +} = slice.actions; +// This is quite type-unsafe… +export function set(key: string, value: unknown) { + const changeset = {}; + dset(changeset, key, value); + return slice.actions.apply(changeset); +} + +export function volumeSelector(state: StoreState) { + return state.settings.volume; +} + +export function isMutedSelector(state: StoreState) { + return state.settings.muted; +} + +function getDefaultLanguage() { + if (typeof window === 'object' && window.navigator?.languages) { + const browserLanguage = availableLanguages.find((lang) => { + return window.navigator.languages.includes(lang); + }); + if (browserLanguage) { + return browserLanguage; + } + } + return 'en'; +} + +let defaultLanguage: string | null = null; +export function languageSelector(state: StoreState) { + if (state.settings.language) { + return state.settings.language; + } + + defaultLanguage ??= getDefaultLanguage(); + return defaultLanguage; +} + +export function videoSizeSelector(state: StoreState) { + return state.settings.videoSize; +} + +export function videoEnabledSelector(state: StoreState) { + return state.settings.videoEnabled; +} + +export function mentionSoundEnabledSelector(state: StoreState) { + return state.settings.mentionSound; +} + +export default slice.reducer; diff --git a/src/reducers/theme.js b/src/reducers/theme.js deleted file mode 100644 index cec67a77a..000000000 --- a/src/reducers/theme.js +++ /dev/null @@ -1,14 +0,0 @@ -import merge from 'deepmerge'; -import { RESET_THEME, APPLY_THEME } from '../constants/ActionTypes'; -import initialState from '../theme'; - -export default function reduce(state = initialState, action = {}) { - switch (action.type) { - case RESET_THEME: - return initialState; - case APPLY_THEME: - return merge(state, action.payload); - default: - return state; - } -} diff --git a/src/reducers/theme.ts b/src/reducers/theme.ts new file mode 100644 index 000000000..7a664f597 --- /dev/null +++ b/src/reducers/theme.ts @@ -0,0 +1,23 @@ +import { type PayloadAction, createSlice } from '@reduxjs/toolkit'; +import type { ThemeOptions } from '@mui/material/styles'; +import merge from 'deepmerge'; +import initialState from '../theme'; + +const slice = createSlice({ + name: 'theme', + initialState, + reducers: { + reset() { + return initialState; + }, + apply(state, action: PayloadAction<ThemeOptions>) { + return merge(state, action.payload); + }, + }, +}); + +export const { + reset, + apply, +} = slice.actions; +export default slice.reducer; diff --git a/src/reducers/time.js b/src/reducers/time.ts similarity index 53% rename from src/reducers/time.js rename to src/reducers/time.ts index de577bc54..ca88594d3 100644 --- a/src/reducers/time.js +++ b/src/reducers/time.ts @@ -1,11 +1,17 @@ +import { AnyAction } from 'redux'; import { SET_TIMER, OFFSET } from '../constants/ActionTypes'; -const initialState = { - timer: 0, +interface State { + timer: ReturnType<typeof setTimeout> | null, + offset: number, +} + +const initialState: State = { + timer: null, offset: 0, }; -export default function reduce(state = initialState, action = {}) { +export default function reduce(state = initialState, action: AnyAction): State { switch (action.type) { case SET_TIMER: return { ...state, timer: action.payload }; diff --git a/src/reducers/users.js b/src/reducers/users.js deleted file mode 100644 index 83504886d..000000000 --- a/src/reducers/users.js +++ /dev/null @@ -1,81 +0,0 @@ -import omit from 'just-omit'; -import { combineReducers } from 'redux'; -import indexBy from 'just-index'; -import { - INIT_STATE, - LOAD_ONLINE_USERS, - USER_JOIN, - USER_LEAVE, - CHANGE_USERNAME, - USER_ADD_ROLES, - USER_REMOVE_ROLES, - RECEIVE_GUEST_COUNT, -} from '../constants/ActionTypes'; - -function updateUser(state, userID, update) { - if (state[userID]) { - return { - ...state, - [userID]: update(state[userID]), - }; - } - return state; -} - -function guestsReducer(state = 0, action = {}) { - if (action.type === INIT_STATE) { - return action.payload.guests; - } - if (action.type === RECEIVE_GUEST_COUNT) { - return action.payload.guests; - } - return state; -} - -function usersReducer(state = {}, action = {}) { - const { type, payload } = action; - switch (type) { - case INIT_STATE: // fall through - case LOAD_ONLINE_USERS: - // this is merged in instead of replacing the state, because sometimes the - // JOIN event from the current user comes in before the LOAD event, and then - // the current user is sometimes excluded from the state. it looks like this - // approach could cause problems, too, though. - // TODO maybe replace state instead anyway and merge in the current user? - return { - ...state, - ...indexBy(payload.users, '_id'), - }; - case USER_JOIN: - return { - ...state, - [payload.user._id]: payload.user, - }; - case USER_LEAVE: - return omit(state, payload.userID); - case CHANGE_USERNAME: - return updateUser(state, payload.userID, (user) => ({ - ...user, - username: payload.username, - })); - case USER_ADD_ROLES: - return updateUser(state, payload.userID, (user) => ({ - ...user, - roles: [...user.roles, ...payload.roles], - })); - case USER_REMOVE_ROLES: - return updateUser(state, payload.userID, (user) => ({ - ...user, - roles: user.roles.filter((role) => !payload.roles.includes(role)), - })); - default: - return state; - } -} - -const reduce = combineReducers({ - guests: guestsReducer, - users: usersReducer, -}); - -export default reduce; diff --git a/src/reducers/users.ts b/src/reducers/users.ts new file mode 100644 index 000000000..171ade0ce --- /dev/null +++ b/src/reducers/users.ts @@ -0,0 +1,141 @@ +import type { AnyAction } from 'redux'; +import { type PayloadAction, createSlice, ThunkAction } from '@reduxjs/toolkit'; +import indexBy from 'just-index'; +import type { StoreState } from '../redux/configureStore'; +import { initState } from './auth'; + +export interface User { + _id: string; + username: string; + avatar: string; + roles: string[]; +} + +interface State { + users: Record<string, User>; + guests: number; +} + +const initialState: State = { + users: {}, + guests: 0, +}; + +const slice = createSlice({ + name: 'users', + initialState, + reducers: { + receiveGuestCount(state, action: PayloadAction<{ guests: number }>) { + state.guests = action.payload.guests; + }, + userJoin(state, action: PayloadAction<{ user: User }>) { + state.users[action.payload.user._id] = action.payload.user; + }, + userLeave(state, action: PayloadAction<{ user: User, userID: string }>) { + delete state.users[action.payload.userID]; + }, + addRoles(state, action: PayloadAction<{ user: User, userID: string, roles: string[] }>) { + const user = state.users[action.payload.userID]; + if (user) { + user.roles = Array.from(new Set([...user.roles, ...action.payload.roles])); + } + }, + removeRoles(state, action: PayloadAction<{ user: User, userID: string, roles: string[] }>) { + const user = state.users[action.payload.userID]; + if (user) { + const remove = new Set(action.payload.roles); + user.roles = user.roles.filter((role) => !remove.has(role)); + } + }, + usernameChanged(state, action: PayloadAction<{ + user: User, + userID: string, + username: string, + }>) { + const user = state.users[action.payload.userID]; + if (user) { + user.username = action.payload.username; + } + }, + }, + extraReducers(builder) { + builder.addCase(initState.fulfilled, (state, action) => { + state.guests = action.payload.guests; + // this is merged in instead of replacing the state, because sometimes the + // JOIN event from the current user comes in before the LOAD event, and then + // the current user is sometimes excluded from the state. it looks like this + // approach could cause problems, too, though. + // TODO maybe replace state instead anyway and merge in the current user? + Object.assign(state.users, indexBy(action.payload.users, '_id')); + }); + }, +}); + +// So other reducers can use them +export const { actions } = slice; + +export const { + receiveGuestCount, + userJoin, +} = actions; + +function selectUser(state: StoreState, userID: string) { + return state.users.users[userID]; +} + +export function userLeave(payload: { userID: string }): + ThunkAction<unknown, StoreState, never, AnyAction> { + return (dispatch, getState) => { + const user = selectUser(getState(), payload.userID); + if (user) { + dispatch(slice.actions.userLeave({ + user, + userID: payload.userID, + })); + } + }; +} + +export function addRoles(payload: { userID: string, roles: string[] }): + ThunkAction<unknown, StoreState, never, AnyAction> { + return (dispatch, getState) => { + const user = selectUser(getState(), payload.userID); + if (user) { + dispatch(slice.actions.addRoles({ + user, + userID: payload.userID, + roles: payload.roles, + })); + } + }; +} + +export function removeRoles(payload: { userID: string, roles: string[] }): + ThunkAction<unknown, StoreState, never, AnyAction> { + return (dispatch, getState) => { + const user = selectUser(getState(), payload.userID); + if (user) { + dispatch(slice.actions.removeRoles({ + user, + userID: payload.userID, + roles: payload.roles, + })); + } + }; +} + +export function usernameChanged(payload: { userID: string, username: string }): + ThunkAction<unknown, StoreState, never, AnyAction> { + return (dispatch, getState) => { + const user = selectUser(getState(), payload.userID); + if (user) { + dispatch(slice.actions.usernameChanged({ + user, + userID: payload.userID, + username: payload.username, + })); + } + }; +} + +export default slice.reducer; diff --git a/src/reducers/votes.js b/src/reducers/votes.ts similarity index 59% rename from src/reducers/votes.js rename to src/reducers/votes.ts index ad11cba10..804baa76b 100644 --- a/src/reducers/votes.js +++ b/src/reducers/votes.ts @@ -1,43 +1,31 @@ +import { AnyAction } from 'redux'; import { - INIT_STATE, - LOAD_VOTES, - ADVANCE, FAVORITE, UPVOTE, DOWNVOTE, - DO_FAVORITE_START, - DO_FAVORITE_COMPLETE, } from '../constants/ActionTypes'; +import { advance } from './booth'; +import { initState } from './auth'; -const initialState = { +export interface VoteStats { + upvotes: string[]; + downvotes: string[]; + favorites: string[]; +} + +const initialState: VoteStats = { upvotes: [], downvotes: [], favorites: [], }; -function setVotes(state, stats) { - return { - ...state, - upvotes: stats.upvotes, - downvotes: stats.downvotes, - favorites: stats.favorites, - }; -} - -export default function reduce(state = initialState, action = {}) { +export default function reduce(state = initialState, action: AnyAction): VoteStats { const { type, payload } = action; switch (type) { - case INIT_STATE: { - const { stats } = payload.booth ?? {}; - if (stats) { - return setVotes(state, stats); - } - return initialState; - } - case ADVANCE: + case initState.fulfilled.type: + return payload.booth?.stats ?? initialState; + case advance.type: return initialState; - case LOAD_VOTES: - return setVotes(state, payload); case UPVOTE: if (state.upvotes.includes(payload.userID)) { return state; @@ -64,10 +52,6 @@ export default function reduce(state = initialState, action = {}) { ...state, favorites: [...state.favorites, payload.userID], }; - case DO_FAVORITE_START: - return state; - case DO_FAVORITE_COMPLETE: - return state; default: return state; } diff --git a/src/reducers/waitlist.js b/src/reducers/waitlist.js deleted file mode 100644 index e3d6eac19..000000000 --- a/src/reducers/waitlist.js +++ /dev/null @@ -1,51 +0,0 @@ -import { - INIT_STATE, - WAITLIST_LOAD, - WAITLIST_LOCK, - WAITLIST_CLEAR, - WAITLIST_UPDATE, - WAITLIST_JOIN, - WAITLIST_LEAVE, -} from '../constants/ActionTypes'; - -const initialState = { - waitlist: [], - locked: false, -}; - -export default function reduce(state = initialState, action = {}) { - const { type, payload } = action; - switch (type) { - case INIT_STATE: - return { - ...state, - waitlist: payload.waitlist, - locked: payload.waitlistLocked, - }; - case WAITLIST_LOAD: - return { - ...state, - waitlist: payload.waitlist, - locked: payload.locked, - }; - case WAITLIST_LOCK: - return { - ...state, - locked: payload.locked, - }; - case WAITLIST_CLEAR: - return { - ...state, - waitlist: [], - }; - case WAITLIST_JOIN: - case WAITLIST_LEAVE: - case WAITLIST_UPDATE: - return { - ...state, - waitlist: payload.waitlist, - }; - default: - return state; - } -} diff --git a/src/reducers/waitlist.ts b/src/reducers/waitlist.ts new file mode 100644 index 000000000..d57b70d49 --- /dev/null +++ b/src/reducers/waitlist.ts @@ -0,0 +1,72 @@ +import { type PayloadAction, createSlice } from '@reduxjs/toolkit'; +import type { StoreState } from '../redux/configureStore'; +import { initState } from './auth'; + +interface State { + waitlist: string[]; + locked: boolean; +} + +const initialState: State = { + waitlist: [], + locked: false, +}; + +const slice = createSlice({ + name: 'waitlist', + initialState, + reducers: { + lock(state, action: PayloadAction<{ locked: boolean }>) { + state.locked = action.payload.locked; + }, + clear(state) { + state.waitlist = []; + }, + join(state, action: PayloadAction<{ userID: string, waitlist: string[] }>) { + state.waitlist = action.payload.waitlist; + }, + leave(state, action: PayloadAction<{ userID: string, waitlist: string[] }>) { + state.waitlist = action.payload.waitlist; + }, + moved(state, action: PayloadAction<{ + userID: string, + moderatorID: string, + position: number, + waitlist: string[], + }>) { + state.waitlist = action.payload.waitlist; + }, + update(state, action: PayloadAction<{ waitlist: string[] }>) { + state.waitlist = action.payload.waitlist; + }, + }, + extraReducers(builder) { + builder.addCase(initState.fulfilled, (state, action) => { + state.waitlist = action.payload.waitlist; + state.locked = action.payload.waitlistLocked; + }); + }, +}); + +export const { + lock, + clear, + join, + leave, + moved, + update, +} = slice.actions; + +export function isLockedSelector(state: StoreState) { + return state.waitlist.locked; +} + +export function sizeSelector(state: StoreState) { + return state.waitlist.waitlist.length; +} + +export function waitlistIDsSelector(state: StoreState) { + return state.waitlist.waitlist; +} + +export default slice.reducer; diff --git a/src/redux/api.ts b/src/redux/api.ts new file mode 100644 index 000000000..bcc76ed53 --- /dev/null +++ b/src/redux/api.ts @@ -0,0 +1,7 @@ +import * as rtk from '@reduxjs/toolkit'; +import type { StoreState } from './configureStore'; + +// eslint-disable-next-line import/prefer-default-export +export const createAsyncThunk = rtk.createAsyncThunk.withTypes<{ + state: StoreState, +}>(); diff --git a/src/redux/configureStore.js b/src/redux/configureStore.js index 989643fcf..54d3fd6cf 100644 --- a/src/redux/configureStore.js +++ b/src/redux/configureStore.js @@ -1,63 +1,37 @@ -import { - applyMiddleware, combineReducers, compose, createStore, -} from 'redux'; -import thunk from 'redux-thunk'; +import { combineReducers, configureStore } from '@reduxjs/toolkit'; import persistSettings from './persistSettings'; import webApiRequest from './request'; import webApiSocket from './socket'; +import webApiSocketHandler from './socketHandler'; import * as reducers from '../reducers'; -import createSourcesReducer from '../reducers/createSourcesReducer'; +import youtubeSourceReducer from '../sources/youtube/reducer'; -// Setting up a store in Redux can be kind of messy because there are a lot of -// things coming together in one place. Luckily, we don't have _that_ much going -// on in üWave, so it's kind of manageable. +const reducer = combineReducers({ + ...reducers, + mediaSources: combineReducers({ + youtube: youtubeSourceReducer, + }), +}); -function createUwaveStore(initialState = {}, options = {}) { - const isTesting = typeof jest !== 'undefined'; - - const middleware = [ - // Redux-Thunk allows dispatching a function to the store instead of an - // action object. These functions can then dispatch action objects as they - // please. It's used primarily for async actions: for example, actions that - // send HTTP requests. Those might dispatch an action object once the - // request finishes. - thunk, - // This allows dispatching REQUEST_START actions to the store, which will - // then be executed and handled as HTTP requests by the middleware. - webApiRequest(), - !isTesting && webApiSocket({ url: options.socketUrl }), - ].filter(Boolean); - - const store = createStore( - // Finish up the reducer function by combining all the different reducers - // into one big reducer that works on one big state object. - combineReducers({ - ...reducers, - sources: createSourcesReducer(options), - }), - initialState, - compose( - // Adds all of the above ☝ middleware features to the store. - applyMiddleware(...middleware), - // Keeps the user's settings in localStorage, so that a refresh doesn't - // reset all your preferences. - // This is done separately from the Middleware features, because it changes - // the _initial_ `settings` state, something that Middleware can't do. - persistSettings, +function createUwaveStore(preloadedState = {}, options = {}) { + const store = configureStore({ + reducer, + middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat( + // This allows dispatching REQUEST_START actions to the store, which will + // then be executed and handled as HTTP requests by the middleware. + webApiRequest(), + webApiSocket({ url: options.socketUrl }), + webApiSocketHandler.middleware, ), - ); - - if (import.meta.hot) { - // Update the store's reducer function when the reducer source code has changed. - import.meta.hot.accept('../reducers/index.js', () => { - store.replaceReducer(combineReducers({ - ...reducers, - sources: createSourcesReducer(options), - })); - }); - } + enhancers: [persistSettings], + preloadedState, + }); return store; } +/** @typedef {ReturnType<typeof reducer>} StoreState */ +/** @typedef {import('redux').Dispatch & + * import('@reduxjs/toolkit').ThunkDispatch<StoreState, void>} AppDispatch */ + export default createUwaveStore; diff --git a/src/redux/persistSettings.d.ts b/src/redux/persistSettings.d.ts new file mode 100644 index 000000000..fd420ee9b --- /dev/null +++ b/src/redux/persistSettings.d.ts @@ -0,0 +1,5 @@ +import { StoreEnhancer } from 'redux'; + +declare const persistSettings: StoreEnhancer; + +export default persistSettings; diff --git a/src/redux/persistSettings.js b/src/redux/persistSettings.js index a5624d875..5e9aea8af 100644 --- a/src/redux/persistSettings.js +++ b/src/redux/persistSettings.js @@ -1,4 +1,4 @@ -import { loadSettings } from '../actions/SettingsActionCreators'; +import { load as loadSettings } from '../reducers/settings'; const SETTINGS_KEY = 'uwaveSettings'; @@ -19,7 +19,9 @@ const persistSettings = (next) => (reducer, initialState) => { const store = next(reducer, initialState); - store.dispatch(loadSettings(settings)); + if (settings) { + store.dispatch(loadSettings(settings)); + } let prevSettings = settings; store.subscribe(() => { diff --git a/src/redux/socket.js b/src/redux/socket.js deleted file mode 100644 index 4d1583711..000000000 --- a/src/redux/socket.js +++ /dev/null @@ -1,316 +0,0 @@ -import { - LOGIN_COMPLETE, - LOGOUT_START, - SOCKET_CONNECT, - SOCKET_RECONNECT, - SOCKET_DISCONNECTED, - SOCKET_CONNECTED, - SEND_MESSAGE, -} from '../constants/ActionTypes'; -import { initState } from '../actions/LoginActionCreators'; -import { - advance, - skipped, -} from '../actions/BoothActionCreators'; -import { - receive as chatReceive, - removeMessage, - removeMessagesByUser, - removeAllMessages, - muteUser as chatMute, - unmuteUser as chatUnmute, - loadEmotes, -} from '../actions/ChatActionCreators'; -import { cyclePlaylist } from '../actions/PlaylistActionCreators'; -import { - join as userJoin, - leave as userLeave, - changeUsername, - addUserRoles, - removeUserRoles, - receiveGuestCount, -} from '../actions/UserActionCreators'; -import { - clearWaitlist, - joinedWaitlist, - leftWaitlist, - updatedWaitlist, - movedInWaitlist, - setLocked as setWaitlistLocked, -} from '../actions/WaitlistActionCreators'; -import { favorited, receiveVote } from '../actions/VoteActionCreators'; - -function defaultUrl() { - const loc = window.location; - const port = loc.port ?? (loc.protocol === 'https:' ? 443 : 80); - const protocol = loc.protocol === 'https:' ? 'wss:' : 'ws:'; - return `${protocol}//${loc.hostname}:${port}/api/socket`; -} - -const actions = { - chatMessage({ - id, userID, message, timestamp, - }) { - return chatReceive({ - _id: id, - userID, - text: message, - timestamp, - }); - }, - chatDelete() { - return removeAllMessages(); - }, - chatDeleteByID({ _id }) { - return removeMessage(_id); - }, - chatDeleteByUser({ userID }) { - return removeMessagesByUser(userID); - }, - chatMute({ userID, expiresAt, moderatorID }) { - return chatMute(userID, { moderatorID, expiresAt }); - }, - chatUnmute({ userID, moderatorID }) { - return chatUnmute(userID, { moderatorID }); - }, - advance(booth) { - return advance(booth); - }, - skip({ userID, moderatorID, reason }) { - return skipped({ userID, moderatorID, reason }); - }, - favorite({ userID, historyID }) { - return favorited({ userID, historyID }); - }, - vote({ _id, value }) { - return receiveVote({ userID: _id, vote: value }); - }, - waitlistJoin({ userID, waitlist }) { - return joinedWaitlist({ userID, waitlist }); - }, - waitlistLeave({ userID, waitlist }) { - return leftWaitlist({ userID, waitlist }); - }, - waitlistUpdate(waitlist) { - return updatedWaitlist(waitlist); - }, - waitlistLock({ locked }) { - return setWaitlistLocked(locked); - }, - waitlistMove({ - userID, moderatorID, position, waitlist, - }) { - return movedInWaitlist({ - userID, moderatorID, position, waitlist, - }); - }, - // TODO Treat moderator force-add and force-remove differently from voluntary - // joins and leaves. - waitlistAdd({ userID, waitlist }) { - return joinedWaitlist({ userID, waitlist }); - }, - waitlistRemove({ userID, waitlist }) { - return leftWaitlist({ userID, waitlist }); - }, - waitlistClear() { - return clearWaitlist(); - }, - playlistCycle({ playlistID }) { - return cyclePlaylist(playlistID); - }, - join(user) { - return userJoin(user); - }, - leave(userID) { - return userLeave(userID); - }, - nameChange({ userID, username }) { - return changeUsername(userID, username); - }, - guests: receiveGuestCount, - 'acl:allow': ({ userID, roles }) => addUserRoles(userID, roles), - 'acl:disallow': ({ userID, roles }) => removeUserRoles(userID, roles), - reloadEmotes: loadEmotes, -}; - -// WebSocket wrapper with reconnection and message parsing. -// This is quite ugly, based on an older version which used reconnecting-websocket -// and a bunch of separate functions nested inside the middleware. -// This should be refactored to move the message handling out of the class, -// and probably move the dispatch() calls to events using `mitt` or options. -class UwaveSocket { - constructor({ url, dispatch, getState }) { - this.url = url; - this.socket = null; - this.queue = []; - this.sentAuthToken = false; - this.authToken = null; - this.opened = false; - this.reconnectAttempts = 0; - this.reconnectTimeout = null; - this.dispatch = dispatch; - this.getState = getState; - } - - isOpen() { - return this.socket && this.opened; - } - - sendAuthToken(token) { - if (this.isOpen()) { - this.socket.send(token); - this.sentAuthToken = true; - } else { - this.authToken = token; - } - } - - send(command, data) { - if (this.isOpen()) { - this.socket.send(JSON.stringify({ command, data })); - } else { - this.queue.push({ command, data }); - } - } - - drainQueuedMessages() { - const messages = this.queue; - this.queue = []; - messages.forEach((msg) => { - this.send(msg.command, msg.data); - }); - } - - onOpen = () => { - this.opened = true; - if (this.authToken) { - this.socket.send(this.authToken); - this.authToken = null; - this.sentAuthToken = true; - } - this.dispatch({ type: SOCKET_CONNECTED }); - }; - - onClose = () => { - if (this.reconnectAttempts === 0) { - this.opened = false; - this.dispatch({ type: SOCKET_DISCONNECTED }); - this.attemptReconnect(); - } - }; - - onMessage = (pack) => { - // Ignore keepalive messages. - if (pack.data === '-') return; - - const { command, data } = JSON.parse(pack.data); - - if (command === 'authenticated') { - this.drainQueuedMessages(); - return; - } - - if (typeof actions[command] === 'function') { - const action = actions[command](data); - if (action) { - this.dispatch(action); - } - } - }; - - connect() { - return new Promise((resolve, reject) => { - this.socket = new WebSocket(this.url); - this.socket.addEventListener('message', this.onMessage); - this.socket.addEventListener('open', () => { - this.onOpen(); - resolve(); - }); - this.socket.addEventListener('close', this.onClose); - this.socket.addEventListener('error', reject); - }); - } - - disconnect() { - this.socket.removeEventListener('close', this.onClose); - this.socket.addEventListener('close', () => { - this.opened = false; - this.dispatch({ type: SOCKET_DISCONNECTED }); - this.socket = null; - }); - this.socket.close(); - } - - reconnect() { - return this.dispatch(initState()) - .then(({ socketToken }) => ( - this.connect().then(() => { - this.sendAuthToken(socketToken); - }) - )) - .then(() => { - this.drainQueuedMessages(); - }); - } - - attemptReconnect = () => { - this.reconnectAttempts += 1; - this.reconnect().then(() => { - this.reconnectAttempts = 0; - }, () => { - this.reconnectTimeout = setTimeout( - this.attemptReconnect, - Math.min(1000 * this.reconnectAttempts, 10000), - ); - }); - }; -} - -export default function middleware({ url = defaultUrl() } = {}) { - return ({ dispatch, getState }) => { - const socket = new UwaveSocket({ - url, - dispatch, - getState, - }); - - window.soc = socket; // eslint-disable-line - - return (next) => (action) => { - const { type, payload, error } = action; - - if (error) { - next(action); - return; - } - - switch (type) { - case SOCKET_RECONNECT: - socket.disconnect(); - socket.attemptReconnect(); - break; - case SOCKET_CONNECT: - socket.connect().catch(() => { - // Start attempting reconnects - socket.attemptReconnect(); - }); - break; - case SEND_MESSAGE: - socket.send('sendChat', payload.message); - break; - case LOGIN_COMPLETE: - if (!socket.sentAuthToken) { - socket.sendAuthToken(payload.socketToken); - } - break; - case LOGOUT_START: - socket.sentAuthToken = false; - socket.send('logout', null); - break; - default: - break; - } - next(action); - }; - }; -} diff --git a/src/redux/socket.ts b/src/redux/socket.ts new file mode 100644 index 000000000..9b954e503 --- /dev/null +++ b/src/redux/socket.ts @@ -0,0 +1,348 @@ +import type { Middleware } from 'redux'; +import { createAction } from '@reduxjs/toolkit'; +import type { AppDispatch } from './configureStore'; +import { + LOGOUT_START, + SOCKET_CONNECT, + SOCKET_RECONNECT, + SOCKET_DISCONNECTED, + SOCKET_CONNECTED, +} from '../constants/ActionTypes'; +import { sendMessage } from '../reducers/chat'; +import { type InitialStatePayload, initState, login } from '../reducers/auth'; + +function defaultUrl() { + const loc = window.location; + const port = loc.port ?? (loc.protocol === 'https:' ? 443 : 80); + const protocol = loc.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${protocol}//${loc.hostname}:${port}/api/socket`; +} + +export type SocketMessageParams = { + join: { + _id: string, + username: string, + slug: string, + roles: string[], + avatar: string, + createdAt: string, + updatedAt: string, + lastSeenAt: string, + }, + leave: string, + guests: number, + + advance: { + historyID: string, + userID: string, + itemID: string, + media: { + artist: string, + title: string, + start: number, + end: number, + media: { + sourceType: string, + sourceID: string, + artist: string, + title: string, + sourceData: object, + }, + }, + playedAt: number, + } | null, + skip: { + userID: string, + moderatorID: string, + reason: string, + }, + + chatMessage: { + id: string, + userID: string, + message: string, + timestamp: number, + }, + chatDelete: { + moderatorID: string, + }, + chatDeleteByID: { + moderatorID: string, + _id: string, + }, + chatDeleteByUser: { + moderatorID: string, + userID: string, + }, + chatMute: { + userID: string, + moderatorID: string, + expiresAt: number, + }, + chatUnmute: { + userID: string, + moderatorID: string, + }, + vote: { + _id: string, + value: -1 | 1, + }, + favorite: { + userID: string, + }, + playlistCycle: { + playlistID: string, + }, + waitlistUpdate: string[], + waitlistJoin: { + userID: string, + waitlist: string[], + }, + waitlistLeave: { + userID: string, + waitlist: string[], + }, + waitlistAdd: { + userID: string, + waitlist: string[], + }, + waitlistMove: { + userID: string, + moderatorID: string, + position: number, + waitlist: string[], + }, + waitlistRemove: { + userID: string, + waitlist: string[], + }, + waitlistClear: { + moderatorID: string, + }, + waitlistLock: { + moderatorID: string, + locked: boolean, + }, + + nameChange: { + userID: string, + username: string, + }, + 'acl:allow': { + userID: string, + roles: string[], + }, + 'acl:disallow': { + userID: string, + roles: string[], + }, + + reloadEmotes: void, +} + +export type SocketMessage = { + [K in keyof SocketMessageParams]: { + command: K, + data: SocketMessageParams[K], + }; +}[keyof SocketMessageParams]; + +export const socketMessage = createAction('websocket/receive', (payload: SocketMessage) => ({ payload })); + +// WebSocket wrapper with reconnection and message parsing. +// This is quite ugly, based on an older version which used reconnecting-websocket +// and a bunch of separate functions nested inside the middleware. +// This should be refactored to move the message handling out of the class, +// and probably move the dispatch() calls to events using `mitt` or options. +class UwaveSocket { + socket: WebSocket | null = null; + + queue: { command: string, data: object | null }[] = []; + + sentAuthToken = false; + + authToken: string | null = null; + + opened = false; + + reconnectAttempts = 0; + + reconnectTimeout: ReturnType<typeof setTimeout> | null = null; + + url: string; + + dispatch: AppDispatch; + + constructor({ url, dispatch }: { + url: string, + dispatch: AppDispatch, + }) { + this.url = url; + this.dispatch = dispatch; + } + + isOpen(): this is { socket: WebSocket } { + return this.socket != null && this.opened; + } + + sendAuthToken(token: string) { + if (this.isOpen()) { + this.socket.send(token); + this.sentAuthToken = true; + } else { + this.authToken = token; + } + } + + send(command: string, data: object | null) { + if (this.isOpen()) { + this.socket.send(JSON.stringify({ command, data })); + } else { + this.queue.push({ command, data }); + } + } + + drainQueuedMessages() { + const messages = this.queue; + this.queue = []; + messages.forEach((msg) => { + this.send(msg.command, msg.data); + }); + } + + onOpen = () => { + this.opened = true; + if (!this.isOpen()) { + return; // Just to help typescript + } + + if (this.authToken) { + this.socket.send(this.authToken); + this.authToken = null; + this.sentAuthToken = true; + } + this.dispatch({ type: SOCKET_CONNECTED }); + }; + + onClose = () => { + if (this.reconnectAttempts === 0) { + this.opened = false; + this.dispatch({ type: SOCKET_DISCONNECTED }); + this.attemptReconnect(); + } + }; + + onMessage = (pack: MessageEvent) => { + // Ignore keepalive messages. + if (pack.data === '-') return; + + const { command, data } = JSON.parse(pack.data); + if (typeof command !== 'string') { + return; + } + + if (command === 'authenticated') { + this.drainQueuedMessages(); + return; + } + + this.dispatch(socketMessage({ + command, + data, + } as SocketMessage)); + }; + + connect() { + return new Promise<void>((resolve, reject) => { + this.socket = new WebSocket(this.url); + this.socket.addEventListener('message', this.onMessage); + this.socket.addEventListener('open', () => { + this.onOpen(); + resolve(); + }); + this.socket.addEventListener('close', this.onClose); + this.socket.addEventListener('error', reject); + }); + } + + disconnect() { + if (!this.isOpen()) { + return; + } + + this.socket.removeEventListener('close', this.onClose); + this.socket.addEventListener('close', () => { + this.opened = false; + this.dispatch({ type: SOCKET_DISCONNECTED }); + }); + this.socket.close(); + } + + async reconnect() { + const payload = (await this.dispatch(initState())).payload as InitialStatePayload; + await this.connect(); + if (payload.socketToken) { + this.sendAuthToken(payload.socketToken); + } + this.drainQueuedMessages(); + } + + attemptReconnect = () => { + this.reconnectAttempts += 1; + this.reconnect().then(() => { + this.reconnectAttempts = 0; + }, () => { + this.reconnectTimeout = setTimeout( + this.attemptReconnect, + Math.min(1000 * this.reconnectAttempts, 10000), + ); + }); + }; +} + +export default function middleware({ url = defaultUrl() } = {}): Middleware { + return ({ dispatch }) => { + const socket = new UwaveSocket({ + url, + dispatch, + }); + + return (next) => (action) => { + const { type, payload, error } = action; + + if (error) { + next(action); + return; + } + + switch (type) { + case SOCKET_RECONNECT: + socket.disconnect(); + socket.attemptReconnect(); + break; + case SOCKET_CONNECT: + socket.connect().catch(() => { + // Start attempting reconnects + socket.attemptReconnect(); + }); + break; + case sendMessage.type: + socket.send('sendChat', payload.message); + break; + case login.fulfilled.type: + case initState.fulfilled.type: + if (!socket.sentAuthToken && payload.socketToken) { + socket.sendAuthToken(payload.socketToken); + } + break; + case LOGOUT_START: + socket.sentAuthToken = false; + socket.send('logout', null); + break; + default: + break; + } + next(action); + }; + }; +} diff --git a/src/redux/socketHandler.ts b/src/redux/socketHandler.ts new file mode 100644 index 000000000..92c8fa1f0 --- /dev/null +++ b/src/redux/socketHandler.ts @@ -0,0 +1,143 @@ +import { createListenerMiddleware } from '@reduxjs/toolkit'; +import { mutate } from 'swr'; +import type { AppDispatch, StoreState } from './configureStore'; +import { advance, skipped } from '../actions/BoothActionCreators'; +import { + deleteMessageByID, + deleteMessagesByUser, + deleteAllMessages, + muteUser, + unmuteUser, +} from '../reducers/chat'; +import * as waitlistActions from '../reducers/waitlist'; +import { receive as receiveMessage } from '../actions/ChatActionCreators'; +import { cyclePlaylist } from '../actions/PlaylistActionCreators'; +import { favorited, receiveVote } from '../actions/VoteActionCreators'; +import { currentTimeSelector } from '../selectors/timeSelectors'; +import { + addRoles, + receiveGuestCount, + removeRoles, + userJoin, + userLeave, + usernameChanged, +} from '../reducers/users'; +import { socketMessage } from './socket'; + +function expectType<T>( + _param: T, // eslint-disable-line @typescript-eslint/no-unused-vars +) { + // type-only function +} + +const middleware = createListenerMiddleware<StoreState, AppDispatch>(); +middleware.startListening({ + actionCreator: socketMessage, + effect: (action, api) => { + const { command, data } = action.payload; + switch (command) { + // Booth + case 'advance': + api.dispatch(advance(data)); + break; + case 'favorite': + api.dispatch(favorited(data)); + break; + case 'vote': + api.dispatch(receiveVote({ userID: data._id, vote: data.value })); + break; + case 'skip': + api.dispatch(skipped(data)); + break; + // Users + case 'join': + api.dispatch(userJoin({ user: data })); + break; + case 'leave': + api.dispatch(userLeave({ userID: data })); + break; + case 'nameChange': + api.dispatch(usernameChanged(data)); + break; + case 'guests': + api.dispatch(receiveGuestCount({ guests: data })); + break; + // Chat + case 'chatMessage': + api.dispatch(receiveMessage({ + _id: data.id, + userID: data.userID, + text: data.message, + timestamp: data.timestamp, + })); + break; + case 'chatDelete': + api.dispatch(deleteAllMessages()); + break; + case 'chatDeleteByID': + api.dispatch(deleteMessageByID(data)); + break; + case 'chatDeleteByUser': + api.dispatch(deleteMessagesByUser(data)); + break; + case 'chatMute': { + const currentTime = currentTimeSelector(api.getState()); + const expireIn = data.expiresAt - currentTime; + const expirationTimer = expireIn > 0 + ? setTimeout(() => api.dispatch(unmuteUser({ userID: data.userID })), expireIn) + : null; + api.dispatch(muteUser({ + ...data, + expirationTimer, + })); + break; + } + case 'chatUnmute': + api.dispatch(unmuteUser(data)); + break; + case 'acl:allow': + api.dispatch(addRoles(data)); + break; + case 'acl:disallow': + api.dispatch(removeRoles(data)); + break; + case 'reloadEmotes': + mutate('/emotes'); + break; + case 'playlistCycle': + api.dispatch(cyclePlaylist(data.playlistID)); + break; + case 'waitlistJoin': + api.dispatch(waitlistActions.join(data)); + break; + case 'waitlistLeave': + api.dispatch(waitlistActions.leave(data)); + break; + case 'waitlistUpdate': + api.dispatch(waitlistActions.update({ waitlist: data })); + break; + case 'waitlistLock': + api.dispatch(waitlistActions.lock(data)); + break; + case 'waitlistMove': + api.dispatch(waitlistActions.moved(data)); + break; + // TODO Treat moderator force-add and force-remove differently from voluntary + // joins and leaves. + case 'waitlistAdd': + api.dispatch(waitlistActions.join(data)); + break; + case 'waitlistRemove': + api.dispatch(waitlistActions.leave(data)); + break; + case 'waitlistClear': + api.dispatch(waitlistActions.clear()); + break; + default: + // Never happens + expectType<never>(command); + } + }, +}); + +export default middleware; diff --git a/src/selectors/addToPlaylistMenuSelectors.js b/src/selectors/addToPlaylistMenuSelectors.js deleted file mode 100644 index e3d12c30e..000000000 --- a/src/selectors/addToPlaylistMenuSelectors.js +++ /dev/null @@ -1,30 +0,0 @@ -import { createSelector, createStructuredSelector } from 'reselect'; -import { playlistsSelector } from './playlistSelectors'; - -const baseSelector = (state) => state.addToPlaylistMenu; -export const isOpenSelector = createSelector(baseSelector, (menu) => menu.open); -export const positionSelector = createSelector(baseSelector, (menu) => menu.position); -const typeSelector = createSelector(baseSelector, (menu) => menu.type); -const dataSelector = createSelector(baseSelector, (menu) => menu.data); - -export const isFavoriteSelector = createSelector(typeSelector, (type) => type === 'favorite'); - -export const mediaSelector = createSelector( - dataSelector, - isOpenSelector, - isFavoriteSelector, - (data, isOpen, isFavorite) => (isOpen && !isFavorite ? data.media : null), -); -export const historyIDSelector = createSelector( - dataSelector, - isOpenSelector, - isFavoriteSelector, - (data, isOpen, isFavorite) => (isOpen && isFavorite ? data.historyID : null), -); - -export const addToPlaylistMenuSelector = createStructuredSelector({ - type: typeSelector, - open: isOpenSelector, - position: positionSelector, - playlists: playlistsSelector, -}); diff --git a/src/selectors/boothSelectors.js b/src/selectors/boothSelectors.js index 3f5babc53..b71f44f57 100644 --- a/src/selectors/boothSelectors.js +++ b/src/selectors/boothSelectors.js @@ -1,14 +1,15 @@ import { createSelector } from 'reselect'; - import { isPreviewMediaDialogOpenSelector } from './dialogSelectors'; -import { isMutedSelector, volumeSelector } from './settingSelectors'; +import { isMutedSelector, volumeSelector } from '../reducers/settings'; import { currentTimeSelector } from './timeSelectors'; +import { currentVotesSelector } from './voteSelectors'; import { currentUserSelector, currentUserHasRoleSelector, usersSelector, } from './userSelectors'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.booth; export const historyIDSelector = createSelector(baseSelector, (booth) => booth.historyID); @@ -42,7 +43,12 @@ export const timeRemainingSelector = createSelector( export const djSelector = createSelector( baseSelector, usersSelector, - (booth, users) => users[booth.djID], + (booth, users) => { + if (booth.djID && booth.djID in users) { + return users[booth.djID]; + } + return null; + }, ); export const isCurrentDJSelector = createSelector( @@ -83,3 +89,23 @@ export const mobilePlaybackVolumeSelector = createSelector( playbackMutedSelector, (isMuted) => (isMuted ? 0 : 100), ); + +export const currentPlaySelector = createSelector( + historyIDSelector, + mediaSelector, + startTimeSelector, + djSelector, + currentVotesSelector, + (historyID, media, timestamp, dj, stats) => { + if (!historyID || !media || !dj || !timestamp || !stats) { + return null; + } + return { + _id: historyID, + user: dj, + media, + timestamp, + stats, + }; + }, +); diff --git a/src/selectors/chatSelectors.js b/src/selectors/chatSelectors.js index 79c8866a0..cd65bda0a 100644 --- a/src/selectors/chatSelectors.js +++ b/src/selectors/chatSelectors.js @@ -15,6 +15,7 @@ import { } from './userSelectors'; import { notificationSettingsSelector } from './settingSelectors'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.chat; export const rawMotdSelector = createSelector(baseSelector, (chat) => chat.motd); diff --git a/src/selectors/configSelectors.js b/src/selectors/configSelectors.js index 7cb3455e5..51815e9d3 100644 --- a/src/selectors/configSelectors.js +++ b/src/selectors/configSelectors.js @@ -1,6 +1,7 @@ import { createSelector } from 'reselect'; import defaultEmoji from '../utils/emojiShortcodes'; +/** @param {import('../redux/configureStore').StoreState} state */ export const configSelector = (state) => state.config; export const requestOptionsSelector = createSelector( @@ -17,11 +18,9 @@ export const requestOptionsSelector = createSelector( export const availableEmojiImagesSelector = createSelector( configSelector, (config) => { - const serverEmotes = config.serverEmotes.map(({ name, url }) => [name, url]); return { ...defaultEmoji, ...config.emoji, - ...Object.fromEntries(serverEmotes), }; }, ); diff --git a/src/selectors/dialogSelectors.js b/src/selectors/dialogSelectors.js index 5aeb02617..aca0323bc 100644 --- a/src/selectors/dialogSelectors.js +++ b/src/selectors/dialogSelectors.js @@ -1,8 +1,9 @@ import { createSelector } from 'reselect'; import { reCaptchaSiteKeySelector } from './configSelectors'; -import { volumeSelector } from './settingSelectors'; +import { volumeSelector } from '../reducers/settings'; import { supportsSocialAuthSelector } from './userSelectors'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.dialogs; const merge = (dialog) => ({ ...dialog.payload, open: dialog.open }); diff --git a/src/selectors/errorSelectors.js b/src/selectors/errorSelectors.js index eccd7a277..59a8334f8 100644 --- a/src/selectors/errorSelectors.js +++ b/src/selectors/errorSelectors.js @@ -1,5 +1,6 @@ import { createSelector } from 'reselect'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.errors; // eslint-disable-next-line import/prefer-default-export diff --git a/src/selectors/importSelectors.js b/src/selectors/importSelectors.js deleted file mode 100644 index 9a208475f..000000000 --- a/src/selectors/importSelectors.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createSelector } from 'reselect'; - -const baseSelector = (state) => state.imports; - -export const selectedSourceTypeSelector = createSelector( - baseSelector, - (imports) => imports.sourceType, -); - -export const showImportPanelSelector = createSelector( - baseSelector, - (imports) => imports.showPanel, -); diff --git a/src/selectors/localeSelectors.js b/src/selectors/localeSelectors.js index 985c73313..03016b4d2 100644 --- a/src/selectors/localeSelectors.js +++ b/src/selectors/localeSelectors.js @@ -2,9 +2,10 @@ import { createSelector } from 'reselect'; import Translator from '@u-wave/translate'; import * as plurals from '@u-wave/translate/plurals'; import { availableLanguages } from '../locales'; -import { languageSelector as currentLanguageSelector } from './settingSelectors'; +import { languageSelector as currentLanguageSelector } from '../reducers/settings'; const defaultLanguageSelector = () => 'en'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.locales; const loadedSelector = createSelector(baseSelector, (base) => base.loaded); diff --git a/src/selectors/playlistSelectors.js b/src/selectors/playlistSelectors.js index 30645c8b5..242601881 100644 --- a/src/selectors/playlistSelectors.js +++ b/src/selectors/playlistSelectors.js @@ -3,6 +3,7 @@ import naturalCmp from 'natural-compare'; const byName = (a, b) => naturalCmp(a.name.toLowerCase(), b.name.toLowerCase()); +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.playlists; export const playlistsByIDSelector = createSelector( @@ -28,7 +29,12 @@ export const activePlaylistIDSelector = createSelector( const activeMediaSelector = createSelector( playlistItemsSelector, activePlaylistIDSelector, - (playlistItems, activePlaylist) => playlistItems[activePlaylist] ?? [], + (playlistItems, activePlaylist) => { + if (activePlaylist && activePlaylist in playlistItems) { + return playlistItems[activePlaylist]; + } + return []; + }, ); function mergePlaylistItems(playlist, playlistItems) { @@ -58,7 +64,12 @@ export const selectedPlaylistIDSelector = createSelector( const selectedMediaSelector = createSelector( playlistItemsSelector, selectedPlaylistIDSelector, - (playlistItems, selectedPlaylist) => playlistItems[selectedPlaylist] ?? [], + (playlistItems, selectedPlaylist) => { + if (selectedPlaylist && selectedPlaylist in playlistItems) { + return playlistItems[selectedPlaylist]; + } + return []; + }, ); const filterSelector = createSelector( @@ -83,10 +94,9 @@ export const playlistItemFilterSelector = createSelector( ); export const filteredSelectedPlaylistItemsSelector = createSelector( - selectedPlaylistIDSelector, selectedMediaSelector, currentFilterSelector, - (selectedID, selectedItems, filter) => { + (selectedItems, filter) => { if (filter) { return filter.items; } @@ -99,7 +109,9 @@ export const selectedPlaylistSelector = createSelector( selectedPlaylistIDSelector, selectedMediaSelector, (playlists, selectedID, selectedMedia) => ( - mergePlaylistItems(playlists.playlists[selectedID], selectedMedia) + typeof selectedID === 'string' + ? mergePlaylistItems(playlists.playlists[selectedID], selectedMedia) + : null ), ); diff --git a/src/selectors/roomHistorySelectors.js b/src/selectors/roomHistorySelectors.js deleted file mode 100644 index 365caf685..000000000 --- a/src/selectors/roomHistorySelectors.js +++ /dev/null @@ -1,61 +0,0 @@ -import { createSelector } from 'reselect'; -import { - historyIDSelector, mediaSelector, startTimeSelector, djSelector, -} from './boothSelectors'; -import { currentUserSelector } from './userSelectors'; -import { currentVotesSelector } from './voteSelectors'; - -const byTimestamp = (a, b) => (a.timestamp < b.timestamp ? 1 : -1); - -const baseSelector = (state) => state.roomHistory; - -export const roomHistorySelector = createSelector( - baseSelector, - (history) => history.slice().sort(byTimestamp), -); - -const addOwnVoteProps = (id) => (entry) => ({ - ...entry, - stats: { - ...entry.stats, - // No ID is provided for guest users. - isDownvote: !!id && entry.stats.downvotes.includes(id), - isFavorite: !!id && entry.stats.favorites.includes(id), - isUpvote: !!id && entry.stats.upvotes.includes(id), - }, -}); - -export const currentPlaySelector = createSelector( - currentUserSelector, - historyIDSelector, - mediaSelector, - startTimeSelector, - djSelector, - currentVotesSelector, - (user, historyID, media, timestamp, dj, stats) => { - if (!historyID) { - return null; - } - const entry = { - _id: historyID, - user: dj, - media, - timestamp, - stats, - }; - return addOwnVoteProps(user ? user._id : null)(entry); - }, -); - -export const roomHistoryWithVotesSelector = createSelector( - roomHistorySelector, - currentUserSelector, - currentPlaySelector, - (history, user, current) => { - const roomHistory = history.map(addOwnVoteProps(user ? user._id : null)); - if (current) { - roomHistory.unshift(current); - } - return roomHistory; - }, -); diff --git a/src/selectors/searchSelectors.js b/src/selectors/searchSelectors.js deleted file mode 100644 index 529c46023..000000000 --- a/src/selectors/searchSelectors.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -import { createSelector } from 'reselect'; - -const baseSearchSelector = (state) => state.mediaSearch; - -export const showSearchResultsSelector = createSelector( - baseSearchSelector, - (search) => !!search.showResults, -); diff --git a/src/selectors/serverSelectors.js b/src/selectors/serverSelectors.js index fd06ca7de..dd4c42998 100644 --- a/src/selectors/serverSelectors.js +++ b/src/selectors/serverSelectors.js @@ -1,5 +1,6 @@ import { createSelector } from 'reselect'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.server; // eslint-disable-next-line import/prefer-default-export diff --git a/src/selectors/settingSelectors.js b/src/selectors/settingSelectors.js index 2e5dc2671..864cdbd63 100644 --- a/src/selectors/settingSelectors.js +++ b/src/selectors/settingSelectors.js @@ -1,79 +1,16 @@ import { createSelector } from 'reselect'; -import { availableLanguages } from '../locales'; import createTheme from '../utils/createTheme'; -const availableLanguagesSelector = () => availableLanguages; - -function getAvailableLanguage(available, languages) { - return languages.find((lang) => ( - available.includes(lang) - )); -} - -const defaultLanguageSelector = createSelector( - availableLanguagesSelector, - (available) => { - if (typeof window === 'object' && window.navigator && window.navigator.languages) { - const browserLanguage = getAvailableLanguage(available, window.navigator.languages); - if (browserLanguage) { - return browserLanguage; - } - } - return 'en'; - }, -); - +/** @param {import('../redux/configureStore').StoreState} state */ const settingsBaseSelector = (state) => state.settings; export const themeSelector = createSelector( + /** @param {import('../redux/configureStore').StoreState} state */ (state) => state.theme, (base) => createTheme(base), ); -export const volumeSelector = createSelector( - settingsBaseSelector, - (settings) => settings.volume, -); - -export const isMutedSelector = createSelector( - settingsBaseSelector, - (settings) => settings.muted, -); - -export const languageSelector = createSelector( - settingsBaseSelector, - defaultLanguageSelector, - (settings, defaultLanguage) => settings.language ?? defaultLanguage, -); - -export const videoSizeSelector = createSelector( - settingsBaseSelector, - (settings) => settings.videoSize, -); - -export const videoEnabledSelector = createSelector( - settingsBaseSelector, - (settings) => settings.videoEnabled, -); - -// Settings with selected values (from selectors above) rather than "saved" -// values (from localStorage). -export const settingsSelector = createSelector( - settingsBaseSelector, - volumeSelector, - isMutedSelector, - videoSizeSelector, - languageSelector, - (base, volume, muted, videoSize, language) => ({ - ...base, - volume, - muted, - videoSize, - language, - }), -); - export const notificationSettingsSelector = createSelector( - settingsSelector, + settingsBaseSelector, (settings) => settings.notifications, ); diff --git a/src/selectors/timeSelectors.js b/src/selectors/timeSelectors.js index 9966facf3..16155b79a 100644 --- a/src/selectors/timeSelectors.js +++ b/src/selectors/timeSelectors.js @@ -1,11 +1,13 @@ import { createSelector } from 'reselect'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.time; const offsetSelector = createSelector(baseSelector, (time) => time.offset); export const timerSelector = createSelector(baseSelector, (time) => time.timer); // Do not use createSelector() to avoid memoization. +/** @param {import('../redux/configureStore').StoreState} state */ export const currentTimeSelector = (state) => { const time = Date.now(); const offset = offsetSelector(state); diff --git a/src/selectors/userSelectors.js b/src/selectors/userSelectors.js index c227ad370..17fe8e52f 100644 --- a/src/selectors/userSelectors.js +++ b/src/selectors/userSelectors.js @@ -2,8 +2,10 @@ import { createSelector } from 'reselect'; import naturalCmp from 'natural-compare'; import { rolesSelector } from './configSelectors'; +/** @param {import('../redux/configureStore').StoreState} state */ const authSelector = (state) => state.auth; +/** @param {import('../redux/configureStore').StoreState} state */ const usersBaseSelector = (state) => state.users; export const usersSelector = createSelector(usersBaseSelector, (base) => base.users); @@ -11,11 +13,12 @@ const currentUserIDSelector = createSelector(authSelector, (auth) => auth.user); export const currentUserSelector = createSelector( usersSelector, currentUserIDSelector, - (users, userID) => ( - userID in users - ? users[userID] - : null - ), + (users, userID) => { + if (userID && userID in users) { + return users[userID]; + } + return null; + }, ); export const isLoggedInSelector = createSelector(currentUserSelector, Boolean); export const tokenSelector = createSelector(authSelector, (auth) => auth.token); diff --git a/src/selectors/voteSelectors.js b/src/selectors/voteSelectors.js index 771fd6d81..dd9de61cb 100644 --- a/src/selectors/voteSelectors.js +++ b/src/selectors/voteSelectors.js @@ -1,9 +1,9 @@ import { createSelector, createStructuredSelector } from 'reselect'; import { currentUserSelector } from './userSelectors'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.votes; -const createPropSelector = (base, prop) => createSelector(base, (obj) => obj[prop]); const createIsSelector = (type) => createSelector( type, currentUserSelector, @@ -14,9 +14,9 @@ const createCountSelector = (type) => createSelector( (array) => array.length, ); -export const favoritesSelector = createPropSelector(baseSelector, 'favorites'); -export const upvotesSelector = createPropSelector(baseSelector, 'upvotes'); -export const downvotesSelector = createPropSelector(baseSelector, 'downvotes'); +export const favoritesSelector = createSelector(baseSelector, (votes) => votes.favorites); +export const upvotesSelector = createSelector(baseSelector, (votes) => votes.upvotes); +export const downvotesSelector = createSelector(baseSelector, (votes) => votes.downvotes); export const currentVotesSelector = createStructuredSelector({ favorites: favoritesSelector, diff --git a/src/selectors/waitlistSelectors.js b/src/selectors/waitlistSelectors.js index a757e732d..99abc62ca 100644 --- a/src/selectors/waitlistSelectors.js +++ b/src/selectors/waitlistSelectors.js @@ -2,6 +2,7 @@ import { createSelector, createStructuredSelector } from 'reselect'; import { timeRemainingSelector, djSelector, isCurrentDJSelector } from './boothSelectors'; import { currentUserSelector, usersSelector } from './userSelectors'; +/** @param {import('../redux/configureStore').StoreState} state */ const baseSelector = (state) => state.waitlist; export const isLockedSelector = createSelector(baseSelector, (wl) => !!wl.locked); diff --git a/src/sources/soundcloud/Player.jsx b/src/sources/soundcloud/Player.jsx deleted file mode 100644 index f3ab09a8e..000000000 --- a/src/sources/soundcloud/Player.jsx +++ /dev/null @@ -1,210 +0,0 @@ -import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { translate } from '@u-wave/react-translate'; -import Paper from '@mui/material/Paper'; -import Button from '@mui/material/Button'; -import Typography from '@mui/material/Typography'; -import { mdiAlertCircle } from '@mdi/js'; -import SvgIcon from '../../components/SvgIcon'; -import SongInfo from './SongInfo'; - -const soundcloudLogo = new URL('../../../assets/img/soundcloud-inline.png', import.meta.url); - -const CLIENT_ID = '9d883cdd4c3c54c6dddda2a5b3a11200'; - -function getErrorMessage(err) { - if (err.name === 'MediaError') { - if (err.code === 2) { - return 'soundcloud.error.network'; - } - if (err.code === 3) { - return 'soundcloud.error.decode'; - } - if (err.code === 4 && /404|not found/i.test(err.message)) { - return 'soundcloud.error.notFound'; - } - } - return 'soundcloud.error.other'; -} - -const enhance = translate(); - -class SoundCloudPlayer extends React.Component { - static propTypes = { - t: PropTypes.func.isRequired, - className: PropTypes.string, - active: PropTypes.bool.isRequired, - enabled: PropTypes.bool, - media: PropTypes.object, - seek: PropTypes.number, - volume: PropTypes.number, - onPlay: PropTypes.func, - }; - - constructor(props) { - super(props); - - this.state = { - error: null, - needsTap: false, - }; - } - - componentDidMount() { - this.audio = new Audio(); - this.audio.addEventListener('error', () => { - this.handleError(this.audio.error); - }); - this.audio.autoplay = true; - this.play(); - } - - componentDidUpdate(prevProps) { - const { - volume, active, enabled, media, - } = this.props; - - if (prevProps.volume !== volume) { - this.audio.volume = volume / 100; - } - if (prevProps.media.sourceID !== media.sourceID - || prevProps.enabled !== enabled - || prevProps.active !== active) { - if (enabled && active) { - this.play(); - } else { - this.stop(); - } - } - } - - componentWillUnmount() { - this.stop(); - } - - handleError = (error) => { - this.setState({ - error, - needsTap: error.name === 'NotAllowedError', - }); - }; - - handlePlay = () => { - this.play(); - }; - - play() { - const { - active, enabled, media, volume, seek, onPlay, - } = this.props; - - this.setState({ needsTap: false, error: null }); - if (enabled && active) { - // In Firefox we have to wait for the "canplaythrough" event before - // seeking. - // http://stackoverflow.com/a/34970444 - const doSeek = () => { - this.audio.currentTime = seek + (media.start ?? 0); - this.audio.volume = volume / 100; - this.audio.removeEventListener('canplaythrough', doSeek, false); - }; - - const { streamUrl } = media.sourceData; - this.audio.src = `${streamUrl}?client_id=${CLIENT_ID}`; - const res = this.audio.play(); - if (res && res.then) res.catch(this.handleError); - this.audio.addEventListener('canplaythrough', doSeek, false); - if (onPlay) { - this.audio.addEventListener('play', onPlay, false); - } - } else { - this.stop(); - } - } - - stop() { - this.setState({ error: null }); - this.audio.pause(); - } - - render() { - const { active } = this.props; - if (!active) { - return null; - } - - const { t, media, className } = this.props; - const { error, needsTap } = this.state; - const { sourceData } = media; - if (!sourceData) { - return <div className={cx('src-soundcloud-Player', className)} />; - } - - if (needsTap) { - return ( - <div className={cx('src-soundcloud-Player', className)}> - <Paper className="src-soundcloud-Player-message"> - <Typography component="p" paragraph> - {t('booth.autoplayBlocked')} - </Typography> - <Button variant="contained" onClick={this.handlePlay}> - {t('booth.play')} - </Button> - </Paper> - </div> - ); - } - - if (error) { - return ( - <div className={cx('src-soundcloud-Player', className)}> - <Paper className="src-soundcloud-Player-error"> - <SvgIcon path={mdiAlertCircle} className="src-soundcloud-Player-errorIcon" /> - <Typography component="p"> - {t('soundcloud.error.template', { - error: t(getErrorMessage(error), { message: error.message }), - })} - </Typography> - </Paper> - </div> - ); - } - - return ( - <div className={cx('src-soundcloud-Player', className)}> - <div className="src-soundcloud-Player-meta"> - <div className="src-soundcloud-Player-info"> - <img - className="src-soundcloud-Player-art" - src={media.thumbnail} - alt="" - /> - <div className="src-soundcloud-Player-links"> - <SongInfo - artist={sourceData.username} - title={sourceData.fullTitle} - artistUrl={sourceData.artistUrl} - trackUrl={sourceData.permalinkUrl} - /> - </div> - </div> - <a - href={sourceData.permalinkUrl} - target="_blank" - rel="noopener noreferrer" - className="src-soundcloud-Player-permalink" - > - View on{' '} - <img - src={soundcloudLogo.href} - alt="SoundCloud" - /> - </a> - </div> - </div> - ); - } -} - -export default enhance(SoundCloudPlayer); diff --git a/src/sources/soundcloud/Player.tsx b/src/sources/soundcloud/Player.tsx new file mode 100644 index 000000000..a4225b3f0 --- /dev/null +++ b/src/sources/soundcloud/Player.tsx @@ -0,0 +1,202 @@ +import cx from 'clsx'; +import { + useEffect, + useMemo, + useRef, + useState, +} from 'react'; +import { useTranslator } from '@u-wave/react-translate'; +import Paper from '@mui/material/Paper'; +import Button from '@mui/material/Button'; +import Typography from '@mui/material/Typography'; +import { mdiAlertCircle } from '@mdi/js'; +import SvgIcon from '../../components/SvgIcon'; +import SongInfo from './SongInfo'; +import { Media } from '../../reducers/booth'; + +const soundcloudLogo = new URL('../../../assets/img/soundcloud-inline.png', import.meta.url); + +const CLIENT_ID = '9d883cdd4c3c54c6dddda2a5b3a11200'; + +function getErrorMessage(err: Error) { + if (err.name === 'MediaError') { + const { code } = err as MediaError & { name: 'MediaError' }; + if (code === 2) { + return 'soundcloud.error.network'; + } + if (code === 3) { + return 'soundcloud.error.decode'; + } + if (code === 4 && /404|not found/i.test(err.message)) { + return 'soundcloud.error.notFound'; + } + } + return 'soundcloud.error.other'; +} + +type SoundCloudPlayerProps = { + className?: string, + active: boolean, + enabled: boolean, + media: Media, + seek: number, + volume: number, + onPlay?: () => void, +}; +function SoundCloudPlayer({ + className, + active, + enabled, + media, + seek, + volume, + onPlay, +}: SoundCloudPlayerProps) { + const { t } = useTranslator(); + const audioRef = useRef<HTMLAudioElement|null>(null); + const [error, setError] = useState<Error|null>(null); + const needsTap = error?.name === 'NotAllowedError'; + + const audioUrl = useMemo(() => { + if ('streamUrl' in media.sourceData && typeof media.sourceData.streamUrl === 'string' + && enabled && active) { + const { streamUrl } = media.sourceData; + return `${streamUrl}?client_id=${CLIENT_ID}`; + } + return null; + }, [media, enabled, active]); + + useEffect(() => { + const audio = new Audio(); + audioRef.current = audio; + audio.addEventListener('error', () => { + if (audio.error) { + setError(Object.assign(audio.error, { name: 'MediaError' })); + } else { + setError(new Error('Unknown error')); + } + }); + }, []); + + useEffect(() => { + setError(null); + if (!audioRef.current || !audioUrl) { + return () => { + // dummy + }; + } + const audio = audioRef.current; + audio.src = audioUrl; + audio.play().catch(setError); + const doSeek = () => { + audio.currentTime = seek + (media.start ?? 0); + audio.removeEventListener('canplaythrough', doSeek, false); + }; + audio.addEventListener('canplaythrough', doSeek, false); + + return () => { + audio.pause(); + audio.removeEventListener('canplaythrough', doSeek, false); + }; + + // `seek` / `media.start` should only be taken into account when + // the media changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [audioUrl]); + + useEffect(() => { + if (audioRef.current) { + audioRef.current.volume = volume / 100; + } + }, [volume]); + + useEffect(() => { + const handler = () => { + setError(null); + onPlay?.(); + }; + + const audio = audioRef.current; + if (audio) { + audio.addEventListener('play', handler, false); + } + return () => { + if (audio) { + audio.removeEventListener('play', handler); + } + }; + }, [onPlay]); + + const sourceData = media.sourceData as undefined | { + username: string, + fullTitle: string, + artistUrl: string, + permalinkUrl: string, + }; + if (!sourceData) { + return <div className={cx('src-soundcloud-Player', className)} />; + } + + if (needsTap) { + return ( + <div className={cx('src-soundcloud-Player', className)}> + <Paper className="src-soundcloud-Player-message"> + <Typography component="p" paragraph> + {t('booth.autoplayBlocked')} + </Typography> + <Button variant="contained" onClick={() => audioRef.current?.play()}> + {t('booth.play')} + </Button> + </Paper> + </div> + ); + } + + if (error) { + return ( + <div className={cx('src-soundcloud-Player', className)}> + <Paper className="src-soundcloud-Player-error"> + <SvgIcon path={mdiAlertCircle} className="src-soundcloud-Player-errorIcon" /> + <Typography component="p"> + {t('soundcloud.error.template', { + error: t(getErrorMessage(error), { message: error.message }), + })} + </Typography> + </Paper> + </div> + ); + } + + return ( + <div className={cx('src-soundcloud-Player', className)}> + <div className="src-soundcloud-Player-meta"> + <div className="src-soundcloud-Player-info"> + <img + className="src-soundcloud-Player-art" + src={media.thumbnail} + alt="" + /> + <div className="src-soundcloud-Player-links"> + <SongInfo + artist={sourceData.username} + title={sourceData.fullTitle} + artistUrl={sourceData.artistUrl} + trackUrl={sourceData.permalinkUrl} + /> + </div> + </div> + <a + href={sourceData.permalinkUrl} + target="_blank" + rel="noopener noreferrer" + className="src-soundcloud-Player-permalink" + > + View on{' '} + <img src={soundcloudLogo.href} alt="SoundCloud" /> + </a> + </div> + </div> + ); +} + +export default SoundCloudPlayer; diff --git a/src/sources/soundcloud/PlayerWrapper.jsx b/src/sources/soundcloud/PlayerWrapper.jsx deleted file mode 100644 index 2e130f999..000000000 --- a/src/sources/soundcloud/PlayerWrapper.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Player from './Player'; -import PreviewPlayer from './PreviewPlayer'; - -const PlayerWrapper = ({ mode, ...props }) => { - if (mode === 'preview') { - return <PreviewPlayer {...props} />; - } - return <Player {...props} mode={mode} />; -}; - -PlayerWrapper.propTypes = { - mode: PropTypes.string.isRequired, -}; - -export default PlayerWrapper; diff --git a/src/sources/soundcloud/PlayerWrapper.tsx b/src/sources/soundcloud/PlayerWrapper.tsx new file mode 100644 index 000000000..874446aa5 --- /dev/null +++ b/src/sources/soundcloud/PlayerWrapper.tsx @@ -0,0 +1,14 @@ +import Player from './Player'; +import PreviewPlayer from './PreviewPlayer'; + +type PlayerWrapperProps = { + mode?: 'preview' | undefined, +} & React.ComponentProps<typeof Player>; +function PlayerWrapper({ mode, ...props }: PlayerWrapperProps) { + if (mode === 'preview') { + return <PreviewPlayer {...props} />; + } + return <Player {...props} />; +} + +export default PlayerWrapper; diff --git a/src/sources/soundcloud/PreviewPlayer.jsx b/src/sources/soundcloud/PreviewPlayer.tsx similarity index 52% rename from src/sources/soundcloud/PreviewPlayer.jsx rename to src/sources/soundcloud/PreviewPlayer.tsx index 6b6d3642f..adbb2424f 100644 --- a/src/sources/soundcloud/PreviewPlayer.jsx +++ b/src/sources/soundcloud/PreviewPlayer.tsx @@ -1,8 +1,6 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import qsStringify from 'qs-stringify'; -const createEmbedUrl = (sourceID) => ( +const createEmbedUrl = (sourceID: string) => ( `https://w.soundcloud.com/player/?${qsStringify({ url: `https://api.soundcloud.com/tracks/${sourceID}`, color: '55B9FF', @@ -17,19 +15,20 @@ const createEmbedUrl = (sourceID) => ( })} ` ); -const PreviewPlayer = ({ media }) => ( - <iframe - title="SoundCloud Embed" - width="640" - height="360" - scrolling="no" - frameBorder="no" - src={createEmbedUrl(media.sourceID)} - /> -); - -PreviewPlayer.propTypes = { - media: PropTypes.object.isRequired, +type PreviewPlayerProps = { + media: { sourceID: string }, }; +function PreviewPlayer({ media }: PreviewPlayerProps) { + return ( + <iframe + title="SoundCloud Embed" + width="640" + height="360" + scrolling="no" + frameBorder="no" + src={createEmbedUrl(media.sourceID)} + /> + ); +} export default PreviewPlayer; diff --git a/src/sources/soundcloud/SongInfo.jsx b/src/sources/soundcloud/SongInfo.tsx similarity index 81% rename from src/sources/soundcloud/SongInfo.jsx rename to src/sources/soundcloud/SongInfo.tsx index f02960fa5..1042390ec 100644 --- a/src/sources/soundcloud/SongInfo.jsx +++ b/src/sources/soundcloud/SongInfo.tsx @@ -1,11 +1,19 @@ -import React from 'react'; -import PropTypes from 'prop-types'; import { mdiHeadphones, mdiMusicNote } from '@mdi/js'; import SvgIcon from '../../components/SvgIcon'; +type SongInfoProps = { + /** The uploader name on SoundCloud. */ + artist: string, + /** The title of the media on SoundCloud. */ + title: string, + /** Full URL to the artist's SoundCloud page. */ + artistUrl: string, + /** Full URL to the track page. */ + trackUrl: string, +}; function SongInfo({ artist, title, artistUrl, trackUrl, -}) { +}: SongInfoProps) { return ( <div className="src-soundcloud-SongInfo"> <a @@ -32,15 +40,4 @@ function SongInfo({ ); } -SongInfo.propTypes = { - /** The uploader name on SoundCloud. */ - artist: PropTypes.string.isRequired, - /** The title of the media on SoundCloud. */ - title: PropTypes.string.isRequired, - /** Full URL to the artist's SoundCloud page. */ - artistUrl: PropTypes.string.isRequired, - /** Full URL to the track page. */ - trackUrl: PropTypes.string.isRequired, -}; - export default SongInfo; diff --git a/src/sources/soundcloud/index.js b/src/sources/soundcloud/index.ts similarity index 69% rename from src/sources/soundcloud/index.js rename to src/sources/soundcloud/index.ts index be9319327..0a3186bd7 100644 --- a/src/sources/soundcloud/index.js +++ b/src/sources/soundcloud/index.ts @@ -1,9 +1,10 @@ +import { MediaSource } from '../../context/MediaSourceContext'; import Player from './PlayerWrapper'; const logo = new URL('../../../assets/img/soundcloud.png', import.meta.url); const icon = new URL('../../../assets/img/soundcloud.png', import.meta.url); -export default function soundcloud() { +export default function soundcloud(): MediaSource { return { name: 'soundcloud', Player, diff --git a/src/sources/youtube/ChannelPanel.jsx b/src/sources/youtube/ChannelPanel.tsx similarity index 59% rename from src/sources/youtube/ChannelPanel.jsx rename to src/sources/youtube/ChannelPanel.tsx index ba30b9a3c..5fd49d8e7 100644 --- a/src/sources/youtube/ChannelPanel.jsx +++ b/src/sources/youtube/ChannelPanel.tsx @@ -1,42 +1,55 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; +import useSWRImmutable from 'swr/immutable'; +import { useRef } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; import ImportPanelHeader from '../../components/PlaylistManager/Import/ImportPanelHeader'; -import PlaylistRow from './PlaylistRow'; - -const { - useRef, -} = React; +import PlaylistRow, { YouTubePlaylist } from './PlaylistRow'; +import uwFetch from '../../utils/fetch'; function estimateSize() { return 56; } +type ChannelPanelProps = { + url: string, + onImportPlaylist: (sourceID: string, name: string) => void, + onClosePanel: () => void, +}; function ChannelPanel({ - importingChannelTitle, - importablePlaylists, + url, onImportPlaylist, onClosePanel, -}) { - const parentRef = useRef(); +}: ChannelPanelProps) { + const { data } = useSWRImmutable<{ + channel: { id: string, title: string }, + playlists: YouTubePlaylist[], + }>( + ['/import/youtube/channel', { qs: { url } }], + uwFetch, + { suspense: true }, + ); + const parentRef = useRef<HTMLDivElement>(null); const virtualizer = useVirtualizer({ - count: importablePlaylists.length, + count: data?.playlists.length ?? 0, getScrollElement: () => parentRef.current, estimateSize, overscan: 6, }); + if (!data) { + return null; + } + return ( <div className="ImportPanel ChannelPanel"> <ImportPanelHeader onClosePanel={onClosePanel}> - {`${importingChannelTitle}'s Playlists`} + {`${data.channel.title}'s Playlists`} </ImportPanelHeader> - <div className="MediaList ImportPanel-body"> + <div className="MediaList ImportPanel-body" ref={parentRef}> <div style={{ height: `${virtualizer.getTotalSize()}px`, width: '100%', position: 'relative' }}> {virtualizer.getVirtualItems().map(({ index, start }) => { - const playlist = importablePlaylists[index]; + const playlist = data.playlists[index]!; const style = { transform: `translateY(${start}px)` }; return ( <PlaylistRow @@ -54,11 +67,4 @@ function ChannelPanel({ ); } -ChannelPanel.propTypes = { - importingChannelTitle: PropTypes.string.isRequired, - importablePlaylists: PropTypes.arrayOf(PropTypes.object).isRequired, - onImportPlaylist: PropTypes.func.isRequired, - onClosePanel: PropTypes.func.isRequired, -}; - export default ChannelPanel; diff --git a/src/sources/youtube/ImportForm.jsx b/src/sources/youtube/ImportForm.tsx similarity index 61% rename from src/sources/youtube/ImportForm.jsx rename to src/sources/youtube/ImportForm.tsx index 5e159d96c..0e4eda8d4 100644 --- a/src/sources/youtube/ImportForm.jsx +++ b/src/sources/youtube/ImportForm.tsx @@ -1,50 +1,44 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useDispatch } from 'react-redux'; +import { useRef, useTransition } from 'react'; import { useTranslator } from '@u-wave/react-translate'; import { mdiPlaylistPlay } from '@mdi/js'; +import { useDispatch } from '../../hooks/useRedux'; import ImportSourceBlock from '../../components/PlaylistManager/Import/ImportSourceBlock'; import Form from '../../components/Form'; import FormGroup from '../../components/Form/Group'; import TextField from '../../components/Form/TextField'; import Button from '../../components/Form/Button'; import SvgIcon from '../../components/SvgIcon'; -import { - getChannelPlaylists, - getImportablePlaylist, -} from './actions'; - -const { - useRef, -} = React; +import { importFromChannel, importFromPlaylist } from './reducer'; +type YoutubeImportFormProps = { + onShowImportPanel: () => void, +} function YoutubeImportForm({ - onHideImportPanel, onShowImportPanel, -}) { +}: YoutubeImportFormProps) { const { t } = useTranslator(); const dispatch = useDispatch(); + const [isPending, startTransition] = useTransition(); - const refChannel = useRef(null); - const refPlaylist = useRef(null); + const refChannel = useRef<HTMLInputElement>(null); + const refPlaylist = useRef<HTMLInputElement>(null); - const handleImportChannel = (event) => { + const handleImportChannel = (event: React.FormEvent) => { event.preventDefault(); - const url = refChannel.current.value; - dispatch(getChannelPlaylists(url)).catch(() => { - onHideImportPanel(); + const url = refChannel.current!.value; + startTransition(() => { + dispatch(importFromChannel({ url })); + onShowImportPanel(); }); - onShowImportPanel(); }; - const handleImportPlaylist = (event) => { + const handleImportPlaylist = (event: React.FormEvent) => { event.preventDefault(); - const url = refPlaylist.current.value; - - dispatch(getImportablePlaylist(url)).catch(() => { - onHideImportPanel(); + const url = refPlaylist.current!.value; + startTransition(() => { + dispatch(importFromPlaylist({ url })); + onShowImportPanel(); }); - onShowImportPanel(); }; return ( @@ -61,7 +55,9 @@ function YoutubeImportForm({ /> </FormGroup> <FormGroup> - <Button>{t('youtube.importChannel')}</Button> + <Button> + {isPending ? '...' : t('youtube.importChannel')} + </Button> </FormGroup> </Form> <Form onSubmit={handleImportPlaylist}> @@ -80,9 +76,4 @@ function YoutubeImportForm({ ); } -YoutubeImportForm.propTypes = { - onShowImportPanel: PropTypes.func.isRequired, - onHideImportPanel: PropTypes.func.isRequired, -}; - export default YoutubeImportForm; diff --git a/src/sources/youtube/ImportPanel.jsx b/src/sources/youtube/ImportPanel.jsx deleted file mode 100644 index b1c8f968a..000000000 --- a/src/sources/youtube/ImportPanel.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; -import { IDLE, LOADING, LOADED } from '../../constants/LoadingStates'; -import { addMediaMenu as openAddMediaMenu } from '../../actions/PlaylistActionCreators'; -import LoadingPanel from '../../components/PlaylistManager/Import/LoadingPanel'; -import { PLAYLIST, CHANNEL } from './constants'; -import { importPlaylist } from './actions'; -import ChannelPanel from './ChannelPanel'; -import PlaylistPanel from './PlaylistPanel'; - -const mapStateToProps = () => ({}); -const mapDispatchToProps = (dispatch) => bindActionCreators({ - onImportPlaylist: importPlaylist, - onOpenAddMediaMenu: openAddMediaMenu, -}, dispatch); - -const YouTubeImportPanel = ({ type, importingState, ...props }) => { - if (importingState === LOADED) { - if (type === PLAYLIST) { - return <PlaylistPanel {...props} />; - } - return <ChannelPanel {...props} />; - } - return <LoadingPanel {...props} />; -}; - -YouTubeImportPanel.propTypes = { - type: PropTypes.oneOf([PLAYLIST, CHANNEL]).isRequired, - importingState: PropTypes.oneOf([IDLE, LOADING, LOADED]), -}; - -export default connect(mapStateToProps, mapDispatchToProps)(YouTubeImportPanel); diff --git a/src/sources/youtube/ImportPanel.tsx b/src/sources/youtube/ImportPanel.tsx new file mode 100644 index 000000000..5b3ed3c15 --- /dev/null +++ b/src/sources/youtube/ImportPanel.tsx @@ -0,0 +1,27 @@ +import { useCallback } from 'react'; +import { useDispatch } from '../../hooks/useRedux'; +import { importPlaylist, type State } from './reducer'; +import ChannelPanel from './ChannelPanel'; +import PlaylistPanel from './PlaylistPanel'; +import LoadingPanel from './LoadingPanel'; + +type YouTubeImportPanelProps = State & { + onClosePanel: () => void, +}; +function YouTubeImportPanel(props: YouTubeImportPanelProps) { + const dispatch = useDispatch(); + const onImportPlaylist = useCallback((sourceID: string, name: string) => { + return dispatch(importPlaylist({ sourceID, name })); + }, [dispatch]); + + const { type } = props; + if (type === 'playlist') { + return <PlaylistPanel {...props} onImportPlaylist={onImportPlaylist} />; + } + if (type === 'channel') { + return <ChannelPanel {...props} onImportPlaylist={onImportPlaylist} />; + } + return <LoadingPanel {...props} />; +} + +export default YouTubeImportPanel; diff --git a/src/sources/youtube/ImportRow.jsx b/src/sources/youtube/ImportRow.tsx similarity index 78% rename from src/sources/youtube/ImportRow.jsx rename to src/sources/youtube/ImportRow.tsx index 430e92b00..c8d05fda1 100644 --- a/src/sources/youtube/ImportRow.jsx +++ b/src/sources/youtube/ImportRow.tsx @@ -1,6 +1,4 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import { SEARCH_RESULT } from '../../constants/DDItemTypes'; import MediaRowBase from '../../components/MediaList/MediaRowBase'; import MediaDuration from '../../components/MediaList/MediaDuration'; @@ -8,12 +6,31 @@ import MediaThumbnail from '../../components/MediaList/MediaThumbnail'; import AddToPlaylistAction from '../../components/MediaList/AddToPlaylistAction'; import PreviewMediaAction from '../../components/MediaList/PreviewMediaAction'; +export interface YouTubeMedia { + _id: string; + sourceType: 'youtube'; + sourceID: string; + sourceData: Record<never, never>, + artist: string; + title: string; + duration: number; + start: number; + end: number; + thumbnail: string; +} + +type ImportRowProps = { + className?: string, + style?: React.CSSProperties, + media: YouTubeMedia, + onClick: () => void, +}; function ImportRow({ className, media, style, onClick, -}) { +}: ImportRowProps) { return ( <MediaRowBase media={media} @@ -42,11 +59,4 @@ function ImportRow({ ); } -ImportRow.propTypes = { - className: PropTypes.string, - style: PropTypes.object, // from virtual list positioning - media: PropTypes.object, - onClick: PropTypes.func, -}; - export default ImportRow; diff --git a/src/sources/youtube/Player.jsx b/src/sources/youtube/Player.tsx similarity index 54% rename from src/sources/youtube/Player.jsx rename to src/sources/youtube/Player.tsx index d962bbcb7..5f620fca7 100644 --- a/src/sources/youtube/Player.jsx +++ b/src/sources/youtube/Player.tsx @@ -1,11 +1,20 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import YouTube from '@u-wave/react-youtube'; +import { useCallback } from 'react'; +import { Media } from '../../reducers/booth'; -const { useCallback } = React; +type YouTubePlayerProps = { + active: boolean, + className?: string, + enabled: boolean, + mode?: 'preview' | undefined, + media: Media | null, + seek: number, + volume: number, + onPlay?: () => void, +}; -const YouTubePlayer = ({ +function YouTubePlayer({ active, className, enabled, @@ -14,29 +23,28 @@ const YouTubePlayer = ({ seek, volume, onPlay, -}) => { - const modeClass = `src-youtube-Player--${mode}`; +}: YouTubePlayerProps) { const controllable = mode === 'preview'; - const handlePause = useCallback((event) => { + const handlePause = useCallback((event: YT.OnStateChangeEvent) => { if (active && !controllable) { event.target.playVideo(); } }, [active, controllable]); return ( - <div className={cx('src-youtube-Player', modeClass, className)} hidden={!active}> - {enabled && ( + <div className={cx('src-youtube-Player', mode && `src-youtube-Player--${mode}`, className)} hidden={!active}> + {enabled && media && ( <YouTube - video={active ? media.sourceID : null} + video={active ? media.sourceID : undefined} width="100%" height="100%" autoplay modestBranding - disableKeyboard volume={volume / 100} playbackRate={1} controls={controllable} + disableKeyboard={!controllable} showRelatedVideos={false} annotations={false} startSeconds={Math.round(seek + (media.start ?? 0))} @@ -47,17 +55,6 @@ const YouTubePlayer = ({ )} </div> ); -}; - -YouTubePlayer.propTypes = { - className: PropTypes.string, - mode: PropTypes.oneOf(['small', 'large', 'preview']), - active: PropTypes.bool.isRequired, - enabled: PropTypes.bool, - media: PropTypes.object, - seek: PropTypes.number, - volume: PropTypes.number, - onPlay: PropTypes.func, -}; +} export default YouTubePlayer; diff --git a/src/sources/youtube/PlaylistPanel.jsx b/src/sources/youtube/PlaylistPanel.tsx similarity index 59% rename from src/sources/youtube/PlaylistPanel.jsx rename to src/sources/youtube/PlaylistPanel.tsx index 916c9b01c..8e7e7a43a 100644 --- a/src/sources/youtube/PlaylistPanel.jsx +++ b/src/sources/youtube/PlaylistPanel.tsx @@ -1,21 +1,38 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import useSWRImmutable from 'swr/immutable'; import Tooltip from '@mui/material/Tooltip'; import IconButton from '@mui/material/IconButton'; import { mdiPlaylistPlus } from '@mdi/js'; import SvgIcon from '../../components/SvgIcon'; import MediaListBase from '../../components/MediaList/BaseMediaList'; import ImportPanelHeader from '../../components/PlaylistManager/Import/ImportPanelHeader'; -import ImportRow from './ImportRow'; +import ImportRow, { YouTubeMedia } from './ImportRow'; +import uwFetch from '../../utils/fetch'; +type YouTubeImportPlaylistPanelProps = { + url: string, + onImportPlaylist: (sourceID: string, name: string) => void, + onClosePanel: () => void, +}; function YouTubeImportPlaylistPanel({ - importingPlaylist, - importingPlaylistItems, + url, onImportPlaylist, onClosePanel, -}) { +}: YouTubeImportPlaylistPanelProps) { + const { data } = useSWRImmutable<{ + playlist: { sourceID: string, name: string }, + items: YouTubeMedia[], + }>( + ['/import/youtube/playlist', { qs: { url } }], + uwFetch, + { suspense: true }, + ); + + if (!data) { + return null; + } + const handleImportFull = () => ( - onImportPlaylist(importingPlaylist.sourceID, importingPlaylist.name) + onImportPlaylist(data.playlist.sourceID, data.playlist.name) ); return ( @@ -23,9 +40,9 @@ function YouTubeImportPlaylistPanel({ <ImportPanelHeader onClosePanel={onClosePanel}> <div className="src-youtube-PlaylistPanel-header"> <div className="src-youtube-PlaylistPanel-name"> - {importingPlaylist.name} + {data.playlist.name} </div> - <Tooltip title={`Import All (${importingPlaylistItems.length})`} placement="top"> + <Tooltip title={`Import All (${data.items.length})`} placement="top"> <IconButton onClick={handleImportFull}> <SvgIcon path={mdiPlaylistPlus} className="src-youtube-PlaylistPanel-importIcon" /> </IconButton> @@ -34,7 +51,7 @@ function YouTubeImportPlaylistPanel({ </ImportPanelHeader> <MediaListBase className="ImportPanel-body" - media={importingPlaylistItems} + media={data.items} listComponent="div" rowComponent={ImportRow} /> @@ -42,14 +59,4 @@ function YouTubeImportPlaylistPanel({ ); } -YouTubeImportPlaylistPanel.propTypes = { - importingPlaylist: PropTypes.shape({ - sourceID: PropTypes.string, - name: PropTypes.string, - }).isRequired, - importingPlaylistItems: PropTypes.arrayOf(PropTypes.object).isRequired, - onImportPlaylist: PropTypes.func.isRequired, - onClosePanel: PropTypes.func.isRequired, -}; - export default YouTubeImportPlaylistPanel; diff --git a/src/sources/youtube/PlaylistRow.jsx b/src/sources/youtube/PlaylistRow.tsx similarity index 67% rename from src/sources/youtube/PlaylistRow.jsx rename to src/sources/youtube/PlaylistRow.tsx index fd61e419a..bfd099a57 100644 --- a/src/sources/youtube/PlaylistRow.jsx +++ b/src/sources/youtube/PlaylistRow.tsx @@ -1,22 +1,34 @@ import cx from 'clsx'; -import React from 'react'; -import PropTypes from 'prop-types'; import IconButton from '@mui/material/IconButton'; import { mdiPlaylistPlus } from '@mdi/js'; import SvgIcon from '../../components/SvgIcon'; -const PlaylistRow = ({ +export interface YouTubePlaylist { + sourceID: string; + name: string; + description: string; + size: number; + thumbnail: string; +} + +type PlaylistRowProps = { + className?: string, + style?: React.CSSProperties, + playlist: YouTubePlaylist, + onImport: () => void, +} +function PlaylistRow({ className, + style, playlist, onImport, // etc - ...attrs -}) => { +}: PlaylistRowProps) { const thumbnail = ( <div className="MediaListRow-thumb"> <img className="MediaListRow-image" - key={playlist.id} + key={playlist.sourceID} src={playlist.thumbnail} loading="lazy" alt="" @@ -25,10 +37,7 @@ const PlaylistRow = ({ ); return ( - <div - className={cx('MediaListRow', 'src-youtube-PlaylistRow', className)} - {...attrs} - > + <div className={cx('MediaListRow', 'src-youtube-PlaylistRow', className)} style={style}> {thumbnail} <div className="src-youtube-PlaylistRow-info" title={playlist.description}> <div className="src-youtube-PlaylistRow-name"> @@ -43,12 +52,6 @@ const PlaylistRow = ({ </IconButton> </div> ); -}; - -PlaylistRow.propTypes = { - className: PropTypes.string, - playlist: PropTypes.object.isRequired, - onImport: PropTypes.func.isRequired, -}; +} export default PlaylistRow; diff --git a/src/sources/youtube/actions.js b/src/sources/youtube/actions.js deleted file mode 100644 index bd0f13b47..000000000 --- a/src/sources/youtube/actions.js +++ /dev/null @@ -1,108 +0,0 @@ -import { get, post } from '../../actions/RequestActionCreators'; - -import { - createPlaylistStart, - createPlaylistComplete, -} from '../../actions/PlaylistActionCreators'; - -import { - GET_IMPORTABLE_PLAYLIST_START, - GET_IMPORTABLE_PLAYLIST_COMPLETE, - GET_CHANNEL_PLAYLISTS_START, - GET_CHANNEL_PLAYLISTS_COMPLETE, - IMPORT_PLAYLIST_START, - IMPORT_PLAYLIST_COMPLETE, -} from './constants'; - -function getImportablePlaylistStart(url) { - return { - type: GET_IMPORTABLE_PLAYLIST_START, - payload: { url }, - }; -} - -function getImportablePlaylistComplete(url, playlist, items) { - return { - type: GET_IMPORTABLE_PLAYLIST_COMPLETE, - payload: { url, playlist, items }, - }; -} - -export function getImportablePlaylist(url) { - return get('/import/youtube/playlist', { - qs: { url }, - onStart: () => getImportablePlaylistStart(url), - onComplete: ({ playlist, items }) => getImportablePlaylistComplete(url, playlist, items), - onError: (error) => ({ - type: GET_IMPORTABLE_PLAYLIST_COMPLETE, - error: true, - payload: error, - meta: { url }, - }), - }); -} - -function importPlaylistStart(id, name) { - return (dispatch) => { - dispatch(createPlaylistStart({ name }, `yt:${id}`)); - dispatch({ - type: IMPORT_PLAYLIST_START, - payload: { id, name }, - }); - }; -} - -function importPlaylistComplete(id, playlist) { - return (dispatch) => { - dispatch({ - type: IMPORT_PLAYLIST_COMPLETE, - payload: { playlist }, - meta: { id }, - }); - dispatch(createPlaylistComplete(playlist, `yt:${id}`)); - }; -} - -export function importPlaylist(id, name) { - return post('/import/youtube/importplaylist', { id, name }, { - onStart: () => importPlaylistStart(id, name), - onComplete: (playlist) => importPlaylistComplete(id, playlist), - onError: (error) => ({ - type: IMPORT_PLAYLIST_COMPLETE, - error: true, - payload: error, - meta: { id }, - }), - }); -} - -function getChannelPlaylistsStart(url) { - return { - type: GET_CHANNEL_PLAYLISTS_START, - payload: { url }, - }; -} - -function getChannelPlaylistsComplete(channel, playlists) { - return { - type: GET_CHANNEL_PLAYLISTS_COMPLETE, - payload: { - channel, - playlists, - }, - }; -} - -export function getChannelPlaylists(url) { - return get('/import/youtube/channel', { - qs: { url }, - onStart: () => getChannelPlaylistsStart(url), - onComplete: ({ channel, playlists }) => getChannelPlaylistsComplete(channel, playlists), - onError: (error) => ({ - type: GET_CHANNEL_PLAYLISTS_COMPLETE, - error: true, - payload: error, - meta: { url }, - }), - }); -} diff --git a/src/sources/youtube/constants.js b/src/sources/youtube/constants.js deleted file mode 100644 index 635dad400..000000000 --- a/src/sources/youtube/constants.js +++ /dev/null @@ -1,11 +0,0 @@ -export const PLAYLIST = 'youtube/import/PLAYLIST'; -export const CHANNEL = 'youtube/import/CHANNEL'; - -export const GET_IMPORTABLE_PLAYLIST_START = 'youtube/import/GET_IMPORTABLE_PLAYLIST_START'; -export const GET_IMPORTABLE_PLAYLIST_COMPLETE = 'youtube/import/GET_IMPORTABLE_PLAYLIST_COMPLETE'; - -export const GET_CHANNEL_PLAYLISTS_START = 'youtube/import/GET_CHANNEL_PLAYLISTS_START'; -export const GET_CHANNEL_PLAYLISTS_COMPLETE = 'youtube/import/GET_CHANNEL_PLAYLISTS_COMPLETE'; - -export const IMPORT_PLAYLIST_START = 'youtube/import/IMPORT_PLAYLIST_START'; -export const IMPORT_PLAYLIST_COMPLETE = 'youtube/import/IMPORT_PLAYLIST_COMPLETE'; diff --git a/src/sources/youtube/index.js b/src/sources/youtube/index.ts similarity index 72% rename from src/sources/youtube/index.js rename to src/sources/youtube/index.ts index fe3500540..94dda901a 100644 --- a/src/sources/youtube/index.js +++ b/src/sources/youtube/index.ts @@ -1,13 +1,14 @@ import React from 'react'; import Player from './Player'; import ImportForm from './ImportForm'; -import reducer from './reducer'; +import reducer, { State } from './reducer'; +import { MediaSource } from '../../context/MediaSourceContext'; const ImportPanel = React.lazy(() => import('./ImportPanel')); const logo = new URL('../../../assets/img/youtube.png', import.meta.url); const icon = new URL('../../../assets/img/youtube-icon.png', import.meta.url); -export default function youtube() { +export default function youtube(): MediaSource<State> { return { name: 'youtube', Player, diff --git a/src/sources/youtube/reducer.js b/src/sources/youtube/reducer.js deleted file mode 100644 index b48c48312..000000000 --- a/src/sources/youtube/reducer.js +++ /dev/null @@ -1,69 +0,0 @@ -import { IDLE, LOADING, LOADED } from '../../constants/LoadingStates'; - -import { - PLAYLIST, - CHANNEL, - GET_IMPORTABLE_PLAYLIST_START, - GET_IMPORTABLE_PLAYLIST_COMPLETE, - GET_CHANNEL_PLAYLISTS_START, - GET_CHANNEL_PLAYLISTS_COMPLETE, -} from './constants'; - -const initialState = { - type: null, - importingState: IDLE, - importingPlaylistName: '', - importingPlaylistItems: [], - importingChannelTitle: '', - importablePlaylists: [], -}; - -export default function reduce(state = initialState, action = {}) { - const { type, error, payload } = action; - switch (type) { - case GET_IMPORTABLE_PLAYLIST_START: - return { - ...state, - type: PLAYLIST, - importingState: LOADING, - }; - case GET_IMPORTABLE_PLAYLIST_COMPLETE: - if (error) { - return { - ...state, - type: null, - importingState: IDLE, - }; - } - - return { - ...state, - importingState: LOADED, - importingPlaylist: payload.playlist, - importingPlaylistItems: payload.items, - }; - case GET_CHANNEL_PLAYLISTS_START: - return { - ...state, - type: CHANNEL, - importingState: LOADING, - }; - case GET_CHANNEL_PLAYLISTS_COMPLETE: - if (error) { - return { - ...state, - type: null, - importingState: IDLE, - }; - } - - return { - ...state, - importingState: LOADED, - importingChannelTitle: payload.channel.title, - importablePlaylists: payload.playlists, - }; - default: - return state; - } -} diff --git a/src/sources/youtube/reducer.ts b/src/sources/youtube/reducer.ts new file mode 100644 index 000000000..9af916b38 --- /dev/null +++ b/src/sources/youtube/reducer.ts @@ -0,0 +1,60 @@ +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; +import { createAsyncThunk } from '../../redux/api'; +import uwFetch from '../../utils/fetch'; +import { createPlaylist } from '../../reducers/playlists'; + +export type State = + | { type: null, url: null } + | { type: 'playlist', url: string } + | { type: 'channel', url: string } + +const initialState = { + type: null, + url: null, +} as State; + +const importPlaylist = createAsyncThunk('youtube/importPlaylist', async ( + { name, sourceID }: { name: string, sourceID: string }, + api, +) => { + api.dispatch(createPlaylist.pending(api.requestId, name)); + + const playlist = await uwFetch<{ + _id: string, + name: string, + size: number, + author: string, + createdAt: string, + updatedAt: string, + }>(['/import/youtube/importplaylist', { + method: 'post', + data: { id: sourceID, name }, + }]); + + api.dispatch(createPlaylist.fulfilled(playlist, api.requestId, name)); +}); + +const slice = createSlice({ + name: 'youtube', + initialState, + reducers: { + importFromChannel(_state, { payload }: PayloadAction<{ url: string }>) { + return { type: 'channel', url: payload.url }; + }, + importFromPlaylist(_state, { payload }: PayloadAction<{ url: string }>) { + return { type: 'playlist', url: payload.url }; + }, + reset() { + return initialState; + }, + }, +}); + +export const { + importFromChannel, + importFromPlaylist, + reset, +} = slice.actions; +export { importPlaylist }; + +export default slice.reducer; diff --git a/src/stores/MediaSearchStore.jsx b/src/stores/MediaSearchStore.jsx deleted file mode 100644 index 320a26bef..000000000 --- a/src/stores/MediaSearchStore.jsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; -import { useDispatch } from 'react-redux'; -import { useAsyncAbortable } from 'react-async-hook'; -import PropTypes from 'prop-types'; -import { get } from '../actions/RequestActionCreators'; -import { IDLE, LOADING, LOADED } from '../constants/LoadingStates'; - -const { - useCallback, - useContext, - useMemo, - useState, -} = React; - -const MediaSearchStoreContext = React.createContext(null); - -function useStoreImplementation() { - const [query, setQuery] = useState(null); - const [activeSource, setActiveSource] = useState('youtube'); - const dispatch = useDispatch(); - - const results = useAsyncAbortable(async (signal) => { - if (!query) { - return null; - } - - const request = get(`/search/${encodeURIComponent(activeSource)}`, { - qs: { query, include: 'playlists' }, - signal, - }); - - const { data } = await dispatch(request); - - return data; - }, [dispatch, query, activeSource]); - - const reset = useCallback(() => { - setQuery(null); - }, []); - - let state = IDLE; - if (results.loading) { - state = LOADING; - } else if (results.result) { - state = LOADED; - } - - const context = useMemo(() => ({ - activeSource, - query, - results: results.result, - resultsCount: results.result ? results.result.length : 0, - state, - - search: setQuery, - reset, - setSource: setActiveSource, - }), [activeSource, query, results, state, setQuery, reset, setActiveSource]); - - return context; -} - -export function MediaSearchStoreProvider({ children }) { - const context = useStoreImplementation(); - - return ( - <MediaSearchStoreContext.Provider value={context}> - {children} - </MediaSearchStoreContext.Provider> - ); -} - -MediaSearchStoreProvider.propTypes = { - children: PropTypes.element.isRequired, -}; - -export function useMediaSearchStore() { - return useContext(MediaSearchStoreContext); -} diff --git a/src/stores/MediaSearchStore.tsx b/src/stores/MediaSearchStore.tsx new file mode 100644 index 000000000..d05198c50 --- /dev/null +++ b/src/stores/MediaSearchStore.tsx @@ -0,0 +1,58 @@ +import React from 'react'; + +const { + useCallback, + useContext, + useMemo, + useState, +} = React; + +interface MediaSearchStore { + activeSource: string; + query: string | null; + search: (query: string | null) => void; + reset: () => void; + setSource: (source: string) => void; +} +const MediaSearchStoreContext = React.createContext<MediaSearchStore | null>(null); + +function useStoreImplementation() { + const [query, setQuery] = useState<string | null>(null); + const [activeSource, setActiveSource] = useState('youtube'); + + const reset = useCallback(() => { + setQuery(null); + }, []); + + const context = useMemo(() => ({ + activeSource, + query, + + search: setQuery, + reset, + setSource: setActiveSource, + }), [activeSource, query, setQuery, reset, setActiveSource]); + + return context; +} + +type MediaSearchStoreProviderProps = { + children: React.ReactNode, +}; +export function MediaSearchStoreProvider({ children }: MediaSearchStoreProviderProps) { + const context = useStoreImplementation(); + + return ( + <MediaSearchStoreContext.Provider value={context}> + {children} + </MediaSearchStoreContext.Provider> + ); +} + +export function useMediaSearchStore() { + const store = useContext(MediaSearchStoreContext); + if (!store) { + throw new Error('Cannot call `useMediaSearchStore` outside of a `MediaSearchStoreProvider`'); + } + return store; +} diff --git a/src/theme.js b/src/theme.js index ea1999478..a09ce2d50 100644 --- a/src/theme.js +++ b/src/theme.js @@ -1,3 +1,4 @@ +/** @type {import('@mui/material/styles').ThemeOptions} */ export default { palette: { mode: 'dark', diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 000000000..53cd91e8b --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1,49 @@ +declare module '*.ico' { + const url: string; + export default url; +} + +declare module '*.png' { + const url: string; + export default url; +} + +declare module '*.yaml' { + const data: object; + export default data; +} + +declare module '@u-wave/react-translate' { + import { Translator } from '@u-wave/translate'; + + export function useTranslator(): Translator; +} + +declare module 'item-selection/immutable' { + export interface ItemSelection<T> { + getIndices(): number[]; + get(): T[]; + set(selection: number[], lastIndex?: number): this; + isSelectedIndex(index: number): boolean; + isSelected(item: T): boolean; + clear(): this; + add(index: number): this; + remove(index: number): this; + select(index: number): this; + deselect(index: number): this; + selectRange(index: number, end?: number): this; + selectToggle(index: number): this; + selectAll(): this; + } + export default function itemSelection<T>(items: T[], selection?: number[]): ItemSelection<T>; +} + +declare module 'splitargs' { + function splitargs(input: string, sep?: RegExp, keepQuotes?: boolean): string[]; + export = splitargs; +} + +declare module 'flash-document-title' { + function flashDocumentTitle(input: string): void; + export = flashDocumentTitle; +} diff --git a/src/utils/chatMentions.js b/src/utils/chatMentions.js index 36bea9dce..218f8243c 100644 --- a/src/utils/chatMentions.js +++ b/src/utils/chatMentions.js @@ -19,7 +19,7 @@ export function getAvailableGroupMentions(canMention) { * Attach user objects to mentions in a parsed chat message. * * @param {Array} tree Parsed message. - * @param {{username: string}[]} state + * @param {import('../redux/configureStore').StoreState} state */ export function resolveMentions(tree, state) { const users = userListSelector(state); diff --git a/src/utils/commands/chat.js b/src/utils/commands/chat.js index 46fe1dfc2..a0af5f8c8 100644 --- a/src/utils/commands/chat.js +++ b/src/utils/commands/chat.js @@ -11,7 +11,7 @@ import { import { log, setMotd, -} from '../../actions/ChatActionCreators'; +} from '../../reducers/chat'; export default [ { diff --git a/src/utils/commands/playback.js b/src/utils/commands/playback.js index 4e7264424..00db450a1 100644 --- a/src/utils/commands/playback.js +++ b/src/utils/commands/playback.js @@ -1,7 +1,11 @@ import { log } from '../../actions/ChatActionCreators'; -import { setVolume, mute, unmute } from '../../actions/PlaybackActionCreators'; import { doUpvote, doDownvote } from '../../actions/VoteActionCreators'; -import { set as setSetting } from '../../actions/SettingsActionCreators'; +import { + setVolume, + mute, + unmute, + setVideoEnabled, +} from '../../reducers/settings'; export default [ { @@ -44,10 +48,10 @@ export default [ description: 'Enable or disable playback. Syntax: "/playback on|off"', action: (_commander, type) => { if (type.toLowerCase() === 'on') { - return setSetting('videoEnabled', true); + return setVideoEnabled(true); } if (type.toLowerCase() === 'off') { - return setSetting('videoEnabled', false); + return setVideoEnabled(false); } return log('Use "/playback on" to enable media playback or "/playback off" to disable it.'); }, diff --git a/src/utils/commands/staff.js b/src/utils/commands/staff.js index 77429afd5..ba0bc8ee1 100644 --- a/src/utils/commands/staff.js +++ b/src/utils/commands/staff.js @@ -10,7 +10,7 @@ import { addUserRole, removeUserRole, } from '../../actions/ModerationActionCreators'; -import { toggleAdmin } from '../../actions/OverlayActionCreators'; +import { toggleOverlay } from '../../reducers/activeOverlay'; export default [ { @@ -65,6 +65,6 @@ export default [ name: 'admin', description: 'Open the administration panel.', guard: isModeratorSelector, - action: () => toggleAdmin(), + action: () => toggleOverlay('admin'), }, ]; diff --git a/src/utils/commands/users.js b/src/utils/commands/users.js index cb40310ca..9e214ff96 100644 --- a/src/utils/commands/users.js +++ b/src/utils/commands/users.js @@ -1,5 +1,5 @@ import { log } from '../../actions/ChatActionCreators'; -import { doChangeUsername } from '../../actions/UserActionCreators'; +import { changeUsername } from '../../reducers/auth'; export default [{ name: 'nick', @@ -9,6 +9,6 @@ export default [{ return log('Username must be between 3 and 32 characters long.'); } - return doChangeUsername(name); + return changeUsername(name); }, }]; diff --git a/src/utils/emojiShortcodes.js b/src/utils/emojiShortcodes.js index 9b22956e5..ffa4ab5dd 100644 --- a/src/utils/emojiShortcodes.js +++ b/src/utils/emojiShortcodes.js @@ -1,3 +1,3 @@ // GENERATED FILE: run `npm run emoji` /* eslint-disable */ -export default JSON.parse("{\"100\":\"6d75617.svg\",\"1234\":\"cda85e0.svg\",\"interrobang\":\"d0e72da.svg\",\"tm\":\"e21e68e.svg\",\"information_source\":\"844715a.svg\",\"left_right_arrow\":\"db7e085.svg\",\"arrow_up_down\":\"e072740.svg\",\"arrow_upper_left\":\"8c36166.svg\",\"arrow_upper_right\":\"5896668.svg\",\"arrow_lower_right\":\"e62c0d5.svg\",\"arrow_lower_left\":\"b373a65.svg\",\"keyboard\":\"afe45d4.svg\",\"sunny\":\"2224ffe.svg\",\"cloud\":\"996d816.svg\",\"umbrella2\":\"0986801.svg\",\"snowman2\":\"4e0e6b2.svg\",\"comet\":\"5742565.svg\",\"ballot_box_with_check\":\"1537a20.svg\",\"umbrella\":\"109200a.svg\",\"coffee\":\"3282153.svg\",\"shamrock\":\"68199fe.svg\",\"skull_crossbones\":\"2002503.svg\",\"skull_and_crossbones\":\"2002503.svg\",\"radioactive\":\"830d87b.svg\",\"radioactive_sign\":\"830d87b.svg\",\"biohazard\":\"1c0e751.svg\",\"biohazard_sign\":\"1c0e751.svg\",\"orthodox_cross\":\"4085b9b.svg\",\"wheel_of_dharma\":\"5ce347e.svg\",\"frowning2\":\"6a2c624.svg\",\"white_frowning_face\":\"6a2c624.svg\",\"female_sign\":\"9a70128.svg\",\"male_sign\":\"efa6bcd.svg\",\"aries\":\"a5af609.svg\",\"taurus\":\"0dd7b96.svg\",\"sagittarius\":\"769343c.svg\",\"capricorn\":\"1a14a8a.svg\",\"aquarius\":\"cc39b15.svg\",\"pisces\":\"ed438b4.svg\",\"spades\":\"3caf82e.svg\",\"clubs\":\"980bdb6.svg\",\"hearts\":\"d3224df.svg\",\"diamonds\":\"04a5083.svg\",\"hotsprings\":\"12def1e.svg\",\"hammer_pick\":\"0be192d.svg\",\"hammer_and_pick\":\"0be192d.svg\",\"anchor\":\"e008be8.svg\",\"crossed_swords\":\"05e4179.svg\",\"medical_symbol\":\"0db03b9.svg\",\"scales\":\"8a658bd.svg\",\"alembic\":\"3979a70.svg\",\"gear\":\"be79bc3.svg\",\"scissors\":\"0095630.svg\",\"white_check_mark\":\"4d69c4a.svg\",\"airplane\":\"3c41f3a.svg\",\"envelope\":\"d45d0ae.svg\",\"black_nib\":\"e4a80ff.svg\",\"heavy_check_mark\":\"220f771.svg\",\"heavy_multiplication_x\":\"4cadfe2.svg\",\"star_of_david\":\"97817c8.svg\",\"sparkles\":\"43a4b5e.svg\",\"eight_spoked_asterisk\":\"3b40c2e.svg\",\"eight_pointed_black_star\":\"6298c15.svg\",\"snowflake\":\"0e29553.svg\",\"sparkle\":\"db70159.svg\",\"question\":\"0ace896.svg\",\"grey_question\":\"d89e98b.svg\",\"grey_exclamation\":\"54414a4.svg\",\"exclamation\":\"97d574d.svg\",\"heart_exclamation\":\"b975686.svg\",\"heavy_heart_exclamation_mark_ornament\":\"b975686.svg\",\"heart\":\"61bd815.svg\",\"heavy_plus_sign\":\"5bfd726.svg\",\"heavy_minus_sign\":\"e393852.svg\",\"heavy_division_sign\":\"ab7f7db.svg\",\"arrow_heading_up\":\"5ab8978.svg\",\"arrow_heading_down\":\"a2aac01.svg\",\"wavy_dash\":\"6869dc1.svg\",\"congratulations\":\"6db8b53.svg\",\"secret\":\"4811a27.svg\",\"grinning\":\"855a20b.svg\",\"smiley\":\"ea6c27e.svg\",\"smile\":\"cc1476e.svg\",\"grin\":\"3f27807.svg\",\"laughing\":\"a1a5b20.svg\",\"satisfied\":\"a1a5b20.svg\",\"sweat_smile\":\"564ce08.svg\",\"joy\":\"dc4914b.svg\",\"rofl\":\"6d92e2a.svg\",\"rolling_on_the_floor_laughing\":\"6d92e2a.svg\",\"relaxed\":\"941ac42.svg\",\"blush\":\"edc2a3e.svg\",\"innocent\":\"6048909.svg\",\"slight_smile\":\"682e14e.svg\",\"slightly_smiling_face\":\"682e14e.svg\",\"upside_down\":\"c3985ca.svg\",\"upside_down_face\":\"c3985ca.svg\",\"wink\":\"28d185d.svg\",\"relieved\":\"73bd852.svg\",\"smiling_face_with_tear\":\"b4b21e4.svg\",\"heart_eyes\":\"bff73dd.svg\",\"smiling_face_with_3_hearts\":\"3a6e61e.svg\",\"kissing_heart\":\"babb293.svg\",\"kissing\":\"9162523.svg\",\"kissing_smiling_eyes\":\"3ef839c.svg\",\"kissing_closed_eyes\":\"2ffc67a.svg\",\"yum\":\"75e9463.svg\",\"stuck_out_tongue\":\"956e398.svg\",\"stuck_out_tongue_closed_eyes\":\"edf2f35.svg\",\"stuck_out_tongue_winking_eye\":\"94505b2.svg\",\"zany_face\":\"c9ca468.svg\",\"face_with_raised_eyebrow\":\"f112b4d.svg\",\"face_with_monocle\":\"770ec60.svg\",\"nerd\":\"c9a30e0.svg\",\"nerd_face\":\"c9a30e0.svg\",\"sunglasses\":\"c0c45e0.svg\",\"star_struck\":\"986b540.svg\",\"partying_face\":\"6dd9ab2.svg\",\"smirk\":\"4783d27.svg\",\"unamused\":\"8442c49.svg\",\"disappointed\":\"2b2beac.svg\",\"pensive\":\"26afe78.svg\",\"worried\":\"925c26f.svg\",\"confused\":\"b3292f4.svg\",\"slight_frown\":\"119074c.svg\",\"slightly_frowning_face\":\"119074c.svg\",\"persevere\":\"f60bd32.svg\",\"confounded\":\"99c5b27.svg\",\"tired_face\":\"89fdb97.svg\",\"weary\":\"d9050ec.svg\",\"pleading_face\":\"443519c.svg\",\"cry\":\"28785e2.svg\",\"sob\":\"6e31c7c.svg\",\"triumph\":\"e08b216.svg\",\"face_exhaling\":\"08b2da6.svg\",\"angry\":\"ce4c95d.svg\",\"rage\":\"a5ccb2c.svg\",\"face_with_symbols_over_mouth\":\"521b2cc.svg\",\"exploding_head\":\"5d20bd8.svg\",\"flushed\":\"386d679.svg\",\"face_in_clouds\":\"e1592e1.svg\",\"hot_face\":\"b32e5c3.svg\",\"cold_face\":\"a6307ad.svg\",\"scream\":\"2f595d0.svg\",\"fearful\":\"0901baa.svg\",\"cold_sweat\":\"999a34b.svg\",\"disappointed_relieved\":\"7fe32af.svg\",\"sweat\":\"91fea65.svg\",\"hugging\":\"72e6b61.svg\",\"hugging_face\":\"72e6b61.svg\",\"thinking\":\"6add816.svg\",\"thinking_face\":\"6add816.svg\",\"face_with_hand_over_mouth\":\"6a9c73f.svg\",\"yawning_face\":\"86204a8.svg\",\"shushing_face\":\"7f17dd2.svg\",\"lying_face\":\"dda5eef.svg\",\"liar\":\"dda5eef.svg\",\"no_mouth\":\"8a99b07.svg\",\"neutral_face\":\"a6195d9.svg\",\"expressionless\":\"461cdef.svg\",\"grimacing\":\"1e20d08.svg\",\"rolling_eyes\":\"db553c8.svg\",\"face_with_rolling_eyes\":\"db553c8.svg\",\"hushed\":\"0af023c.svg\",\"frowning\":\"7fe2396.svg\",\"anguished\":\"b236aa7.svg\",\"open_mouth\":\"0ed7e03.svg\",\"astonished\":\"fc1ede6.svg\",\"sleeping\":\"6955348.svg\",\"drooling_face\":\"0c952c8.svg\",\"drool\":\"0c952c8.svg\",\"sleepy\":\"c244ab4.svg\",\"dizzy_face\":\"a9a67d9.svg\",\"face_with_spiral_eyes\":\"8a63df4.svg\",\"zipper_mouth\":\"47e6ec5.svg\",\"zipper_mouth_face\":\"47e6ec5.svg\",\"woozy_face\":\"1eb097a.svg\",\"nauseated_face\":\"93cd3a4.svg\",\"sick\":\"93cd3a4.svg\",\"face_vomiting\":\"7c7a02b.svg\",\"sneezing_face\":\"cd839a5.svg\",\"sneeze\":\"cd839a5.svg\",\"mask\":\"422f5af.svg\",\"thermometer_face\":\"1d11ea3.svg\",\"face_with_thermometer\":\"1d11ea3.svg\",\"head_bandage\":\"dfce78c.svg\",\"face_with_head_bandage\":\"dfce78c.svg\",\"money_mouth\":\"eabac9a.svg\",\"money_mouth_face\":\"eabac9a.svg\",\"cowboy\":\"d59f4db.svg\",\"face_with_cowboy_hat\":\"d59f4db.svg\",\"disguised_face\":\"6b530e0.svg\",\"smiling_imp\":\"62a11b2.svg\",\"imp\":\"5eb5bd8.svg\",\"japanese_ogre\":\"4a69ea6.svg\",\"japanese_goblin\":\"7aaf1ce.svg\",\"clown\":\"0712ba3.svg\",\"clown_face\":\"0712ba3.svg\",\"poop\":\"06b9ffa.svg\",\"shit\":\"06b9ffa.svg\",\"hankey\":\"06b9ffa.svg\",\"poo\":\"06b9ffa.svg\",\"ghost\":\"c2eea99.svg\",\"skull\":\"2283d79.svg\",\"skeleton\":\"2283d79.svg\",\"alien\":\"90ca85f.svg\",\"space_invader\":\"8c48ddf.svg\",\"robot\":\"6d8c6cf.svg\",\"robot_face\":\"6d8c6cf.svg\",\"jack_o_lantern\":\"9b16264.svg\",\"smiley_cat\":\"cc354ab.svg\",\"smile_cat\":\"efa9820.svg\",\"joy_cat\":\"8c5c4d9.svg\",\"heart_eyes_cat\":\"b5a077b.svg\",\"smirk_cat\":\"e89c5cd.svg\",\"kissing_cat\":\"6604a6b.svg\",\"scream_cat\":\"8c3016b.svg\",\"crying_cat_face\":\"0996639.svg\",\"pouting_cat\":\"7844a05.svg\",\"palms_up_together\":\"d1d5410.svg\",\"palms_up_together_tone1\":\"f6537bd.svg\",\"palms_up_together_light_skin_tone\":\"f6537bd.svg\",\"palms_up_together_tone2\":\"f44274d.svg\",\"palms_up_together_medium_light_skin_tone\":\"f44274d.svg\",\"palms_up_together_tone3\":\"dbb55bf.svg\",\"palms_up_together_medium_skin_tone\":\"dbb55bf.svg\",\"palms_up_together_tone4\":\"9038675.svg\",\"palms_up_together_medium_dark_skin_tone\":\"9038675.svg\",\"palms_up_together_tone5\":\"adec7d8.svg\",\"palms_up_together_dark_skin_tone\":\"adec7d8.svg\",\"open_hands\":\"118466e.svg\",\"open_hands_tone1\":\"a32e437.svg\",\"open_hands_tone2\":\"7d4ae39.svg\",\"open_hands_tone3\":\"83781f4.svg\",\"open_hands_tone4\":\"e6731c9.svg\",\"open_hands_tone5\":\"f338a35.svg\",\"raised_hands\":\"6e2bcf7.svg\",\"raised_hands_tone1\":\"af13a2f.svg\",\"raised_hands_tone2\":\"2428031.svg\",\"raised_hands_tone3\":\"89f2527.svg\",\"raised_hands_tone4\":\"3fdbc3b.svg\",\"raised_hands_tone5\":\"760a669.svg\",\"clap\":\"54853c6.svg\",\"clap_tone1\":\"99e769e.svg\",\"clap_tone2\":\"f1d64a7.svg\",\"clap_tone3\":\"c3cf438.svg\",\"clap_tone4\":\"a0ab9a4.svg\",\"clap_tone5\":\"5716e91.svg\",\"handshake\":\"a04d286.svg\",\"shaking_hands\":\"a04d286.svg\",\"thumbsup\":\"f8fee8e.svg\",\"+1\":\"f8fee8e.svg\",\"thumbup\":\"f8fee8e.svg\",\"thumbsup_tone1\":\"220c50f.svg\",\"+1_tone1\":\"220c50f.svg\",\"thumbup_tone1\":\"220c50f.svg\",\"thumbsup_tone2\":\"040be8e.svg\",\"+1_tone2\":\"040be8e.svg\",\"thumbup_tone2\":\"040be8e.svg\",\"thumbsup_tone3\":\"26c7aa0.svg\",\"+1_tone3\":\"26c7aa0.svg\",\"thumbup_tone3\":\"26c7aa0.svg\",\"thumbsup_tone4\":\"5c2a9a1.svg\",\"+1_tone4\":\"5c2a9a1.svg\",\"thumbup_tone4\":\"5c2a9a1.svg\",\"thumbsup_tone5\":\"cc823ef.svg\",\"+1_tone5\":\"cc823ef.svg\",\"thumbup_tone5\":\"cc823ef.svg\",\"thumbsdown\":\"0e682e9.svg\",\"-1\":\"0e682e9.svg\",\"thumbdown\":\"0e682e9.svg\",\"thumbsdown_tone1\":\"f89f247.svg\",\"-1_tone1\":\"f89f247.svg\",\"thumbdown_tone1\":\"f89f247.svg\",\"thumbsdown_tone2\":\"de63981.svg\",\"-1_tone2\":\"de63981.svg\",\"thumbdown_tone2\":\"de63981.svg\",\"thumbsdown_tone3\":\"b3cc536.svg\",\"-1_tone3\":\"b3cc536.svg\",\"thumbdown_tone3\":\"b3cc536.svg\",\"thumbsdown_tone4\":\"93e70b8.svg\",\"-1_tone4\":\"93e70b8.svg\",\"thumbdown_tone4\":\"93e70b8.svg\",\"thumbsdown_tone5\":\"d3bce71.svg\",\"-1_tone5\":\"d3bce71.svg\",\"thumbdown_tone5\":\"d3bce71.svg\",\"punch\":\"93d9d16.svg\",\"punch_tone1\":\"1b2deff.svg\",\"punch_tone2\":\"fbf114a.svg\",\"punch_tone3\":\"506ed1c.svg\",\"punch_tone4\":\"3a1b73e.svg\",\"punch_tone5\":\"0c2ec0b.svg\",\"fist\":\"410baea.svg\",\"fist_tone1\":\"80f2d54.svg\",\"fist_tone2\":\"391dca8.svg\",\"fist_tone3\":\"0429915.svg\",\"fist_tone4\":\"e0ae4cf.svg\",\"fist_tone5\":\"dc2dac6.svg\",\"left_facing_fist\":\"ee167ee.svg\",\"left_fist\":\"ee167ee.svg\",\"left_facing_fist_tone1\":\"bca4b94.svg\",\"left_fist_tone1\":\"bca4b94.svg\",\"left_facing_fist_tone2\":\"c32bae1.svg\",\"left_fist_tone2\":\"c32bae1.svg\",\"left_facing_fist_tone3\":\"bff4577.svg\",\"left_fist_tone3\":\"bff4577.svg\",\"left_facing_fist_tone4\":\"cb22fea.svg\",\"left_fist_tone4\":\"cb22fea.svg\",\"left_facing_fist_tone5\":\"0605cfc.svg\",\"left_fist_tone5\":\"0605cfc.svg\",\"right_facing_fist\":\"8a25069.svg\",\"right_fist\":\"8a25069.svg\",\"right_facing_fist_tone1\":\"50ddaf8.svg\",\"right_fist_tone1\":\"50ddaf8.svg\",\"right_facing_fist_tone2\":\"429925f.svg\",\"right_fist_tone2\":\"429925f.svg\",\"right_facing_fist_tone3\":\"bbf8af5.svg\",\"right_fist_tone3\":\"bbf8af5.svg\",\"right_facing_fist_tone4\":\"f66d395.svg\",\"right_fist_tone4\":\"f66d395.svg\",\"right_facing_fist_tone5\":\"996f47c.svg\",\"right_fist_tone5\":\"996f47c.svg\",\"fingers_crossed\":\"dc3511e.svg\",\"hand_with_index_and_middle_finger_crossed\":\"dc3511e.svg\",\"fingers_crossed_tone1\":\"c6255b4.svg\",\"hand_with_index_and_middle_fingers_crossed_tone1\":\"c6255b4.svg\",\"fingers_crossed_tone2\":\"38d3101.svg\",\"hand_with_index_and_middle_fingers_crossed_tone2\":\"38d3101.svg\",\"fingers_crossed_tone3\":\"12724d3.svg\",\"hand_with_index_and_middle_fingers_crossed_tone3\":\"12724d3.svg\",\"fingers_crossed_tone4\":\"ed4dd94.svg\",\"hand_with_index_and_middle_fingers_crossed_tone4\":\"ed4dd94.svg\",\"fingers_crossed_tone5\":\"d0fb18e.svg\",\"hand_with_index_and_middle_fingers_crossed_tone5\":\"d0fb18e.svg\",\"v\":\"febf6ba.svg\",\"v_tone1\":\"dbe5d18.svg\",\"v_tone2\":\"af07f0f.svg\",\"v_tone3\":\"580ecd3.svg\",\"v_tone4\":\"e152620.svg\",\"v_tone5\":\"235bbf1.svg\",\"love_you_gesture\":\"cc54e70.svg\",\"love_you_gesture_tone1\":\"17cd4fa.svg\",\"love_you_gesture_light_skin_tone\":\"17cd4fa.svg\",\"love_you_gesture_tone2\":\"6291d8a.svg\",\"love_you_gesture_medium_light_skin_tone\":\"6291d8a.svg\",\"love_you_gesture_tone3\":\"db2b81a.svg\",\"love_you_gesture_medium_skin_tone\":\"db2b81a.svg\",\"love_you_gesture_tone4\":\"8cb6fdd.svg\",\"love_you_gesture_medium_dark_skin_tone\":\"8cb6fdd.svg\",\"love_you_gesture_tone5\":\"ef34a19.svg\",\"love_you_gesture_dark_skin_tone\":\"ef34a19.svg\",\"metal\":\"873d964.svg\",\"sign_of_the_horns\":\"873d964.svg\",\"metal_tone1\":\"52888a2.svg\",\"sign_of_the_horns_tone1\":\"52888a2.svg\",\"metal_tone2\":\"f264e36.svg\",\"sign_of_the_horns_tone2\":\"f264e36.svg\",\"metal_tone3\":\"7e09314.svg\",\"sign_of_the_horns_tone3\":\"7e09314.svg\",\"metal_tone4\":\"4cab71a.svg\",\"sign_of_the_horns_tone4\":\"4cab71a.svg\",\"metal_tone5\":\"63e55cf.svg\",\"sign_of_the_horns_tone5\":\"63e55cf.svg\",\"ok_hand\":\"08c8a43.svg\",\"ok_hand_tone1\":\"f069401.svg\",\"ok_hand_tone2\":\"66ce630.svg\",\"ok_hand_tone3\":\"c68f7ee.svg\",\"ok_hand_tone4\":\"f9f46a9.svg\",\"ok_hand_tone5\":\"304452a.svg\",\"pinching_hand\":\"5c8da33.svg\",\"pinching_hand_tone1\":\"c40530a.svg\",\"pinching_hand_light_skin_tone\":\"c40530a.svg\",\"pinching_hand_tone2\":\"f44b317.svg\",\"pinching_hand_medium_light_skin_tone\":\"f44b317.svg\",\"pinching_hand_tone3\":\"296d23d.svg\",\"pinching_hand_medium_skin_tone\":\"296d23d.svg\",\"pinching_hand_tone4\":\"e600777.svg\",\"pinching_hand_medium_dark_skin_tone\":\"e600777.svg\",\"pinching_hand_tone5\":\"6109389.svg\",\"pinching_hand_dark_skin_tone\":\"6109389.svg\",\"pinched_fingers\":\"51a509d.svg\",\"pinched_fingers_tone2\":\"953a175.svg\",\"pinched_fingers_medium_light_skin_tone\":\"953a175.svg\",\"pinched_fingers_tone1\":\"2b990de.svg\",\"pinched_fingers_light_skin_tone\":\"2b990de.svg\",\"pinched_fingers_tone3\":\"6e6e2c7.svg\",\"pinched_fingers_medium_skin_tone\":\"6e6e2c7.svg\",\"pinched_fingers_tone4\":\"94b01dd.svg\",\"pinched_fingers_medium_dark_skin_tone\":\"94b01dd.svg\",\"pinched_fingers_tone5\":\"ec2e0ce.svg\",\"pinched_fingers_dark_skin_tone\":\"ec2e0ce.svg\",\"point_left\":\"edcc59f.svg\",\"point_left_tone1\":\"3230da3.svg\",\"point_left_tone2\":\"609bc7b.svg\",\"point_left_tone3\":\"f33129f.svg\",\"point_left_tone4\":\"868774c.svg\",\"point_left_tone5\":\"411935b.svg\",\"point_right\":\"e6620a7.svg\",\"point_right_tone1\":\"26f4e15.svg\",\"point_right_tone2\":\"e1f9849.svg\",\"point_right_tone3\":\"192043c.svg\",\"point_right_tone4\":\"a7e605e.svg\",\"point_right_tone5\":\"8644a09.svg\",\"point_up_2\":\"cffa2d8.svg\",\"point_up_2_tone1\":\"c501490.svg\",\"point_up_2_tone2\":\"66bc00a.svg\",\"point_up_2_tone3\":\"f117f5f.svg\",\"point_up_2_tone4\":\"b4ed3bb.svg\",\"point_up_2_tone5\":\"f86e6b9.svg\",\"point_down\":\"b80d789.svg\",\"point_down_tone1\":\"70129dd.svg\",\"point_down_tone2\":\"0ae7eea.svg\",\"point_down_tone3\":\"aad4f39.svg\",\"point_down_tone4\":\"1b0389f.svg\",\"point_down_tone5\":\"1d266ab.svg\",\"point_up\":\"14059d0.svg\",\"point_up_tone1\":\"a68d50d.svg\",\"point_up_tone2\":\"0dabe5a.svg\",\"point_up_tone3\":\"b044a10.svg\",\"point_up_tone4\":\"bd422f8.svg\",\"point_up_tone5\":\"36eec31.svg\",\"raised_hand\":\"a01ee6f.svg\",\"raised_hand_tone1\":\"63d88cb.svg\",\"raised_hand_tone2\":\"15ad4b4.svg\",\"raised_hand_tone3\":\"7df5ac6.svg\",\"raised_hand_tone4\":\"de49c80.svg\",\"raised_hand_tone5\":\"4e4e217.svg\",\"raised_back_of_hand\":\"03a3431.svg\",\"back_of_hand\":\"03a3431.svg\",\"raised_back_of_hand_tone1\":\"1e47667.svg\",\"back_of_hand_tone1\":\"1e47667.svg\",\"raised_back_of_hand_tone2\":\"dbe0c11.svg\",\"back_of_hand_tone2\":\"dbe0c11.svg\",\"raised_back_of_hand_tone3\":\"a189f32.svg\",\"back_of_hand_tone3\":\"a189f32.svg\",\"raised_back_of_hand_tone4\":\"aabe8b6.svg\",\"back_of_hand_tone4\":\"aabe8b6.svg\",\"raised_back_of_hand_tone5\":\"1a35c12.svg\",\"back_of_hand_tone5\":\"1a35c12.svg\",\"hand_splayed\":\"1e46fe9.svg\",\"raised_hand_with_fingers_splayed\":\"1e46fe9.svg\",\"hand_splayed_tone1\":\"8fe34bf.svg\",\"raised_hand_with_fingers_splayed_tone1\":\"8fe34bf.svg\",\"hand_splayed_tone2\":\"404ac42.svg\",\"raised_hand_with_fingers_splayed_tone2\":\"404ac42.svg\",\"hand_splayed_tone3\":\"f972a1a.svg\",\"raised_hand_with_fingers_splayed_tone3\":\"f972a1a.svg\",\"hand_splayed_tone4\":\"9ee98fa.svg\",\"raised_hand_with_fingers_splayed_tone4\":\"9ee98fa.svg\",\"hand_splayed_tone5\":\"a8706ca.svg\",\"raised_hand_with_fingers_splayed_tone5\":\"a8706ca.svg\",\"vulcan\":\"33a87e5.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers\":\"33a87e5.svg\",\"vulcan_tone1\":\"e2257d7.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone1\":\"e2257d7.svg\",\"vulcan_tone2\":\"1c31b51.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone2\":\"1c31b51.svg\",\"vulcan_tone3\":\"b2b5252.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone3\":\"b2b5252.svg\",\"vulcan_tone4\":\"aac1b5a.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone4\":\"aac1b5a.svg\",\"vulcan_tone5\":\"d8031f8.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone5\":\"d8031f8.svg\",\"wave\":\"416968a.svg\",\"wave_tone1\":\"428aceb.svg\",\"wave_tone2\":\"6dd2d1f.svg\",\"wave_tone3\":\"fa497a2.svg\",\"wave_tone4\":\"70bd7cf.svg\",\"wave_tone5\":\"7e74227.svg\",\"call_me\":\"eabacb6.svg\",\"call_me_hand\":\"eabacb6.svg\",\"call_me_tone1\":\"39ee699.svg\",\"call_me_hand_tone1\":\"39ee699.svg\",\"call_me_tone2\":\"a193407.svg\",\"call_me_hand_tone2\":\"a193407.svg\",\"call_me_tone3\":\"4e66c1c.svg\",\"call_me_hand_tone3\":\"4e66c1c.svg\",\"call_me_tone4\":\"fb552b1.svg\",\"call_me_hand_tone4\":\"fb552b1.svg\",\"call_me_tone5\":\"ced6cd1.svg\",\"call_me_hand_tone5\":\"ced6cd1.svg\",\"muscle\":\"9c1b263.svg\",\"muscle_tone1\":\"3489c7a.svg\",\"muscle_tone2\":\"c8b0739.svg\",\"muscle_tone3\":\"61af40c.svg\",\"muscle_tone4\":\"0b00d63.svg\",\"muscle_tone5\":\"e4ccfae.svg\",\"mechanical_arm\":\"789706a.svg\",\"middle_finger\":\"516015e.svg\",\"reversed_hand_with_middle_finger_extended\":\"516015e.svg\",\"middle_finger_tone1\":\"56a20e3.svg\",\"reversed_hand_with_middle_finger_extended_tone1\":\"56a20e3.svg\",\"middle_finger_tone2\":\"79b0369.svg\",\"reversed_hand_with_middle_finger_extended_tone2\":\"79b0369.svg\",\"middle_finger_tone3\":\"d762daa.svg\",\"reversed_hand_with_middle_finger_extended_tone3\":\"d762daa.svg\",\"middle_finger_tone4\":\"a16903d.svg\",\"reversed_hand_with_middle_finger_extended_tone4\":\"a16903d.svg\",\"middle_finger_tone5\":\"0433221.svg\",\"reversed_hand_with_middle_finger_extended_tone5\":\"0433221.svg\",\"writing_hand\":\"c06fe85.svg\",\"writing_hand_tone1\":\"3bb9865.svg\",\"writing_hand_tone2\":\"09613d5.svg\",\"writing_hand_tone3\":\"8f677e9.svg\",\"writing_hand_tone4\":\"a80ff84.svg\",\"writing_hand_tone5\":\"bc76cfd.svg\",\"pray\":\"61d7402.svg\",\"pray_tone1\":\"4a7f7a8.svg\",\"pray_tone2\":\"488d7bc.svg\",\"pray_tone3\":\"abb5e1f.svg\",\"pray_tone4\":\"8ee76a6.svg\",\"pray_tone5\":\"4e53992.svg\",\"foot\":\"f7eb2e4.svg\",\"foot_tone1\":\"c6e8410.svg\",\"foot_light_skin_tone\":\"c6e8410.svg\",\"foot_tone2\":\"58a17a3.svg\",\"foot_medium_light_skin_tone\":\"58a17a3.svg\",\"foot_tone3\":\"e3c956c.svg\",\"foot_medium_skin_tone\":\"e3c956c.svg\",\"foot_tone4\":\"f781d93.svg\",\"foot_medium_dark_skin_tone\":\"f781d93.svg\",\"foot_tone5\":\"2ba7377.svg\",\"foot_dark_skin_tone\":\"2ba7377.svg\",\"leg\":\"091f5fb.svg\",\"leg_tone1\":\"6072e6e.svg\",\"leg_light_skin_tone\":\"6072e6e.svg\",\"leg_tone2\":\"f05e535.svg\",\"leg_medium_light_skin_tone\":\"f05e535.svg\",\"leg_tone3\":\"a9ef097.svg\",\"leg_medium_skin_tone\":\"a9ef097.svg\",\"leg_tone4\":\"8716aa9.svg\",\"leg_medium_dark_skin_tone\":\"8716aa9.svg\",\"leg_tone5\":\"a928e6b.svg\",\"leg_dark_skin_tone\":\"a928e6b.svg\",\"mechanical_leg\":\"b7974d1.svg\",\"lipstick\":\"9f28886.svg\",\"kiss\":\"c72dfb2.svg\",\"lips\":\"2920bdc.svg\",\"tooth\":\"ebeb871.svg\",\"tongue\":\"3e1f809.svg\",\"ear\":\"c5f35e2.svg\",\"ear_tone1\":\"7d56b68.svg\",\"ear_tone2\":\"59113b8.svg\",\"ear_tone3\":\"34ff93f.svg\",\"ear_tone4\":\"1b2fbc0.svg\",\"ear_tone5\":\"e53cb4d.svg\",\"ear_with_hearing_aid\":\"25cb021.svg\",\"ear_with_hearing_aid_tone1\":\"0ae090c.svg\",\"ear_with_hearing_aid_light_skin_tone\":\"0ae090c.svg\",\"ear_with_hearing_aid_tone2\":\"f695cdd.svg\",\"ear_with_hearing_aid_medium_light_skin_tone\":\"f695cdd.svg\",\"ear_with_hearing_aid_tone3\":\"0d382e1.svg\",\"ear_with_hearing_aid_medium_skin_tone\":\"0d382e1.svg\",\"ear_with_hearing_aid_tone4\":\"57064f7.svg\",\"ear_with_hearing_aid_medium_dark_skin_tone\":\"57064f7.svg\",\"ear_with_hearing_aid_tone5\":\"eef2ced.svg\",\"ear_with_hearing_aid_dark_skin_tone\":\"eef2ced.svg\",\"nose\":\"bd8ef1d.svg\",\"nose_tone1\":\"e0f60a6.svg\",\"nose_tone2\":\"ace3849.svg\",\"nose_tone3\":\"66b75d0.svg\",\"nose_tone4\":\"6b8323e.svg\",\"nose_tone5\":\"79b1d60.svg\",\"footprints\":\"774dca0.svg\",\"eye\":\"ce6d3bc.svg\",\"eyes\":\"504e124.svg\",\"brain\":\"9ca0f1a.svg\",\"anatomical_heart\":\"0a683ed.svg\",\"lungs\":\"76ce912.svg\",\"bone\":\"10f3a37.svg\",\"speaking_head\":\"e2a0c47.svg\",\"speaking_head_in_silhouette\":\"e2a0c47.svg\",\"bust_in_silhouette\":\"b77275e.svg\",\"busts_in_silhouette\":\"4775308.svg\",\"people_hugging\":\"9ba1877.svg\",\"baby\":\"6b120e0.svg\",\"baby_tone1\":\"4970605.svg\",\"baby_tone2\":\"1c238b7.svg\",\"baby_tone3\":\"3d346f2.svg\",\"baby_tone4\":\"2256735.svg\",\"baby_tone5\":\"b1e0f97.svg\",\"girl\":\"05657c1.svg\",\"girl_tone1\":\"8918ad5.svg\",\"girl_tone2\":\"6d3bdbc.svg\",\"girl_tone3\":\"3b6f2bb.svg\",\"girl_tone4\":\"8592bac.svg\",\"girl_tone5\":\"bbcbedc.svg\",\"child\":\"0c86a55.svg\",\"child_tone1\":\"1a1ee91.svg\",\"child_light_skin_tone\":\"1a1ee91.svg\",\"child_tone2\":\"8117d83.svg\",\"child_medium_light_skin_tone\":\"8117d83.svg\",\"child_tone3\":\"98efc1d.svg\",\"child_medium_skin_tone\":\"98efc1d.svg\",\"child_tone4\":\"ade7753.svg\",\"child_medium_dark_skin_tone\":\"ade7753.svg\",\"child_tone5\":\"776d50a.svg\",\"child_dark_skin_tone\":\"776d50a.svg\",\"boy\":\"e8fb01a.svg\",\"boy_tone1\":\"e099d02.svg\",\"boy_tone2\":\"9fb2c42.svg\",\"boy_tone3\":\"957b277.svg\",\"boy_tone4\":\"3084c47.svg\",\"boy_tone5\":\"39a0989.svg\",\"woman\":\"a0b627d.svg\",\"woman_tone1\":\"0eb2b3a.svg\",\"woman_tone2\":\"fff6382.svg\",\"woman_tone3\":\"8eb1775.svg\",\"woman_tone4\":\"76e777a.svg\",\"woman_tone5\":\"129cba3.svg\",\"adult\":\"e68c3d5.svg\",\"adult_tone1\":\"de2b6fd.svg\",\"adult_light_skin_tone\":\"de2b6fd.svg\",\"adult_tone2\":\"6290f21.svg\",\"adult_medium_light_skin_tone\":\"6290f21.svg\",\"adult_tone3\":\"ab633c5.svg\",\"adult_medium_skin_tone\":\"ab633c5.svg\",\"adult_tone4\":\"bd9903f.svg\",\"adult_medium_dark_skin_tone\":\"bd9903f.svg\",\"adult_tone5\":\"2aff0bd.svg\",\"adult_dark_skin_tone\":\"2aff0bd.svg\",\"man\":\"bb89b12.svg\",\"man_tone1\":\"aeabe4e.svg\",\"man_tone2\":\"13e0aba.svg\",\"man_tone3\":\"e9f553f.svg\",\"man_tone4\":\"fd63055.svg\",\"man_tone5\":\"d16a927.svg\",\"person_curly_hair\":\"053f135.svg\",\"person_tone1_curly_hair\":\"b99a9c0.svg\",\"person_light_skin_tone_curly_hair\":\"b99a9c0.svg\",\"person_tone2_curly_hair\":\"a15cd41.svg\",\"person_medium_light_skin_tone_curly_hair\":\"a15cd41.svg\",\"person_tone3_curly_hair\":\"c7b9601.svg\",\"person_medium_skin_tone_curly_hair\":\"c7b9601.svg\",\"person_tone4_curly_hair\":\"e9673a8.svg\",\"person_medium_dark_skin_tone_curly_hair\":\"e9673a8.svg\",\"person_tone5_curly_hair\":\"e8f2685.svg\",\"person_dark_skin_tone_curly_hair\":\"e8f2685.svg\",\"woman_curly_haired\":\"7f65748.svg\",\"woman_curly_haired_tone1\":\"a3a7ba2.svg\",\"woman_curly_haired_light_skin_tone\":\"a3a7ba2.svg\",\"woman_curly_haired_tone2\":\"152918f.svg\",\"woman_curly_haired_medium_light_skin_tone\":\"152918f.svg\",\"woman_curly_haired_tone3\":\"2286c64.svg\",\"woman_curly_haired_medium_skin_tone\":\"2286c64.svg\",\"woman_curly_haired_tone4\":\"23ae61d.svg\",\"woman_curly_haired_medium_dark_skin_tone\":\"23ae61d.svg\",\"woman_curly_haired_tone5\":\"f4e7d4e.svg\",\"woman_curly_haired_dark_skin_tone\":\"f4e7d4e.svg\",\"man_curly_haired\":\"b6adf8d.svg\",\"man_curly_haired_tone1\":\"39e9ae7.svg\",\"man_curly_haired_light_skin_tone\":\"39e9ae7.svg\",\"man_curly_haired_tone2\":\"41bc09c.svg\",\"man_curly_haired_medium_light_skin_tone\":\"41bc09c.svg\",\"man_curly_haired_tone3\":\"eb53bb6.svg\",\"man_curly_haired_medium_skin_tone\":\"eb53bb6.svg\",\"man_curly_haired_tone4\":\"d9401de.svg\",\"man_curly_haired_medium_dark_skin_tone\":\"d9401de.svg\",\"man_curly_haired_tone5\":\"f7b918d.svg\",\"man_curly_haired_dark_skin_tone\":\"f7b918d.svg\",\"person_red_hair\":\"cc2093a.svg\",\"person_tone1_red_hair\":\"5c41b26.svg\",\"person_light_skin_tone_red_hair\":\"5c41b26.svg\",\"person_tone2_red_hair\":\"ba97ee4.svg\",\"person_medium_light_skin_tone_red_hair\":\"ba97ee4.svg\",\"person_tone3_red_hair\":\"542a340.svg\",\"person_medium_skin_tone_red_hair\":\"542a340.svg\",\"person_tone4_red_hair\":\"88cbfe4.svg\",\"person_medium_dark_skin_tone_red_hair\":\"88cbfe4.svg\",\"person_tone5_red_hair\":\"7c58e8b.svg\",\"person_dark_skin_tone_red_hair\":\"7c58e8b.svg\",\"woman_red_haired\":\"da96491.svg\",\"woman_red_haired_tone1\":\"b268f8a.svg\",\"woman_red_haired_light_skin_tone\":\"b268f8a.svg\",\"woman_red_haired_tone2\":\"d5b4bf3.svg\",\"woman_red_haired_medium_light_skin_tone\":\"d5b4bf3.svg\",\"woman_red_haired_tone3\":\"94b1930.svg\",\"woman_red_haired_medium_skin_tone\":\"94b1930.svg\",\"woman_red_haired_tone4\":\"7e48c63.svg\",\"woman_red_haired_medium_dark_skin_tone\":\"7e48c63.svg\",\"woman_red_haired_tone5\":\"42f33f8.svg\",\"woman_red_haired_dark_skin_tone\":\"42f33f8.svg\",\"man_red_haired\":\"75a6d21.svg\",\"man_red_haired_tone1\":\"f9c72b5.svg\",\"man_red_haired_light_skin_tone\":\"f9c72b5.svg\",\"man_red_haired_tone2\":\"4bf433a.svg\",\"man_red_haired_medium_light_skin_tone\":\"4bf433a.svg\",\"man_red_haired_tone3\":\"504bb42.svg\",\"man_red_haired_medium_skin_tone\":\"504bb42.svg\",\"man_red_haired_tone4\":\"3a20581.svg\",\"man_red_haired_medium_dark_skin_tone\":\"3a20581.svg\",\"man_red_haired_tone5\":\"bf9e793.svg\",\"man_red_haired_dark_skin_tone\":\"bf9e793.svg\",\"blond-haired_woman\":\"0523090.svg\",\"blond-haired_woman_tone1\":\"187a349.svg\",\"blond-haired_woman_light_skin_tone\":\"187a349.svg\",\"blond-haired_woman_tone2\":\"fff6382.svg\",\"blond-haired_woman_medium_light_skin_tone\":\"fff6382.svg\",\"blond-haired_woman_tone3\":\"6f8c884.svg\",\"blond-haired_woman_medium_skin_tone\":\"6f8c884.svg\",\"blond-haired_woman_tone4\":\"fc47714.svg\",\"blond-haired_woman_medium_dark_skin_tone\":\"fc47714.svg\",\"blond-haired_woman_tone5\":\"8235eeb.svg\",\"blond-haired_woman_dark_skin_tone\":\"8235eeb.svg\",\"blond_haired_person\":\"73f2288.svg\",\"person_with_blond_hair\":\"73f2288.svg\",\"blond_haired_person_tone1\":\"29a62d0.svg\",\"person_with_blond_hair_tone1\":\"29a62d0.svg\",\"blond_haired_person_tone2\":\"07ec158.svg\",\"person_with_blond_hair_tone2\":\"07ec158.svg\",\"blond_haired_person_tone3\":\"e622a4b.svg\",\"person_with_blond_hair_tone3\":\"e622a4b.svg\",\"blond_haired_person_tone4\":\"4921dfd.svg\",\"person_with_blond_hair_tone4\":\"4921dfd.svg\",\"blond_haired_person_tone5\":\"61d33f2.svg\",\"person_with_blond_hair_tone5\":\"61d33f2.svg\",\"blond-haired_man\":\"74de604.svg\",\"blond-haired_man_tone1\":\"5fba535.svg\",\"blond-haired_man_light_skin_tone\":\"5fba535.svg\",\"blond-haired_man_tone2\":\"458f0cc.svg\",\"blond-haired_man_medium_light_skin_tone\":\"458f0cc.svg\",\"blond-haired_man_tone3\":\"2b4e848.svg\",\"blond-haired_man_medium_skin_tone\":\"2b4e848.svg\",\"blond-haired_man_tone4\":\"e065966.svg\",\"blond-haired_man_medium_dark_skin_tone\":\"e065966.svg\",\"blond-haired_man_tone5\":\"d4e74be.svg\",\"blond-haired_man_dark_skin_tone\":\"d4e74be.svg\",\"person_white_hair\":\"a888959.svg\",\"person_tone1_white_hair\":\"45f6b72.svg\",\"person_light_skin_tone_white_hair\":\"45f6b72.svg\",\"person_tone2_white_hair\":\"8cd1671.svg\",\"person_medium_light_skin_tone_white_hair\":\"8cd1671.svg\",\"person_tone3_white_hair\":\"552b1e2.svg\",\"person_medium_skin_tone_white_hair\":\"552b1e2.svg\",\"person_tone4_white_hair\":\"24ae36b.svg\",\"person_medium_dark_skin_tone_white_hair\":\"24ae36b.svg\",\"person_tone5_white_hair\":\"e20ef19.svg\",\"person_dark_skin_tone_white_hair\":\"e20ef19.svg\",\"woman_white_haired\":\"f08552a.svg\",\"woman_white_haired_tone1\":\"dc1f2d6.svg\",\"woman_white_haired_light_skin_tone\":\"dc1f2d6.svg\",\"woman_white_haired_tone2\":\"0818e97.svg\",\"woman_white_haired_medium_light_skin_tone\":\"0818e97.svg\",\"woman_white_haired_tone3\":\"5603b0a.svg\",\"woman_white_haired_medium_skin_tone\":\"5603b0a.svg\",\"woman_white_haired_tone4\":\"2bda365.svg\",\"woman_white_haired_medium_dark_skin_tone\":\"2bda365.svg\",\"woman_white_haired_tone5\":\"f0584a9.svg\",\"woman_white_haired_dark_skin_tone\":\"f0584a9.svg\",\"man_white_haired\":\"bfe7b10.svg\",\"man_white_haired_tone1\":\"7146b21.svg\",\"man_white_haired_light_skin_tone\":\"7146b21.svg\",\"man_white_haired_tone2\":\"e021716.svg\",\"man_white_haired_medium_light_skin_tone\":\"e021716.svg\",\"man_white_haired_tone3\":\"796eb5f.svg\",\"man_white_haired_medium_skin_tone\":\"796eb5f.svg\",\"man_white_haired_tone4\":\"a35578d.svg\",\"man_white_haired_medium_dark_skin_tone\":\"a35578d.svg\",\"man_white_haired_tone5\":\"81ccd28.svg\",\"man_white_haired_dark_skin_tone\":\"81ccd28.svg\",\"person_bald\":\"104edb8.svg\",\"person_tone1_bald\":\"dde0988.svg\",\"person_light_skin_tone_bald\":\"dde0988.svg\",\"person_tone2_bald\":\"33377a2.svg\",\"person_medium_light_skin_tone_bald\":\"33377a2.svg\",\"person_tone3_bald\":\"1219df1.svg\",\"person_medium_skin_tone_bald\":\"1219df1.svg\",\"person_tone4_bald\":\"db8ce84.svg\",\"person_medium_dark_skin_tone_bald\":\"db8ce84.svg\",\"person_tone5_bald\":\"8dff4d4.svg\",\"person_dark_skin_tone_bald\":\"8dff4d4.svg\",\"woman_bald\":\"51d82b4.svg\",\"woman_bald_tone1\":\"ee90ae0.svg\",\"woman_bald_light_skin_tone\":\"ee90ae0.svg\",\"woman_bald_tone2\":\"8726e02.svg\",\"woman_bald_medium_light_skin_tone\":\"8726e02.svg\",\"woman_bald_tone3\":\"ddaa0ac.svg\",\"woman_bald_medium_skin_tone\":\"ddaa0ac.svg\",\"woman_bald_tone4\":\"774e784.svg\",\"woman_bald_medium_dark_skin_tone\":\"774e784.svg\",\"woman_bald_tone5\":\"bdd8178.svg\",\"woman_bald_dark_skin_tone\":\"bdd8178.svg\",\"man_bald\":\"4c265b1.svg\",\"man_bald_tone1\":\"ca04a9a.svg\",\"man_bald_light_skin_tone\":\"ca04a9a.svg\",\"man_bald_tone2\":\"a777c1f.svg\",\"man_bald_medium_light_skin_tone\":\"a777c1f.svg\",\"man_bald_tone3\":\"ce24d3a.svg\",\"man_bald_medium_skin_tone\":\"ce24d3a.svg\",\"man_bald_tone4\":\"3a94da1.svg\",\"man_bald_medium_dark_skin_tone\":\"3a94da1.svg\",\"man_bald_tone5\":\"acdb52b.svg\",\"man_bald_dark_skin_tone\":\"acdb52b.svg\",\"bearded_person\":\"a3e69d0.svg\",\"bearded_person_tone1\":\"55239df.svg\",\"bearded_person_light_skin_tone\":\"55239df.svg\",\"bearded_person_tone2\":\"7e53735.svg\",\"bearded_person_medium_light_skin_tone\":\"7e53735.svg\",\"bearded_person_tone3\":\"eaa8c25.svg\",\"bearded_person_medium_skin_tone\":\"eaa8c25.svg\",\"bearded_person_tone4\":\"a5e9ed9.svg\",\"bearded_person_medium_dark_skin_tone\":\"a5e9ed9.svg\",\"bearded_person_tone5\":\"2d120d5.svg\",\"bearded_person_dark_skin_tone\":\"2d120d5.svg\",\"man_beard\":\"567c295.svg\",\"man_tone1_beard\":\"549c546.svg\",\"man_light_skin_tone_beard\":\"549c546.svg\",\"man_tone2_beard\":\"44c4d8f.svg\",\"man_medium_light_skin_tone_beard\":\"44c4d8f.svg\",\"man_tone3_beard\":\"64017a9.svg\",\"man_medium_skin_tone_beard\":\"64017a9.svg\",\"man_tone4_beard\":\"abf3fe9.svg\",\"man_medium_dark_skin_tone_beard\":\"abf3fe9.svg\",\"man_tone5_beard\":\"c35fc33.svg\",\"man_dark_skin_tone_beard\":\"c35fc33.svg\",\"woman_beard\":\"4abd174.svg\",\"woman_tone1_beard\":\"6d854d7.svg\",\"woman_light_skin_tone_beard\":\"6d854d7.svg\",\"woman_tone2_beard\":\"c573411.svg\",\"woman_medium_light_skin_tone_beard\":\"c573411.svg\",\"woman_tone3_beard\":\"e682e71.svg\",\"woman_medium_skin_tone_beard\":\"e682e71.svg\",\"woman_tone4_beard\":\"884c1a7.svg\",\"woman_medium_dark_skin_tone_beard\":\"884c1a7.svg\",\"woman_tone5_beard\":\"5417b7f.svg\",\"woman_dark_skin_tone_beard\":\"5417b7f.svg\",\"older_woman\":\"cdd9b53.svg\",\"grandma\":\"cdd9b53.svg\",\"older_woman_tone1\":\"42c231d.svg\",\"grandma_tone1\":\"42c231d.svg\",\"older_woman_tone2\":\"f17d047.svg\",\"grandma_tone2\":\"f17d047.svg\",\"older_woman_tone3\":\"8cdefc8.svg\",\"grandma_tone3\":\"8cdefc8.svg\",\"older_woman_tone4\":\"e59c265.svg\",\"grandma_tone4\":\"e59c265.svg\",\"older_woman_tone5\":\"a8f6abc.svg\",\"grandma_tone5\":\"a8f6abc.svg\",\"older_adult\":\"4b64147.svg\",\"older_adult_tone1\":\"5e150c6.svg\",\"older_adult_light_skin_tone\":\"5e150c6.svg\",\"older_adult_tone2\":\"d7be541.svg\",\"older_adult_medium_light_skin_tone\":\"d7be541.svg\",\"older_adult_tone3\":\"20ea415.svg\",\"older_adult_medium_skin_tone\":\"20ea415.svg\",\"older_adult_tone4\":\"570924e.svg\",\"older_adult_medium_dark_skin_tone\":\"570924e.svg\",\"older_adult_tone5\":\"eeec292.svg\",\"older_adult_dark_skin_tone\":\"eeec292.svg\",\"older_man\":\"be4ea09.svg\",\"older_man_tone1\":\"2b69c63.svg\",\"older_man_tone2\":\"389c84b.svg\",\"older_man_tone3\":\"319464b.svg\",\"older_man_tone4\":\"86734d7.svg\",\"older_man_tone5\":\"08d7b15.svg\",\"man_with_chinese_cap\":\"06ae976.svg\",\"man_with_gua_pi_mao\":\"06ae976.svg\",\"man_with_chinese_cap_tone1\":\"2a983b9.svg\",\"man_with_gua_pi_mao_tone1\":\"2a983b9.svg\",\"man_with_chinese_cap_tone2\":\"155e404.svg\",\"man_with_gua_pi_mao_tone2\":\"155e404.svg\",\"man_with_chinese_cap_tone3\":\"8059954.svg\",\"man_with_gua_pi_mao_tone3\":\"8059954.svg\",\"man_with_chinese_cap_tone4\":\"c25d709.svg\",\"man_with_gua_pi_mao_tone4\":\"c25d709.svg\",\"man_with_chinese_cap_tone5\":\"333c3d0.svg\",\"man_with_gua_pi_mao_tone5\":\"333c3d0.svg\",\"person_wearing_turban\":\"0ca8dd5.svg\",\"man_with_turban\":\"0ca8dd5.svg\",\"person_wearing_turban_tone1\":\"4656d99.svg\",\"man_with_turban_tone1\":\"4656d99.svg\",\"person_wearing_turban_tone2\":\"dfbaf66.svg\",\"man_with_turban_tone2\":\"dfbaf66.svg\",\"person_wearing_turban_tone3\":\"3c15f41.svg\",\"man_with_turban_tone3\":\"3c15f41.svg\",\"person_wearing_turban_tone4\":\"d94e644.svg\",\"man_with_turban_tone4\":\"d94e644.svg\",\"person_wearing_turban_tone5\":\"d3cc0ec.svg\",\"man_with_turban_tone5\":\"d3cc0ec.svg\",\"woman_wearing_turban\":\"913976a.svg\",\"woman_wearing_turban_tone1\":\"170f58d.svg\",\"woman_wearing_turban_light_skin_tone\":\"170f58d.svg\",\"woman_wearing_turban_tone2\":\"ac9a5a1.svg\",\"woman_wearing_turban_medium_light_skin_tone\":\"ac9a5a1.svg\",\"woman_wearing_turban_tone3\":\"e576494.svg\",\"woman_wearing_turban_medium_skin_tone\":\"e576494.svg\",\"woman_wearing_turban_tone4\":\"beba980.svg\",\"woman_wearing_turban_medium_dark_skin_tone\":\"beba980.svg\",\"woman_wearing_turban_tone5\":\"78bb876.svg\",\"woman_wearing_turban_dark_skin_tone\":\"78bb876.svg\",\"man_wearing_turban\":\"1ab02a3.svg\",\"man_wearing_turban_tone1\":\"fa699d7.svg\",\"man_wearing_turban_light_skin_tone\":\"fa699d7.svg\",\"man_wearing_turban_tone2\":\"e532833.svg\",\"man_wearing_turban_medium_light_skin_tone\":\"e532833.svg\",\"man_wearing_turban_tone3\":\"ddb1af8.svg\",\"man_wearing_turban_medium_skin_tone\":\"ddb1af8.svg\",\"man_wearing_turban_tone4\":\"3ac0218.svg\",\"man_wearing_turban_medium_dark_skin_tone\":\"3ac0218.svg\",\"man_wearing_turban_tone5\":\"40976b3.svg\",\"man_wearing_turban_dark_skin_tone\":\"40976b3.svg\",\"woman_with_headscarf\":\"c0f9ef4.svg\",\"woman_with_headscarf_tone1\":\"71fe9c3.svg\",\"woman_with_headscarf_light_skin_tone\":\"71fe9c3.svg\",\"woman_with_headscarf_tone2\":\"4ac4ff7.svg\",\"woman_with_headscarf_medium_light_skin_tone\":\"4ac4ff7.svg\",\"woman_with_headscarf_tone3\":\"7cf843f.svg\",\"woman_with_headscarf_medium_skin_tone\":\"7cf843f.svg\",\"woman_with_headscarf_tone4\":\"8dde333.svg\",\"woman_with_headscarf_medium_dark_skin_tone\":\"8dde333.svg\",\"woman_with_headscarf_tone5\":\"cd6ea39.svg\",\"woman_with_headscarf_dark_skin_tone\":\"cd6ea39.svg\",\"police_officer\":\"55d8b37.svg\",\"cop\":\"55d8b37.svg\",\"police_officer_tone1\":\"b95742f.svg\",\"cop_tone1\":\"b95742f.svg\",\"police_officer_tone2\":\"606957d.svg\",\"cop_tone2\":\"606957d.svg\",\"police_officer_tone3\":\"1a8a9ee.svg\",\"cop_tone3\":\"1a8a9ee.svg\",\"police_officer_tone4\":\"94e4814.svg\",\"cop_tone4\":\"94e4814.svg\",\"police_officer_tone5\":\"cc685e6.svg\",\"cop_tone5\":\"cc685e6.svg\",\"woman_police_officer\":\"147d06b.svg\",\"woman_police_officer_tone1\":\"390aa26.svg\",\"woman_police_officer_light_skin_tone\":\"390aa26.svg\",\"woman_police_officer_tone2\":\"0814464.svg\",\"woman_police_officer_medium_light_skin_tone\":\"0814464.svg\",\"woman_police_officer_tone3\":\"feba5e2.svg\",\"woman_police_officer_medium_skin_tone\":\"feba5e2.svg\",\"woman_police_officer_tone4\":\"bc488b0.svg\",\"woman_police_officer_medium_dark_skin_tone\":\"bc488b0.svg\",\"woman_police_officer_tone5\":\"fe6c71e.svg\",\"woman_police_officer_dark_skin_tone\":\"fe6c71e.svg\",\"man_police_officer\":\"5917c6e.svg\",\"man_police_officer_tone1\":\"d4802b5.svg\",\"man_police_officer_light_skin_tone\":\"d4802b5.svg\",\"man_police_officer_tone2\":\"7f1a418.svg\",\"man_police_officer_medium_light_skin_tone\":\"7f1a418.svg\",\"man_police_officer_tone3\":\"a2b980e.svg\",\"man_police_officer_medium_skin_tone\":\"a2b980e.svg\",\"man_police_officer_tone4\":\"a4d52ea.svg\",\"man_police_officer_medium_dark_skin_tone\":\"a4d52ea.svg\",\"man_police_officer_tone5\":\"266cefb.svg\",\"man_police_officer_dark_skin_tone\":\"266cefb.svg\",\"construction_worker\":\"0f13c5b.svg\",\"construction_worker_tone1\":\"34c2a70.svg\",\"construction_worker_tone2\":\"f4168f1.svg\",\"construction_worker_tone3\":\"8b0acfa.svg\",\"construction_worker_tone4\":\"8b5b749.svg\",\"construction_worker_tone5\":\"5839b6c.svg\",\"woman_construction_worker\":\"0351b72.svg\",\"woman_construction_worker_tone1\":\"dc63f79.svg\",\"woman_construction_worker_light_skin_tone\":\"dc63f79.svg\",\"woman_construction_worker_tone2\":\"cb23235.svg\",\"woman_construction_worker_medium_light_skin_tone\":\"cb23235.svg\",\"woman_construction_worker_tone3\":\"a1ad1da.svg\",\"woman_construction_worker_medium_skin_tone\":\"a1ad1da.svg\",\"woman_construction_worker_tone4\":\"0a08c63.svg\",\"woman_construction_worker_medium_dark_skin_tone\":\"0a08c63.svg\",\"woman_construction_worker_tone5\":\"8ee3406.svg\",\"woman_construction_worker_dark_skin_tone\":\"8ee3406.svg\",\"man_construction_worker\":\"d2bfd43.svg\",\"man_construction_worker_tone1\":\"6dcd0a6.svg\",\"man_construction_worker_light_skin_tone\":\"6dcd0a6.svg\",\"man_construction_worker_tone2\":\"c0c7334.svg\",\"man_construction_worker_medium_light_skin_tone\":\"c0c7334.svg\",\"man_construction_worker_tone3\":\"2825484.svg\",\"man_construction_worker_medium_skin_tone\":\"2825484.svg\",\"man_construction_worker_tone4\":\"c7a36a5.svg\",\"man_construction_worker_medium_dark_skin_tone\":\"c7a36a5.svg\",\"man_construction_worker_tone5\":\"bfa8937.svg\",\"man_construction_worker_dark_skin_tone\":\"bfa8937.svg\",\"guard\":\"308ae99.svg\",\"guardsman\":\"308ae99.svg\",\"guard_tone1\":\"4026dd4.svg\",\"guardsman_tone1\":\"4026dd4.svg\",\"guard_tone2\":\"fe4ddb5.svg\",\"guardsman_tone2\":\"fe4ddb5.svg\",\"guard_tone3\":\"23dac93.svg\",\"guardsman_tone3\":\"23dac93.svg\",\"guard_tone4\":\"2f7282c.svg\",\"guardsman_tone4\":\"2f7282c.svg\",\"guard_tone5\":\"bdb030d.svg\",\"guardsman_tone5\":\"bdb030d.svg\",\"woman_guard\":\"6dcbee7.svg\",\"woman_guard_tone1\":\"bc1720a.svg\",\"woman_guard_light_skin_tone\":\"bc1720a.svg\",\"woman_guard_tone2\":\"670ae61.svg\",\"woman_guard_medium_light_skin_tone\":\"670ae61.svg\",\"woman_guard_tone3\":\"79abf2c.svg\",\"woman_guard_medium_skin_tone\":\"79abf2c.svg\",\"woman_guard_tone4\":\"b96832b.svg\",\"woman_guard_medium_dark_skin_tone\":\"b96832b.svg\",\"woman_guard_tone5\":\"19ab501.svg\",\"woman_guard_dark_skin_tone\":\"19ab501.svg\",\"man_guard\":\"18b010d.svg\",\"man_guard_tone1\":\"107e2f4.svg\",\"man_guard_light_skin_tone\":\"107e2f4.svg\",\"man_guard_tone2\":\"7b02510.svg\",\"man_guard_medium_light_skin_tone\":\"7b02510.svg\",\"man_guard_tone3\":\"bb1fa80.svg\",\"man_guard_medium_skin_tone\":\"bb1fa80.svg\",\"man_guard_tone4\":\"f95cebf.svg\",\"man_guard_medium_dark_skin_tone\":\"f95cebf.svg\",\"man_guard_tone5\":\"80c0660.svg\",\"man_guard_dark_skin_tone\":\"80c0660.svg\",\"detective\":\"92f451b.svg\",\"spy\":\"92f451b.svg\",\"sleuth_or_spy\":\"92f451b.svg\",\"detective_tone1\":\"acdb648.svg\",\"spy_tone1\":\"acdb648.svg\",\"sleuth_or_spy_tone1\":\"acdb648.svg\",\"detective_tone2\":\"ebbf06e.svg\",\"spy_tone2\":\"ebbf06e.svg\",\"sleuth_or_spy_tone2\":\"ebbf06e.svg\",\"detective_tone3\":\"481c8c7.svg\",\"spy_tone3\":\"481c8c7.svg\",\"sleuth_or_spy_tone3\":\"481c8c7.svg\",\"detective_tone4\":\"28ae476.svg\",\"spy_tone4\":\"28ae476.svg\",\"sleuth_or_spy_tone4\":\"28ae476.svg\",\"detective_tone5\":\"234d7e5.svg\",\"spy_tone5\":\"234d7e5.svg\",\"sleuth_or_spy_tone5\":\"234d7e5.svg\",\"woman_detective\":\"4a3753b.svg\",\"woman_detective_tone1\":\"0ddd142.svg\",\"woman_detective_light_skin_tone\":\"0ddd142.svg\",\"woman_detective_tone2\":\"4bc3fe3.svg\",\"woman_detective_medium_light_skin_tone\":\"4bc3fe3.svg\",\"woman_detective_tone3\":\"344d59f.svg\",\"woman_detective_medium_skin_tone\":\"344d59f.svg\",\"woman_detective_tone4\":\"4347e0f.svg\",\"woman_detective_medium_dark_skin_tone\":\"4347e0f.svg\",\"woman_detective_tone5\":\"b9b28fc.svg\",\"woman_detective_dark_skin_tone\":\"b9b28fc.svg\",\"man_detective\":\"2391fd5.svg\",\"man_detective_tone1\":\"c2d5db0.svg\",\"man_detective_light_skin_tone\":\"c2d5db0.svg\",\"man_detective_tone2\":\"68a9ab5.svg\",\"man_detective_medium_light_skin_tone\":\"68a9ab5.svg\",\"man_detective_tone3\":\"9969bab.svg\",\"man_detective_medium_skin_tone\":\"9969bab.svg\",\"man_detective_tone4\":\"cd65781.svg\",\"man_detective_medium_dark_skin_tone\":\"cd65781.svg\",\"man_detective_tone5\":\"69b5578.svg\",\"man_detective_dark_skin_tone\":\"69b5578.svg\",\"health_worker\":\"6b32127.svg\",\"health_worker_tone1\":\"fb3f046.svg\",\"health_worker_light_skin_tone\":\"fb3f046.svg\",\"health_worker_tone2\":\"06fccf8.svg\",\"health_worker_medium_light_skin_tone\":\"06fccf8.svg\",\"health_worker_tone3\":\"90d36ab.svg\",\"health_worker_medium_skin_tone\":\"90d36ab.svg\",\"health_worker_tone4\":\"1c1963d.svg\",\"health_worker_medium_dark_skin_tone\":\"1c1963d.svg\",\"health_worker_tone5\":\"adec8f8.svg\",\"health_worker_dark_skin_tone\":\"adec8f8.svg\",\"woman_health_worker\":\"907cb95.svg\",\"woman_health_worker_tone1\":\"b877224.svg\",\"woman_health_worker_light_skin_tone\":\"b877224.svg\",\"woman_health_worker_tone2\":\"ccb3ee5.svg\",\"woman_health_worker_medium_light_skin_tone\":\"ccb3ee5.svg\",\"woman_health_worker_tone3\":\"b7f2d7f.svg\",\"woman_health_worker_medium_skin_tone\":\"b7f2d7f.svg\",\"woman_health_worker_tone4\":\"e5b097f.svg\",\"woman_health_worker_medium_dark_skin_tone\":\"e5b097f.svg\",\"woman_health_worker_tone5\":\"e50ddd0.svg\",\"woman_health_worker_dark_skin_tone\":\"e50ddd0.svg\",\"man_health_worker\":\"1a4fb77.svg\",\"man_health_worker_tone1\":\"0281347.svg\",\"man_health_worker_light_skin_tone\":\"0281347.svg\",\"man_health_worker_tone2\":\"fb9a511.svg\",\"man_health_worker_medium_light_skin_tone\":\"fb9a511.svg\",\"man_health_worker_tone3\":\"d29ffa8.svg\",\"man_health_worker_medium_skin_tone\":\"d29ffa8.svg\",\"man_health_worker_tone4\":\"8b7e9fa.svg\",\"man_health_worker_medium_dark_skin_tone\":\"8b7e9fa.svg\",\"man_health_worker_tone5\":\"c666f32.svg\",\"man_health_worker_dark_skin_tone\":\"c666f32.svg\",\"farmer\":\"ce590f6.svg\",\"farmer_tone1\":\"7a4bff9.svg\",\"farmer_light_skin_tone\":\"7a4bff9.svg\",\"farmer_tone2\":\"7a37abb.svg\",\"farmer_medium_light_skin_tone\":\"7a37abb.svg\",\"farmer_tone3\":\"035ea17.svg\",\"farmer_medium_skin_tone\":\"035ea17.svg\",\"farmer_tone4\":\"cc52f4d.svg\",\"farmer_medium_dark_skin_tone\":\"cc52f4d.svg\",\"farmer_tone5\":\"0acd150.svg\",\"farmer_dark_skin_tone\":\"0acd150.svg\",\"woman_farmer\":\"56ec7b4.svg\",\"woman_farmer_tone1\":\"51f3c57.svg\",\"woman_farmer_light_skin_tone\":\"51f3c57.svg\",\"woman_farmer_tone2\":\"33d3b56.svg\",\"woman_farmer_medium_light_skin_tone\":\"33d3b56.svg\",\"woman_farmer_tone3\":\"92462af.svg\",\"woman_farmer_medium_skin_tone\":\"92462af.svg\",\"woman_farmer_tone4\":\"d7eb2bd.svg\",\"woman_farmer_medium_dark_skin_tone\":\"d7eb2bd.svg\",\"woman_farmer_tone5\":\"eb3a9fe.svg\",\"woman_farmer_dark_skin_tone\":\"eb3a9fe.svg\",\"man_farmer\":\"0b4d127.svg\",\"man_farmer_tone1\":\"d54fbc7.svg\",\"man_farmer_light_skin_tone\":\"d54fbc7.svg\",\"man_farmer_tone2\":\"7b938bc.svg\",\"man_farmer_medium_light_skin_tone\":\"7b938bc.svg\",\"man_farmer_tone3\":\"26600cd.svg\",\"man_farmer_medium_skin_tone\":\"26600cd.svg\",\"man_farmer_tone4\":\"4efb06d.svg\",\"man_farmer_medium_dark_skin_tone\":\"4efb06d.svg\",\"man_farmer_tone5\":\"6e76064.svg\",\"man_farmer_dark_skin_tone\":\"6e76064.svg\",\"cook\":\"a4a63f8.svg\",\"cook_tone1\":\"f8bd45b.svg\",\"cook_light_skin_tone\":\"f8bd45b.svg\",\"cook_tone2\":\"241bd68.svg\",\"cook_medium_light_skin_tone\":\"241bd68.svg\",\"cook_tone3\":\"9bff94a.svg\",\"cook_medium_skin_tone\":\"9bff94a.svg\",\"cook_tone4\":\"89acdc9.svg\",\"cook_medium_dark_skin_tone\":\"89acdc9.svg\",\"cook_tone5\":\"557f06f.svg\",\"cook_dark_skin_tone\":\"557f06f.svg\",\"woman_cook\":\"e164261.svg\",\"woman_cook_tone1\":\"4dd310d.svg\",\"woman_cook_light_skin_tone\":\"4dd310d.svg\",\"woman_cook_tone2\":\"dde8ca0.svg\",\"woman_cook_medium_light_skin_tone\":\"dde8ca0.svg\",\"woman_cook_tone3\":\"280c136.svg\",\"woman_cook_medium_skin_tone\":\"280c136.svg\",\"woman_cook_tone4\":\"1bad9d6.svg\",\"woman_cook_medium_dark_skin_tone\":\"1bad9d6.svg\",\"woman_cook_tone5\":\"a7d627f.svg\",\"woman_cook_dark_skin_tone\":\"a7d627f.svg\",\"man_cook\":\"3361675.svg\",\"man_cook_tone1\":\"ead2696.svg\",\"man_cook_light_skin_tone\":\"ead2696.svg\",\"man_cook_tone2\":\"e881854.svg\",\"man_cook_medium_light_skin_tone\":\"e881854.svg\",\"man_cook_tone3\":\"291f0e8.svg\",\"man_cook_medium_skin_tone\":\"291f0e8.svg\",\"man_cook_tone4\":\"a071615.svg\",\"man_cook_medium_dark_skin_tone\":\"a071615.svg\",\"man_cook_tone5\":\"bb826a2.svg\",\"man_cook_dark_skin_tone\":\"bb826a2.svg\",\"student\":\"0850b86.svg\",\"student_tone1\":\"13422e9.svg\",\"student_light_skin_tone\":\"13422e9.svg\",\"student_tone2\":\"9df70e3.svg\",\"student_medium_light_skin_tone\":\"9df70e3.svg\",\"student_tone3\":\"4abba29.svg\",\"student_medium_skin_tone\":\"4abba29.svg\",\"student_tone4\":\"29e7950.svg\",\"student_medium_dark_skin_tone\":\"29e7950.svg\",\"student_tone5\":\"334db35.svg\",\"student_dark_skin_tone\":\"334db35.svg\",\"woman_student\":\"d08ef82.svg\",\"woman_student_tone1\":\"22ca3f8.svg\",\"woman_student_light_skin_tone\":\"22ca3f8.svg\",\"woman_student_tone2\":\"c1ef510.svg\",\"woman_student_medium_light_skin_tone\":\"c1ef510.svg\",\"woman_student_tone3\":\"6d41fb5.svg\",\"woman_student_medium_skin_tone\":\"6d41fb5.svg\",\"woman_student_tone4\":\"66ab761.svg\",\"woman_student_medium_dark_skin_tone\":\"66ab761.svg\",\"woman_student_tone5\":\"e9fa0e7.svg\",\"woman_student_dark_skin_tone\":\"e9fa0e7.svg\",\"man_student\":\"12a1dd0.svg\",\"man_student_tone1\":\"b571bb8.svg\",\"man_student_light_skin_tone\":\"b571bb8.svg\",\"man_student_tone2\":\"afeb55d.svg\",\"man_student_medium_light_skin_tone\":\"afeb55d.svg\",\"man_student_tone3\":\"8362db4.svg\",\"man_student_medium_skin_tone\":\"8362db4.svg\",\"man_student_tone4\":\"642e769.svg\",\"man_student_medium_dark_skin_tone\":\"642e769.svg\",\"man_student_tone5\":\"ffdeacf.svg\",\"man_student_dark_skin_tone\":\"ffdeacf.svg\",\"singer\":\"1b13111.svg\",\"singer_tone1\":\"a2b97f0.svg\",\"singer_light_skin_tone\":\"a2b97f0.svg\",\"singer_tone2\":\"d278abb.svg\",\"singer_medium_light_skin_tone\":\"d278abb.svg\",\"singer_tone3\":\"447dbe5.svg\",\"singer_medium_skin_tone\":\"447dbe5.svg\",\"singer_tone4\":\"0857ac9.svg\",\"singer_medium_dark_skin_tone\":\"0857ac9.svg\",\"singer_tone5\":\"6cded83.svg\",\"singer_dark_skin_tone\":\"6cded83.svg\",\"woman_singer\":\"698a172.svg\",\"woman_singer_tone1\":\"5a06595.svg\",\"woman_singer_light_skin_tone\":\"5a06595.svg\",\"woman_singer_tone2\":\"5262515.svg\",\"woman_singer_medium_light_skin_tone\":\"5262515.svg\",\"woman_singer_tone3\":\"b68f63b.svg\",\"woman_singer_medium_skin_tone\":\"b68f63b.svg\",\"woman_singer_tone4\":\"d0b4e7a.svg\",\"woman_singer_medium_dark_skin_tone\":\"d0b4e7a.svg\",\"woman_singer_tone5\":\"fe5edce.svg\",\"woman_singer_dark_skin_tone\":\"fe5edce.svg\",\"man_singer\":\"8f9fa74.svg\",\"man_singer_tone1\":\"f25f21d.svg\",\"man_singer_light_skin_tone\":\"f25f21d.svg\",\"man_singer_tone2\":\"3375b10.svg\",\"man_singer_medium_light_skin_tone\":\"3375b10.svg\",\"man_singer_tone3\":\"aed9010.svg\",\"man_singer_medium_skin_tone\":\"aed9010.svg\",\"man_singer_tone4\":\"684e6dd.svg\",\"man_singer_medium_dark_skin_tone\":\"684e6dd.svg\",\"man_singer_tone5\":\"71eed43.svg\",\"man_singer_dark_skin_tone\":\"71eed43.svg\",\"teacher\":\"3f05ac8.svg\",\"teacher_tone1\":\"547622b.svg\",\"teacher_light_skin_tone\":\"547622b.svg\",\"teacher_tone2\":\"73dda57.svg\",\"teacher_medium_light_skin_tone\":\"73dda57.svg\",\"teacher_tone3\":\"d37c8c4.svg\",\"teacher_medium_skin_tone\":\"d37c8c4.svg\",\"teacher_tone4\":\"22b0ccd.svg\",\"teacher_medium_dark_skin_tone\":\"22b0ccd.svg\",\"teacher_tone5\":\"4c83bb0.svg\",\"teacher_dark_skin_tone\":\"4c83bb0.svg\",\"woman_teacher\":\"69ffebb.svg\",\"woman_teacher_tone1\":\"8a52eb0.svg\",\"woman_teacher_light_skin_tone\":\"8a52eb0.svg\",\"woman_teacher_tone2\":\"a5753b7.svg\",\"woman_teacher_medium_light_skin_tone\":\"a5753b7.svg\",\"woman_teacher_tone3\":\"2d95430.svg\",\"woman_teacher_medium_skin_tone\":\"2d95430.svg\",\"woman_teacher_tone4\":\"e816c4a.svg\",\"woman_teacher_medium_dark_skin_tone\":\"e816c4a.svg\",\"woman_teacher_tone5\":\"998dd7e.svg\",\"woman_teacher_dark_skin_tone\":\"998dd7e.svg\",\"man_teacher\":\"324b2b6.svg\",\"man_teacher_tone1\":\"8575f3e.svg\",\"man_teacher_light_skin_tone\":\"8575f3e.svg\",\"man_teacher_tone2\":\"90504c4.svg\",\"man_teacher_medium_light_skin_tone\":\"90504c4.svg\",\"man_teacher_tone3\":\"655137d.svg\",\"man_teacher_medium_skin_tone\":\"655137d.svg\",\"man_teacher_tone4\":\"0b1145e.svg\",\"man_teacher_medium_dark_skin_tone\":\"0b1145e.svg\",\"man_teacher_tone5\":\"28f1192.svg\",\"man_teacher_dark_skin_tone\":\"28f1192.svg\",\"factory_worker\":\"1022142.svg\",\"factory_worker_tone1\":\"edf101c.svg\",\"factory_worker_light_skin_tone\":\"edf101c.svg\",\"factory_worker_tone2\":\"281146d.svg\",\"factory_worker_medium_light_skin_tone\":\"281146d.svg\",\"factory_worker_tone3\":\"ec2df97.svg\",\"factory_worker_medium_skin_tone\":\"ec2df97.svg\",\"factory_worker_tone4\":\"88e3a63.svg\",\"factory_worker_medium_dark_skin_tone\":\"88e3a63.svg\",\"factory_worker_tone5\":\"b74d155.svg\",\"factory_worker_dark_skin_tone\":\"b74d155.svg\",\"woman_factory_worker\":\"d345c63.svg\",\"woman_factory_worker_tone1\":\"688bad2.svg\",\"woman_factory_worker_light_skin_tone\":\"688bad2.svg\",\"woman_factory_worker_tone2\":\"b9093a8.svg\",\"woman_factory_worker_medium_light_skin_tone\":\"b9093a8.svg\",\"woman_factory_worker_tone3\":\"5b07641.svg\",\"woman_factory_worker_medium_skin_tone\":\"5b07641.svg\",\"woman_factory_worker_tone4\":\"1016e81.svg\",\"woman_factory_worker_medium_dark_skin_tone\":\"1016e81.svg\",\"woman_factory_worker_tone5\":\"6b92c08.svg\",\"woman_factory_worker_dark_skin_tone\":\"6b92c08.svg\",\"man_factory_worker\":\"48e1ea2.svg\",\"man_factory_worker_tone1\":\"5a94900.svg\",\"man_factory_worker_light_skin_tone\":\"5a94900.svg\",\"man_factory_worker_tone2\":\"11a4f9e.svg\",\"man_factory_worker_medium_light_skin_tone\":\"11a4f9e.svg\",\"man_factory_worker_tone3\":\"dc7ee23.svg\",\"man_factory_worker_medium_skin_tone\":\"dc7ee23.svg\",\"man_factory_worker_tone4\":\"df07e07.svg\",\"man_factory_worker_medium_dark_skin_tone\":\"df07e07.svg\",\"man_factory_worker_tone5\":\"4b6bb27.svg\",\"man_factory_worker_dark_skin_tone\":\"4b6bb27.svg\",\"technologist\":\"180fac5.svg\",\"technologist_tone1\":\"e68839b.svg\",\"technologist_light_skin_tone\":\"e68839b.svg\",\"technologist_tone2\":\"4cc9d44.svg\",\"technologist_medium_light_skin_tone\":\"4cc9d44.svg\",\"technologist_tone3\":\"4475992.svg\",\"technologist_medium_skin_tone\":\"4475992.svg\",\"technologist_tone4\":\"c681683.svg\",\"technologist_medium_dark_skin_tone\":\"c681683.svg\",\"technologist_tone5\":\"328d629.svg\",\"technologist_dark_skin_tone\":\"328d629.svg\",\"woman_technologist\":\"96ff8eb.svg\",\"woman_technologist_tone1\":\"21d8aae.svg\",\"woman_technologist_light_skin_tone\":\"21d8aae.svg\",\"woman_technologist_tone2\":\"1cc6fb3.svg\",\"woman_technologist_medium_light_skin_tone\":\"1cc6fb3.svg\",\"woman_technologist_tone3\":\"ad8f99a.svg\",\"woman_technologist_medium_skin_tone\":\"ad8f99a.svg\",\"woman_technologist_tone4\":\"897cd9c.svg\",\"woman_technologist_medium_dark_skin_tone\":\"897cd9c.svg\",\"woman_technologist_tone5\":\"eeb6cd8.svg\",\"woman_technologist_dark_skin_tone\":\"eeb6cd8.svg\",\"man_technologist\":\"8e0d837.svg\",\"man_technologist_tone1\":\"7229031.svg\",\"man_technologist_light_skin_tone\":\"7229031.svg\",\"man_technologist_tone2\":\"adf0160.svg\",\"man_technologist_medium_light_skin_tone\":\"adf0160.svg\",\"man_technologist_tone3\":\"622261c.svg\",\"man_technologist_medium_skin_tone\":\"622261c.svg\",\"man_technologist_tone4\":\"0daf3e6.svg\",\"man_technologist_medium_dark_skin_tone\":\"0daf3e6.svg\",\"man_technologist_tone5\":\"6212e10.svg\",\"man_technologist_dark_skin_tone\":\"6212e10.svg\",\"office_worker\":\"6c1b458.svg\",\"office_worker_tone1\":\"c2d3f36.svg\",\"office_worker_light_skin_tone\":\"c2d3f36.svg\",\"office_worker_tone2\":\"552a453.svg\",\"office_worker_medium_light_skin_tone\":\"552a453.svg\",\"office_worker_tone3\":\"958ac28.svg\",\"office_worker_medium_skin_tone\":\"958ac28.svg\",\"office_worker_tone4\":\"e379783.svg\",\"office_worker_medium_dark_skin_tone\":\"e379783.svg\",\"office_worker_tone5\":\"80ce786.svg\",\"office_worker_dark_skin_tone\":\"80ce786.svg\",\"woman_office_worker\":\"489e529.svg\",\"woman_office_worker_tone1\":\"b94d93c.svg\",\"woman_office_worker_light_skin_tone\":\"b94d93c.svg\",\"woman_office_worker_tone2\":\"55d6ebc.svg\",\"woman_office_worker_medium_light_skin_tone\":\"55d6ebc.svg\",\"woman_office_worker_tone3\":\"9a3098d.svg\",\"woman_office_worker_medium_skin_tone\":\"9a3098d.svg\",\"woman_office_worker_tone4\":\"ecb8f66.svg\",\"woman_office_worker_medium_dark_skin_tone\":\"ecb8f66.svg\",\"woman_office_worker_tone5\":\"b1c480e.svg\",\"woman_office_worker_dark_skin_tone\":\"b1c480e.svg\",\"man_office_worker\":\"6c73696.svg\",\"man_office_worker_tone1\":\"0e9ee64.svg\",\"man_office_worker_light_skin_tone\":\"0e9ee64.svg\",\"man_office_worker_tone2\":\"5630728.svg\",\"man_office_worker_medium_light_skin_tone\":\"5630728.svg\",\"man_office_worker_tone3\":\"10ba092.svg\",\"man_office_worker_medium_skin_tone\":\"10ba092.svg\",\"man_office_worker_tone4\":\"d0d3184.svg\",\"man_office_worker_medium_dark_skin_tone\":\"d0d3184.svg\",\"man_office_worker_tone5\":\"f85801a.svg\",\"man_office_worker_dark_skin_tone\":\"f85801a.svg\",\"mechanic\":\"ee455f1.svg\",\"mechanic_tone1\":\"d5f36f6.svg\",\"mechanic_light_skin_tone\":\"d5f36f6.svg\",\"mechanic_tone2\":\"bd0d424.svg\",\"mechanic_medium_light_skin_tone\":\"bd0d424.svg\",\"mechanic_tone3\":\"4dcab11.svg\",\"mechanic_medium_skin_tone\":\"4dcab11.svg\",\"mechanic_tone4\":\"a79edc4.svg\",\"mechanic_medium_dark_skin_tone\":\"a79edc4.svg\",\"mechanic_tone5\":\"f515402.svg\",\"mechanic_dark_skin_tone\":\"f515402.svg\",\"woman_mechanic\":\"96e0809.svg\",\"woman_mechanic_tone1\":\"566d88c.svg\",\"woman_mechanic_light_skin_tone\":\"566d88c.svg\",\"woman_mechanic_tone2\":\"ba98536.svg\",\"woman_mechanic_medium_light_skin_tone\":\"ba98536.svg\",\"woman_mechanic_tone3\":\"0e01036.svg\",\"woman_mechanic_medium_skin_tone\":\"0e01036.svg\",\"woman_mechanic_tone4\":\"c03256d.svg\",\"woman_mechanic_medium_dark_skin_tone\":\"c03256d.svg\",\"woman_mechanic_tone5\":\"f03cd8b.svg\",\"woman_mechanic_dark_skin_tone\":\"f03cd8b.svg\",\"man_mechanic\":\"cc3ed09.svg\",\"man_mechanic_tone1\":\"d77dcc0.svg\",\"man_mechanic_light_skin_tone\":\"d77dcc0.svg\",\"man_mechanic_tone2\":\"69d531c.svg\",\"man_mechanic_medium_light_skin_tone\":\"69d531c.svg\",\"man_mechanic_tone3\":\"db68d58.svg\",\"man_mechanic_medium_skin_tone\":\"db68d58.svg\",\"man_mechanic_tone4\":\"d1987e9.svg\",\"man_mechanic_medium_dark_skin_tone\":\"d1987e9.svg\",\"man_mechanic_tone5\":\"79cbe87.svg\",\"man_mechanic_dark_skin_tone\":\"79cbe87.svg\",\"scientist\":\"dbdb85d.svg\",\"scientist_tone1\":\"33f3bf1.svg\",\"scientist_light_skin_tone\":\"33f3bf1.svg\",\"scientist_tone2\":\"2d086a8.svg\",\"scientist_medium_light_skin_tone\":\"2d086a8.svg\",\"scientist_tone3\":\"486400e.svg\",\"scientist_medium_skin_tone\":\"486400e.svg\",\"scientist_tone4\":\"c0c96cb.svg\",\"scientist_medium_dark_skin_tone\":\"c0c96cb.svg\",\"scientist_tone5\":\"30c16d5.svg\",\"scientist_dark_skin_tone\":\"30c16d5.svg\",\"woman_scientist\":\"1e38eed.svg\",\"woman_scientist_tone1\":\"440f076.svg\",\"woman_scientist_light_skin_tone\":\"440f076.svg\",\"woman_scientist_tone2\":\"066face.svg\",\"woman_scientist_medium_light_skin_tone\":\"066face.svg\",\"woman_scientist_tone3\":\"d2ea502.svg\",\"woman_scientist_medium_skin_tone\":\"d2ea502.svg\",\"woman_scientist_tone4\":\"4015482.svg\",\"woman_scientist_medium_dark_skin_tone\":\"4015482.svg\",\"woman_scientist_tone5\":\"d943ff4.svg\",\"woman_scientist_dark_skin_tone\":\"d943ff4.svg\",\"man_scientist\":\"10538bf.svg\",\"man_scientist_tone1\":\"96213db.svg\",\"man_scientist_light_skin_tone\":\"96213db.svg\",\"man_scientist_tone2\":\"f767abd.svg\",\"man_scientist_medium_light_skin_tone\":\"f767abd.svg\",\"man_scientist_tone3\":\"0a15702.svg\",\"man_scientist_medium_skin_tone\":\"0a15702.svg\",\"man_scientist_tone4\":\"9e2db11.svg\",\"man_scientist_medium_dark_skin_tone\":\"9e2db11.svg\",\"man_scientist_tone5\":\"36c67c1.svg\",\"man_scientist_dark_skin_tone\":\"36c67c1.svg\",\"artist\":\"cf51bad.svg\",\"artist_tone1\":\"2b58f09.svg\",\"artist_light_skin_tone\":\"2b58f09.svg\",\"artist_tone2\":\"e0ba0de.svg\",\"artist_medium_light_skin_tone\":\"e0ba0de.svg\",\"artist_tone3\":\"288c495.svg\",\"artist_medium_skin_tone\":\"288c495.svg\",\"artist_tone4\":\"c0ff43a.svg\",\"artist_medium_dark_skin_tone\":\"c0ff43a.svg\",\"artist_tone5\":\"c47a742.svg\",\"artist_dark_skin_tone\":\"c47a742.svg\",\"woman_artist\":\"c2e427e.svg\",\"woman_artist_tone1\":\"dff44c7.svg\",\"woman_artist_light_skin_tone\":\"dff44c7.svg\",\"woman_artist_tone2\":\"7fe9606.svg\",\"woman_artist_medium_light_skin_tone\":\"7fe9606.svg\",\"woman_artist_tone3\":\"7a50642.svg\",\"woman_artist_medium_skin_tone\":\"7a50642.svg\",\"woman_artist_tone4\":\"6da5ebe.svg\",\"woman_artist_medium_dark_skin_tone\":\"6da5ebe.svg\",\"woman_artist_tone5\":\"d504204.svg\",\"woman_artist_dark_skin_tone\":\"d504204.svg\",\"man_artist\":\"cfe2741.svg\",\"man_artist_tone1\":\"df98294.svg\",\"man_artist_light_skin_tone\":\"df98294.svg\",\"man_artist_tone2\":\"db34dc8.svg\",\"man_artist_medium_light_skin_tone\":\"db34dc8.svg\",\"man_artist_tone3\":\"7fa36cf.svg\",\"man_artist_medium_skin_tone\":\"7fa36cf.svg\",\"man_artist_tone4\":\"256b112.svg\",\"man_artist_medium_dark_skin_tone\":\"256b112.svg\",\"man_artist_tone5\":\"c7973d8.svg\",\"man_artist_dark_skin_tone\":\"c7973d8.svg\",\"firefighter\":\"8dab584.svg\",\"firefighter_tone1\":\"c5499b3.svg\",\"firefighter_light_skin_tone\":\"c5499b3.svg\",\"firefighter_tone2\":\"3850d1a.svg\",\"firefighter_medium_light_skin_tone\":\"3850d1a.svg\",\"firefighter_tone3\":\"ed6bc04.svg\",\"firefighter_medium_skin_tone\":\"ed6bc04.svg\",\"firefighter_tone4\":\"ea27ae9.svg\",\"firefighter_medium_dark_skin_tone\":\"ea27ae9.svg\",\"firefighter_tone5\":\"39a926b.svg\",\"firefighter_dark_skin_tone\":\"39a926b.svg\",\"woman_firefighter\":\"9be3bf6.svg\",\"woman_firefighter_tone1\":\"d6f34fb.svg\",\"woman_firefighter_light_skin_tone\":\"d6f34fb.svg\",\"woman_firefighter_tone2\":\"665a6d5.svg\",\"woman_firefighter_medium_light_skin_tone\":\"665a6d5.svg\",\"woman_firefighter_tone3\":\"f4d24e1.svg\",\"woman_firefighter_medium_skin_tone\":\"f4d24e1.svg\",\"woman_firefighter_tone4\":\"be5b501.svg\",\"woman_firefighter_medium_dark_skin_tone\":\"be5b501.svg\",\"woman_firefighter_tone5\":\"4ffb181.svg\",\"woman_firefighter_dark_skin_tone\":\"4ffb181.svg\",\"man_firefighter\":\"5615861.svg\",\"man_firefighter_tone1\":\"710e509.svg\",\"man_firefighter_light_skin_tone\":\"710e509.svg\",\"man_firefighter_tone2\":\"4217476.svg\",\"man_firefighter_medium_light_skin_tone\":\"4217476.svg\",\"man_firefighter_tone3\":\"b22debb.svg\",\"man_firefighter_medium_skin_tone\":\"b22debb.svg\",\"man_firefighter_tone4\":\"d8691e8.svg\",\"man_firefighter_medium_dark_skin_tone\":\"d8691e8.svg\",\"man_firefighter_tone5\":\"9cb1c1c.svg\",\"man_firefighter_dark_skin_tone\":\"9cb1c1c.svg\",\"pilot\":\"785704c.svg\",\"pilot_tone1\":\"148b717.svg\",\"pilot_light_skin_tone\":\"148b717.svg\",\"pilot_tone2\":\"950c47d.svg\",\"pilot_medium_light_skin_tone\":\"950c47d.svg\",\"pilot_tone3\":\"8fed0c6.svg\",\"pilot_medium_skin_tone\":\"8fed0c6.svg\",\"pilot_tone4\":\"5efa2e4.svg\",\"pilot_medium_dark_skin_tone\":\"5efa2e4.svg\",\"pilot_tone5\":\"be28d19.svg\",\"pilot_dark_skin_tone\":\"be28d19.svg\",\"woman_pilot\":\"8d6bd3b.svg\",\"woman_pilot_tone1\":\"0bba5fe.svg\",\"woman_pilot_light_skin_tone\":\"0bba5fe.svg\",\"woman_pilot_tone2\":\"2c0fbfe.svg\",\"woman_pilot_medium_light_skin_tone\":\"2c0fbfe.svg\",\"woman_pilot_tone3\":\"ced65e1.svg\",\"woman_pilot_medium_skin_tone\":\"ced65e1.svg\",\"woman_pilot_tone4\":\"5a10ba1.svg\",\"woman_pilot_medium_dark_skin_tone\":\"5a10ba1.svg\",\"woman_pilot_tone5\":\"8521720.svg\",\"woman_pilot_dark_skin_tone\":\"8521720.svg\",\"man_pilot\":\"f160e27.svg\",\"man_pilot_tone1\":\"5700642.svg\",\"man_pilot_light_skin_tone\":\"5700642.svg\",\"man_pilot_tone2\":\"a355e7a.svg\",\"man_pilot_medium_light_skin_tone\":\"a355e7a.svg\",\"man_pilot_tone3\":\"0aa1b01.svg\",\"man_pilot_medium_skin_tone\":\"0aa1b01.svg\",\"man_pilot_tone4\":\"7777935.svg\",\"man_pilot_medium_dark_skin_tone\":\"7777935.svg\",\"man_pilot_tone5\":\"eb6b0a5.svg\",\"man_pilot_dark_skin_tone\":\"eb6b0a5.svg\",\"astronaut\":\"8e3de15.svg\",\"astronaut_tone1\":\"1746690.svg\",\"astronaut_light_skin_tone\":\"1746690.svg\",\"astronaut_tone2\":\"acf8752.svg\",\"astronaut_medium_light_skin_tone\":\"acf8752.svg\",\"astronaut_tone3\":\"9ce3df2.svg\",\"astronaut_medium_skin_tone\":\"9ce3df2.svg\",\"astronaut_tone4\":\"6edf598.svg\",\"astronaut_medium_dark_skin_tone\":\"6edf598.svg\",\"astronaut_tone5\":\"b187089.svg\",\"astronaut_dark_skin_tone\":\"b187089.svg\",\"woman_astronaut\":\"e761b0a.svg\",\"woman_astronaut_tone1\":\"c9ca667.svg\",\"woman_astronaut_light_skin_tone\":\"c9ca667.svg\",\"woman_astronaut_tone2\":\"1357a9b.svg\",\"woman_astronaut_medium_light_skin_tone\":\"1357a9b.svg\",\"woman_astronaut_tone3\":\"96cac7d.svg\",\"woman_astronaut_medium_skin_tone\":\"96cac7d.svg\",\"woman_astronaut_tone4\":\"98c8131.svg\",\"woman_astronaut_medium_dark_skin_tone\":\"98c8131.svg\",\"woman_astronaut_tone5\":\"28f1de1.svg\",\"woman_astronaut_dark_skin_tone\":\"28f1de1.svg\",\"man_astronaut\":\"9808aa4.svg\",\"man_astronaut_tone1\":\"3fdecd6.svg\",\"man_astronaut_light_skin_tone\":\"3fdecd6.svg\",\"man_astronaut_tone2\":\"ad74c6f.svg\",\"man_astronaut_medium_light_skin_tone\":\"ad74c6f.svg\",\"man_astronaut_tone3\":\"fba65b3.svg\",\"man_astronaut_medium_skin_tone\":\"fba65b3.svg\",\"man_astronaut_tone4\":\"cc68f55.svg\",\"man_astronaut_medium_dark_skin_tone\":\"cc68f55.svg\",\"man_astronaut_tone5\":\"6638445.svg\",\"man_astronaut_dark_skin_tone\":\"6638445.svg\",\"judge\":\"64bc381.svg\",\"judge_tone1\":\"e6f6aa9.svg\",\"judge_light_skin_tone\":\"e6f6aa9.svg\",\"judge_tone2\":\"4ea5d96.svg\",\"judge_medium_light_skin_tone\":\"4ea5d96.svg\",\"judge_tone3\":\"91a587d.svg\",\"judge_medium_skin_tone\":\"91a587d.svg\",\"judge_tone4\":\"0491570.svg\",\"judge_medium_dark_skin_tone\":\"0491570.svg\",\"judge_tone5\":\"a959700.svg\",\"judge_dark_skin_tone\":\"a959700.svg\",\"woman_judge\":\"ccf4f4a.svg\",\"woman_judge_tone1\":\"1a4affd.svg\",\"woman_judge_light_skin_tone\":\"1a4affd.svg\",\"woman_judge_tone2\":\"68cda2e.svg\",\"woman_judge_medium_light_skin_tone\":\"68cda2e.svg\",\"woman_judge_tone3\":\"761a41e.svg\",\"woman_judge_medium_skin_tone\":\"761a41e.svg\",\"woman_judge_tone4\":\"91d0ae8.svg\",\"woman_judge_medium_dark_skin_tone\":\"91d0ae8.svg\",\"woman_judge_tone5\":\"47693f0.svg\",\"woman_judge_dark_skin_tone\":\"47693f0.svg\",\"man_judge\":\"54742de.svg\",\"man_judge_tone1\":\"d6fe135.svg\",\"man_judge_light_skin_tone\":\"d6fe135.svg\",\"man_judge_tone2\":\"98d25e6.svg\",\"man_judge_medium_light_skin_tone\":\"98d25e6.svg\",\"man_judge_tone3\":\"07877f2.svg\",\"man_judge_medium_skin_tone\":\"07877f2.svg\",\"man_judge_tone4\":\"b844d09.svg\",\"man_judge_medium_dark_skin_tone\":\"b844d09.svg\",\"man_judge_tone5\":\"3f3ba5b.svg\",\"man_judge_dark_skin_tone\":\"3f3ba5b.svg\",\"person_with_veil\":\"da48cb6.svg\",\"person_with_veil_tone1\":\"5f6784e.svg\",\"person_with_veil_tone2\":\"33d1769.svg\",\"person_with_veil_tone3\":\"378ca17.svg\",\"person_with_veil_tone4\":\"5b2ccf0.svg\",\"person_with_veil_tone5\":\"ad98ee6.svg\",\"woman_with_veil\":\"eef28b9.svg\",\"woman_with_veil_tone1\":\"6d6022c.svg\",\"woman_with_veil_light_skin_tone\":\"6d6022c.svg\",\"woman_with_veil_tone2\":\"befe93a.svg\",\"woman_with_veil_medium_light_skin_tone\":\"befe93a.svg\",\"woman_with_veil_tone3\":\"4831916.svg\",\"woman_with_veil_medium_skin_tone\":\"4831916.svg\",\"woman_with_veil_tone4\":\"a6c8373.svg\",\"woman_with_veil_medium_dark_skin_tone\":\"a6c8373.svg\",\"woman_with_veil_tone5\":\"e48a636.svg\",\"woman_with_veil_dark_skin_tone\":\"e48a636.svg\",\"man_with_veil\":\"af12168.svg\",\"man_with_veil_tone1\":\"bb62ddf.svg\",\"man_with_veil_light_skin_tone\":\"bb62ddf.svg\",\"man_with_veil_tone2\":\"3c6240d.svg\",\"man_with_veil_medium_light_skin_tone\":\"3c6240d.svg\",\"man_with_veil_tone3\":\"cee8ac2.svg\",\"man_with_veil_medium_skin_tone\":\"cee8ac2.svg\",\"man_with_veil_tone4\":\"2eccab7.svg\",\"man_with_veil_medium_dark_skin_tone\":\"2eccab7.svg\",\"man_with_veil_tone5\":\"03e1c14.svg\",\"man_with_veil_dark_skin_tone\":\"03e1c14.svg\",\"person_in_tuxedo\":\"ce76b6f.svg\",\"person_in_tuxedo_tone1\":\"02ac1d5.svg\",\"tuxedo_tone1\":\"02ac1d5.svg\",\"person_in_tuxedo_tone2\":\"6c6a785.svg\",\"tuxedo_tone2\":\"6c6a785.svg\",\"person_in_tuxedo_tone3\":\"102177c.svg\",\"tuxedo_tone3\":\"102177c.svg\",\"person_in_tuxedo_tone4\":\"de81b72.svg\",\"tuxedo_tone4\":\"de81b72.svg\",\"person_in_tuxedo_tone5\":\"4f9a016.svg\",\"tuxedo_tone5\":\"4f9a016.svg\",\"woman_in_tuxedo\":\"1b4c556.svg\",\"woman_in_tuxedo_tone1\":\"aebb06c.svg\",\"woman_in_tuxedo_light_skin_tone\":\"aebb06c.svg\",\"woman_in_tuxedo_tone2\":\"d4f9c94.svg\",\"woman_in_tuxedo_medium_light_skin_tone\":\"d4f9c94.svg\",\"woman_in_tuxedo_tone3\":\"fc516a4.svg\",\"woman_in_tuxedo_medium_skin_tone\":\"fc516a4.svg\",\"woman_in_tuxedo_tone4\":\"783e4d6.svg\",\"woman_in_tuxedo_medium_dark_skin_tone\":\"783e4d6.svg\",\"woman_in_tuxedo_tone5\":\"184b3ea.svg\",\"woman_in_tuxedo_dark_skin_tone\":\"184b3ea.svg\",\"man_in_tuxedo\":\"e36ceab.svg\",\"man_in_tuxedo_tone1\":\"e499807.svg\",\"man_in_tuxedo_light_skin_tone\":\"e499807.svg\",\"man_in_tuxedo_tone2\":\"98e1f5a.svg\",\"man_in_tuxedo_medium_light_skin_tone\":\"98e1f5a.svg\",\"man_in_tuxedo_tone3\":\"b2a0f7f.svg\",\"man_in_tuxedo_medium_skin_tone\":\"b2a0f7f.svg\",\"man_in_tuxedo_tone4\":\"ee694bc.svg\",\"man_in_tuxedo_medium_dark_skin_tone\":\"ee694bc.svg\",\"man_in_tuxedo_tone5\":\"088b13d.svg\",\"man_in_tuxedo_dark_skin_tone\":\"088b13d.svg\",\"princess\":\"aaff7f9.svg\",\"princess_tone1\":\"38e308a.svg\",\"princess_tone2\":\"f71896c.svg\",\"princess_tone3\":\"67a69cf.svg\",\"princess_tone4\":\"93458e2.svg\",\"princess_tone5\":\"3875fb5.svg\",\"prince\":\"9134687.svg\",\"prince_tone1\":\"d82092a.svg\",\"prince_tone2\":\"84b86f2.svg\",\"prince_tone3\":\"e91494a.svg\",\"prince_tone4\":\"bbe3e3d.svg\",\"prince_tone5\":\"c67979c.svg\",\"superhero\":\"2a7cb83.svg\",\"superhero_tone1\":\"2a281d0.svg\",\"superhero_light_skin_tone\":\"2a281d0.svg\",\"superhero_tone2\":\"be8b52a.svg\",\"superhero_medium_light_skin_tone\":\"be8b52a.svg\",\"superhero_tone3\":\"84e7eff.svg\",\"superhero_medium_skin_tone\":\"84e7eff.svg\",\"superhero_tone4\":\"fb4d597.svg\",\"superhero_medium_dark_skin_tone\":\"fb4d597.svg\",\"superhero_tone5\":\"2dcafca.svg\",\"superhero_dark_skin_tone\":\"2dcafca.svg\",\"woman_superhero\":\"5f6874f.svg\",\"woman_superhero_tone1\":\"bfa062e.svg\",\"woman_superhero_light_skin_tone\":\"bfa062e.svg\",\"woman_superhero_tone2\":\"01ee993.svg\",\"woman_superhero_medium_light_skin_tone\":\"01ee993.svg\",\"woman_superhero_tone3\":\"b85e3bb.svg\",\"woman_superhero_medium_skin_tone\":\"b85e3bb.svg\",\"woman_superhero_tone4\":\"530fa21.svg\",\"woman_superhero_medium_dark_skin_tone\":\"530fa21.svg\",\"woman_superhero_tone5\":\"3d099c0.svg\",\"woman_superhero_dark_skin_tone\":\"3d099c0.svg\",\"man_superhero\":\"3d31512.svg\",\"man_superhero_tone1\":\"4bb6671.svg\",\"man_superhero_light_skin_tone\":\"4bb6671.svg\",\"man_superhero_tone2\":\"a3d233c.svg\",\"man_superhero_medium_light_skin_tone\":\"a3d233c.svg\",\"man_superhero_tone3\":\"a32fc96.svg\",\"man_superhero_medium_skin_tone\":\"a32fc96.svg\",\"man_superhero_tone4\":\"715306d.svg\",\"man_superhero_medium_dark_skin_tone\":\"715306d.svg\",\"man_superhero_tone5\":\"d1e46ec.svg\",\"man_superhero_dark_skin_tone\":\"d1e46ec.svg\",\"supervillain\":\"47d4ea8.svg\",\"supervillain_tone1\":\"68926de.svg\",\"supervillain_light_skin_tone\":\"68926de.svg\",\"supervillain_tone2\":\"08b55bb.svg\",\"supervillain_medium_light_skin_tone\":\"08b55bb.svg\",\"supervillain_tone3\":\"d5258a0.svg\",\"supervillain_medium_skin_tone\":\"d5258a0.svg\",\"supervillain_tone4\":\"9d0e6a0.svg\",\"supervillain_medium_dark_skin_tone\":\"9d0e6a0.svg\",\"supervillain_tone5\":\"f7a5251.svg\",\"supervillain_dark_skin_tone\":\"f7a5251.svg\",\"woman_supervillain\":\"f98a12a.svg\",\"woman_supervillain_tone1\":\"0ea6f73.svg\",\"woman_supervillain_light_skin_tone\":\"0ea6f73.svg\",\"woman_supervillain_tone2\":\"42bc4a0.svg\",\"woman_supervillain_medium_light_skin_tone\":\"42bc4a0.svg\",\"woman_supervillain_tone3\":\"acc45b1.svg\",\"woman_supervillain_medium_skin_tone\":\"acc45b1.svg\",\"woman_supervillain_tone4\":\"547f08b.svg\",\"woman_supervillain_medium_dark_skin_tone\":\"547f08b.svg\",\"woman_supervillain_tone5\":\"26d4e57.svg\",\"woman_supervillain_dark_skin_tone\":\"26d4e57.svg\",\"man_supervillain\":\"94811ca.svg\",\"man_supervillain_tone1\":\"7d8c99e.svg\",\"man_supervillain_light_skin_tone\":\"7d8c99e.svg\",\"man_supervillain_tone2\":\"d01d27c.svg\",\"man_supervillain_medium_light_skin_tone\":\"d01d27c.svg\",\"man_supervillain_tone3\":\"e4707e4.svg\",\"man_supervillain_medium_skin_tone\":\"e4707e4.svg\",\"man_supervillain_tone4\":\"7704ce8.svg\",\"man_supervillain_medium_dark_skin_tone\":\"7704ce8.svg\",\"man_supervillain_tone5\":\"68ae7ed.svg\",\"man_supervillain_dark_skin_tone\":\"68ae7ed.svg\",\"ninja\":\"d001f14.svg\",\"ninja_tone1\":\"f86f7d0.svg\",\"ninja_light_skin_tone\":\"f86f7d0.svg\",\"ninja_tone2\":\"6b1255b.svg\",\"ninja_medium_light_skin_tone\":\"6b1255b.svg\",\"ninja_tone3\":\"1753fa5.svg\",\"ninja_medium_skin_tone\":\"1753fa5.svg\",\"ninja_tone4\":\"2fbc364.svg\",\"ninja_medium_dark_skin_tone\":\"2fbc364.svg\",\"ninja_tone5\":\"ab7ffad.svg\",\"ninja_dark_skin_tone\":\"ab7ffad.svg\",\"mx_claus\":\"a43f217.svg\",\"mx_claus_tone1\":\"a87d0a4.svg\",\"mx_claus_light_skin_tone\":\"a87d0a4.svg\",\"mx_claus_tone2\":\"2fbb54d.svg\",\"mx_claus_medium_light_skin_tone\":\"2fbb54d.svg\",\"mx_claus_tone3\":\"dab90e3.svg\",\"mx_claus_medium_skin_tone\":\"dab90e3.svg\",\"mx_claus_tone4\":\"1f91eef.svg\",\"mx_claus_medium_dark_skin_tone\":\"1f91eef.svg\",\"mx_claus_tone5\":\"6eb0eda.svg\",\"mx_claus_dark_skin_tone\":\"6eb0eda.svg\",\"mrs_claus\":\"6fbfdf1.svg\",\"mother_christmas\":\"6fbfdf1.svg\",\"mrs_claus_tone1\":\"78605ec.svg\",\"mother_christmas_tone1\":\"78605ec.svg\",\"mrs_claus_tone2\":\"402cdef.svg\",\"mother_christmas_tone2\":\"402cdef.svg\",\"mrs_claus_tone3\":\"f00b9d1.svg\",\"mother_christmas_tone3\":\"f00b9d1.svg\",\"mrs_claus_tone4\":\"6f2ec41.svg\",\"mother_christmas_tone4\":\"6f2ec41.svg\",\"mrs_claus_tone5\":\"65fc4ad.svg\",\"mother_christmas_tone5\":\"65fc4ad.svg\",\"santa\":\"3c0da1a.svg\",\"santa_tone1\":\"515eeb5.svg\",\"santa_tone2\":\"8efe1a2.svg\",\"santa_tone3\":\"bf4fd7b.svg\",\"santa_tone4\":\"80f1e35.svg\",\"santa_tone5\":\"3fcedda.svg\",\"mage\":\"35c7dd0.svg\",\"mage_tone1\":\"1e804b7.svg\",\"mage_light_skin_tone\":\"1e804b7.svg\",\"mage_tone2\":\"cf5a715.svg\",\"mage_medium_light_skin_tone\":\"cf5a715.svg\",\"mage_tone3\":\"28c4572.svg\",\"mage_medium_skin_tone\":\"28c4572.svg\",\"mage_tone4\":\"f77ab6f.svg\",\"mage_medium_dark_skin_tone\":\"f77ab6f.svg\",\"mage_tone5\":\"ece463d.svg\",\"mage_dark_skin_tone\":\"ece463d.svg\",\"woman_mage\":\"e04c248.svg\",\"woman_mage_tone1\":\"e0aa54d.svg\",\"woman_mage_light_skin_tone\":\"e0aa54d.svg\",\"woman_mage_tone2\":\"108feae.svg\",\"woman_mage_medium_light_skin_tone\":\"108feae.svg\",\"woman_mage_tone3\":\"7338a57.svg\",\"woman_mage_medium_skin_tone\":\"7338a57.svg\",\"woman_mage_tone4\":\"8585330.svg\",\"woman_mage_medium_dark_skin_tone\":\"8585330.svg\",\"woman_mage_tone5\":\"bbf1ed6.svg\",\"woman_mage_dark_skin_tone\":\"bbf1ed6.svg\",\"man_mage\":\"bfbfcda.svg\",\"man_mage_tone1\":\"fb1d8a3.svg\",\"man_mage_light_skin_tone\":\"fb1d8a3.svg\",\"man_mage_tone2\":\"510b86b.svg\",\"man_mage_medium_light_skin_tone\":\"510b86b.svg\",\"man_mage_tone3\":\"970876e.svg\",\"man_mage_medium_skin_tone\":\"970876e.svg\",\"man_mage_tone4\":\"dd2878a.svg\",\"man_mage_medium_dark_skin_tone\":\"dd2878a.svg\",\"man_mage_tone5\":\"c8cd380.svg\",\"man_mage_dark_skin_tone\":\"c8cd380.svg\",\"elf\":\"51f107b.svg\",\"elf_tone1\":\"fdd331a.svg\",\"elf_light_skin_tone\":\"fdd331a.svg\",\"elf_tone2\":\"9e14b16.svg\",\"elf_medium_light_skin_tone\":\"9e14b16.svg\",\"elf_tone3\":\"188b33c.svg\",\"elf_medium_skin_tone\":\"188b33c.svg\",\"elf_tone4\":\"0fc6b11.svg\",\"elf_medium_dark_skin_tone\":\"0fc6b11.svg\",\"elf_tone5\":\"208e35d.svg\",\"elf_dark_skin_tone\":\"208e35d.svg\",\"woman_elf\":\"019283b.svg\",\"woman_elf_tone1\":\"e3efdd8.svg\",\"woman_elf_light_skin_tone\":\"e3efdd8.svg\",\"woman_elf_tone2\":\"a45cfcf.svg\",\"woman_elf_medium_light_skin_tone\":\"a45cfcf.svg\",\"woman_elf_tone3\":\"b17534c.svg\",\"woman_elf_medium_skin_tone\":\"b17534c.svg\",\"woman_elf_tone4\":\"9512c8c.svg\",\"woman_elf_medium_dark_skin_tone\":\"9512c8c.svg\",\"woman_elf_tone5\":\"e8679cd.svg\",\"woman_elf_dark_skin_tone\":\"e8679cd.svg\",\"man_elf\":\"6e524c0.svg\",\"man_elf_tone1\":\"c3764a0.svg\",\"man_elf_light_skin_tone\":\"c3764a0.svg\",\"man_elf_tone2\":\"270bc04.svg\",\"man_elf_medium_light_skin_tone\":\"270bc04.svg\",\"man_elf_tone3\":\"040e78f.svg\",\"man_elf_medium_skin_tone\":\"040e78f.svg\",\"man_elf_tone4\":\"6086303.svg\",\"man_elf_medium_dark_skin_tone\":\"6086303.svg\",\"man_elf_tone5\":\"54d0c8e.svg\",\"man_elf_dark_skin_tone\":\"54d0c8e.svg\",\"vampire\":\"c9240be.svg\",\"vampire_tone1\":\"6a5176b.svg\",\"vampire_light_skin_tone\":\"6a5176b.svg\",\"vampire_tone2\":\"8bebc78.svg\",\"vampire_medium_light_skin_tone\":\"8bebc78.svg\",\"vampire_tone3\":\"eee994b.svg\",\"vampire_medium_skin_tone\":\"eee994b.svg\",\"vampire_tone4\":\"49b8038.svg\",\"vampire_medium_dark_skin_tone\":\"49b8038.svg\",\"vampire_tone5\":\"dfe56c1.svg\",\"vampire_dark_skin_tone\":\"dfe56c1.svg\",\"woman_vampire\":\"b2881b5.svg\",\"woman_vampire_tone1\":\"40eb1fd.svg\",\"woman_vampire_light_skin_tone\":\"40eb1fd.svg\",\"woman_vampire_tone2\":\"ab33484.svg\",\"woman_vampire_medium_light_skin_tone\":\"ab33484.svg\",\"woman_vampire_tone3\":\"3b5dffd.svg\",\"woman_vampire_medium_skin_tone\":\"3b5dffd.svg\",\"woman_vampire_tone4\":\"48059df.svg\",\"woman_vampire_medium_dark_skin_tone\":\"48059df.svg\",\"woman_vampire_tone5\":\"d138a43.svg\",\"woman_vampire_dark_skin_tone\":\"d138a43.svg\",\"man_vampire\":\"ee43274.svg\",\"man_vampire_tone1\":\"7cc2814.svg\",\"man_vampire_light_skin_tone\":\"7cc2814.svg\",\"man_vampire_tone2\":\"2e4f9c0.svg\",\"man_vampire_medium_light_skin_tone\":\"2e4f9c0.svg\",\"man_vampire_tone3\":\"7e1bef4.svg\",\"man_vampire_medium_skin_tone\":\"7e1bef4.svg\",\"man_vampire_tone4\":\"8ad9939.svg\",\"man_vampire_medium_dark_skin_tone\":\"8ad9939.svg\",\"man_vampire_tone5\":\"89f48be.svg\",\"man_vampire_dark_skin_tone\":\"89f48be.svg\",\"zombie\":\"9b3de1a.svg\",\"woman_zombie\":\"c5dc304.svg\",\"man_zombie\":\"e4cbd08.svg\",\"genie\":\"52125d5.svg\",\"woman_genie\":\"8a99bd6.svg\",\"man_genie\":\"362805a.svg\",\"merperson\":\"12f1a80.svg\",\"merperson_tone1\":\"8d5ab2b.svg\",\"merperson_light_skin_tone\":\"8d5ab2b.svg\",\"merperson_tone2\":\"f1dc516.svg\",\"merperson_medium_light_skin_tone\":\"f1dc516.svg\",\"merperson_tone3\":\"cba0642.svg\",\"merperson_medium_skin_tone\":\"cba0642.svg\",\"merperson_tone4\":\"54e94f4.svg\",\"merperson_medium_dark_skin_tone\":\"54e94f4.svg\",\"merperson_tone5\":\"d7827d6.svg\",\"merperson_dark_skin_tone\":\"d7827d6.svg\",\"mermaid\":\"26e0101.svg\",\"mermaid_tone1\":\"5f74ea7.svg\",\"mermaid_light_skin_tone\":\"5f74ea7.svg\",\"mermaid_tone2\":\"0b92906.svg\",\"mermaid_medium_light_skin_tone\":\"0b92906.svg\",\"mermaid_tone3\":\"c9ea451.svg\",\"mermaid_medium_skin_tone\":\"c9ea451.svg\",\"mermaid_tone4\":\"34dba67.svg\",\"mermaid_medium_dark_skin_tone\":\"34dba67.svg\",\"mermaid_tone5\":\"27d982b.svg\",\"mermaid_dark_skin_tone\":\"27d982b.svg\",\"merman\":\"d490d90.svg\",\"merman_tone1\":\"48e7845.svg\",\"merman_light_skin_tone\":\"48e7845.svg\",\"merman_tone2\":\"c5af351.svg\",\"merman_medium_light_skin_tone\":\"c5af351.svg\",\"merman_tone3\":\"069e1f8.svg\",\"merman_medium_skin_tone\":\"069e1f8.svg\",\"merman_tone4\":\"f499b89.svg\",\"merman_medium_dark_skin_tone\":\"f499b89.svg\",\"merman_tone5\":\"52d49c0.svg\",\"merman_dark_skin_tone\":\"52d49c0.svg\",\"fairy\":\"f58e1ca.svg\",\"fairy_tone1\":\"d96091c.svg\",\"fairy_light_skin_tone\":\"d96091c.svg\",\"fairy_tone2\":\"b5a4373.svg\",\"fairy_medium_light_skin_tone\":\"b5a4373.svg\",\"fairy_tone3\":\"19d1f2e.svg\",\"fairy_medium_skin_tone\":\"19d1f2e.svg\",\"fairy_tone4\":\"1342420.svg\",\"fairy_medium_dark_skin_tone\":\"1342420.svg\",\"fairy_tone5\":\"dd5e22f.svg\",\"fairy_dark_skin_tone\":\"dd5e22f.svg\",\"woman_fairy\":\"ebcceac.svg\",\"woman_fairy_tone1\":\"ecf7c6d.svg\",\"woman_fairy_light_skin_tone\":\"ecf7c6d.svg\",\"woman_fairy_tone2\":\"d9e7ef5.svg\",\"woman_fairy_medium_light_skin_tone\":\"d9e7ef5.svg\",\"woman_fairy_tone3\":\"2e1c1af.svg\",\"woman_fairy_medium_skin_tone\":\"2e1c1af.svg\",\"woman_fairy_tone4\":\"89c9eb1.svg\",\"woman_fairy_medium_dark_skin_tone\":\"89c9eb1.svg\",\"woman_fairy_tone5\":\"5f3d231.svg\",\"woman_fairy_dark_skin_tone\":\"5f3d231.svg\",\"man_fairy\":\"c0ad896.svg\",\"man_fairy_tone1\":\"4980f30.svg\",\"man_fairy_light_skin_tone\":\"4980f30.svg\",\"man_fairy_tone2\":\"ee3cd49.svg\",\"man_fairy_medium_light_skin_tone\":\"ee3cd49.svg\",\"man_fairy_tone3\":\"fa2f069.svg\",\"man_fairy_medium_skin_tone\":\"fa2f069.svg\",\"man_fairy_tone4\":\"0fc2831.svg\",\"man_fairy_medium_dark_skin_tone\":\"0fc2831.svg\",\"man_fairy_tone5\":\"539d458.svg\",\"man_fairy_dark_skin_tone\":\"539d458.svg\",\"angel\":\"b3387d6.svg\",\"angel_tone1\":\"239a32d.svg\",\"angel_tone2\":\"07baf5d.svg\",\"angel_tone3\":\"6a489bf.svg\",\"angel_tone4\":\"fd27a77.svg\",\"angel_tone5\":\"ec08846.svg\",\"pregnant_woman\":\"ef4c944.svg\",\"expecting_woman\":\"ef4c944.svg\",\"pregnant_woman_tone1\":\"224a2f2.svg\",\"expecting_woman_tone1\":\"224a2f2.svg\",\"pregnant_woman_tone2\":\"9682714.svg\",\"expecting_woman_tone2\":\"9682714.svg\",\"pregnant_woman_tone3\":\"1f068a5.svg\",\"expecting_woman_tone3\":\"1f068a5.svg\",\"pregnant_woman_tone4\":\"cf94942.svg\",\"expecting_woman_tone4\":\"cf94942.svg\",\"pregnant_woman_tone5\":\"7a6a689.svg\",\"expecting_woman_tone5\":\"7a6a689.svg\",\"breast_feeding\":\"2b10008.svg\",\"breast_feeding_tone1\":\"a439669.svg\",\"breast_feeding_light_skin_tone\":\"a439669.svg\",\"breast_feeding_tone2\":\"796ac62.svg\",\"breast_feeding_medium_light_skin_tone\":\"796ac62.svg\",\"breast_feeding_tone3\":\"96d180c.svg\",\"breast_feeding_medium_skin_tone\":\"96d180c.svg\",\"breast_feeding_tone4\":\"32e8140.svg\",\"breast_feeding_medium_dark_skin_tone\":\"32e8140.svg\",\"breast_feeding_tone5\":\"2bfc6f2.svg\",\"breast_feeding_dark_skin_tone\":\"2bfc6f2.svg\",\"person_feeding_baby\":\"af1bc07.svg\",\"person_feeding_baby_tone1\":\"3db7608.svg\",\"person_feeding_baby_light_skin_tone\":\"3db7608.svg\",\"person_feeding_baby_tone2\":\"7936480.svg\",\"person_feeding_baby_medium_light_skin_tone\":\"7936480.svg\",\"person_feeding_baby_tone3\":\"e977a1d.svg\",\"person_feeding_baby_medium_skin_tone\":\"e977a1d.svg\",\"person_feeding_baby_tone4\":\"ba074f2.svg\",\"person_feeding_baby_medium_dark_skin_tone\":\"ba074f2.svg\",\"person_feeding_baby_tone5\":\"72ee126.svg\",\"person_feeding_baby_dark_skin_tone\":\"72ee126.svg\",\"woman_feeding_baby\":\"9a6693c.svg\",\"woman_feeding_baby_tone1\":\"a3164cc.svg\",\"woman_feeding_baby_light_skin_tone\":\"a3164cc.svg\",\"woman_feeding_baby_tone2\":\"875b4e4.svg\",\"woman_feeding_baby_medium_light_skin_tone\":\"875b4e4.svg\",\"woman_feeding_baby_tone3\":\"4e937ef.svg\",\"woman_feeding_baby_medium_skin_tone\":\"4e937ef.svg\",\"woman_feeding_baby_tone4\":\"711191e.svg\",\"woman_feeding_baby_medium_dark_skin_tone\":\"711191e.svg\",\"woman_feeding_baby_tone5\":\"5e0cf66.svg\",\"woman_feeding_baby_dark_skin_tone\":\"5e0cf66.svg\",\"man_feeding_baby\":\"1d1792e.svg\",\"man_feeding_baby_tone1\":\"879bb6c.svg\",\"man_feeding_baby_light_skin_tone\":\"879bb6c.svg\",\"man_feeding_baby_tone2\":\"84656da.svg\",\"man_feeding_baby_medium_light_skin_tone\":\"84656da.svg\",\"man_feeding_baby_tone3\":\"dc9847b.svg\",\"man_feeding_baby_medium_skin_tone\":\"dc9847b.svg\",\"man_feeding_baby_tone4\":\"3b82610.svg\",\"man_feeding_baby_medium_dark_skin_tone\":\"3b82610.svg\",\"man_feeding_baby_tone5\":\"49de399.svg\",\"man_feeding_baby_dark_skin_tone\":\"49de399.svg\",\"person_bowing\":\"c941147.svg\",\"bow\":\"c941147.svg\",\"person_bowing_tone1\":\"4f54e38.svg\",\"bow_tone1\":\"4f54e38.svg\",\"person_bowing_tone2\":\"b97c8e5.svg\",\"bow_tone2\":\"b97c8e5.svg\",\"person_bowing_tone3\":\"7821a37.svg\",\"bow_tone3\":\"7821a37.svg\",\"person_bowing_tone4\":\"840d2d8.svg\",\"bow_tone4\":\"840d2d8.svg\",\"person_bowing_tone5\":\"b701817.svg\",\"bow_tone5\":\"b701817.svg\",\"woman_bowing\":\"f2660f4.svg\",\"woman_bowing_tone1\":\"21bb2a0.svg\",\"woman_bowing_light_skin_tone\":\"21bb2a0.svg\",\"woman_bowing_tone2\":\"78d96e1.svg\",\"woman_bowing_medium_light_skin_tone\":\"78d96e1.svg\",\"woman_bowing_tone3\":\"e851e7f.svg\",\"woman_bowing_medium_skin_tone\":\"e851e7f.svg\",\"woman_bowing_tone4\":\"19435af.svg\",\"woman_bowing_medium_dark_skin_tone\":\"19435af.svg\",\"woman_bowing_tone5\":\"227b2bc.svg\",\"woman_bowing_dark_skin_tone\":\"227b2bc.svg\",\"man_bowing\":\"9417936.svg\",\"man_bowing_tone1\":\"4a24679.svg\",\"man_bowing_light_skin_tone\":\"4a24679.svg\",\"man_bowing_tone2\":\"8b945bc.svg\",\"man_bowing_medium_light_skin_tone\":\"8b945bc.svg\",\"man_bowing_tone3\":\"c1fd4c8.svg\",\"man_bowing_medium_skin_tone\":\"c1fd4c8.svg\",\"man_bowing_tone4\":\"a82718c.svg\",\"man_bowing_medium_dark_skin_tone\":\"a82718c.svg\",\"man_bowing_tone5\":\"550eec8.svg\",\"man_bowing_dark_skin_tone\":\"550eec8.svg\",\"person_tipping_hand\":\"9ff61cb.svg\",\"information_desk_person\":\"9ff61cb.svg\",\"person_tipping_hand_tone1\":\"91b9440.svg\",\"information_desk_person_tone1\":\"91b9440.svg\",\"person_tipping_hand_tone2\":\"4bb5ba9.svg\",\"information_desk_person_tone2\":\"4bb5ba9.svg\",\"person_tipping_hand_tone3\":\"2bcf099.svg\",\"information_desk_person_tone3\":\"2bcf099.svg\",\"person_tipping_hand_tone4\":\"1e8e06f.svg\",\"information_desk_person_tone4\":\"1e8e06f.svg\",\"person_tipping_hand_tone5\":\"9272072.svg\",\"information_desk_person_tone5\":\"9272072.svg\",\"woman_tipping_hand\":\"c94f989.svg\",\"woman_tipping_hand_tone1\":\"b326225.svg\",\"woman_tipping_hand_light_skin_tone\":\"b326225.svg\",\"woman_tipping_hand_tone2\":\"1a1afc4.svg\",\"woman_tipping_hand_medium_light_skin_tone\":\"1a1afc4.svg\",\"woman_tipping_hand_tone3\":\"58f6da9.svg\",\"woman_tipping_hand_medium_skin_tone\":\"58f6da9.svg\",\"woman_tipping_hand_tone4\":\"2c50ea8.svg\",\"woman_tipping_hand_medium_dark_skin_tone\":\"2c50ea8.svg\",\"woman_tipping_hand_tone5\":\"8090582.svg\",\"woman_tipping_hand_dark_skin_tone\":\"8090582.svg\",\"man_tipping_hand\":\"df0ef8e.svg\",\"man_tipping_hand_tone1\":\"a7fe8d2.svg\",\"man_tipping_hand_light_skin_tone\":\"a7fe8d2.svg\",\"man_tipping_hand_tone2\":\"4e72ec9.svg\",\"man_tipping_hand_medium_light_skin_tone\":\"4e72ec9.svg\",\"man_tipping_hand_tone3\":\"a7e0481.svg\",\"man_tipping_hand_medium_skin_tone\":\"a7e0481.svg\",\"man_tipping_hand_tone4\":\"ca1be4f.svg\",\"man_tipping_hand_medium_dark_skin_tone\":\"ca1be4f.svg\",\"man_tipping_hand_tone5\":\"ab22b3f.svg\",\"man_tipping_hand_dark_skin_tone\":\"ab22b3f.svg\",\"person_gesturing_no\":\"b3d3cab.svg\",\"no_good\":\"b3d3cab.svg\",\"person_gesturing_no_tone1\":\"5761bba.svg\",\"no_good_tone1\":\"5761bba.svg\",\"person_gesturing_no_tone2\":\"e92da27.svg\",\"no_good_tone2\":\"e92da27.svg\",\"person_gesturing_no_tone3\":\"52cf54e.svg\",\"no_good_tone3\":\"52cf54e.svg\",\"person_gesturing_no_tone4\":\"4d41682.svg\",\"no_good_tone4\":\"4d41682.svg\",\"person_gesturing_no_tone5\":\"734a4ec.svg\",\"no_good_tone5\":\"734a4ec.svg\",\"woman_gesturing_no\":\"0cf0c5b.svg\",\"woman_gesturing_no_tone1\":\"c8e7646.svg\",\"woman_gesturing_no_light_skin_tone\":\"c8e7646.svg\",\"woman_gesturing_no_tone2\":\"ed0f0dd.svg\",\"woman_gesturing_no_medium_light_skin_tone\":\"ed0f0dd.svg\",\"woman_gesturing_no_tone3\":\"69fe3a5.svg\",\"woman_gesturing_no_medium_skin_tone\":\"69fe3a5.svg\",\"woman_gesturing_no_tone4\":\"e9d62cb.svg\",\"woman_gesturing_no_medium_dark_skin_tone\":\"e9d62cb.svg\",\"woman_gesturing_no_tone5\":\"0945226.svg\",\"woman_gesturing_no_dark_skin_tone\":\"0945226.svg\",\"man_gesturing_no\":\"36264f7.svg\",\"man_gesturing_no_tone1\":\"fa93037.svg\",\"man_gesturing_no_light_skin_tone\":\"fa93037.svg\",\"man_gesturing_no_tone2\":\"db4e57a.svg\",\"man_gesturing_no_medium_light_skin_tone\":\"db4e57a.svg\",\"man_gesturing_no_tone3\":\"149936d.svg\",\"man_gesturing_no_medium_skin_tone\":\"149936d.svg\",\"man_gesturing_no_tone4\":\"555adbc.svg\",\"man_gesturing_no_medium_dark_skin_tone\":\"555adbc.svg\",\"man_gesturing_no_tone5\":\"74b112d.svg\",\"man_gesturing_no_dark_skin_tone\":\"74b112d.svg\",\"person_gesturing_ok\":\"78d8c1b.svg\",\"ok_woman\":\"78d8c1b.svg\",\"person_gesturing_ok_tone1\":\"a8a7d2b.svg\",\"ok_woman_tone1\":\"a8a7d2b.svg\",\"person_gesturing_ok_tone2\":\"1932339.svg\",\"ok_woman_tone2\":\"1932339.svg\",\"person_gesturing_ok_tone3\":\"62a69d5.svg\",\"ok_woman_tone3\":\"62a69d5.svg\",\"person_gesturing_ok_tone4\":\"ab3bd3f.svg\",\"ok_woman_tone4\":\"ab3bd3f.svg\",\"person_gesturing_ok_tone5\":\"498658e.svg\",\"ok_woman_tone5\":\"498658e.svg\",\"woman_gesturing_ok\":\"c12f22f.svg\",\"woman_gesturing_ok_tone1\":\"bbaf25a.svg\",\"woman_gesturing_ok_light_skin_tone\":\"bbaf25a.svg\",\"woman_gesturing_ok_tone2\":\"5086512.svg\",\"woman_gesturing_ok_medium_light_skin_tone\":\"5086512.svg\",\"woman_gesturing_ok_tone3\":\"16d7752.svg\",\"woman_gesturing_ok_medium_skin_tone\":\"16d7752.svg\",\"woman_gesturing_ok_tone4\":\"827931c.svg\",\"woman_gesturing_ok_medium_dark_skin_tone\":\"827931c.svg\",\"woman_gesturing_ok_tone5\":\"9d225f5.svg\",\"woman_gesturing_ok_dark_skin_tone\":\"9d225f5.svg\",\"man_gesturing_ok\":\"c805342.svg\",\"man_gesturing_ok_tone1\":\"d6d537f.svg\",\"man_gesturing_ok_light_skin_tone\":\"d6d537f.svg\",\"man_gesturing_ok_tone2\":\"723bd7c.svg\",\"man_gesturing_ok_medium_light_skin_tone\":\"723bd7c.svg\",\"man_gesturing_ok_tone3\":\"c793134.svg\",\"man_gesturing_ok_medium_skin_tone\":\"c793134.svg\",\"man_gesturing_ok_tone4\":\"82c3ecf.svg\",\"man_gesturing_ok_medium_dark_skin_tone\":\"82c3ecf.svg\",\"man_gesturing_ok_tone5\":\"527cdca.svg\",\"man_gesturing_ok_dark_skin_tone\":\"527cdca.svg\",\"person_raising_hand\":\"233672b.svg\",\"raising_hand\":\"233672b.svg\",\"person_raising_hand_tone1\":\"effaeab.svg\",\"raising_hand_tone1\":\"effaeab.svg\",\"person_raising_hand_tone2\":\"44ef541.svg\",\"raising_hand_tone2\":\"44ef541.svg\",\"person_raising_hand_tone3\":\"154c8f1.svg\",\"raising_hand_tone3\":\"154c8f1.svg\",\"person_raising_hand_tone4\":\"6ba1f11.svg\",\"raising_hand_tone4\":\"6ba1f11.svg\",\"person_raising_hand_tone5\":\"fe1afd4.svg\",\"raising_hand_tone5\":\"fe1afd4.svg\",\"woman_raising_hand\":\"5292981.svg\",\"woman_raising_hand_tone1\":\"a3c06be.svg\",\"woman_raising_hand_light_skin_tone\":\"a3c06be.svg\",\"woman_raising_hand_tone2\":\"9476e45.svg\",\"woman_raising_hand_medium_light_skin_tone\":\"9476e45.svg\",\"woman_raising_hand_tone3\":\"b3888a9.svg\",\"woman_raising_hand_medium_skin_tone\":\"b3888a9.svg\",\"woman_raising_hand_tone4\":\"5b6980b.svg\",\"woman_raising_hand_medium_dark_skin_tone\":\"5b6980b.svg\",\"woman_raising_hand_tone5\":\"a5ed245.svg\",\"woman_raising_hand_dark_skin_tone\":\"a5ed245.svg\",\"man_raising_hand\":\"72bbf7d.svg\",\"man_raising_hand_tone1\":\"bdcf877.svg\",\"man_raising_hand_light_skin_tone\":\"bdcf877.svg\",\"man_raising_hand_tone2\":\"22d2886.svg\",\"man_raising_hand_medium_light_skin_tone\":\"22d2886.svg\",\"man_raising_hand_tone3\":\"6bee419.svg\",\"man_raising_hand_medium_skin_tone\":\"6bee419.svg\",\"man_raising_hand_tone4\":\"9747d0a.svg\",\"man_raising_hand_medium_dark_skin_tone\":\"9747d0a.svg\",\"man_raising_hand_tone5\":\"dbde589.svg\",\"man_raising_hand_dark_skin_tone\":\"dbde589.svg\",\"deaf_person\":\"6544e85.svg\",\"deaf_person_tone1\":\"e438224.svg\",\"deaf_person_light_skin_tone\":\"e438224.svg\",\"deaf_person_tone2\":\"487331a.svg\",\"deaf_person_medium_light_skin_tone\":\"487331a.svg\",\"deaf_person_tone3\":\"2b0c9df.svg\",\"deaf_person_medium_skin_tone\":\"2b0c9df.svg\",\"deaf_person_tone4\":\"fcc98bd.svg\",\"deaf_person_medium_dark_skin_tone\":\"fcc98bd.svg\",\"deaf_person_tone5\":\"52c382a.svg\",\"deaf_person_dark_skin_tone\":\"52c382a.svg\",\"deaf_woman\":\"86e5fef.svg\",\"deaf_woman_tone1\":\"ae24285.svg\",\"deaf_woman_light_skin_tone\":\"ae24285.svg\",\"deaf_woman_tone2\":\"0d4577a.svg\",\"deaf_woman_medium_light_skin_tone\":\"0d4577a.svg\",\"deaf_woman_tone3\":\"e08dc29.svg\",\"deaf_woman_medium_skin_tone\":\"e08dc29.svg\",\"deaf_woman_tone4\":\"dc524f8.svg\",\"deaf_woman_medium_dark_skin_tone\":\"dc524f8.svg\",\"deaf_woman_tone5\":\"695de57.svg\",\"deaf_woman_dark_skin_tone\":\"695de57.svg\",\"deaf_man\":\"3985709.svg\",\"deaf_man_tone1\":\"c8f2b7c.svg\",\"deaf_man_light_skin_tone\":\"c8f2b7c.svg\",\"deaf_man_tone2\":\"bc043e0.svg\",\"deaf_man_medium_light_skin_tone\":\"bc043e0.svg\",\"deaf_man_tone3\":\"4bd7e00.svg\",\"deaf_man_medium_skin_tone\":\"4bd7e00.svg\",\"deaf_man_tone4\":\"4c31d34.svg\",\"deaf_man_medium_dark_skin_tone\":\"4c31d34.svg\",\"deaf_man_tone5\":\"3d0d9dc.svg\",\"deaf_man_dark_skin_tone\":\"3d0d9dc.svg\",\"person_facepalming\":\"b1ef4ff.svg\",\"face_palm\":\"b1ef4ff.svg\",\"facepalm\":\"b1ef4ff.svg\",\"person_facepalming_tone1\":\"5c12246.svg\",\"face_palm_tone1\":\"5c12246.svg\",\"facepalm_tone1\":\"5c12246.svg\",\"person_facepalming_tone2\":\"00f0044.svg\",\"face_palm_tone2\":\"00f0044.svg\",\"facepalm_tone2\":\"00f0044.svg\",\"person_facepalming_tone3\":\"2c4e6e4.svg\",\"face_palm_tone3\":\"2c4e6e4.svg\",\"facepalm_tone3\":\"2c4e6e4.svg\",\"person_facepalming_tone4\":\"b4618b8.svg\",\"face_palm_tone4\":\"b4618b8.svg\",\"facepalm_tone4\":\"b4618b8.svg\",\"person_facepalming_tone5\":\"c7effed.svg\",\"face_palm_tone5\":\"c7effed.svg\",\"facepalm_tone5\":\"c7effed.svg\",\"woman_facepalming\":\"b0e9cd8.svg\",\"woman_facepalming_tone1\":\"0c79612.svg\",\"woman_facepalming_light_skin_tone\":\"0c79612.svg\",\"woman_facepalming_tone2\":\"c678063.svg\",\"woman_facepalming_medium_light_skin_tone\":\"c678063.svg\",\"woman_facepalming_tone3\":\"016f3e5.svg\",\"woman_facepalming_medium_skin_tone\":\"016f3e5.svg\",\"woman_facepalming_tone4\":\"5ad9a80.svg\",\"woman_facepalming_medium_dark_skin_tone\":\"5ad9a80.svg\",\"woman_facepalming_tone5\":\"858411b.svg\",\"woman_facepalming_dark_skin_tone\":\"858411b.svg\",\"man_facepalming\":\"ebe3c51.svg\",\"man_facepalming_tone1\":\"c9bd6c8.svg\",\"man_facepalming_light_skin_tone\":\"c9bd6c8.svg\",\"man_facepalming_tone2\":\"e64451e.svg\",\"man_facepalming_medium_light_skin_tone\":\"e64451e.svg\",\"man_facepalming_tone3\":\"a1f5dfb.svg\",\"man_facepalming_medium_skin_tone\":\"a1f5dfb.svg\",\"man_facepalming_tone4\":\"2518b02.svg\",\"man_facepalming_medium_dark_skin_tone\":\"2518b02.svg\",\"man_facepalming_tone5\":\"5ddde41.svg\",\"man_facepalming_dark_skin_tone\":\"5ddde41.svg\",\"person_shrugging\":\"9f9d201.svg\",\"shrug\":\"9f9d201.svg\",\"person_shrugging_tone1\":\"c808491.svg\",\"shrug_tone1\":\"c808491.svg\",\"person_shrugging_tone2\":\"9e7ab0d.svg\",\"shrug_tone2\":\"9e7ab0d.svg\",\"person_shrugging_tone3\":\"add6153.svg\",\"shrug_tone3\":\"add6153.svg\",\"person_shrugging_tone4\":\"e2aa2fd.svg\",\"shrug_tone4\":\"e2aa2fd.svg\",\"person_shrugging_tone5\":\"a889b10.svg\",\"shrug_tone5\":\"a889b10.svg\",\"woman_shrugging\":\"07d7116.svg\",\"woman_shrugging_tone1\":\"ef01911.svg\",\"woman_shrugging_light_skin_tone\":\"ef01911.svg\",\"woman_shrugging_tone2\":\"6a7505b.svg\",\"woman_shrugging_medium_light_skin_tone\":\"6a7505b.svg\",\"woman_shrugging_tone3\":\"fb69dde.svg\",\"woman_shrugging_medium_skin_tone\":\"fb69dde.svg\",\"woman_shrugging_tone4\":\"e51d390.svg\",\"woman_shrugging_medium_dark_skin_tone\":\"e51d390.svg\",\"woman_shrugging_tone5\":\"b4e9af2.svg\",\"woman_shrugging_dark_skin_tone\":\"b4e9af2.svg\",\"man_shrugging\":\"461ded8.svg\",\"man_shrugging_tone1\":\"c566d67.svg\",\"man_shrugging_light_skin_tone\":\"c566d67.svg\",\"man_shrugging_tone2\":\"5513f53.svg\",\"man_shrugging_medium_light_skin_tone\":\"5513f53.svg\",\"man_shrugging_tone3\":\"e32a5a7.svg\",\"man_shrugging_medium_skin_tone\":\"e32a5a7.svg\",\"man_shrugging_tone4\":\"b9af4c1.svg\",\"man_shrugging_medium_dark_skin_tone\":\"b9af4c1.svg\",\"man_shrugging_tone5\":\"37cd4e4.svg\",\"man_shrugging_dark_skin_tone\":\"37cd4e4.svg\",\"person_pouting\":\"e0c72d3.svg\",\"person_with_pouting_face\":\"e0c72d3.svg\",\"person_pouting_tone1\":\"b8d02d5.svg\",\"person_with_pouting_face_tone1\":\"b8d02d5.svg\",\"person_pouting_tone2\":\"8761f4d.svg\",\"person_with_pouting_face_tone2\":\"8761f4d.svg\",\"person_pouting_tone3\":\"917193e.svg\",\"person_with_pouting_face_tone3\":\"917193e.svg\",\"person_pouting_tone4\":\"afd130f.svg\",\"person_with_pouting_face_tone4\":\"afd130f.svg\",\"person_pouting_tone5\":\"1345297.svg\",\"person_with_pouting_face_tone5\":\"1345297.svg\",\"woman_pouting\":\"23bdd67.svg\",\"woman_pouting_tone1\":\"68a870b.svg\",\"woman_pouting_light_skin_tone\":\"68a870b.svg\",\"woman_pouting_tone2\":\"87cc3e3.svg\",\"woman_pouting_medium_light_skin_tone\":\"87cc3e3.svg\",\"woman_pouting_tone3\":\"ebb6550.svg\",\"woman_pouting_medium_skin_tone\":\"ebb6550.svg\",\"woman_pouting_tone4\":\"b157967.svg\",\"woman_pouting_medium_dark_skin_tone\":\"b157967.svg\",\"woman_pouting_tone5\":\"3b4c2f4.svg\",\"woman_pouting_dark_skin_tone\":\"3b4c2f4.svg\",\"man_pouting\":\"0a478b3.svg\",\"man_pouting_tone1\":\"a09c4f8.svg\",\"man_pouting_light_skin_tone\":\"a09c4f8.svg\",\"man_pouting_tone2\":\"ccb3ec0.svg\",\"man_pouting_medium_light_skin_tone\":\"ccb3ec0.svg\",\"man_pouting_tone3\":\"a976c3f.svg\",\"man_pouting_medium_skin_tone\":\"a976c3f.svg\",\"man_pouting_tone4\":\"a0c0da1.svg\",\"man_pouting_medium_dark_skin_tone\":\"a0c0da1.svg\",\"man_pouting_tone5\":\"b36e7cb.svg\",\"man_pouting_dark_skin_tone\":\"b36e7cb.svg\",\"person_frowning\":\"b54d16c.svg\",\"person_frowning_tone1\":\"1d91a35.svg\",\"person_frowning_tone2\":\"bd11f84.svg\",\"person_frowning_tone3\":\"0075836.svg\",\"person_frowning_tone4\":\"2f4c682.svg\",\"person_frowning_tone5\":\"f05d72b.svg\",\"woman_frowning\":\"0ad5677.svg\",\"woman_frowning_tone1\":\"b52e466.svg\",\"woman_frowning_light_skin_tone\":\"b52e466.svg\",\"woman_frowning_tone2\":\"31501dc.svg\",\"woman_frowning_medium_light_skin_tone\":\"31501dc.svg\",\"woman_frowning_tone3\":\"4c683ec.svg\",\"woman_frowning_medium_skin_tone\":\"4c683ec.svg\",\"woman_frowning_tone4\":\"62f239b.svg\",\"woman_frowning_medium_dark_skin_tone\":\"62f239b.svg\",\"woman_frowning_tone5\":\"b2348e4.svg\",\"woman_frowning_dark_skin_tone\":\"b2348e4.svg\",\"man_frowning\":\"c8012a8.svg\",\"man_frowning_tone1\":\"bfb307e.svg\",\"man_frowning_light_skin_tone\":\"bfb307e.svg\",\"man_frowning_tone2\":\"9408d7c.svg\",\"man_frowning_medium_light_skin_tone\":\"9408d7c.svg\",\"man_frowning_tone3\":\"654d019.svg\",\"man_frowning_medium_skin_tone\":\"654d019.svg\",\"man_frowning_tone4\":\"1992e8a.svg\",\"man_frowning_medium_dark_skin_tone\":\"1992e8a.svg\",\"man_frowning_tone5\":\"607cb42.svg\",\"man_frowning_dark_skin_tone\":\"607cb42.svg\",\"person_getting_haircut\":\"5195d8f.svg\",\"haircut\":\"5195d8f.svg\",\"person_getting_haircut_tone1\":\"24cfd2f.svg\",\"haircut_tone1\":\"24cfd2f.svg\",\"person_getting_haircut_tone2\":\"58e729e.svg\",\"haircut_tone2\":\"58e729e.svg\",\"person_getting_haircut_tone3\":\"d05262f.svg\",\"haircut_tone3\":\"d05262f.svg\",\"person_getting_haircut_tone4\":\"5e61065.svg\",\"haircut_tone4\":\"5e61065.svg\",\"person_getting_haircut_tone5\":\"0dfa781.svg\",\"haircut_tone5\":\"0dfa781.svg\",\"woman_getting_haircut\":\"1a18b7f.svg\",\"woman_getting_haircut_tone1\":\"aa700ad.svg\",\"woman_getting_haircut_light_skin_tone\":\"aa700ad.svg\",\"woman_getting_haircut_tone2\":\"e498a95.svg\",\"woman_getting_haircut_medium_light_skin_tone\":\"e498a95.svg\",\"woman_getting_haircut_tone3\":\"bcd258a.svg\",\"woman_getting_haircut_medium_skin_tone\":\"bcd258a.svg\",\"woman_getting_haircut_tone4\":\"2ee70bb.svg\",\"woman_getting_haircut_medium_dark_skin_tone\":\"2ee70bb.svg\",\"woman_getting_haircut_tone5\":\"1f38e96.svg\",\"woman_getting_haircut_dark_skin_tone\":\"1f38e96.svg\",\"man_getting_haircut\":\"adc5266.svg\",\"man_getting_haircut_tone1\":\"424c650.svg\",\"man_getting_haircut_light_skin_tone\":\"424c650.svg\",\"man_getting_haircut_tone2\":\"49090ff.svg\",\"man_getting_haircut_medium_light_skin_tone\":\"49090ff.svg\",\"man_getting_haircut_tone3\":\"27ff3ea.svg\",\"man_getting_haircut_medium_skin_tone\":\"27ff3ea.svg\",\"man_getting_haircut_tone4\":\"d2484c1.svg\",\"man_getting_haircut_medium_dark_skin_tone\":\"d2484c1.svg\",\"man_getting_haircut_tone5\":\"551363b.svg\",\"man_getting_haircut_dark_skin_tone\":\"551363b.svg\",\"person_getting_massage\":\"d5fe7f4.svg\",\"massage\":\"d5fe7f4.svg\",\"person_getting_massage_tone1\":\"e4857ca.svg\",\"massage_tone1\":\"e4857ca.svg\",\"person_getting_massage_tone2\":\"9b27a37.svg\",\"massage_tone2\":\"9b27a37.svg\",\"person_getting_massage_tone3\":\"0ee9111.svg\",\"massage_tone3\":\"0ee9111.svg\",\"person_getting_massage_tone4\":\"d695c28.svg\",\"massage_tone4\":\"d695c28.svg\",\"person_getting_massage_tone5\":\"f38b5b4.svg\",\"massage_tone5\":\"f38b5b4.svg\",\"woman_getting_face_massage\":\"20e293b.svg\",\"woman_getting_face_massage_tone1\":\"9c68367.svg\",\"woman_getting_face_massage_light_skin_tone\":\"9c68367.svg\",\"woman_getting_face_massage_tone2\":\"5f4591b.svg\",\"woman_getting_face_massage_medium_light_skin_tone\":\"5f4591b.svg\",\"woman_getting_face_massage_tone3\":\"e50c761.svg\",\"woman_getting_face_massage_medium_skin_tone\":\"e50c761.svg\",\"woman_getting_face_massage_tone4\":\"f74ecb8.svg\",\"woman_getting_face_massage_medium_dark_skin_tone\":\"f74ecb8.svg\",\"woman_getting_face_massage_tone5\":\"e73552f.svg\",\"woman_getting_face_massage_dark_skin_tone\":\"e73552f.svg\",\"man_getting_face_massage\":\"116f585.svg\",\"man_getting_face_massage_tone1\":\"2336974.svg\",\"man_getting_face_massage_light_skin_tone\":\"2336974.svg\",\"man_getting_face_massage_tone2\":\"8aada29.svg\",\"man_getting_face_massage_medium_light_skin_tone\":\"8aada29.svg\",\"man_getting_face_massage_tone3\":\"e4262a8.svg\",\"man_getting_face_massage_medium_skin_tone\":\"e4262a8.svg\",\"man_getting_face_massage_tone4\":\"3426889.svg\",\"man_getting_face_massage_medium_dark_skin_tone\":\"3426889.svg\",\"man_getting_face_massage_tone5\":\"44c3dcf.svg\",\"man_getting_face_massage_dark_skin_tone\":\"44c3dcf.svg\",\"person_in_steamy_room\":\"34eb462.svg\",\"person_in_steamy_room_tone1\":\"bc4b231.svg\",\"person_in_steamy_room_light_skin_tone\":\"bc4b231.svg\",\"person_in_steamy_room_tone2\":\"80a1fee.svg\",\"person_in_steamy_room_medium_light_skin_tone\":\"80a1fee.svg\",\"person_in_steamy_room_tone3\":\"efda8b7.svg\",\"person_in_steamy_room_medium_skin_tone\":\"efda8b7.svg\",\"person_in_steamy_room_tone4\":\"1b86631.svg\",\"person_in_steamy_room_medium_dark_skin_tone\":\"1b86631.svg\",\"person_in_steamy_room_tone5\":\"97bfa4c.svg\",\"person_in_steamy_room_dark_skin_tone\":\"97bfa4c.svg\",\"woman_in_steamy_room\":\"ff97577.svg\",\"woman_in_steamy_room_tone1\":\"c5be413.svg\",\"woman_in_steamy_room_light_skin_tone\":\"c5be413.svg\",\"woman_in_steamy_room_tone2\":\"5f66664.svg\",\"woman_in_steamy_room_medium_light_skin_tone\":\"5f66664.svg\",\"woman_in_steamy_room_tone3\":\"30cbfeb.svg\",\"woman_in_steamy_room_medium_skin_tone\":\"30cbfeb.svg\",\"woman_in_steamy_room_tone4\":\"d97af6c.svg\",\"woman_in_steamy_room_medium_dark_skin_tone\":\"d97af6c.svg\",\"woman_in_steamy_room_tone5\":\"27256eb.svg\",\"woman_in_steamy_room_dark_skin_tone\":\"27256eb.svg\",\"man_in_steamy_room\":\"b478994.svg\",\"man_in_steamy_room_tone1\":\"ac368ef.svg\",\"man_in_steamy_room_light_skin_tone\":\"ac368ef.svg\",\"man_in_steamy_room_tone2\":\"e091810.svg\",\"man_in_steamy_room_medium_light_skin_tone\":\"e091810.svg\",\"man_in_steamy_room_tone3\":\"76979d9.svg\",\"man_in_steamy_room_medium_skin_tone\":\"76979d9.svg\",\"man_in_steamy_room_tone4\":\"d2872ca.svg\",\"man_in_steamy_room_medium_dark_skin_tone\":\"d2872ca.svg\",\"man_in_steamy_room_tone5\":\"a874aeb.svg\",\"man_in_steamy_room_dark_skin_tone\":\"a874aeb.svg\",\"nail_care\":\"9560c40.svg\",\"nail_care_tone1\":\"4d00842.svg\",\"nail_care_tone2\":\"d395ba9.svg\",\"nail_care_tone3\":\"e66d129.svg\",\"nail_care_tone4\":\"7d733a5.svg\",\"nail_care_tone5\":\"273c192.svg\",\"selfie\":\"78c0d71.svg\",\"selfie_tone1\":\"08d46cd.svg\",\"selfie_tone2\":\"dbe8ad8.svg\",\"selfie_tone3\":\"e9830d4.svg\",\"selfie_tone4\":\"d6a0954.svg\",\"selfie_tone5\":\"e2e70c9.svg\",\"dancer\":\"d269f51.svg\",\"dancer_tone1\":\"08c020d.svg\",\"dancer_tone2\":\"ee1c1c4.svg\",\"dancer_tone3\":\"cfa402c.svg\",\"dancer_tone4\":\"b382fe7.svg\",\"dancer_tone5\":\"b3148f8.svg\",\"man_dancing\":\"4d39df0.svg\",\"male_dancer\":\"4d39df0.svg\",\"man_dancing_tone1\":\"15b88cf.svg\",\"male_dancer_tone1\":\"15b88cf.svg\",\"man_dancing_tone2\":\"4fee914.svg\",\"male_dancer_tone2\":\"4fee914.svg\",\"man_dancing_tone3\":\"dfc7558.svg\",\"male_dancer_tone3\":\"dfc7558.svg\",\"man_dancing_tone5\":\"cbf8cd2.svg\",\"male_dancer_tone5\":\"cbf8cd2.svg\",\"man_dancing_tone4\":\"f3373d8.svg\",\"male_dancer_tone4\":\"f3373d8.svg\",\"people_with_bunny_ears_partying\":\"1109bba.svg\",\"dancers\":\"1109bba.svg\",\"women_with_bunny_ears_partying\":\"31d5b7f.svg\",\"men_with_bunny_ears_partying\":\"1797f13.svg\",\"levitate\":\"de6429e.svg\",\"man_in_business_suit_levitating\":\"de6429e.svg\",\"levitate_tone1\":\"7109687.svg\",\"man_in_business_suit_levitating_tone1\":\"7109687.svg\",\"man_in_business_suit_levitating_light_skin_tone\":\"7109687.svg\",\"levitate_tone2\":\"69d0a60.svg\",\"man_in_business_suit_levitating_tone2\":\"69d0a60.svg\",\"man_in_business_suit_levitating_medium_light_skin_tone\":\"69d0a60.svg\",\"levitate_tone3\":\"0c06cb8.svg\",\"man_in_business_suit_levitating_tone3\":\"0c06cb8.svg\",\"man_in_business_suit_levitating_medium_skin_tone\":\"0c06cb8.svg\",\"levitate_tone4\":\"d24578b.svg\",\"man_in_business_suit_levitating_tone4\":\"d24578b.svg\",\"man_in_business_suit_levitating_medium_dark_skin_tone\":\"d24578b.svg\",\"levitate_tone5\":\"65ac60f.svg\",\"man_in_business_suit_levitating_tone5\":\"65ac60f.svg\",\"man_in_business_suit_levitating_dark_skin_tone\":\"65ac60f.svg\",\"person_in_manual_wheelchair\":\"84cf080.svg\",\"person_in_manual_wheelchair_tone1\":\"f229855.svg\",\"person_in_manual_wheelchair_light_skin_tone\":\"f229855.svg\",\"person_in_manual_wheelchair_tone2\":\"17c2b7c.svg\",\"person_in_manual_wheelchair_medium_light_skin_tone\":\"17c2b7c.svg\",\"person_in_manual_wheelchair_tone3\":\"c4677a3.svg\",\"person_in_manual_wheelchair_medium_skin_tone\":\"c4677a3.svg\",\"person_in_manual_wheelchair_tone4\":\"c89e2b3.svg\",\"person_in_manual_wheelchair_medium_dark_skin_tone\":\"c89e2b3.svg\",\"person_in_manual_wheelchair_tone5\":\"616eafd.svg\",\"person_in_manual_wheelchair_dark_skin_tone\":\"616eafd.svg\",\"woman_in_manual_wheelchair\":\"ff97b0d.svg\",\"woman_in_manual_wheelchair_tone1\":\"0b8a7c8.svg\",\"woman_in_manual_wheelchair_light_skin_tone\":\"0b8a7c8.svg\",\"woman_in_manual_wheelchair_tone2\":\"2687b77.svg\",\"woman_in_manual_wheelchair_medium_light_skin_tone\":\"2687b77.svg\",\"woman_in_manual_wheelchair_tone3\":\"a4bb607.svg\",\"woman_in_manual_wheelchair_medium_skin_tone\":\"a4bb607.svg\",\"woman_in_manual_wheelchair_tone4\":\"fe46ede.svg\",\"woman_in_manual_wheelchair_medium_dark_skin_tone\":\"fe46ede.svg\",\"woman_in_manual_wheelchair_tone5\":\"dbfde96.svg\",\"woman_in_manual_wheelchair_dark_skin_tone\":\"dbfde96.svg\",\"man_in_manual_wheelchair\":\"7339ecd.svg\",\"man_in_manual_wheelchair_tone1\":\"ac5160b.svg\",\"man_in_manual_wheelchair_light_skin_tone\":\"ac5160b.svg\",\"man_in_manual_wheelchair_tone2\":\"f621f15.svg\",\"man_in_manual_wheelchair_medium_light_skin_tone\":\"f621f15.svg\",\"man_in_manual_wheelchair_tone3\":\"910e29e.svg\",\"man_in_manual_wheelchair_medium_skin_tone\":\"910e29e.svg\",\"man_in_manual_wheelchair_tone4\":\"76f1b06.svg\",\"man_in_manual_wheelchair_medium_dark_skin_tone\":\"76f1b06.svg\",\"man_in_manual_wheelchair_tone5\":\"7a97c0f.svg\",\"man_in_manual_wheelchair_dark_skin_tone\":\"7a97c0f.svg\",\"person_in_motorized_wheelchair\":\"c83226f.svg\",\"person_in_motorized_wheelchair_tone1\":\"d528ff2.svg\",\"person_in_motorized_wheelchair_light_skin_tone\":\"d528ff2.svg\",\"person_in_motorized_wheelchair_tone2\":\"93260e5.svg\",\"person_in_motorized_wheelchair_medium_light_skin_tone\":\"93260e5.svg\",\"person_in_motorized_wheelchair_tone3\":\"73d4365.svg\",\"person_in_motorized_wheelchair_medium_skin_tone\":\"73d4365.svg\",\"person_in_motorized_wheelchair_tone4\":\"33dbaca.svg\",\"person_in_motorized_wheelchair_medium_dark_skin_tone\":\"33dbaca.svg\",\"person_in_motorized_wheelchair_tone5\":\"3e9a112.svg\",\"person_in_motorized_wheelchair_dark_skin_tone\":\"3e9a112.svg\",\"woman_in_motorized_wheelchair\":\"fa4cb6b.svg\",\"woman_in_motorized_wheelchair_tone1\":\"ec04498.svg\",\"woman_in_motorized_wheelchair_light_skin_tone\":\"ec04498.svg\",\"woman_in_motorized_wheelchair_tone2\":\"67b6621.svg\",\"woman_in_motorized_wheelchair_medium_light_skin_tone\":\"67b6621.svg\",\"woman_in_motorized_wheelchair_tone3\":\"b63086c.svg\",\"woman_in_motorized_wheelchair_medium_skin_tone\":\"b63086c.svg\",\"woman_in_motorized_wheelchair_tone4\":\"0f8297e.svg\",\"woman_in_motorized_wheelchair_medium_dark_skin_tone\":\"0f8297e.svg\",\"woman_in_motorized_wheelchair_tone5\":\"7bc88ca.svg\",\"woman_in_motorized_wheelchair_dark_skin_tone\":\"7bc88ca.svg\",\"man_in_motorized_wheelchair\":\"af8954f.svg\",\"man_in_motorized_wheelchair_tone1\":\"db8adc1.svg\",\"man_in_motorized_wheelchair_light_skin_tone\":\"db8adc1.svg\",\"man_in_motorized_wheelchair_tone2\":\"b6dd254.svg\",\"man_in_motorized_wheelchair_medium_light_skin_tone\":\"b6dd254.svg\",\"man_in_motorized_wheelchair_tone3\":\"3a72c60.svg\",\"man_in_motorized_wheelchair_medium_skin_tone\":\"3a72c60.svg\",\"man_in_motorized_wheelchair_tone4\":\"a286a6a.svg\",\"man_in_motorized_wheelchair_medium_dark_skin_tone\":\"a286a6a.svg\",\"man_in_motorized_wheelchair_tone5\":\"31dffd1.svg\",\"man_in_motorized_wheelchair_dark_skin_tone\":\"31dffd1.svg\",\"person_walking\":\"65f60ce.svg\",\"walking\":\"65f60ce.svg\",\"person_walking_tone1\":\"d6a801f.svg\",\"walking_tone1\":\"d6a801f.svg\",\"person_walking_tone2\":\"0303228.svg\",\"walking_tone2\":\"0303228.svg\",\"person_walking_tone3\":\"3943f9e.svg\",\"walking_tone3\":\"3943f9e.svg\",\"person_walking_tone4\":\"95a9b35.svg\",\"walking_tone4\":\"95a9b35.svg\",\"person_walking_tone5\":\"cc5ec42.svg\",\"walking_tone5\":\"cc5ec42.svg\",\"woman_walking\":\"6598a59.svg\",\"woman_walking_tone1\":\"45c2450.svg\",\"woman_walking_light_skin_tone\":\"45c2450.svg\",\"woman_walking_tone2\":\"ad46e39.svg\",\"woman_walking_medium_light_skin_tone\":\"ad46e39.svg\",\"woman_walking_tone3\":\"654c09d.svg\",\"woman_walking_medium_skin_tone\":\"654c09d.svg\",\"woman_walking_tone4\":\"39b56ca.svg\",\"woman_walking_medium_dark_skin_tone\":\"39b56ca.svg\",\"woman_walking_tone5\":\"30ef6bd.svg\",\"woman_walking_dark_skin_tone\":\"30ef6bd.svg\",\"man_walking\":\"9c36511.svg\",\"man_walking_tone1\":\"0d6f57e.svg\",\"man_walking_light_skin_tone\":\"0d6f57e.svg\",\"man_walking_tone2\":\"fc77377.svg\",\"man_walking_medium_light_skin_tone\":\"fc77377.svg\",\"man_walking_tone3\":\"ee7f10a.svg\",\"man_walking_medium_skin_tone\":\"ee7f10a.svg\",\"man_walking_tone4\":\"b3cb34d.svg\",\"man_walking_medium_dark_skin_tone\":\"b3cb34d.svg\",\"man_walking_tone5\":\"89abc50.svg\",\"man_walking_dark_skin_tone\":\"89abc50.svg\",\"person_with_probing_cane\":\"887fd29.svg\",\"person_with_probing_cane_tone1\":\"ef344e8.svg\",\"person_with_probing_cane_light_skin_tone\":\"ef344e8.svg\",\"person_with_probing_cane_tone2\":\"ac74bd6.svg\",\"person_with_probing_cane_medium_light_skin_tone\":\"ac74bd6.svg\",\"person_with_probing_cane_tone3\":\"44e8e57.svg\",\"person_with_probing_cane_medium_skin_tone\":\"44e8e57.svg\",\"person_with_probing_cane_tone4\":\"6ae8265.svg\",\"person_with_probing_cane_medium_dark_skin_tone\":\"6ae8265.svg\",\"person_with_probing_cane_tone5\":\"0db34f2.svg\",\"person_with_probing_cane_dark_skin_tone\":\"0db34f2.svg\",\"woman_with_probing_cane\":\"88b2d91.svg\",\"woman_with_probing_cane_tone1\":\"cca5c5f.svg\",\"woman_with_probing_cane_light_skin_tone\":\"cca5c5f.svg\",\"woman_with_probing_cane_tone2\":\"f17fa9f.svg\",\"woman_with_probing_cane_medium_light_skin_tone\":\"f17fa9f.svg\",\"woman_with_probing_cane_tone3\":\"90a4d48.svg\",\"woman_with_probing_cane_medium_skin_tone\":\"90a4d48.svg\",\"woman_with_probing_cane_tone4\":\"c3f9228.svg\",\"woman_with_probing_cane_medium_dark_skin_tone\":\"c3f9228.svg\",\"woman_with_probing_cane_tone5\":\"47af028.svg\",\"woman_with_probing_cane_dark_skin_tone\":\"47af028.svg\",\"man_with_probing_cane\":\"642663b.svg\",\"man_with_probing_cane_tone1\":\"e606600.svg\",\"man_with_probing_cane_light_skin_tone\":\"e606600.svg\",\"man_with_probing_cane_tone3\":\"ae4530a.svg\",\"man_with_probing_cane_medium_skin_tone\":\"ae4530a.svg\",\"man_with_probing_cane_tone2\":\"b8fd4db.svg\",\"man_with_probing_cane_medium_light_skin_tone\":\"b8fd4db.svg\",\"man_with_probing_cane_tone4\":\"528cd32.svg\",\"man_with_probing_cane_medium_dark_skin_tone\":\"528cd32.svg\",\"man_with_probing_cane_tone5\":\"5148180.svg\",\"man_with_probing_cane_dark_skin_tone\":\"5148180.svg\",\"person_kneeling\":\"f567a4e.svg\",\"person_kneeling_tone1\":\"ff08ed5.svg\",\"person_kneeling_light_skin_tone\":\"ff08ed5.svg\",\"person_kneeling_tone2\":\"680a5a2.svg\",\"person_kneeling_medium_light_skin_tone\":\"680a5a2.svg\",\"person_kneeling_tone3\":\"4278f87.svg\",\"person_kneeling_medium_skin_tone\":\"4278f87.svg\",\"person_kneeling_tone4\":\"423f6d6.svg\",\"person_kneeling_medium_dark_skin_tone\":\"423f6d6.svg\",\"person_kneeling_tone5\":\"84c6b50.svg\",\"person_kneeling_dark_skin_tone\":\"84c6b50.svg\",\"woman_kneeling\":\"ed2af90.svg\",\"woman_kneeling_tone1\":\"25de7c5.svg\",\"woman_kneeling_light_skin_tone\":\"25de7c5.svg\",\"woman_kneeling_tone2\":\"0f4b629.svg\",\"woman_kneeling_medium_light_skin_tone\":\"0f4b629.svg\",\"woman_kneeling_tone3\":\"65c5945.svg\",\"woman_kneeling_medium_skin_tone\":\"65c5945.svg\",\"woman_kneeling_tone4\":\"0de34a1.svg\",\"woman_kneeling_medium_dark_skin_tone\":\"0de34a1.svg\",\"woman_kneeling_tone5\":\"7c7ac31.svg\",\"woman_kneeling_dark_skin_tone\":\"7c7ac31.svg\",\"man_kneeling\":\"ff6c0be.svg\",\"man_kneeling_tone1\":\"9bb3f4c.svg\",\"man_kneeling_light_skin_tone\":\"9bb3f4c.svg\",\"man_kneeling_tone2\":\"2b54d90.svg\",\"man_kneeling_medium_light_skin_tone\":\"2b54d90.svg\",\"man_kneeling_tone3\":\"cefb539.svg\",\"man_kneeling_medium_skin_tone\":\"cefb539.svg\",\"man_kneeling_tone4\":\"9b36f24.svg\",\"man_kneeling_medium_dark_skin_tone\":\"9b36f24.svg\",\"man_kneeling_tone5\":\"76b7f90.svg\",\"man_kneeling_dark_skin_tone\":\"76b7f90.svg\",\"person_running\":\"14a1805.svg\",\"runner\":\"14a1805.svg\",\"person_running_tone1\":\"e38b1e2.svg\",\"runner_tone1\":\"e38b1e2.svg\",\"person_running_tone2\":\"e3dc02b.svg\",\"runner_tone2\":\"e3dc02b.svg\",\"person_running_tone3\":\"07092d7.svg\",\"runner_tone3\":\"07092d7.svg\",\"person_running_tone4\":\"ff8fb96.svg\",\"runner_tone4\":\"ff8fb96.svg\",\"person_running_tone5\":\"db3fcb5.svg\",\"runner_tone5\":\"db3fcb5.svg\",\"woman_running\":\"54428e4.svg\",\"woman_running_tone1\":\"7e37d8c.svg\",\"woman_running_light_skin_tone\":\"7e37d8c.svg\",\"woman_running_tone2\":\"93b8bdf.svg\",\"woman_running_medium_light_skin_tone\":\"93b8bdf.svg\",\"woman_running_tone3\":\"6e25d9b.svg\",\"woman_running_medium_skin_tone\":\"6e25d9b.svg\",\"woman_running_tone4\":\"f608102.svg\",\"woman_running_medium_dark_skin_tone\":\"f608102.svg\",\"woman_running_tone5\":\"ea57c5b.svg\",\"woman_running_dark_skin_tone\":\"ea57c5b.svg\",\"man_running\":\"24b7322.svg\",\"man_running_tone1\":\"df099d9.svg\",\"man_running_light_skin_tone\":\"df099d9.svg\",\"man_running_tone2\":\"692c6c7.svg\",\"man_running_medium_light_skin_tone\":\"692c6c7.svg\",\"man_running_tone3\":\"f3a32e6.svg\",\"man_running_medium_skin_tone\":\"f3a32e6.svg\",\"man_running_tone4\":\"c7b7abe.svg\",\"man_running_medium_dark_skin_tone\":\"c7b7abe.svg\",\"man_running_tone5\":\"6692d4b.svg\",\"man_running_dark_skin_tone\":\"6692d4b.svg\",\"person_standing\":\"44c7448.svg\",\"person_standing_tone1\":\"8cff530.svg\",\"person_standing_light_skin_tone\":\"8cff530.svg\",\"person_standing_tone2\":\"8533db2.svg\",\"person_standing_medium_light_skin_tone\":\"8533db2.svg\",\"person_standing_tone3\":\"80db0f5.svg\",\"person_standing_medium_skin_tone\":\"80db0f5.svg\",\"person_standing_tone4\":\"b8e5e63.svg\",\"person_standing_medium_dark_skin_tone\":\"b8e5e63.svg\",\"person_standing_tone5\":\"f111f67.svg\",\"person_standing_dark_skin_tone\":\"f111f67.svg\",\"woman_standing\":\"fa8c4a0.svg\",\"woman_standing_tone1\":\"cf856b3.svg\",\"woman_standing_light_skin_tone\":\"cf856b3.svg\",\"woman_standing_tone2\":\"1e2288e.svg\",\"woman_standing_medium_light_skin_tone\":\"1e2288e.svg\",\"woman_standing_tone3\":\"d80e460.svg\",\"woman_standing_medium_skin_tone\":\"d80e460.svg\",\"woman_standing_tone4\":\"85b7da4.svg\",\"woman_standing_medium_dark_skin_tone\":\"85b7da4.svg\",\"woman_standing_tone5\":\"e38a4ab.svg\",\"woman_standing_dark_skin_tone\":\"e38a4ab.svg\",\"man_standing\":\"aa33f3f.svg\",\"man_standing_tone1\":\"cc40d0d.svg\",\"man_standing_light_skin_tone\":\"cc40d0d.svg\",\"man_standing_tone2\":\"d5128b4.svg\",\"man_standing_medium_light_skin_tone\":\"d5128b4.svg\",\"man_standing_tone3\":\"14fe4be.svg\",\"man_standing_medium_skin_tone\":\"14fe4be.svg\",\"man_standing_tone4\":\"20adb5e.svg\",\"man_standing_medium_dark_skin_tone\":\"20adb5e.svg\",\"man_standing_tone5\":\"b6ba2e8.svg\",\"man_standing_dark_skin_tone\":\"b6ba2e8.svg\",\"people_holding_hands\":\"4c2921a.svg\",\"people_holding_hands_tone1\":\"23acced.svg\",\"people_holding_hands_light_skin_tone\":\"23acced.svg\",\"people_holding_hands_tone1_tone2\":\"3339791.svg\",\"people_holding_hands_light_skin_tone_medium_light_skin_tone\":\"3339791.svg\",\"people_holding_hands_tone1_tone3\":\"58cee68.svg\",\"people_holding_hands_light_skin_tone_medium_skin_tone\":\"58cee68.svg\",\"people_holding_hands_tone1_tone4\":\"9ebfdf3.svg\",\"people_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"9ebfdf3.svg\",\"people_holding_hands_tone1_tone5\":\"29a99d5.svg\",\"people_holding_hands_light_skin_tone_dark_skin_tone\":\"29a99d5.svg\",\"people_holding_hands_tone2_tone1\":\"d3bc4f8.svg\",\"people_holding_hands_medium_light_skin_tone_light_skin_tone\":\"d3bc4f8.svg\",\"people_holding_hands_tone2\":\"39d4330.svg\",\"people_holding_hands_medium_light_skin_tone\":\"39d4330.svg\",\"people_holding_hands_tone2_tone3\":\"24662bc.svg\",\"people_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"24662bc.svg\",\"people_holding_hands_tone2_tone4\":\"9620340.svg\",\"people_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"9620340.svg\",\"people_holding_hands_tone2_tone5\":\"07db777.svg\",\"people_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"07db777.svg\",\"people_holding_hands_tone3_tone1\":\"787c7ae.svg\",\"people_holding_hands_medium_skin_tone_light_skin_tone\":\"787c7ae.svg\",\"people_holding_hands_tone3_tone2\":\"f84075b.svg\",\"people_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"f84075b.svg\",\"people_holding_hands_tone3\":\"25ef13b.svg\",\"people_holding_hands_medium_skin_tone\":\"25ef13b.svg\",\"people_holding_hands_tone3_tone4\":\"9b75f7a.svg\",\"people_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"9b75f7a.svg\",\"people_holding_hands_tone3_tone5\":\"fd33f12.svg\",\"people_holding_hands_medium_skin_tone_dark_skin_tone\":\"fd33f12.svg\",\"people_holding_hands_tone4_tone1\":\"d450d92.svg\",\"people_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"d450d92.svg\",\"people_holding_hands_tone4_tone2\":\"06a0c9a.svg\",\"people_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"06a0c9a.svg\",\"people_holding_hands_tone4_tone3\":\"509577c.svg\",\"people_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"509577c.svg\",\"people_holding_hands_tone4\":\"7629eeb.svg\",\"people_holding_hands_medium_dark_skin_tone\":\"7629eeb.svg\",\"people_holding_hands_tone4_tone5\":\"06f01ca.svg\",\"people_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"06f01ca.svg\",\"people_holding_hands_tone5_tone1\":\"ee997a3.svg\",\"people_holding_hands_dark_skin_tone_light_skin_tone\":\"ee997a3.svg\",\"people_holding_hands_tone5_tone2\":\"fb5155b.svg\",\"people_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"fb5155b.svg\",\"people_holding_hands_tone5_tone3\":\"33faa2b.svg\",\"people_holding_hands_dark_skin_tone_medium_skin_tone\":\"33faa2b.svg\",\"people_holding_hands_tone5_tone4\":\"b9084e9.svg\",\"people_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"b9084e9.svg\",\"people_holding_hands_tone5\":\"fabdfad.svg\",\"people_holding_hands_dark_skin_tone\":\"fabdfad.svg\",\"couple\":\"35af177.svg\",\"woman_and_man_holding_hands_tone1\":\"5e3020f.svg\",\"woman_and_man_holding_hands_light_skin_tone\":\"5e3020f.svg\",\"woman_and_man_holding_hands_tone1_tone2\":\"8531337.svg\",\"woman_and_man_holding_hands_light_skin_tone_medium_light_skin_tone\":\"8531337.svg\",\"woman_and_man_holding_hands_tone1_tone3\":\"0b38682.svg\",\"woman_and_man_holding_hands_light_skin_tone_medium_skin_tone\":\"0b38682.svg\",\"woman_and_man_holding_hands_tone1_tone4\":\"19257a4.svg\",\"woman_and_man_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"19257a4.svg\",\"woman_and_man_holding_hands_tone1_tone5\":\"e7da92e.svg\",\"woman_and_man_holding_hands_light_skin_tone_dark_skin_tone\":\"e7da92e.svg\",\"woman_and_man_holding_hands_tone2_tone1\":\"83ccc36.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone\":\"83ccc36.svg\",\"woman_and_man_holding_hands_tone2\":\"bb20c0b.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone\":\"bb20c0b.svg\",\"woman_and_man_holding_hands_tone2_tone3\":\"bf9dd09.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"bf9dd09.svg\",\"woman_and_man_holding_hands_tone2_tone4\":\"b177d3a.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"b177d3a.svg\",\"woman_and_man_holding_hands_tone2_tone5\":\"534b32d.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"534b32d.svg\",\"woman_and_man_holding_hands_tone3_tone1\":\"c7dc261.svg\",\"woman_and_man_holding_hands_medium_skin_tone_light_skin_tone\":\"c7dc261.svg\",\"woman_and_man_holding_hands_tone3_tone2\":\"0bbaf07.svg\",\"woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"0bbaf07.svg\",\"woman_and_man_holding_hands_tone3\":\"4397176.svg\",\"woman_and_man_holding_hands_medium_skin_tone\":\"4397176.svg\",\"woman_and_man_holding_hands_tone3_tone4\":\"20a298a.svg\",\"woman_and_man_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"20a298a.svg\",\"woman_and_man_holding_hands_tone3_tone5\":\"0f5431e.svg\",\"woman_and_man_holding_hands_medium_skin_tone_dark_skin_tone\":\"0f5431e.svg\",\"woman_and_man_holding_hands_tone4_tone1\":\"49419da.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"49419da.svg\",\"woman_and_man_holding_hands_tone4_tone2\":\"9c70a54.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"9c70a54.svg\",\"woman_and_man_holding_hands_tone4_tone3\":\"1428bea.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"1428bea.svg\",\"woman_and_man_holding_hands_tone4\":\"ec98a92.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone\":\"ec98a92.svg\",\"woman_and_man_holding_hands_tone4_tone5\":\"ae856c7.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"ae856c7.svg\",\"woman_and_man_holding_hands_tone5_tone1\":\"60a7744.svg\",\"woman_and_man_holding_hands_dark_skin_tone_light_skin_tone\":\"60a7744.svg\",\"woman_and_man_holding_hands_tone5_tone2\":\"ec2337f.svg\",\"woman_and_man_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"ec2337f.svg\",\"woman_and_man_holding_hands_tone5_tone3\":\"3c1d8c6.svg\",\"woman_and_man_holding_hands_dark_skin_tone_medium_skin_tone\":\"3c1d8c6.svg\",\"woman_and_man_holding_hands_tone5_tone4\":\"91c8276.svg\",\"woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"91c8276.svg\",\"woman_and_man_holding_hands_tone5\":\"c118d19.svg\",\"woman_and_man_holding_hands_dark_skin_tone\":\"c118d19.svg\",\"two_women_holding_hands\":\"d4d81a7.svg\",\"women_holding_hands_tone1\":\"9f3a904.svg\",\"women_holding_hands_light_skin_tone\":\"9f3a904.svg\",\"women_holding_hands_tone1_tone2\":\"f019f2d.svg\",\"women_holding_hands_light_skin_tone_medium_light_skin_tone\":\"f019f2d.svg\",\"women_holding_hands_tone1_tone3\":\"2b0d304.svg\",\"women_holding_hands_light_skin_tone_medium_skin_tone\":\"2b0d304.svg\",\"women_holding_hands_tone1_tone4\":\"ca03ea3.svg\",\"women_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"ca03ea3.svg\",\"women_holding_hands_tone1_tone5\":\"2e472d0.svg\",\"women_holding_hands_light_skin_tone_dark_skin_tone\":\"2e472d0.svg\",\"women_holding_hands_tone2_tone1\":\"10a59fd.svg\",\"women_holding_hands_medium_light_skin_tone_light_skin_tone\":\"10a59fd.svg\",\"women_holding_hands_tone2\":\"3957d42.svg\",\"women_holding_hands_medium_light_skin_tone\":\"3957d42.svg\",\"women_holding_hands_tone2_tone3\":\"dc3bab4.svg\",\"women_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"dc3bab4.svg\",\"women_holding_hands_tone2_tone4\":\"40b1b87.svg\",\"women_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"40b1b87.svg\",\"women_holding_hands_tone2_tone5\":\"3fe54bb.svg\",\"women_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"3fe54bb.svg\",\"women_holding_hands_tone3_tone1\":\"09efefb.svg\",\"women_holding_hands_medium_skin_tone_light_skin_tone\":\"09efefb.svg\",\"women_holding_hands_tone3_tone2\":\"2c1246c.svg\",\"women_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"2c1246c.svg\",\"women_holding_hands_tone3\":\"416f28b.svg\",\"women_holding_hands_medium_skin_tone\":\"416f28b.svg\",\"women_holding_hands_tone3_tone4\":\"42f3168.svg\",\"women_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"42f3168.svg\",\"women_holding_hands_tone3_tone5\":\"71f5c02.svg\",\"women_holding_hands_medium_skin_tone_dark_skin_tone\":\"71f5c02.svg\",\"women_holding_hands_tone4_tone1\":\"45391b2.svg\",\"women_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"45391b2.svg\",\"women_holding_hands_tone4_tone2\":\"61fa36f.svg\",\"women_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"61fa36f.svg\",\"women_holding_hands_tone4_tone3\":\"7fdd172.svg\",\"women_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"7fdd172.svg\",\"women_holding_hands_tone4\":\"e121f44.svg\",\"women_holding_hands_medium_dark_skin_tone\":\"e121f44.svg\",\"women_holding_hands_tone4_tone5\":\"b9907f1.svg\",\"women_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"b9907f1.svg\",\"women_holding_hands_tone5_tone1\":\"894fd21.svg\",\"women_holding_hands_dark_skin_tone_light_skin_tone\":\"894fd21.svg\",\"women_holding_hands_tone5_tone2\":\"30f422c.svg\",\"women_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"30f422c.svg\",\"women_holding_hands_tone5_tone3\":\"459c4cc.svg\",\"women_holding_hands_dark_skin_tone_medium_skin_tone\":\"459c4cc.svg\",\"women_holding_hands_tone5_tone4\":\"d2f51cf.svg\",\"women_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"d2f51cf.svg\",\"women_holding_hands_tone5\":\"cb0d7e2.svg\",\"women_holding_hands_dark_skin_tone\":\"cb0d7e2.svg\",\"two_men_holding_hands\":\"46278c1.svg\",\"men_holding_hands_tone1\":\"25a7f2b.svg\",\"men_holding_hands_light_skin_tone\":\"25a7f2b.svg\",\"men_holding_hands_tone1_tone2\":\"13e0905.svg\",\"men_holding_hands_light_skin_tone_medium_light_skin_tone\":\"13e0905.svg\",\"men_holding_hands_tone1_tone3\":\"7011592.svg\",\"men_holding_hands_light_skin_tone_medium_skin_tone\":\"7011592.svg\",\"men_holding_hands_tone1_tone4\":\"e5a0c51.svg\",\"men_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"e5a0c51.svg\",\"men_holding_hands_tone1_tone5\":\"a07ee13.svg\",\"men_holding_hands_light_skin_tone_dark_skin_tone\":\"a07ee13.svg\",\"men_holding_hands_tone2_tone1\":\"2875f82.svg\",\"men_holding_hands_medium_light_skin_tone_light_skin_tone\":\"2875f82.svg\",\"men_holding_hands_tone2\":\"dcbf89b.svg\",\"men_holding_hands_medium_light_skin_tone\":\"dcbf89b.svg\",\"men_holding_hands_tone2_tone3\":\"3b37bb4.svg\",\"men_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"3b37bb4.svg\",\"men_holding_hands_tone2_tone4\":\"28e9236.svg\",\"men_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"28e9236.svg\",\"men_holding_hands_tone2_tone5\":\"a96dce6.svg\",\"men_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"a96dce6.svg\",\"men_holding_hands_tone3_tone1\":\"65628cf.svg\",\"men_holding_hands_medium_skin_tone_light_skin_tone\":\"65628cf.svg\",\"men_holding_hands_tone3_tone2\":\"742f722.svg\",\"men_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"742f722.svg\",\"men_holding_hands_tone3\":\"ce0b97d.svg\",\"men_holding_hands_medium_skin_tone\":\"ce0b97d.svg\",\"men_holding_hands_tone3_tone4\":\"3c716d7.svg\",\"men_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"3c716d7.svg\",\"men_holding_hands_tone3_tone5\":\"cf7ed37.svg\",\"men_holding_hands_medium_skin_tone_dark_skin_tone\":\"cf7ed37.svg\",\"men_holding_hands_tone4_tone1\":\"0a49ab6.svg\",\"men_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"0a49ab6.svg\",\"men_holding_hands_tone4_tone2\":\"3162d59.svg\",\"men_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"3162d59.svg\",\"men_holding_hands_tone4_tone3\":\"bc00cff.svg\",\"men_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"bc00cff.svg\",\"men_holding_hands_tone4\":\"56b1d4c.svg\",\"men_holding_hands_medium_dark_skin_tone\":\"56b1d4c.svg\",\"men_holding_hands_tone4_tone5\":\"6271f0e.svg\",\"men_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"6271f0e.svg\",\"men_holding_hands_tone5_tone1\":\"7c83af9.svg\",\"men_holding_hands_dark_skin_tone_light_skin_tone\":\"7c83af9.svg\",\"men_holding_hands_tone5_tone2\":\"09a7f65.svg\",\"men_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"09a7f65.svg\",\"men_holding_hands_tone5_tone3\":\"b4c7538.svg\",\"men_holding_hands_dark_skin_tone_medium_skin_tone\":\"b4c7538.svg\",\"men_holding_hands_tone5_tone4\":\"4262f27.svg\",\"men_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"4262f27.svg\",\"men_holding_hands_tone5\":\"6d21918.svg\",\"men_holding_hands_dark_skin_tone\":\"6d21918.svg\",\"couple_with_heart\":\"af40bcf.svg\",\"couple_with_heart_tone1\":\"5f2b928.svg\",\"couple_with_heart_light_skin_tone\":\"5f2b928.svg\",\"couple_with_heart_person_person_tone1_tone2\":\"5176395.svg\",\"couple_with_heart_person_person_light_skin_tone_medium_light_skin_tone\":\"5176395.svg\",\"couple_with_heart_person_person_tone1_tone3\":\"08ddb48.svg\",\"couple_with_heart_person_person_light_skin_tone_medium_skin_tone\":\"08ddb48.svg\",\"couple_with_heart_person_person_tone1_tone4\":\"b660f3b.svg\",\"couple_with_heart_person_person_light_skin_tone_medium_dark_skin_tone\":\"b660f3b.svg\",\"couple_with_heart_person_person_tone1_tone5\":\"9a8cfb9.svg\",\"couple_with_heart_person_person_light_skin_tone_dark_skin_tone\":\"9a8cfb9.svg\",\"couple_with_heart_person_person_tone2_tone1\":\"d04e02d.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_light_skin_tone\":\"d04e02d.svg\",\"couple_with_heart_tone2\":\"fade9d8.svg\",\"couple_with_heart_medium_light_skin_tone\":\"fade9d8.svg\",\"couple_with_heart_person_person_tone2_tone3\":\"ab10672.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_medium_skin_tone\":\"ab10672.svg\",\"couple_with_heart_person_person_tone2_tone4\":\"4d7d08e.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_medium_dark_skin_tone\":\"4d7d08e.svg\",\"couple_with_heart_person_person_tone2_tone5\":\"d7ff730.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_dark_skin_tone\":\"d7ff730.svg\",\"couple_with_heart_person_person_tone3_tone1\":\"54caa13.svg\",\"couple_with_heart_person_person_medium_skin_tone_light_skin_tone\":\"54caa13.svg\",\"couple_with_heart_person_person_tone3_tone2\":\"f511868.svg\",\"couple_with_heart_person_person_medium_skin_tone_medium_light_skin_tone\":\"f511868.svg\",\"couple_with_heart_tone3\":\"daf06ce.svg\",\"couple_with_heart_medium_skin_tone\":\"daf06ce.svg\",\"couple_with_heart_person_person_tone3_tone4\":\"7778d77.svg\",\"couple_with_heart_person_person_medium_skin_tone_medium_dark_skin_tone\":\"7778d77.svg\",\"couple_with_heart_person_person_tone3_tone5\":\"976cf0c.svg\",\"couple_with_heart_person_person_medium_skin_tone_dark_skin_tone\":\"976cf0c.svg\",\"couple_with_heart_person_person_tone4_tone1\":\"d50905a.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_light_skin_tone\":\"d50905a.svg\",\"couple_with_heart_person_person_tone4_tone2\":\"0c9e773.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_medium_light_skin_tone\":\"0c9e773.svg\",\"couple_with_heart_person_person_tone4_tone3\":\"c9530eb.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_medium_skin_tone\":\"c9530eb.svg\",\"couple_with_heart_tone4\":\"94dfc9e.svg\",\"couple_with_heart_medium_dark_skin_tone\":\"94dfc9e.svg\",\"couple_with_heart_person_person_tone4_tone5\":\"3176f7e.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_dark_skin_tone\":\"3176f7e.svg\",\"couple_with_heart_person_person_tone5_tone1\":\"ad8ed70.svg\",\"couple_with_heart_person_person_dark_skin_tone_light_skin_tone\":\"ad8ed70.svg\",\"couple_with_heart_person_person_tone5_tone2\":\"df4b6c5.svg\",\"couple_with_heart_person_person_dark_skin_tone_medium_light_skin_tone\":\"df4b6c5.svg\",\"couple_with_heart_person_person_tone5_tone3\":\"fa7c3a9.svg\",\"couple_with_heart_person_person_dark_skin_tone_medium_skin_tone\":\"fa7c3a9.svg\",\"couple_with_heart_person_person_tone5_tone4\":\"76912c3.svg\",\"couple_with_heart_person_person_dark_skin_tone_medium_dark_skin_tone\":\"76912c3.svg\",\"couple_with_heart_tone5\":\"fa72e85.svg\",\"couple_with_heart_dark_skin_tone\":\"fa72e85.svg\",\"couple_with_heart_woman_man\":\"4ba9ae9.svg\",\"couple_with_heart_woman_man_tone1\":\"ee4737f.svg\",\"couple_with_heart_woman_man_light_skin_tone\":\"ee4737f.svg\",\"couple_with_heart_woman_man_tone1_tone2\":\"b7abde9.svg\",\"couple_with_heart_woman_man_light_skin_tone_medium_light_skin_tone\":\"b7abde9.svg\",\"couple_with_heart_woman_man_tone1_tone3\":\"25501c0.svg\",\"couple_with_heart_woman_man_light_skin_tone_medium_skin_tone\":\"25501c0.svg\",\"couple_with_heart_woman_man_tone1_tone4\":\"aa39f5c.svg\",\"couple_with_heart_woman_man_light_skin_tone_medium_dark_skin_tone\":\"aa39f5c.svg\",\"couple_with_heart_woman_man_tone1_tone5\":\"bf2d719.svg\",\"couple_with_heart_woman_man_light_skin_tone_dark_skin_tone\":\"bf2d719.svg\",\"couple_with_heart_woman_man_tone2_tone1\":\"6849f0b.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_light_skin_tone\":\"6849f0b.svg\",\"couple_with_heart_woman_man_tone2\":\"b2436ae.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone\":\"b2436ae.svg\",\"couple_with_heart_woman_man_tone2_tone3\":\"772964b.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_medium_skin_tone\":\"772964b.svg\",\"couple_with_heart_woman_man_tone2_tone4\":\"4d268fe.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_medium_dark_skin_tone\":\"4d268fe.svg\",\"couple_with_heart_woman_man_tone2_tone5\":\"0c875ad.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_dark_skin_tone\":\"0c875ad.svg\",\"couple_with_heart_woman_man_tone3_tone1\":\"9980aeb.svg\",\"couple_with_heart_woman_man_medium_skin_tone_light_skin_tone\":\"9980aeb.svg\",\"couple_with_heart_woman_man_tone3_tone2\":\"29ecd32.svg\",\"couple_with_heart_woman_man_medium_skin_tone_medium_light_skin_tone\":\"29ecd32.svg\",\"couple_with_heart_woman_man_tone3\":\"205b89c.svg\",\"couple_with_heart_woman_man_medium_skin_tone\":\"205b89c.svg\",\"couple_with_heart_woman_man_tone3_tone4\":\"9409034.svg\",\"couple_with_heart_woman_man_medium_skin_tone_medium_dark_skin_tone\":\"9409034.svg\",\"couple_with_heart_woman_man_tone3_tone5\":\"1473a1f.svg\",\"couple_with_heart_woman_man_medium_skin_tone_dark_skin_tone\":\"1473a1f.svg\",\"couple_with_heart_woman_man_tone4_tone1\":\"5e38999.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_light_skin_tone\":\"5e38999.svg\",\"couple_with_heart_woman_man_tone4_tone2\":\"4d463ce.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_medium_light_skin_tone\":\"4d463ce.svg\",\"couple_with_heart_woman_man_tone4_tone3\":\"1f3c617.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_medium_skin_tone\":\"1f3c617.svg\",\"couple_with_heart_woman_man_tone4\":\"64d398a.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone\":\"64d398a.svg\",\"couple_with_heart_woman_man_tone4_tone5\":\"b5d64a8.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_dark_skin_tone\":\"b5d64a8.svg\",\"couple_with_heart_woman_man_tone5_tone1\":\"e31437a.svg\",\"couple_with_heart_woman_man_dark_skin_tone_light_skin_tone\":\"e31437a.svg\",\"couple_with_heart_woman_man_tone5_tone2\":\"763373b.svg\",\"couple_with_heart_woman_man_dark_skin_tone_medium_light_skin_tone\":\"763373b.svg\",\"couple_with_heart_woman_man_tone5_tone3\":\"847a67d.svg\",\"couple_with_heart_woman_man_dark_skin_tone_medium_skin_tone\":\"847a67d.svg\",\"couple_with_heart_woman_man_tone5_tone4\":\"5c7b670.svg\",\"couple_with_heart_woman_man_dark_skin_tone_medium_dark_skin_tone\":\"5c7b670.svg\",\"couple_with_heart_woman_man_tone5\":\"e2192ab.svg\",\"couple_with_heart_woman_man_dark_skin_tone\":\"e2192ab.svg\",\"couple_ww\":\"a273046.svg\",\"couple_with_heart_ww\":\"a273046.svg\",\"couple_with_heart_woman_woman_tone1\":\"71a7732.svg\",\"couple_with_heart_woman_woman_light_skin_tone\":\"71a7732.svg\",\"couple_with_heart_woman_woman_tone1_tone2\":\"5b57cfd.svg\",\"couple_with_heart_woman_woman_light_skin_tone_medium_light_skin_tone\":\"5b57cfd.svg\",\"couple_with_heart_woman_woman_tone1_tone3\":\"83b48c0.svg\",\"couple_with_heart_woman_woman_light_skin_tone_medium_skin_tone\":\"83b48c0.svg\",\"couple_with_heart_woman_woman_tone1_tone4\":\"2167b7b.svg\",\"couple_with_heart_woman_woman_light_skin_tone_medium_dark_skin_tone\":\"2167b7b.svg\",\"couple_with_heart_woman_woman_tone1_tone5\":\"5291555.svg\",\"couple_with_heart_woman_woman_light_skin_tone_dark_skin_tone\":\"5291555.svg\",\"couple_with_heart_woman_woman_tone2_tone1\":\"7d11633.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_light_skin_tone\":\"7d11633.svg\",\"couple_with_heart_woman_woman_tone2\":\"4e8354b.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone\":\"4e8354b.svg\",\"couple_with_heart_woman_woman_tone2_tone3\":\"e816ed2.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_medium_skin_tone\":\"e816ed2.svg\",\"couple_with_heart_woman_woman_tone2_tone4\":\"6149103.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_medium_dark_skin_tone\":\"6149103.svg\",\"couple_with_heart_woman_woman_tone2_tone5\":\"68c7223.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_dark_skin_tone\":\"68c7223.svg\",\"couple_with_heart_woman_woman_tone3_tone1\":\"9cb0a5b.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_light_skin_tone\":\"9cb0a5b.svg\",\"couple_with_heart_woman_woman_tone3_tone2\":\"a3389b9.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_medium_light_skin_tone\":\"a3389b9.svg\",\"couple_with_heart_woman_woman_tone3\":\"ca8af0f.svg\",\"couple_with_heart_woman_woman_medium_skin_tone\":\"ca8af0f.svg\",\"couple_with_heart_woman_woman_tone3_tone4\":\"b5ddb1d.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_medium_dark_skin_tone\":\"b5ddb1d.svg\",\"couple_with_heart_woman_woman_tone3_tone5\":\"312590d.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_dark_skin_tone\":\"312590d.svg\",\"couple_with_heart_woman_woman_tone4_tone1\":\"cee38d3.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_light_skin_tone\":\"cee38d3.svg\",\"couple_with_heart_woman_woman_tone4_tone2\":\"2c3e8c7.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_medium_light_skin_tone\":\"2c3e8c7.svg\",\"couple_with_heart_woman_woman_tone4_tone3\":\"b31f429.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_medium_skin_tone\":\"b31f429.svg\",\"couple_with_heart_woman_woman_tone4\":\"ca98fa7.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone\":\"ca98fa7.svg\",\"couple_with_heart_woman_woman_tone4_tone5\":\"a30be68.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_dark_skin_tone\":\"a30be68.svg\",\"couple_with_heart_woman_woman_tone5_tone1\":\"45894b5.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_light_skin_tone\":\"45894b5.svg\",\"couple_with_heart_woman_woman_tone5_tone2\":\"f30a655.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_medium_light_skin_tone\":\"f30a655.svg\",\"couple_with_heart_woman_woman_tone5_tone3\":\"59ca073.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_medium_skin_tone\":\"59ca073.svg\",\"couple_with_heart_woman_woman_tone5_tone4\":\"05e04ee.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_medium_dark_skin_tone\":\"05e04ee.svg\",\"couple_with_heart_woman_woman_tone5\":\"bc34159.svg\",\"couple_with_heart_woman_woman_dark_skin_tone\":\"bc34159.svg\",\"couple_mm\":\"4f72e4d.svg\",\"couple_with_heart_mm\":\"4f72e4d.svg\",\"couple_with_heart_man_man_tone1\":\"e23ddc3.svg\",\"couple_with_heart_man_man_light_skin_tone\":\"e23ddc3.svg\",\"couple_with_heart_man_man_tone1_tone2\":\"727d29b.svg\",\"couple_with_heart_man_man_light_skin_tone_medium_light_skin_tone\":\"727d29b.svg\",\"couple_with_heart_man_man_tone1_tone3\":\"d92a25b.svg\",\"couple_with_heart_man_man_light_skin_tone_medium_skin_tone\":\"d92a25b.svg\",\"couple_with_heart_man_man_tone1_tone4\":\"7f8af18.svg\",\"couple_with_heart_man_man_light_skin_tone_medium_dark_skin_tone\":\"7f8af18.svg\",\"couple_with_heart_man_man_tone1_tone5\":\"801610f.svg\",\"couple_with_heart_man_man_light_skin_tone_dark_skin_tone\":\"801610f.svg\",\"couple_with_heart_man_man_tone2_tone1\":\"188b556.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_light_skin_tone\":\"188b556.svg\",\"couple_with_heart_man_man_tone2\":\"ea0b8e8.svg\",\"couple_with_heart_man_man_medium_light_skin_tone\":\"ea0b8e8.svg\",\"couple_with_heart_man_man_tone2_tone3\":\"cdd6d98.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_medium_skin_tone\":\"cdd6d98.svg\",\"couple_with_heart_man_man_tone2_tone4\":\"5c8241d.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_medium_dark_skin_tone\":\"5c8241d.svg\",\"couple_with_heart_man_man_tone2_tone5\":\"940ccbc.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_dark_skin_tone\":\"940ccbc.svg\",\"couple_with_heart_man_man_tone3_tone1\":\"5f78671.svg\",\"couple_with_heart_man_man_medium_skin_tone_light_skin_tone\":\"5f78671.svg\",\"couple_with_heart_man_man_tone3_tone2\":\"668c44a.svg\",\"couple_with_heart_man_man_medium_skin_tone_medium_light_skin_tone\":\"668c44a.svg\",\"couple_with_heart_man_man_tone3\":\"391f2e8.svg\",\"couple_with_heart_man_man_medium_skin_tone\":\"391f2e8.svg\",\"couple_with_heart_man_man_tone3_tone4\":\"bd2bbda.svg\",\"couple_with_heart_man_man_medium_skin_tone_medium_dark_skin_tone\":\"bd2bbda.svg\",\"couple_with_heart_man_man_tone3_tone5\":\"5432ce1.svg\",\"couple_with_heart_man_man_medium_skin_tone_dark_skin_tone\":\"5432ce1.svg\",\"couple_with_heart_man_man_tone4_tone1\":\"311f33b.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_light_skin_tone\":\"311f33b.svg\",\"couple_with_heart_man_man_tone4_tone2\":\"25ff44f.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_medium_light_skin_tone\":\"25ff44f.svg\",\"couple_with_heart_man_man_tone4_tone3\":\"2fcfd65.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_medium_skin_tone\":\"2fcfd65.svg\",\"couple_with_heart_man_man_tone4\":\"eeda17f.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone\":\"eeda17f.svg\",\"couple_with_heart_man_man_tone4_tone5\":\"9b6398f.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_dark_skin_tone\":\"9b6398f.svg\",\"couple_with_heart_man_man_tone5_tone1\":\"941a640.svg\",\"couple_with_heart_man_man_dark_skin_tone_light_skin_tone\":\"941a640.svg\",\"couple_with_heart_man_man_tone5_tone2\":\"41c12de.svg\",\"couple_with_heart_man_man_dark_skin_tone_medium_light_skin_tone\":\"41c12de.svg\",\"couple_with_heart_man_man_tone5_tone3\":\"d5c2770.svg\",\"couple_with_heart_man_man_dark_skin_tone_medium_skin_tone\":\"d5c2770.svg\",\"couple_with_heart_man_man_tone5_tone4\":\"3601c55.svg\",\"couple_with_heart_man_man_dark_skin_tone_medium_dark_skin_tone\":\"3601c55.svg\",\"couple_with_heart_man_man_tone5\":\"53a595a.svg\",\"couple_with_heart_man_man_dark_skin_tone\":\"53a595a.svg\",\"couplekiss\":\"50e9765.svg\",\"kiss_tone1\":\"e8abe66.svg\",\"kiss_light_skin_tone\":\"e8abe66.svg\",\"kiss_person_person_tone1_tone2\":\"5a8a06f.svg\",\"kiss_person_person_light_skin_tone_medium_light_skin_tone\":\"5a8a06f.svg\",\"kiss_person_person_tone1_tone3\":\"267fbc6.svg\",\"kiss_person_person_light_skin_tone_medium_skin_tone\":\"267fbc6.svg\",\"kiss_person_person_tone1_tone4\":\"2709814.svg\",\"kiss_person_person_light_skin_tone_medium_dark_skin_tone\":\"2709814.svg\",\"kiss_person_person_tone1_tone5\":\"5d74f10.svg\",\"kiss_person_person_light_skin_tone_dark_skin_tone\":\"5d74f10.svg\",\"kiss_person_person_tone2_tone1\":\"2a88f80.svg\",\"kiss_person_person_medium_light_skin_tone_light_skin_tone\":\"2a88f80.svg\",\"kiss_tone2\":\"7135329.svg\",\"kiss_medium_light_skin_tone\":\"7135329.svg\",\"kiss_person_person_tone2_tone3\":\"d8627da.svg\",\"kiss_person_person_medium_light_skin_tone_medium_skin_tone\":\"d8627da.svg\",\"kiss_person_person_tone2_tone4\":\"6fb3187.svg\",\"kiss_person_person_medium_light_skin_tone_medium_dark_skin_tone\":\"6fb3187.svg\",\"kiss_person_person_tone2_tone5\":\"c824563.svg\",\"kiss_person_person_medium_light_skin_tone_dark_skin_tone\":\"c824563.svg\",\"kiss_person_person_tone3_tone1\":\"9e29515.svg\",\"kiss_person_person_medium_skin_tone_light_skin_tone\":\"9e29515.svg\",\"kiss_person_person_tone3_tone2\":\"d2e0f25.svg\",\"kiss_person_person_medium_skin_tone_medium_light_skin_tone\":\"d2e0f25.svg\",\"kiss_tone3\":\"9d00a50.svg\",\"kiss_medium_skin_tone\":\"9d00a50.svg\",\"kiss_person_person_tone3_tone4\":\"0a6fff3.svg\",\"kiss_person_person_medium_skin_tone_medium_dark_skin_tone\":\"0a6fff3.svg\",\"kiss_person_person_tone3_tone5\":\"3daef15.svg\",\"kiss_person_person_medium_skin_tone_dark_skin_tone\":\"3daef15.svg\",\"kiss_person_person_tone4_tone1\":\"eabe6ef.svg\",\"kiss_person_person_medium_dark_skin_tone_light_skin_tone\":\"eabe6ef.svg\",\"kiss_person_person_tone4_tone2\":\"55e735c.svg\",\"kiss_person_person_medium_dark_skin_tone_medium_light_skin_tone\":\"55e735c.svg\",\"kiss_person_person_tone4_tone3\":\"d8da4fc.svg\",\"kiss_person_person_medium_dark_skin_tone_medium_skin_tone\":\"d8da4fc.svg\",\"kiss_tone4\":\"0d01700.svg\",\"kiss_medium_dark_skin_tone\":\"0d01700.svg\",\"kiss_person_person_tone4_tone5\":\"388581e.svg\",\"kiss_person_person_medium_dark_skin_tone_dark_skin_tone\":\"388581e.svg\",\"kiss_person_person_tone5_tone1\":\"9ee87dc.svg\",\"kiss_person_person_dark_skin_tone_light_skin_tone\":\"9ee87dc.svg\",\"kiss_person_person_tone5_tone2\":\"128699b.svg\",\"kiss_person_person_dark_skin_tone_medium_light_skin_tone\":\"128699b.svg\",\"kiss_person_person_tone5_tone3\":\"366a841.svg\",\"kiss_person_person_dark_skin_tone_medium_skin_tone\":\"366a841.svg\",\"kiss_person_person_tone5_tone4\":\"15f3606.svg\",\"kiss_person_person_dark_skin_tone_medium_dark_skin_tone\":\"15f3606.svg\",\"kiss_tone5\":\"2fc44b6.svg\",\"kiss_dark_skin_tone\":\"2fc44b6.svg\",\"kiss_woman_man\":\"0dbcb90.svg\",\"kiss_woman_man_tone1\":\"057900f.svg\",\"kiss_woman_man_light_skin_tone\":\"057900f.svg\",\"kiss_woman_man_tone1_tone2\":\"e10e63e.svg\",\"kiss_woman_man_light_skin_tone_medium_light_skin_tone\":\"e10e63e.svg\",\"kiss_woman_man_tone1_tone3\":\"9bfefc3.svg\",\"kiss_woman_man_light_skin_tone_medium_skin_tone\":\"9bfefc3.svg\",\"kiss_woman_man_tone1_tone4\":\"c32ee52.svg\",\"kiss_woman_man_light_skin_tone_medium_dark_skin_tone\":\"c32ee52.svg\",\"kiss_woman_man_tone1_tone5\":\"2f31920.svg\",\"kiss_woman_man_light_skin_tone_dark_skin_tone\":\"2f31920.svg\",\"kiss_woman_man_tone2_tone1\":\"0d96135.svg\",\"kiss_woman_man_medium_light_skin_tone_light_skin_tone\":\"0d96135.svg\",\"kiss_woman_man_tone2\":\"a6f4310.svg\",\"kiss_woman_man_medium_light_skin_tone\":\"a6f4310.svg\",\"kiss_woman_man_tone2_tone3\":\"70cb75b.svg\",\"kiss_woman_man_medium_light_skin_tone_medium_skin_tone\":\"70cb75b.svg\",\"kiss_woman_man_tone2_tone4\":\"e78c495.svg\",\"kiss_woman_man_medium_light_skin_tone_medium_dark_skin_tone\":\"e78c495.svg\",\"kiss_woman_man_tone2_tone5\":\"5185f3c.svg\",\"kiss_woman_man_medium_light_skin_tone_dark_skin_tone\":\"5185f3c.svg\",\"kiss_woman_man_tone3_tone1\":\"ae871f6.svg\",\"kiss_woman_man_medium_skin_tone_light_skin_tone\":\"ae871f6.svg\",\"kiss_woman_man_tone3_tone2\":\"7d7c436.svg\",\"kiss_woman_man_medium_skin_tone_medium_light_skin_tone\":\"7d7c436.svg\",\"kiss_woman_man_tone3\":\"5fc84ac.svg\",\"kiss_woman_man_medium_skin_tone\":\"5fc84ac.svg\",\"kiss_woman_man_tone3_tone4\":\"2a54f60.svg\",\"kiss_woman_man_medium_skin_tone_medium_dark_skin_tone\":\"2a54f60.svg\",\"kiss_woman_man_tone3_tone5\":\"65f1649.svg\",\"kiss_woman_man_medium_skin_tone_dark_skin_tone\":\"65f1649.svg\",\"kiss_woman_man_tone4_tone1\":\"164ff1c.svg\",\"kiss_woman_man_medium_dark_skin_tone_light_skin_tone\":\"164ff1c.svg\",\"kiss_woman_man_tone4_tone2\":\"5cc97f6.svg\",\"kiss_woman_man_medium_dark_skin_tone_medium_light_skin_tone\":\"5cc97f6.svg\",\"kiss_woman_man_tone4_tone3\":\"e4dbeff.svg\",\"kiss_woman_man_medium_dark_skin_tone_medium_skin_tone\":\"e4dbeff.svg\",\"kiss_woman_man_tone4\":\"6d9c654.svg\",\"kiss_woman_man_medium_dark_skin_tone\":\"6d9c654.svg\",\"kiss_woman_man_tone4_tone5\":\"2b44647.svg\",\"kiss_woman_man_medium_dark_skin_tone_dark_skin_tone\":\"2b44647.svg\",\"kiss_woman_man_tone5_tone1\":\"c294edc.svg\",\"kiss_woman_man_dark_skin_tone_light_skin_tone\":\"c294edc.svg\",\"kiss_woman_man_tone5_tone2\":\"c83598f.svg\",\"kiss_woman_man_dark_skin_tone_medium_light_skin_tone\":\"c83598f.svg\",\"kiss_woman_man_tone5_tone3\":\"9b6ff37.svg\",\"kiss_woman_man_dark_skin_tone_medium_skin_tone\":\"9b6ff37.svg\",\"kiss_woman_man_tone5_tone4\":\"c8a9736.svg\",\"kiss_woman_man_dark_skin_tone_medium_dark_skin_tone\":\"c8a9736.svg\",\"kiss_woman_man_tone5\":\"20884e4.svg\",\"kiss_woman_man_dark_skin_tone\":\"20884e4.svg\",\"kiss_ww\":\"8178a91.svg\",\"couplekiss_ww\":\"8178a91.svg\",\"kiss_woman_woman_tone1\":\"f0778b5.svg\",\"kiss_woman_woman_light_skin_tone\":\"f0778b5.svg\",\"kiss_woman_woman_tone1_tone2\":\"903034d.svg\",\"kiss_woman_woman_light_skin_tone_medium_light_skin_tone\":\"903034d.svg\",\"kiss_woman_woman_tone1_tone3\":\"fe2f2c4.svg\",\"kiss_woman_woman_light_skin_tone_medium_skin_tone\":\"fe2f2c4.svg\",\"kiss_woman_woman_tone1_tone4\":\"b4d4817.svg\",\"kiss_woman_woman_light_skin_tone_medium_dark_skin_tone\":\"b4d4817.svg\",\"kiss_woman_woman_tone1_tone5\":\"d9d2b03.svg\",\"kiss_woman_woman_light_skin_tone_dark_skin_tone\":\"d9d2b03.svg\",\"kiss_woman_woman_tone2_tone1\":\"ae1d840.svg\",\"kiss_woman_woman_medium_light_skin_tone_light_skin_tone\":\"ae1d840.svg\",\"kiss_woman_woman_tone2\":\"bbab6f1.svg\",\"kiss_woman_woman_medium_light_skin_tone\":\"bbab6f1.svg\",\"kiss_woman_woman_tone2_tone3\":\"cc08ac5.svg\",\"kiss_woman_woman_medium_light_skin_tone_medium_skin_tone\":\"cc08ac5.svg\",\"kiss_woman_woman_tone2_tone4\":\"4435887.svg\",\"kiss_woman_woman_medium_light_skin_tone_medium_dark_skin_tone\":\"4435887.svg\",\"kiss_woman_woman_tone2_tone5\":\"ac198a6.svg\",\"kiss_woman_woman_medium_light_skin_tone_dark_skin_tone\":\"ac198a6.svg\",\"kiss_woman_woman_tone3_tone1\":\"c5422f9.svg\",\"kiss_woman_woman_medium_skin_tone_light_skin_tone\":\"c5422f9.svg\",\"kiss_woman_woman_tone3_tone2\":\"956ccaa.svg\",\"kiss_woman_woman_medium_skin_tone_medium_light_skin_tone\":\"956ccaa.svg\",\"kiss_woman_woman_tone3\":\"b93bbe7.svg\",\"kiss_woman_woman_medium_skin_tone\":\"b93bbe7.svg\",\"kiss_woman_woman_tone3_tone4\":\"854faa6.svg\",\"kiss_woman_woman_medium_skin_tone_medium_dark_skin_tone\":\"854faa6.svg\",\"kiss_woman_woman_tone3_tone5\":\"3fbb3c6.svg\",\"kiss_woman_woman_medium_skin_tone_dark_skin_tone\":\"3fbb3c6.svg\",\"kiss_woman_woman_tone4_tone1\":\"37b681c.svg\",\"kiss_woman_woman_medium_dark_skin_tone_light_skin_tone\":\"37b681c.svg\",\"kiss_woman_woman_tone4_tone2\":\"7c4d4cd.svg\",\"kiss_woman_woman_medium_dark_skin_tone_medium_light_skin_tone\":\"7c4d4cd.svg\",\"kiss_woman_woman_tone4_tone3\":\"7c4edd2.svg\",\"kiss_woman_woman_medium_dark_skin_tone_medium_skin_tone\":\"7c4edd2.svg\",\"kiss_woman_woman_tone4\":\"e789a7e.svg\",\"kiss_woman_woman_medium_dark_skin_tone\":\"e789a7e.svg\",\"kiss_woman_woman_tone4_tone5\":\"28414d1.svg\",\"kiss_woman_woman_medium_dark_skin_tone_dark_skin_tone\":\"28414d1.svg\",\"kiss_woman_woman_tone5_tone1\":\"171e3ec.svg\",\"kiss_woman_woman_dark_skin_tone_light_skin_tone\":\"171e3ec.svg\",\"kiss_woman_woman_tone5_tone2\":\"4f115af.svg\",\"kiss_woman_woman_dark_skin_tone_medium_light_skin_tone\":\"4f115af.svg\",\"kiss_woman_woman_tone5_tone3\":\"7a92f09.svg\",\"kiss_woman_woman_dark_skin_tone_medium_skin_tone\":\"7a92f09.svg\",\"kiss_woman_woman_tone5_tone4\":\"68ff21c.svg\",\"kiss_woman_woman_dark_skin_tone_medium_dark_skin_tone\":\"68ff21c.svg\",\"kiss_woman_woman_tone5\":\"a2d3381.svg\",\"kiss_woman_woman_dark_skin_tone\":\"a2d3381.svg\",\"kiss_mm\":\"6967070.svg\",\"couplekiss_mm\":\"6967070.svg\",\"kiss_man_man_tone1\":\"daebf04.svg\",\"kiss_man_man_light_skin_tone\":\"daebf04.svg\",\"kiss_man_man_tone1_tone2\":\"aaf5148.svg\",\"kiss_man_man_light_skin_tone_medium_light_skin_tone\":\"aaf5148.svg\",\"kiss_man_man_tone1_tone3\":\"4fe3ff4.svg\",\"kiss_man_man_light_skin_tone_medium_skin_tone\":\"4fe3ff4.svg\",\"kiss_man_man_tone1_tone4\":\"8b5b118.svg\",\"kiss_man_man_light_skin_tone_medium_dark_skin_tone\":\"8b5b118.svg\",\"kiss_man_man_tone1_tone5\":\"a63dd18.svg\",\"kiss_man_man_light_skin_tone_dark_skin_tone\":\"a63dd18.svg\",\"kiss_man_man_tone2_tone1\":\"1176193.svg\",\"kiss_man_man_medium_light_skin_tone_light_skin_tone\":\"1176193.svg\",\"kiss_man_man_tone2\":\"d1e279e.svg\",\"kiss_man_man_medium_light_skin_tone\":\"d1e279e.svg\",\"kiss_man_man_tone2_tone3\":\"5010cc5.svg\",\"kiss_man_man_medium_light_skin_tone_medium_skin_tone\":\"5010cc5.svg\",\"kiss_man_man_tone2_tone4\":\"97365b5.svg\",\"kiss_man_man_medium_light_skin_tone_medium_dark_skin_tone\":\"97365b5.svg\",\"kiss_man_man_tone2_tone5\":\"a03f828.svg\",\"kiss_man_man_medium_light_skin_tone_dark_skin_tone\":\"a03f828.svg\",\"kiss_man_man_tone3_tone1\":\"5cf78cd.svg\",\"kiss_man_man_medium_skin_tone_light_skin_tone\":\"5cf78cd.svg\",\"kiss_man_man_tone3_tone2\":\"eec1671.svg\",\"kiss_man_man_medium_skin_tone_medium_light_skin_tone\":\"eec1671.svg\",\"kiss_man_man_tone3\":\"ac16467.svg\",\"kiss_man_man_medium_skin_tone\":\"ac16467.svg\",\"kiss_man_man_tone3_tone4\":\"1f65a21.svg\",\"kiss_man_man_medium_skin_tone_medium_dark_skin_tone\":\"1f65a21.svg\",\"kiss_man_man_tone3_tone5\":\"2571aa8.svg\",\"kiss_man_man_medium_skin_tone_dark_skin_tone\":\"2571aa8.svg\",\"kiss_man_man_tone4_tone1\":\"ae94cdd.svg\",\"kiss_man_man_medium_dark_skin_tone_light_skin_tone\":\"ae94cdd.svg\",\"kiss_man_man_tone4_tone2\":\"af98b91.svg\",\"kiss_man_man_medium_dark_skin_tone_medium_light_skin_tone\":\"af98b91.svg\",\"kiss_man_man_tone4_tone3\":\"a5938b1.svg\",\"kiss_man_man_medium_dark_skin_tone_medium_skin_tone\":\"a5938b1.svg\",\"kiss_man_man_tone4\":\"cfbc60b.svg\",\"kiss_man_man_medium_dark_skin_tone\":\"cfbc60b.svg\",\"kiss_man_man_tone4_tone5\":\"23a3035.svg\",\"kiss_man_man_medium_dark_skin_tone_dark_skin_tone\":\"23a3035.svg\",\"kiss_man_man_tone5_tone1\":\"97c98e7.svg\",\"kiss_man_man_dark_skin_tone_light_skin_tone\":\"97c98e7.svg\",\"kiss_man_man_tone5_tone2\":\"f053a7d.svg\",\"kiss_man_man_dark_skin_tone_medium_light_skin_tone\":\"f053a7d.svg\",\"kiss_man_man_tone5_tone3\":\"6c64227.svg\",\"kiss_man_man_dark_skin_tone_medium_skin_tone\":\"6c64227.svg\",\"kiss_man_man_tone5_tone4\":\"bafdd3d.svg\",\"kiss_man_man_dark_skin_tone_medium_dark_skin_tone\":\"bafdd3d.svg\",\"kiss_man_man_tone5\":\"7a365d5.svg\",\"kiss_man_man_dark_skin_tone\":\"7a365d5.svg\",\"family\":\"f3080a8.svg\",\"family_man_woman_boy\":\"8ce0110.svg\",\"family_mwg\":\"54714d0.svg\",\"family_mwgb\":\"648ad9c.svg\",\"family_mwbb\":\"0731ba7.svg\",\"family_mwgg\":\"bfc9af4.svg\",\"family_wwb\":\"f89180c.svg\",\"family_wwg\":\"e3e4078.svg\",\"family_wwgb\":\"f12cc9f.svg\",\"family_wwbb\":\"944c106.svg\",\"family_wwgg\":\"68381fa.svg\",\"family_mmb\":\"0e8aeea.svg\",\"family_mmg\":\"1327dff.svg\",\"family_mmgb\":\"5daa081.svg\",\"family_mmbb\":\"fe59165.svg\",\"family_mmgg\":\"5e3f235.svg\",\"family_woman_boy\":\"62fa5ed.svg\",\"family_woman_girl\":\"686ecb5.svg\",\"family_woman_girl_boy\":\"9520cae.svg\",\"family_woman_boy_boy\":\"d50fdf4.svg\",\"family_woman_girl_girl\":\"f08e120.svg\",\"family_man_boy\":\"debae09.svg\",\"family_man_girl\":\"e097176.svg\",\"family_man_girl_boy\":\"6e8be23.svg\",\"family_man_boy_boy\":\"80017f3.svg\",\"family_man_girl_girl\":\"1d95b13.svg\",\"yarn\":\"43e5942.svg\",\"thread\":\"6f01cd8.svg\",\"coat\":\"a756b6d.svg\",\"lab_coat\":\"c22bdeb.svg\",\"safety_vest\":\"fe1b8e4.svg\",\"womans_clothes\":\"7683d2c.svg\",\"shirt\":\"0e8e17d.svg\",\"jeans\":\"74254b8.svg\",\"briefs\":\"d44cc00.svg\",\"shorts\":\"c1719f0.svg\",\"necktie\":\"bcfe0da.svg\",\"dress\":\"bcd31ac.svg\",\"bikini\":\"ad60a01.svg\",\"one_piece_swimsuit\":\"5ba709f.svg\",\"kimono\":\"ef81375.svg\",\"sari\":\"1e29b67.svg\",\"womans_flat_shoe\":\"3c3719b.svg\",\"high_heel\":\"324bebb.svg\",\"sandal\":\"1ded3e6.svg\",\"boot\":\"ae22de3.svg\",\"mans_shoe\":\"7162529.svg\",\"athletic_shoe\":\"0f41eb5.svg\",\"hiking_boot\":\"20ea4c3.svg\",\"thong_sandal\":\"5e729f4.svg\",\"socks\":\"10bf122.svg\",\"gloves\":\"827eb70.svg\",\"scarf\":\"0a15c48.svg\",\"tophat\":\"527228e.svg\",\"billed_cap\":\"cb444a5.svg\",\"womans_hat\":\"6176a41.svg\",\"mortar_board\":\"e26973e.svg\",\"helmet_with_cross\":\"135808c.svg\",\"helmet_with_white_cross\":\"135808c.svg\",\"military_helmet\":\"54f8c27.svg\",\"crown\":\"c3e9e36.svg\",\"ring\":\"2014936.svg\",\"pouch\":\"b371954.svg\",\"purse\":\"51824e6.svg\",\"handbag\":\"f5f7c00.svg\",\"briefcase\":\"08f6139.svg\",\"school_satchel\":\"af42baa.svg\",\"luggage\":\"f62ce09.svg\",\"eyeglasses\":\"23837f2.svg\",\"dark_sunglasses\":\"73f2977.svg\",\"goggles\":\"3c9969d.svg\",\"closed_umbrella\":\"cdabf7f.svg\",\"curly_haired\":\"146d347.svg\",\"red_haired\":\"0950cb4.svg\",\"white_haired\":\"dabdbec.svg\",\"bald\":\"3ef301d.svg\",\"dog\":\"3ccb464.svg\",\"cat\":\"e2ebe95.svg\",\"mouse\":\"f629f7d.svg\",\"hamster\":\"d07281d.svg\",\"rabbit\":\"4b797a9.svg\",\"fox\":\"6786a19.svg\",\"fox_face\":\"6786a19.svg\",\"bear\":\"d242a98.svg\",\"panda_face\":\"7a547a9.svg\",\"polar_bear\":\"d157692.svg\",\"koala\":\"c694c1d.svg\",\"tiger\":\"8875758.svg\",\"lion_face\":\"2957e30.svg\",\"lion\":\"2957e30.svg\",\"cow\":\"e003105.svg\",\"pig\":\"eb5e463.svg\",\"pig_nose\":\"c5891b9.svg\",\"frog\":\"0978222.svg\",\"monkey_face\":\"2c750b3.svg\",\"see_no_evil\":\"28d931d.svg\",\"hear_no_evil\":\"b06fe2f.svg\",\"speak_no_evil\":\"9ae86c5.svg\",\"monkey\":\"b9dedd9.svg\",\"chicken\":\"dc90644.svg\",\"penguin\":\"8b55d00.svg\",\"bird\":\"44973ab.svg\",\"baby_chick\":\"8c1a38f.svg\",\"hatching_chick\":\"73b21bf.svg\",\"hatched_chick\":\"f549882.svg\",\"duck\":\"01e958f.svg\",\"dodo\":\"5828b4b.svg\",\"eagle\":\"85327ee.svg\",\"owl\":\"f492bd3.svg\",\"bat\":\"821240b.svg\",\"wolf\":\"bdd08b6.svg\",\"boar\":\"a69fcbf.svg\",\"horse\":\"2d9abe9.svg\",\"unicorn\":\"8af1860.svg\",\"unicorn_face\":\"8af1860.svg\",\"bee\":\"3494a3a.svg\",\"bug\":\"d889001.svg\",\"butterfly\":\"638165b.svg\",\"snail\":\"7803ddf.svg\",\"worm\":\"11c85bb.svg\",\"lady_beetle\":\"fd3dd90.svg\",\"ant\":\"dcf8a67.svg\",\"fly\":\"7e58c3a.svg\",\"mosquito\":\"db9de23.svg\",\"cockroach\":\"f5066c9.svg\",\"beetle\":\"e3eaeeb.svg\",\"cricket\":\"315a214.svg\",\"spider\":\"45355c9.svg\",\"spider_web\":\"c5ad60d.svg\",\"scorpion\":\"2407882.svg\",\"turtle\":\"77a65b1.svg\",\"snake\":\"b49f0fe.svg\",\"lizard\":\"8615fbb.svg\",\"t_rex\":\"faeecb5.svg\",\"sauropod\":\"f03b670.svg\",\"octopus\":\"6ccec50.svg\",\"squid\":\"93f40d2.svg\",\"shrimp\":\"f0b0645.svg\",\"lobster\":\"c421b5f.svg\",\"crab\":\"d70bb64.svg\",\"blowfish\":\"5df5274.svg\",\"tropical_fish\":\"a800a26.svg\",\"fish\":\"169733f.svg\",\"seal\":\"6e87588.svg\",\"dolphin\":\"ca2e93d.svg\",\"whale\":\"fe7709b.svg\",\"whale2\":\"043cb5d.svg\",\"shark\":\"868bd9b.svg\",\"crocodile\":\"d08535e.svg\",\"tiger2\":\"4c0fd27.svg\",\"leopard\":\"17441b2.svg\",\"zebra\":\"62b20e1.svg\",\"gorilla\":\"ec170c1.svg\",\"orangutan\":\"aa04d6f.svg\",\"elephant\":\"ac19e02.svg\",\"mammoth\":\"6f6f5ef.svg\",\"bison\":\"c715b3b.svg\",\"hippopotamus\":\"b3f28d5.svg\",\"rhino\":\"3454677.svg\",\"rhinoceros\":\"3454677.svg\",\"dromedary_camel\":\"7533fdf.svg\",\"camel\":\"cc5d6a8.svg\",\"giraffe\":\"f957a7e.svg\",\"kangaroo\":\"419ee1c.svg\",\"water_buffalo\":\"653eea1.svg\",\"ox\":\"ced4876.svg\",\"cow2\":\"c7b24eb.svg\",\"racehorse\":\"8767732.svg\",\"pig2\":\"1fc6bf2.svg\",\"ram\":\"0c037b6.svg\",\"sheep\":\"9ea5d57.svg\",\"llama\":\"951cbdc.svg\",\"goat\":\"a8818ae.svg\",\"deer\":\"02bf0b4.svg\",\"dog2\":\"bc98734.svg\",\"poodle\":\"96f3e45.svg\",\"guide_dog\":\"27e2fca.svg\",\"service_dog\":\"cb230b5.svg\",\"cat2\":\"5ac09fa.svg\",\"black_cat\":\"5e424b9.svg\",\"rooster\":\"b53713a.svg\",\"turkey\":\"8564eee.svg\",\"peacock\":\"b8fd358.svg\",\"parrot\":\"c261148.svg\",\"swan\":\"465cea3.svg\",\"flamingo\":\"39308a0.svg\",\"dove\":\"f14ffc3.svg\",\"dove_of_peace\":\"f14ffc3.svg\",\"rabbit2\":\"1a97df2.svg\",\"raccoon\":\"50d5c58.svg\",\"skunk\":\"f4aa11d.svg\",\"badger\":\"5d92a7e.svg\",\"beaver\":\"52b6b8c.svg\",\"otter\":\"068f895.svg\",\"sloth\":\"3acaf10.svg\",\"mouse2\":\"61eb46a.svg\",\"rat\":\"dd81c25.svg\",\"chipmunk\":\"a161717.svg\",\"hedgehog\":\"3f641a9.svg\",\"feet\":\"7c3b4de.svg\",\"paw_prints\":\"7c3b4de.svg\",\"dragon\":\"c684bd5.svg\",\"dragon_face\":\"f448b81.svg\",\"cactus\":\"024570f.svg\",\"christmas_tree\":\"9b0d052.svg\",\"evergreen_tree\":\"4d0c026.svg\",\"deciduous_tree\":\"ba8daf3.svg\",\"palm_tree\":\"f2e66ab.svg\",\"seedling\":\"f8affca.svg\",\"herb\":\"ad39154.svg\",\"four_leaf_clover\":\"df35d4a.svg\",\"bamboo\":\"7496521.svg\",\"tanabata_tree\":\"91ca4fa.svg\",\"leaves\":\"068e911.svg\",\"fallen_leaf\":\"886a48a.svg\",\"maple_leaf\":\"9ae5fa7.svg\",\"feather\":\"8ff77f9.svg\",\"mushroom\":\"a67208b.svg\",\"shell\":\"0592258.svg\",\"rock\":\"e392535.svg\",\"wood\":\"1e0a8ec.svg\",\"ear_of_rice\":\"33d35a4.svg\",\"potted_plant\":\"0da4cbf.svg\",\"bouquet\":\"a2974d1.svg\",\"tulip\":\"48bb0a3.svg\",\"rose\":\"accbfe6.svg\",\"wilted_rose\":\"67bae71.svg\",\"wilted_flower\":\"67bae71.svg\",\"hibiscus\":\"513465b.svg\",\"cherry_blossom\":\"6204820.svg\",\"blossom\":\"73f14e9.svg\",\"sunflower\":\"b92dff6.svg\",\"sun_with_face\":\"60bb982.svg\",\"full_moon_with_face\":\"79ebe64.svg\",\"first_quarter_moon_with_face\":\"673c333.svg\",\"last_quarter_moon_with_face\":\"209492f.svg\",\"new_moon_with_face\":\"41511ee.svg\",\"full_moon\":\"6d25c78.svg\",\"waning_gibbous_moon\":\"d8c695f.svg\",\"last_quarter_moon\":\"1429a32.svg\",\"waning_crescent_moon\":\"68e8d59.svg\",\"new_moon\":\"44c72b8.svg\",\"waxing_crescent_moon\":\"2be5564.svg\",\"first_quarter_moon\":\"d1647fd.svg\",\"waxing_gibbous_moon\":\"f578f4a.svg\",\"crescent_moon\":\"74e0cd6.svg\",\"earth_americas\":\"24bfedb.svg\",\"earth_africa\":\"41440d6.svg\",\"earth_asia\":\"a6d7932.svg\",\"ringed_planet\":\"8e9f64b.svg\",\"dizzy\":\"1ad4ca7.svg\",\"star\":\"40ae1e8.svg\",\"star2\":\"2894cf6.svg\",\"zap\":\"6bd13c3.svg\",\"boom\":\"54f1411.svg\",\"fire\":\"fc3cdd9.svg\",\"flame\":\"fc3cdd9.svg\",\"cloud_tornado\":\"01dba25.svg\",\"cloud_with_tornado\":\"01dba25.svg\",\"rainbow\":\"d2577d6.svg\",\"white_sun_small_cloud\":\"3b149d9.svg\",\"white_sun_with_small_cloud\":\"3b149d9.svg\",\"partly_sunny\":\"c0ced7a.svg\",\"white_sun_cloud\":\"bce7696.svg\",\"white_sun_behind_cloud\":\"bce7696.svg\",\"white_sun_rain_cloud\":\"f85c555.svg\",\"white_sun_behind_cloud_with_rain\":\"f85c555.svg\",\"cloud_rain\":\"a3983f3.svg\",\"cloud_with_rain\":\"a3983f3.svg\",\"thunder_cloud_rain\":\"ef0448c.svg\",\"thunder_cloud_and_rain\":\"ef0448c.svg\",\"cloud_lightning\":\"33914f1.svg\",\"cloud_with_lightning\":\"33914f1.svg\",\"cloud_snow\":\"8469ee7.svg\",\"cloud_with_snow\":\"8469ee7.svg\",\"snowman\":\"fee310d.svg\",\"wind_blowing_face\":\"686ea7b.svg\",\"dash\":\"e8111bf.svg\",\"droplet\":\"57bf439.svg\",\"sweat_drops\":\"83189c4.svg\",\"ocean\":\"db6c885.svg\",\"fog\":\"2d0cc00.svg\",\"green_apple\":\"2698f57.svg\",\"apple\":\"9aa8526.svg\",\"pear\":\"b248cb9.svg\",\"tangerine\":\"150cca0.svg\",\"lemon\":\"6916b3b.svg\",\"banana\":\"de55a5a.svg\",\"watermelon\":\"69959c6.svg\",\"grapes\":\"653c308.svg\",\"blueberries\":\"31e80b2.svg\",\"strawberry\":\"f52278a.svg\",\"melon\":\"a5bac83.svg\",\"cherries\":\"56a7af8.svg\",\"peach\":\"c39295e.svg\",\"mango\":\"e4d91b8.svg\",\"pineapple\":\"466e1eb.svg\",\"coconut\":\"7cc0fe9.svg\",\"kiwi\":\"2399915.svg\",\"kiwifruit\":\"2399915.svg\",\"tomato\":\"d00d0c0.svg\",\"eggplant\":\"6238f3b.svg\",\"avocado\":\"3f5d895.svg\",\"olive\":\"3793899.svg\",\"broccoli\":\"3deb0a0.svg\",\"leafy_green\":\"b99ba4b.svg\",\"bell_pepper\":\"f3f9cbe.svg\",\"cucumber\":\"146d731.svg\",\"hot_pepper\":\"09edf0d.svg\",\"corn\":\"9a9a70f.svg\",\"carrot\":\"45af58f.svg\",\"garlic\":\"cb4b336.svg\",\"onion\":\"87204b6.svg\",\"potato\":\"a495bba.svg\",\"sweet_potato\":\"497c5db.svg\",\"croissant\":\"e56a95a.svg\",\"bagel\":\"135300b.svg\",\"bread\":\"e07342f.svg\",\"french_bread\":\"c5b8b00.svg\",\"baguette_bread\":\"c5b8b00.svg\",\"flatbread\":\"d5102ef.svg\",\"pretzel\":\"50ee080.svg\",\"cheese\":\"bf4fc04.svg\",\"cheese_wedge\":\"bf4fc04.svg\",\"egg\":\"316cb2e.svg\",\"cooking\":\"21c68e8.svg\",\"butter\":\"c125503.svg\",\"pancakes\":\"bfc4f54.svg\",\"waffle\":\"7895253.svg\",\"bacon\":\"dd2d7b5.svg\",\"cut_of_meat\":\"ea6e2c8.svg\",\"poultry_leg\":\"294e088.svg\",\"meat_on_bone\":\"e7d524b.svg\",\"hotdog\":\"c1cf757.svg\",\"hot_dog\":\"c1cf757.svg\",\"hamburger\":\"3dd4533.svg\",\"fries\":\"4abb8a9.svg\",\"pizza\":\"77a05f4.svg\",\"sandwich\":\"5e993f1.svg\",\"stuffed_flatbread\":\"a3280e2.svg\",\"stuffed_pita\":\"a3280e2.svg\",\"falafel\":\"a67ea38.svg\",\"taco\":\"2cd7996.svg\",\"burrito\":\"146b5e8.svg\",\"tamale\":\"c6d1faf.svg\",\"salad\":\"9590157.svg\",\"green_salad\":\"9590157.svg\",\"shallow_pan_of_food\":\"fc31e25.svg\",\"paella\":\"fc31e25.svg\",\"fondue\":\"dd52ac5.svg\",\"canned_food\":\"099b1a2.svg\",\"spaghetti\":\"e6a22ba.svg\",\"ramen\":\"ac86183.svg\",\"stew\":\"97aa48a.svg\",\"curry\":\"a1d2dc4.svg\",\"sushi\":\"067e889.svg\",\"bento\":\"0fd2feb.svg\",\"dumpling\":\"71491bf.svg\",\"oyster\":\"7c887a4.svg\",\"fried_shrimp\":\"04bd57d.svg\",\"rice_ball\":\"a6b77cf.svg\",\"rice\":\"fd4ae11.svg\",\"rice_cracker\":\"77fbf2e.svg\",\"fish_cake\":\"a94c6f5.svg\",\"fortune_cookie\":\"adae735.svg\",\"moon_cake\":\"3cf1f6c.svg\",\"oden\":\"30afd74.svg\",\"dango\":\"71ba14b.svg\",\"shaved_ice\":\"41b99c7.svg\",\"ice_cream\":\"967e342.svg\",\"icecream\":\"a659029.svg\",\"pie\":\"26758e2.svg\",\"cupcake\":\"6e1882a.svg\",\"cake\":\"a5a0d93.svg\",\"birthday\":\"ebfc760.svg\",\"custard\":\"7e61e0c.svg\",\"pudding\":\"7e61e0c.svg\",\"flan\":\"7e61e0c.svg\",\"lollipop\":\"2ca11ad.svg\",\"candy\":\"32f0f2e.svg\",\"chocolate_bar\":\"e60cdf7.svg\",\"popcorn\":\"ab01b78.svg\",\"doughnut\":\"c3385bc.svg\",\"cookie\":\"9d3f367.svg\",\"chestnut\":\"dd5851b.svg\",\"peanuts\":\"a20e792.svg\",\"shelled_peanut\":\"a20e792.svg\",\"honey_pot\":\"a0bdfae.svg\",\"milk\":\"821274d.svg\",\"glass_of_milk\":\"821274d.svg\",\"baby_bottle\":\"8a5b07d.svg\",\"tea\":\"b321e0c.svg\",\"teapot\":\"01e2f91.svg\",\"mate\":\"8dd46d2.svg\",\"bubble_tea\":\"2051cef.svg\",\"beverage_box\":\"e4435be.svg\",\"cup_with_straw\":\"55bf11e.svg\",\"sake\":\"5c5e3ba.svg\",\"beer\":\"95fb995.svg\",\"beers\":\"a3b4911.svg\",\"champagne_glass\":\"4b2aa03.svg\",\"clinking_glass\":\"4b2aa03.svg\",\"wine_glass\":\"3206d4e.svg\",\"tumbler_glass\":\"11bbc42.svg\",\"whisky\":\"11bbc42.svg\",\"cocktail\":\"3a21ef2.svg\",\"tropical_drink\":\"8d0ac3d.svg\",\"champagne\":\"f7cb49a.svg\",\"bottle_with_popping_cork\":\"f7cb49a.svg\",\"ice_cube\":\"3798289.svg\",\"spoon\":\"7f3b449.svg\",\"fork_and_knife\":\"410cb1a.svg\",\"fork_knife_plate\":\"54cfb15.svg\",\"fork_and_knife_with_plate\":\"54cfb15.svg\",\"bowl_with_spoon\":\"cea4b0b.svg\",\"takeout_box\":\"2b60e9b.svg\",\"chopsticks\":\"785de11.svg\",\"salt\":\"ec10ed1.svg\",\"soccer\":\"fe5016a.svg\",\"basketball\":\"0af3e2e.svg\",\"football\":\"613427a.svg\",\"baseball\":\"4e1371c.svg\",\"softball\":\"6da5625.svg\",\"tennis\":\"f1bc91d.svg\",\"volleyball\":\"6f326b4.svg\",\"rugby_football\":\"bf09743.svg\",\"flying_disc\":\"0d8a28d.svg\",\"boomerang\":\"e2a13ed.svg\",\"8ball\":\"e1568b2.svg\",\"yo_yo\":\"9424c4a.svg\",\"ping_pong\":\"d4cd1c6.svg\",\"table_tennis\":\"d4cd1c6.svg\",\"badminton\":\"7a082b9.svg\",\"hockey\":\"4ec1cc9.svg\",\"field_hockey\":\"464cb70.svg\",\"lacrosse\":\"8e814bb.svg\",\"cricket_game\":\"4aae708.svg\",\"cricket_bat_ball\":\"4aae708.svg\",\"goal\":\"08895cc.svg\",\"goal_net\":\"08895cc.svg\",\"golf\":\"6bbe5a3.svg\",\"kite\":\"3821f31.svg\",\"bow_and_arrow\":\"068e73e.svg\",\"archery\":\"068e73e.svg\",\"fishing_pole_and_fish\":\"8ec3056.svg\",\"diving_mask\":\"e49ef97.svg\",\"boxing_glove\":\"5e6de39.svg\",\"boxing_gloves\":\"5e6de39.svg\",\"martial_arts_uniform\":\"d9afc6f.svg\",\"karate_uniform\":\"d9afc6f.svg\",\"running_shirt_with_sash\":\"715d5c3.svg\",\"skateboard\":\"7ea93e9.svg\",\"roller_skate\":\"f314913.svg\",\"sled\":\"aa00254.svg\",\"ice_skate\":\"d9d11f6.svg\",\"curling_stone\":\"8e27381.svg\",\"ski\":\"34ea7a2.svg\",\"skier\":\"8e86867.svg\",\"snowboarder\":\"924f676.svg\",\"snowboarder_tone1\":\"6378d9c.svg\",\"snowboarder_light_skin_tone\":\"6378d9c.svg\",\"snowboarder_tone2\":\"a867bbf.svg\",\"snowboarder_medium_light_skin_tone\":\"a867bbf.svg\",\"snowboarder_tone3\":\"d53f50d.svg\",\"snowboarder_medium_skin_tone\":\"d53f50d.svg\",\"snowboarder_tone4\":\"3b89122.svg\",\"snowboarder_medium_dark_skin_tone\":\"3b89122.svg\",\"snowboarder_tone5\":\"bc52d26.svg\",\"snowboarder_dark_skin_tone\":\"bc52d26.svg\",\"parachute\":\"235aa80.svg\",\"person_lifting_weights\":\"b90ac11.svg\",\"lifter\":\"b90ac11.svg\",\"weight_lifter\":\"b90ac11.svg\",\"person_lifting_weights_tone1\":\"34d9b74.svg\",\"lifter_tone1\":\"34d9b74.svg\",\"weight_lifter_tone1\":\"34d9b74.svg\",\"person_lifting_weights_tone2\":\"f27c582.svg\",\"lifter_tone2\":\"f27c582.svg\",\"weight_lifter_tone2\":\"f27c582.svg\",\"person_lifting_weights_tone3\":\"dd131fc.svg\",\"lifter_tone3\":\"dd131fc.svg\",\"weight_lifter_tone3\":\"dd131fc.svg\",\"person_lifting_weights_tone4\":\"e57f8bb.svg\",\"lifter_tone4\":\"e57f8bb.svg\",\"weight_lifter_tone4\":\"e57f8bb.svg\",\"person_lifting_weights_tone5\":\"de9bcfd.svg\",\"lifter_tone5\":\"de9bcfd.svg\",\"weight_lifter_tone5\":\"de9bcfd.svg\",\"woman_lifting_weights\":\"62a33df.svg\",\"woman_lifting_weights_tone1\":\"3660157.svg\",\"woman_lifting_weights_light_skin_tone\":\"3660157.svg\",\"woman_lifting_weights_tone2\":\"e191ca6.svg\",\"woman_lifting_weights_medium_light_skin_tone\":\"e191ca6.svg\",\"woman_lifting_weights_tone3\":\"e09b339.svg\",\"woman_lifting_weights_medium_skin_tone\":\"e09b339.svg\",\"woman_lifting_weights_tone4\":\"62072c2.svg\",\"woman_lifting_weights_medium_dark_skin_tone\":\"62072c2.svg\",\"woman_lifting_weights_tone5\":\"91a30cb.svg\",\"woman_lifting_weights_dark_skin_tone\":\"91a30cb.svg\",\"man_lifting_weights\":\"b1c9983.svg\",\"man_lifting_weights_tone1\":\"9533af5.svg\",\"man_lifting_weights_light_skin_tone\":\"9533af5.svg\",\"man_lifting_weights_tone2\":\"ee2a6a9.svg\",\"man_lifting_weights_medium_light_skin_tone\":\"ee2a6a9.svg\",\"man_lifting_weights_tone3\":\"e5f3b8f.svg\",\"man_lifting_weights_medium_skin_tone\":\"e5f3b8f.svg\",\"man_lifting_weights_tone4\":\"9731124.svg\",\"man_lifting_weights_medium_dark_skin_tone\":\"9731124.svg\",\"man_lifting_weights_tone5\":\"cd99f79.svg\",\"man_lifting_weights_dark_skin_tone\":\"cd99f79.svg\",\"people_wrestling\":\"53c665d.svg\",\"wrestlers\":\"53c665d.svg\",\"wrestling\":\"53c665d.svg\",\"women_wrestling\":\"1353766.svg\",\"men_wrestling\":\"39251fc.svg\",\"person_doing_cartwheel\":\"ceaa20d.svg\",\"cartwheel\":\"ceaa20d.svg\",\"person_doing_cartwheel_tone1\":\"e0a4877.svg\",\"cartwheel_tone1\":\"e0a4877.svg\",\"person_doing_cartwheel_tone2\":\"20b9a39.svg\",\"cartwheel_tone2\":\"20b9a39.svg\",\"person_doing_cartwheel_tone3\":\"7003f2d.svg\",\"cartwheel_tone3\":\"7003f2d.svg\",\"person_doing_cartwheel_tone4\":\"2dce1a6.svg\",\"cartwheel_tone4\":\"2dce1a6.svg\",\"person_doing_cartwheel_tone5\":\"1fd5723.svg\",\"cartwheel_tone5\":\"1fd5723.svg\",\"woman_cartwheeling\":\"f9d123e.svg\",\"woman_cartwheeling_tone1\":\"937a8be.svg\",\"woman_cartwheeling_light_skin_tone\":\"937a8be.svg\",\"woman_cartwheeling_tone2\":\"08252f5.svg\",\"woman_cartwheeling_medium_light_skin_tone\":\"08252f5.svg\",\"woman_cartwheeling_tone3\":\"546ef7e.svg\",\"woman_cartwheeling_medium_skin_tone\":\"546ef7e.svg\",\"woman_cartwheeling_tone4\":\"0f82417.svg\",\"woman_cartwheeling_medium_dark_skin_tone\":\"0f82417.svg\",\"woman_cartwheeling_tone5\":\"2554418.svg\",\"woman_cartwheeling_dark_skin_tone\":\"2554418.svg\",\"man_cartwheeling\":\"a091dd5.svg\",\"man_cartwheeling_tone1\":\"f6ee5ef.svg\",\"man_cartwheeling_light_skin_tone\":\"f6ee5ef.svg\",\"man_cartwheeling_tone2\":\"0cc10b6.svg\",\"man_cartwheeling_medium_light_skin_tone\":\"0cc10b6.svg\",\"man_cartwheeling_tone3\":\"9a5c406.svg\",\"man_cartwheeling_medium_skin_tone\":\"9a5c406.svg\",\"man_cartwheeling_tone4\":\"b039a4a.svg\",\"man_cartwheeling_medium_dark_skin_tone\":\"b039a4a.svg\",\"man_cartwheeling_tone5\":\"b3a7e4c.svg\",\"man_cartwheeling_dark_skin_tone\":\"b3a7e4c.svg\",\"person_bouncing_ball\":\"c59fd96.svg\",\"basketball_player\":\"c59fd96.svg\",\"person_with_ball\":\"c59fd96.svg\",\"person_bouncing_ball_tone1\":\"b308087.svg\",\"basketball_player_tone1\":\"b308087.svg\",\"person_with_ball_tone1\":\"b308087.svg\",\"person_bouncing_ball_tone2\":\"95d1ab8.svg\",\"basketball_player_tone2\":\"95d1ab8.svg\",\"person_with_ball_tone2\":\"95d1ab8.svg\",\"person_bouncing_ball_tone3\":\"130e022.svg\",\"basketball_player_tone3\":\"130e022.svg\",\"person_with_ball_tone3\":\"130e022.svg\",\"person_bouncing_ball_tone4\":\"e1bcfae.svg\",\"basketball_player_tone4\":\"e1bcfae.svg\",\"person_with_ball_tone4\":\"e1bcfae.svg\",\"person_bouncing_ball_tone5\":\"048f5ff.svg\",\"basketball_player_tone5\":\"048f5ff.svg\",\"person_with_ball_tone5\":\"048f5ff.svg\",\"woman_bouncing_ball\":\"8c28093.svg\",\"woman_bouncing_ball_tone1\":\"9eef462.svg\",\"woman_bouncing_ball_light_skin_tone\":\"9eef462.svg\",\"woman_bouncing_ball_tone2\":\"2c4ab8d.svg\",\"woman_bouncing_ball_medium_light_skin_tone\":\"2c4ab8d.svg\",\"woman_bouncing_ball_tone3\":\"66fe37b.svg\",\"woman_bouncing_ball_medium_skin_tone\":\"66fe37b.svg\",\"woman_bouncing_ball_tone4\":\"c75a4e7.svg\",\"woman_bouncing_ball_medium_dark_skin_tone\":\"c75a4e7.svg\",\"woman_bouncing_ball_tone5\":\"506f725.svg\",\"woman_bouncing_ball_dark_skin_tone\":\"506f725.svg\",\"man_bouncing_ball\":\"b6a7c56.svg\",\"man_bouncing_ball_tone1\":\"322cb44.svg\",\"man_bouncing_ball_light_skin_tone\":\"322cb44.svg\",\"man_bouncing_ball_tone2\":\"50cbc45.svg\",\"man_bouncing_ball_medium_light_skin_tone\":\"50cbc45.svg\",\"man_bouncing_ball_tone3\":\"ef9c2e8.svg\",\"man_bouncing_ball_medium_skin_tone\":\"ef9c2e8.svg\",\"man_bouncing_ball_tone4\":\"e8fa7bf.svg\",\"man_bouncing_ball_medium_dark_skin_tone\":\"e8fa7bf.svg\",\"man_bouncing_ball_tone5\":\"dec8825.svg\",\"man_bouncing_ball_dark_skin_tone\":\"dec8825.svg\",\"person_fencing\":\"3f34bca.svg\",\"fencer\":\"3f34bca.svg\",\"fencing\":\"3f34bca.svg\",\"person_playing_handball\":\"b68a89f.svg\",\"handball\":\"b68a89f.svg\",\"person_playing_handball_tone1\":\"9589a8e.svg\",\"handball_tone1\":\"9589a8e.svg\",\"person_playing_handball_tone2\":\"838a0a1.svg\",\"handball_tone2\":\"838a0a1.svg\",\"person_playing_handball_tone3\":\"5c34d86.svg\",\"handball_tone3\":\"5c34d86.svg\",\"person_playing_handball_tone4\":\"b48abf5.svg\",\"handball_tone4\":\"b48abf5.svg\",\"person_playing_handball_tone5\":\"5ae9150.svg\",\"handball_tone5\":\"5ae9150.svg\",\"woman_playing_handball\":\"3d904f4.svg\",\"woman_playing_handball_tone1\":\"ce426bd.svg\",\"woman_playing_handball_light_skin_tone\":\"ce426bd.svg\",\"woman_playing_handball_tone2\":\"eaed791.svg\",\"woman_playing_handball_medium_light_skin_tone\":\"eaed791.svg\",\"woman_playing_handball_tone3\":\"96267aa.svg\",\"woman_playing_handball_medium_skin_tone\":\"96267aa.svg\",\"woman_playing_handball_tone4\":\"0688baa.svg\",\"woman_playing_handball_medium_dark_skin_tone\":\"0688baa.svg\",\"woman_playing_handball_tone5\":\"7d4d45a.svg\",\"woman_playing_handball_dark_skin_tone\":\"7d4d45a.svg\",\"man_playing_handball\":\"16e5ae3.svg\",\"man_playing_handball_tone1\":\"07d7439.svg\",\"man_playing_handball_light_skin_tone\":\"07d7439.svg\",\"man_playing_handball_tone2\":\"8ec0da9.svg\",\"man_playing_handball_medium_light_skin_tone\":\"8ec0da9.svg\",\"man_playing_handball_tone3\":\"0f401f9.svg\",\"man_playing_handball_medium_skin_tone\":\"0f401f9.svg\",\"man_playing_handball_tone4\":\"42a6db5.svg\",\"man_playing_handball_medium_dark_skin_tone\":\"42a6db5.svg\",\"man_playing_handball_tone5\":\"be6e83c.svg\",\"man_playing_handball_dark_skin_tone\":\"be6e83c.svg\",\"person_golfing\":\"7670549.svg\",\"golfer\":\"7670549.svg\",\"person_golfing_tone1\":\"aef1d45.svg\",\"person_golfing_light_skin_tone\":\"aef1d45.svg\",\"person_golfing_tone2\":\"0be94ad.svg\",\"person_golfing_medium_light_skin_tone\":\"0be94ad.svg\",\"person_golfing_tone3\":\"ed7649c.svg\",\"person_golfing_medium_skin_tone\":\"ed7649c.svg\",\"person_golfing_tone4\":\"5c3cba6.svg\",\"person_golfing_medium_dark_skin_tone\":\"5c3cba6.svg\",\"person_golfing_tone5\":\"5ea05fb.svg\",\"person_golfing_dark_skin_tone\":\"5ea05fb.svg\",\"woman_golfing\":\"b3abda4.svg\",\"woman_golfing_tone1\":\"b70878e.svg\",\"woman_golfing_light_skin_tone\":\"b70878e.svg\",\"woman_golfing_tone2\":\"b5598cf.svg\",\"woman_golfing_medium_light_skin_tone\":\"b5598cf.svg\",\"woman_golfing_tone3\":\"3ba78bf.svg\",\"woman_golfing_medium_skin_tone\":\"3ba78bf.svg\",\"woman_golfing_tone4\":\"891855f.svg\",\"woman_golfing_medium_dark_skin_tone\":\"891855f.svg\",\"woman_golfing_tone5\":\"dea660f.svg\",\"woman_golfing_dark_skin_tone\":\"dea660f.svg\",\"man_golfing\":\"318beb6.svg\",\"man_golfing_tone1\":\"ae64959.svg\",\"man_golfing_light_skin_tone\":\"ae64959.svg\",\"man_golfing_tone2\":\"953e4d1.svg\",\"man_golfing_medium_light_skin_tone\":\"953e4d1.svg\",\"man_golfing_tone3\":\"a490490.svg\",\"man_golfing_medium_skin_tone\":\"a490490.svg\",\"man_golfing_tone4\":\"6fec785.svg\",\"man_golfing_medium_dark_skin_tone\":\"6fec785.svg\",\"man_golfing_tone5\":\"fa6305a.svg\",\"man_golfing_dark_skin_tone\":\"fa6305a.svg\",\"horse_racing\":\"cf37033.svg\",\"horse_racing_tone1\":\"6655068.svg\",\"horse_racing_tone2\":\"8da15b8.svg\",\"horse_racing_tone3\":\"2e8ea94.svg\",\"horse_racing_tone4\":\"81e6ea9.svg\",\"horse_racing_tone5\":\"1dd66e6.svg\",\"person_in_lotus_position\":\"e7772e3.svg\",\"person_in_lotus_position_tone1\":\"085ede7.svg\",\"person_in_lotus_position_light_skin_tone\":\"085ede7.svg\",\"person_in_lotus_position_tone2\":\"b2de70b.svg\",\"person_in_lotus_position_medium_light_skin_tone\":\"b2de70b.svg\",\"person_in_lotus_position_tone3\":\"5a3f5ad.svg\",\"person_in_lotus_position_medium_skin_tone\":\"5a3f5ad.svg\",\"person_in_lotus_position_tone4\":\"f089de4.svg\",\"person_in_lotus_position_medium_dark_skin_tone\":\"f089de4.svg\",\"person_in_lotus_position_tone5\":\"40aac9b.svg\",\"person_in_lotus_position_dark_skin_tone\":\"40aac9b.svg\",\"woman_in_lotus_position\":\"32e01c8.svg\",\"woman_in_lotus_position_tone1\":\"60b3f38.svg\",\"woman_in_lotus_position_light_skin_tone\":\"60b3f38.svg\",\"woman_in_lotus_position_tone2\":\"b2fb18a.svg\",\"woman_in_lotus_position_medium_light_skin_tone\":\"b2fb18a.svg\",\"woman_in_lotus_position_tone3\":\"701c642.svg\",\"woman_in_lotus_position_medium_skin_tone\":\"701c642.svg\",\"woman_in_lotus_position_tone4\":\"cb3e88b.svg\",\"woman_in_lotus_position_medium_dark_skin_tone\":\"cb3e88b.svg\",\"woman_in_lotus_position_tone5\":\"21eb27c.svg\",\"woman_in_lotus_position_dark_skin_tone\":\"21eb27c.svg\",\"man_in_lotus_position\":\"8a422b1.svg\",\"man_in_lotus_position_tone1\":\"bd641d1.svg\",\"man_in_lotus_position_light_skin_tone\":\"bd641d1.svg\",\"man_in_lotus_position_tone2\":\"bc4c728.svg\",\"man_in_lotus_position_medium_light_skin_tone\":\"bc4c728.svg\",\"man_in_lotus_position_tone3\":\"462d985.svg\",\"man_in_lotus_position_medium_skin_tone\":\"462d985.svg\",\"man_in_lotus_position_tone4\":\"a0ec16e.svg\",\"man_in_lotus_position_medium_dark_skin_tone\":\"a0ec16e.svg\",\"man_in_lotus_position_tone5\":\"3edb59b.svg\",\"man_in_lotus_position_dark_skin_tone\":\"3edb59b.svg\",\"person_surfing\":\"c27cd92.svg\",\"surfer\":\"c27cd92.svg\",\"person_surfing_tone1\":\"f27cf26.svg\",\"surfer_tone1\":\"f27cf26.svg\",\"person_surfing_tone2\":\"3355d94.svg\",\"surfer_tone2\":\"3355d94.svg\",\"person_surfing_tone3\":\"46c6fb7.svg\",\"surfer_tone3\":\"46c6fb7.svg\",\"person_surfing_tone4\":\"2e67152.svg\",\"surfer_tone4\":\"2e67152.svg\",\"person_surfing_tone5\":\"b736746.svg\",\"surfer_tone5\":\"b736746.svg\",\"woman_surfing\":\"e72e11a.svg\",\"woman_surfing_tone1\":\"336b653.svg\",\"woman_surfing_light_skin_tone\":\"336b653.svg\",\"woman_surfing_tone2\":\"7685ea8.svg\",\"woman_surfing_medium_light_skin_tone\":\"7685ea8.svg\",\"woman_surfing_tone3\":\"763a75b.svg\",\"woman_surfing_medium_skin_tone\":\"763a75b.svg\",\"woman_surfing_tone4\":\"2095063.svg\",\"woman_surfing_medium_dark_skin_tone\":\"2095063.svg\",\"woman_surfing_tone5\":\"ecaab7e.svg\",\"woman_surfing_dark_skin_tone\":\"ecaab7e.svg\",\"man_surfing\":\"7f7d510.svg\",\"man_surfing_tone1\":\"0eea655.svg\",\"man_surfing_light_skin_tone\":\"0eea655.svg\",\"man_surfing_tone2\":\"ab7483c.svg\",\"man_surfing_medium_light_skin_tone\":\"ab7483c.svg\",\"man_surfing_tone3\":\"7919132.svg\",\"man_surfing_medium_skin_tone\":\"7919132.svg\",\"man_surfing_tone4\":\"d53f5ab.svg\",\"man_surfing_medium_dark_skin_tone\":\"d53f5ab.svg\",\"man_surfing_tone5\":\"cd6b5f3.svg\",\"man_surfing_dark_skin_tone\":\"cd6b5f3.svg\",\"person_swimming\":\"28777cf.svg\",\"swimmer\":\"28777cf.svg\",\"person_swimming_tone1\":\"df6d508.svg\",\"swimmer_tone1\":\"df6d508.svg\",\"person_swimming_tone2\":\"1bba0d0.svg\",\"swimmer_tone2\":\"1bba0d0.svg\",\"person_swimming_tone3\":\"b9edd35.svg\",\"swimmer_tone3\":\"b9edd35.svg\",\"person_swimming_tone4\":\"d37ded5.svg\",\"swimmer_tone4\":\"d37ded5.svg\",\"person_swimming_tone5\":\"a1071f0.svg\",\"swimmer_tone5\":\"a1071f0.svg\",\"woman_swimming\":\"49661b2.svg\",\"woman_swimming_tone1\":\"e79e53b.svg\",\"woman_swimming_light_skin_tone\":\"e79e53b.svg\",\"woman_swimming_tone2\":\"163be27.svg\",\"woman_swimming_medium_light_skin_tone\":\"163be27.svg\",\"woman_swimming_tone3\":\"b0f2942.svg\",\"woman_swimming_medium_skin_tone\":\"b0f2942.svg\",\"woman_swimming_tone4\":\"3b262f8.svg\",\"woman_swimming_medium_dark_skin_tone\":\"3b262f8.svg\",\"woman_swimming_tone5\":\"e9e3a6b.svg\",\"woman_swimming_dark_skin_tone\":\"e9e3a6b.svg\",\"man_swimming\":\"bf31394.svg\",\"man_swimming_tone1\":\"c59559e.svg\",\"man_swimming_light_skin_tone\":\"c59559e.svg\",\"man_swimming_tone2\":\"400e4cf.svg\",\"man_swimming_medium_light_skin_tone\":\"400e4cf.svg\",\"man_swimming_tone3\":\"779c541.svg\",\"man_swimming_medium_skin_tone\":\"779c541.svg\",\"man_swimming_tone4\":\"b02d784.svg\",\"man_swimming_medium_dark_skin_tone\":\"b02d784.svg\",\"man_swimming_tone5\":\"73eb78a.svg\",\"man_swimming_dark_skin_tone\":\"73eb78a.svg\",\"person_playing_water_polo\":\"06d4fe3.svg\",\"water_polo\":\"06d4fe3.svg\",\"person_playing_water_polo_tone1\":\"52d1e9b.svg\",\"water_polo_tone1\":\"52d1e9b.svg\",\"person_playing_water_polo_tone2\":\"2d709f9.svg\",\"water_polo_tone2\":\"2d709f9.svg\",\"person_playing_water_polo_tone3\":\"53b980a.svg\",\"water_polo_tone3\":\"53b980a.svg\",\"person_playing_water_polo_tone4\":\"057a799.svg\",\"water_polo_tone4\":\"057a799.svg\",\"person_playing_water_polo_tone5\":\"ddf84ba.svg\",\"water_polo_tone5\":\"ddf84ba.svg\",\"woman_playing_water_polo\":\"f46966d.svg\",\"woman_playing_water_polo_tone1\":\"567c0e1.svg\",\"woman_playing_water_polo_light_skin_tone\":\"567c0e1.svg\",\"woman_playing_water_polo_tone2\":\"c5c8263.svg\",\"woman_playing_water_polo_medium_light_skin_tone\":\"c5c8263.svg\",\"woman_playing_water_polo_tone3\":\"57dc235.svg\",\"woman_playing_water_polo_medium_skin_tone\":\"57dc235.svg\",\"woman_playing_water_polo_tone4\":\"177d57d.svg\",\"woman_playing_water_polo_medium_dark_skin_tone\":\"177d57d.svg\",\"woman_playing_water_polo_tone5\":\"596ba46.svg\",\"woman_playing_water_polo_dark_skin_tone\":\"596ba46.svg\",\"man_playing_water_polo\":\"ebc362c.svg\",\"man_playing_water_polo_tone1\":\"ead613e.svg\",\"man_playing_water_polo_light_skin_tone\":\"ead613e.svg\",\"man_playing_water_polo_tone2\":\"753c7f2.svg\",\"man_playing_water_polo_medium_light_skin_tone\":\"753c7f2.svg\",\"man_playing_water_polo_tone3\":\"666dcd9.svg\",\"man_playing_water_polo_medium_skin_tone\":\"666dcd9.svg\",\"man_playing_water_polo_tone4\":\"13a8332.svg\",\"man_playing_water_polo_medium_dark_skin_tone\":\"13a8332.svg\",\"man_playing_water_polo_tone5\":\"da368cd.svg\",\"man_playing_water_polo_dark_skin_tone\":\"da368cd.svg\",\"person_rowing_boat\":\"0ff3b31.svg\",\"rowboat\":\"0ff3b31.svg\",\"person_rowing_boat_tone1\":\"01fef47.svg\",\"rowboat_tone1\":\"01fef47.svg\",\"person_rowing_boat_tone2\":\"3d61432.svg\",\"rowboat_tone2\":\"3d61432.svg\",\"person_rowing_boat_tone3\":\"712d209.svg\",\"rowboat_tone3\":\"712d209.svg\",\"person_rowing_boat_tone4\":\"5549b7f.svg\",\"rowboat_tone4\":\"5549b7f.svg\",\"person_rowing_boat_tone5\":\"d1a1e9b.svg\",\"rowboat_tone5\":\"d1a1e9b.svg\",\"woman_rowing_boat\":\"2db7225.svg\",\"woman_rowing_boat_tone1\":\"28ce4ef.svg\",\"woman_rowing_boat_light_skin_tone\":\"28ce4ef.svg\",\"woman_rowing_boat_tone2\":\"319931f.svg\",\"woman_rowing_boat_medium_light_skin_tone\":\"319931f.svg\",\"woman_rowing_boat_tone3\":\"a4d57bd.svg\",\"woman_rowing_boat_medium_skin_tone\":\"a4d57bd.svg\",\"woman_rowing_boat_tone4\":\"0836442.svg\",\"woman_rowing_boat_medium_dark_skin_tone\":\"0836442.svg\",\"woman_rowing_boat_tone5\":\"126b354.svg\",\"woman_rowing_boat_dark_skin_tone\":\"126b354.svg\",\"man_rowing_boat\":\"9b50e6e.svg\",\"man_rowing_boat_tone1\":\"2111cad.svg\",\"man_rowing_boat_light_skin_tone\":\"2111cad.svg\",\"man_rowing_boat_tone2\":\"c96ba76.svg\",\"man_rowing_boat_medium_light_skin_tone\":\"c96ba76.svg\",\"man_rowing_boat_tone3\":\"8f39815.svg\",\"man_rowing_boat_medium_skin_tone\":\"8f39815.svg\",\"man_rowing_boat_tone4\":\"2447569.svg\",\"man_rowing_boat_medium_dark_skin_tone\":\"2447569.svg\",\"man_rowing_boat_tone5\":\"9f1fc73.svg\",\"man_rowing_boat_dark_skin_tone\":\"9f1fc73.svg\",\"person_climbing\":\"346ef3c.svg\",\"person_climbing_tone1\":\"21bf53e.svg\",\"person_climbing_light_skin_tone\":\"21bf53e.svg\",\"person_climbing_tone2\":\"7247dd3.svg\",\"person_climbing_medium_light_skin_tone\":\"7247dd3.svg\",\"person_climbing_tone3\":\"82d7d7d.svg\",\"person_climbing_medium_skin_tone\":\"82d7d7d.svg\",\"person_climbing_tone4\":\"5f96b71.svg\",\"person_climbing_medium_dark_skin_tone\":\"5f96b71.svg\",\"person_climbing_tone5\":\"9449a0b.svg\",\"person_climbing_dark_skin_tone\":\"9449a0b.svg\",\"woman_climbing\":\"e7b9c6e.svg\",\"woman_climbing_tone1\":\"d348f64.svg\",\"woman_climbing_light_skin_tone\":\"d348f64.svg\",\"woman_climbing_tone2\":\"ca220ab.svg\",\"woman_climbing_medium_light_skin_tone\":\"ca220ab.svg\",\"woman_climbing_tone3\":\"cbd19fd.svg\",\"woman_climbing_medium_skin_tone\":\"cbd19fd.svg\",\"woman_climbing_tone4\":\"adc0bf8.svg\",\"woman_climbing_medium_dark_skin_tone\":\"adc0bf8.svg\",\"woman_climbing_tone5\":\"0142ab2.svg\",\"woman_climbing_dark_skin_tone\":\"0142ab2.svg\",\"man_climbing\":\"87c7287.svg\",\"man_climbing_tone1\":\"12e1965.svg\",\"man_climbing_light_skin_tone\":\"12e1965.svg\",\"man_climbing_tone2\":\"63f594d.svg\",\"man_climbing_medium_light_skin_tone\":\"63f594d.svg\",\"man_climbing_tone3\":\"06891c1.svg\",\"man_climbing_medium_skin_tone\":\"06891c1.svg\",\"man_climbing_tone4\":\"814ac9f.svg\",\"man_climbing_medium_dark_skin_tone\":\"814ac9f.svg\",\"man_climbing_tone5\":\"3f6e241.svg\",\"man_climbing_dark_skin_tone\":\"3f6e241.svg\",\"person_mountain_biking\":\"890c347.svg\",\"mountain_bicyclist\":\"890c347.svg\",\"person_mountain_biking_tone1\":\"2d7f3f6.svg\",\"mountain_bicyclist_tone1\":\"2d7f3f6.svg\",\"person_mountain_biking_tone2\":\"3ae6862.svg\",\"mountain_bicyclist_tone2\":\"3ae6862.svg\",\"person_mountain_biking_tone3\":\"0da06a0.svg\",\"mountain_bicyclist_tone3\":\"0da06a0.svg\",\"person_mountain_biking_tone4\":\"77c8088.svg\",\"mountain_bicyclist_tone4\":\"77c8088.svg\",\"person_mountain_biking_tone5\":\"03a7b4f.svg\",\"mountain_bicyclist_tone5\":\"03a7b4f.svg\",\"woman_mountain_biking\":\"6a57fb1.svg\",\"woman_mountain_biking_tone1\":\"d80c94a.svg\",\"woman_mountain_biking_light_skin_tone\":\"d80c94a.svg\",\"woman_mountain_biking_tone2\":\"7689ca9.svg\",\"woman_mountain_biking_medium_light_skin_tone\":\"7689ca9.svg\",\"woman_mountain_biking_tone3\":\"8a0612e.svg\",\"woman_mountain_biking_medium_skin_tone\":\"8a0612e.svg\",\"woman_mountain_biking_tone4\":\"e74c90f.svg\",\"woman_mountain_biking_medium_dark_skin_tone\":\"e74c90f.svg\",\"woman_mountain_biking_tone5\":\"7e1cade.svg\",\"woman_mountain_biking_dark_skin_tone\":\"7e1cade.svg\",\"man_mountain_biking\":\"2672109.svg\",\"man_mountain_biking_tone1\":\"0313118.svg\",\"man_mountain_biking_light_skin_tone\":\"0313118.svg\",\"man_mountain_biking_tone2\":\"75b5216.svg\",\"man_mountain_biking_medium_light_skin_tone\":\"75b5216.svg\",\"man_mountain_biking_tone3\":\"00a2eaf.svg\",\"man_mountain_biking_medium_skin_tone\":\"00a2eaf.svg\",\"man_mountain_biking_tone4\":\"a595c8c.svg\",\"man_mountain_biking_medium_dark_skin_tone\":\"a595c8c.svg\",\"man_mountain_biking_tone5\":\"a4f8d93.svg\",\"man_mountain_biking_dark_skin_tone\":\"a4f8d93.svg\",\"person_biking\":\"6044207.svg\",\"bicyclist\":\"6044207.svg\",\"person_biking_tone1\":\"7444817.svg\",\"bicyclist_tone1\":\"7444817.svg\",\"person_biking_tone2\":\"c88dda5.svg\",\"bicyclist_tone2\":\"c88dda5.svg\",\"person_biking_tone3\":\"8647d8d.svg\",\"bicyclist_tone3\":\"8647d8d.svg\",\"person_biking_tone4\":\"1e876ca.svg\",\"bicyclist_tone4\":\"1e876ca.svg\",\"person_biking_tone5\":\"b32808a.svg\",\"bicyclist_tone5\":\"b32808a.svg\",\"woman_biking\":\"93a8bad.svg\",\"woman_biking_tone1\":\"b6049e8.svg\",\"woman_biking_light_skin_tone\":\"b6049e8.svg\",\"woman_biking_tone2\":\"0a5b09e.svg\",\"woman_biking_medium_light_skin_tone\":\"0a5b09e.svg\",\"woman_biking_tone3\":\"306a73e.svg\",\"woman_biking_medium_skin_tone\":\"306a73e.svg\",\"woman_biking_tone4\":\"7e7705a.svg\",\"woman_biking_medium_dark_skin_tone\":\"7e7705a.svg\",\"woman_biking_tone5\":\"e6189d9.svg\",\"woman_biking_dark_skin_tone\":\"e6189d9.svg\",\"man_biking\":\"6f05980.svg\",\"man_biking_tone1\":\"2b3276d.svg\",\"man_biking_light_skin_tone\":\"2b3276d.svg\",\"man_biking_tone2\":\"b6b8f8f.svg\",\"man_biking_medium_light_skin_tone\":\"b6b8f8f.svg\",\"man_biking_tone3\":\"226b02b.svg\",\"man_biking_medium_skin_tone\":\"226b02b.svg\",\"man_biking_tone4\":\"3c7d7e9.svg\",\"man_biking_medium_dark_skin_tone\":\"3c7d7e9.svg\",\"man_biking_tone5\":\"03c0dbb.svg\",\"man_biking_dark_skin_tone\":\"03c0dbb.svg\",\"trophy\":\"c3e6f70.svg\",\"first_place\":\"db793a8.svg\",\"first_place_medal\":\"db793a8.svg\",\"second_place\":\"e93fea1.svg\",\"second_place_medal\":\"e93fea1.svg\",\"third_place\":\"47d8c17.svg\",\"third_place_medal\":\"47d8c17.svg\",\"medal\":\"6779ec9.svg\",\"sports_medal\":\"6779ec9.svg\",\"military_medal\":\"fb6339d.svg\",\"rosette\":\"31f7d5f.svg\",\"reminder_ribbon\":\"bb34e42.svg\",\"ticket\":\"1deed76.svg\",\"tickets\":\"ffca92f.svg\",\"admission_tickets\":\"ffca92f.svg\",\"circus_tent\":\"b6b1de7.svg\",\"person_juggling\":\"82eeb05.svg\",\"juggling\":\"82eeb05.svg\",\"juggler\":\"82eeb05.svg\",\"person_juggling_tone1\":\"9b8710a.svg\",\"juggling_tone1\":\"9b8710a.svg\",\"juggler_tone1\":\"9b8710a.svg\",\"person_juggling_tone2\":\"6b046e1.svg\",\"juggling_tone2\":\"6b046e1.svg\",\"juggler_tone2\":\"6b046e1.svg\",\"person_juggling_tone3\":\"42af1b2.svg\",\"juggling_tone3\":\"42af1b2.svg\",\"juggler_tone3\":\"42af1b2.svg\",\"person_juggling_tone4\":\"106733f.svg\",\"juggling_tone4\":\"106733f.svg\",\"juggler_tone4\":\"106733f.svg\",\"person_juggling_tone5\":\"2bbbbe4.svg\",\"juggling_tone5\":\"2bbbbe4.svg\",\"juggler_tone5\":\"2bbbbe4.svg\",\"woman_juggling\":\"cc14be0.svg\",\"woman_juggling_tone1\":\"90866dc.svg\",\"woman_juggling_light_skin_tone\":\"90866dc.svg\",\"woman_juggling_tone2\":\"3baaaef.svg\",\"woman_juggling_medium_light_skin_tone\":\"3baaaef.svg\",\"woman_juggling_tone3\":\"f389b19.svg\",\"woman_juggling_medium_skin_tone\":\"f389b19.svg\",\"woman_juggling_tone4\":\"8f862bd.svg\",\"woman_juggling_medium_dark_skin_tone\":\"8f862bd.svg\",\"woman_juggling_tone5\":\"07ae5b7.svg\",\"woman_juggling_dark_skin_tone\":\"07ae5b7.svg\",\"man_juggling\":\"49fa575.svg\",\"man_juggling_tone1\":\"b6928e8.svg\",\"man_juggling_light_skin_tone\":\"b6928e8.svg\",\"man_juggling_tone2\":\"a8e2b25.svg\",\"man_juggling_medium_light_skin_tone\":\"a8e2b25.svg\",\"man_juggling_tone3\":\"37bf0a3.svg\",\"man_juggling_medium_skin_tone\":\"37bf0a3.svg\",\"man_juggling_tone4\":\"bf1af5b.svg\",\"man_juggling_medium_dark_skin_tone\":\"bf1af5b.svg\",\"man_juggling_tone5\":\"cd7490e.svg\",\"man_juggling_dark_skin_tone\":\"cd7490e.svg\",\"performing_arts\":\"d08e092.svg\",\"ballet_shoes\":\"ce680d6.svg\",\"art\":\"6347d5d.svg\",\"clapper\":\"38c53c4.svg\",\"microphone\":\"0332817.svg\",\"headphones\":\"b75ccb1.svg\",\"musical_score\":\"9718ae8.svg\",\"musical_keyboard\":\"c127233.svg\",\"drum\":\"d34837b.svg\",\"drum_with_drumsticks\":\"d34837b.svg\",\"long_drum\":\"adfee2b.svg\",\"saxophone\":\"ea68fa3.svg\",\"trumpet\":\"cf8ad96.svg\",\"guitar\":\"b749b6d.svg\",\"banjo\":\"3c2cfe2.svg\",\"violin\":\"239b6a4.svg\",\"accordion\":\"d10245b.svg\",\"game_die\":\"cb770e2.svg\",\"chess_pawn\":\"ebef237.svg\",\"dart\":\"61b30d8.svg\",\"bowling\":\"b15446c.svg\",\"video_game\":\"475d1d9.svg\",\"slot_machine\":\"99abb72.svg\",\"jigsaw\":\"09048a1.svg\",\"red_car\":\"4648f06.svg\",\"taxi\":\"096c8b6.svg\",\"blue_car\":\"73e65e4.svg\",\"pickup_truck\":\"4fc90c4.svg\",\"bus\":\"717af8d.svg\",\"trolleybus\":\"5fc4e9c.svg\",\"race_car\":\"cda42cb.svg\",\"racing_car\":\"cda42cb.svg\",\"police_car\":\"d10f0e6.svg\",\"ambulance\":\"766fae7.svg\",\"fire_engine\":\"7ea9b1c.svg\",\"minibus\":\"7f3d2f9.svg\",\"truck\":\"4c34438.svg\",\"articulated_lorry\":\"ab2711f.svg\",\"tractor\":\"65e7e6c.svg\",\"probing_cane\":\"6cf7b22.svg\",\"manual_wheelchair\":\"f56cfd0.svg\",\"motorized_wheelchair\":\"35a9989.svg\",\"scooter\":\"4a5c78a.svg\",\"bike\":\"4f666ce.svg\",\"motor_scooter\":\"029f569.svg\",\"motorbike\":\"029f569.svg\",\"motorcycle\":\"a5d6418.svg\",\"racing_motorcycle\":\"a5d6418.svg\",\"auto_rickshaw\":\"401f92e.svg\",\"rotating_light\":\"6e0b4fb.svg\",\"oncoming_police_car\":\"c2efc9d.svg\",\"oncoming_bus\":\"48172ac.svg\",\"oncoming_automobile\":\"24e53f0.svg\",\"oncoming_taxi\":\"913eb22.svg\",\"aerial_tramway\":\"b6f3c4d.svg\",\"mountain_cableway\":\"0afd8e2.svg\",\"suspension_railway\":\"5fe46e4.svg\",\"railway_car\":\"61192cb.svg\",\"train\":\"201aebe.svg\",\"mountain_railway\":\"ff90e50.svg\",\"monorail\":\"b20874d.svg\",\"bullettrain_side\":\"7b850f3.svg\",\"bullettrain_front\":\"4b26830.svg\",\"light_rail\":\"27ee392.svg\",\"steam_locomotive\":\"cf2e7e4.svg\",\"train2\":\"f8defca.svg\",\"metro\":\"ba8bf59.svg\",\"tram\":\"15b1e38.svg\",\"station\":\"d6487f3.svg\",\"airplane_departure\":\"9f942b0.svg\",\"airplane_arriving\":\"ffe9ef5.svg\",\"airplane_small\":\"ca8c361.svg\",\"small_airplane\":\"ca8c361.svg\",\"seat\":\"fe25542.svg\",\"satellite_orbital\":\"f3b1fa1.svg\",\"rocket\":\"aa0d4e6.svg\",\"flying_saucer\":\"679db8c.svg\",\"helicopter\":\"19951f3.svg\",\"canoe\":\"f939398.svg\",\"kayak\":\"f939398.svg\",\"sailboat\":\"5246c7b.svg\",\"speedboat\":\"9ce4d8f.svg\",\"motorboat\":\"d1dae16.svg\",\"cruise_ship\":\"b6bac4d.svg\",\"passenger_ship\":\"b6bac4d.svg\",\"ferry\":\"8d9fa6d.svg\",\"ship\":\"34984e4.svg\",\"fuelpump\":\"19b45a9.svg\",\"construction\":\"7161b1c.svg\",\"vertical_traffic_light\":\"70e5f1a.svg\",\"traffic_light\":\"1f2edbd.svg\",\"busstop\":\"18f7597.svg\",\"map\":\"0ebaa6e.svg\",\"world_map\":\"0ebaa6e.svg\",\"moyai\":\"bddc0b5.svg\",\"statue_of_liberty\":\"46507e6.svg\",\"tokyo_tower\":\"64fdf85.svg\",\"european_castle\":\"37dbf79.svg\",\"japanese_castle\":\"c5c7e2d.svg\",\"stadium\":\"38115c3.svg\",\"ferris_wheel\":\"9de8642.svg\",\"roller_coaster\":\"b9e9c42.svg\",\"carousel_horse\":\"e64de10.svg\",\"fountain\":\"5aca3cd.svg\",\"beach_umbrella\":\"4156648.svg\",\"umbrella_on_ground\":\"4156648.svg\",\"beach\":\"9124dab.svg\",\"beach_with_umbrella\":\"9124dab.svg\",\"island\":\"73ce89c.svg\",\"desert_island\":\"73ce89c.svg\",\"desert\":\"e3ce8c9.svg\",\"volcano\":\"bf5d238.svg\",\"mountain\":\"1e77e79.svg\",\"mountain_snow\":\"1f23b37.svg\",\"snow_capped_mountain\":\"1f23b37.svg\",\"mount_fuji\":\"b436b7a.svg\",\"camping\":\"f6c6d51.svg\",\"tent\":\"6eb1399.svg\",\"house\":\"7affc4c.svg\",\"house_with_garden\":\"670d333.svg\",\"homes\":\"171dd2d.svg\",\"house_buildings\":\"171dd2d.svg\",\"house_abandoned\":\"6556bab.svg\",\"derelict_house_building\":\"6556bab.svg\",\"hut\":\"0287086.svg\",\"construction_site\":\"05a9407.svg\",\"building_construction\":\"05a9407.svg\",\"factory\":\"2ef3927.svg\",\"office\":\"49c6f4a.svg\",\"department_store\":\"a9826b1.svg\",\"post_office\":\"f5a09a8.svg\",\"european_post_office\":\"85a65b5.svg\",\"hospital\":\"61a201f.svg\",\"bank\":\"ec0d6b9.svg\",\"hotel\":\"2bd109e.svg\",\"convenience_store\":\"d94f921.svg\",\"school\":\"519ff41.svg\",\"love_hotel\":\"ab4d549.svg\",\"wedding\":\"3c54c5a.svg\",\"classical_building\":\"95e1830.svg\",\"church\":\"962f222.svg\",\"mosque\":\"d4d07fb.svg\",\"synagogue\":\"9120b90.svg\",\"hindu_temple\":\"f614b6d.svg\",\"kaaba\":\"8661a60.svg\",\"shinto_shrine\":\"ffc1cf2.svg\",\"railway_track\":\"45037f1.svg\",\"railroad_track\":\"45037f1.svg\",\"motorway\":\"8d46cb0.svg\",\"japan\":\"55121d5.svg\",\"rice_scene\":\"c281ca8.svg\",\"park\":\"ca41c23.svg\",\"national_park\":\"ca41c23.svg\",\"sunrise\":\"c345c7f.svg\",\"sunrise_over_mountains\":\"daecba5.svg\",\"stars\":\"976c4b0.svg\",\"sparkler\":\"5ae1115.svg\",\"fireworks\":\"c1504db.svg\",\"city_sunset\":\"add21f4.svg\",\"city_sunrise\":\"add21f4.svg\",\"city_dusk\":\"1615620.svg\",\"cityscape\":\"bcd1a03.svg\",\"night_with_stars\":\"b20b31d.svg\",\"milky_way\":\"7a8b8fe.svg\",\"bridge_at_night\":\"b3645d7.svg\",\"foggy\":\"7554b94.svg\",\"watch\":\"8cd2198.svg\",\"mobile_phone\":\"043a332.svg\",\"calling\":\"8093f31.svg\",\"computer\":\"a1cbd41.svg\",\"desktop\":\"49d1d8c.svg\",\"desktop_computer\":\"49d1d8c.svg\",\"printer\":\"0477c27.svg\",\"mouse_three_button\":\"e8bf4ae.svg\",\"three_button_mouse\":\"e8bf4ae.svg\",\"trackball\":\"eca4e5f.svg\",\"joystick\":\"31ffc51.svg\",\"compression\":\"2ae5c68.svg\",\"minidisc\":\"b857d2b.svg\",\"floppy_disk\":\"724655d.svg\",\"cd\":\"19887b0.svg\",\"dvd\":\"2d1fb24.svg\",\"vhs\":\"69c1ca5.svg\",\"camera\":\"f6b208b.svg\",\"camera_with_flash\":\"e69232c.svg\",\"video_camera\":\"0769511.svg\",\"movie_camera\":\"ada41ed.svg\",\"projector\":\"31e6fce.svg\",\"film_projector\":\"31e6fce.svg\",\"film_frames\":\"d0566b1.svg\",\"telephone_receiver\":\"d0cb02d.svg\",\"telephone\":\"b5bcee9.svg\",\"pager\":\"1508393.svg\",\"fax\":\"d03c69e.svg\",\"tv\":\"8185cfd.svg\",\"radio\":\"96aca60.svg\",\"microphone2\":\"edd109f.svg\",\"studio_microphone\":\"edd109f.svg\",\"level_slider\":\"5da41ef.svg\",\"control_knobs\":\"75bc99a.svg\",\"compass\":\"76c66a6.svg\",\"stopwatch\":\"8c25acf.svg\",\"timer\":\"29b66ab.svg\",\"timer_clock\":\"29b66ab.svg\",\"alarm_clock\":\"69d9e77.svg\",\"clock\":\"3c8b83f.svg\",\"mantlepiece_clock\":\"3c8b83f.svg\",\"hourglass\":\"ac8067d.svg\",\"hourglass_flowing_sand\":\"a93761d.svg\",\"satellite\":\"85da884.svg\",\"battery\":\"b2a3fa5.svg\",\"electric_plug\":\"04bcd7b.svg\",\"bulb\":\"0310db5.svg\",\"flashlight\":\"491b3cc.svg\",\"candle\":\"e0102d6.svg\",\"diya_lamp\":\"e62bf44.svg\",\"fire_extinguisher\":\"859318c.svg\",\"oil\":\"85dca88.svg\",\"oil_drum\":\"85dca88.svg\",\"money_with_wings\":\"394e674.svg\",\"dollar\":\"e5da110.svg\",\"yen\":\"31e33a4.svg\",\"euro\":\"0526eb6.svg\",\"pound\":\"cb3cc79.svg\",\"coin\":\"1030e8c.svg\",\"moneybag\":\"5f37ed0.svg\",\"credit_card\":\"00afcde.svg\",\"gem\":\"6ac2f69.svg\",\"ladder\":\"b52cf4f.svg\",\"toolbox\":\"949effe.svg\",\"screwdriver\":\"aa022d1.svg\",\"wrench\":\"1b0fc89.svg\",\"hammer\":\"c68f5bf.svg\",\"tools\":\"ced20a7.svg\",\"hammer_and_wrench\":\"ced20a7.svg\",\"pick\":\"8aaf7d2.svg\",\"nut_and_bolt\":\"e91cfa5.svg\",\"bricks\":\"af8390c.svg\",\"chains\":\"34432a5.svg\",\"hook\":\"7c8375e.svg\",\"knot\":\"4853ab7.svg\",\"magnet\":\"d9d3c78.svg\",\"gun\":\"5401572.svg\",\"bomb\":\"705a333.svg\",\"firecracker\":\"fc466b7.svg\",\"axe\":\"38a6e4c.svg\",\"carpentry_saw\":\"38a740a.svg\",\"knife\":\"3382c2c.svg\",\"dagger\":\"f974ae3.svg\",\"dagger_knife\":\"f974ae3.svg\",\"shield\":\"0d534b0.svg\",\"smoking\":\"f709fc8.svg\",\"coffin\":\"0f45480.svg\",\"headstone\":\"5f2708d.svg\",\"urn\":\"6b8d9f1.svg\",\"funeral_urn\":\"6b8d9f1.svg\",\"amphora\":\"2a10a18.svg\",\"magic_wand\":\"abcf317.svg\",\"crystal_ball\":\"15d1b34.svg\",\"prayer_beads\":\"fecca1a.svg\",\"nazar_amulet\":\"6b02e26.svg\",\"barber\":\"54ba31e.svg\",\"telescope\":\"625d524.svg\",\"microscope\":\"f1fd0f0.svg\",\"hole\":\"6e81e53.svg\",\"window\":\"33a5ce8.svg\",\"adhesive_bandage\":\"cc4d394.svg\",\"stethoscope\":\"3cd880e.svg\",\"pill\":\"06481bd.svg\",\"syringe\":\"3126fb2.svg\",\"drop_of_blood\":\"c214a30.svg\",\"dna\":\"bc1c9dc.svg\",\"microbe\":\"751fc12.svg\",\"petri_dish\":\"1dd0c34.svg\",\"test_tube\":\"3628ffc.svg\",\"thermometer\":\"aee2f27.svg\",\"mouse_trap\":\"7580985.svg\",\"broom\":\"2e58d3d.svg\",\"basket\":\"d558daa.svg\",\"sewing_needle\":\"3322d7c.svg\",\"roll_of_paper\":\"4bb9b48.svg\",\"toilet\":\"9944889.svg\",\"plunger\":\"f209c2f.svg\",\"bucket\":\"8e9cdc0.svg\",\"potable_water\":\"0c357ca.svg\",\"shower\":\"ca42b84.svg\",\"bathtub\":\"cdc6826.svg\",\"bath\":\"b15ecb4.svg\",\"bath_tone1\":\"b73c83b.svg\",\"bath_tone2\":\"4dc5728.svg\",\"bath_tone3\":\"4a6dc70.svg\",\"bath_tone4\":\"ffca481.svg\",\"bath_tone5\":\"45d0461.svg\",\"toothbrush\":\"09a491b.svg\",\"soap\":\"54dd924.svg\",\"razor\":\"0d83e13.svg\",\"sponge\":\"8de141f.svg\",\"squeeze_bottle\":\"2b63004.svg\",\"bellhop\":\"9e8511f.svg\",\"bellhop_bell\":\"9e8511f.svg\",\"key\":\"f024110.svg\",\"key2\":\"f7b6e6b.svg\",\"old_key\":\"f7b6e6b.svg\",\"door\":\"eec520d.svg\",\"chair\":\"bc332e6.svg\",\"mirror\":\"39db427.svg\",\"couch\":\"ebb4f4d.svg\",\"couch_and_lamp\":\"ebb4f4d.svg\",\"bed\":\"722e9a2.svg\",\"sleeping_accommodation\":\"848e303.svg\",\"person_in_bed_tone1\":\"4e627cc.svg\",\"person_in_bed_light_skin_tone\":\"4e627cc.svg\",\"person_in_bed_tone2\":\"edb7a4c.svg\",\"person_in_bed_medium_light_skin_tone\":\"edb7a4c.svg\",\"person_in_bed_tone3\":\"66bcd2b.svg\",\"person_in_bed_medium_skin_tone\":\"66bcd2b.svg\",\"person_in_bed_tone4\":\"d9a1851.svg\",\"person_in_bed_medium_dark_skin_tone\":\"d9a1851.svg\",\"person_in_bed_tone5\":\"30e9323.svg\",\"person_in_bed_dark_skin_tone\":\"30e9323.svg\",\"teddy_bear\":\"1b3b59e.svg\",\"frame_photo\":\"f773485.svg\",\"frame_with_picture\":\"f773485.svg\",\"shopping_bags\":\"ee2a1bd.svg\",\"shopping_cart\":\"92bbb27.svg\",\"shopping_trolley\":\"92bbb27.svg\",\"gift\":\"667a23e.svg\",\"balloon\":\"c77e962.svg\",\"flags\":\"bee24a6.svg\",\"ribbon\":\"62342e3.svg\",\"confetti_ball\":\"d060485.svg\",\"tada\":\"3eff897.svg\",\"pinata\":\"8449683.svg\",\"nesting_dolls\":\"e6ed873.svg\",\"dolls\":\"f0f2c76.svg\",\"izakaya_lantern\":\"96d5937.svg\",\"wind_chime\":\"cb4b9cc.svg\",\"red_envelope\":\"1b3bbc0.svg\",\"envelope_with_arrow\":\"2840e02.svg\",\"incoming_envelope\":\"0dc4ce5.svg\",\"e-mail\":\"8b97fb1.svg\",\"email\":\"8b97fb1.svg\",\"love_letter\":\"8b99ce1.svg\",\"inbox_tray\":\"d2f41f2.svg\",\"outbox_tray\":\"34d71ce.svg\",\"package\":\"35b2169.svg\",\"label\":\"d4c5eb8.svg\",\"mailbox_closed\":\"5485425.svg\",\"mailbox\":\"f390395.svg\",\"mailbox_with_mail\":\"866cf4c.svg\",\"mailbox_with_no_mail\":\"81356e8.svg\",\"postbox\":\"ddcaa58.svg\",\"postal_horn\":\"5bb498a.svg\",\"placard\":\"980cf8a.svg\",\"scroll\":\"83ef1c5.svg\",\"page_with_curl\":\"715306e.svg\",\"page_facing_up\":\"f503e29.svg\",\"bookmark_tabs\":\"15c5d93.svg\",\"receipt\":\"e78618d.svg\",\"bar_chart\":\"d9f3686.svg\",\"chart_with_upwards_trend\":\"c2d2846.svg\",\"chart_with_downwards_trend\":\"b793d0e.svg\",\"notepad_spiral\":\"14933b2.svg\",\"spiral_note_pad\":\"14933b2.svg\",\"calendar_spiral\":\"e6b67b0.svg\",\"spiral_calendar_pad\":\"e6b67b0.svg\",\"calendar\":\"535e551.svg\",\"date\":\"b41658d.svg\",\"wastebasket\":\"8a4d76d.svg\",\"card_index\":\"d606c3a.svg\",\"card_box\":\"1410be1.svg\",\"card_file_box\":\"1410be1.svg\",\"ballot_box\":\"b77638a.svg\",\"ballot_box_with_ballot\":\"b77638a.svg\",\"file_cabinet\":\"c23e1f7.svg\",\"clipboard\":\"734d53a.svg\",\"file_folder\":\"7270d1a.svg\",\"open_file_folder\":\"17b8130.svg\",\"dividers\":\"a3166fb.svg\",\"card_index_dividers\":\"a3166fb.svg\",\"newspaper2\":\"78af43c.svg\",\"rolled_up_newspaper\":\"78af43c.svg\",\"newspaper\":\"33e45ff.svg\",\"notebook\":\"944dedb.svg\",\"notebook_with_decorative_cover\":\"7bf9b8b.svg\",\"ledger\":\"035d8fb.svg\",\"closed_book\":\"d191cf2.svg\",\"green_book\":\"1263d2d.svg\",\"blue_book\":\"c8f1aae.svg\",\"orange_book\":\"96acb2f.svg\",\"books\":\"de7b39d.svg\",\"book\":\"68ab4c4.svg\",\"bookmark\":\"5722afe.svg\",\"safety_pin\":\"02701ce.svg\",\"link\":\"64b8ced.svg\",\"paperclip\":\"a5cadec.svg\",\"paperclips\":\"ee9497c.svg\",\"linked_paperclips\":\"ee9497c.svg\",\"triangular_ruler\":\"70403b8.svg\",\"straight_ruler\":\"2ef34f4.svg\",\"abacus\":\"5736cb9.svg\",\"pushpin\":\"fe05cca.svg\",\"round_pushpin\":\"1cfaddc.svg\",\"pen_ballpoint\":\"68e2cd3.svg\",\"lower_left_ballpoint_pen\":\"68e2cd3.svg\",\"pen_fountain\":\"438545d.svg\",\"lower_left_fountain_pen\":\"438545d.svg\",\"paintbrush\":\"d1c4b5e.svg\",\"lower_left_paintbrush\":\"d1c4b5e.svg\",\"crayon\":\"7230001.svg\",\"lower_left_crayon\":\"7230001.svg\",\"pencil\":\"c95a532.svg\",\"memo\":\"c95a532.svg\",\"pencil2\":\"c3fe3d3.svg\",\"mag\":\"4d82637.svg\",\"mag_right\":\"52b5e36.svg\",\"lock_with_ink_pen\":\"1e6575f.svg\",\"closed_lock_with_key\":\"38d17e7.svg\",\"lock\":\"d131271.svg\",\"unlock\":\"b7ccda7.svg\",\"orange_heart\":\"f42c7a7.svg\",\"yellow_heart\":\"00ee6f2.svg\",\"green_heart\":\"6f33c33.svg\",\"blue_heart\":\"46cf244.svg\",\"purple_heart\":\"0514cbb.svg\",\"black_heart\":\"671d2be.svg\",\"brown_heart\":\"57627e2.svg\",\"white_heart\":\"9f3bddf.svg\",\"broken_heart\":\"e27c117.svg\",\"two_hearts\":\"230d425.svg\",\"revolving_hearts\":\"f1f519f.svg\",\"heartbeat\":\"95cf806.svg\",\"heartpulse\":\"9b2e17a.svg\",\"sparkling_heart\":\"383a7b6.svg\",\"cupid\":\"a708e66.svg\",\"gift_heart\":\"1a0c7fc.svg\",\"mending_heart\":\"bb2dee2.svg\",\"heart_on_fire\":\"686b568.svg\",\"heart_decoration\":\"9ee5106.svg\",\"peace\":\"81ac8f2.svg\",\"peace_symbol\":\"81ac8f2.svg\",\"cross\":\"0352b99.svg\",\"latin_cross\":\"0352b99.svg\",\"star_and_crescent\":\"87e2668.svg\",\"om_symbol\":\"fdbef1c.svg\",\"six_pointed_star\":\"6367072.svg\",\"menorah\":\"49fe2f3.svg\",\"yin_yang\":\"782b6e0.svg\",\"place_of_worship\":\"40e98b3.svg\",\"worship_symbol\":\"40e98b3.svg\",\"ophiuchus\":\"4be146d.svg\",\"gemini\":\"39ccf78.svg\",\"cancer\":\"1e6bf0d.svg\",\"leo\":\"571693e.svg\",\"virgo\":\"315b50a.svg\",\"libra\":\"59f58f6.svg\",\"scorpius\":\"b6e89bf.svg\",\"id\":\"08f0aed.svg\",\"atom\":\"62bdeb7.svg\",\"atom_symbol\":\"62bdeb7.svg\",\"accept\":\"de5e369.svg\",\"mobile_phone_off\":\"0046ab1.svg\",\"vibration_mode\":\"fbee5ea.svg\",\"u6709\":\"7c32c00.svg\",\"u7121\":\"93bf37c.svg\",\"u7533\":\"c630391.svg\",\"u55b6\":\"765d280.svg\",\"u6708\":\"ff7053e.svg\",\"vs\":\"92b6e21.svg\",\"white_flower\":\"3561149.svg\",\"ideograph_advantage\":\"ce742e0.svg\",\"u5408\":\"2a415c0.svg\",\"u6e80\":\"079b9a5.svg\",\"u5272\":\"3abb1c3.svg\",\"u7981\":\"5f7fd48.svg\",\"a\":\"4d2357b.svg\",\"b\":\"15c3646.svg\",\"ab\":\"84f84e4.svg\",\"cl\":\"06c5b84.svg\",\"o2\":\"32f4bbe.svg\",\"sos\":\"9de07ec.svg\",\"x\":\"3a778be.svg\",\"o\":\"4407433.svg\",\"octagonal_sign\":\"db5dae1.svg\",\"stop_sign\":\"db5dae1.svg\",\"no_entry\":\"2431948.svg\",\"name_badge\":\"8e5412b.svg\",\"no_entry_sign\":\"6d87aae.svg\",\"anger\":\"05c2db1.svg\",\"no_pedestrians\":\"476e169.svg\",\"do_not_litter\":\"8c379b2.svg\",\"no_bicycles\":\"70b6a87.svg\",\"non-potable_water\":\"ac822b0.svg\",\"underage\":\"a0dc432.svg\",\"no_mobile_phones\":\"038ef1f.svg\",\"no_smoking\":\"4ef8a9d.svg\",\"bangbang\":\"62824e0.svg\",\"low_brightness\":\"118f858.svg\",\"high_brightness\":\"8ad70fe.svg\",\"part_alternation_mark\":\"4f63f69.svg\",\"warning\":\"8d54d46.svg\",\"children_crossing\":\"77b0db8.svg\",\"trident\":\"a7d3c5a.svg\",\"fleur-de-lis\":\"f1b7b1a.svg\",\"beginner\":\"8636018.svg\",\"recycle\":\"53bf457.svg\",\"u6307\":\"9922ede.svg\",\"chart\":\"23c755c.svg\",\"negative_squared_cross_mark\":\"b7ea18a.svg\",\"globe_with_meridians\":\"2e01a51.svg\",\"diamond_shape_with_a_dot_inside\":\"cf75eb9.svg\",\"m\":\"f62c2ef.svg\",\"cyclone\":\"c59443e.svg\",\"zzz\":\"da19ffe.svg\",\"atm\":\"faef8df.svg\",\"wc\":\"6f23bcd.svg\",\"wheelchair\":\"85c9f56.svg\",\"parking\":\"1d8a190.svg\",\"u7a7a\":\"5dfaae1.svg\",\"sa\":\"2a42295.svg\",\"passport_control\":\"6996331.svg\",\"customs\":\"87c1f0b.svg\",\"baggage_claim\":\"e0404d8.svg\",\"left_luggage\":\"fe66858.svg\",\"elevator\":\"4085820.svg\",\"mens\":\"baf6ba4.svg\",\"womens\":\"4f3d3d3.svg\",\"baby_symbol\":\"dc8abeb.svg\",\"restroom\":\"1c1d4b1.svg\",\"put_litter_in_its_place\":\"5c8437b.svg\",\"cinema\":\"9229e02.svg\",\"signal_strength\":\"d77ae4f.svg\",\"koko\":\"742a4da.svg\",\"symbols\":\"0675dde.svg\",\"abc\":\"f046fcb.svg\",\"abcd\":\"c50f908.svg\",\"capital_abcd\":\"0060d9a.svg\",\"ng\":\"eb732a9.svg\",\"ok\":\"f4bdfeb.svg\",\"up\":\"8149045.svg\",\"cool\":\"22331aa.svg\",\"new\":\"e1a41f7.svg\",\"free\":\"f942f77.svg\",\"keycap_ten\":\"156b08b.svg\",\"eject\":\"c456e52.svg\",\"eject_symbol\":\"c456e52.svg\",\"arrow_forward\":\"ddc7d76.svg\",\"pause_button\":\"26e7adc.svg\",\"double_vertical_bar\":\"26e7adc.svg\",\"play_pause\":\"6ebd001.svg\",\"stop_button\":\"0e334b6.svg\",\"record_button\":\"00e7f17.svg\",\"track_next\":\"7773750.svg\",\"next_track\":\"7773750.svg\",\"track_previous\":\"e48c0e5.svg\",\"previous_track\":\"e48c0e5.svg\",\"fast_forward\":\"4e5cba4.svg\",\"rewind\":\"69e3a53.svg\",\"arrow_double_up\":\"3f5e2f1.svg\",\"arrow_double_down\":\"4457f0f.svg\",\"arrow_backward\":\"87c98dd.svg\",\"arrow_up_small\":\"d0d5c2c.svg\",\"arrow_down_small\":\"9e1110f.svg\",\"arrow_right\":\"7fd81bf.svg\",\"arrow_left\":\"a432020.svg\",\"arrow_up\":\"145534d.svg\",\"arrow_down\":\"31b41df.svg\",\"arrow_right_hook\":\"b5043ba.svg\",\"leftwards_arrow_with_hook\":\"2f11417.svg\",\"twisted_rightwards_arrows\":\"a88a7f5.svg\",\"repeat\":\"1543113.svg\",\"repeat_one\":\"c73671f.svg\",\"arrows_counterclockwise\":\"6416a28.svg\",\"arrows_clockwise\":\"8ccdeab.svg\",\"musical_note\":\"bd8cb8d.svg\",\"notes\":\"ac4a2ab.svg\",\"infinity\":\"9be29bc.svg\",\"heavy_dollar_sign\":\"ce4626a.svg\",\"currency_exchange\":\"f92fd67.svg\",\"curly_loop\":\"81f6081.svg\",\"loop\":\"db1d000.svg\",\"end\":\"f33a1a5.svg\",\"back\":\"5f9eccf.svg\",\"on\":\"e431464.svg\",\"top\":\"907c2e4.svg\",\"soon\":\"b03cc8c.svg\",\"radio_button\":\"26d4f6c.svg\",\"white_circle\":\"878f00b.svg\",\"black_circle\":\"ee7749a.svg\",\"red_circle\":\"3e94570.svg\",\"blue_circle\":\"4bfbb7b.svg\",\"brown_circle\":\"0d2e831.svg\",\"purple_circle\":\"3e4174e.svg\",\"green_circle\":\"125b1ec.svg\",\"yellow_circle\":\"b86c5e4.svg\",\"orange_circle\":\"cf825eb.svg\",\"small_red_triangle\":\"00d21f8.svg\",\"small_red_triangle_down\":\"0bcf5ff.svg\",\"small_orange_diamond\":\"b80bfa0.svg\",\"small_blue_diamond\":\"660eb8d.svg\",\"large_orange_diamond\":\"73e4a33.svg\",\"large_blue_diamond\":\"2011e33.svg\",\"white_square_button\":\"7411701.svg\",\"black_square_button\":\"274717d.svg\",\"black_small_square\":\"fbabe68.svg\",\"white_small_square\":\"2e67568.svg\",\"black_medium_small_square\":\"3b4427b.svg\",\"white_medium_small_square\":\"00b5ec5.svg\",\"black_medium_square\":\"522667a.svg\",\"white_medium_square\":\"d1e58db.svg\",\"black_large_square\":\"637d2e5.svg\",\"white_large_square\":\"f05e212.svg\",\"orange_square\":\"006b61a.svg\",\"blue_square\":\"12b9986.svg\",\"red_square\":\"62ac584.svg\",\"brown_square\":\"6b19693.svg\",\"purple_square\":\"487d6ca.svg\",\"green_square\":\"3f5720c.svg\",\"yellow_square\":\"af8c2d4.svg\",\"speaker\":\"c02c90c.svg\",\"mute\":\"56c7c3c.svg\",\"sound\":\"b493060.svg\",\"loud_sound\":\"0c1f211.svg\",\"bell\":\"afd3446.svg\",\"no_bell\":\"69d9d8b.svg\",\"mega\":\"342e222.svg\",\"loudspeaker\":\"3ae22f0.svg\",\"speech_left\":\"ef62b73.svg\",\"left_speech_bubble\":\"ef62b73.svg\",\"speech_balloon\":\"ca7bbec.svg\",\"thought_balloon\":\"31f13a5.svg\",\"anger_right\":\"83383b9.svg\",\"right_anger_bubble\":\"83383b9.svg\",\"black_joker\":\"848f060.svg\",\"flower_playing_cards\":\"e350d7d.svg\",\"mahjong\":\"eeca78a.svg\",\"clock1\":\"c21d8a7.svg\",\"clock2\":\"0570833.svg\",\"clock3\":\"a40be16.svg\",\"clock4\":\"1f74d9f.svg\",\"clock5\":\"f864964.svg\",\"clock6\":\"9f23d49.svg\",\"clock7\":\"6fca2db.svg\",\"clock8\":\"1861145.svg\",\"clock9\":\"da17b83.svg\",\"clock10\":\"64c8f11.svg\",\"clock11\":\"8635d2c.svg\",\"clock12\":\"5f9757c.svg\",\"clock130\":\"e289ef7.svg\",\"clock230\":\"e6ebfa4.svg\",\"clock330\":\"addac22.svg\",\"clock430\":\"244dc36.svg\",\"clock530\":\"39990cf.svg\",\"clock630\":\"23376b9.svg\",\"clock730\":\"8d14ee4.svg\",\"clock830\":\"e70ea22.svg\",\"clock930\":\"f40959f.svg\",\"clock1030\":\"b07a3c9.svg\",\"clock1130\":\"26233c1.svg\",\"clock1230\":\"9b4d7d3.svg\",\"transgender_symbol\":\"ddf109e.svg\",\"flag_white\":\"a50f7fb.svg\",\"waving_white_flag\":\"a50f7fb.svg\",\"flag_black\":\"c9ae19e.svg\",\"waving_black_flag\":\"c9ae19e.svg\",\"checkered_flag\":\"3390133.svg\",\"triangular_flag_on_post\":\"16f482e.svg\",\"rainbow_flag\":\"6e96910.svg\",\"gay_pride_flag\":\"6e96910.svg\",\"transgender_flag\":\"f998d7c.svg\",\"pirate_flag\":\"9e00e92.svg\",\"flag_af\":\"021e19b.svg\",\"af\":\"021e19b.svg\",\"flag_ax\":\"7e7b820.svg\",\"ax\":\"7e7b820.svg\",\"flag_al\":\"16a82f9.svg\",\"al\":\"16a82f9.svg\",\"flag_dz\":\"d75256e.svg\",\"dz\":\"d75256e.svg\",\"flag_as\":\"9717b6c.svg\",\"as\":\"9717b6c.svg\",\"flag_ad\":\"f04fc99.svg\",\"ad\":\"f04fc99.svg\",\"flag_ao\":\"897dc1e.svg\",\"ao\":\"897dc1e.svg\",\"flag_ai\":\"f264d5f.svg\",\"ai\":\"f264d5f.svg\",\"flag_aq\":\"6ddd951.svg\",\"aq\":\"6ddd951.svg\",\"flag_ag\":\"43db600.svg\",\"ag\":\"43db600.svg\",\"flag_ar\":\"6400d86.svg\",\"ar\":\"6400d86.svg\",\"flag_am\":\"ca78cae.svg\",\"am\":\"ca78cae.svg\",\"flag_aw\":\"29c5ff8.svg\",\"aw\":\"29c5ff8.svg\",\"flag_au\":\"9d6fbca.svg\",\"au\":\"9d6fbca.svg\",\"flag_at\":\"df7fc82.svg\",\"at\":\"df7fc82.svg\",\"flag_az\":\"46f0416.svg\",\"az\":\"46f0416.svg\",\"flag_bs\":\"c0e2384.svg\",\"bs\":\"c0e2384.svg\",\"flag_bh\":\"f0bbd1c.svg\",\"bh\":\"f0bbd1c.svg\",\"flag_bd\":\"260e2c2.svg\",\"bd\":\"260e2c2.svg\",\"flag_bb\":\"78dfe57.svg\",\"bb\":\"78dfe57.svg\",\"flag_by\":\"86cf5da.svg\",\"by\":\"86cf5da.svg\",\"flag_be\":\"0c4ab23.svg\",\"be\":\"0c4ab23.svg\",\"flag_bz\":\"43c82a1.svg\",\"bz\":\"43c82a1.svg\",\"flag_bj\":\"4387163.svg\",\"bj\":\"4387163.svg\",\"flag_bm\":\"9afaba5.svg\",\"bm\":\"9afaba5.svg\",\"flag_bt\":\"a5aaec2.svg\",\"bt\":\"a5aaec2.svg\",\"flag_bo\":\"8f369cc.svg\",\"bo\":\"8f369cc.svg\",\"flag_ba\":\"c549423.svg\",\"ba\":\"c549423.svg\",\"flag_bw\":\"b68d515.svg\",\"bw\":\"b68d515.svg\",\"flag_br\":\"8807761.svg\",\"br\":\"8807761.svg\",\"flag_io\":\"80ba637.svg\",\"io\":\"80ba637.svg\",\"flag_vg\":\"9af55a7.svg\",\"vg\":\"9af55a7.svg\",\"flag_bn\":\"8921a94.svg\",\"bn\":\"8921a94.svg\",\"flag_bg\":\"9e2baa7.svg\",\"bg\":\"9e2baa7.svg\",\"flag_bf\":\"6efb5e6.svg\",\"bf\":\"6efb5e6.svg\",\"flag_bi\":\"c30fef5.svg\",\"bi\":\"c30fef5.svg\",\"flag_kh\":\"4fffe5d.svg\",\"kh\":\"4fffe5d.svg\",\"flag_cm\":\"85f707f.svg\",\"cm\":\"85f707f.svg\",\"flag_ca\":\"c8257e6.svg\",\"ca\":\"c8257e6.svg\",\"flag_ic\":\"ccd25a8.svg\",\"ic\":\"ccd25a8.svg\",\"flag_cv\":\"3601756.svg\",\"cv\":\"3601756.svg\",\"flag_bq\":\"895520d.svg\",\"bq\":\"895520d.svg\",\"flag_ky\":\"b42cd3d.svg\",\"ky\":\"b42cd3d.svg\",\"flag_cf\":\"0b6aa82.svg\",\"cf\":\"0b6aa82.svg\",\"flag_td\":\"3fb4d3b.svg\",\"td\":\"3fb4d3b.svg\",\"flag_cl\":\"736e4d4.svg\",\"chile\":\"736e4d4.svg\",\"flag_cn\":\"11fb0d7.svg\",\"cn\":\"11fb0d7.svg\",\"flag_cx\":\"3d3cf13.svg\",\"cx\":\"3d3cf13.svg\",\"flag_cc\":\"dab36e7.svg\",\"cc\":\"dab36e7.svg\",\"flag_co\":\"4779a07.svg\",\"co\":\"4779a07.svg\",\"flag_km\":\"281b7a8.svg\",\"km\":\"281b7a8.svg\",\"flag_cg\":\"02147fe.svg\",\"cg\":\"02147fe.svg\",\"flag_cd\":\"1570933.svg\",\"congo\":\"1570933.svg\",\"flag_ck\":\"d1ada81.svg\",\"ck\":\"d1ada81.svg\",\"flag_cr\":\"1fa2a8a.svg\",\"cr\":\"1fa2a8a.svg\",\"flag_ci\":\"c281f36.svg\",\"ci\":\"c281f36.svg\",\"flag_hr\":\"8e6c6f0.svg\",\"hr\":\"8e6c6f0.svg\",\"flag_cu\":\"c7a2da5.svg\",\"cu\":\"c7a2da5.svg\",\"flag_cw\":\"3c2dbfc.svg\",\"cw\":\"3c2dbfc.svg\",\"flag_cy\":\"5b42267.svg\",\"cy\":\"5b42267.svg\",\"flag_cz\":\"d2b9eed.svg\",\"cz\":\"d2b9eed.svg\",\"flag_dk\":\"450e300.svg\",\"dk\":\"450e300.svg\",\"flag_dj\":\"1c0c52c.svg\",\"dj\":\"1c0c52c.svg\",\"flag_dm\":\"babf9e7.svg\",\"dm\":\"babf9e7.svg\",\"flag_do\":\"5e49b01.svg\",\"do\":\"5e49b01.svg\",\"flag_ec\":\"a0d4fbd.svg\",\"ec\":\"a0d4fbd.svg\",\"flag_eg\":\"793c58c.svg\",\"eg\":\"793c58c.svg\",\"flag_sv\":\"60580e4.svg\",\"sv\":\"60580e4.svg\",\"flag_gq\":\"0b3f2c2.svg\",\"gq\":\"0b3f2c2.svg\",\"flag_er\":\"7797e8c.svg\",\"er\":\"7797e8c.svg\",\"flag_ee\":\"4fbd9a7.svg\",\"ee\":\"4fbd9a7.svg\",\"flag_et\":\"66fb1fd.svg\",\"et\":\"66fb1fd.svg\",\"flag_eu\":\"bdf20eb.svg\",\"eu\":\"bdf20eb.svg\",\"flag_fk\":\"5688b65.svg\",\"fk\":\"5688b65.svg\",\"flag_fo\":\"e06015c.svg\",\"fo\":\"e06015c.svg\",\"flag_fj\":\"724a378.svg\",\"fj\":\"724a378.svg\",\"flag_fi\":\"dbb78d5.svg\",\"fi\":\"dbb78d5.svg\",\"flag_fr\":\"5cff674.svg\",\"fr\":\"5cff674.svg\",\"flag_gf\":\"6036e01.svg\",\"gf\":\"6036e01.svg\",\"flag_pf\":\"1a3c99f.svg\",\"pf\":\"1a3c99f.svg\",\"flag_tf\":\"a103c9a.svg\",\"tf\":\"a103c9a.svg\",\"flag_ga\":\"2cb99a0.svg\",\"ga\":\"2cb99a0.svg\",\"flag_gm\":\"5818aec.svg\",\"gm\":\"5818aec.svg\",\"flag_ge\":\"4d9cdea.svg\",\"ge\":\"4d9cdea.svg\",\"flag_de\":\"1a8edb7.svg\",\"de\":\"1a8edb7.svg\",\"flag_gh\":\"59086bb.svg\",\"gh\":\"59086bb.svg\",\"flag_gi\":\"3ccc59a.svg\",\"gi\":\"3ccc59a.svg\",\"flag_gr\":\"7292d30.svg\",\"gr\":\"7292d30.svg\",\"flag_gl\":\"5f1fc89.svg\",\"gl\":\"5f1fc89.svg\",\"flag_gd\":\"56a6c04.svg\",\"gd\":\"56a6c04.svg\",\"flag_gp\":\"cce9290.svg\",\"gp\":\"cce9290.svg\",\"flag_gu\":\"861d7e0.svg\",\"gu\":\"861d7e0.svg\",\"flag_gt\":\"0c6496e.svg\",\"gt\":\"0c6496e.svg\",\"flag_gg\":\"cda502a.svg\",\"gg\":\"cda502a.svg\",\"flag_gn\":\"7ddeab1.svg\",\"gn\":\"7ddeab1.svg\",\"flag_gw\":\"dfccc52.svg\",\"gw\":\"dfccc52.svg\",\"flag_gy\":\"d5a6bef.svg\",\"gy\":\"d5a6bef.svg\",\"flag_ht\":\"7375ef7.svg\",\"ht\":\"7375ef7.svg\",\"flag_hn\":\"3e1122c.svg\",\"hn\":\"3e1122c.svg\",\"flag_hk\":\"647125f.svg\",\"hk\":\"647125f.svg\",\"flag_hu\":\"9193ed6.svg\",\"hu\":\"9193ed6.svg\",\"flag_is\":\"cfd6994.svg\",\"is\":\"cfd6994.svg\",\"flag_in\":\"41f09b0.svg\",\"in\":\"41f09b0.svg\",\"flag_id\":\"cec6ea4.svg\",\"indonesia\":\"cec6ea4.svg\",\"flag_ir\":\"79a52a6.svg\",\"ir\":\"79a52a6.svg\",\"flag_iq\":\"e61ee4a.svg\",\"iq\":\"e61ee4a.svg\",\"flag_ie\":\"c3b5afc.svg\",\"ie\":\"c3b5afc.svg\",\"flag_im\":\"4b596cd.svg\",\"im\":\"4b596cd.svg\",\"flag_il\":\"2210905.svg\",\"il\":\"2210905.svg\",\"flag_it\":\"e4a918d.svg\",\"it\":\"e4a918d.svg\",\"flag_jm\":\"8b3496f.svg\",\"jm\":\"8b3496f.svg\",\"flag_jp\":\"6648971.svg\",\"jp\":\"6648971.svg\",\"crossed_flags\":\"06a6bc5.svg\",\"flag_je\":\"4ddd431.svg\",\"je\":\"4ddd431.svg\",\"flag_jo\":\"1e7b07b.svg\",\"jo\":\"1e7b07b.svg\",\"flag_kz\":\"dc3d46c.svg\",\"kz\":\"dc3d46c.svg\",\"flag_ke\":\"7e58fbd.svg\",\"ke\":\"7e58fbd.svg\",\"flag_ki\":\"a738347.svg\",\"ki\":\"a738347.svg\",\"flag_xk\":\"232353a.svg\",\"xk\":\"232353a.svg\",\"flag_kw\":\"3d83192.svg\",\"kw\":\"3d83192.svg\",\"flag_kg\":\"f7a706f.svg\",\"kg\":\"f7a706f.svg\",\"flag_la\":\"c60a423.svg\",\"la\":\"c60a423.svg\",\"flag_lv\":\"29510db.svg\",\"lv\":\"29510db.svg\",\"flag_lb\":\"57c2b9b.svg\",\"lb\":\"57c2b9b.svg\",\"flag_ls\":\"ad8a2dc.svg\",\"ls\":\"ad8a2dc.svg\",\"flag_lr\":\"1a9ac5c.svg\",\"lr\":\"1a9ac5c.svg\",\"flag_ly\":\"a5fea03.svg\",\"ly\":\"a5fea03.svg\",\"flag_li\":\"94ed289.svg\",\"li\":\"94ed289.svg\",\"flag_lt\":\"cc86db2.svg\",\"lt\":\"cc86db2.svg\",\"flag_lu\":\"0ee6ec7.svg\",\"lu\":\"0ee6ec7.svg\",\"flag_mo\":\"5065e30.svg\",\"mo\":\"5065e30.svg\",\"flag_mk\":\"aeede56.svg\",\"mk\":\"aeede56.svg\",\"flag_mg\":\"82e95c1.svg\",\"mg\":\"82e95c1.svg\",\"flag_mw\":\"b18642d.svg\",\"mw\":\"b18642d.svg\",\"flag_my\":\"1689dc8.svg\",\"my\":\"1689dc8.svg\",\"flag_mv\":\"2ed1065.svg\",\"mv\":\"2ed1065.svg\",\"flag_ml\":\"6c80614.svg\",\"ml\":\"6c80614.svg\",\"flag_mt\":\"5c9fbf1.svg\",\"mt\":\"5c9fbf1.svg\",\"flag_mh\":\"be2f0bb.svg\",\"mh\":\"be2f0bb.svg\",\"flag_mq\":\"7a75dc9.svg\",\"mq\":\"7a75dc9.svg\",\"flag_mr\":\"dff1ba5.svg\",\"mr\":\"dff1ba5.svg\",\"flag_mu\":\"79cacd5.svg\",\"mu\":\"79cacd5.svg\",\"flag_yt\":\"30705e0.svg\",\"yt\":\"30705e0.svg\",\"flag_mx\":\"456b673.svg\",\"mx\":\"456b673.svg\",\"flag_fm\":\"6cbab14.svg\",\"fm\":\"6cbab14.svg\",\"flag_md\":\"ab95150.svg\",\"md\":\"ab95150.svg\",\"flag_mc\":\"11df3fe.svg\",\"mc\":\"11df3fe.svg\",\"flag_mn\":\"925fd1e.svg\",\"mn\":\"925fd1e.svg\",\"flag_me\":\"eb70192.svg\",\"me\":\"eb70192.svg\",\"flag_ms\":\"50fbe95.svg\",\"ms\":\"50fbe95.svg\",\"flag_ma\":\"17a17e2.svg\",\"ma\":\"17a17e2.svg\",\"flag_mz\":\"8dcf8bd.svg\",\"mz\":\"8dcf8bd.svg\",\"flag_mm\":\"3d0cb06.svg\",\"mm\":\"3d0cb06.svg\",\"flag_na\":\"3f08e8d.svg\",\"na\":\"3f08e8d.svg\",\"flag_nr\":\"a4b0613.svg\",\"nr\":\"a4b0613.svg\",\"flag_np\":\"7618ed2.svg\",\"np\":\"7618ed2.svg\",\"flag_nl\":\"2bf611b.svg\",\"nl\":\"2bf611b.svg\",\"flag_nc\":\"63c6363.svg\",\"nc\":\"63c6363.svg\",\"flag_nz\":\"143c6cb.svg\",\"nz\":\"143c6cb.svg\",\"flag_ni\":\"a4c869c.svg\",\"ni\":\"a4c869c.svg\",\"flag_ne\":\"264a3f7.svg\",\"ne\":\"264a3f7.svg\",\"flag_ng\":\"7aa6dd1.svg\",\"nigeria\":\"7aa6dd1.svg\",\"flag_nu\":\"a81d8cd.svg\",\"nu\":\"a81d8cd.svg\",\"flag_nf\":\"1f55bf8.svg\",\"nf\":\"1f55bf8.svg\",\"flag_kp\":\"22b01b7.svg\",\"kp\":\"22b01b7.svg\",\"flag_mp\":\"704174c.svg\",\"mp\":\"704174c.svg\",\"flag_no\":\"8ead297.svg\",\"no\":\"8ead297.svg\",\"flag_om\":\"83309b0.svg\",\"om\":\"83309b0.svg\",\"flag_pk\":\"63477da.svg\",\"pk\":\"63477da.svg\",\"flag_pw\":\"7806d88.svg\",\"pw\":\"7806d88.svg\",\"flag_ps\":\"ed1ab14.svg\",\"ps\":\"ed1ab14.svg\",\"flag_pa\":\"5300ebb.svg\",\"pa\":\"5300ebb.svg\",\"flag_pg\":\"b2d5ce6.svg\",\"pg\":\"b2d5ce6.svg\",\"flag_py\":\"4230491.svg\",\"py\":\"4230491.svg\",\"flag_pe\":\"a27ffb4.svg\",\"pe\":\"a27ffb4.svg\",\"flag_ph\":\"d66113b.svg\",\"ph\":\"d66113b.svg\",\"flag_pn\":\"27cadf4.svg\",\"pn\":\"27cadf4.svg\",\"flag_pl\":\"fca0605.svg\",\"pl\":\"fca0605.svg\",\"flag_pt\":\"f0fbb6a.svg\",\"pt\":\"f0fbb6a.svg\",\"flag_pr\":\"1f8701b.svg\",\"pr\":\"1f8701b.svg\",\"flag_qa\":\"c098ca4.svg\",\"qa\":\"c098ca4.svg\",\"flag_re\":\"13fdd39.svg\",\"re\":\"13fdd39.svg\",\"flag_ro\":\"b56504a.svg\",\"ro\":\"b56504a.svg\",\"flag_ru\":\"904f92c.svg\",\"ru\":\"904f92c.svg\",\"flag_rw\":\"ccce0f2.svg\",\"rw\":\"ccce0f2.svg\",\"flag_ws\":\"db45833.svg\",\"ws\":\"db45833.svg\",\"flag_sm\":\"9f22d88.svg\",\"sm\":\"9f22d88.svg\",\"flag_st\":\"c1570c6.svg\",\"st\":\"c1570c6.svg\",\"flag_sa\":\"a1b7982.svg\",\"saudiarabia\":\"a1b7982.svg\",\"saudi\":\"a1b7982.svg\",\"flag_sn\":\"840d9e2.svg\",\"sn\":\"840d9e2.svg\",\"flag_rs\":\"99cc773.svg\",\"rs\":\"99cc773.svg\",\"flag_sc\":\"55b9a97.svg\",\"sc\":\"55b9a97.svg\",\"flag_sl\":\"90325e9.svg\",\"sl\":\"90325e9.svg\",\"flag_sg\":\"9b25e68.svg\",\"sg\":\"9b25e68.svg\",\"flag_sx\":\"898d18c.svg\",\"sx\":\"898d18c.svg\",\"flag_sk\":\"93a9eef.svg\",\"sk\":\"93a9eef.svg\",\"flag_si\":\"5411747.svg\",\"si\":\"5411747.svg\",\"flag_gs\":\"ffbb640.svg\",\"gs\":\"ffbb640.svg\",\"flag_sb\":\"c95ec38.svg\",\"sb\":\"c95ec38.svg\",\"flag_so\":\"7152ad9.svg\",\"so\":\"7152ad9.svg\",\"flag_za\":\"1fdd78a.svg\",\"za\":\"1fdd78a.svg\",\"flag_kr\":\"8010072.svg\",\"kr\":\"8010072.svg\",\"flag_ss\":\"955766c.svg\",\"ss\":\"955766c.svg\",\"flag_es\":\"882b8a5.svg\",\"es\":\"882b8a5.svg\",\"flag_lk\":\"1ea9311.svg\",\"lk\":\"1ea9311.svg\",\"flag_bl\":\"65be4e2.svg\",\"bl\":\"65be4e2.svg\",\"flag_sh\":\"60f689f.svg\",\"sh\":\"60f689f.svg\",\"flag_kn\":\"ab7357a.svg\",\"kn\":\"ab7357a.svg\",\"flag_lc\":\"58f05bc.svg\",\"lc\":\"58f05bc.svg\",\"flag_pm\":\"793f2a1.svg\",\"pm\":\"793f2a1.svg\",\"flag_vc\":\"08c258a.svg\",\"vc\":\"08c258a.svg\",\"flag_sd\":\"c18be0c.svg\",\"sd\":\"c18be0c.svg\",\"flag_sr\":\"def026c.svg\",\"sr\":\"def026c.svg\",\"flag_sz\":\"90c9442.svg\",\"sz\":\"90c9442.svg\",\"flag_se\":\"db90821.svg\",\"se\":\"db90821.svg\",\"flag_ch\":\"583f42f.svg\",\"ch\":\"583f42f.svg\",\"flag_sy\":\"ee512bb.svg\",\"sy\":\"ee512bb.svg\",\"flag_tw\":\"7cb6090.svg\",\"tw\":\"7cb6090.svg\",\"flag_tj\":\"d422fb2.svg\",\"tj\":\"d422fb2.svg\",\"flag_tz\":\"fa1a399.svg\",\"tz\":\"fa1a399.svg\",\"flag_th\":\"a9413d5.svg\",\"th\":\"a9413d5.svg\",\"flag_tl\":\"393a39d.svg\",\"tl\":\"393a39d.svg\",\"flag_tg\":\"30d9a64.svg\",\"tg\":\"30d9a64.svg\",\"flag_tk\":\"6f952b9.svg\",\"tk\":\"6f952b9.svg\",\"flag_to\":\"9bd12aa.svg\",\"to\":\"9bd12aa.svg\",\"flag_tt\":\"23248eb.svg\",\"tt\":\"23248eb.svg\",\"flag_tn\":\"49a4f80.svg\",\"tn\":\"49a4f80.svg\",\"flag_tr\":\"38d8134.svg\",\"tr\":\"38d8134.svg\",\"flag_tm\":\"7855a69.svg\",\"turkmenistan\":\"7855a69.svg\",\"flag_tc\":\"f2246a1.svg\",\"tc\":\"f2246a1.svg\",\"flag_vi\":\"d3e3869.svg\",\"vi\":\"d3e3869.svg\",\"flag_tv\":\"e279f07.svg\",\"tuvalu\":\"e279f07.svg\",\"flag_ug\":\"b8a0b18.svg\",\"ug\":\"b8a0b18.svg\",\"flag_ua\":\"9a457bf.svg\",\"ua\":\"9a457bf.svg\",\"flag_ae\":\"3aaa070.svg\",\"ae\":\"3aaa070.svg\",\"flag_gb\":\"8769359.svg\",\"gb\":\"8769359.svg\",\"england\":\"9e4c2f7.svg\",\"scotland\":\"102beba.svg\",\"wales\":\"889e756.svg\",\"flag_us\":\"84b0e30.svg\",\"us\":\"84b0e30.svg\",\"flag_uy\":\"9245552.svg\",\"uy\":\"9245552.svg\",\"flag_uz\":\"ed83e3c.svg\",\"uz\":\"ed83e3c.svg\",\"flag_vu\":\"6bbb7d2.svg\",\"vu\":\"6bbb7d2.svg\",\"flag_va\":\"a1a2d63.svg\",\"va\":\"a1a2d63.svg\",\"flag_ve\":\"15397c2.svg\",\"ve\":\"15397c2.svg\",\"flag_vn\":\"59f29b4.svg\",\"vn\":\"59f29b4.svg\",\"flag_wf\":\"c070457.svg\",\"wf\":\"c070457.svg\",\"flag_eh\":\"ef917c3.svg\",\"eh\":\"ef917c3.svg\",\"flag_ye\":\"3dc1641.svg\",\"ye\":\"3dc1641.svg\",\"flag_zm\":\"d5aa7bf.svg\",\"zm\":\"d5aa7bf.svg\",\"flag_zw\":\"1339620.svg\",\"zw\":\"1339620.svg\",\"flag_ac\":\"8a4e07a.svg\",\"ac\":\"8a4e07a.svg\",\"flag_bv\":\"a57dbec.svg\",\"bv\":\"a57dbec.svg\",\"flag_cp\":\"5cff674.svg\",\"cp\":\"5cff674.svg\",\"flag_ea\":\"882b8a5.svg\",\"ea\":\"882b8a5.svg\",\"flag_dg\":\"80ba637.svg\",\"dg\":\"80ba637.svg\",\"flag_hm\":\"9d6fbca.svg\",\"hm\":\"9d6fbca.svg\",\"flag_mf\":\"5cff674.svg\",\"mf\":\"5cff674.svg\",\"flag_sj\":\"8ead297.svg\",\"sj\":\"8ead297.svg\",\"flag_ta\":\"48a59c7.svg\",\"ta\":\"48a59c7.svg\",\"flag_um\":\"84b0e30.svg\",\"um\":\"84b0e30.svg\",\"united_nations\":\"b78eaa7.svg\",\"tone1\":\"5c22a97.svg\",\"tone2\":\"1bde3f6.svg\",\"tone3\":\"30c76df.svg\",\"tone4\":\"e2c6475.svg\",\"tone5\":\"7a30939.svg\",\"regional_indicator_z\":\"ba4c07e.svg\",\"regional_indicator_y\":\"9ae7657.svg\",\"regional_indicator_x\":\"737ad95.svg\",\"regional_indicator_w\":\"fb4dbc8.svg\",\"regional_indicator_v\":\"edf1413.svg\",\"regional_indicator_u\":\"16f72a9.svg\",\"regional_indicator_t\":\"1fd0821.svg\",\"regional_indicator_s\":\"8cd4908.svg\",\"regional_indicator_r\":\"d3c6db1.svg\",\"regional_indicator_q\":\"531402c.svg\",\"regional_indicator_p\":\"973b3ec.svg\",\"regional_indicator_o\":\"a9fc48d.svg\",\"regional_indicator_n\":\"de42301.svg\",\"regional_indicator_m\":\"22dc734.svg\",\"regional_indicator_l\":\"f03a0fa.svg\",\"regional_indicator_k\":\"f873ac4.svg\",\"regional_indicator_j\":\"4241d63.svg\",\"regional_indicator_i\":\"2ac4206.svg\",\"regional_indicator_h\":\"42dc7d9.svg\",\"regional_indicator_g\":\"598a430.svg\",\"regional_indicator_f\":\"c68d66b.svg\",\"regional_indicator_e\":\"2ec6c44.svg\",\"regional_indicator_d\":\"a9d2a41.svg\",\"regional_indicator_c\":\"2d7b2d5.svg\",\"regional_indicator_b\":\"19bb970.svg\",\"regional_indicator_a\":\"c3eea8b.svg\",\"playground_slide\":\"841888e.svg\",\"slide\":\"841888e.svg\",\"wheel\":\"664c69f.svg\",\"lifebuoy\":\"6a7795b.svg\",\"ring_buoy\":\"6a7795b.svg\",\"heavy_equals_sign\":\"5dca87a.svg\",\"handshake_tone1\":\"9e20e72.svg\",\"handshake_tone2\":\"a69a3c0.svg\",\"handshake_tone3\":\"a239aeb.svg\",\"handshake_tone4\":\"6ba2d2b.svg\",\"handshake_tone5\":\"ab9ac37.svg\",\"face_holding_back_tears\":\"76d6bee.svg\",\"watery_eyes\":\"76d6bee.svg\",\"troll\":\"229b6bb.svg\",\"x-ray\":\"673885d.svg\",\"xray\":\"673885d.svg\",\"crutch\":\"0f9056b.svg\",\"disco\":\"17dbd0f.svg\",\"disco_ball\":\"17dbd0f.svg\",\"mirror_ball\":\"17dbd0f.svg\",\"id_card\":\"c8b9ad7.svg\",\"low_battery\":\"504a87f.svg\",\"hamsa\":\"eb16f78.svg\",\"lotus\":\"ec6c2a1.svg\",\"coral\":\"c3039c9.svg\",\"empty_nest\":\"9104910.svg\",\"nest\":\"9104910.svg\",\"nest_with_eggs\":\"026bda7.svg\",\"pregnant_man_tone1\":\"71a04cd.svg\",\"pregnant_man_tone2\":\"4ba6c48.svg\",\"pregnant_man_tone3\":\"7f3cc27.svg\",\"pregnant_man_tone4\":\"f38a33d.svg\",\"pregnant_man_tone5\":\"47131d4.svg\",\"pregnant_man\":\"d2ae49d.svg\",\"pregnant_person_tone1\":\"466de37.svg\",\"pregnant_person_tone2\":\"f032ead.svg\",\"pregnant_person_tone3\":\"6285b37.svg\",\"pregnant_person_tone4\":\"9135282.svg\",\"pregnant_person_tone5\":\"a32420e.svg\",\"pregnant_person\":\"92b367c.svg\",\"person_with_crown_tone1\":\"5d0e4d1.svg\",\"royalty_tone1\":\"5d0e4d1.svg\",\"person_with_crown_tone2\":\"9fd5bed.svg\",\"royalty_tone2\":\"9fd5bed.svg\",\"person_with_crown_tone3\":\"721e07b.svg\",\"royalty_tone3\":\"721e07b.svg\",\"person_with_crown_tone4\":\"6e75772.svg\",\"royalty_tone4\":\"6e75772.svg\",\"person_with_crown_tone5\":\"1adf78a.svg\",\"royalty_tone5\":\"1adf78a.svg\",\"person_with_crown\":\"3051fdf.svg\",\"royalty\":\"3051fdf.svg\",\"pour\":\"6775ee5.svg\",\"pouring_liquid\":\"6775ee5.svg\",\"beans\":\"b65fc0b.svg\",\"jar\":\"7596a1f.svg\",\"melt\":\"975980b.svg\",\"melting_face\":\"975980b.svg\",\"salute\":\"66c008c.svg\",\"saluting_face\":\"66c008c.svg\",\"face_with_open_eyes_hand_over_mouth\":\"856fd0f.svg\",\"gasp\":\"856fd0f.svg\",\"face_with_peeking_eye\":\"e85969d.svg\",\"peek\":\"e85969d.svg\",\"face_with_diagonal_mouth\":\"792e329.svg\",\"dotted_line_face\":\"b258132.svg\",\"biting_lip\":\"94a08c5.svg\",\"bubbles\":\"8a18bb0.svg\",\"hand_with_index_finger_and_thumb_crossed_tone1\":\"75a69ec.svg\",\"hand_with_index_finger_and_thumb_crossed_tone2\":\"032bb22.svg\",\"hand_with_index_finger_and_thumb_crossed_tone3\":\"d8b0fbc.svg\",\"hand_with_index_finger_and_thumb_crossed_tone4\":\"496e94b.svg\",\"hand_with_index_finger_and_thumb_crossed_tone5\":\"2c239e7.svg\",\"hand_with_index_finger_and_thumb_crossed\":\"626684e.svg\",\"handshake_tone1-2\":\"7f92346.svg\",\"handshake_tone1-3\":\"e752822.svg\",\"handshake_tone1-4\":\"20443c0.svg\",\"handshake_tone1-5\":\"1e9a54e.svg\",\"rightwards_hand_tone1\":\"0caa220.svg\",\"handshake_tone2-1\":\"9354a6d.svg\",\"handshake_tone2-3\":\"a6001aa.svg\",\"handshake_tone2-4\":\"a773a03.svg\",\"handshake_tone2-5\":\"58b2d9b.svg\",\"rightwards_hand_tone2\":\"beb9d59.svg\",\"handshake_tone3-1\":\"b443bdb.svg\",\"handshake_tone3-2\":\"f47f680.svg\",\"handshake_tone3-4\":\"d74e57c.svg\",\"handshake_tone3-5\":\"0ecb087.svg\",\"rightwards_hand_tone3\":\"b250137.svg\",\"handshake_tone4-1\":\"59a488b.svg\",\"handshake_tone4-2\":\"4578949.svg\",\"handshake_tone4-3\":\"80eedae.svg\",\"handshake_tone4-5\":\"0ddd6a4.svg\",\"rightwards_hand_tone4\":\"7f2c38a.svg\",\"handshake_tone5-1\":\"e2d81fa.svg\",\"handshake_tone5-2\":\"a530c09.svg\",\"handshake_tone5-3\":\"a708e77.svg\",\"handshake_tone5-4\":\"249aa4c.svg\",\"rightwards_hand_tone5\":\"631268a.svg\",\"rightwards_hand\":\"f9e9234.svg\",\"leftwards_hand_tone1\":\"c7c9afd.svg\",\"leftwards_hand_tone2\":\"d3c5d47.svg\",\"leftwards_hand_tone3\":\"5dddf2b.svg\",\"leftwards_hand_tone4\":\"28145be.svg\",\"leftwards_hand_tone5\":\"e0f982a.svg\",\"leftwards_hand\":\"4bb73fc.svg\",\"palm_down_tone1\":\"ec03c5f.svg\",\"palm_down_tone2\":\"b353622.svg\",\"palm_down_tone3\":\"1d8fa8d.svg\",\"palm_down_tone4\":\"72583a0.svg\",\"palm_down_tone5\":\"c2413bd.svg\",\"palm_down\":\"e0f0077.svg\",\"palm_up_tone1\":\"50dc0a8.svg\",\"palm_up_tone2\":\"8b3df47.svg\",\"palm_up_tone3\":\"9764c3b.svg\",\"palm_up_tone4\":\"b78929e.svg\",\"palm_up_tone5\":\"3f4ff70.svg\",\"palm_up\":\"f5b1a42.svg\",\"point_forward_tone1\":\"cbea9e4.svg\",\"point_forward_tone2\":\"064092d.svg\",\"point_forward_tone3\":\"4c482c7.svg\",\"point_forward_tone4\":\"176117f.svg\",\"point_forward_tone5\":\"a08eda9.svg\",\"point_forward\":\"ba6907e.svg\",\"heart_hands_tone1\":\"59c6549.svg\",\"heart_hands_tone2\":\"3b1e862.svg\",\"heart_hands_tone3\":\"d167cc3.svg\",\"heart_hands_tone4\":\"def0c92.svg\",\"heart_hands_tone5\":\"41f154d.svg\",\"heart_hands\":\"f5a07ed.svg\"}"); \ No newline at end of file +export default JSON.parse("{\"100\":\"6d75617.svg\",\"1234\":\"cda85e0.svg\",\"interrobang\":\"d0e72da.svg\",\"tm\":\"e21e68e.svg\",\"trade_mark\":\"e21e68e.svg\",\"information_source\":\"844715a.svg\",\"information\":\"844715a.svg\",\"left_right_arrow\":\"db7e085.svg\",\"arrow_up_down\":\"e072740.svg\",\"up_down_arrow\":\"e072740.svg\",\"arrow_upper_left\":\"8c36166.svg\",\"up_left_arrow\":\"8c36166.svg\",\"arrow_upper_right\":\"5896668.svg\",\"arrow_lower_right\":\"e62c0d5.svg\",\"arrow_lower_left\":\"b373a65.svg\",\"keyboard\":\"afe45d4.svg\",\"sunny\":\"2224ffe.svg\",\"sun\":\"2224ffe.svg\",\"cloud\":\"996d816.svg\",\"umbrella2\":\"0986801.svg\",\"snowman2\":\"4e0e6b2.svg\",\"comet\":\"5742565.svg\",\"ballot_box_with_check\":\"1537a20.svg\",\"umbrella\":\"109200a.svg\",\"coffee\":\"3282153.svg\",\"hot_beverage\":\"3282153.svg\",\"shamrock\":\"68199fe.svg\",\"skull_crossbones\":\"2002503.svg\",\"skull_and_crossbones\":\"2002503.svg\",\"radioactive\":\"830d87b.svg\",\"radioactive_sign\":\"830d87b.svg\",\"biohazard\":\"1c0e751.svg\",\"biohazard_sign\":\"1c0e751.svg\",\"orthodox_cross\":\"4085b9b.svg\",\"wheel_of_dharma\":\"5ce347e.svg\",\"frowning2\":\"6a2c624.svg\",\"white_frowning_face\":\"6a2c624.svg\",\"frowning_face\":\"6a2c624.svg\",\"female_sign\":\"9a70128.svg\",\"male_sign\":\"efa6bcd.svg\",\"aries\":\"a5af609.svg\",\"taurus\":\"0dd7b96.svg\",\"sagittarius\":\"769343c.svg\",\"capricorn\":\"1a14a8a.svg\",\"aquarius\":\"cc39b15.svg\",\"pisces\":\"ed438b4.svg\",\"spades\":\"3caf82e.svg\",\"spade_suit\":\"3caf82e.svg\",\"clubs\":\"980bdb6.svg\",\"club_suit\":\"980bdb6.svg\",\"hearts\":\"d3224df.svg\",\"heart_suit\":\"d3224df.svg\",\"diamonds\":\"04a5083.svg\",\"diamond_suit\":\"04a5083.svg\",\"hotsprings\":\"12def1e.svg\",\"hot_springs\":\"12def1e.svg\",\"hammer_pick\":\"0be192d.svg\",\"hammer_and_pick\":\"0be192d.svg\",\"anchor\":\"e008be8.svg\",\"crossed_swords\":\"05e4179.svg\",\"medical_symbol\":\"0db03b9.svg\",\"scales\":\"8a658bd.svg\",\"balance_scale\":\"8a658bd.svg\",\"alembic\":\"3979a70.svg\",\"gear\":\"be79bc3.svg\",\"scissors\":\"0095630.svg\",\"white_check_mark\":\"4d69c4a.svg\",\"airplane\":\"3c41f3a.svg\",\"envelope\":\"d45d0ae.svg\",\"black_nib\":\"e4a80ff.svg\",\"heavy_check_mark\":\"220f771.svg\",\"check_mark\":\"220f771.svg\",\"heavy_multiplication_x\":\"4cadfe2.svg\",\"star_of_david\":\"97817c8.svg\",\"sparkles\":\"43a4b5e.svg\",\"eight_spoked_asterisk\":\"3b40c2e.svg\",\"eight_pointed_black_star\":\"6298c15.svg\",\"snowflake\":\"0e29553.svg\",\"sparkle\":\"db70159.svg\",\"question\":\"0ace896.svg\",\"question_mark\":\"0ace896.svg\",\"grey_question\":\"d89e98b.svg\",\"grey_exclamation\":\"54414a4.svg\",\"exclamation\":\"97d574d.svg\",\"heart_exclamation\":\"b975686.svg\",\"heavy_heart_exclamation_mark_ornament\":\"b975686.svg\",\"heart\":\"61bd815.svg\",\"red_heart\":\"61bd815.svg\",\"heavy_plus_sign\":\"5bfd726.svg\",\"heavy_minus_sign\":\"e393852.svg\",\"heavy_division_sign\":\"ab7f7db.svg\",\"arrow_heading_up\":\"5ab8978.svg\",\"arrow_heading_down\":\"a2aac01.svg\",\"wavy_dash\":\"6869dc1.svg\",\"congratulations\":\"6db8b53.svg\",\"secret\":\"4811a27.svg\",\"grinning\":\"855a20b.svg\",\"grinning_face\":\"855a20b.svg\",\"smiley\":\"ea6c27e.svg\",\"smile\":\"cc1476e.svg\",\"grin\":\"3f27807.svg\",\"laughing\":\"a1a5b20.svg\",\"satisfied\":\"a1a5b20.svg\",\"face_holding_back_tears\":\"76d6bee.svg\",\"sweat_smile\":\"564ce08.svg\",\"joy\":\"dc4914b.svg\",\"rofl\":\"6d92e2a.svg\",\"rolling_on_the_floor_laughing\":\"6d92e2a.svg\",\"smiling_face_with_tear\":\"b4b21e4.svg\",\"relaxed\":\"941ac42.svg\",\"smiling_face\":\"941ac42.svg\",\"blush\":\"edc2a3e.svg\",\"innocent\":\"6048909.svg\",\"slight_smile\":\"682e14e.svg\",\"slightly_smiling_face\":\"682e14e.svg\",\"upside_down\":\"c3985ca.svg\",\"upside_down_face\":\"c3985ca.svg\",\"wink\":\"28d185d.svg\",\"winking_face\":\"28d185d.svg\",\"relieved\":\"73bd852.svg\",\"relieved_face\":\"73bd852.svg\",\"heart_eyes\":\"bff73dd.svg\",\"smiling_face_with_3_hearts\":\"3a6e61e.svg\",\"kissing_heart\":\"babb293.svg\",\"kissing\":\"9162523.svg\",\"kissing_face\":\"9162523.svg\",\"kissing_smiling_eyes\":\"3ef839c.svg\",\"kissing_closed_eyes\":\"2ffc67a.svg\",\"yum\":\"75e9463.svg\",\"stuck_out_tongue\":\"956e398.svg\",\"stuck_out_tongue_closed_eyes\":\"edf2f35.svg\",\"stuck_out_tongue_winking_eye\":\"94505b2.svg\",\"zany_face\":\"c9ca468.svg\",\"face_with_raised_eyebrow\":\"f112b4d.svg\",\"face_with_monocle\":\"770ec60.svg\",\"nerd\":\"c9a30e0.svg\",\"nerd_face\":\"c9a30e0.svg\",\"sunglasses\":\"c0c45e0.svg\",\"disguised_face\":\"6b530e0.svg\",\"star_struck\":\"986b540.svg\",\"partying_face\":\"6dd9ab2.svg\",\"smirk\":\"4783d27.svg\",\"smirking_face\":\"4783d27.svg\",\"unamused\":\"8442c49.svg\",\"unamused_face\":\"8442c49.svg\",\"disappointed\":\"2b2beac.svg\",\"pensive\":\"26afe78.svg\",\"pensive_face\":\"26afe78.svg\",\"worried\":\"925c26f.svg\",\"worried_face\":\"925c26f.svg\",\"confused\":\"b3292f4.svg\",\"confused_face\":\"b3292f4.svg\",\"slight_frown\":\"119074c.svg\",\"slightly_frowning_face\":\"119074c.svg\",\"persevere\":\"f60bd32.svg\",\"confounded\":\"99c5b27.svg\",\"tired_face\":\"89fdb97.svg\",\"weary\":\"d9050ec.svg\",\"weary_face\":\"d9050ec.svg\",\"pleading_face\":\"443519c.svg\",\"cry\":\"28785e2.svg\",\"crying_face\":\"28785e2.svg\",\"sob\":\"6e31c7c.svg\",\"triumph\":\"e08b216.svg\",\"angry\":\"ce4c95d.svg\",\"angry_face\":\"ce4c95d.svg\",\"rage\":\"a5ccb2c.svg\",\"pouting_face\":\"a5ccb2c.svg\",\"face_with_symbols_over_mouth\":\"521b2cc.svg\",\"exploding_head\":\"5d20bd8.svg\",\"flushed\":\"386d679.svg\",\"flushed_face\":\"386d679.svg\",\"hot_face\":\"b32e5c3.svg\",\"cold_face\":\"a6307ad.svg\",\"face_in_clouds\":\"e1592e1.svg\",\"scream\":\"2f595d0.svg\",\"fearful\":\"0901baa.svg\",\"fearful_face\":\"0901baa.svg\",\"cold_sweat\":\"999a34b.svg\",\"disappointed_relieved\":\"7fe32af.svg\",\"sweat\":\"91fea65.svg\",\"hugging\":\"72e6b61.svg\",\"hugging_face\":\"72e6b61.svg\",\"thinking\":\"6add816.svg\",\"thinking_face\":\"6add816.svg\",\"face_with_peeking_eye\":\"e85969d.svg\",\"face_with_hand_over_mouth\":\"6a9c73f.svg\",\"face_with_open_eyes_and_hand_over_mouth\":\"856fd0f.svg\",\"saluting_face\":\"66c008c.svg\",\"shushing_face\":\"7f17dd2.svg\",\"melting_face\":\"975980b.svg\",\"lying_face\":\"dda5eef.svg\",\"liar\":\"dda5eef.svg\",\"no_mouth\":\"8a99b07.svg\",\"dotted_line_face\":\"b258132.svg\",\"neutral_face\":\"a6195d9.svg\",\"face_with_diagonal_mouth\":\"792e329.svg\",\"expressionless\":\"461cdef.svg\",\"grimacing\":\"1e20d08.svg\",\"rolling_eyes\":\"db553c8.svg\",\"face_with_rolling_eyes\":\"db553c8.svg\",\"hushed\":\"0af023c.svg\",\"hushed_face\":\"0af023c.svg\",\"frowning\":\"7fe2396.svg\",\"anguished\":\"b236aa7.svg\",\"open_mouth\":\"0ed7e03.svg\",\"astonished\":\"fc1ede6.svg\",\"yawning_face\":\"86204a8.svg\",\"sleeping\":\"6955348.svg\",\"sleeping_face\":\"6955348.svg\",\"drooling_face\":\"0c952c8.svg\",\"drool\":\"0c952c8.svg\",\"sleepy\":\"c244ab4.svg\",\"sleepy_face\":\"c244ab4.svg\",\"face_exhaling\":\"08b2da6.svg\",\"dizzy_face\":\"a9a67d9.svg\",\"face_with_spiral_eyes\":\"8a63df4.svg\",\"zipper_mouth\":\"47e6ec5.svg\",\"zipper_mouth_face\":\"47e6ec5.svg\",\"woozy_face\":\"1eb097a.svg\",\"nauseated_face\":\"93cd3a4.svg\",\"sick\":\"93cd3a4.svg\",\"face_vomiting\":\"7c7a02b.svg\",\"sneezing_face\":\"cd839a5.svg\",\"sneeze\":\"cd839a5.svg\",\"mask\":\"422f5af.svg\",\"thermometer_face\":\"1d11ea3.svg\",\"face_with_thermometer\":\"1d11ea3.svg\",\"head_bandage\":\"dfce78c.svg\",\"face_with_head_bandage\":\"dfce78c.svg\",\"money_mouth\":\"eabac9a.svg\",\"money_mouth_face\":\"eabac9a.svg\",\"cowboy\":\"d59f4db.svg\",\"face_with_cowboy_hat\":\"d59f4db.svg\",\"smiling_imp\":\"62a11b2.svg\",\"imp\":\"5eb5bd8.svg\",\"japanese_ogre\":\"4a69ea6.svg\",\"ogre\":\"4a69ea6.svg\",\"japanese_goblin\":\"7aaf1ce.svg\",\"goblin\":\"7aaf1ce.svg\",\"clown\":\"0712ba3.svg\",\"clown_face\":\"0712ba3.svg\",\"poop\":\"06b9ffa.svg\",\"shit\":\"06b9ffa.svg\",\"hankey\":\"06b9ffa.svg\",\"poo\":\"06b9ffa.svg\",\"pile_of_poo\":\"06b9ffa.svg\",\"ghost\":\"c2eea99.svg\",\"skull\":\"2283d79.svg\",\"skeleton\":\"2283d79.svg\",\"alien\":\"90ca85f.svg\",\"space_invader\":\"8c48ddf.svg\",\"alien_monster\":\"8c48ddf.svg\",\"robot\":\"6d8c6cf.svg\",\"robot_face\":\"6d8c6cf.svg\",\"jack_o_lantern\":\"9b16264.svg\",\"smiley_cat\":\"cc354ab.svg\",\"grinning_cat\":\"cc354ab.svg\",\"smile_cat\":\"efa9820.svg\",\"joy_cat\":\"8c5c4d9.svg\",\"heart_eyes_cat\":\"b5a077b.svg\",\"smirk_cat\":\"e89c5cd.svg\",\"kissing_cat\":\"6604a6b.svg\",\"scream_cat\":\"8c3016b.svg\",\"weary_cat\":\"8c3016b.svg\",\"crying_cat_face\":\"0996639.svg\",\"crying_cat\":\"0996639.svg\",\"pouting_cat\":\"7844a05.svg\",\"heart_hands\":\"f5a07ed.svg\",\"heart_hands_tone1\":\"59c6549.svg\",\"heart_hands_light_skin_tone\":\"59c6549.svg\",\"heart_hands_tone2\":\"3b1e862.svg\",\"heart_hands_medium_light_skin_tone\":\"3b1e862.svg\",\"heart_hands_tone3\":\"d167cc3.svg\",\"heart_hands_medium_skin_tone\":\"d167cc3.svg\",\"heart_hands_tone4\":\"def0c92.svg\",\"heart_hands_medium_dark_skin_tone\":\"def0c92.svg\",\"heart_hands_tone5\":\"41f154d.svg\",\"heart_hands_dark_skin_tone\":\"41f154d.svg\",\"palms_up_together\":\"d1d5410.svg\",\"palms_up_together_tone1\":\"f6537bd.svg\",\"palms_up_together_light_skin_tone\":\"f6537bd.svg\",\"palms_up_together_tone2\":\"f44274d.svg\",\"palms_up_together_medium_light_skin_tone\":\"f44274d.svg\",\"palms_up_together_tone3\":\"dbb55bf.svg\",\"palms_up_together_medium_skin_tone\":\"dbb55bf.svg\",\"palms_up_together_tone4\":\"9038675.svg\",\"palms_up_together_medium_dark_skin_tone\":\"9038675.svg\",\"palms_up_together_tone5\":\"adec7d8.svg\",\"palms_up_together_dark_skin_tone\":\"adec7d8.svg\",\"open_hands\":\"118466e.svg\",\"open_hands_tone1\":\"a32e437.svg\",\"open_hands_tone2\":\"7d4ae39.svg\",\"open_hands_tone3\":\"83781f4.svg\",\"open_hands_tone4\":\"e6731c9.svg\",\"open_hands_tone5\":\"f338a35.svg\",\"raised_hands\":\"6e2bcf7.svg\",\"raising_hands\":\"6e2bcf7.svg\",\"raised_hands_tone1\":\"af13a2f.svg\",\"raised_hands_tone2\":\"2428031.svg\",\"raised_hands_tone3\":\"89f2527.svg\",\"raised_hands_tone4\":\"3fdbc3b.svg\",\"raised_hands_tone5\":\"760a669.svg\",\"clap\":\"54853c6.svg\",\"clap_tone1\":\"99e769e.svg\",\"clap_tone2\":\"f1d64a7.svg\",\"clap_tone3\":\"c3cf438.svg\",\"clap_tone4\":\"a0ab9a4.svg\",\"clap_tone5\":\"5716e91.svg\",\"handshake\":\"a04d286.svg\",\"shaking_hands\":\"a04d286.svg\",\"handshake_tone1\":\"9e20e72.svg\",\"handshake_light_skin_tone\":\"9e20e72.svg\",\"handshake_tone1_tone2\":\"7f92346.svg\",\"handshake_light_skin_tone_medium_light_skin_tone\":\"7f92346.svg\",\"handshake_tone1_tone3\":\"e752822.svg\",\"handshake_light_skin_tone_medium_skin_tone\":\"e752822.svg\",\"handshake_tone1_tone4\":\"20443c0.svg\",\"handshake_light_skin_tone_medium_dark_skin_tone\":\"20443c0.svg\",\"handshake_tone1_tone5\":\"1e9a54e.svg\",\"handshake_light_skin_tone_dark_skin_tone\":\"1e9a54e.svg\",\"handshake_tone2_tone1\":\"9354a6d.svg\",\"handshake_medium_light_skin_tone_light_skin_tone\":\"9354a6d.svg\",\"handshake_tone2\":\"a69a3c0.svg\",\"handshake_medium_light_skin_tone\":\"a69a3c0.svg\",\"handshake_tone2_tone3\":\"a6001aa.svg\",\"handshake_medium_light_skin_tone_medium_skin_tone\":\"a6001aa.svg\",\"handshake_tone2_tone4\":\"a773a03.svg\",\"handshake_medium_light_skin_tone_medium_dark_skin_tone\":\"a773a03.svg\",\"handshake_tone2_tone5\":\"58b2d9b.svg\",\"handshake_medium_light_skin_tone_dark_skin_tone\":\"58b2d9b.svg\",\"handshake_tone3_tone1\":\"b443bdb.svg\",\"handshake_medium_skin_tone_light_skin_tone\":\"b443bdb.svg\",\"handshake_tone3_tone2\":\"f47f680.svg\",\"handshake_medium_skin_tone_medium_light_skin_tone\":\"f47f680.svg\",\"handshake_tone3\":\"a239aeb.svg\",\"handshake_medium_skin_tone\":\"a239aeb.svg\",\"handshake_tone3_tone4\":\"d74e57c.svg\",\"handshake_medium_skin_tone_medium_dark_skin_tone\":\"d74e57c.svg\",\"handshake_tone3_tone5\":\"0ecb087.svg\",\"handshake_medium_skin_tone_dark_skin_tone\":\"0ecb087.svg\",\"handshake_tone4_tone1\":\"59a488b.svg\",\"handshake_medium_dark_skin_tone_light_skin_tone\":\"59a488b.svg\",\"handshake_tone4_tone2\":\"4578949.svg\",\"handshake_medium_dark_skin_tone_medium_light_skin_tone\":\"4578949.svg\",\"handshake_tone4_tone3\":\"80eedae.svg\",\"handshake_medium_dark_skin_tone_medium_skin_tone\":\"80eedae.svg\",\"handshake_tone4\":\"6ba2d2b.svg\",\"handshake_medium_dark_skin_tone\":\"6ba2d2b.svg\",\"handshake_tone4_tone5\":\"0ddd6a4.svg\",\"handshake_medium_dark_skin_tone_dark_skin_tone\":\"0ddd6a4.svg\",\"handshake_tone5_tone1\":\"e2d81fa.svg\",\"handshake_dark_skin_tone_light_skin_tone\":\"e2d81fa.svg\",\"handshake_tone5_tone2\":\"a530c09.svg\",\"handshake_dark_skin_tone_medium_light_skin_tone\":\"a530c09.svg\",\"handshake_tone5_tone3\":\"a708e77.svg\",\"handshake_dark_skin_tone_medium_skin_tone\":\"a708e77.svg\",\"handshake_tone5_tone4\":\"249aa4c.svg\",\"handshake_dark_skin_tone_medium_dark_skin_tone\":\"249aa4c.svg\",\"handshake_tone5\":\"ab9ac37.svg\",\"handshake_dark_skin_tone\":\"ab9ac37.svg\",\"thumbsup\":\"f8fee8e.svg\",\"+1\":\"f8fee8e.svg\",\"thumbup\":\"f8fee8e.svg\",\"thumbs_up\":\"f8fee8e.svg\",\"thumbsup_tone1\":\"220c50f.svg\",\"+1_tone1\":\"220c50f.svg\",\"thumbup_tone1\":\"220c50f.svg\",\"thumbsup_tone2\":\"040be8e.svg\",\"+1_tone2\":\"040be8e.svg\",\"thumbup_tone2\":\"040be8e.svg\",\"thumbsup_tone3\":\"26c7aa0.svg\",\"+1_tone3\":\"26c7aa0.svg\",\"thumbup_tone3\":\"26c7aa0.svg\",\"thumbsup_tone4\":\"5c2a9a1.svg\",\"+1_tone4\":\"5c2a9a1.svg\",\"thumbup_tone4\":\"5c2a9a1.svg\",\"thumbsup_tone5\":\"cc823ef.svg\",\"+1_tone5\":\"cc823ef.svg\",\"thumbup_tone5\":\"cc823ef.svg\",\"thumbsdown\":\"0e682e9.svg\",\"-1\":\"0e682e9.svg\",\"thumbdown\":\"0e682e9.svg\",\"thumbs_down\":\"0e682e9.svg\",\"thumbsdown_tone1\":\"f89f247.svg\",\"-1_tone1\":\"f89f247.svg\",\"thumbdown_tone1\":\"f89f247.svg\",\"thumbsdown_tone2\":\"de63981.svg\",\"-1_tone2\":\"de63981.svg\",\"thumbdown_tone2\":\"de63981.svg\",\"thumbsdown_tone3\":\"b3cc536.svg\",\"-1_tone3\":\"b3cc536.svg\",\"thumbdown_tone3\":\"b3cc536.svg\",\"thumbsdown_tone4\":\"93e70b8.svg\",\"-1_tone4\":\"93e70b8.svg\",\"thumbdown_tone4\":\"93e70b8.svg\",\"thumbsdown_tone5\":\"d3bce71.svg\",\"-1_tone5\":\"d3bce71.svg\",\"thumbdown_tone5\":\"d3bce71.svg\",\"punch\":\"93d9d16.svg\",\"oncoming_fist\":\"93d9d16.svg\",\"punch_tone1\":\"1b2deff.svg\",\"punch_tone2\":\"fbf114a.svg\",\"punch_tone3\":\"506ed1c.svg\",\"punch_tone4\":\"3a1b73e.svg\",\"punch_tone5\":\"0c2ec0b.svg\",\"fist\":\"410baea.svg\",\"raised_fist\":\"410baea.svg\",\"fist_tone1\":\"80f2d54.svg\",\"fist_tone2\":\"391dca8.svg\",\"fist_tone3\":\"0429915.svg\",\"fist_tone4\":\"e0ae4cf.svg\",\"fist_tone5\":\"dc2dac6.svg\",\"left_facing_fist\":\"ee167ee.svg\",\"left_fist\":\"ee167ee.svg\",\"left_facing_fist_tone1\":\"bca4b94.svg\",\"left_fist_tone1\":\"bca4b94.svg\",\"left_facing_fist_tone2\":\"c32bae1.svg\",\"left_fist_tone2\":\"c32bae1.svg\",\"left_facing_fist_tone3\":\"bff4577.svg\",\"left_fist_tone3\":\"bff4577.svg\",\"left_facing_fist_tone4\":\"cb22fea.svg\",\"left_fist_tone4\":\"cb22fea.svg\",\"left_facing_fist_tone5\":\"0605cfc.svg\",\"left_fist_tone5\":\"0605cfc.svg\",\"right_facing_fist\":\"8a25069.svg\",\"right_fist\":\"8a25069.svg\",\"right_facing_fist_tone1\":\"50ddaf8.svg\",\"right_fist_tone1\":\"50ddaf8.svg\",\"right_facing_fist_tone2\":\"429925f.svg\",\"right_fist_tone2\":\"429925f.svg\",\"right_facing_fist_tone3\":\"bbf8af5.svg\",\"right_fist_tone3\":\"bbf8af5.svg\",\"right_facing_fist_tone4\":\"f66d395.svg\",\"right_fist_tone4\":\"f66d395.svg\",\"right_facing_fist_tone5\":\"996f47c.svg\",\"right_fist_tone5\":\"996f47c.svg\",\"fingers_crossed\":\"dc3511e.svg\",\"hand_with_index_and_middle_finger_crossed\":\"dc3511e.svg\",\"fingers_crossed_tone1\":\"c6255b4.svg\",\"hand_with_index_and_middle_fingers_crossed_tone1\":\"c6255b4.svg\",\"fingers_crossed_tone2\":\"38d3101.svg\",\"hand_with_index_and_middle_fingers_crossed_tone2\":\"38d3101.svg\",\"fingers_crossed_tone3\":\"12724d3.svg\",\"hand_with_index_and_middle_fingers_crossed_tone3\":\"12724d3.svg\",\"fingers_crossed_tone4\":\"ed4dd94.svg\",\"hand_with_index_and_middle_fingers_crossed_tone4\":\"ed4dd94.svg\",\"fingers_crossed_tone5\":\"d0fb18e.svg\",\"hand_with_index_and_middle_fingers_crossed_tone5\":\"d0fb18e.svg\",\"v\":\"febf6ba.svg\",\"victory_hand\":\"febf6ba.svg\",\"v_tone1\":\"dbe5d18.svg\",\"v_tone2\":\"af07f0f.svg\",\"v_tone3\":\"580ecd3.svg\",\"v_tone4\":\"e152620.svg\",\"v_tone5\":\"235bbf1.svg\",\"hand_with_index_finger_and_thumb_crossed\":\"626684e.svg\",\"hand_with_index_finger_and_thumb_crossed_tone1\":\"75a69ec.svg\",\"hand_with_index_finger_and_thumb_crossed_light_skin_tone\":\"75a69ec.svg\",\"hand_with_index_finger_and_thumb_crossed_tone2\":\"032bb22.svg\",\"hand_with_index_finger_and_thumb_crossed_medium_light_skin_tone\":\"032bb22.svg\",\"hand_with_index_finger_and_thumb_crossed_tone3\":\"d8b0fbc.svg\",\"hand_with_index_finger_and_thumb_crossed_medium_skin_tone\":\"d8b0fbc.svg\",\"hand_with_index_finger_and_thumb_crossed_tone4\":\"496e94b.svg\",\"hand_with_index_finger_and_thumb_crossed_medium_dark_skin_tone\":\"496e94b.svg\",\"hand_with_index_finger_and_thumb_crossed_tone5\":\"2c239e7.svg\",\"hand_with_index_finger_and_thumb_crossed_dark_skin_tone\":\"2c239e7.svg\",\"love_you_gesture\":\"cc54e70.svg\",\"love_you_gesture_tone1\":\"17cd4fa.svg\",\"love_you_gesture_light_skin_tone\":\"17cd4fa.svg\",\"love_you_gesture_tone2\":\"6291d8a.svg\",\"love_you_gesture_medium_light_skin_tone\":\"6291d8a.svg\",\"love_you_gesture_tone3\":\"db2b81a.svg\",\"love_you_gesture_medium_skin_tone\":\"db2b81a.svg\",\"love_you_gesture_tone4\":\"8cb6fdd.svg\",\"love_you_gesture_medium_dark_skin_tone\":\"8cb6fdd.svg\",\"love_you_gesture_tone5\":\"ef34a19.svg\",\"love_you_gesture_dark_skin_tone\":\"ef34a19.svg\",\"metal\":\"873d964.svg\",\"sign_of_the_horns\":\"873d964.svg\",\"metal_tone1\":\"52888a2.svg\",\"sign_of_the_horns_tone1\":\"52888a2.svg\",\"metal_tone2\":\"f264e36.svg\",\"sign_of_the_horns_tone2\":\"f264e36.svg\",\"metal_tone3\":\"7e09314.svg\",\"sign_of_the_horns_tone3\":\"7e09314.svg\",\"metal_tone4\":\"4cab71a.svg\",\"sign_of_the_horns_tone4\":\"4cab71a.svg\",\"metal_tone5\":\"63e55cf.svg\",\"sign_of_the_horns_tone5\":\"63e55cf.svg\",\"ok_hand\":\"08c8a43.svg\",\"ok_hand_tone1\":\"f069401.svg\",\"ok_hand_tone2\":\"66ce630.svg\",\"ok_hand_tone3\":\"c68f7ee.svg\",\"ok_hand_tone4\":\"f9f46a9.svg\",\"ok_hand_tone5\":\"304452a.svg\",\"pinched_fingers\":\"51a509d.svg\",\"pinched_fingers_tone2\":\"953a175.svg\",\"pinched_fingers_medium_light_skin_tone\":\"953a175.svg\",\"pinched_fingers_tone1\":\"2b990de.svg\",\"pinched_fingers_light_skin_tone\":\"2b990de.svg\",\"pinched_fingers_tone3\":\"6e6e2c7.svg\",\"pinched_fingers_medium_skin_tone\":\"6e6e2c7.svg\",\"pinched_fingers_tone4\":\"94b01dd.svg\",\"pinched_fingers_medium_dark_skin_tone\":\"94b01dd.svg\",\"pinched_fingers_tone5\":\"ec2e0ce.svg\",\"pinched_fingers_dark_skin_tone\":\"ec2e0ce.svg\",\"pinching_hand\":\"5c8da33.svg\",\"pinching_hand_tone1\":\"c40530a.svg\",\"pinching_hand_light_skin_tone\":\"c40530a.svg\",\"pinching_hand_tone2\":\"f44b317.svg\",\"pinching_hand_medium_light_skin_tone\":\"f44b317.svg\",\"pinching_hand_tone3\":\"296d23d.svg\",\"pinching_hand_medium_skin_tone\":\"296d23d.svg\",\"pinching_hand_tone4\":\"e600777.svg\",\"pinching_hand_medium_dark_skin_tone\":\"e600777.svg\",\"pinching_hand_tone5\":\"6109389.svg\",\"pinching_hand_dark_skin_tone\":\"6109389.svg\",\"palm_down_hand\":\"e0f0077.svg\",\"palm_down_hand_tone1\":\"ec03c5f.svg\",\"palm_down_hand_light_skin_tone\":\"ec03c5f.svg\",\"palm_down_hand_tone2\":\"b353622.svg\",\"palm_down_hand_medium_light_skin_tone\":\"b353622.svg\",\"palm_down_hand_tone3\":\"1d8fa8d.svg\",\"palm_down_hand_medium_skin_tone\":\"1d8fa8d.svg\",\"palm_down_hand_tone4\":\"72583a0.svg\",\"palm_down_hand_medium_dark_skin_tone\":\"72583a0.svg\",\"palm_down_hand_tone5\":\"c2413bd.svg\",\"palm_down_hand_dark_skin_tone\":\"c2413bd.svg\",\"palm_up_hand\":\"f5b1a42.svg\",\"palm_up_hand_tone1\":\"50dc0a8.svg\",\"palm_up_hand_light_skin_tone\":\"50dc0a8.svg\",\"palm_up_hand_tone2\":\"8b3df47.svg\",\"palm_up_hand_medium_light_skin_tone\":\"8b3df47.svg\",\"palm_up_hand_tone3\":\"9764c3b.svg\",\"palm_up_hand_medium_skin_tone\":\"9764c3b.svg\",\"palm_up_hand_tone4\":\"b78929e.svg\",\"palm_up_hand_medium_dark_skin_tone\":\"b78929e.svg\",\"palm_up_hand_tone5\":\"3f4ff70.svg\",\"palm_up_hand_dark_skin_tone\":\"3f4ff70.svg\",\"point_left\":\"edcc59f.svg\",\"point_left_tone1\":\"3230da3.svg\",\"point_left_tone2\":\"609bc7b.svg\",\"point_left_tone3\":\"f33129f.svg\",\"point_left_tone4\":\"868774c.svg\",\"point_left_tone5\":\"411935b.svg\",\"point_right\":\"e6620a7.svg\",\"point_right_tone1\":\"26f4e15.svg\",\"point_right_tone2\":\"e1f9849.svg\",\"point_right_tone3\":\"192043c.svg\",\"point_right_tone4\":\"a7e605e.svg\",\"point_right_tone5\":\"8644a09.svg\",\"point_up_2\":\"cffa2d8.svg\",\"point_up_2_tone1\":\"c501490.svg\",\"point_up_2_tone2\":\"66bc00a.svg\",\"point_up_2_tone3\":\"f117f5f.svg\",\"point_up_2_tone4\":\"b4ed3bb.svg\",\"point_up_2_tone5\":\"f86e6b9.svg\",\"point_down\":\"b80d789.svg\",\"point_down_tone1\":\"70129dd.svg\",\"point_down_tone2\":\"0ae7eea.svg\",\"point_down_tone3\":\"aad4f39.svg\",\"point_down_tone4\":\"1b0389f.svg\",\"point_down_tone5\":\"1d266ab.svg\",\"point_up\":\"14059d0.svg\",\"point_up_tone1\":\"a68d50d.svg\",\"point_up_tone2\":\"0dabe5a.svg\",\"point_up_tone3\":\"b044a10.svg\",\"point_up_tone4\":\"bd422f8.svg\",\"point_up_tone5\":\"36eec31.svg\",\"raised_hand\":\"a01ee6f.svg\",\"raised_hand_tone1\":\"63d88cb.svg\",\"raised_hand_tone2\":\"15ad4b4.svg\",\"raised_hand_tone3\":\"7df5ac6.svg\",\"raised_hand_tone4\":\"de49c80.svg\",\"raised_hand_tone5\":\"4e4e217.svg\",\"raised_back_of_hand\":\"03a3431.svg\",\"back_of_hand\":\"03a3431.svg\",\"raised_back_of_hand_tone1\":\"1e47667.svg\",\"back_of_hand_tone1\":\"1e47667.svg\",\"raised_back_of_hand_tone2\":\"dbe0c11.svg\",\"back_of_hand_tone2\":\"dbe0c11.svg\",\"raised_back_of_hand_tone3\":\"a189f32.svg\",\"back_of_hand_tone3\":\"a189f32.svg\",\"raised_back_of_hand_tone4\":\"aabe8b6.svg\",\"back_of_hand_tone4\":\"aabe8b6.svg\",\"raised_back_of_hand_tone5\":\"1a35c12.svg\",\"back_of_hand_tone5\":\"1a35c12.svg\",\"hand_splayed\":\"1e46fe9.svg\",\"raised_hand_with_fingers_splayed\":\"1e46fe9.svg\",\"hand_splayed_tone1\":\"8fe34bf.svg\",\"raised_hand_with_fingers_splayed_tone1\":\"8fe34bf.svg\",\"hand_splayed_tone2\":\"404ac42.svg\",\"raised_hand_with_fingers_splayed_tone2\":\"404ac42.svg\",\"hand_splayed_tone3\":\"f972a1a.svg\",\"raised_hand_with_fingers_splayed_tone3\":\"f972a1a.svg\",\"hand_splayed_tone4\":\"9ee98fa.svg\",\"raised_hand_with_fingers_splayed_tone4\":\"9ee98fa.svg\",\"hand_splayed_tone5\":\"a8706ca.svg\",\"raised_hand_with_fingers_splayed_tone5\":\"a8706ca.svg\",\"vulcan\":\"33a87e5.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers\":\"33a87e5.svg\",\"vulcan_salute\":\"33a87e5.svg\",\"vulcan_tone1\":\"e2257d7.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone1\":\"e2257d7.svg\",\"vulcan_tone2\":\"1c31b51.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone2\":\"1c31b51.svg\",\"vulcan_tone3\":\"b2b5252.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone3\":\"b2b5252.svg\",\"vulcan_tone4\":\"aac1b5a.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone4\":\"aac1b5a.svg\",\"vulcan_tone5\":\"d8031f8.svg\",\"raised_hand_with_part_between_middle_and_ring_fingers_tone5\":\"d8031f8.svg\",\"wave\":\"416968a.svg\",\"waving_hand\":\"416968a.svg\",\"wave_tone1\":\"428aceb.svg\",\"wave_tone2\":\"6dd2d1f.svg\",\"wave_tone3\":\"fa497a2.svg\",\"wave_tone4\":\"70bd7cf.svg\",\"wave_tone5\":\"7e74227.svg\",\"call_me\":\"eabacb6.svg\",\"call_me_hand\":\"eabacb6.svg\",\"call_me_tone1\":\"39ee699.svg\",\"call_me_hand_tone1\":\"39ee699.svg\",\"call_me_tone2\":\"a193407.svg\",\"call_me_hand_tone2\":\"a193407.svg\",\"call_me_tone3\":\"4e66c1c.svg\",\"call_me_hand_tone3\":\"4e66c1c.svg\",\"call_me_tone4\":\"fb552b1.svg\",\"call_me_hand_tone4\":\"fb552b1.svg\",\"call_me_tone5\":\"ced6cd1.svg\",\"call_me_hand_tone5\":\"ced6cd1.svg\",\"leftwards_hand\":\"4bb73fc.svg\",\"leftwards_hand_tone1\":\"c7c9afd.svg\",\"leftwards_hand_light_skin_tone\":\"c7c9afd.svg\",\"leftwards_hand_tone2\":\"d3c5d47.svg\",\"leftwards_hand_medium_light_skin_tone\":\"d3c5d47.svg\",\"leftwards_hand_tone3\":\"5dddf2b.svg\",\"leftwards_hand_medium_skin_tone\":\"5dddf2b.svg\",\"leftwards_hand_tone4\":\"28145be.svg\",\"leftwards_hand_medium_dark_skin_tone\":\"28145be.svg\",\"leftwards_hand_tone5\":\"e0f982a.svg\",\"leftwards_hand_dark_skin_tone\":\"e0f982a.svg\",\"rightwards_hand\":\"f9e9234.svg\",\"rightwards_hand_tone1\":\"0caa220.svg\",\"rightwards_hand_light_skin_tone\":\"0caa220.svg\",\"rightwards_hand_tone2\":\"beb9d59.svg\",\"rightwards_hand_medium_light_skin_tone\":\"beb9d59.svg\",\"rightwards_hand_tone3\":\"b250137.svg\",\"rightwards_hand_medium_skin_tone\":\"b250137.svg\",\"rightwards_hand_tone4\":\"7f2c38a.svg\",\"rightwards_hand_medium_dark_skin_tone\":\"7f2c38a.svg\",\"rightwards_hand_tone5\":\"631268a.svg\",\"rightwards_hand_dark_skin_tone\":\"631268a.svg\",\"muscle\":\"9c1b263.svg\",\"flexed_biceps\":\"9c1b263.svg\",\"muscle_tone1\":\"3489c7a.svg\",\"muscle_tone2\":\"c8b0739.svg\",\"muscle_tone3\":\"61af40c.svg\",\"muscle_tone4\":\"0b00d63.svg\",\"muscle_tone5\":\"e4ccfae.svg\",\"mechanical_arm\":\"789706a.svg\",\"middle_finger\":\"516015e.svg\",\"reversed_hand_with_middle_finger_extended\":\"516015e.svg\",\"middle_finger_tone1\":\"56a20e3.svg\",\"reversed_hand_with_middle_finger_extended_tone1\":\"56a20e3.svg\",\"middle_finger_tone2\":\"79b0369.svg\",\"reversed_hand_with_middle_finger_extended_tone2\":\"79b0369.svg\",\"middle_finger_tone3\":\"d762daa.svg\",\"reversed_hand_with_middle_finger_extended_tone3\":\"d762daa.svg\",\"middle_finger_tone4\":\"a16903d.svg\",\"reversed_hand_with_middle_finger_extended_tone4\":\"a16903d.svg\",\"middle_finger_tone5\":\"0433221.svg\",\"reversed_hand_with_middle_finger_extended_tone5\":\"0433221.svg\",\"writing_hand\":\"c06fe85.svg\",\"writing_hand_tone1\":\"3bb9865.svg\",\"writing_hand_tone2\":\"09613d5.svg\",\"writing_hand_tone3\":\"8f677e9.svg\",\"writing_hand_tone4\":\"a80ff84.svg\",\"writing_hand_tone5\":\"bc76cfd.svg\",\"pray\":\"61d7402.svg\",\"folded_hands\":\"61d7402.svg\",\"pray_tone1\":\"4a7f7a8.svg\",\"pray_tone2\":\"488d7bc.svg\",\"pray_tone3\":\"abb5e1f.svg\",\"pray_tone4\":\"8ee76a6.svg\",\"pray_tone5\":\"4e53992.svg\",\"index_pointing_at_the_viewer\":\"ba6907e.svg\",\"index_pointing_at_the_viewer_tone1\":\"cbea9e4.svg\",\"index_pointing_at_the_viewer_light_skin_tone\":\"cbea9e4.svg\",\"index_pointing_at_the_viewer_tone2\":\"064092d.svg\",\"index_pointing_at_the_viewer_medium_light_skin_tone\":\"064092d.svg\",\"index_pointing_at_the_viewer_tone3\":\"4c482c7.svg\",\"index_pointing_at_the_viewer_medium_skin_tone\":\"4c482c7.svg\",\"index_pointing_at_the_viewer_tone4\":\"176117f.svg\",\"index_pointing_at_the_viewer_medium_dark_skin_tone\":\"176117f.svg\",\"index_pointing_at_the_viewer_tone5\":\"a08eda9.svg\",\"index_pointing_at_the_viewer_dark_skin_tone\":\"a08eda9.svg\",\"foot\":\"f7eb2e4.svg\",\"foot_tone1\":\"c6e8410.svg\",\"foot_light_skin_tone\":\"c6e8410.svg\",\"foot_tone2\":\"58a17a3.svg\",\"foot_medium_light_skin_tone\":\"58a17a3.svg\",\"foot_tone3\":\"e3c956c.svg\",\"foot_medium_skin_tone\":\"e3c956c.svg\",\"foot_tone4\":\"f781d93.svg\",\"foot_medium_dark_skin_tone\":\"f781d93.svg\",\"foot_tone5\":\"2ba7377.svg\",\"foot_dark_skin_tone\":\"2ba7377.svg\",\"leg\":\"091f5fb.svg\",\"leg_tone1\":\"6072e6e.svg\",\"leg_light_skin_tone\":\"6072e6e.svg\",\"leg_tone2\":\"f05e535.svg\",\"leg_medium_light_skin_tone\":\"f05e535.svg\",\"leg_tone3\":\"a9ef097.svg\",\"leg_medium_skin_tone\":\"a9ef097.svg\",\"leg_tone4\":\"8716aa9.svg\",\"leg_medium_dark_skin_tone\":\"8716aa9.svg\",\"leg_tone5\":\"a928e6b.svg\",\"leg_dark_skin_tone\":\"a928e6b.svg\",\"mechanical_leg\":\"b7974d1.svg\",\"lipstick\":\"9f28886.svg\",\"kiss\":\"c72dfb2.svg\",\"kiss_mark\":\"c72dfb2.svg\",\"lips\":\"2920bdc.svg\",\"mouth\":\"2920bdc.svg\",\"biting_lip\":\"94a08c5.svg\",\"tooth\":\"ebeb871.svg\",\"tongue\":\"3e1f809.svg\",\"ear\":\"c5f35e2.svg\",\"ear_tone1\":\"7d56b68.svg\",\"ear_tone2\":\"59113b8.svg\",\"ear_tone3\":\"34ff93f.svg\",\"ear_tone4\":\"1b2fbc0.svg\",\"ear_tone5\":\"e53cb4d.svg\",\"ear_with_hearing_aid\":\"25cb021.svg\",\"ear_with_hearing_aid_tone1\":\"0ae090c.svg\",\"ear_with_hearing_aid_light_skin_tone\":\"0ae090c.svg\",\"ear_with_hearing_aid_tone2\":\"f695cdd.svg\",\"ear_with_hearing_aid_medium_light_skin_tone\":\"f695cdd.svg\",\"ear_with_hearing_aid_tone3\":\"0d382e1.svg\",\"ear_with_hearing_aid_medium_skin_tone\":\"0d382e1.svg\",\"ear_with_hearing_aid_tone4\":\"57064f7.svg\",\"ear_with_hearing_aid_medium_dark_skin_tone\":\"57064f7.svg\",\"ear_with_hearing_aid_tone5\":\"eef2ced.svg\",\"ear_with_hearing_aid_dark_skin_tone\":\"eef2ced.svg\",\"nose\":\"bd8ef1d.svg\",\"nose_tone1\":\"e0f60a6.svg\",\"nose_tone2\":\"ace3849.svg\",\"nose_tone3\":\"66b75d0.svg\",\"nose_tone4\":\"6b8323e.svg\",\"nose_tone5\":\"79b1d60.svg\",\"footprints\":\"774dca0.svg\",\"eye\":\"ce6d3bc.svg\",\"eyes\":\"504e124.svg\",\"anatomical_heart\":\"0a683ed.svg\",\"lungs\":\"76ce912.svg\",\"brain\":\"9ca0f1a.svg\",\"speaking_head\":\"e2a0c47.svg\",\"speaking_head_in_silhouette\":\"e2a0c47.svg\",\"bust_in_silhouette\":\"b77275e.svg\",\"busts_in_silhouette\":\"4775308.svg\",\"people_hugging\":\"9ba1877.svg\",\"baby\":\"6b120e0.svg\",\"baby_tone1\":\"4970605.svg\",\"baby_tone2\":\"1c238b7.svg\",\"baby_tone3\":\"3d346f2.svg\",\"baby_tone4\":\"2256735.svg\",\"baby_tone5\":\"b1e0f97.svg\",\"child\":\"0c86a55.svg\",\"child_tone1\":\"1a1ee91.svg\",\"child_light_skin_tone\":\"1a1ee91.svg\",\"child_tone2\":\"8117d83.svg\",\"child_medium_light_skin_tone\":\"8117d83.svg\",\"child_tone3\":\"98efc1d.svg\",\"child_medium_skin_tone\":\"98efc1d.svg\",\"child_tone4\":\"ade7753.svg\",\"child_medium_dark_skin_tone\":\"ade7753.svg\",\"child_tone5\":\"776d50a.svg\",\"child_dark_skin_tone\":\"776d50a.svg\",\"girl\":\"05657c1.svg\",\"girl_tone1\":\"8918ad5.svg\",\"girl_tone2\":\"6d3bdbc.svg\",\"girl_tone3\":\"3b6f2bb.svg\",\"girl_tone4\":\"8592bac.svg\",\"girl_tone5\":\"bbcbedc.svg\",\"boy\":\"e8fb01a.svg\",\"boy_tone1\":\"e099d02.svg\",\"boy_tone2\":\"9fb2c42.svg\",\"boy_tone3\":\"957b277.svg\",\"boy_tone4\":\"3084c47.svg\",\"boy_tone5\":\"39a0989.svg\",\"adult\":\"e68c3d5.svg\",\"person\":\"e68c3d5.svg\",\"adult_tone1\":\"de2b6fd.svg\",\"adult_light_skin_tone\":\"de2b6fd.svg\",\"adult_tone2\":\"6290f21.svg\",\"adult_medium_light_skin_tone\":\"6290f21.svg\",\"adult_tone3\":\"ab633c5.svg\",\"adult_medium_skin_tone\":\"ab633c5.svg\",\"adult_tone4\":\"bd9903f.svg\",\"adult_medium_dark_skin_tone\":\"bd9903f.svg\",\"adult_tone5\":\"2aff0bd.svg\",\"adult_dark_skin_tone\":\"2aff0bd.svg\",\"woman\":\"a0b627d.svg\",\"woman_tone1\":\"0eb2b3a.svg\",\"woman_tone2\":\"fff6382.svg\",\"woman_tone3\":\"8eb1775.svg\",\"woman_tone4\":\"76e777a.svg\",\"woman_tone5\":\"129cba3.svg\",\"man\":\"bb89b12.svg\",\"man_tone1\":\"aeabe4e.svg\",\"man_tone2\":\"13e0aba.svg\",\"man_tone3\":\"e9f553f.svg\",\"man_tone4\":\"fd63055.svg\",\"man_tone5\":\"d16a927.svg\",\"person_curly_hair\":\"053f135.svg\",\"person_tone1_curly_hair\":\"b99a9c0.svg\",\"person_light_skin_tone_curly_hair\":\"b99a9c0.svg\",\"person_tone2_curly_hair\":\"a15cd41.svg\",\"person_medium_light_skin_tone_curly_hair\":\"a15cd41.svg\",\"person_tone3_curly_hair\":\"c7b9601.svg\",\"person_medium_skin_tone_curly_hair\":\"c7b9601.svg\",\"person_tone4_curly_hair\":\"e9673a8.svg\",\"person_medium_dark_skin_tone_curly_hair\":\"e9673a8.svg\",\"person_tone5_curly_hair\":\"e8f2685.svg\",\"person_dark_skin_tone_curly_hair\":\"e8f2685.svg\",\"woman_curly_haired\":\"7f65748.svg\",\"woman_curly_haired_tone1\":\"a3a7ba2.svg\",\"woman_curly_haired_light_skin_tone\":\"a3a7ba2.svg\",\"woman_curly_haired_tone2\":\"152918f.svg\",\"woman_curly_haired_medium_light_skin_tone\":\"152918f.svg\",\"woman_curly_haired_tone3\":\"2286c64.svg\",\"woman_curly_haired_medium_skin_tone\":\"2286c64.svg\",\"woman_curly_haired_tone4\":\"23ae61d.svg\",\"woman_curly_haired_medium_dark_skin_tone\":\"23ae61d.svg\",\"woman_curly_haired_tone5\":\"f4e7d4e.svg\",\"woman_curly_haired_dark_skin_tone\":\"f4e7d4e.svg\",\"man_curly_haired\":\"b6adf8d.svg\",\"man_curly_haired_tone1\":\"39e9ae7.svg\",\"man_curly_haired_light_skin_tone\":\"39e9ae7.svg\",\"man_curly_haired_tone2\":\"41bc09c.svg\",\"man_curly_haired_medium_light_skin_tone\":\"41bc09c.svg\",\"man_curly_haired_tone3\":\"eb53bb6.svg\",\"man_curly_haired_medium_skin_tone\":\"eb53bb6.svg\",\"man_curly_haired_tone4\":\"d9401de.svg\",\"man_curly_haired_medium_dark_skin_tone\":\"d9401de.svg\",\"man_curly_haired_tone5\":\"f7b918d.svg\",\"man_curly_haired_dark_skin_tone\":\"f7b918d.svg\",\"person_red_hair\":\"cc2093a.svg\",\"person_tone1_red_hair\":\"5c41b26.svg\",\"person_light_skin_tone_red_hair\":\"5c41b26.svg\",\"person_tone2_red_hair\":\"ba97ee4.svg\",\"person_medium_light_skin_tone_red_hair\":\"ba97ee4.svg\",\"person_tone3_red_hair\":\"542a340.svg\",\"person_medium_skin_tone_red_hair\":\"542a340.svg\",\"person_tone4_red_hair\":\"88cbfe4.svg\",\"person_medium_dark_skin_tone_red_hair\":\"88cbfe4.svg\",\"person_tone5_red_hair\":\"7c58e8b.svg\",\"person_dark_skin_tone_red_hair\":\"7c58e8b.svg\",\"woman_red_haired\":\"da96491.svg\",\"woman_red_haired_tone1\":\"b268f8a.svg\",\"woman_red_haired_light_skin_tone\":\"b268f8a.svg\",\"woman_red_haired_tone2\":\"d5b4bf3.svg\",\"woman_red_haired_medium_light_skin_tone\":\"d5b4bf3.svg\",\"woman_red_haired_tone3\":\"94b1930.svg\",\"woman_red_haired_medium_skin_tone\":\"94b1930.svg\",\"woman_red_haired_tone4\":\"7e48c63.svg\",\"woman_red_haired_medium_dark_skin_tone\":\"7e48c63.svg\",\"woman_red_haired_tone5\":\"42f33f8.svg\",\"woman_red_haired_dark_skin_tone\":\"42f33f8.svg\",\"man_red_haired\":\"75a6d21.svg\",\"man_red_hair\":\"75a6d21.svg\",\"man_red_haired_tone1\":\"f9c72b5.svg\",\"man_red_haired_light_skin_tone\":\"f9c72b5.svg\",\"man_red_haired_tone2\":\"4bf433a.svg\",\"man_red_haired_medium_light_skin_tone\":\"4bf433a.svg\",\"man_red_haired_tone3\":\"504bb42.svg\",\"man_red_haired_medium_skin_tone\":\"504bb42.svg\",\"man_red_haired_tone4\":\"3a20581.svg\",\"man_red_haired_medium_dark_skin_tone\":\"3a20581.svg\",\"man_red_haired_tone5\":\"bf9e793.svg\",\"man_red_haired_dark_skin_tone\":\"bf9e793.svg\",\"blond_haired_person\":\"73f2288.svg\",\"person_with_blond_hair\":\"73f2288.svg\",\"blond_haired_person_tone1\":\"29a62d0.svg\",\"person_with_blond_hair_tone1\":\"29a62d0.svg\",\"blond_haired_person_tone2\":\"07ec158.svg\",\"person_with_blond_hair_tone2\":\"07ec158.svg\",\"blond_haired_person_tone3\":\"e622a4b.svg\",\"person_with_blond_hair_tone3\":\"e622a4b.svg\",\"blond_haired_person_tone4\":\"4921dfd.svg\",\"person_with_blond_hair_tone4\":\"4921dfd.svg\",\"blond_haired_person_tone5\":\"61d33f2.svg\",\"person_with_blond_hair_tone5\":\"61d33f2.svg\",\"blond-haired_woman\":\"0523090.svg\",\"blond-haired_woman_tone1\":\"187a349.svg\",\"blond-haired_woman_light_skin_tone\":\"187a349.svg\",\"blond-haired_woman_tone2\":\"fff6382.svg\",\"blond-haired_woman_medium_light_skin_tone\":\"fff6382.svg\",\"blond-haired_woman_tone3\":\"6f8c884.svg\",\"blond-haired_woman_medium_skin_tone\":\"6f8c884.svg\",\"blond-haired_woman_tone4\":\"fc47714.svg\",\"blond-haired_woman_medium_dark_skin_tone\":\"fc47714.svg\",\"blond-haired_woman_tone5\":\"8235eeb.svg\",\"blond-haired_woman_dark_skin_tone\":\"8235eeb.svg\",\"blond-haired_man\":\"74de604.svg\",\"blond-haired_man_tone1\":\"5fba535.svg\",\"blond-haired_man_light_skin_tone\":\"5fba535.svg\",\"blond-haired_man_tone2\":\"458f0cc.svg\",\"blond-haired_man_medium_light_skin_tone\":\"458f0cc.svg\",\"blond-haired_man_tone3\":\"2b4e848.svg\",\"blond-haired_man_medium_skin_tone\":\"2b4e848.svg\",\"blond-haired_man_tone4\":\"e065966.svg\",\"blond-haired_man_medium_dark_skin_tone\":\"e065966.svg\",\"blond-haired_man_tone5\":\"d4e74be.svg\",\"blond-haired_man_dark_skin_tone\":\"d4e74be.svg\",\"person_white_hair\":\"a888959.svg\",\"person_tone1_white_hair\":\"45f6b72.svg\",\"person_light_skin_tone_white_hair\":\"45f6b72.svg\",\"person_tone2_white_hair\":\"8cd1671.svg\",\"person_medium_light_skin_tone_white_hair\":\"8cd1671.svg\",\"person_tone3_white_hair\":\"552b1e2.svg\",\"person_medium_skin_tone_white_hair\":\"552b1e2.svg\",\"person_tone4_white_hair\":\"24ae36b.svg\",\"person_medium_dark_skin_tone_white_hair\":\"24ae36b.svg\",\"person_tone5_white_hair\":\"e20ef19.svg\",\"person_dark_skin_tone_white_hair\":\"e20ef19.svg\",\"woman_white_haired\":\"f08552a.svg\",\"woman_white_haired_tone1\":\"dc1f2d6.svg\",\"woman_white_haired_light_skin_tone\":\"dc1f2d6.svg\",\"woman_white_haired_tone2\":\"0818e97.svg\",\"woman_white_haired_medium_light_skin_tone\":\"0818e97.svg\",\"woman_white_haired_tone3\":\"5603b0a.svg\",\"woman_white_haired_medium_skin_tone\":\"5603b0a.svg\",\"woman_white_haired_tone4\":\"2bda365.svg\",\"woman_white_haired_medium_dark_skin_tone\":\"2bda365.svg\",\"woman_white_haired_tone5\":\"f0584a9.svg\",\"woman_white_haired_dark_skin_tone\":\"f0584a9.svg\",\"man_white_haired\":\"bfe7b10.svg\",\"man_white_haired_tone1\":\"7146b21.svg\",\"man_white_haired_light_skin_tone\":\"7146b21.svg\",\"man_white_haired_tone2\":\"e021716.svg\",\"man_white_haired_medium_light_skin_tone\":\"e021716.svg\",\"man_white_haired_tone3\":\"796eb5f.svg\",\"man_white_haired_medium_skin_tone\":\"796eb5f.svg\",\"man_white_haired_tone4\":\"a35578d.svg\",\"man_white_haired_medium_dark_skin_tone\":\"a35578d.svg\",\"man_white_haired_tone5\":\"81ccd28.svg\",\"man_white_haired_dark_skin_tone\":\"81ccd28.svg\",\"person_bald\":\"104edb8.svg\",\"person_tone1_bald\":\"dde0988.svg\",\"person_light_skin_tone_bald\":\"dde0988.svg\",\"person_tone2_bald\":\"33377a2.svg\",\"person_medium_light_skin_tone_bald\":\"33377a2.svg\",\"person_tone3_bald\":\"1219df1.svg\",\"person_medium_skin_tone_bald\":\"1219df1.svg\",\"person_tone4_bald\":\"db8ce84.svg\",\"person_medium_dark_skin_tone_bald\":\"db8ce84.svg\",\"person_tone5_bald\":\"8dff4d4.svg\",\"person_dark_skin_tone_bald\":\"8dff4d4.svg\",\"woman_bald\":\"51d82b4.svg\",\"woman_bald_tone1\":\"ee90ae0.svg\",\"woman_bald_light_skin_tone\":\"ee90ae0.svg\",\"woman_bald_tone2\":\"8726e02.svg\",\"woman_bald_medium_light_skin_tone\":\"8726e02.svg\",\"woman_bald_tone3\":\"ddaa0ac.svg\",\"woman_bald_medium_skin_tone\":\"ddaa0ac.svg\",\"woman_bald_tone4\":\"774e784.svg\",\"woman_bald_medium_dark_skin_tone\":\"774e784.svg\",\"woman_bald_tone5\":\"bdd8178.svg\",\"woman_bald_dark_skin_tone\":\"bdd8178.svg\",\"man_bald\":\"4c265b1.svg\",\"man_bald_tone1\":\"ca04a9a.svg\",\"man_bald_light_skin_tone\":\"ca04a9a.svg\",\"man_bald_tone2\":\"a777c1f.svg\",\"man_bald_medium_light_skin_tone\":\"a777c1f.svg\",\"man_bald_tone3\":\"ce24d3a.svg\",\"man_bald_medium_skin_tone\":\"ce24d3a.svg\",\"man_bald_tone4\":\"3a94da1.svg\",\"man_bald_medium_dark_skin_tone\":\"3a94da1.svg\",\"man_bald_tone5\":\"acdb52b.svg\",\"man_bald_dark_skin_tone\":\"acdb52b.svg\",\"bearded_person\":\"a3e69d0.svg\",\"person_beard\":\"a3e69d0.svg\",\"bearded_person_tone1\":\"55239df.svg\",\"bearded_person_light_skin_tone\":\"55239df.svg\",\"bearded_person_tone2\":\"7e53735.svg\",\"bearded_person_medium_light_skin_tone\":\"7e53735.svg\",\"bearded_person_tone3\":\"eaa8c25.svg\",\"bearded_person_medium_skin_tone\":\"eaa8c25.svg\",\"bearded_person_tone4\":\"a5e9ed9.svg\",\"bearded_person_medium_dark_skin_tone\":\"a5e9ed9.svg\",\"bearded_person_tone5\":\"2d120d5.svg\",\"bearded_person_dark_skin_tone\":\"2d120d5.svg\",\"woman_beard\":\"4abd174.svg\",\"woman_tone1_beard\":\"6d854d7.svg\",\"woman_light_skin_tone_beard\":\"6d854d7.svg\",\"woman_tone2_beard\":\"c573411.svg\",\"woman_medium_light_skin_tone_beard\":\"c573411.svg\",\"woman_tone3_beard\":\"e682e71.svg\",\"woman_medium_skin_tone_beard\":\"e682e71.svg\",\"woman_tone4_beard\":\"884c1a7.svg\",\"woman_medium_dark_skin_tone_beard\":\"884c1a7.svg\",\"woman_tone5_beard\":\"5417b7f.svg\",\"woman_dark_skin_tone_beard\":\"5417b7f.svg\",\"man_beard\":\"567c295.svg\",\"man_tone1_beard\":\"549c546.svg\",\"man_light_skin_tone_beard\":\"549c546.svg\",\"man_tone2_beard\":\"44c4d8f.svg\",\"man_medium_light_skin_tone_beard\":\"44c4d8f.svg\",\"man_tone3_beard\":\"64017a9.svg\",\"man_medium_skin_tone_beard\":\"64017a9.svg\",\"man_tone4_beard\":\"abf3fe9.svg\",\"man_medium_dark_skin_tone_beard\":\"abf3fe9.svg\",\"man_tone5_beard\":\"c35fc33.svg\",\"man_dark_skin_tone_beard\":\"c35fc33.svg\",\"older_adult\":\"4b64147.svg\",\"older_person\":\"4b64147.svg\",\"older_adult_tone1\":\"5e150c6.svg\",\"older_adult_light_skin_tone\":\"5e150c6.svg\",\"older_adult_tone2\":\"d7be541.svg\",\"older_adult_medium_light_skin_tone\":\"d7be541.svg\",\"older_adult_tone3\":\"20ea415.svg\",\"older_adult_medium_skin_tone\":\"20ea415.svg\",\"older_adult_tone4\":\"570924e.svg\",\"older_adult_medium_dark_skin_tone\":\"570924e.svg\",\"older_adult_tone5\":\"eeec292.svg\",\"older_adult_dark_skin_tone\":\"eeec292.svg\",\"older_woman\":\"cdd9b53.svg\",\"grandma\":\"cdd9b53.svg\",\"old_woman\":\"cdd9b53.svg\",\"older_woman_tone1\":\"42c231d.svg\",\"grandma_tone1\":\"42c231d.svg\",\"older_woman_tone2\":\"f17d047.svg\",\"grandma_tone2\":\"f17d047.svg\",\"older_woman_tone3\":\"8cdefc8.svg\",\"grandma_tone3\":\"8cdefc8.svg\",\"older_woman_tone4\":\"e59c265.svg\",\"grandma_tone4\":\"e59c265.svg\",\"older_woman_tone5\":\"a8f6abc.svg\",\"grandma_tone5\":\"a8f6abc.svg\",\"older_man\":\"be4ea09.svg\",\"old_man\":\"be4ea09.svg\",\"older_man_tone1\":\"2b69c63.svg\",\"older_man_tone2\":\"389c84b.svg\",\"older_man_tone3\":\"319464b.svg\",\"older_man_tone4\":\"86734d7.svg\",\"older_man_tone5\":\"08d7b15.svg\",\"man_with_chinese_cap\":\"06ae976.svg\",\"man_with_gua_pi_mao\":\"06ae976.svg\",\"man_with_chinese_cap_tone1\":\"2a983b9.svg\",\"man_with_gua_pi_mao_tone1\":\"2a983b9.svg\",\"man_with_chinese_cap_tone2\":\"155e404.svg\",\"man_with_gua_pi_mao_tone2\":\"155e404.svg\",\"man_with_chinese_cap_tone3\":\"8059954.svg\",\"man_with_gua_pi_mao_tone3\":\"8059954.svg\",\"man_with_chinese_cap_tone4\":\"c25d709.svg\",\"man_with_gua_pi_mao_tone4\":\"c25d709.svg\",\"man_with_chinese_cap_tone5\":\"333c3d0.svg\",\"man_with_gua_pi_mao_tone5\":\"333c3d0.svg\",\"person_wearing_turban\":\"0ca8dd5.svg\",\"man_with_turban\":\"0ca8dd5.svg\",\"person_wearing_turban_tone1\":\"4656d99.svg\",\"man_with_turban_tone1\":\"4656d99.svg\",\"person_wearing_turban_tone2\":\"dfbaf66.svg\",\"man_with_turban_tone2\":\"dfbaf66.svg\",\"person_wearing_turban_tone3\":\"3c15f41.svg\",\"man_with_turban_tone3\":\"3c15f41.svg\",\"person_wearing_turban_tone4\":\"d94e644.svg\",\"man_with_turban_tone4\":\"d94e644.svg\",\"person_wearing_turban_tone5\":\"d3cc0ec.svg\",\"man_with_turban_tone5\":\"d3cc0ec.svg\",\"woman_wearing_turban\":\"913976a.svg\",\"woman_wearing_turban_tone1\":\"170f58d.svg\",\"woman_wearing_turban_light_skin_tone\":\"170f58d.svg\",\"woman_wearing_turban_tone2\":\"ac9a5a1.svg\",\"woman_wearing_turban_medium_light_skin_tone\":\"ac9a5a1.svg\",\"woman_wearing_turban_tone3\":\"e576494.svg\",\"woman_wearing_turban_medium_skin_tone\":\"e576494.svg\",\"woman_wearing_turban_tone4\":\"beba980.svg\",\"woman_wearing_turban_medium_dark_skin_tone\":\"beba980.svg\",\"woman_wearing_turban_tone5\":\"78bb876.svg\",\"woman_wearing_turban_dark_skin_tone\":\"78bb876.svg\",\"man_wearing_turban\":\"1ab02a3.svg\",\"man_wearing_turban_tone1\":\"fa699d7.svg\",\"man_wearing_turban_light_skin_tone\":\"fa699d7.svg\",\"man_wearing_turban_tone2\":\"e532833.svg\",\"man_wearing_turban_medium_light_skin_tone\":\"e532833.svg\",\"man_wearing_turban_tone3\":\"ddb1af8.svg\",\"man_wearing_turban_medium_skin_tone\":\"ddb1af8.svg\",\"man_wearing_turban_tone4\":\"3ac0218.svg\",\"man_wearing_turban_medium_dark_skin_tone\":\"3ac0218.svg\",\"man_wearing_turban_tone5\":\"40976b3.svg\",\"man_wearing_turban_dark_skin_tone\":\"40976b3.svg\",\"woman_with_headscarf\":\"c0f9ef4.svg\",\"woman_with_headscarf_tone1\":\"71fe9c3.svg\",\"woman_with_headscarf_light_skin_tone\":\"71fe9c3.svg\",\"woman_with_headscarf_tone2\":\"4ac4ff7.svg\",\"woman_with_headscarf_medium_light_skin_tone\":\"4ac4ff7.svg\",\"woman_with_headscarf_tone3\":\"7cf843f.svg\",\"woman_with_headscarf_medium_skin_tone\":\"7cf843f.svg\",\"woman_with_headscarf_tone4\":\"8dde333.svg\",\"woman_with_headscarf_medium_dark_skin_tone\":\"8dde333.svg\",\"woman_with_headscarf_tone5\":\"cd6ea39.svg\",\"woman_with_headscarf_dark_skin_tone\":\"cd6ea39.svg\",\"police_officer\":\"55d8b37.svg\",\"cop\":\"55d8b37.svg\",\"police_officer_tone1\":\"b95742f.svg\",\"cop_tone1\":\"b95742f.svg\",\"police_officer_tone2\":\"606957d.svg\",\"cop_tone2\":\"606957d.svg\",\"police_officer_tone3\":\"1a8a9ee.svg\",\"cop_tone3\":\"1a8a9ee.svg\",\"police_officer_tone4\":\"94e4814.svg\",\"cop_tone4\":\"94e4814.svg\",\"police_officer_tone5\":\"cc685e6.svg\",\"cop_tone5\":\"cc685e6.svg\",\"woman_police_officer\":\"147d06b.svg\",\"woman_police_officer_tone1\":\"390aa26.svg\",\"woman_police_officer_light_skin_tone\":\"390aa26.svg\",\"woman_police_officer_tone2\":\"0814464.svg\",\"woman_police_officer_medium_light_skin_tone\":\"0814464.svg\",\"woman_police_officer_tone3\":\"feba5e2.svg\",\"woman_police_officer_medium_skin_tone\":\"feba5e2.svg\",\"woman_police_officer_tone4\":\"bc488b0.svg\",\"woman_police_officer_medium_dark_skin_tone\":\"bc488b0.svg\",\"woman_police_officer_tone5\":\"fe6c71e.svg\",\"woman_police_officer_dark_skin_tone\":\"fe6c71e.svg\",\"man_police_officer\":\"5917c6e.svg\",\"man_police_officer_tone1\":\"d4802b5.svg\",\"man_police_officer_light_skin_tone\":\"d4802b5.svg\",\"man_police_officer_tone2\":\"7f1a418.svg\",\"man_police_officer_medium_light_skin_tone\":\"7f1a418.svg\",\"man_police_officer_tone3\":\"a2b980e.svg\",\"man_police_officer_medium_skin_tone\":\"a2b980e.svg\",\"man_police_officer_tone4\":\"a4d52ea.svg\",\"man_police_officer_medium_dark_skin_tone\":\"a4d52ea.svg\",\"man_police_officer_tone5\":\"266cefb.svg\",\"man_police_officer_dark_skin_tone\":\"266cefb.svg\",\"construction_worker\":\"0f13c5b.svg\",\"construction_worker_tone1\":\"34c2a70.svg\",\"construction_worker_tone2\":\"f4168f1.svg\",\"construction_worker_tone3\":\"8b0acfa.svg\",\"construction_worker_tone4\":\"8b5b749.svg\",\"construction_worker_tone5\":\"5839b6c.svg\",\"woman_construction_worker\":\"0351b72.svg\",\"woman_construction_worker_tone1\":\"dc63f79.svg\",\"woman_construction_worker_light_skin_tone\":\"dc63f79.svg\",\"woman_construction_worker_tone2\":\"cb23235.svg\",\"woman_construction_worker_medium_light_skin_tone\":\"cb23235.svg\",\"woman_construction_worker_tone3\":\"a1ad1da.svg\",\"woman_construction_worker_medium_skin_tone\":\"a1ad1da.svg\",\"woman_construction_worker_tone4\":\"0a08c63.svg\",\"woman_construction_worker_medium_dark_skin_tone\":\"0a08c63.svg\",\"woman_construction_worker_tone5\":\"8ee3406.svg\",\"woman_construction_worker_dark_skin_tone\":\"8ee3406.svg\",\"man_construction_worker\":\"d2bfd43.svg\",\"man_construction_worker_tone1\":\"6dcd0a6.svg\",\"man_construction_worker_light_skin_tone\":\"6dcd0a6.svg\",\"man_construction_worker_tone2\":\"c0c7334.svg\",\"man_construction_worker_medium_light_skin_tone\":\"c0c7334.svg\",\"man_construction_worker_tone3\":\"2825484.svg\",\"man_construction_worker_medium_skin_tone\":\"2825484.svg\",\"man_construction_worker_tone4\":\"c7a36a5.svg\",\"man_construction_worker_medium_dark_skin_tone\":\"c7a36a5.svg\",\"man_construction_worker_tone5\":\"bfa8937.svg\",\"man_construction_worker_dark_skin_tone\":\"bfa8937.svg\",\"guard\":\"308ae99.svg\",\"guardsman\":\"308ae99.svg\",\"guard_tone1\":\"4026dd4.svg\",\"guardsman_tone1\":\"4026dd4.svg\",\"guard_tone2\":\"fe4ddb5.svg\",\"guardsman_tone2\":\"fe4ddb5.svg\",\"guard_tone3\":\"23dac93.svg\",\"guardsman_tone3\":\"23dac93.svg\",\"guard_tone4\":\"2f7282c.svg\",\"guardsman_tone4\":\"2f7282c.svg\",\"guard_tone5\":\"bdb030d.svg\",\"guardsman_tone5\":\"bdb030d.svg\",\"woman_guard\":\"6dcbee7.svg\",\"woman_guard_tone1\":\"bc1720a.svg\",\"woman_guard_light_skin_tone\":\"bc1720a.svg\",\"woman_guard_tone2\":\"670ae61.svg\",\"woman_guard_medium_light_skin_tone\":\"670ae61.svg\",\"woman_guard_tone3\":\"79abf2c.svg\",\"woman_guard_medium_skin_tone\":\"79abf2c.svg\",\"woman_guard_tone4\":\"b96832b.svg\",\"woman_guard_medium_dark_skin_tone\":\"b96832b.svg\",\"woman_guard_tone5\":\"19ab501.svg\",\"woman_guard_dark_skin_tone\":\"19ab501.svg\",\"man_guard\":\"18b010d.svg\",\"man_guard_tone1\":\"107e2f4.svg\",\"man_guard_light_skin_tone\":\"107e2f4.svg\",\"man_guard_tone2\":\"7b02510.svg\",\"man_guard_medium_light_skin_tone\":\"7b02510.svg\",\"man_guard_tone3\":\"bb1fa80.svg\",\"man_guard_medium_skin_tone\":\"bb1fa80.svg\",\"man_guard_tone4\":\"f95cebf.svg\",\"man_guard_medium_dark_skin_tone\":\"f95cebf.svg\",\"man_guard_tone5\":\"80c0660.svg\",\"man_guard_dark_skin_tone\":\"80c0660.svg\",\"detective\":\"92f451b.svg\",\"spy\":\"92f451b.svg\",\"sleuth_or_spy\":\"92f451b.svg\",\"detective_tone1\":\"acdb648.svg\",\"spy_tone1\":\"acdb648.svg\",\"sleuth_or_spy_tone1\":\"acdb648.svg\",\"detective_tone2\":\"ebbf06e.svg\",\"spy_tone2\":\"ebbf06e.svg\",\"sleuth_or_spy_tone2\":\"ebbf06e.svg\",\"detective_tone3\":\"481c8c7.svg\",\"spy_tone3\":\"481c8c7.svg\",\"sleuth_or_spy_tone3\":\"481c8c7.svg\",\"detective_tone4\":\"28ae476.svg\",\"spy_tone4\":\"28ae476.svg\",\"sleuth_or_spy_tone4\":\"28ae476.svg\",\"detective_tone5\":\"234d7e5.svg\",\"spy_tone5\":\"234d7e5.svg\",\"sleuth_or_spy_tone5\":\"234d7e5.svg\",\"woman_detective\":\"4a3753b.svg\",\"woman_detective_tone1\":\"0ddd142.svg\",\"woman_detective_light_skin_tone\":\"0ddd142.svg\",\"woman_detective_tone2\":\"4bc3fe3.svg\",\"woman_detective_medium_light_skin_tone\":\"4bc3fe3.svg\",\"woman_detective_tone3\":\"344d59f.svg\",\"woman_detective_medium_skin_tone\":\"344d59f.svg\",\"woman_detective_tone4\":\"4347e0f.svg\",\"woman_detective_medium_dark_skin_tone\":\"4347e0f.svg\",\"woman_detective_tone5\":\"b9b28fc.svg\",\"woman_detective_dark_skin_tone\":\"b9b28fc.svg\",\"man_detective\":\"2391fd5.svg\",\"man_detective_tone1\":\"c2d5db0.svg\",\"man_detective_light_skin_tone\":\"c2d5db0.svg\",\"man_detective_tone2\":\"68a9ab5.svg\",\"man_detective_medium_light_skin_tone\":\"68a9ab5.svg\",\"man_detective_tone3\":\"9969bab.svg\",\"man_detective_medium_skin_tone\":\"9969bab.svg\",\"man_detective_tone4\":\"cd65781.svg\",\"man_detective_medium_dark_skin_tone\":\"cd65781.svg\",\"man_detective_tone5\":\"69b5578.svg\",\"man_detective_dark_skin_tone\":\"69b5578.svg\",\"health_worker\":\"6b32127.svg\",\"health_worker_tone1\":\"fb3f046.svg\",\"health_worker_light_skin_tone\":\"fb3f046.svg\",\"health_worker_tone2\":\"06fccf8.svg\",\"health_worker_medium_light_skin_tone\":\"06fccf8.svg\",\"health_worker_tone3\":\"90d36ab.svg\",\"health_worker_medium_skin_tone\":\"90d36ab.svg\",\"health_worker_tone4\":\"1c1963d.svg\",\"health_worker_medium_dark_skin_tone\":\"1c1963d.svg\",\"health_worker_tone5\":\"adec8f8.svg\",\"health_worker_dark_skin_tone\":\"adec8f8.svg\",\"woman_health_worker\":\"907cb95.svg\",\"woman_health_worker_tone1\":\"b877224.svg\",\"woman_health_worker_light_skin_tone\":\"b877224.svg\",\"woman_health_worker_tone2\":\"ccb3ee5.svg\",\"woman_health_worker_medium_light_skin_tone\":\"ccb3ee5.svg\",\"woman_health_worker_tone3\":\"b7f2d7f.svg\",\"woman_health_worker_medium_skin_tone\":\"b7f2d7f.svg\",\"woman_health_worker_tone4\":\"e5b097f.svg\",\"woman_health_worker_medium_dark_skin_tone\":\"e5b097f.svg\",\"woman_health_worker_tone5\":\"e50ddd0.svg\",\"woman_health_worker_dark_skin_tone\":\"e50ddd0.svg\",\"man_health_worker\":\"1a4fb77.svg\",\"man_health_worker_tone1\":\"0281347.svg\",\"man_health_worker_light_skin_tone\":\"0281347.svg\",\"man_health_worker_tone2\":\"fb9a511.svg\",\"man_health_worker_medium_light_skin_tone\":\"fb9a511.svg\",\"man_health_worker_tone3\":\"d29ffa8.svg\",\"man_health_worker_medium_skin_tone\":\"d29ffa8.svg\",\"man_health_worker_tone4\":\"8b7e9fa.svg\",\"man_health_worker_medium_dark_skin_tone\":\"8b7e9fa.svg\",\"man_health_worker_tone5\":\"c666f32.svg\",\"man_health_worker_dark_skin_tone\":\"c666f32.svg\",\"farmer\":\"ce590f6.svg\",\"farmer_tone1\":\"7a4bff9.svg\",\"farmer_light_skin_tone\":\"7a4bff9.svg\",\"farmer_tone2\":\"7a37abb.svg\",\"farmer_medium_light_skin_tone\":\"7a37abb.svg\",\"farmer_tone3\":\"035ea17.svg\",\"farmer_medium_skin_tone\":\"035ea17.svg\",\"farmer_tone4\":\"cc52f4d.svg\",\"farmer_medium_dark_skin_tone\":\"cc52f4d.svg\",\"farmer_tone5\":\"0acd150.svg\",\"farmer_dark_skin_tone\":\"0acd150.svg\",\"woman_farmer\":\"56ec7b4.svg\",\"woman_farmer_tone1\":\"51f3c57.svg\",\"woman_farmer_light_skin_tone\":\"51f3c57.svg\",\"woman_farmer_tone2\":\"33d3b56.svg\",\"woman_farmer_medium_light_skin_tone\":\"33d3b56.svg\",\"woman_farmer_tone3\":\"92462af.svg\",\"woman_farmer_medium_skin_tone\":\"92462af.svg\",\"woman_farmer_tone4\":\"d7eb2bd.svg\",\"woman_farmer_medium_dark_skin_tone\":\"d7eb2bd.svg\",\"woman_farmer_tone5\":\"eb3a9fe.svg\",\"woman_farmer_dark_skin_tone\":\"eb3a9fe.svg\",\"man_farmer\":\"0b4d127.svg\",\"man_farmer_tone1\":\"d54fbc7.svg\",\"man_farmer_light_skin_tone\":\"d54fbc7.svg\",\"man_farmer_tone2\":\"7b938bc.svg\",\"man_farmer_medium_light_skin_tone\":\"7b938bc.svg\",\"man_farmer_tone3\":\"26600cd.svg\",\"man_farmer_medium_skin_tone\":\"26600cd.svg\",\"man_farmer_tone4\":\"4efb06d.svg\",\"man_farmer_medium_dark_skin_tone\":\"4efb06d.svg\",\"man_farmer_tone5\":\"6e76064.svg\",\"man_farmer_dark_skin_tone\":\"6e76064.svg\",\"cook\":\"a4a63f8.svg\",\"cook_tone1\":\"f8bd45b.svg\",\"cook_light_skin_tone\":\"f8bd45b.svg\",\"cook_tone2\":\"241bd68.svg\",\"cook_medium_light_skin_tone\":\"241bd68.svg\",\"cook_tone3\":\"9bff94a.svg\",\"cook_medium_skin_tone\":\"9bff94a.svg\",\"cook_tone4\":\"89acdc9.svg\",\"cook_medium_dark_skin_tone\":\"89acdc9.svg\",\"cook_tone5\":\"557f06f.svg\",\"cook_dark_skin_tone\":\"557f06f.svg\",\"woman_cook\":\"e164261.svg\",\"woman_cook_tone1\":\"4dd310d.svg\",\"woman_cook_light_skin_tone\":\"4dd310d.svg\",\"woman_cook_tone2\":\"dde8ca0.svg\",\"woman_cook_medium_light_skin_tone\":\"dde8ca0.svg\",\"woman_cook_tone3\":\"280c136.svg\",\"woman_cook_medium_skin_tone\":\"280c136.svg\",\"woman_cook_tone4\":\"1bad9d6.svg\",\"woman_cook_medium_dark_skin_tone\":\"1bad9d6.svg\",\"woman_cook_tone5\":\"a7d627f.svg\",\"woman_cook_dark_skin_tone\":\"a7d627f.svg\",\"man_cook\":\"3361675.svg\",\"man_cook_tone1\":\"ead2696.svg\",\"man_cook_light_skin_tone\":\"ead2696.svg\",\"man_cook_tone2\":\"e881854.svg\",\"man_cook_medium_light_skin_tone\":\"e881854.svg\",\"man_cook_tone3\":\"291f0e8.svg\",\"man_cook_medium_skin_tone\":\"291f0e8.svg\",\"man_cook_tone4\":\"a071615.svg\",\"man_cook_medium_dark_skin_tone\":\"a071615.svg\",\"man_cook_tone5\":\"bb826a2.svg\",\"man_cook_dark_skin_tone\":\"bb826a2.svg\",\"student\":\"0850b86.svg\",\"student_tone1\":\"13422e9.svg\",\"student_light_skin_tone\":\"13422e9.svg\",\"student_tone2\":\"9df70e3.svg\",\"student_medium_light_skin_tone\":\"9df70e3.svg\",\"student_tone3\":\"4abba29.svg\",\"student_medium_skin_tone\":\"4abba29.svg\",\"student_tone4\":\"29e7950.svg\",\"student_medium_dark_skin_tone\":\"29e7950.svg\",\"student_tone5\":\"334db35.svg\",\"student_dark_skin_tone\":\"334db35.svg\",\"woman_student\":\"d08ef82.svg\",\"woman_student_tone1\":\"22ca3f8.svg\",\"woman_student_light_skin_tone\":\"22ca3f8.svg\",\"woman_student_tone2\":\"c1ef510.svg\",\"woman_student_medium_light_skin_tone\":\"c1ef510.svg\",\"woman_student_tone3\":\"6d41fb5.svg\",\"woman_student_medium_skin_tone\":\"6d41fb5.svg\",\"woman_student_tone4\":\"66ab761.svg\",\"woman_student_medium_dark_skin_tone\":\"66ab761.svg\",\"woman_student_tone5\":\"e9fa0e7.svg\",\"woman_student_dark_skin_tone\":\"e9fa0e7.svg\",\"man_student\":\"12a1dd0.svg\",\"man_student_tone1\":\"b571bb8.svg\",\"man_student_light_skin_tone\":\"b571bb8.svg\",\"man_student_tone2\":\"afeb55d.svg\",\"man_student_medium_light_skin_tone\":\"afeb55d.svg\",\"man_student_tone3\":\"8362db4.svg\",\"man_student_medium_skin_tone\":\"8362db4.svg\",\"man_student_tone4\":\"642e769.svg\",\"man_student_medium_dark_skin_tone\":\"642e769.svg\",\"man_student_tone5\":\"ffdeacf.svg\",\"man_student_dark_skin_tone\":\"ffdeacf.svg\",\"singer\":\"1b13111.svg\",\"singer_tone1\":\"a2b97f0.svg\",\"singer_light_skin_tone\":\"a2b97f0.svg\",\"singer_tone2\":\"d278abb.svg\",\"singer_medium_light_skin_tone\":\"d278abb.svg\",\"singer_tone3\":\"447dbe5.svg\",\"singer_medium_skin_tone\":\"447dbe5.svg\",\"singer_tone4\":\"0857ac9.svg\",\"singer_medium_dark_skin_tone\":\"0857ac9.svg\",\"singer_tone5\":\"6cded83.svg\",\"singer_dark_skin_tone\":\"6cded83.svg\",\"woman_singer\":\"698a172.svg\",\"woman_singer_tone1\":\"5a06595.svg\",\"woman_singer_light_skin_tone\":\"5a06595.svg\",\"woman_singer_tone2\":\"5262515.svg\",\"woman_singer_medium_light_skin_tone\":\"5262515.svg\",\"woman_singer_tone3\":\"b68f63b.svg\",\"woman_singer_medium_skin_tone\":\"b68f63b.svg\",\"woman_singer_tone4\":\"d0b4e7a.svg\",\"woman_singer_medium_dark_skin_tone\":\"d0b4e7a.svg\",\"woman_singer_tone5\":\"fe5edce.svg\",\"woman_singer_dark_skin_tone\":\"fe5edce.svg\",\"man_singer\":\"8f9fa74.svg\",\"man_singer_tone1\":\"f25f21d.svg\",\"man_singer_light_skin_tone\":\"f25f21d.svg\",\"man_singer_tone2\":\"3375b10.svg\",\"man_singer_medium_light_skin_tone\":\"3375b10.svg\",\"man_singer_tone3\":\"aed9010.svg\",\"man_singer_medium_skin_tone\":\"aed9010.svg\",\"man_singer_tone4\":\"684e6dd.svg\",\"man_singer_medium_dark_skin_tone\":\"684e6dd.svg\",\"man_singer_tone5\":\"71eed43.svg\",\"man_singer_dark_skin_tone\":\"71eed43.svg\",\"teacher\":\"3f05ac8.svg\",\"teacher_tone1\":\"547622b.svg\",\"teacher_light_skin_tone\":\"547622b.svg\",\"teacher_tone2\":\"73dda57.svg\",\"teacher_medium_light_skin_tone\":\"73dda57.svg\",\"teacher_tone3\":\"d37c8c4.svg\",\"teacher_medium_skin_tone\":\"d37c8c4.svg\",\"teacher_tone4\":\"22b0ccd.svg\",\"teacher_medium_dark_skin_tone\":\"22b0ccd.svg\",\"teacher_tone5\":\"4c83bb0.svg\",\"teacher_dark_skin_tone\":\"4c83bb0.svg\",\"woman_teacher\":\"69ffebb.svg\",\"woman_teacher_tone1\":\"8a52eb0.svg\",\"woman_teacher_light_skin_tone\":\"8a52eb0.svg\",\"woman_teacher_tone2\":\"a5753b7.svg\",\"woman_teacher_medium_light_skin_tone\":\"a5753b7.svg\",\"woman_teacher_tone3\":\"2d95430.svg\",\"woman_teacher_medium_skin_tone\":\"2d95430.svg\",\"woman_teacher_tone4\":\"e816c4a.svg\",\"woman_teacher_medium_dark_skin_tone\":\"e816c4a.svg\",\"woman_teacher_tone5\":\"998dd7e.svg\",\"woman_teacher_dark_skin_tone\":\"998dd7e.svg\",\"man_teacher\":\"324b2b6.svg\",\"man_teacher_tone1\":\"8575f3e.svg\",\"man_teacher_light_skin_tone\":\"8575f3e.svg\",\"man_teacher_tone2\":\"90504c4.svg\",\"man_teacher_medium_light_skin_tone\":\"90504c4.svg\",\"man_teacher_tone3\":\"655137d.svg\",\"man_teacher_medium_skin_tone\":\"655137d.svg\",\"man_teacher_tone4\":\"0b1145e.svg\",\"man_teacher_medium_dark_skin_tone\":\"0b1145e.svg\",\"man_teacher_tone5\":\"28f1192.svg\",\"man_teacher_dark_skin_tone\":\"28f1192.svg\",\"factory_worker\":\"1022142.svg\",\"factory_worker_tone1\":\"edf101c.svg\",\"factory_worker_light_skin_tone\":\"edf101c.svg\",\"factory_worker_tone2\":\"281146d.svg\",\"factory_worker_medium_light_skin_tone\":\"281146d.svg\",\"factory_worker_tone3\":\"ec2df97.svg\",\"factory_worker_medium_skin_tone\":\"ec2df97.svg\",\"factory_worker_tone4\":\"88e3a63.svg\",\"factory_worker_medium_dark_skin_tone\":\"88e3a63.svg\",\"factory_worker_tone5\":\"b74d155.svg\",\"factory_worker_dark_skin_tone\":\"b74d155.svg\",\"woman_factory_worker\":\"d345c63.svg\",\"woman_factory_worker_tone1\":\"688bad2.svg\",\"woman_factory_worker_light_skin_tone\":\"688bad2.svg\",\"woman_factory_worker_tone2\":\"b9093a8.svg\",\"woman_factory_worker_medium_light_skin_tone\":\"b9093a8.svg\",\"woman_factory_worker_tone3\":\"5b07641.svg\",\"woman_factory_worker_medium_skin_tone\":\"5b07641.svg\",\"woman_factory_worker_tone4\":\"1016e81.svg\",\"woman_factory_worker_medium_dark_skin_tone\":\"1016e81.svg\",\"woman_factory_worker_tone5\":\"6b92c08.svg\",\"woman_factory_worker_dark_skin_tone\":\"6b92c08.svg\",\"man_factory_worker\":\"48e1ea2.svg\",\"man_factory_worker_tone1\":\"5a94900.svg\",\"man_factory_worker_light_skin_tone\":\"5a94900.svg\",\"man_factory_worker_tone2\":\"11a4f9e.svg\",\"man_factory_worker_medium_light_skin_tone\":\"11a4f9e.svg\",\"man_factory_worker_tone3\":\"dc7ee23.svg\",\"man_factory_worker_medium_skin_tone\":\"dc7ee23.svg\",\"man_factory_worker_tone4\":\"df07e07.svg\",\"man_factory_worker_medium_dark_skin_tone\":\"df07e07.svg\",\"man_factory_worker_tone5\":\"4b6bb27.svg\",\"man_factory_worker_dark_skin_tone\":\"4b6bb27.svg\",\"technologist\":\"180fac5.svg\",\"technologist_tone1\":\"e68839b.svg\",\"technologist_light_skin_tone\":\"e68839b.svg\",\"technologist_tone2\":\"4cc9d44.svg\",\"technologist_medium_light_skin_tone\":\"4cc9d44.svg\",\"technologist_tone3\":\"4475992.svg\",\"technologist_medium_skin_tone\":\"4475992.svg\",\"technologist_tone4\":\"c681683.svg\",\"technologist_medium_dark_skin_tone\":\"c681683.svg\",\"technologist_tone5\":\"328d629.svg\",\"technologist_dark_skin_tone\":\"328d629.svg\",\"woman_technologist\":\"96ff8eb.svg\",\"woman_technologist_tone1\":\"21d8aae.svg\",\"woman_technologist_light_skin_tone\":\"21d8aae.svg\",\"woman_technologist_tone2\":\"1cc6fb3.svg\",\"woman_technologist_medium_light_skin_tone\":\"1cc6fb3.svg\",\"woman_technologist_tone3\":\"ad8f99a.svg\",\"woman_technologist_medium_skin_tone\":\"ad8f99a.svg\",\"woman_technologist_tone4\":\"897cd9c.svg\",\"woman_technologist_medium_dark_skin_tone\":\"897cd9c.svg\",\"woman_technologist_tone5\":\"eeb6cd8.svg\",\"woman_technologist_dark_skin_tone\":\"eeb6cd8.svg\",\"man_technologist\":\"8e0d837.svg\",\"man_technologist_tone1\":\"7229031.svg\",\"man_technologist_light_skin_tone\":\"7229031.svg\",\"man_technologist_tone2\":\"adf0160.svg\",\"man_technologist_medium_light_skin_tone\":\"adf0160.svg\",\"man_technologist_tone3\":\"622261c.svg\",\"man_technologist_medium_skin_tone\":\"622261c.svg\",\"man_technologist_tone4\":\"0daf3e6.svg\",\"man_technologist_medium_dark_skin_tone\":\"0daf3e6.svg\",\"man_technologist_tone5\":\"6212e10.svg\",\"man_technologist_dark_skin_tone\":\"6212e10.svg\",\"office_worker\":\"6c1b458.svg\",\"office_worker_tone1\":\"c2d3f36.svg\",\"office_worker_light_skin_tone\":\"c2d3f36.svg\",\"office_worker_tone2\":\"552a453.svg\",\"office_worker_medium_light_skin_tone\":\"552a453.svg\",\"office_worker_tone3\":\"958ac28.svg\",\"office_worker_medium_skin_tone\":\"958ac28.svg\",\"office_worker_tone4\":\"e379783.svg\",\"office_worker_medium_dark_skin_tone\":\"e379783.svg\",\"office_worker_tone5\":\"80ce786.svg\",\"office_worker_dark_skin_tone\":\"80ce786.svg\",\"woman_office_worker\":\"489e529.svg\",\"woman_office_worker_tone1\":\"b94d93c.svg\",\"woman_office_worker_light_skin_tone\":\"b94d93c.svg\",\"woman_office_worker_tone2\":\"55d6ebc.svg\",\"woman_office_worker_medium_light_skin_tone\":\"55d6ebc.svg\",\"woman_office_worker_tone3\":\"9a3098d.svg\",\"woman_office_worker_medium_skin_tone\":\"9a3098d.svg\",\"woman_office_worker_tone4\":\"ecb8f66.svg\",\"woman_office_worker_medium_dark_skin_tone\":\"ecb8f66.svg\",\"woman_office_worker_tone5\":\"b1c480e.svg\",\"woman_office_worker_dark_skin_tone\":\"b1c480e.svg\",\"man_office_worker\":\"6c73696.svg\",\"man_office_worker_tone1\":\"0e9ee64.svg\",\"man_office_worker_light_skin_tone\":\"0e9ee64.svg\",\"man_office_worker_tone2\":\"5630728.svg\",\"man_office_worker_medium_light_skin_tone\":\"5630728.svg\",\"man_office_worker_tone3\":\"10ba092.svg\",\"man_office_worker_medium_skin_tone\":\"10ba092.svg\",\"man_office_worker_tone4\":\"d0d3184.svg\",\"man_office_worker_medium_dark_skin_tone\":\"d0d3184.svg\",\"man_office_worker_tone5\":\"f85801a.svg\",\"man_office_worker_dark_skin_tone\":\"f85801a.svg\",\"mechanic\":\"ee455f1.svg\",\"mechanic_tone1\":\"d5f36f6.svg\",\"mechanic_light_skin_tone\":\"d5f36f6.svg\",\"mechanic_tone2\":\"bd0d424.svg\",\"mechanic_medium_light_skin_tone\":\"bd0d424.svg\",\"mechanic_tone3\":\"4dcab11.svg\",\"mechanic_medium_skin_tone\":\"4dcab11.svg\",\"mechanic_tone4\":\"a79edc4.svg\",\"mechanic_medium_dark_skin_tone\":\"a79edc4.svg\",\"mechanic_tone5\":\"f515402.svg\",\"mechanic_dark_skin_tone\":\"f515402.svg\",\"woman_mechanic\":\"96e0809.svg\",\"woman_mechanic_tone1\":\"566d88c.svg\",\"woman_mechanic_light_skin_tone\":\"566d88c.svg\",\"woman_mechanic_tone2\":\"ba98536.svg\",\"woman_mechanic_medium_light_skin_tone\":\"ba98536.svg\",\"woman_mechanic_tone3\":\"0e01036.svg\",\"woman_mechanic_medium_skin_tone\":\"0e01036.svg\",\"woman_mechanic_tone4\":\"c03256d.svg\",\"woman_mechanic_medium_dark_skin_tone\":\"c03256d.svg\",\"woman_mechanic_tone5\":\"f03cd8b.svg\",\"woman_mechanic_dark_skin_tone\":\"f03cd8b.svg\",\"man_mechanic\":\"cc3ed09.svg\",\"man_mechanic_tone1\":\"d77dcc0.svg\",\"man_mechanic_light_skin_tone\":\"d77dcc0.svg\",\"man_mechanic_tone2\":\"69d531c.svg\",\"man_mechanic_medium_light_skin_tone\":\"69d531c.svg\",\"man_mechanic_tone3\":\"db68d58.svg\",\"man_mechanic_medium_skin_tone\":\"db68d58.svg\",\"man_mechanic_tone4\":\"d1987e9.svg\",\"man_mechanic_medium_dark_skin_tone\":\"d1987e9.svg\",\"man_mechanic_tone5\":\"79cbe87.svg\",\"man_mechanic_dark_skin_tone\":\"79cbe87.svg\",\"scientist\":\"dbdb85d.svg\",\"scientist_tone1\":\"33f3bf1.svg\",\"scientist_light_skin_tone\":\"33f3bf1.svg\",\"scientist_tone2\":\"2d086a8.svg\",\"scientist_medium_light_skin_tone\":\"2d086a8.svg\",\"scientist_tone3\":\"486400e.svg\",\"scientist_medium_skin_tone\":\"486400e.svg\",\"scientist_tone4\":\"c0c96cb.svg\",\"scientist_medium_dark_skin_tone\":\"c0c96cb.svg\",\"scientist_tone5\":\"30c16d5.svg\",\"scientist_dark_skin_tone\":\"30c16d5.svg\",\"woman_scientist\":\"1e38eed.svg\",\"woman_scientist_tone1\":\"440f076.svg\",\"woman_scientist_light_skin_tone\":\"440f076.svg\",\"woman_scientist_tone2\":\"066face.svg\",\"woman_scientist_medium_light_skin_tone\":\"066face.svg\",\"woman_scientist_tone3\":\"d2ea502.svg\",\"woman_scientist_medium_skin_tone\":\"d2ea502.svg\",\"woman_scientist_tone4\":\"4015482.svg\",\"woman_scientist_medium_dark_skin_tone\":\"4015482.svg\",\"woman_scientist_tone5\":\"d943ff4.svg\",\"woman_scientist_dark_skin_tone\":\"d943ff4.svg\",\"man_scientist\":\"10538bf.svg\",\"man_scientist_tone1\":\"96213db.svg\",\"man_scientist_light_skin_tone\":\"96213db.svg\",\"man_scientist_tone2\":\"f767abd.svg\",\"man_scientist_medium_light_skin_tone\":\"f767abd.svg\",\"man_scientist_tone3\":\"0a15702.svg\",\"man_scientist_medium_skin_tone\":\"0a15702.svg\",\"man_scientist_tone4\":\"9e2db11.svg\",\"man_scientist_medium_dark_skin_tone\":\"9e2db11.svg\",\"man_scientist_tone5\":\"36c67c1.svg\",\"man_scientist_dark_skin_tone\":\"36c67c1.svg\",\"artist\":\"cf51bad.svg\",\"artist_tone1\":\"2b58f09.svg\",\"artist_light_skin_tone\":\"2b58f09.svg\",\"artist_tone2\":\"e0ba0de.svg\",\"artist_medium_light_skin_tone\":\"e0ba0de.svg\",\"artist_tone3\":\"288c495.svg\",\"artist_medium_skin_tone\":\"288c495.svg\",\"artist_tone4\":\"c0ff43a.svg\",\"artist_medium_dark_skin_tone\":\"c0ff43a.svg\",\"artist_tone5\":\"c47a742.svg\",\"artist_dark_skin_tone\":\"c47a742.svg\",\"woman_artist\":\"c2e427e.svg\",\"woman_artist_tone1\":\"dff44c7.svg\",\"woman_artist_light_skin_tone\":\"dff44c7.svg\",\"woman_artist_tone2\":\"7fe9606.svg\",\"woman_artist_medium_light_skin_tone\":\"7fe9606.svg\",\"woman_artist_tone3\":\"7a50642.svg\",\"woman_artist_medium_skin_tone\":\"7a50642.svg\",\"woman_artist_tone4\":\"6da5ebe.svg\",\"woman_artist_medium_dark_skin_tone\":\"6da5ebe.svg\",\"woman_artist_tone5\":\"d504204.svg\",\"woman_artist_dark_skin_tone\":\"d504204.svg\",\"man_artist\":\"cfe2741.svg\",\"man_artist_tone1\":\"df98294.svg\",\"man_artist_light_skin_tone\":\"df98294.svg\",\"man_artist_tone2\":\"db34dc8.svg\",\"man_artist_medium_light_skin_tone\":\"db34dc8.svg\",\"man_artist_tone3\":\"7fa36cf.svg\",\"man_artist_medium_skin_tone\":\"7fa36cf.svg\",\"man_artist_tone4\":\"256b112.svg\",\"man_artist_medium_dark_skin_tone\":\"256b112.svg\",\"man_artist_tone5\":\"c7973d8.svg\",\"man_artist_dark_skin_tone\":\"c7973d8.svg\",\"firefighter\":\"8dab584.svg\",\"firefighter_tone1\":\"c5499b3.svg\",\"firefighter_light_skin_tone\":\"c5499b3.svg\",\"firefighter_tone2\":\"3850d1a.svg\",\"firefighter_medium_light_skin_tone\":\"3850d1a.svg\",\"firefighter_tone3\":\"ed6bc04.svg\",\"firefighter_medium_skin_tone\":\"ed6bc04.svg\",\"firefighter_tone4\":\"ea27ae9.svg\",\"firefighter_medium_dark_skin_tone\":\"ea27ae9.svg\",\"firefighter_tone5\":\"39a926b.svg\",\"firefighter_dark_skin_tone\":\"39a926b.svg\",\"woman_firefighter\":\"9be3bf6.svg\",\"woman_firefighter_tone1\":\"d6f34fb.svg\",\"woman_firefighter_light_skin_tone\":\"d6f34fb.svg\",\"woman_firefighter_tone2\":\"665a6d5.svg\",\"woman_firefighter_medium_light_skin_tone\":\"665a6d5.svg\",\"woman_firefighter_tone3\":\"f4d24e1.svg\",\"woman_firefighter_medium_skin_tone\":\"f4d24e1.svg\",\"woman_firefighter_tone4\":\"be5b501.svg\",\"woman_firefighter_medium_dark_skin_tone\":\"be5b501.svg\",\"woman_firefighter_tone5\":\"4ffb181.svg\",\"woman_firefighter_dark_skin_tone\":\"4ffb181.svg\",\"man_firefighter\":\"5615861.svg\",\"man_firefighter_tone1\":\"710e509.svg\",\"man_firefighter_light_skin_tone\":\"710e509.svg\",\"man_firefighter_tone2\":\"4217476.svg\",\"man_firefighter_medium_light_skin_tone\":\"4217476.svg\",\"man_firefighter_tone3\":\"b22debb.svg\",\"man_firefighter_medium_skin_tone\":\"b22debb.svg\",\"man_firefighter_tone4\":\"d8691e8.svg\",\"man_firefighter_medium_dark_skin_tone\":\"d8691e8.svg\",\"man_firefighter_tone5\":\"9cb1c1c.svg\",\"man_firefighter_dark_skin_tone\":\"9cb1c1c.svg\",\"pilot\":\"785704c.svg\",\"pilot_tone1\":\"148b717.svg\",\"pilot_light_skin_tone\":\"148b717.svg\",\"pilot_tone2\":\"950c47d.svg\",\"pilot_medium_light_skin_tone\":\"950c47d.svg\",\"pilot_tone3\":\"8fed0c6.svg\",\"pilot_medium_skin_tone\":\"8fed0c6.svg\",\"pilot_tone4\":\"5efa2e4.svg\",\"pilot_medium_dark_skin_tone\":\"5efa2e4.svg\",\"pilot_tone5\":\"be28d19.svg\",\"pilot_dark_skin_tone\":\"be28d19.svg\",\"woman_pilot\":\"8d6bd3b.svg\",\"woman_pilot_tone1\":\"0bba5fe.svg\",\"woman_pilot_light_skin_tone\":\"0bba5fe.svg\",\"woman_pilot_tone2\":\"2c0fbfe.svg\",\"woman_pilot_medium_light_skin_tone\":\"2c0fbfe.svg\",\"woman_pilot_tone3\":\"ced65e1.svg\",\"woman_pilot_medium_skin_tone\":\"ced65e1.svg\",\"woman_pilot_tone4\":\"5a10ba1.svg\",\"woman_pilot_medium_dark_skin_tone\":\"5a10ba1.svg\",\"woman_pilot_tone5\":\"8521720.svg\",\"woman_pilot_dark_skin_tone\":\"8521720.svg\",\"man_pilot\":\"f160e27.svg\",\"man_pilot_tone1\":\"5700642.svg\",\"man_pilot_light_skin_tone\":\"5700642.svg\",\"man_pilot_tone2\":\"a355e7a.svg\",\"man_pilot_medium_light_skin_tone\":\"a355e7a.svg\",\"man_pilot_tone3\":\"0aa1b01.svg\",\"man_pilot_medium_skin_tone\":\"0aa1b01.svg\",\"man_pilot_tone4\":\"7777935.svg\",\"man_pilot_medium_dark_skin_tone\":\"7777935.svg\",\"man_pilot_tone5\":\"eb6b0a5.svg\",\"man_pilot_dark_skin_tone\":\"eb6b0a5.svg\",\"astronaut\":\"8e3de15.svg\",\"astronaut_tone1\":\"1746690.svg\",\"astronaut_light_skin_tone\":\"1746690.svg\",\"astronaut_tone2\":\"acf8752.svg\",\"astronaut_medium_light_skin_tone\":\"acf8752.svg\",\"astronaut_tone3\":\"9ce3df2.svg\",\"astronaut_medium_skin_tone\":\"9ce3df2.svg\",\"astronaut_tone4\":\"6edf598.svg\",\"astronaut_medium_dark_skin_tone\":\"6edf598.svg\",\"astronaut_tone5\":\"b187089.svg\",\"astronaut_dark_skin_tone\":\"b187089.svg\",\"woman_astronaut\":\"e761b0a.svg\",\"woman_astronaut_tone1\":\"c9ca667.svg\",\"woman_astronaut_light_skin_tone\":\"c9ca667.svg\",\"woman_astronaut_tone2\":\"1357a9b.svg\",\"woman_astronaut_medium_light_skin_tone\":\"1357a9b.svg\",\"woman_astronaut_tone3\":\"96cac7d.svg\",\"woman_astronaut_medium_skin_tone\":\"96cac7d.svg\",\"woman_astronaut_tone4\":\"98c8131.svg\",\"woman_astronaut_medium_dark_skin_tone\":\"98c8131.svg\",\"woman_astronaut_tone5\":\"28f1de1.svg\",\"woman_astronaut_dark_skin_tone\":\"28f1de1.svg\",\"man_astronaut\":\"9808aa4.svg\",\"man_astronaut_tone1\":\"3fdecd6.svg\",\"man_astronaut_light_skin_tone\":\"3fdecd6.svg\",\"man_astronaut_tone2\":\"ad74c6f.svg\",\"man_astronaut_medium_light_skin_tone\":\"ad74c6f.svg\",\"man_astronaut_tone3\":\"fba65b3.svg\",\"man_astronaut_medium_skin_tone\":\"fba65b3.svg\",\"man_astronaut_tone4\":\"cc68f55.svg\",\"man_astronaut_medium_dark_skin_tone\":\"cc68f55.svg\",\"man_astronaut_tone5\":\"6638445.svg\",\"man_astronaut_dark_skin_tone\":\"6638445.svg\",\"judge\":\"64bc381.svg\",\"judge_tone1\":\"e6f6aa9.svg\",\"judge_light_skin_tone\":\"e6f6aa9.svg\",\"judge_tone2\":\"4ea5d96.svg\",\"judge_medium_light_skin_tone\":\"4ea5d96.svg\",\"judge_tone3\":\"91a587d.svg\",\"judge_medium_skin_tone\":\"91a587d.svg\",\"judge_tone4\":\"0491570.svg\",\"judge_medium_dark_skin_tone\":\"0491570.svg\",\"judge_tone5\":\"a959700.svg\",\"judge_dark_skin_tone\":\"a959700.svg\",\"woman_judge\":\"ccf4f4a.svg\",\"woman_judge_tone1\":\"1a4affd.svg\",\"woman_judge_light_skin_tone\":\"1a4affd.svg\",\"woman_judge_tone2\":\"68cda2e.svg\",\"woman_judge_medium_light_skin_tone\":\"68cda2e.svg\",\"woman_judge_tone3\":\"761a41e.svg\",\"woman_judge_medium_skin_tone\":\"761a41e.svg\",\"woman_judge_tone4\":\"91d0ae8.svg\",\"woman_judge_medium_dark_skin_tone\":\"91d0ae8.svg\",\"woman_judge_tone5\":\"47693f0.svg\",\"woman_judge_dark_skin_tone\":\"47693f0.svg\",\"man_judge\":\"54742de.svg\",\"man_judge_tone1\":\"d6fe135.svg\",\"man_judge_light_skin_tone\":\"d6fe135.svg\",\"man_judge_tone2\":\"98d25e6.svg\",\"man_judge_medium_light_skin_tone\":\"98d25e6.svg\",\"man_judge_tone3\":\"07877f2.svg\",\"man_judge_medium_skin_tone\":\"07877f2.svg\",\"man_judge_tone4\":\"b844d09.svg\",\"man_judge_medium_dark_skin_tone\":\"b844d09.svg\",\"man_judge_tone5\":\"3f3ba5b.svg\",\"man_judge_dark_skin_tone\":\"3f3ba5b.svg\",\"person_with_veil\":\"da48cb6.svg\",\"person_with_veil_tone1\":\"5f6784e.svg\",\"person_with_veil_tone2\":\"33d1769.svg\",\"person_with_veil_tone3\":\"378ca17.svg\",\"person_with_veil_tone4\":\"5b2ccf0.svg\",\"person_with_veil_tone5\":\"ad98ee6.svg\",\"woman_with_veil\":\"eef28b9.svg\",\"woman_with_veil_tone1\":\"6d6022c.svg\",\"woman_with_veil_light_skin_tone\":\"6d6022c.svg\",\"woman_with_veil_tone2\":\"befe93a.svg\",\"woman_with_veil_medium_light_skin_tone\":\"befe93a.svg\",\"woman_with_veil_tone3\":\"4831916.svg\",\"woman_with_veil_medium_skin_tone\":\"4831916.svg\",\"woman_with_veil_tone4\":\"a6c8373.svg\",\"woman_with_veil_medium_dark_skin_tone\":\"a6c8373.svg\",\"woman_with_veil_tone5\":\"e48a636.svg\",\"woman_with_veil_dark_skin_tone\":\"e48a636.svg\",\"man_with_veil\":\"af12168.svg\",\"man_with_veil_tone1\":\"bb62ddf.svg\",\"man_with_veil_light_skin_tone\":\"bb62ddf.svg\",\"man_with_veil_tone2\":\"3c6240d.svg\",\"man_with_veil_medium_light_skin_tone\":\"3c6240d.svg\",\"man_with_veil_tone3\":\"cee8ac2.svg\",\"man_with_veil_medium_skin_tone\":\"cee8ac2.svg\",\"man_with_veil_tone4\":\"2eccab7.svg\",\"man_with_veil_medium_dark_skin_tone\":\"2eccab7.svg\",\"man_with_veil_tone5\":\"03e1c14.svg\",\"man_with_veil_dark_skin_tone\":\"03e1c14.svg\",\"person_in_tuxedo\":\"ce76b6f.svg\",\"person_in_tuxedo_tone1\":\"02ac1d5.svg\",\"tuxedo_tone1\":\"02ac1d5.svg\",\"person_in_tuxedo_tone2\":\"6c6a785.svg\",\"tuxedo_tone2\":\"6c6a785.svg\",\"person_in_tuxedo_tone3\":\"102177c.svg\",\"tuxedo_tone3\":\"102177c.svg\",\"person_in_tuxedo_tone4\":\"de81b72.svg\",\"tuxedo_tone4\":\"de81b72.svg\",\"person_in_tuxedo_tone5\":\"4f9a016.svg\",\"tuxedo_tone5\":\"4f9a016.svg\",\"woman_in_tuxedo\":\"1b4c556.svg\",\"woman_in_tuxedo_tone1\":\"aebb06c.svg\",\"woman_in_tuxedo_light_skin_tone\":\"aebb06c.svg\",\"woman_in_tuxedo_tone2\":\"d4f9c94.svg\",\"woman_in_tuxedo_medium_light_skin_tone\":\"d4f9c94.svg\",\"woman_in_tuxedo_tone3\":\"fc516a4.svg\",\"woman_in_tuxedo_medium_skin_tone\":\"fc516a4.svg\",\"woman_in_tuxedo_tone4\":\"783e4d6.svg\",\"woman_in_tuxedo_medium_dark_skin_tone\":\"783e4d6.svg\",\"woman_in_tuxedo_tone5\":\"184b3ea.svg\",\"woman_in_tuxedo_dark_skin_tone\":\"184b3ea.svg\",\"man_in_tuxedo\":\"e36ceab.svg\",\"man_in_tuxedo_tone1\":\"e499807.svg\",\"man_in_tuxedo_light_skin_tone\":\"e499807.svg\",\"man_in_tuxedo_tone2\":\"98e1f5a.svg\",\"man_in_tuxedo_medium_light_skin_tone\":\"98e1f5a.svg\",\"man_in_tuxedo_tone3\":\"b2a0f7f.svg\",\"man_in_tuxedo_medium_skin_tone\":\"b2a0f7f.svg\",\"man_in_tuxedo_tone4\":\"ee694bc.svg\",\"man_in_tuxedo_medium_dark_skin_tone\":\"ee694bc.svg\",\"man_in_tuxedo_tone5\":\"088b13d.svg\",\"man_in_tuxedo_dark_skin_tone\":\"088b13d.svg\",\"person_with_crown\":\"3051fdf.svg\",\"person_with_crown_tone1\":\"5d0e4d1.svg\",\"person_with_crown_light_skin_tone\":\"5d0e4d1.svg\",\"person_with_crown_tone2\":\"9fd5bed.svg\",\"person_with_crown_medium_light_skin_tone\":\"9fd5bed.svg\",\"person_with_crown_tone3\":\"721e07b.svg\",\"person_with_crown_medium_skin_tone\":\"721e07b.svg\",\"person_with_crown_tone4\":\"6e75772.svg\",\"person_with_crown_medium_dark_skin_tone\":\"6e75772.svg\",\"person_with_crown_tone5\":\"1adf78a.svg\",\"person_with_crown_dark_skin_tone\":\"1adf78a.svg\",\"princess\":\"aaff7f9.svg\",\"princess_tone1\":\"38e308a.svg\",\"princess_tone2\":\"f71896c.svg\",\"princess_tone3\":\"67a69cf.svg\",\"princess_tone4\":\"93458e2.svg\",\"princess_tone5\":\"3875fb5.svg\",\"prince\":\"9134687.svg\",\"prince_tone1\":\"d82092a.svg\",\"prince_tone2\":\"84b86f2.svg\",\"prince_tone3\":\"e91494a.svg\",\"prince_tone4\":\"bbe3e3d.svg\",\"prince_tone5\":\"c67979c.svg\",\"superhero\":\"2a7cb83.svg\",\"superhero_tone1\":\"2a281d0.svg\",\"superhero_light_skin_tone\":\"2a281d0.svg\",\"superhero_tone2\":\"be8b52a.svg\",\"superhero_medium_light_skin_tone\":\"be8b52a.svg\",\"superhero_tone3\":\"84e7eff.svg\",\"superhero_medium_skin_tone\":\"84e7eff.svg\",\"superhero_tone4\":\"fb4d597.svg\",\"superhero_medium_dark_skin_tone\":\"fb4d597.svg\",\"superhero_tone5\":\"2dcafca.svg\",\"superhero_dark_skin_tone\":\"2dcafca.svg\",\"woman_superhero\":\"5f6874f.svg\",\"woman_superhero_tone1\":\"bfa062e.svg\",\"woman_superhero_light_skin_tone\":\"bfa062e.svg\",\"woman_superhero_tone2\":\"01ee993.svg\",\"woman_superhero_medium_light_skin_tone\":\"01ee993.svg\",\"woman_superhero_tone3\":\"b85e3bb.svg\",\"woman_superhero_medium_skin_tone\":\"b85e3bb.svg\",\"woman_superhero_tone4\":\"530fa21.svg\",\"woman_superhero_medium_dark_skin_tone\":\"530fa21.svg\",\"woman_superhero_tone5\":\"3d099c0.svg\",\"woman_superhero_dark_skin_tone\":\"3d099c0.svg\",\"man_superhero\":\"3d31512.svg\",\"man_superhero_tone1\":\"4bb6671.svg\",\"man_superhero_light_skin_tone\":\"4bb6671.svg\",\"man_superhero_tone2\":\"a3d233c.svg\",\"man_superhero_medium_light_skin_tone\":\"a3d233c.svg\",\"man_superhero_tone3\":\"a32fc96.svg\",\"man_superhero_medium_skin_tone\":\"a32fc96.svg\",\"man_superhero_tone4\":\"715306d.svg\",\"man_superhero_medium_dark_skin_tone\":\"715306d.svg\",\"man_superhero_tone5\":\"d1e46ec.svg\",\"man_superhero_dark_skin_tone\":\"d1e46ec.svg\",\"supervillain\":\"47d4ea8.svg\",\"supervillain_tone1\":\"68926de.svg\",\"supervillain_light_skin_tone\":\"68926de.svg\",\"supervillain_tone2\":\"08b55bb.svg\",\"supervillain_medium_light_skin_tone\":\"08b55bb.svg\",\"supervillain_tone3\":\"d5258a0.svg\",\"supervillain_medium_skin_tone\":\"d5258a0.svg\",\"supervillain_tone4\":\"9d0e6a0.svg\",\"supervillain_medium_dark_skin_tone\":\"9d0e6a0.svg\",\"supervillain_tone5\":\"f7a5251.svg\",\"supervillain_dark_skin_tone\":\"f7a5251.svg\",\"woman_supervillain\":\"f98a12a.svg\",\"woman_supervillain_tone1\":\"0ea6f73.svg\",\"woman_supervillain_light_skin_tone\":\"0ea6f73.svg\",\"woman_supervillain_tone2\":\"42bc4a0.svg\",\"woman_supervillain_medium_light_skin_tone\":\"42bc4a0.svg\",\"woman_supervillain_tone3\":\"acc45b1.svg\",\"woman_supervillain_medium_skin_tone\":\"acc45b1.svg\",\"woman_supervillain_tone4\":\"547f08b.svg\",\"woman_supervillain_medium_dark_skin_tone\":\"547f08b.svg\",\"woman_supervillain_tone5\":\"26d4e57.svg\",\"woman_supervillain_dark_skin_tone\":\"26d4e57.svg\",\"man_supervillain\":\"94811ca.svg\",\"man_supervillain_tone1\":\"7d8c99e.svg\",\"man_supervillain_light_skin_tone\":\"7d8c99e.svg\",\"man_supervillain_tone2\":\"d01d27c.svg\",\"man_supervillain_medium_light_skin_tone\":\"d01d27c.svg\",\"man_supervillain_tone3\":\"e4707e4.svg\",\"man_supervillain_medium_skin_tone\":\"e4707e4.svg\",\"man_supervillain_tone4\":\"7704ce8.svg\",\"man_supervillain_medium_dark_skin_tone\":\"7704ce8.svg\",\"man_supervillain_tone5\":\"68ae7ed.svg\",\"man_supervillain_dark_skin_tone\":\"68ae7ed.svg\",\"ninja\":\"d001f14.svg\",\"ninja_tone1\":\"f86f7d0.svg\",\"ninja_light_skin_tone\":\"f86f7d0.svg\",\"ninja_tone2\":\"6b1255b.svg\",\"ninja_medium_light_skin_tone\":\"6b1255b.svg\",\"ninja_tone3\":\"1753fa5.svg\",\"ninja_medium_skin_tone\":\"1753fa5.svg\",\"ninja_tone4\":\"2fbc364.svg\",\"ninja_medium_dark_skin_tone\":\"2fbc364.svg\",\"ninja_tone5\":\"ab7ffad.svg\",\"ninja_dark_skin_tone\":\"ab7ffad.svg\",\"mx_claus\":\"a43f217.svg\",\"mx_claus_tone1\":\"a87d0a4.svg\",\"mx_claus_light_skin_tone\":\"a87d0a4.svg\",\"mx_claus_tone2\":\"2fbb54d.svg\",\"mx_claus_medium_light_skin_tone\":\"2fbb54d.svg\",\"mx_claus_tone3\":\"dab90e3.svg\",\"mx_claus_medium_skin_tone\":\"dab90e3.svg\",\"mx_claus_tone4\":\"1f91eef.svg\",\"mx_claus_medium_dark_skin_tone\":\"1f91eef.svg\",\"mx_claus_tone5\":\"6eb0eda.svg\",\"mx_claus_dark_skin_tone\":\"6eb0eda.svg\",\"mrs_claus\":\"6fbfdf1.svg\",\"mother_christmas\":\"6fbfdf1.svg\",\"mrs_claus_tone1\":\"78605ec.svg\",\"mother_christmas_tone1\":\"78605ec.svg\",\"mrs_claus_tone2\":\"402cdef.svg\",\"mother_christmas_tone2\":\"402cdef.svg\",\"mrs_claus_tone3\":\"f00b9d1.svg\",\"mother_christmas_tone3\":\"f00b9d1.svg\",\"mrs_claus_tone4\":\"6f2ec41.svg\",\"mother_christmas_tone4\":\"6f2ec41.svg\",\"mrs_claus_tone5\":\"65fc4ad.svg\",\"mother_christmas_tone5\":\"65fc4ad.svg\",\"santa\":\"3c0da1a.svg\",\"santa_claus\":\"3c0da1a.svg\",\"santa_tone1\":\"515eeb5.svg\",\"santa_tone2\":\"8efe1a2.svg\",\"santa_tone3\":\"bf4fd7b.svg\",\"santa_tone4\":\"80f1e35.svg\",\"santa_tone5\":\"3fcedda.svg\",\"mage\":\"35c7dd0.svg\",\"mage_tone1\":\"1e804b7.svg\",\"mage_light_skin_tone\":\"1e804b7.svg\",\"mage_tone2\":\"cf5a715.svg\",\"mage_medium_light_skin_tone\":\"cf5a715.svg\",\"mage_tone3\":\"28c4572.svg\",\"mage_medium_skin_tone\":\"28c4572.svg\",\"mage_tone4\":\"f77ab6f.svg\",\"mage_medium_dark_skin_tone\":\"f77ab6f.svg\",\"mage_tone5\":\"ece463d.svg\",\"mage_dark_skin_tone\":\"ece463d.svg\",\"woman_mage\":\"e04c248.svg\",\"woman_mage_tone1\":\"e0aa54d.svg\",\"woman_mage_light_skin_tone\":\"e0aa54d.svg\",\"woman_mage_tone2\":\"108feae.svg\",\"woman_mage_medium_light_skin_tone\":\"108feae.svg\",\"woman_mage_tone3\":\"7338a57.svg\",\"woman_mage_medium_skin_tone\":\"7338a57.svg\",\"woman_mage_tone4\":\"8585330.svg\",\"woman_mage_medium_dark_skin_tone\":\"8585330.svg\",\"woman_mage_tone5\":\"bbf1ed6.svg\",\"woman_mage_dark_skin_tone\":\"bbf1ed6.svg\",\"man_mage\":\"bfbfcda.svg\",\"man_mage_tone1\":\"fb1d8a3.svg\",\"man_mage_light_skin_tone\":\"fb1d8a3.svg\",\"man_mage_tone2\":\"510b86b.svg\",\"man_mage_medium_light_skin_tone\":\"510b86b.svg\",\"man_mage_tone3\":\"970876e.svg\",\"man_mage_medium_skin_tone\":\"970876e.svg\",\"man_mage_tone4\":\"dd2878a.svg\",\"man_mage_medium_dark_skin_tone\":\"dd2878a.svg\",\"man_mage_tone5\":\"c8cd380.svg\",\"man_mage_dark_skin_tone\":\"c8cd380.svg\",\"elf\":\"51f107b.svg\",\"elf_tone1\":\"fdd331a.svg\",\"elf_light_skin_tone\":\"fdd331a.svg\",\"elf_tone2\":\"9e14b16.svg\",\"elf_medium_light_skin_tone\":\"9e14b16.svg\",\"elf_tone3\":\"188b33c.svg\",\"elf_medium_skin_tone\":\"188b33c.svg\",\"elf_tone4\":\"0fc6b11.svg\",\"elf_medium_dark_skin_tone\":\"0fc6b11.svg\",\"elf_tone5\":\"208e35d.svg\",\"elf_dark_skin_tone\":\"208e35d.svg\",\"woman_elf\":\"019283b.svg\",\"woman_elf_tone1\":\"e3efdd8.svg\",\"woman_elf_light_skin_tone\":\"e3efdd8.svg\",\"woman_elf_tone2\":\"a45cfcf.svg\",\"woman_elf_medium_light_skin_tone\":\"a45cfcf.svg\",\"woman_elf_tone3\":\"b17534c.svg\",\"woman_elf_medium_skin_tone\":\"b17534c.svg\",\"woman_elf_tone4\":\"9512c8c.svg\",\"woman_elf_medium_dark_skin_tone\":\"9512c8c.svg\",\"woman_elf_tone5\":\"e8679cd.svg\",\"woman_elf_dark_skin_tone\":\"e8679cd.svg\",\"man_elf\":\"6e524c0.svg\",\"man_elf_tone1\":\"c3764a0.svg\",\"man_elf_light_skin_tone\":\"c3764a0.svg\",\"man_elf_tone2\":\"270bc04.svg\",\"man_elf_medium_light_skin_tone\":\"270bc04.svg\",\"man_elf_tone3\":\"040e78f.svg\",\"man_elf_medium_skin_tone\":\"040e78f.svg\",\"man_elf_tone4\":\"6086303.svg\",\"man_elf_medium_dark_skin_tone\":\"6086303.svg\",\"man_elf_tone5\":\"54d0c8e.svg\",\"man_elf_dark_skin_tone\":\"54d0c8e.svg\",\"troll\":\"229b6bb.svg\",\"vampire\":\"c9240be.svg\",\"vampire_tone1\":\"6a5176b.svg\",\"vampire_light_skin_tone\":\"6a5176b.svg\",\"vampire_tone2\":\"8bebc78.svg\",\"vampire_medium_light_skin_tone\":\"8bebc78.svg\",\"vampire_tone3\":\"eee994b.svg\",\"vampire_medium_skin_tone\":\"eee994b.svg\",\"vampire_tone4\":\"49b8038.svg\",\"vampire_medium_dark_skin_tone\":\"49b8038.svg\",\"vampire_tone5\":\"dfe56c1.svg\",\"vampire_dark_skin_tone\":\"dfe56c1.svg\",\"woman_vampire\":\"b2881b5.svg\",\"woman_vampire_tone1\":\"40eb1fd.svg\",\"woman_vampire_light_skin_tone\":\"40eb1fd.svg\",\"woman_vampire_tone2\":\"ab33484.svg\",\"woman_vampire_medium_light_skin_tone\":\"ab33484.svg\",\"woman_vampire_tone3\":\"3b5dffd.svg\",\"woman_vampire_medium_skin_tone\":\"3b5dffd.svg\",\"woman_vampire_tone4\":\"48059df.svg\",\"woman_vampire_medium_dark_skin_tone\":\"48059df.svg\",\"woman_vampire_tone5\":\"d138a43.svg\",\"woman_vampire_dark_skin_tone\":\"d138a43.svg\",\"man_vampire\":\"ee43274.svg\",\"man_vampire_tone1\":\"7cc2814.svg\",\"man_vampire_light_skin_tone\":\"7cc2814.svg\",\"man_vampire_tone2\":\"2e4f9c0.svg\",\"man_vampire_medium_light_skin_tone\":\"2e4f9c0.svg\",\"man_vampire_tone3\":\"7e1bef4.svg\",\"man_vampire_medium_skin_tone\":\"7e1bef4.svg\",\"man_vampire_tone4\":\"8ad9939.svg\",\"man_vampire_medium_dark_skin_tone\":\"8ad9939.svg\",\"man_vampire_tone5\":\"89f48be.svg\",\"man_vampire_dark_skin_tone\":\"89f48be.svg\",\"zombie\":\"9b3de1a.svg\",\"woman_zombie\":\"c5dc304.svg\",\"man_zombie\":\"e4cbd08.svg\",\"genie\":\"52125d5.svg\",\"woman_genie\":\"8a99bd6.svg\",\"man_genie\":\"362805a.svg\",\"merperson\":\"12f1a80.svg\",\"merperson_tone1\":\"8d5ab2b.svg\",\"merperson_light_skin_tone\":\"8d5ab2b.svg\",\"merperson_tone2\":\"f1dc516.svg\",\"merperson_medium_light_skin_tone\":\"f1dc516.svg\",\"merperson_tone3\":\"cba0642.svg\",\"merperson_medium_skin_tone\":\"cba0642.svg\",\"merperson_tone4\":\"54e94f4.svg\",\"merperson_medium_dark_skin_tone\":\"54e94f4.svg\",\"merperson_tone5\":\"d7827d6.svg\",\"merperson_dark_skin_tone\":\"d7827d6.svg\",\"mermaid\":\"26e0101.svg\",\"mermaid_tone1\":\"5f74ea7.svg\",\"mermaid_light_skin_tone\":\"5f74ea7.svg\",\"mermaid_tone2\":\"0b92906.svg\",\"mermaid_medium_light_skin_tone\":\"0b92906.svg\",\"mermaid_tone3\":\"c9ea451.svg\",\"mermaid_medium_skin_tone\":\"c9ea451.svg\",\"mermaid_tone4\":\"34dba67.svg\",\"mermaid_medium_dark_skin_tone\":\"34dba67.svg\",\"mermaid_tone5\":\"27d982b.svg\",\"mermaid_dark_skin_tone\":\"27d982b.svg\",\"merman\":\"d490d90.svg\",\"merman_tone1\":\"48e7845.svg\",\"merman_light_skin_tone\":\"48e7845.svg\",\"merman_tone2\":\"c5af351.svg\",\"merman_medium_light_skin_tone\":\"c5af351.svg\",\"merman_tone3\":\"069e1f8.svg\",\"merman_medium_skin_tone\":\"069e1f8.svg\",\"merman_tone4\":\"f499b89.svg\",\"merman_medium_dark_skin_tone\":\"f499b89.svg\",\"merman_tone5\":\"52d49c0.svg\",\"merman_dark_skin_tone\":\"52d49c0.svg\",\"fairy\":\"f58e1ca.svg\",\"fairy_tone1\":\"d96091c.svg\",\"fairy_light_skin_tone\":\"d96091c.svg\",\"fairy_tone2\":\"b5a4373.svg\",\"fairy_medium_light_skin_tone\":\"b5a4373.svg\",\"fairy_tone3\":\"19d1f2e.svg\",\"fairy_medium_skin_tone\":\"19d1f2e.svg\",\"fairy_tone4\":\"1342420.svg\",\"fairy_medium_dark_skin_tone\":\"1342420.svg\",\"fairy_tone5\":\"dd5e22f.svg\",\"fairy_dark_skin_tone\":\"dd5e22f.svg\",\"woman_fairy\":\"ebcceac.svg\",\"woman_fairy_tone1\":\"ecf7c6d.svg\",\"woman_fairy_light_skin_tone\":\"ecf7c6d.svg\",\"woman_fairy_tone2\":\"d9e7ef5.svg\",\"woman_fairy_medium_light_skin_tone\":\"d9e7ef5.svg\",\"woman_fairy_tone3\":\"2e1c1af.svg\",\"woman_fairy_medium_skin_tone\":\"2e1c1af.svg\",\"woman_fairy_tone4\":\"89c9eb1.svg\",\"woman_fairy_medium_dark_skin_tone\":\"89c9eb1.svg\",\"woman_fairy_tone5\":\"5f3d231.svg\",\"woman_fairy_dark_skin_tone\":\"5f3d231.svg\",\"man_fairy\":\"c0ad896.svg\",\"man_fairy_tone1\":\"4980f30.svg\",\"man_fairy_light_skin_tone\":\"4980f30.svg\",\"man_fairy_tone2\":\"ee3cd49.svg\",\"man_fairy_medium_light_skin_tone\":\"ee3cd49.svg\",\"man_fairy_tone3\":\"fa2f069.svg\",\"man_fairy_medium_skin_tone\":\"fa2f069.svg\",\"man_fairy_tone4\":\"0fc2831.svg\",\"man_fairy_medium_dark_skin_tone\":\"0fc2831.svg\",\"man_fairy_tone5\":\"539d458.svg\",\"man_fairy_dark_skin_tone\":\"539d458.svg\",\"angel\":\"b3387d6.svg\",\"baby_angel\":\"b3387d6.svg\",\"angel_tone1\":\"239a32d.svg\",\"angel_tone2\":\"07baf5d.svg\",\"angel_tone3\":\"6a489bf.svg\",\"angel_tone4\":\"fd27a77.svg\",\"angel_tone5\":\"ec08846.svg\",\"pregnant_person\":\"92b367c.svg\",\"pregnant_person_tone1\":\"466de37.svg\",\"pregnant_person_light_skin_tone\":\"466de37.svg\",\"pregnant_person_tone2\":\"f032ead.svg\",\"pregnant_person_medium_light_skin_tone\":\"f032ead.svg\",\"pregnant_person_tone3\":\"6285b37.svg\",\"pregnant_person_medium_skin_tone\":\"6285b37.svg\",\"pregnant_person_tone4\":\"9135282.svg\",\"pregnant_person_medium_dark_skin_tone\":\"9135282.svg\",\"pregnant_person_tone5\":\"a32420e.svg\",\"pregnant_person_dark_skin_tone\":\"a32420e.svg\",\"pregnant_woman\":\"ef4c944.svg\",\"expecting_woman\":\"ef4c944.svg\",\"pregnant_woman_tone1\":\"224a2f2.svg\",\"expecting_woman_tone1\":\"224a2f2.svg\",\"pregnant_woman_tone2\":\"9682714.svg\",\"expecting_woman_tone2\":\"9682714.svg\",\"pregnant_woman_tone3\":\"1f068a5.svg\",\"expecting_woman_tone3\":\"1f068a5.svg\",\"pregnant_woman_tone4\":\"cf94942.svg\",\"expecting_woman_tone4\":\"cf94942.svg\",\"pregnant_woman_tone5\":\"7a6a689.svg\",\"expecting_woman_tone5\":\"7a6a689.svg\",\"pregnant_man\":\"d2ae49d.svg\",\"pregnant_man_tone1\":\"71a04cd.svg\",\"pregnant_man_light_skin_tone\":\"71a04cd.svg\",\"pregnant_man_tone2\":\"4ba6c48.svg\",\"pregnant_man_medium_light_skin_tone\":\"4ba6c48.svg\",\"pregnant_man_tone3\":\"7f3cc27.svg\",\"pregnant_man_medium_skin_tone\":\"7f3cc27.svg\",\"pregnant_man_tone4\":\"f38a33d.svg\",\"pregnant_man_medium_dark_skin_tone\":\"f38a33d.svg\",\"pregnant_man_tone5\":\"47131d4.svg\",\"pregnant_man_dark_skin_tone\":\"47131d4.svg\",\"breast_feeding\":\"2b10008.svg\",\"breast_feeding_tone1\":\"a439669.svg\",\"breast_feeding_light_skin_tone\":\"a439669.svg\",\"breast_feeding_tone2\":\"796ac62.svg\",\"breast_feeding_medium_light_skin_tone\":\"796ac62.svg\",\"breast_feeding_tone3\":\"96d180c.svg\",\"breast_feeding_medium_skin_tone\":\"96d180c.svg\",\"breast_feeding_tone4\":\"32e8140.svg\",\"breast_feeding_medium_dark_skin_tone\":\"32e8140.svg\",\"breast_feeding_tone5\":\"2bfc6f2.svg\",\"breast_feeding_dark_skin_tone\":\"2bfc6f2.svg\",\"person_feeding_baby\":\"af1bc07.svg\",\"person_feeding_baby_tone1\":\"3db7608.svg\",\"person_feeding_baby_light_skin_tone\":\"3db7608.svg\",\"person_feeding_baby_tone2\":\"7936480.svg\",\"person_feeding_baby_medium_light_skin_tone\":\"7936480.svg\",\"person_feeding_baby_tone3\":\"e977a1d.svg\",\"person_feeding_baby_medium_skin_tone\":\"e977a1d.svg\",\"person_feeding_baby_tone4\":\"ba074f2.svg\",\"person_feeding_baby_medium_dark_skin_tone\":\"ba074f2.svg\",\"person_feeding_baby_tone5\":\"72ee126.svg\",\"person_feeding_baby_dark_skin_tone\":\"72ee126.svg\",\"woman_feeding_baby\":\"9a6693c.svg\",\"woman_feeding_baby_tone1\":\"a3164cc.svg\",\"woman_feeding_baby_light_skin_tone\":\"a3164cc.svg\",\"woman_feeding_baby_tone2\":\"875b4e4.svg\",\"woman_feeding_baby_medium_light_skin_tone\":\"875b4e4.svg\",\"woman_feeding_baby_tone3\":\"4e937ef.svg\",\"woman_feeding_baby_medium_skin_tone\":\"4e937ef.svg\",\"woman_feeding_baby_tone4\":\"711191e.svg\",\"woman_feeding_baby_medium_dark_skin_tone\":\"711191e.svg\",\"woman_feeding_baby_tone5\":\"5e0cf66.svg\",\"woman_feeding_baby_dark_skin_tone\":\"5e0cf66.svg\",\"man_feeding_baby\":\"1d1792e.svg\",\"man_feeding_baby_tone1\":\"879bb6c.svg\",\"man_feeding_baby_light_skin_tone\":\"879bb6c.svg\",\"man_feeding_baby_tone2\":\"84656da.svg\",\"man_feeding_baby_medium_light_skin_tone\":\"84656da.svg\",\"man_feeding_baby_tone3\":\"dc9847b.svg\",\"man_feeding_baby_medium_skin_tone\":\"dc9847b.svg\",\"man_feeding_baby_tone4\":\"3b82610.svg\",\"man_feeding_baby_medium_dark_skin_tone\":\"3b82610.svg\",\"man_feeding_baby_tone5\":\"49de399.svg\",\"man_feeding_baby_dark_skin_tone\":\"49de399.svg\",\"person_bowing\":\"c941147.svg\",\"bow\":\"c941147.svg\",\"person_bowing_tone1\":\"4f54e38.svg\",\"bow_tone1\":\"4f54e38.svg\",\"person_bowing_tone2\":\"b97c8e5.svg\",\"bow_tone2\":\"b97c8e5.svg\",\"person_bowing_tone3\":\"7821a37.svg\",\"bow_tone3\":\"7821a37.svg\",\"person_bowing_tone4\":\"840d2d8.svg\",\"bow_tone4\":\"840d2d8.svg\",\"person_bowing_tone5\":\"b701817.svg\",\"bow_tone5\":\"b701817.svg\",\"woman_bowing\":\"f2660f4.svg\",\"woman_bowing_tone1\":\"21bb2a0.svg\",\"woman_bowing_light_skin_tone\":\"21bb2a0.svg\",\"woman_bowing_tone2\":\"78d96e1.svg\",\"woman_bowing_medium_light_skin_tone\":\"78d96e1.svg\",\"woman_bowing_tone3\":\"e851e7f.svg\",\"woman_bowing_medium_skin_tone\":\"e851e7f.svg\",\"woman_bowing_tone4\":\"19435af.svg\",\"woman_bowing_medium_dark_skin_tone\":\"19435af.svg\",\"woman_bowing_tone5\":\"227b2bc.svg\",\"woman_bowing_dark_skin_tone\":\"227b2bc.svg\",\"man_bowing\":\"9417936.svg\",\"man_bowing_tone1\":\"4a24679.svg\",\"man_bowing_light_skin_tone\":\"4a24679.svg\",\"man_bowing_tone2\":\"8b945bc.svg\",\"man_bowing_medium_light_skin_tone\":\"8b945bc.svg\",\"man_bowing_tone3\":\"c1fd4c8.svg\",\"man_bowing_medium_skin_tone\":\"c1fd4c8.svg\",\"man_bowing_tone4\":\"a82718c.svg\",\"man_bowing_medium_dark_skin_tone\":\"a82718c.svg\",\"man_bowing_tone5\":\"550eec8.svg\",\"man_bowing_dark_skin_tone\":\"550eec8.svg\",\"person_tipping_hand\":\"9ff61cb.svg\",\"information_desk_person\":\"9ff61cb.svg\",\"person_tipping_hand_tone1\":\"91b9440.svg\",\"information_desk_person_tone1\":\"91b9440.svg\",\"person_tipping_hand_tone2\":\"4bb5ba9.svg\",\"information_desk_person_tone2\":\"4bb5ba9.svg\",\"person_tipping_hand_tone3\":\"2bcf099.svg\",\"information_desk_person_tone3\":\"2bcf099.svg\",\"person_tipping_hand_tone4\":\"1e8e06f.svg\",\"information_desk_person_tone4\":\"1e8e06f.svg\",\"person_tipping_hand_tone5\":\"9272072.svg\",\"information_desk_person_tone5\":\"9272072.svg\",\"woman_tipping_hand\":\"c94f989.svg\",\"woman_tipping_hand_tone1\":\"b326225.svg\",\"woman_tipping_hand_light_skin_tone\":\"b326225.svg\",\"woman_tipping_hand_tone2\":\"1a1afc4.svg\",\"woman_tipping_hand_medium_light_skin_tone\":\"1a1afc4.svg\",\"woman_tipping_hand_tone3\":\"58f6da9.svg\",\"woman_tipping_hand_medium_skin_tone\":\"58f6da9.svg\",\"woman_tipping_hand_tone4\":\"2c50ea8.svg\",\"woman_tipping_hand_medium_dark_skin_tone\":\"2c50ea8.svg\",\"woman_tipping_hand_tone5\":\"8090582.svg\",\"woman_tipping_hand_dark_skin_tone\":\"8090582.svg\",\"man_tipping_hand\":\"df0ef8e.svg\",\"man_tipping_hand_tone1\":\"a7fe8d2.svg\",\"man_tipping_hand_light_skin_tone\":\"a7fe8d2.svg\",\"man_tipping_hand_tone2\":\"4e72ec9.svg\",\"man_tipping_hand_medium_light_skin_tone\":\"4e72ec9.svg\",\"man_tipping_hand_tone3\":\"a7e0481.svg\",\"man_tipping_hand_medium_skin_tone\":\"a7e0481.svg\",\"man_tipping_hand_tone4\":\"ca1be4f.svg\",\"man_tipping_hand_medium_dark_skin_tone\":\"ca1be4f.svg\",\"man_tipping_hand_tone5\":\"ab22b3f.svg\",\"man_tipping_hand_dark_skin_tone\":\"ab22b3f.svg\",\"person_gesturing_no\":\"b3d3cab.svg\",\"no_good\":\"b3d3cab.svg\",\"person_gesturing_no_tone1\":\"5761bba.svg\",\"no_good_tone1\":\"5761bba.svg\",\"person_gesturing_no_tone2\":\"e92da27.svg\",\"no_good_tone2\":\"e92da27.svg\",\"person_gesturing_no_tone3\":\"52cf54e.svg\",\"no_good_tone3\":\"52cf54e.svg\",\"person_gesturing_no_tone4\":\"4d41682.svg\",\"no_good_tone4\":\"4d41682.svg\",\"person_gesturing_no_tone5\":\"734a4ec.svg\",\"no_good_tone5\":\"734a4ec.svg\",\"woman_gesturing_no\":\"0cf0c5b.svg\",\"woman_gesturing_no_tone1\":\"c8e7646.svg\",\"woman_gesturing_no_light_skin_tone\":\"c8e7646.svg\",\"woman_gesturing_no_tone2\":\"ed0f0dd.svg\",\"woman_gesturing_no_medium_light_skin_tone\":\"ed0f0dd.svg\",\"woman_gesturing_no_tone3\":\"69fe3a5.svg\",\"woman_gesturing_no_medium_skin_tone\":\"69fe3a5.svg\",\"woman_gesturing_no_tone4\":\"e9d62cb.svg\",\"woman_gesturing_no_medium_dark_skin_tone\":\"e9d62cb.svg\",\"woman_gesturing_no_tone5\":\"0945226.svg\",\"woman_gesturing_no_dark_skin_tone\":\"0945226.svg\",\"man_gesturing_no\":\"36264f7.svg\",\"man_gesturing_no_tone1\":\"fa93037.svg\",\"man_gesturing_no_light_skin_tone\":\"fa93037.svg\",\"man_gesturing_no_tone2\":\"db4e57a.svg\",\"man_gesturing_no_medium_light_skin_tone\":\"db4e57a.svg\",\"man_gesturing_no_tone3\":\"149936d.svg\",\"man_gesturing_no_medium_skin_tone\":\"149936d.svg\",\"man_gesturing_no_tone4\":\"555adbc.svg\",\"man_gesturing_no_medium_dark_skin_tone\":\"555adbc.svg\",\"man_gesturing_no_tone5\":\"74b112d.svg\",\"man_gesturing_no_dark_skin_tone\":\"74b112d.svg\",\"person_gesturing_ok\":\"78d8c1b.svg\",\"ok_woman\":\"78d8c1b.svg\",\"person_gesturing_ok_tone1\":\"a8a7d2b.svg\",\"ok_woman_tone1\":\"a8a7d2b.svg\",\"person_gesturing_ok_tone2\":\"1932339.svg\",\"ok_woman_tone2\":\"1932339.svg\",\"person_gesturing_ok_tone3\":\"62a69d5.svg\",\"ok_woman_tone3\":\"62a69d5.svg\",\"person_gesturing_ok_tone4\":\"ab3bd3f.svg\",\"ok_woman_tone4\":\"ab3bd3f.svg\",\"person_gesturing_ok_tone5\":\"498658e.svg\",\"ok_woman_tone5\":\"498658e.svg\",\"woman_gesturing_ok\":\"c12f22f.svg\",\"woman_gesturing_ok_tone1\":\"bbaf25a.svg\",\"woman_gesturing_ok_light_skin_tone\":\"bbaf25a.svg\",\"woman_gesturing_ok_tone2\":\"5086512.svg\",\"woman_gesturing_ok_medium_light_skin_tone\":\"5086512.svg\",\"woman_gesturing_ok_tone3\":\"16d7752.svg\",\"woman_gesturing_ok_medium_skin_tone\":\"16d7752.svg\",\"woman_gesturing_ok_tone4\":\"827931c.svg\",\"woman_gesturing_ok_medium_dark_skin_tone\":\"827931c.svg\",\"woman_gesturing_ok_tone5\":\"9d225f5.svg\",\"woman_gesturing_ok_dark_skin_tone\":\"9d225f5.svg\",\"man_gesturing_ok\":\"c805342.svg\",\"man_gesturing_ok_tone1\":\"d6d537f.svg\",\"man_gesturing_ok_light_skin_tone\":\"d6d537f.svg\",\"man_gesturing_ok_tone2\":\"723bd7c.svg\",\"man_gesturing_ok_medium_light_skin_tone\":\"723bd7c.svg\",\"man_gesturing_ok_tone3\":\"c793134.svg\",\"man_gesturing_ok_medium_skin_tone\":\"c793134.svg\",\"man_gesturing_ok_tone4\":\"82c3ecf.svg\",\"man_gesturing_ok_medium_dark_skin_tone\":\"82c3ecf.svg\",\"man_gesturing_ok_tone5\":\"527cdca.svg\",\"man_gesturing_ok_dark_skin_tone\":\"527cdca.svg\",\"person_raising_hand\":\"233672b.svg\",\"raising_hand\":\"233672b.svg\",\"person_raising_hand_tone1\":\"effaeab.svg\",\"raising_hand_tone1\":\"effaeab.svg\",\"person_raising_hand_tone2\":\"44ef541.svg\",\"raising_hand_tone2\":\"44ef541.svg\",\"person_raising_hand_tone3\":\"154c8f1.svg\",\"raising_hand_tone3\":\"154c8f1.svg\",\"person_raising_hand_tone4\":\"6ba1f11.svg\",\"raising_hand_tone4\":\"6ba1f11.svg\",\"person_raising_hand_tone5\":\"fe1afd4.svg\",\"raising_hand_tone5\":\"fe1afd4.svg\",\"woman_raising_hand\":\"5292981.svg\",\"woman_raising_hand_tone1\":\"a3c06be.svg\",\"woman_raising_hand_light_skin_tone\":\"a3c06be.svg\",\"woman_raising_hand_tone2\":\"9476e45.svg\",\"woman_raising_hand_medium_light_skin_tone\":\"9476e45.svg\",\"woman_raising_hand_tone3\":\"b3888a9.svg\",\"woman_raising_hand_medium_skin_tone\":\"b3888a9.svg\",\"woman_raising_hand_tone4\":\"5b6980b.svg\",\"woman_raising_hand_medium_dark_skin_tone\":\"5b6980b.svg\",\"woman_raising_hand_tone5\":\"a5ed245.svg\",\"woman_raising_hand_dark_skin_tone\":\"a5ed245.svg\",\"man_raising_hand\":\"72bbf7d.svg\",\"man_raising_hand_tone1\":\"bdcf877.svg\",\"man_raising_hand_light_skin_tone\":\"bdcf877.svg\",\"man_raising_hand_tone2\":\"22d2886.svg\",\"man_raising_hand_medium_light_skin_tone\":\"22d2886.svg\",\"man_raising_hand_tone3\":\"6bee419.svg\",\"man_raising_hand_medium_skin_tone\":\"6bee419.svg\",\"man_raising_hand_tone4\":\"9747d0a.svg\",\"man_raising_hand_medium_dark_skin_tone\":\"9747d0a.svg\",\"man_raising_hand_tone5\":\"dbde589.svg\",\"man_raising_hand_dark_skin_tone\":\"dbde589.svg\",\"deaf_person\":\"6544e85.svg\",\"deaf_person_tone1\":\"e438224.svg\",\"deaf_person_light_skin_tone\":\"e438224.svg\",\"deaf_person_tone2\":\"487331a.svg\",\"deaf_person_medium_light_skin_tone\":\"487331a.svg\",\"deaf_person_tone3\":\"2b0c9df.svg\",\"deaf_person_medium_skin_tone\":\"2b0c9df.svg\",\"deaf_person_tone4\":\"fcc98bd.svg\",\"deaf_person_medium_dark_skin_tone\":\"fcc98bd.svg\",\"deaf_person_tone5\":\"52c382a.svg\",\"deaf_person_dark_skin_tone\":\"52c382a.svg\",\"deaf_woman\":\"86e5fef.svg\",\"deaf_woman_tone1\":\"ae24285.svg\",\"deaf_woman_light_skin_tone\":\"ae24285.svg\",\"deaf_woman_tone2\":\"0d4577a.svg\",\"deaf_woman_medium_light_skin_tone\":\"0d4577a.svg\",\"deaf_woman_tone3\":\"e08dc29.svg\",\"deaf_woman_medium_skin_tone\":\"e08dc29.svg\",\"deaf_woman_tone4\":\"dc524f8.svg\",\"deaf_woman_medium_dark_skin_tone\":\"dc524f8.svg\",\"deaf_woman_tone5\":\"695de57.svg\",\"deaf_woman_dark_skin_tone\":\"695de57.svg\",\"deaf_man\":\"3985709.svg\",\"deaf_man_tone1\":\"c8f2b7c.svg\",\"deaf_man_light_skin_tone\":\"c8f2b7c.svg\",\"deaf_man_tone2\":\"bc043e0.svg\",\"deaf_man_medium_light_skin_tone\":\"bc043e0.svg\",\"deaf_man_tone3\":\"4bd7e00.svg\",\"deaf_man_medium_skin_tone\":\"4bd7e00.svg\",\"deaf_man_tone4\":\"4c31d34.svg\",\"deaf_man_medium_dark_skin_tone\":\"4c31d34.svg\",\"deaf_man_tone5\":\"3d0d9dc.svg\",\"deaf_man_dark_skin_tone\":\"3d0d9dc.svg\",\"person_facepalming\":\"b1ef4ff.svg\",\"face_palm\":\"b1ef4ff.svg\",\"facepalm\":\"b1ef4ff.svg\",\"person_facepalming_tone1\":\"5c12246.svg\",\"face_palm_tone1\":\"5c12246.svg\",\"facepalm_tone1\":\"5c12246.svg\",\"person_facepalming_tone2\":\"00f0044.svg\",\"face_palm_tone2\":\"00f0044.svg\",\"facepalm_tone2\":\"00f0044.svg\",\"person_facepalming_tone3\":\"2c4e6e4.svg\",\"face_palm_tone3\":\"2c4e6e4.svg\",\"facepalm_tone3\":\"2c4e6e4.svg\",\"person_facepalming_tone4\":\"b4618b8.svg\",\"face_palm_tone4\":\"b4618b8.svg\",\"facepalm_tone4\":\"b4618b8.svg\",\"person_facepalming_tone5\":\"c7effed.svg\",\"face_palm_tone5\":\"c7effed.svg\",\"facepalm_tone5\":\"c7effed.svg\",\"woman_facepalming\":\"b0e9cd8.svg\",\"woman_facepalming_tone1\":\"0c79612.svg\",\"woman_facepalming_light_skin_tone\":\"0c79612.svg\",\"woman_facepalming_tone2\":\"c678063.svg\",\"woman_facepalming_medium_light_skin_tone\":\"c678063.svg\",\"woman_facepalming_tone3\":\"016f3e5.svg\",\"woman_facepalming_medium_skin_tone\":\"016f3e5.svg\",\"woman_facepalming_tone4\":\"5ad9a80.svg\",\"woman_facepalming_medium_dark_skin_tone\":\"5ad9a80.svg\",\"woman_facepalming_tone5\":\"858411b.svg\",\"woman_facepalming_dark_skin_tone\":\"858411b.svg\",\"man_facepalming\":\"ebe3c51.svg\",\"man_facepalming_tone1\":\"c9bd6c8.svg\",\"man_facepalming_light_skin_tone\":\"c9bd6c8.svg\",\"man_facepalming_tone2\":\"e64451e.svg\",\"man_facepalming_medium_light_skin_tone\":\"e64451e.svg\",\"man_facepalming_tone3\":\"a1f5dfb.svg\",\"man_facepalming_medium_skin_tone\":\"a1f5dfb.svg\",\"man_facepalming_tone4\":\"2518b02.svg\",\"man_facepalming_medium_dark_skin_tone\":\"2518b02.svg\",\"man_facepalming_tone5\":\"5ddde41.svg\",\"man_facepalming_dark_skin_tone\":\"5ddde41.svg\",\"person_shrugging\":\"9f9d201.svg\",\"shrug\":\"9f9d201.svg\",\"person_shrugging_tone1\":\"c808491.svg\",\"shrug_tone1\":\"c808491.svg\",\"person_shrugging_tone2\":\"9e7ab0d.svg\",\"shrug_tone2\":\"9e7ab0d.svg\",\"person_shrugging_tone3\":\"add6153.svg\",\"shrug_tone3\":\"add6153.svg\",\"person_shrugging_tone4\":\"e2aa2fd.svg\",\"shrug_tone4\":\"e2aa2fd.svg\",\"person_shrugging_tone5\":\"a889b10.svg\",\"shrug_tone5\":\"a889b10.svg\",\"woman_shrugging\":\"07d7116.svg\",\"woman_shrugging_tone1\":\"ef01911.svg\",\"woman_shrugging_light_skin_tone\":\"ef01911.svg\",\"woman_shrugging_tone2\":\"6a7505b.svg\",\"woman_shrugging_medium_light_skin_tone\":\"6a7505b.svg\",\"woman_shrugging_tone3\":\"fb69dde.svg\",\"woman_shrugging_medium_skin_tone\":\"fb69dde.svg\",\"woman_shrugging_tone4\":\"e51d390.svg\",\"woman_shrugging_medium_dark_skin_tone\":\"e51d390.svg\",\"woman_shrugging_tone5\":\"b4e9af2.svg\",\"woman_shrugging_dark_skin_tone\":\"b4e9af2.svg\",\"man_shrugging\":\"461ded8.svg\",\"man_shrugging_tone1\":\"c566d67.svg\",\"man_shrugging_light_skin_tone\":\"c566d67.svg\",\"man_shrugging_tone2\":\"5513f53.svg\",\"man_shrugging_medium_light_skin_tone\":\"5513f53.svg\",\"man_shrugging_tone3\":\"e32a5a7.svg\",\"man_shrugging_medium_skin_tone\":\"e32a5a7.svg\",\"man_shrugging_tone4\":\"b9af4c1.svg\",\"man_shrugging_medium_dark_skin_tone\":\"b9af4c1.svg\",\"man_shrugging_tone5\":\"37cd4e4.svg\",\"man_shrugging_dark_skin_tone\":\"37cd4e4.svg\",\"person_pouting\":\"e0c72d3.svg\",\"person_with_pouting_face\":\"e0c72d3.svg\",\"person_pouting_tone1\":\"b8d02d5.svg\",\"person_with_pouting_face_tone1\":\"b8d02d5.svg\",\"person_pouting_tone2\":\"8761f4d.svg\",\"person_with_pouting_face_tone2\":\"8761f4d.svg\",\"person_pouting_tone3\":\"917193e.svg\",\"person_with_pouting_face_tone3\":\"917193e.svg\",\"person_pouting_tone4\":\"afd130f.svg\",\"person_with_pouting_face_tone4\":\"afd130f.svg\",\"person_pouting_tone5\":\"1345297.svg\",\"person_with_pouting_face_tone5\":\"1345297.svg\",\"woman_pouting\":\"23bdd67.svg\",\"woman_pouting_tone1\":\"68a870b.svg\",\"woman_pouting_light_skin_tone\":\"68a870b.svg\",\"woman_pouting_tone2\":\"87cc3e3.svg\",\"woman_pouting_medium_light_skin_tone\":\"87cc3e3.svg\",\"woman_pouting_tone3\":\"ebb6550.svg\",\"woman_pouting_medium_skin_tone\":\"ebb6550.svg\",\"woman_pouting_tone4\":\"b157967.svg\",\"woman_pouting_medium_dark_skin_tone\":\"b157967.svg\",\"woman_pouting_tone5\":\"3b4c2f4.svg\",\"woman_pouting_dark_skin_tone\":\"3b4c2f4.svg\",\"man_pouting\":\"0a478b3.svg\",\"man_pouting_tone1\":\"a09c4f8.svg\",\"man_pouting_light_skin_tone\":\"a09c4f8.svg\",\"man_pouting_tone2\":\"ccb3ec0.svg\",\"man_pouting_medium_light_skin_tone\":\"ccb3ec0.svg\",\"man_pouting_tone3\":\"a976c3f.svg\",\"man_pouting_medium_skin_tone\":\"a976c3f.svg\",\"man_pouting_tone4\":\"a0c0da1.svg\",\"man_pouting_medium_dark_skin_tone\":\"a0c0da1.svg\",\"man_pouting_tone5\":\"b36e7cb.svg\",\"man_pouting_dark_skin_tone\":\"b36e7cb.svg\",\"person_frowning\":\"b54d16c.svg\",\"person_frowning_tone1\":\"1d91a35.svg\",\"person_frowning_tone2\":\"bd11f84.svg\",\"person_frowning_tone3\":\"0075836.svg\",\"person_frowning_tone4\":\"2f4c682.svg\",\"person_frowning_tone5\":\"f05d72b.svg\",\"woman_frowning\":\"0ad5677.svg\",\"woman_frowning_tone1\":\"b52e466.svg\",\"woman_frowning_light_skin_tone\":\"b52e466.svg\",\"woman_frowning_tone2\":\"31501dc.svg\",\"woman_frowning_medium_light_skin_tone\":\"31501dc.svg\",\"woman_frowning_tone3\":\"4c683ec.svg\",\"woman_frowning_medium_skin_tone\":\"4c683ec.svg\",\"woman_frowning_tone4\":\"62f239b.svg\",\"woman_frowning_medium_dark_skin_tone\":\"62f239b.svg\",\"woman_frowning_tone5\":\"b2348e4.svg\",\"woman_frowning_dark_skin_tone\":\"b2348e4.svg\",\"man_frowning\":\"c8012a8.svg\",\"man_frowning_tone1\":\"bfb307e.svg\",\"man_frowning_light_skin_tone\":\"bfb307e.svg\",\"man_frowning_tone2\":\"9408d7c.svg\",\"man_frowning_medium_light_skin_tone\":\"9408d7c.svg\",\"man_frowning_tone3\":\"654d019.svg\",\"man_frowning_medium_skin_tone\":\"654d019.svg\",\"man_frowning_tone4\":\"1992e8a.svg\",\"man_frowning_medium_dark_skin_tone\":\"1992e8a.svg\",\"man_frowning_tone5\":\"607cb42.svg\",\"man_frowning_dark_skin_tone\":\"607cb42.svg\",\"person_getting_haircut\":\"5195d8f.svg\",\"haircut\":\"5195d8f.svg\",\"person_getting_haircut_tone1\":\"24cfd2f.svg\",\"haircut_tone1\":\"24cfd2f.svg\",\"person_getting_haircut_tone2\":\"58e729e.svg\",\"haircut_tone2\":\"58e729e.svg\",\"person_getting_haircut_tone3\":\"d05262f.svg\",\"haircut_tone3\":\"d05262f.svg\",\"person_getting_haircut_tone4\":\"5e61065.svg\",\"haircut_tone4\":\"5e61065.svg\",\"person_getting_haircut_tone5\":\"0dfa781.svg\",\"haircut_tone5\":\"0dfa781.svg\",\"woman_getting_haircut\":\"1a18b7f.svg\",\"woman_getting_haircut_tone1\":\"aa700ad.svg\",\"woman_getting_haircut_light_skin_tone\":\"aa700ad.svg\",\"woman_getting_haircut_tone2\":\"e498a95.svg\",\"woman_getting_haircut_medium_light_skin_tone\":\"e498a95.svg\",\"woman_getting_haircut_tone3\":\"bcd258a.svg\",\"woman_getting_haircut_medium_skin_tone\":\"bcd258a.svg\",\"woman_getting_haircut_tone4\":\"2ee70bb.svg\",\"woman_getting_haircut_medium_dark_skin_tone\":\"2ee70bb.svg\",\"woman_getting_haircut_tone5\":\"1f38e96.svg\",\"woman_getting_haircut_dark_skin_tone\":\"1f38e96.svg\",\"man_getting_haircut\":\"adc5266.svg\",\"man_getting_haircut_tone1\":\"424c650.svg\",\"man_getting_haircut_light_skin_tone\":\"424c650.svg\",\"man_getting_haircut_tone2\":\"49090ff.svg\",\"man_getting_haircut_medium_light_skin_tone\":\"49090ff.svg\",\"man_getting_haircut_tone3\":\"27ff3ea.svg\",\"man_getting_haircut_medium_skin_tone\":\"27ff3ea.svg\",\"man_getting_haircut_tone4\":\"d2484c1.svg\",\"man_getting_haircut_medium_dark_skin_tone\":\"d2484c1.svg\",\"man_getting_haircut_tone5\":\"551363b.svg\",\"man_getting_haircut_dark_skin_tone\":\"551363b.svg\",\"person_getting_massage\":\"d5fe7f4.svg\",\"massage\":\"d5fe7f4.svg\",\"person_getting_massage_tone1\":\"e4857ca.svg\",\"massage_tone1\":\"e4857ca.svg\",\"person_getting_massage_tone2\":\"9b27a37.svg\",\"massage_tone2\":\"9b27a37.svg\",\"person_getting_massage_tone3\":\"0ee9111.svg\",\"massage_tone3\":\"0ee9111.svg\",\"person_getting_massage_tone4\":\"d695c28.svg\",\"massage_tone4\":\"d695c28.svg\",\"person_getting_massage_tone5\":\"f38b5b4.svg\",\"massage_tone5\":\"f38b5b4.svg\",\"woman_getting_face_massage\":\"20e293b.svg\",\"woman_getting_face_massage_tone1\":\"9c68367.svg\",\"woman_getting_face_massage_light_skin_tone\":\"9c68367.svg\",\"woman_getting_face_massage_tone2\":\"5f4591b.svg\",\"woman_getting_face_massage_medium_light_skin_tone\":\"5f4591b.svg\",\"woman_getting_face_massage_tone3\":\"e50c761.svg\",\"woman_getting_face_massage_medium_skin_tone\":\"e50c761.svg\",\"woman_getting_face_massage_tone4\":\"f74ecb8.svg\",\"woman_getting_face_massage_medium_dark_skin_tone\":\"f74ecb8.svg\",\"woman_getting_face_massage_tone5\":\"e73552f.svg\",\"woman_getting_face_massage_dark_skin_tone\":\"e73552f.svg\",\"man_getting_face_massage\":\"116f585.svg\",\"man_getting_face_massage_tone1\":\"2336974.svg\",\"man_getting_face_massage_light_skin_tone\":\"2336974.svg\",\"man_getting_face_massage_tone2\":\"8aada29.svg\",\"man_getting_face_massage_medium_light_skin_tone\":\"8aada29.svg\",\"man_getting_face_massage_tone3\":\"e4262a8.svg\",\"man_getting_face_massage_medium_skin_tone\":\"e4262a8.svg\",\"man_getting_face_massage_tone4\":\"3426889.svg\",\"man_getting_face_massage_medium_dark_skin_tone\":\"3426889.svg\",\"man_getting_face_massage_tone5\":\"44c3dcf.svg\",\"man_getting_face_massage_dark_skin_tone\":\"44c3dcf.svg\",\"person_in_steamy_room\":\"34eb462.svg\",\"person_in_steamy_room_tone1\":\"bc4b231.svg\",\"person_in_steamy_room_light_skin_tone\":\"bc4b231.svg\",\"person_in_steamy_room_tone2\":\"80a1fee.svg\",\"person_in_steamy_room_medium_light_skin_tone\":\"80a1fee.svg\",\"person_in_steamy_room_tone3\":\"efda8b7.svg\",\"person_in_steamy_room_medium_skin_tone\":\"efda8b7.svg\",\"person_in_steamy_room_tone4\":\"1b86631.svg\",\"person_in_steamy_room_medium_dark_skin_tone\":\"1b86631.svg\",\"person_in_steamy_room_tone5\":\"97bfa4c.svg\",\"person_in_steamy_room_dark_skin_tone\":\"97bfa4c.svg\",\"woman_in_steamy_room\":\"ff97577.svg\",\"woman_in_steamy_room_tone1\":\"c5be413.svg\",\"woman_in_steamy_room_light_skin_tone\":\"c5be413.svg\",\"woman_in_steamy_room_tone2\":\"5f66664.svg\",\"woman_in_steamy_room_medium_light_skin_tone\":\"5f66664.svg\",\"woman_in_steamy_room_tone3\":\"30cbfeb.svg\",\"woman_in_steamy_room_medium_skin_tone\":\"30cbfeb.svg\",\"woman_in_steamy_room_tone4\":\"d97af6c.svg\",\"woman_in_steamy_room_medium_dark_skin_tone\":\"d97af6c.svg\",\"woman_in_steamy_room_tone5\":\"27256eb.svg\",\"woman_in_steamy_room_dark_skin_tone\":\"27256eb.svg\",\"man_in_steamy_room\":\"b478994.svg\",\"man_in_steamy_room_tone1\":\"ac368ef.svg\",\"man_in_steamy_room_light_skin_tone\":\"ac368ef.svg\",\"man_in_steamy_room_tone2\":\"e091810.svg\",\"man_in_steamy_room_medium_light_skin_tone\":\"e091810.svg\",\"man_in_steamy_room_tone3\":\"76979d9.svg\",\"man_in_steamy_room_medium_skin_tone\":\"76979d9.svg\",\"man_in_steamy_room_tone4\":\"d2872ca.svg\",\"man_in_steamy_room_medium_dark_skin_tone\":\"d2872ca.svg\",\"man_in_steamy_room_tone5\":\"a874aeb.svg\",\"man_in_steamy_room_dark_skin_tone\":\"a874aeb.svg\",\"nail_care\":\"9560c40.svg\",\"nail_polish\":\"9560c40.svg\",\"nail_care_tone1\":\"4d00842.svg\",\"nail_care_tone2\":\"d395ba9.svg\",\"nail_care_tone3\":\"e66d129.svg\",\"nail_care_tone4\":\"7d733a5.svg\",\"nail_care_tone5\":\"273c192.svg\",\"selfie\":\"78c0d71.svg\",\"selfie_tone1\":\"08d46cd.svg\",\"selfie_tone2\":\"dbe8ad8.svg\",\"selfie_tone3\":\"e9830d4.svg\",\"selfie_tone4\":\"d6a0954.svg\",\"selfie_tone5\":\"e2e70c9.svg\",\"dancer\":\"d269f51.svg\",\"woman_dancing\":\"d269f51.svg\",\"dancer_tone1\":\"08c020d.svg\",\"dancer_tone2\":\"ee1c1c4.svg\",\"dancer_tone3\":\"cfa402c.svg\",\"dancer_tone4\":\"b382fe7.svg\",\"dancer_tone5\":\"b3148f8.svg\",\"man_dancing\":\"4d39df0.svg\",\"male_dancer\":\"4d39df0.svg\",\"man_dancing_tone1\":\"15b88cf.svg\",\"male_dancer_tone1\":\"15b88cf.svg\",\"man_dancing_tone2\":\"4fee914.svg\",\"male_dancer_tone2\":\"4fee914.svg\",\"man_dancing_tone3\":\"dfc7558.svg\",\"male_dancer_tone3\":\"dfc7558.svg\",\"man_dancing_tone5\":\"cbf8cd2.svg\",\"male_dancer_tone5\":\"cbf8cd2.svg\",\"man_dancing_tone4\":\"f3373d8.svg\",\"male_dancer_tone4\":\"f3373d8.svg\",\"people_with_bunny_ears_partying\":\"1109bba.svg\",\"dancers\":\"1109bba.svg\",\"women_with_bunny_ears_partying\":\"31d5b7f.svg\",\"men_with_bunny_ears_partying\":\"1797f13.svg\",\"levitate\":\"de6429e.svg\",\"man_in_business_suit_levitating\":\"de6429e.svg\",\"levitate_tone1\":\"7109687.svg\",\"man_in_business_suit_levitating_tone1\":\"7109687.svg\",\"man_in_business_suit_levitating_light_skin_tone\":\"7109687.svg\",\"levitate_tone2\":\"69d0a60.svg\",\"man_in_business_suit_levitating_tone2\":\"69d0a60.svg\",\"man_in_business_suit_levitating_medium_light_skin_tone\":\"69d0a60.svg\",\"levitate_tone3\":\"0c06cb8.svg\",\"man_in_business_suit_levitating_tone3\":\"0c06cb8.svg\",\"man_in_business_suit_levitating_medium_skin_tone\":\"0c06cb8.svg\",\"levitate_tone4\":\"d24578b.svg\",\"man_in_business_suit_levitating_tone4\":\"d24578b.svg\",\"man_in_business_suit_levitating_medium_dark_skin_tone\":\"d24578b.svg\",\"levitate_tone5\":\"65ac60f.svg\",\"man_in_business_suit_levitating_tone5\":\"65ac60f.svg\",\"man_in_business_suit_levitating_dark_skin_tone\":\"65ac60f.svg\",\"person_in_manual_wheelchair\":\"84cf080.svg\",\"person_in_manual_wheelchair_tone1\":\"f229855.svg\",\"person_in_manual_wheelchair_light_skin_tone\":\"f229855.svg\",\"person_in_manual_wheelchair_tone2\":\"17c2b7c.svg\",\"person_in_manual_wheelchair_medium_light_skin_tone\":\"17c2b7c.svg\",\"person_in_manual_wheelchair_tone3\":\"c4677a3.svg\",\"person_in_manual_wheelchair_medium_skin_tone\":\"c4677a3.svg\",\"person_in_manual_wheelchair_tone4\":\"c89e2b3.svg\",\"person_in_manual_wheelchair_medium_dark_skin_tone\":\"c89e2b3.svg\",\"person_in_manual_wheelchair_tone5\":\"616eafd.svg\",\"person_in_manual_wheelchair_dark_skin_tone\":\"616eafd.svg\",\"woman_in_manual_wheelchair\":\"ff97b0d.svg\",\"woman_in_manual_wheelchair_tone1\":\"0b8a7c8.svg\",\"woman_in_manual_wheelchair_light_skin_tone\":\"0b8a7c8.svg\",\"woman_in_manual_wheelchair_tone2\":\"2687b77.svg\",\"woman_in_manual_wheelchair_medium_light_skin_tone\":\"2687b77.svg\",\"woman_in_manual_wheelchair_tone3\":\"a4bb607.svg\",\"woman_in_manual_wheelchair_medium_skin_tone\":\"a4bb607.svg\",\"woman_in_manual_wheelchair_tone4\":\"fe46ede.svg\",\"woman_in_manual_wheelchair_medium_dark_skin_tone\":\"fe46ede.svg\",\"woman_in_manual_wheelchair_tone5\":\"dbfde96.svg\",\"woman_in_manual_wheelchair_dark_skin_tone\":\"dbfde96.svg\",\"man_in_manual_wheelchair\":\"7339ecd.svg\",\"man_in_manual_wheelchair_tone1\":\"ac5160b.svg\",\"man_in_manual_wheelchair_light_skin_tone\":\"ac5160b.svg\",\"man_in_manual_wheelchair_tone2\":\"f621f15.svg\",\"man_in_manual_wheelchair_medium_light_skin_tone\":\"f621f15.svg\",\"man_in_manual_wheelchair_tone3\":\"910e29e.svg\",\"man_in_manual_wheelchair_medium_skin_tone\":\"910e29e.svg\",\"man_in_manual_wheelchair_tone4\":\"76f1b06.svg\",\"man_in_manual_wheelchair_medium_dark_skin_tone\":\"76f1b06.svg\",\"man_in_manual_wheelchair_tone5\":\"7a97c0f.svg\",\"man_in_manual_wheelchair_dark_skin_tone\":\"7a97c0f.svg\",\"person_in_motorized_wheelchair\":\"c83226f.svg\",\"person_in_motorized_wheelchair_tone1\":\"d528ff2.svg\",\"person_in_motorized_wheelchair_light_skin_tone\":\"d528ff2.svg\",\"person_in_motorized_wheelchair_tone2\":\"93260e5.svg\",\"person_in_motorized_wheelchair_medium_light_skin_tone\":\"93260e5.svg\",\"person_in_motorized_wheelchair_tone3\":\"73d4365.svg\",\"person_in_motorized_wheelchair_medium_skin_tone\":\"73d4365.svg\",\"person_in_motorized_wheelchair_tone4\":\"33dbaca.svg\",\"person_in_motorized_wheelchair_medium_dark_skin_tone\":\"33dbaca.svg\",\"person_in_motorized_wheelchair_tone5\":\"3e9a112.svg\",\"person_in_motorized_wheelchair_dark_skin_tone\":\"3e9a112.svg\",\"woman_in_motorized_wheelchair\":\"fa4cb6b.svg\",\"woman_in_motorized_wheelchair_tone1\":\"ec04498.svg\",\"woman_in_motorized_wheelchair_light_skin_tone\":\"ec04498.svg\",\"woman_in_motorized_wheelchair_tone2\":\"67b6621.svg\",\"woman_in_motorized_wheelchair_medium_light_skin_tone\":\"67b6621.svg\",\"woman_in_motorized_wheelchair_tone3\":\"b63086c.svg\",\"woman_in_motorized_wheelchair_medium_skin_tone\":\"b63086c.svg\",\"woman_in_motorized_wheelchair_tone4\":\"0f8297e.svg\",\"woman_in_motorized_wheelchair_medium_dark_skin_tone\":\"0f8297e.svg\",\"woman_in_motorized_wheelchair_tone5\":\"7bc88ca.svg\",\"woman_in_motorized_wheelchair_dark_skin_tone\":\"7bc88ca.svg\",\"man_in_motorized_wheelchair\":\"af8954f.svg\",\"man_in_motorized_wheelchair_tone1\":\"db8adc1.svg\",\"man_in_motorized_wheelchair_light_skin_tone\":\"db8adc1.svg\",\"man_in_motorized_wheelchair_tone2\":\"b6dd254.svg\",\"man_in_motorized_wheelchair_medium_light_skin_tone\":\"b6dd254.svg\",\"man_in_motorized_wheelchair_tone3\":\"3a72c60.svg\",\"man_in_motorized_wheelchair_medium_skin_tone\":\"3a72c60.svg\",\"man_in_motorized_wheelchair_tone4\":\"a286a6a.svg\",\"man_in_motorized_wheelchair_medium_dark_skin_tone\":\"a286a6a.svg\",\"man_in_motorized_wheelchair_tone5\":\"31dffd1.svg\",\"man_in_motorized_wheelchair_dark_skin_tone\":\"31dffd1.svg\",\"person_walking\":\"65f60ce.svg\",\"walking\":\"65f60ce.svg\",\"person_walking_tone1\":\"d6a801f.svg\",\"walking_tone1\":\"d6a801f.svg\",\"person_walking_tone2\":\"0303228.svg\",\"walking_tone2\":\"0303228.svg\",\"person_walking_tone3\":\"3943f9e.svg\",\"walking_tone3\":\"3943f9e.svg\",\"person_walking_tone4\":\"95a9b35.svg\",\"walking_tone4\":\"95a9b35.svg\",\"person_walking_tone5\":\"cc5ec42.svg\",\"walking_tone5\":\"cc5ec42.svg\",\"woman_walking\":\"6598a59.svg\",\"woman_walking_tone1\":\"45c2450.svg\",\"woman_walking_light_skin_tone\":\"45c2450.svg\",\"woman_walking_tone2\":\"ad46e39.svg\",\"woman_walking_medium_light_skin_tone\":\"ad46e39.svg\",\"woman_walking_tone3\":\"654c09d.svg\",\"woman_walking_medium_skin_tone\":\"654c09d.svg\",\"woman_walking_tone4\":\"39b56ca.svg\",\"woman_walking_medium_dark_skin_tone\":\"39b56ca.svg\",\"woman_walking_tone5\":\"30ef6bd.svg\",\"woman_walking_dark_skin_tone\":\"30ef6bd.svg\",\"man_walking\":\"9c36511.svg\",\"man_walking_tone1\":\"0d6f57e.svg\",\"man_walking_light_skin_tone\":\"0d6f57e.svg\",\"man_walking_tone2\":\"fc77377.svg\",\"man_walking_medium_light_skin_tone\":\"fc77377.svg\",\"man_walking_tone3\":\"ee7f10a.svg\",\"man_walking_medium_skin_tone\":\"ee7f10a.svg\",\"man_walking_tone4\":\"b3cb34d.svg\",\"man_walking_medium_dark_skin_tone\":\"b3cb34d.svg\",\"man_walking_tone5\":\"89abc50.svg\",\"man_walking_dark_skin_tone\":\"89abc50.svg\",\"person_with_probing_cane\":\"887fd29.svg\",\"person_with_probing_cane_tone1\":\"ef344e8.svg\",\"person_with_probing_cane_light_skin_tone\":\"ef344e8.svg\",\"person_with_probing_cane_tone2\":\"ac74bd6.svg\",\"person_with_probing_cane_medium_light_skin_tone\":\"ac74bd6.svg\",\"person_with_probing_cane_tone3\":\"44e8e57.svg\",\"person_with_probing_cane_medium_skin_tone\":\"44e8e57.svg\",\"person_with_probing_cane_tone4\":\"6ae8265.svg\",\"person_with_probing_cane_medium_dark_skin_tone\":\"6ae8265.svg\",\"person_with_probing_cane_tone5\":\"0db34f2.svg\",\"person_with_probing_cane_dark_skin_tone\":\"0db34f2.svg\",\"woman_with_probing_cane\":\"88b2d91.svg\",\"woman_with_probing_cane_tone1\":\"cca5c5f.svg\",\"woman_with_probing_cane_light_skin_tone\":\"cca5c5f.svg\",\"woman_with_probing_cane_tone2\":\"f17fa9f.svg\",\"woman_with_probing_cane_medium_light_skin_tone\":\"f17fa9f.svg\",\"woman_with_probing_cane_tone3\":\"90a4d48.svg\",\"woman_with_probing_cane_medium_skin_tone\":\"90a4d48.svg\",\"woman_with_probing_cane_tone4\":\"c3f9228.svg\",\"woman_with_probing_cane_medium_dark_skin_tone\":\"c3f9228.svg\",\"woman_with_probing_cane_tone5\":\"47af028.svg\",\"woman_with_probing_cane_dark_skin_tone\":\"47af028.svg\",\"man_with_probing_cane\":\"642663b.svg\",\"man_with_probing_cane_tone1\":\"e606600.svg\",\"man_with_probing_cane_light_skin_tone\":\"e606600.svg\",\"man_with_probing_cane_tone2\":\"b8fd4db.svg\",\"man_with_probing_cane_medium_light_skin_tone\":\"b8fd4db.svg\",\"man_with_probing_cane_tone3\":\"ae4530a.svg\",\"man_with_probing_cane_medium_skin_tone\":\"ae4530a.svg\",\"man_with_probing_cane_tone4\":\"528cd32.svg\",\"man_with_probing_cane_medium_dark_skin_tone\":\"528cd32.svg\",\"man_with_probing_cane_tone5\":\"5148180.svg\",\"man_with_probing_cane_dark_skin_tone\":\"5148180.svg\",\"person_kneeling\":\"f567a4e.svg\",\"person_kneeling_tone1\":\"ff08ed5.svg\",\"person_kneeling_light_skin_tone\":\"ff08ed5.svg\",\"person_kneeling_tone2\":\"680a5a2.svg\",\"person_kneeling_medium_light_skin_tone\":\"680a5a2.svg\",\"person_kneeling_tone3\":\"4278f87.svg\",\"person_kneeling_medium_skin_tone\":\"4278f87.svg\",\"person_kneeling_tone4\":\"423f6d6.svg\",\"person_kneeling_medium_dark_skin_tone\":\"423f6d6.svg\",\"person_kneeling_tone5\":\"84c6b50.svg\",\"person_kneeling_dark_skin_tone\":\"84c6b50.svg\",\"woman_kneeling\":\"ed2af90.svg\",\"woman_kneeling_tone1\":\"25de7c5.svg\",\"woman_kneeling_light_skin_tone\":\"25de7c5.svg\",\"woman_kneeling_tone2\":\"0f4b629.svg\",\"woman_kneeling_medium_light_skin_tone\":\"0f4b629.svg\",\"woman_kneeling_tone3\":\"65c5945.svg\",\"woman_kneeling_medium_skin_tone\":\"65c5945.svg\",\"woman_kneeling_tone4\":\"0de34a1.svg\",\"woman_kneeling_medium_dark_skin_tone\":\"0de34a1.svg\",\"woman_kneeling_tone5\":\"7c7ac31.svg\",\"woman_kneeling_dark_skin_tone\":\"7c7ac31.svg\",\"man_kneeling\":\"ff6c0be.svg\",\"man_kneeling_tone1\":\"9bb3f4c.svg\",\"man_kneeling_light_skin_tone\":\"9bb3f4c.svg\",\"man_kneeling_tone2\":\"2b54d90.svg\",\"man_kneeling_medium_light_skin_tone\":\"2b54d90.svg\",\"man_kneeling_tone3\":\"cefb539.svg\",\"man_kneeling_medium_skin_tone\":\"cefb539.svg\",\"man_kneeling_tone4\":\"9b36f24.svg\",\"man_kneeling_medium_dark_skin_tone\":\"9b36f24.svg\",\"man_kneeling_tone5\":\"76b7f90.svg\",\"man_kneeling_dark_skin_tone\":\"76b7f90.svg\",\"person_running\":\"14a1805.svg\",\"runner\":\"14a1805.svg\",\"person_running_tone1\":\"e38b1e2.svg\",\"runner_tone1\":\"e38b1e2.svg\",\"person_running_tone2\":\"e3dc02b.svg\",\"runner_tone2\":\"e3dc02b.svg\",\"person_running_tone3\":\"07092d7.svg\",\"runner_tone3\":\"07092d7.svg\",\"person_running_tone4\":\"ff8fb96.svg\",\"runner_tone4\":\"ff8fb96.svg\",\"person_running_tone5\":\"db3fcb5.svg\",\"runner_tone5\":\"db3fcb5.svg\",\"woman_running\":\"54428e4.svg\",\"woman_running_tone1\":\"7e37d8c.svg\",\"woman_running_light_skin_tone\":\"7e37d8c.svg\",\"woman_running_tone2\":\"93b8bdf.svg\",\"woman_running_medium_light_skin_tone\":\"93b8bdf.svg\",\"woman_running_tone3\":\"6e25d9b.svg\",\"woman_running_medium_skin_tone\":\"6e25d9b.svg\",\"woman_running_tone4\":\"f608102.svg\",\"woman_running_medium_dark_skin_tone\":\"f608102.svg\",\"woman_running_tone5\":\"ea57c5b.svg\",\"woman_running_dark_skin_tone\":\"ea57c5b.svg\",\"man_running\":\"24b7322.svg\",\"man_running_tone1\":\"df099d9.svg\",\"man_running_light_skin_tone\":\"df099d9.svg\",\"man_running_tone2\":\"692c6c7.svg\",\"man_running_medium_light_skin_tone\":\"692c6c7.svg\",\"man_running_tone3\":\"f3a32e6.svg\",\"man_running_medium_skin_tone\":\"f3a32e6.svg\",\"man_running_tone4\":\"c7b7abe.svg\",\"man_running_medium_dark_skin_tone\":\"c7b7abe.svg\",\"man_running_tone5\":\"6692d4b.svg\",\"man_running_dark_skin_tone\":\"6692d4b.svg\",\"person_standing\":\"44c7448.svg\",\"person_standing_tone1\":\"8cff530.svg\",\"person_standing_light_skin_tone\":\"8cff530.svg\",\"person_standing_tone2\":\"8533db2.svg\",\"person_standing_medium_light_skin_tone\":\"8533db2.svg\",\"person_standing_tone3\":\"80db0f5.svg\",\"person_standing_medium_skin_tone\":\"80db0f5.svg\",\"person_standing_tone4\":\"b8e5e63.svg\",\"person_standing_medium_dark_skin_tone\":\"b8e5e63.svg\",\"person_standing_tone5\":\"f111f67.svg\",\"person_standing_dark_skin_tone\":\"f111f67.svg\",\"woman_standing\":\"fa8c4a0.svg\",\"woman_standing_tone1\":\"cf856b3.svg\",\"woman_standing_light_skin_tone\":\"cf856b3.svg\",\"woman_standing_tone2\":\"1e2288e.svg\",\"woman_standing_medium_light_skin_tone\":\"1e2288e.svg\",\"woman_standing_tone3\":\"d80e460.svg\",\"woman_standing_medium_skin_tone\":\"d80e460.svg\",\"woman_standing_tone4\":\"85b7da4.svg\",\"woman_standing_medium_dark_skin_tone\":\"85b7da4.svg\",\"woman_standing_tone5\":\"e38a4ab.svg\",\"woman_standing_dark_skin_tone\":\"e38a4ab.svg\",\"man_standing\":\"aa33f3f.svg\",\"man_standing_tone1\":\"cc40d0d.svg\",\"man_standing_light_skin_tone\":\"cc40d0d.svg\",\"man_standing_tone2\":\"d5128b4.svg\",\"man_standing_medium_light_skin_tone\":\"d5128b4.svg\",\"man_standing_tone3\":\"14fe4be.svg\",\"man_standing_medium_skin_tone\":\"14fe4be.svg\",\"man_standing_tone4\":\"20adb5e.svg\",\"man_standing_medium_dark_skin_tone\":\"20adb5e.svg\",\"man_standing_tone5\":\"b6ba2e8.svg\",\"man_standing_dark_skin_tone\":\"b6ba2e8.svg\",\"people_holding_hands\":\"4c2921a.svg\",\"people_holding_hands_tone1\":\"23acced.svg\",\"people_holding_hands_light_skin_tone\":\"23acced.svg\",\"people_holding_hands_tone1_tone2\":\"3339791.svg\",\"people_holding_hands_light_skin_tone_medium_light_skin_tone\":\"3339791.svg\",\"people_holding_hands_tone1_tone3\":\"58cee68.svg\",\"people_holding_hands_light_skin_tone_medium_skin_tone\":\"58cee68.svg\",\"people_holding_hands_tone1_tone4\":\"9ebfdf3.svg\",\"people_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"9ebfdf3.svg\",\"people_holding_hands_tone1_tone5\":\"29a99d5.svg\",\"people_holding_hands_light_skin_tone_dark_skin_tone\":\"29a99d5.svg\",\"people_holding_hands_tone2_tone1\":\"d3bc4f8.svg\",\"people_holding_hands_medium_light_skin_tone_light_skin_tone\":\"d3bc4f8.svg\",\"people_holding_hands_tone2\":\"39d4330.svg\",\"people_holding_hands_medium_light_skin_tone\":\"39d4330.svg\",\"people_holding_hands_tone2_tone3\":\"24662bc.svg\",\"people_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"24662bc.svg\",\"people_holding_hands_tone2_tone4\":\"9620340.svg\",\"people_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"9620340.svg\",\"people_holding_hands_tone2_tone5\":\"07db777.svg\",\"people_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"07db777.svg\",\"people_holding_hands_tone3_tone1\":\"787c7ae.svg\",\"people_holding_hands_medium_skin_tone_light_skin_tone\":\"787c7ae.svg\",\"people_holding_hands_tone3_tone2\":\"f84075b.svg\",\"people_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"f84075b.svg\",\"people_holding_hands_tone3\":\"25ef13b.svg\",\"people_holding_hands_medium_skin_tone\":\"25ef13b.svg\",\"people_holding_hands_tone3_tone4\":\"9b75f7a.svg\",\"people_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"9b75f7a.svg\",\"people_holding_hands_tone3_tone5\":\"fd33f12.svg\",\"people_holding_hands_medium_skin_tone_dark_skin_tone\":\"fd33f12.svg\",\"people_holding_hands_tone4_tone1\":\"d450d92.svg\",\"people_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"d450d92.svg\",\"people_holding_hands_tone4_tone2\":\"06a0c9a.svg\",\"people_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"06a0c9a.svg\",\"people_holding_hands_tone4_tone3\":\"509577c.svg\",\"people_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"509577c.svg\",\"people_holding_hands_tone4\":\"7629eeb.svg\",\"people_holding_hands_medium_dark_skin_tone\":\"7629eeb.svg\",\"people_holding_hands_tone4_tone5\":\"06f01ca.svg\",\"people_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"06f01ca.svg\",\"people_holding_hands_tone5_tone1\":\"ee997a3.svg\",\"people_holding_hands_dark_skin_tone_light_skin_tone\":\"ee997a3.svg\",\"people_holding_hands_tone5_tone2\":\"fb5155b.svg\",\"people_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"fb5155b.svg\",\"people_holding_hands_tone5_tone3\":\"33faa2b.svg\",\"people_holding_hands_dark_skin_tone_medium_skin_tone\":\"33faa2b.svg\",\"people_holding_hands_tone5_tone4\":\"b9084e9.svg\",\"people_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"b9084e9.svg\",\"people_holding_hands_tone5\":\"fabdfad.svg\",\"people_holding_hands_dark_skin_tone\":\"fabdfad.svg\",\"couple\":\"35af177.svg\",\"woman_and_man_holding_hands_tone1\":\"5e3020f.svg\",\"woman_and_man_holding_hands_light_skin_tone\":\"5e3020f.svg\",\"woman_and_man_holding_hands_tone1_tone2\":\"8531337.svg\",\"woman_and_man_holding_hands_light_skin_tone_medium_light_skin_tone\":\"8531337.svg\",\"woman_and_man_holding_hands_tone1_tone3\":\"0b38682.svg\",\"woman_and_man_holding_hands_light_skin_tone_medium_skin_tone\":\"0b38682.svg\",\"woman_and_man_holding_hands_tone1_tone4\":\"19257a4.svg\",\"woman_and_man_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"19257a4.svg\",\"woman_and_man_holding_hands_tone1_tone5\":\"e7da92e.svg\",\"woman_and_man_holding_hands_light_skin_tone_dark_skin_tone\":\"e7da92e.svg\",\"woman_and_man_holding_hands_tone2_tone1\":\"83ccc36.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_light_skin_tone\":\"83ccc36.svg\",\"woman_and_man_holding_hands_tone2\":\"bb20c0b.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone\":\"bb20c0b.svg\",\"woman_and_man_holding_hands_tone2_tone3\":\"bf9dd09.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"bf9dd09.svg\",\"woman_and_man_holding_hands_tone2_tone4\":\"b177d3a.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"b177d3a.svg\",\"woman_and_man_holding_hands_tone2_tone5\":\"534b32d.svg\",\"woman_and_man_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"534b32d.svg\",\"woman_and_man_holding_hands_tone3_tone1\":\"c7dc261.svg\",\"woman_and_man_holding_hands_medium_skin_tone_light_skin_tone\":\"c7dc261.svg\",\"woman_and_man_holding_hands_tone3_tone2\":\"0bbaf07.svg\",\"woman_and_man_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"0bbaf07.svg\",\"woman_and_man_holding_hands_tone3\":\"4397176.svg\",\"woman_and_man_holding_hands_medium_skin_tone\":\"4397176.svg\",\"woman_and_man_holding_hands_tone3_tone4\":\"20a298a.svg\",\"woman_and_man_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"20a298a.svg\",\"woman_and_man_holding_hands_tone3_tone5\":\"0f5431e.svg\",\"woman_and_man_holding_hands_medium_skin_tone_dark_skin_tone\":\"0f5431e.svg\",\"woman_and_man_holding_hands_tone4_tone1\":\"49419da.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"49419da.svg\",\"woman_and_man_holding_hands_tone4_tone2\":\"9c70a54.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"9c70a54.svg\",\"woman_and_man_holding_hands_tone4_tone3\":\"1428bea.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"1428bea.svg\",\"woman_and_man_holding_hands_tone4\":\"ec98a92.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone\":\"ec98a92.svg\",\"woman_and_man_holding_hands_tone4_tone5\":\"ae856c7.svg\",\"woman_and_man_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"ae856c7.svg\",\"woman_and_man_holding_hands_tone5_tone1\":\"60a7744.svg\",\"woman_and_man_holding_hands_dark_skin_tone_light_skin_tone\":\"60a7744.svg\",\"woman_and_man_holding_hands_tone5_tone2\":\"ec2337f.svg\",\"woman_and_man_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"ec2337f.svg\",\"woman_and_man_holding_hands_tone5_tone3\":\"3c1d8c6.svg\",\"woman_and_man_holding_hands_dark_skin_tone_medium_skin_tone\":\"3c1d8c6.svg\",\"woman_and_man_holding_hands_tone5_tone4\":\"91c8276.svg\",\"woman_and_man_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"91c8276.svg\",\"woman_and_man_holding_hands_tone5\":\"c118d19.svg\",\"woman_and_man_holding_hands_dark_skin_tone\":\"c118d19.svg\",\"two_women_holding_hands\":\"d4d81a7.svg\",\"women_holding_hands_tone1\":\"9f3a904.svg\",\"women_holding_hands_light_skin_tone\":\"9f3a904.svg\",\"women_holding_hands_tone1_tone2\":\"f019f2d.svg\",\"women_holding_hands_light_skin_tone_medium_light_skin_tone\":\"f019f2d.svg\",\"women_holding_hands_tone1_tone3\":\"2b0d304.svg\",\"women_holding_hands_light_skin_tone_medium_skin_tone\":\"2b0d304.svg\",\"women_holding_hands_tone1_tone4\":\"ca03ea3.svg\",\"women_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"ca03ea3.svg\",\"women_holding_hands_tone1_tone5\":\"2e472d0.svg\",\"women_holding_hands_light_skin_tone_dark_skin_tone\":\"2e472d0.svg\",\"women_holding_hands_tone2_tone1\":\"10a59fd.svg\",\"women_holding_hands_medium_light_skin_tone_light_skin_tone\":\"10a59fd.svg\",\"women_holding_hands_tone2\":\"3957d42.svg\",\"women_holding_hands_medium_light_skin_tone\":\"3957d42.svg\",\"women_holding_hands_tone2_tone3\":\"dc3bab4.svg\",\"women_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"dc3bab4.svg\",\"women_holding_hands_tone2_tone4\":\"40b1b87.svg\",\"women_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"40b1b87.svg\",\"women_holding_hands_tone2_tone5\":\"3fe54bb.svg\",\"women_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"3fe54bb.svg\",\"women_holding_hands_tone3_tone1\":\"09efefb.svg\",\"women_holding_hands_medium_skin_tone_light_skin_tone\":\"09efefb.svg\",\"women_holding_hands_tone3_tone2\":\"2c1246c.svg\",\"women_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"2c1246c.svg\",\"women_holding_hands_tone3\":\"416f28b.svg\",\"women_holding_hands_medium_skin_tone\":\"416f28b.svg\",\"women_holding_hands_tone3_tone4\":\"42f3168.svg\",\"women_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"42f3168.svg\",\"women_holding_hands_tone3_tone5\":\"71f5c02.svg\",\"women_holding_hands_medium_skin_tone_dark_skin_tone\":\"71f5c02.svg\",\"women_holding_hands_tone4_tone1\":\"45391b2.svg\",\"women_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"45391b2.svg\",\"women_holding_hands_tone4_tone2\":\"61fa36f.svg\",\"women_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"61fa36f.svg\",\"women_holding_hands_tone4_tone3\":\"7fdd172.svg\",\"women_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"7fdd172.svg\",\"women_holding_hands_tone4\":\"e121f44.svg\",\"women_holding_hands_medium_dark_skin_tone\":\"e121f44.svg\",\"women_holding_hands_tone4_tone5\":\"b9907f1.svg\",\"women_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"b9907f1.svg\",\"women_holding_hands_tone5_tone1\":\"894fd21.svg\",\"women_holding_hands_dark_skin_tone_light_skin_tone\":\"894fd21.svg\",\"women_holding_hands_tone5_tone2\":\"30f422c.svg\",\"women_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"30f422c.svg\",\"women_holding_hands_tone5_tone3\":\"459c4cc.svg\",\"women_holding_hands_dark_skin_tone_medium_skin_tone\":\"459c4cc.svg\",\"women_holding_hands_tone5_tone4\":\"d2f51cf.svg\",\"women_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"d2f51cf.svg\",\"women_holding_hands_tone5\":\"cb0d7e2.svg\",\"women_holding_hands_dark_skin_tone\":\"cb0d7e2.svg\",\"two_men_holding_hands\":\"46278c1.svg\",\"men_holding_hands_tone1\":\"25a7f2b.svg\",\"men_holding_hands_light_skin_tone\":\"25a7f2b.svg\",\"men_holding_hands_tone1_tone2\":\"13e0905.svg\",\"men_holding_hands_light_skin_tone_medium_light_skin_tone\":\"13e0905.svg\",\"men_holding_hands_tone1_tone3\":\"7011592.svg\",\"men_holding_hands_light_skin_tone_medium_skin_tone\":\"7011592.svg\",\"men_holding_hands_tone1_tone4\":\"e5a0c51.svg\",\"men_holding_hands_light_skin_tone_medium_dark_skin_tone\":\"e5a0c51.svg\",\"men_holding_hands_tone1_tone5\":\"a07ee13.svg\",\"men_holding_hands_light_skin_tone_dark_skin_tone\":\"a07ee13.svg\",\"men_holding_hands_tone2_tone1\":\"2875f82.svg\",\"men_holding_hands_medium_light_skin_tone_light_skin_tone\":\"2875f82.svg\",\"men_holding_hands_tone2\":\"dcbf89b.svg\",\"men_holding_hands_medium_light_skin_tone\":\"dcbf89b.svg\",\"men_holding_hands_tone2_tone3\":\"3b37bb4.svg\",\"men_holding_hands_medium_light_skin_tone_medium_skin_tone\":\"3b37bb4.svg\",\"men_holding_hands_tone2_tone4\":\"28e9236.svg\",\"men_holding_hands_medium_light_skin_tone_medium_dark_skin_tone\":\"28e9236.svg\",\"men_holding_hands_tone2_tone5\":\"a96dce6.svg\",\"men_holding_hands_medium_light_skin_tone_dark_skin_tone\":\"a96dce6.svg\",\"men_holding_hands_tone3_tone1\":\"65628cf.svg\",\"men_holding_hands_medium_skin_tone_light_skin_tone\":\"65628cf.svg\",\"men_holding_hands_tone3_tone2\":\"742f722.svg\",\"men_holding_hands_medium_skin_tone_medium_light_skin_tone\":\"742f722.svg\",\"men_holding_hands_tone3\":\"ce0b97d.svg\",\"men_holding_hands_medium_skin_tone\":\"ce0b97d.svg\",\"men_holding_hands_tone3_tone4\":\"3c716d7.svg\",\"men_holding_hands_medium_skin_tone_medium_dark_skin_tone\":\"3c716d7.svg\",\"men_holding_hands_tone3_tone5\":\"cf7ed37.svg\",\"men_holding_hands_medium_skin_tone_dark_skin_tone\":\"cf7ed37.svg\",\"men_holding_hands_tone4_tone1\":\"0a49ab6.svg\",\"men_holding_hands_medium_dark_skin_tone_light_skin_tone\":\"0a49ab6.svg\",\"men_holding_hands_tone4_tone2\":\"3162d59.svg\",\"men_holding_hands_medium_dark_skin_tone_medium_light_skin_tone\":\"3162d59.svg\",\"men_holding_hands_tone4_tone3\":\"bc00cff.svg\",\"men_holding_hands_medium_dark_skin_tone_medium_skin_tone\":\"bc00cff.svg\",\"men_holding_hands_tone4\":\"56b1d4c.svg\",\"men_holding_hands_medium_dark_skin_tone\":\"56b1d4c.svg\",\"men_holding_hands_tone4_tone5\":\"6271f0e.svg\",\"men_holding_hands_medium_dark_skin_tone_dark_skin_tone\":\"6271f0e.svg\",\"men_holding_hands_tone5_tone1\":\"7c83af9.svg\",\"men_holding_hands_dark_skin_tone_light_skin_tone\":\"7c83af9.svg\",\"men_holding_hands_tone5_tone2\":\"09a7f65.svg\",\"men_holding_hands_dark_skin_tone_medium_light_skin_tone\":\"09a7f65.svg\",\"men_holding_hands_tone5_tone3\":\"b4c7538.svg\",\"men_holding_hands_dark_skin_tone_medium_skin_tone\":\"b4c7538.svg\",\"men_holding_hands_tone5_tone4\":\"4262f27.svg\",\"men_holding_hands_dark_skin_tone_medium_dark_skin_tone\":\"4262f27.svg\",\"men_holding_hands_tone5\":\"6d21918.svg\",\"men_holding_hands_dark_skin_tone\":\"6d21918.svg\",\"couple_with_heart\":\"af40bcf.svg\",\"couple_with_heart_tone1\":\"5f2b928.svg\",\"couple_with_heart_light_skin_tone\":\"5f2b928.svg\",\"couple_with_heart_person_person_tone1_tone2\":\"5176395.svg\",\"couple_with_heart_person_person_light_skin_tone_medium_light_skin_tone\":\"5176395.svg\",\"couple_with_heart_person_person_tone1_tone3\":\"08ddb48.svg\",\"couple_with_heart_person_person_light_skin_tone_medium_skin_tone\":\"08ddb48.svg\",\"couple_with_heart_person_person_tone1_tone4\":\"b660f3b.svg\",\"couple_with_heart_person_person_light_skin_tone_medium_dark_skin_tone\":\"b660f3b.svg\",\"couple_with_heart_person_person_tone1_tone5\":\"9a8cfb9.svg\",\"couple_with_heart_person_person_light_skin_tone_dark_skin_tone\":\"9a8cfb9.svg\",\"couple_with_heart_person_person_tone2_tone1\":\"d04e02d.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_light_skin_tone\":\"d04e02d.svg\",\"couple_with_heart_tone2\":\"fade9d8.svg\",\"couple_with_heart_medium_light_skin_tone\":\"fade9d8.svg\",\"couple_with_heart_person_person_tone2_tone3\":\"ab10672.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_medium_skin_tone\":\"ab10672.svg\",\"couple_with_heart_person_person_tone2_tone4\":\"4d7d08e.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_medium_dark_skin_tone\":\"4d7d08e.svg\",\"couple_with_heart_person_person_tone2_tone5\":\"d7ff730.svg\",\"couple_with_heart_person_person_medium_light_skin_tone_dark_skin_tone\":\"d7ff730.svg\",\"couple_with_heart_person_person_tone3_tone1\":\"54caa13.svg\",\"couple_with_heart_person_person_medium_skin_tone_light_skin_tone\":\"54caa13.svg\",\"couple_with_heart_person_person_tone3_tone2\":\"f511868.svg\",\"couple_with_heart_person_person_medium_skin_tone_medium_light_skin_tone\":\"f511868.svg\",\"couple_with_heart_tone3\":\"daf06ce.svg\",\"couple_with_heart_medium_skin_tone\":\"daf06ce.svg\",\"couple_with_heart_person_person_tone3_tone4\":\"7778d77.svg\",\"couple_with_heart_person_person_medium_skin_tone_medium_dark_skin_tone\":\"7778d77.svg\",\"couple_with_heart_person_person_tone3_tone5\":\"976cf0c.svg\",\"couple_with_heart_person_person_medium_skin_tone_dark_skin_tone\":\"976cf0c.svg\",\"couple_with_heart_person_person_tone4_tone1\":\"d50905a.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_light_skin_tone\":\"d50905a.svg\",\"couple_with_heart_person_person_tone4_tone2\":\"0c9e773.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_medium_light_skin_tone\":\"0c9e773.svg\",\"couple_with_heart_person_person_tone4_tone3\":\"c9530eb.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_medium_skin_tone\":\"c9530eb.svg\",\"couple_with_heart_tone4\":\"94dfc9e.svg\",\"couple_with_heart_medium_dark_skin_tone\":\"94dfc9e.svg\",\"couple_with_heart_person_person_tone4_tone5\":\"3176f7e.svg\",\"couple_with_heart_person_person_medium_dark_skin_tone_dark_skin_tone\":\"3176f7e.svg\",\"couple_with_heart_person_person_tone5_tone1\":\"ad8ed70.svg\",\"couple_with_heart_person_person_dark_skin_tone_light_skin_tone\":\"ad8ed70.svg\",\"couple_with_heart_person_person_tone5_tone2\":\"df4b6c5.svg\",\"couple_with_heart_person_person_dark_skin_tone_medium_light_skin_tone\":\"df4b6c5.svg\",\"couple_with_heart_person_person_tone5_tone3\":\"fa7c3a9.svg\",\"couple_with_heart_person_person_dark_skin_tone_medium_skin_tone\":\"fa7c3a9.svg\",\"couple_with_heart_person_person_tone5_tone4\":\"76912c3.svg\",\"couple_with_heart_person_person_dark_skin_tone_medium_dark_skin_tone\":\"76912c3.svg\",\"couple_with_heart_tone5\":\"fa72e85.svg\",\"couple_with_heart_dark_skin_tone\":\"fa72e85.svg\",\"couple_with_heart_woman_man\":\"4ba9ae9.svg\",\"couple_with_heart_woman_man_tone1\":\"ee4737f.svg\",\"couple_with_heart_woman_man_light_skin_tone\":\"ee4737f.svg\",\"couple_with_heart_woman_man_tone1_tone2\":\"b7abde9.svg\",\"couple_with_heart_woman_man_light_skin_tone_medium_light_skin_tone\":\"b7abde9.svg\",\"couple_with_heart_woman_man_tone1_tone3\":\"25501c0.svg\",\"couple_with_heart_woman_man_light_skin_tone_medium_skin_tone\":\"25501c0.svg\",\"couple_with_heart_woman_man_tone1_tone4\":\"aa39f5c.svg\",\"couple_with_heart_woman_man_light_skin_tone_medium_dark_skin_tone\":\"aa39f5c.svg\",\"couple_with_heart_woman_man_tone1_tone5\":\"bf2d719.svg\",\"couple_with_heart_woman_man_light_skin_tone_dark_skin_tone\":\"bf2d719.svg\",\"couple_with_heart_woman_man_tone2_tone1\":\"6849f0b.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_light_skin_tone\":\"6849f0b.svg\",\"couple_with_heart_woman_man_tone2\":\"b2436ae.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone\":\"b2436ae.svg\",\"couple_with_heart_woman_man_tone2_tone3\":\"772964b.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_medium_skin_tone\":\"772964b.svg\",\"couple_with_heart_woman_man_tone2_tone4\":\"4d268fe.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_medium_dark_skin_tone\":\"4d268fe.svg\",\"couple_with_heart_woman_man_tone2_tone5\":\"0c875ad.svg\",\"couple_with_heart_woman_man_medium_light_skin_tone_dark_skin_tone\":\"0c875ad.svg\",\"couple_with_heart_woman_man_tone3_tone1\":\"9980aeb.svg\",\"couple_with_heart_woman_man_medium_skin_tone_light_skin_tone\":\"9980aeb.svg\",\"couple_with_heart_woman_man_tone3_tone2\":\"29ecd32.svg\",\"couple_with_heart_woman_man_medium_skin_tone_medium_light_skin_tone\":\"29ecd32.svg\",\"couple_with_heart_woman_man_tone3\":\"205b89c.svg\",\"couple_with_heart_woman_man_medium_skin_tone\":\"205b89c.svg\",\"couple_with_heart_woman_man_tone3_tone4\":\"9409034.svg\",\"couple_with_heart_woman_man_medium_skin_tone_medium_dark_skin_tone\":\"9409034.svg\",\"couple_with_heart_woman_man_tone3_tone5\":\"1473a1f.svg\",\"couple_with_heart_woman_man_medium_skin_tone_dark_skin_tone\":\"1473a1f.svg\",\"couple_with_heart_woman_man_tone4_tone1\":\"5e38999.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_light_skin_tone\":\"5e38999.svg\",\"couple_with_heart_woman_man_tone4_tone2\":\"4d463ce.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_medium_light_skin_tone\":\"4d463ce.svg\",\"couple_with_heart_woman_man_tone4_tone3\":\"1f3c617.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_medium_skin_tone\":\"1f3c617.svg\",\"couple_with_heart_woman_man_tone4\":\"64d398a.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone\":\"64d398a.svg\",\"couple_with_heart_woman_man_tone4_tone5\":\"b5d64a8.svg\",\"couple_with_heart_woman_man_medium_dark_skin_tone_dark_skin_tone\":\"b5d64a8.svg\",\"couple_with_heart_woman_man_tone5_tone1\":\"e31437a.svg\",\"couple_with_heart_woman_man_dark_skin_tone_light_skin_tone\":\"e31437a.svg\",\"couple_with_heart_woman_man_tone5_tone2\":\"763373b.svg\",\"couple_with_heart_woman_man_dark_skin_tone_medium_light_skin_tone\":\"763373b.svg\",\"couple_with_heart_woman_man_tone5_tone3\":\"847a67d.svg\",\"couple_with_heart_woman_man_dark_skin_tone_medium_skin_tone\":\"847a67d.svg\",\"couple_with_heart_woman_man_tone5_tone4\":\"5c7b670.svg\",\"couple_with_heart_woman_man_dark_skin_tone_medium_dark_skin_tone\":\"5c7b670.svg\",\"couple_with_heart_woman_man_tone5\":\"e2192ab.svg\",\"couple_with_heart_woman_man_dark_skin_tone\":\"e2192ab.svg\",\"couple_ww\":\"a273046.svg\",\"couple_with_heart_ww\":\"a273046.svg\",\"couple_with_heart_woman_woman_tone1\":\"71a7732.svg\",\"couple_with_heart_woman_woman_light_skin_tone\":\"71a7732.svg\",\"couple_with_heart_woman_woman_tone1_tone2\":\"5b57cfd.svg\",\"couple_with_heart_woman_woman_light_skin_tone_medium_light_skin_tone\":\"5b57cfd.svg\",\"couple_with_heart_woman_woman_tone1_tone3\":\"83b48c0.svg\",\"couple_with_heart_woman_woman_light_skin_tone_medium_skin_tone\":\"83b48c0.svg\",\"couple_with_heart_woman_woman_tone1_tone4\":\"2167b7b.svg\",\"couple_with_heart_woman_woman_light_skin_tone_medium_dark_skin_tone\":\"2167b7b.svg\",\"couple_with_heart_woman_woman_tone1_tone5\":\"5291555.svg\",\"couple_with_heart_woman_woman_light_skin_tone_dark_skin_tone\":\"5291555.svg\",\"couple_with_heart_woman_woman_tone2_tone1\":\"7d11633.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_light_skin_tone\":\"7d11633.svg\",\"couple_with_heart_woman_woman_tone2\":\"4e8354b.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone\":\"4e8354b.svg\",\"couple_with_heart_woman_woman_tone2_tone3\":\"e816ed2.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_medium_skin_tone\":\"e816ed2.svg\",\"couple_with_heart_woman_woman_tone2_tone4\":\"6149103.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_medium_dark_skin_tone\":\"6149103.svg\",\"couple_with_heart_woman_woman_tone2_tone5\":\"68c7223.svg\",\"couple_with_heart_woman_woman_medium_light_skin_tone_dark_skin_tone\":\"68c7223.svg\",\"couple_with_heart_woman_woman_tone3_tone1\":\"9cb0a5b.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_light_skin_tone\":\"9cb0a5b.svg\",\"couple_with_heart_woman_woman_tone3_tone2\":\"a3389b9.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_medium_light_skin_tone\":\"a3389b9.svg\",\"couple_with_heart_woman_woman_tone3\":\"ca8af0f.svg\",\"couple_with_heart_woman_woman_medium_skin_tone\":\"ca8af0f.svg\",\"couple_with_heart_woman_woman_tone3_tone4\":\"b5ddb1d.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_medium_dark_skin_tone\":\"b5ddb1d.svg\",\"couple_with_heart_woman_woman_tone3_tone5\":\"312590d.svg\",\"couple_with_heart_woman_woman_medium_skin_tone_dark_skin_tone\":\"312590d.svg\",\"couple_with_heart_woman_woman_tone4_tone1\":\"cee38d3.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_light_skin_tone\":\"cee38d3.svg\",\"couple_with_heart_woman_woman_tone4_tone2\":\"2c3e8c7.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_medium_light_skin_tone\":\"2c3e8c7.svg\",\"couple_with_heart_woman_woman_tone4_tone3\":\"b31f429.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_medium_skin_tone\":\"b31f429.svg\",\"couple_with_heart_woman_woman_tone4\":\"ca98fa7.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone\":\"ca98fa7.svg\",\"couple_with_heart_woman_woman_tone4_tone5\":\"a30be68.svg\",\"couple_with_heart_woman_woman_medium_dark_skin_tone_dark_skin_tone\":\"a30be68.svg\",\"couple_with_heart_woman_woman_tone5_tone1\":\"45894b5.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_light_skin_tone\":\"45894b5.svg\",\"couple_with_heart_woman_woman_tone5_tone2\":\"f30a655.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_medium_light_skin_tone\":\"f30a655.svg\",\"couple_with_heart_woman_woman_tone5_tone3\":\"59ca073.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_medium_skin_tone\":\"59ca073.svg\",\"couple_with_heart_woman_woman_tone5_tone4\":\"05e04ee.svg\",\"couple_with_heart_woman_woman_dark_skin_tone_medium_dark_skin_tone\":\"05e04ee.svg\",\"couple_with_heart_woman_woman_tone5\":\"bc34159.svg\",\"couple_with_heart_woman_woman_dark_skin_tone\":\"bc34159.svg\",\"couple_mm\":\"4f72e4d.svg\",\"couple_with_heart_mm\":\"4f72e4d.svg\",\"couple_with_heart_man_man_tone1\":\"e23ddc3.svg\",\"couple_with_heart_man_man_light_skin_tone\":\"e23ddc3.svg\",\"couple_with_heart_man_man_tone1_tone2\":\"727d29b.svg\",\"couple_with_heart_man_man_light_skin_tone_medium_light_skin_tone\":\"727d29b.svg\",\"couple_with_heart_man_man_tone1_tone3\":\"d92a25b.svg\",\"couple_with_heart_man_man_light_skin_tone_medium_skin_tone\":\"d92a25b.svg\",\"couple_with_heart_man_man_tone1_tone4\":\"7f8af18.svg\",\"couple_with_heart_man_man_light_skin_tone_medium_dark_skin_tone\":\"7f8af18.svg\",\"couple_with_heart_man_man_tone1_tone5\":\"801610f.svg\",\"couple_with_heart_man_man_light_skin_tone_dark_skin_tone\":\"801610f.svg\",\"couple_with_heart_man_man_tone2_tone1\":\"188b556.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_light_skin_tone\":\"188b556.svg\",\"couple_with_heart_man_man_tone2\":\"ea0b8e8.svg\",\"couple_with_heart_man_man_medium_light_skin_tone\":\"ea0b8e8.svg\",\"couple_with_heart_man_man_tone2_tone3\":\"cdd6d98.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_medium_skin_tone\":\"cdd6d98.svg\",\"couple_with_heart_man_man_tone2_tone4\":\"5c8241d.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_medium_dark_skin_tone\":\"5c8241d.svg\",\"couple_with_heart_man_man_tone2_tone5\":\"940ccbc.svg\",\"couple_with_heart_man_man_medium_light_skin_tone_dark_skin_tone\":\"940ccbc.svg\",\"couple_with_heart_man_man_tone3_tone1\":\"5f78671.svg\",\"couple_with_heart_man_man_medium_skin_tone_light_skin_tone\":\"5f78671.svg\",\"couple_with_heart_man_man_tone3_tone2\":\"668c44a.svg\",\"couple_with_heart_man_man_medium_skin_tone_medium_light_skin_tone\":\"668c44a.svg\",\"couple_with_heart_man_man_tone3\":\"391f2e8.svg\",\"couple_with_heart_man_man_medium_skin_tone\":\"391f2e8.svg\",\"couple_with_heart_man_man_tone3_tone4\":\"bd2bbda.svg\",\"couple_with_heart_man_man_medium_skin_tone_medium_dark_skin_tone\":\"bd2bbda.svg\",\"couple_with_heart_man_man_tone3_tone5\":\"5432ce1.svg\",\"couple_with_heart_man_man_medium_skin_tone_dark_skin_tone\":\"5432ce1.svg\",\"couple_with_heart_man_man_tone4_tone1\":\"311f33b.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_light_skin_tone\":\"311f33b.svg\",\"couple_with_heart_man_man_tone4_tone2\":\"25ff44f.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_medium_light_skin_tone\":\"25ff44f.svg\",\"couple_with_heart_man_man_tone4_tone3\":\"2fcfd65.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_medium_skin_tone\":\"2fcfd65.svg\",\"couple_with_heart_man_man_tone4\":\"eeda17f.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone\":\"eeda17f.svg\",\"couple_with_heart_man_man_tone4_tone5\":\"9b6398f.svg\",\"couple_with_heart_man_man_medium_dark_skin_tone_dark_skin_tone\":\"9b6398f.svg\",\"couple_with_heart_man_man_tone5_tone1\":\"941a640.svg\",\"couple_with_heart_man_man_dark_skin_tone_light_skin_tone\":\"941a640.svg\",\"couple_with_heart_man_man_tone5_tone2\":\"41c12de.svg\",\"couple_with_heart_man_man_dark_skin_tone_medium_light_skin_tone\":\"41c12de.svg\",\"couple_with_heart_man_man_tone5_tone3\":\"d5c2770.svg\",\"couple_with_heart_man_man_dark_skin_tone_medium_skin_tone\":\"d5c2770.svg\",\"couple_with_heart_man_man_tone5_tone4\":\"3601c55.svg\",\"couple_with_heart_man_man_dark_skin_tone_medium_dark_skin_tone\":\"3601c55.svg\",\"couple_with_heart_man_man_tone5\":\"53a595a.svg\",\"couple_with_heart_man_man_dark_skin_tone\":\"53a595a.svg\",\"couplekiss\":\"50e9765.svg\",\"kiss_tone1\":\"e8abe66.svg\",\"kiss_light_skin_tone\":\"e8abe66.svg\",\"kiss_person_person_tone1_tone2\":\"5a8a06f.svg\",\"kiss_person_person_light_skin_tone_medium_light_skin_tone\":\"5a8a06f.svg\",\"kiss_person_person_tone1_tone3\":\"267fbc6.svg\",\"kiss_person_person_light_skin_tone_medium_skin_tone\":\"267fbc6.svg\",\"kiss_person_person_tone1_tone4\":\"2709814.svg\",\"kiss_person_person_light_skin_tone_medium_dark_skin_tone\":\"2709814.svg\",\"kiss_person_person_tone1_tone5\":\"5d74f10.svg\",\"kiss_person_person_light_skin_tone_dark_skin_tone\":\"5d74f10.svg\",\"kiss_person_person_tone2_tone1\":\"2a88f80.svg\",\"kiss_person_person_medium_light_skin_tone_light_skin_tone\":\"2a88f80.svg\",\"kiss_tone2\":\"7135329.svg\",\"kiss_medium_light_skin_tone\":\"7135329.svg\",\"kiss_person_person_tone2_tone3\":\"d8627da.svg\",\"kiss_person_person_medium_light_skin_tone_medium_skin_tone\":\"d8627da.svg\",\"kiss_person_person_tone2_tone4\":\"6fb3187.svg\",\"kiss_person_person_medium_light_skin_tone_medium_dark_skin_tone\":\"6fb3187.svg\",\"kiss_person_person_tone2_tone5\":\"c824563.svg\",\"kiss_person_person_medium_light_skin_tone_dark_skin_tone\":\"c824563.svg\",\"kiss_person_person_tone3_tone1\":\"9e29515.svg\",\"kiss_person_person_medium_skin_tone_light_skin_tone\":\"9e29515.svg\",\"kiss_person_person_tone3_tone2\":\"d2e0f25.svg\",\"kiss_person_person_medium_skin_tone_medium_light_skin_tone\":\"d2e0f25.svg\",\"kiss_tone3\":\"9d00a50.svg\",\"kiss_medium_skin_tone\":\"9d00a50.svg\",\"kiss_person_person_tone3_tone4\":\"0a6fff3.svg\",\"kiss_person_person_medium_skin_tone_medium_dark_skin_tone\":\"0a6fff3.svg\",\"kiss_person_person_tone3_tone5\":\"3daef15.svg\",\"kiss_person_person_medium_skin_tone_dark_skin_tone\":\"3daef15.svg\",\"kiss_person_person_tone4_tone1\":\"eabe6ef.svg\",\"kiss_person_person_medium_dark_skin_tone_light_skin_tone\":\"eabe6ef.svg\",\"kiss_person_person_tone4_tone2\":\"55e735c.svg\",\"kiss_person_person_medium_dark_skin_tone_medium_light_skin_tone\":\"55e735c.svg\",\"kiss_person_person_tone4_tone3\":\"d8da4fc.svg\",\"kiss_person_person_medium_dark_skin_tone_medium_skin_tone\":\"d8da4fc.svg\",\"kiss_tone4\":\"0d01700.svg\",\"kiss_medium_dark_skin_tone\":\"0d01700.svg\",\"kiss_person_person_tone4_tone5\":\"388581e.svg\",\"kiss_person_person_medium_dark_skin_tone_dark_skin_tone\":\"388581e.svg\",\"kiss_person_person_tone5_tone1\":\"9ee87dc.svg\",\"kiss_person_person_dark_skin_tone_light_skin_tone\":\"9ee87dc.svg\",\"kiss_person_person_tone5_tone2\":\"128699b.svg\",\"kiss_person_person_dark_skin_tone_medium_light_skin_tone\":\"128699b.svg\",\"kiss_person_person_tone5_tone3\":\"366a841.svg\",\"kiss_person_person_dark_skin_tone_medium_skin_tone\":\"366a841.svg\",\"kiss_person_person_tone5_tone4\":\"15f3606.svg\",\"kiss_person_person_dark_skin_tone_medium_dark_skin_tone\":\"15f3606.svg\",\"kiss_tone5\":\"2fc44b6.svg\",\"kiss_dark_skin_tone\":\"2fc44b6.svg\",\"kiss_woman_man\":\"0dbcb90.svg\",\"kiss_woman_man_tone1\":\"057900f.svg\",\"kiss_woman_man_light_skin_tone\":\"057900f.svg\",\"kiss_woman_man_tone1_tone2\":\"e10e63e.svg\",\"kiss_woman_man_light_skin_tone_medium_light_skin_tone\":\"e10e63e.svg\",\"kiss_woman_man_tone1_tone3\":\"9bfefc3.svg\",\"kiss_woman_man_light_skin_tone_medium_skin_tone\":\"9bfefc3.svg\",\"kiss_woman_man_tone1_tone4\":\"c32ee52.svg\",\"kiss_woman_man_light_skin_tone_medium_dark_skin_tone\":\"c32ee52.svg\",\"kiss_woman_man_tone1_tone5\":\"2f31920.svg\",\"kiss_woman_man_light_skin_tone_dark_skin_tone\":\"2f31920.svg\",\"kiss_woman_man_tone2_tone1\":\"0d96135.svg\",\"kiss_woman_man_medium_light_skin_tone_light_skin_tone\":\"0d96135.svg\",\"kiss_woman_man_tone2\":\"a6f4310.svg\",\"kiss_woman_man_medium_light_skin_tone\":\"a6f4310.svg\",\"kiss_woman_man_tone2_tone3\":\"70cb75b.svg\",\"kiss_woman_man_medium_light_skin_tone_medium_skin_tone\":\"70cb75b.svg\",\"kiss_woman_man_tone2_tone4\":\"e78c495.svg\",\"kiss_woman_man_medium_light_skin_tone_medium_dark_skin_tone\":\"e78c495.svg\",\"kiss_woman_man_tone2_tone5\":\"5185f3c.svg\",\"kiss_woman_man_medium_light_skin_tone_dark_skin_tone\":\"5185f3c.svg\",\"kiss_woman_man_tone3_tone1\":\"ae871f6.svg\",\"kiss_woman_man_medium_skin_tone_light_skin_tone\":\"ae871f6.svg\",\"kiss_woman_man_tone3_tone2\":\"7d7c436.svg\",\"kiss_woman_man_medium_skin_tone_medium_light_skin_tone\":\"7d7c436.svg\",\"kiss_woman_man_tone3\":\"5fc84ac.svg\",\"kiss_woman_man_medium_skin_tone\":\"5fc84ac.svg\",\"kiss_woman_man_tone3_tone4\":\"2a54f60.svg\",\"kiss_woman_man_medium_skin_tone_medium_dark_skin_tone\":\"2a54f60.svg\",\"kiss_woman_man_tone3_tone5\":\"65f1649.svg\",\"kiss_woman_man_medium_skin_tone_dark_skin_tone\":\"65f1649.svg\",\"kiss_woman_man_tone4_tone1\":\"164ff1c.svg\",\"kiss_woman_man_medium_dark_skin_tone_light_skin_tone\":\"164ff1c.svg\",\"kiss_woman_man_tone4_tone2\":\"5cc97f6.svg\",\"kiss_woman_man_medium_dark_skin_tone_medium_light_skin_tone\":\"5cc97f6.svg\",\"kiss_woman_man_tone4_tone3\":\"e4dbeff.svg\",\"kiss_woman_man_medium_dark_skin_tone_medium_skin_tone\":\"e4dbeff.svg\",\"kiss_woman_man_tone4\":\"6d9c654.svg\",\"kiss_woman_man_medium_dark_skin_tone\":\"6d9c654.svg\",\"kiss_woman_man_tone4_tone5\":\"2b44647.svg\",\"kiss_woman_man_medium_dark_skin_tone_dark_skin_tone\":\"2b44647.svg\",\"kiss_woman_man_tone5_tone1\":\"c294edc.svg\",\"kiss_woman_man_dark_skin_tone_light_skin_tone\":\"c294edc.svg\",\"kiss_woman_man_tone5_tone2\":\"c83598f.svg\",\"kiss_woman_man_dark_skin_tone_medium_light_skin_tone\":\"c83598f.svg\",\"kiss_woman_man_tone5_tone3\":\"9b6ff37.svg\",\"kiss_woman_man_dark_skin_tone_medium_skin_tone\":\"9b6ff37.svg\",\"kiss_woman_man_tone5_tone4\":\"c8a9736.svg\",\"kiss_woman_man_dark_skin_tone_medium_dark_skin_tone\":\"c8a9736.svg\",\"kiss_woman_man_tone5\":\"20884e4.svg\",\"kiss_woman_man_dark_skin_tone\":\"20884e4.svg\",\"kiss_ww\":\"8178a91.svg\",\"couplekiss_ww\":\"8178a91.svg\",\"kiss_woman_woman_tone1\":\"f0778b5.svg\",\"kiss_woman_woman_light_skin_tone\":\"f0778b5.svg\",\"kiss_woman_woman_tone1_tone2\":\"903034d.svg\",\"kiss_woman_woman_light_skin_tone_medium_light_skin_tone\":\"903034d.svg\",\"kiss_woman_woman_tone1_tone3\":\"fe2f2c4.svg\",\"kiss_woman_woman_light_skin_tone_medium_skin_tone\":\"fe2f2c4.svg\",\"kiss_woman_woman_tone1_tone4\":\"b4d4817.svg\",\"kiss_woman_woman_light_skin_tone_medium_dark_skin_tone\":\"b4d4817.svg\",\"kiss_woman_woman_tone1_tone5\":\"d9d2b03.svg\",\"kiss_woman_woman_light_skin_tone_dark_skin_tone\":\"d9d2b03.svg\",\"kiss_woman_woman_tone2_tone1\":\"ae1d840.svg\",\"kiss_woman_woman_medium_light_skin_tone_light_skin_tone\":\"ae1d840.svg\",\"kiss_woman_woman_tone2\":\"bbab6f1.svg\",\"kiss_woman_woman_medium_light_skin_tone\":\"bbab6f1.svg\",\"kiss_woman_woman_tone2_tone3\":\"cc08ac5.svg\",\"kiss_woman_woman_medium_light_skin_tone_medium_skin_tone\":\"cc08ac5.svg\",\"kiss_woman_woman_tone2_tone4\":\"4435887.svg\",\"kiss_woman_woman_medium_light_skin_tone_medium_dark_skin_tone\":\"4435887.svg\",\"kiss_woman_woman_tone2_tone5\":\"ac198a6.svg\",\"kiss_woman_woman_medium_light_skin_tone_dark_skin_tone\":\"ac198a6.svg\",\"kiss_woman_woman_tone3_tone1\":\"c5422f9.svg\",\"kiss_woman_woman_medium_skin_tone_light_skin_tone\":\"c5422f9.svg\",\"kiss_woman_woman_tone3_tone2\":\"956ccaa.svg\",\"kiss_woman_woman_medium_skin_tone_medium_light_skin_tone\":\"956ccaa.svg\",\"kiss_woman_woman_tone3\":\"b93bbe7.svg\",\"kiss_woman_woman_medium_skin_tone\":\"b93bbe7.svg\",\"kiss_woman_woman_tone3_tone4\":\"854faa6.svg\",\"kiss_woman_woman_medium_skin_tone_medium_dark_skin_tone\":\"854faa6.svg\",\"kiss_woman_woman_tone3_tone5\":\"3fbb3c6.svg\",\"kiss_woman_woman_medium_skin_tone_dark_skin_tone\":\"3fbb3c6.svg\",\"kiss_woman_woman_tone4_tone1\":\"37b681c.svg\",\"kiss_woman_woman_medium_dark_skin_tone_light_skin_tone\":\"37b681c.svg\",\"kiss_woman_woman_tone4_tone2\":\"7c4d4cd.svg\",\"kiss_woman_woman_medium_dark_skin_tone_medium_light_skin_tone\":\"7c4d4cd.svg\",\"kiss_woman_woman_tone4_tone3\":\"7c4edd2.svg\",\"kiss_woman_woman_medium_dark_skin_tone_medium_skin_tone\":\"7c4edd2.svg\",\"kiss_woman_woman_tone4\":\"e789a7e.svg\",\"kiss_woman_woman_medium_dark_skin_tone\":\"e789a7e.svg\",\"kiss_woman_woman_tone4_tone5\":\"28414d1.svg\",\"kiss_woman_woman_medium_dark_skin_tone_dark_skin_tone\":\"28414d1.svg\",\"kiss_woman_woman_tone5_tone1\":\"171e3ec.svg\",\"kiss_woman_woman_dark_skin_tone_light_skin_tone\":\"171e3ec.svg\",\"kiss_woman_woman_tone5_tone2\":\"4f115af.svg\",\"kiss_woman_woman_dark_skin_tone_medium_light_skin_tone\":\"4f115af.svg\",\"kiss_woman_woman_tone5_tone3\":\"7a92f09.svg\",\"kiss_woman_woman_dark_skin_tone_medium_skin_tone\":\"7a92f09.svg\",\"kiss_woman_woman_tone5_tone4\":\"68ff21c.svg\",\"kiss_woman_woman_dark_skin_tone_medium_dark_skin_tone\":\"68ff21c.svg\",\"kiss_woman_woman_tone5\":\"a2d3381.svg\",\"kiss_woman_woman_dark_skin_tone\":\"a2d3381.svg\",\"kiss_mm\":\"6967070.svg\",\"couplekiss_mm\":\"6967070.svg\",\"kiss_man_man\":\"6967070.svg\",\"kiss_man_man_tone1\":\"daebf04.svg\",\"kiss_man_man_light_skin_tone\":\"daebf04.svg\",\"kiss_man_man_tone1_tone2\":\"aaf5148.svg\",\"kiss_man_man_light_skin_tone_medium_light_skin_tone\":\"aaf5148.svg\",\"kiss_man_man_tone1_tone3\":\"4fe3ff4.svg\",\"kiss_man_man_light_skin_tone_medium_skin_tone\":\"4fe3ff4.svg\",\"kiss_man_man_tone1_tone4\":\"8b5b118.svg\",\"kiss_man_man_light_skin_tone_medium_dark_skin_tone\":\"8b5b118.svg\",\"kiss_man_man_tone1_tone5\":\"a63dd18.svg\",\"kiss_man_man_light_skin_tone_dark_skin_tone\":\"a63dd18.svg\",\"kiss_man_man_tone2_tone1\":\"1176193.svg\",\"kiss_man_man_medium_light_skin_tone_light_skin_tone\":\"1176193.svg\",\"kiss_man_man_tone2\":\"d1e279e.svg\",\"kiss_man_man_medium_light_skin_tone\":\"d1e279e.svg\",\"kiss_man_man_tone2_tone3\":\"5010cc5.svg\",\"kiss_man_man_medium_light_skin_tone_medium_skin_tone\":\"5010cc5.svg\",\"kiss_man_man_tone2_tone4\":\"97365b5.svg\",\"kiss_man_man_medium_light_skin_tone_medium_dark_skin_tone\":\"97365b5.svg\",\"kiss_man_man_tone2_tone5\":\"a03f828.svg\",\"kiss_man_man_medium_light_skin_tone_dark_skin_tone\":\"a03f828.svg\",\"kiss_man_man_tone3_tone1\":\"5cf78cd.svg\",\"kiss_man_man_medium_skin_tone_light_skin_tone\":\"5cf78cd.svg\",\"kiss_man_man_tone3_tone2\":\"eec1671.svg\",\"kiss_man_man_medium_skin_tone_medium_light_skin_tone\":\"eec1671.svg\",\"kiss_man_man_tone3\":\"ac16467.svg\",\"kiss_man_man_medium_skin_tone\":\"ac16467.svg\",\"kiss_man_man_tone3_tone4\":\"1f65a21.svg\",\"kiss_man_man_medium_skin_tone_medium_dark_skin_tone\":\"1f65a21.svg\",\"kiss_man_man_tone3_tone5\":\"2571aa8.svg\",\"kiss_man_man_medium_skin_tone_dark_skin_tone\":\"2571aa8.svg\",\"kiss_man_man_tone4_tone1\":\"ae94cdd.svg\",\"kiss_man_man_medium_dark_skin_tone_light_skin_tone\":\"ae94cdd.svg\",\"kiss_man_man_tone4_tone2\":\"af98b91.svg\",\"kiss_man_man_medium_dark_skin_tone_medium_light_skin_tone\":\"af98b91.svg\",\"kiss_man_man_tone4_tone3\":\"a5938b1.svg\",\"kiss_man_man_medium_dark_skin_tone_medium_skin_tone\":\"a5938b1.svg\",\"kiss_man_man_tone4\":\"cfbc60b.svg\",\"kiss_man_man_medium_dark_skin_tone\":\"cfbc60b.svg\",\"kiss_man_man_tone4_tone5\":\"23a3035.svg\",\"kiss_man_man_medium_dark_skin_tone_dark_skin_tone\":\"23a3035.svg\",\"kiss_man_man_tone5_tone1\":\"97c98e7.svg\",\"kiss_man_man_dark_skin_tone_light_skin_tone\":\"97c98e7.svg\",\"kiss_man_man_tone5_tone2\":\"f053a7d.svg\",\"kiss_man_man_dark_skin_tone_medium_light_skin_tone\":\"f053a7d.svg\",\"kiss_man_man_tone5_tone3\":\"6c64227.svg\",\"kiss_man_man_dark_skin_tone_medium_skin_tone\":\"6c64227.svg\",\"kiss_man_man_tone5_tone4\":\"bafdd3d.svg\",\"kiss_man_man_dark_skin_tone_medium_dark_skin_tone\":\"bafdd3d.svg\",\"kiss_man_man_tone5\":\"7a365d5.svg\",\"kiss_man_man_dark_skin_tone\":\"7a365d5.svg\",\"family\":\"f3080a8.svg\",\"family_man_woman_boy\":\"8ce0110.svg\",\"family_mwg\":\"54714d0.svg\",\"family_mwgb\":\"648ad9c.svg\",\"family_mwbb\":\"0731ba7.svg\",\"family_mwgg\":\"bfc9af4.svg\",\"family_wwb\":\"f89180c.svg\",\"family_wwg\":\"e3e4078.svg\",\"family_wwgb\":\"f12cc9f.svg\",\"family_wwbb\":\"944c106.svg\",\"family_wwgg\":\"68381fa.svg\",\"family_mmb\":\"0e8aeea.svg\",\"family_mmg\":\"1327dff.svg\",\"family_mmgb\":\"5daa081.svg\",\"family_mmbb\":\"fe59165.svg\",\"family_mmgg\":\"5e3f235.svg\",\"family_woman_boy\":\"62fa5ed.svg\",\"family_woman_girl\":\"686ecb5.svg\",\"family_woman_girl_boy\":\"9520cae.svg\",\"family_woman_boy_boy\":\"d50fdf4.svg\",\"family_woman_girl_girl\":\"f08e120.svg\",\"family_man_boy\":\"debae09.svg\",\"family_man_girl\":\"e097176.svg\",\"family_man_girl_boy\":\"6e8be23.svg\",\"family_man_boy_boy\":\"80017f3.svg\",\"family_man_girl_girl\":\"1d95b13.svg\",\"knot\":\"4853ab7.svg\",\"yarn\":\"43e5942.svg\",\"thread\":\"6f01cd8.svg\",\"sewing_needle\":\"3322d7c.svg\",\"coat\":\"a756b6d.svg\",\"lab_coat\":\"c22bdeb.svg\",\"safety_vest\":\"fe1b8e4.svg\",\"womans_clothes\":\"7683d2c.svg\",\"shirt\":\"0e8e17d.svg\",\"t_shirt\":\"0e8e17d.svg\",\"jeans\":\"74254b8.svg\",\"briefs\":\"d44cc00.svg\",\"shorts\":\"c1719f0.svg\",\"necktie\":\"bcfe0da.svg\",\"dress\":\"bcd31ac.svg\",\"bikini\":\"ad60a01.svg\",\"one_piece_swimsuit\":\"5ba709f.svg\",\"kimono\":\"ef81375.svg\",\"sari\":\"1e29b67.svg\",\"thong_sandal\":\"5e729f4.svg\",\"womans_flat_shoe\":\"3c3719b.svg\",\"flat_shoe\":\"3c3719b.svg\",\"high_heel\":\"324bebb.svg\",\"sandal\":\"1ded3e6.svg\",\"womans_sandal\":\"1ded3e6.svg\",\"boot\":\"ae22de3.svg\",\"womans_boot\":\"ae22de3.svg\",\"mans_shoe\":\"7162529.svg\",\"athletic_shoe\":\"0f41eb5.svg\",\"running_shoe\":\"0f41eb5.svg\",\"hiking_boot\":\"20ea4c3.svg\",\"socks\":\"10bf122.svg\",\"gloves\":\"827eb70.svg\",\"scarf\":\"0a15c48.svg\",\"tophat\":\"527228e.svg\",\"top_hat\":\"527228e.svg\",\"billed_cap\":\"cb444a5.svg\",\"womans_hat\":\"6176a41.svg\",\"mortar_board\":\"e26973e.svg\",\"helmet_with_cross\":\"135808c.svg\",\"helmet_with_white_cross\":\"135808c.svg\",\"military_helmet\":\"54f8c27.svg\",\"crown\":\"c3e9e36.svg\",\"ring\":\"2014936.svg\",\"pouch\":\"b371954.svg\",\"clutch_bag\":\"b371954.svg\",\"purse\":\"51824e6.svg\",\"handbag\":\"f5f7c00.svg\",\"briefcase\":\"08f6139.svg\",\"school_satchel\":\"af42baa.svg\",\"backpack\":\"af42baa.svg\",\"luggage\":\"f62ce09.svg\",\"eyeglasses\":\"23837f2.svg\",\"glasses\":\"23837f2.svg\",\"dark_sunglasses\":\"73f2977.svg\",\"goggles\":\"3c9969d.svg\",\"closed_umbrella\":\"cdabf7f.svg\",\"curly_haired\":\"146d347.svg\",\"curly_hair\":\"146d347.svg\",\"red_haired\":\"0950cb4.svg\",\"red_hair\":\"0950cb4.svg\",\"white_haired\":\"dabdbec.svg\",\"white_hair\":\"dabdbec.svg\",\"bald\":\"3ef301d.svg\",\"dog\":\"3ccb464.svg\",\"dog_face\":\"3ccb464.svg\",\"cat\":\"e2ebe95.svg\",\"cat_face\":\"e2ebe95.svg\",\"mouse\":\"f629f7d.svg\",\"mouse_face\":\"f629f7d.svg\",\"hamster\":\"d07281d.svg\",\"rabbit\":\"4b797a9.svg\",\"rabbit_face\":\"4b797a9.svg\",\"fox\":\"6786a19.svg\",\"fox_face\":\"6786a19.svg\",\"bear\":\"d242a98.svg\",\"panda_face\":\"7a547a9.svg\",\"panda\":\"7a547a9.svg\",\"polar_bear\":\"d157692.svg\",\"koala\":\"c694c1d.svg\",\"tiger\":\"8875758.svg\",\"tiger_face\":\"8875758.svg\",\"lion_face\":\"2957e30.svg\",\"lion\":\"2957e30.svg\",\"cow\":\"e003105.svg\",\"cow_face\":\"e003105.svg\",\"pig\":\"eb5e463.svg\",\"pig_face\":\"eb5e463.svg\",\"pig_nose\":\"c5891b9.svg\",\"frog\":\"0978222.svg\",\"monkey_face\":\"2c750b3.svg\",\"see_no_evil\":\"28d931d.svg\",\"hear_no_evil\":\"b06fe2f.svg\",\"speak_no_evil\":\"9ae86c5.svg\",\"monkey\":\"b9dedd9.svg\",\"chicken\":\"dc90644.svg\",\"penguin\":\"8b55d00.svg\",\"bird\":\"44973ab.svg\",\"baby_chick\":\"8c1a38f.svg\",\"hatching_chick\":\"73b21bf.svg\",\"hatched_chick\":\"f549882.svg\",\"duck\":\"01e958f.svg\",\"eagle\":\"85327ee.svg\",\"owl\":\"f492bd3.svg\",\"bat\":\"821240b.svg\",\"wolf\":\"bdd08b6.svg\",\"boar\":\"a69fcbf.svg\",\"horse\":\"2d9abe9.svg\",\"horse_face\":\"2d9abe9.svg\",\"unicorn\":\"8af1860.svg\",\"unicorn_face\":\"8af1860.svg\",\"bee\":\"3494a3a.svg\",\"honeybee\":\"3494a3a.svg\",\"bug\":\"d889001.svg\",\"butterfly\":\"638165b.svg\",\"snail\":\"7803ddf.svg\",\"worm\":\"11c85bb.svg\",\"lady_beetle\":\"fd3dd90.svg\",\"ant\":\"dcf8a67.svg\",\"fly\":\"7e58c3a.svg\",\"mosquito\":\"db9de23.svg\",\"cockroach\":\"f5066c9.svg\",\"beetle\":\"e3eaeeb.svg\",\"cricket\":\"315a214.svg\",\"spider\":\"45355c9.svg\",\"spider_web\":\"c5ad60d.svg\",\"scorpion\":\"2407882.svg\",\"turtle\":\"77a65b1.svg\",\"snake\":\"b49f0fe.svg\",\"lizard\":\"8615fbb.svg\",\"t_rex\":\"faeecb5.svg\",\"sauropod\":\"f03b670.svg\",\"octopus\":\"6ccec50.svg\",\"squid\":\"93f40d2.svg\",\"shrimp\":\"f0b0645.svg\",\"lobster\":\"c421b5f.svg\",\"crab\":\"d70bb64.svg\",\"blowfish\":\"5df5274.svg\",\"tropical_fish\":\"a800a26.svg\",\"fish\":\"169733f.svg\",\"seal\":\"6e87588.svg\",\"dolphin\":\"ca2e93d.svg\",\"whale\":\"fe7709b.svg\",\"whale2\":\"043cb5d.svg\",\"shark\":\"868bd9b.svg\",\"crocodile\":\"d08535e.svg\",\"tiger2\":\"4c0fd27.svg\",\"leopard\":\"17441b2.svg\",\"zebra\":\"62b20e1.svg\",\"gorilla\":\"ec170c1.svg\",\"orangutan\":\"aa04d6f.svg\",\"elephant\":\"ac19e02.svg\",\"mammoth\":\"6f6f5ef.svg\",\"bison\":\"c715b3b.svg\",\"hippopotamus\":\"b3f28d5.svg\",\"rhino\":\"3454677.svg\",\"rhinoceros\":\"3454677.svg\",\"dromedary_camel\":\"7533fdf.svg\",\"camel\":\"cc5d6a8.svg\",\"giraffe\":\"f957a7e.svg\",\"kangaroo\":\"419ee1c.svg\",\"water_buffalo\":\"653eea1.svg\",\"ox\":\"ced4876.svg\",\"cow2\":\"c7b24eb.svg\",\"racehorse\":\"8767732.svg\",\"pig2\":\"1fc6bf2.svg\",\"ram\":\"0c037b6.svg\",\"sheep\":\"9ea5d57.svg\",\"ewe\":\"9ea5d57.svg\",\"llama\":\"951cbdc.svg\",\"goat\":\"a8818ae.svg\",\"deer\":\"02bf0b4.svg\",\"dog2\":\"bc98734.svg\",\"poodle\":\"96f3e45.svg\",\"guide_dog\":\"27e2fca.svg\",\"service_dog\":\"cb230b5.svg\",\"cat2\":\"5ac09fa.svg\",\"black_cat\":\"5e424b9.svg\",\"feather\":\"8ff77f9.svg\",\"rooster\":\"b53713a.svg\",\"turkey\":\"8564eee.svg\",\"dodo\":\"5828b4b.svg\",\"peacock\":\"b8fd358.svg\",\"parrot\":\"c261148.svg\",\"swan\":\"465cea3.svg\",\"flamingo\":\"39308a0.svg\",\"dove\":\"f14ffc3.svg\",\"dove_of_peace\":\"f14ffc3.svg\",\"rabbit2\":\"1a97df2.svg\",\"raccoon\":\"50d5c58.svg\",\"skunk\":\"f4aa11d.svg\",\"badger\":\"5d92a7e.svg\",\"beaver\":\"52b6b8c.svg\",\"otter\":\"068f895.svg\",\"sloth\":\"3acaf10.svg\",\"mouse2\":\"61eb46a.svg\",\"rat\":\"dd81c25.svg\",\"chipmunk\":\"a161717.svg\",\"hedgehog\":\"3f641a9.svg\",\"feet\":\"7c3b4de.svg\",\"paw_prints\":\"7c3b4de.svg\",\"dragon\":\"c684bd5.svg\",\"dragon_face\":\"f448b81.svg\",\"cactus\":\"024570f.svg\",\"christmas_tree\":\"9b0d052.svg\",\"evergreen_tree\":\"4d0c026.svg\",\"deciduous_tree\":\"ba8daf3.svg\",\"palm_tree\":\"f2e66ab.svg\",\"seedling\":\"f8affca.svg\",\"herb\":\"ad39154.svg\",\"four_leaf_clover\":\"df35d4a.svg\",\"bamboo\":\"7496521.svg\",\"tanabata_tree\":\"91ca4fa.svg\",\"leaves\":\"068e911.svg\",\"fallen_leaf\":\"886a48a.svg\",\"maple_leaf\":\"9ae5fa7.svg\",\"empty_nest\":\"9104910.svg\",\"nest_with_eggs\":\"026bda7.svg\",\"mushroom\":\"a67208b.svg\",\"shell\":\"0592258.svg\",\"spiral_shell\":\"0592258.svg\",\"coral\":\"c3039c9.svg\",\"rock\":\"e392535.svg\",\"wood\":\"1e0a8ec.svg\",\"ear_of_rice\":\"33d35a4.svg\",\"sheaf_of_rice\":\"33d35a4.svg\",\"potted_plant\":\"0da4cbf.svg\",\"bouquet\":\"a2974d1.svg\",\"tulip\":\"48bb0a3.svg\",\"rose\":\"accbfe6.svg\",\"wilted_rose\":\"67bae71.svg\",\"wilted_flower\":\"67bae71.svg\",\"lotus\":\"ec6c2a1.svg\",\"hibiscus\":\"513465b.svg\",\"cherry_blossom\":\"6204820.svg\",\"blossom\":\"73f14e9.svg\",\"sunflower\":\"b92dff6.svg\",\"sun_with_face\":\"60bb982.svg\",\"full_moon_with_face\":\"79ebe64.svg\",\"first_quarter_moon_with_face\":\"673c333.svg\",\"last_quarter_moon_with_face\":\"209492f.svg\",\"new_moon_with_face\":\"41511ee.svg\",\"new_moon_face\":\"41511ee.svg\",\"full_moon\":\"6d25c78.svg\",\"waning_gibbous_moon\":\"d8c695f.svg\",\"last_quarter_moon\":\"1429a32.svg\",\"waning_crescent_moon\":\"68e8d59.svg\",\"new_moon\":\"44c72b8.svg\",\"waxing_crescent_moon\":\"2be5564.svg\",\"first_quarter_moon\":\"d1647fd.svg\",\"waxing_gibbous_moon\":\"f578f4a.svg\",\"crescent_moon\":\"74e0cd6.svg\",\"earth_americas\":\"24bfedb.svg\",\"earth_africa\":\"41440d6.svg\",\"earth_asia\":\"a6d7932.svg\",\"ringed_planet\":\"8e9f64b.svg\",\"dizzy\":\"1ad4ca7.svg\",\"star\":\"40ae1e8.svg\",\"star2\":\"2894cf6.svg\",\"glowing_star\":\"2894cf6.svg\",\"zap\":\"6bd13c3.svg\",\"high_voltage\":\"6bd13c3.svg\",\"boom\":\"54f1411.svg\",\"collision\":\"54f1411.svg\",\"fire\":\"fc3cdd9.svg\",\"flame\":\"fc3cdd9.svg\",\"cloud_tornado\":\"01dba25.svg\",\"cloud_with_tornado\":\"01dba25.svg\",\"tornado\":\"01dba25.svg\",\"rainbow\":\"d2577d6.svg\",\"white_sun_small_cloud\":\"3b149d9.svg\",\"white_sun_with_small_cloud\":\"3b149d9.svg\",\"partly_sunny\":\"c0ced7a.svg\",\"white_sun_cloud\":\"bce7696.svg\",\"white_sun_behind_cloud\":\"bce7696.svg\",\"white_sun_rain_cloud\":\"f85c555.svg\",\"white_sun_behind_cloud_with_rain\":\"f85c555.svg\",\"cloud_rain\":\"a3983f3.svg\",\"cloud_with_rain\":\"a3983f3.svg\",\"thunder_cloud_rain\":\"ef0448c.svg\",\"thunder_cloud_and_rain\":\"ef0448c.svg\",\"cloud_lightning\":\"33914f1.svg\",\"cloud_with_lightning\":\"33914f1.svg\",\"cloud_snow\":\"8469ee7.svg\",\"cloud_with_snow\":\"8469ee7.svg\",\"snowman\":\"fee310d.svg\",\"wind_blowing_face\":\"686ea7b.svg\",\"wind_face\":\"686ea7b.svg\",\"dash\":\"e8111bf.svg\",\"dashing_away\":\"e8111bf.svg\",\"droplet\":\"57bf439.svg\",\"sweat_drops\":\"83189c4.svg\",\"bubbles\":\"8a18bb0.svg\",\"ocean\":\"db6c885.svg\",\"water_wave\":\"db6c885.svg\",\"fog\":\"2d0cc00.svg\",\"green_apple\":\"2698f57.svg\",\"apple\":\"9aa8526.svg\",\"red_apple\":\"9aa8526.svg\",\"pear\":\"b248cb9.svg\",\"tangerine\":\"150cca0.svg\",\"lemon\":\"6916b3b.svg\",\"banana\":\"de55a5a.svg\",\"watermelon\":\"69959c6.svg\",\"grapes\":\"653c308.svg\",\"blueberries\":\"31e80b2.svg\",\"strawberry\":\"f52278a.svg\",\"melon\":\"a5bac83.svg\",\"cherries\":\"56a7af8.svg\",\"peach\":\"c39295e.svg\",\"mango\":\"e4d91b8.svg\",\"pineapple\":\"466e1eb.svg\",\"coconut\":\"7cc0fe9.svg\",\"kiwi\":\"2399915.svg\",\"kiwifruit\":\"2399915.svg\",\"kiwi_fruit\":\"2399915.svg\",\"tomato\":\"d00d0c0.svg\",\"eggplant\":\"6238f3b.svg\",\"avocado\":\"3f5d895.svg\",\"olive\":\"3793899.svg\",\"broccoli\":\"3deb0a0.svg\",\"leafy_green\":\"b99ba4b.svg\",\"bell_pepper\":\"f3f9cbe.svg\",\"cucumber\":\"146d731.svg\",\"hot_pepper\":\"09edf0d.svg\",\"corn\":\"9a9a70f.svg\",\"ear_of_corn\":\"9a9a70f.svg\",\"carrot\":\"45af58f.svg\",\"garlic\":\"cb4b336.svg\",\"onion\":\"87204b6.svg\",\"potato\":\"a495bba.svg\",\"sweet_potato\":\"497c5db.svg\",\"croissant\":\"e56a95a.svg\",\"bagel\":\"135300b.svg\",\"bread\":\"e07342f.svg\",\"french_bread\":\"c5b8b00.svg\",\"baguette_bread\":\"c5b8b00.svg\",\"flatbread\":\"d5102ef.svg\",\"pretzel\":\"50ee080.svg\",\"cheese\":\"bf4fc04.svg\",\"cheese_wedge\":\"bf4fc04.svg\",\"egg\":\"316cb2e.svg\",\"cooking\":\"21c68e8.svg\",\"butter\":\"c125503.svg\",\"pancakes\":\"bfc4f54.svg\",\"waffle\":\"7895253.svg\",\"bacon\":\"dd2d7b5.svg\",\"cut_of_meat\":\"ea6e2c8.svg\",\"poultry_leg\":\"294e088.svg\",\"meat_on_bone\":\"e7d524b.svg\",\"bone\":\"10f3a37.svg\",\"hotdog\":\"c1cf757.svg\",\"hot_dog\":\"c1cf757.svg\",\"hamburger\":\"3dd4533.svg\",\"fries\":\"4abb8a9.svg\",\"french_fries\":\"4abb8a9.svg\",\"pizza\":\"77a05f4.svg\",\"sandwich\":\"5e993f1.svg\",\"stuffed_flatbread\":\"a3280e2.svg\",\"stuffed_pita\":\"a3280e2.svg\",\"falafel\":\"a67ea38.svg\",\"taco\":\"2cd7996.svg\",\"burrito\":\"146b5e8.svg\",\"tamale\":\"c6d1faf.svg\",\"salad\":\"9590157.svg\",\"green_salad\":\"9590157.svg\",\"shallow_pan_of_food\":\"fc31e25.svg\",\"paella\":\"fc31e25.svg\",\"fondue\":\"dd52ac5.svg\",\"canned_food\":\"099b1a2.svg\",\"jar\":\"7596a1f.svg\",\"spaghetti\":\"e6a22ba.svg\",\"ramen\":\"ac86183.svg\",\"steaming_bowl\":\"ac86183.svg\",\"stew\":\"97aa48a.svg\",\"pot_of_food\":\"97aa48a.svg\",\"curry\":\"a1d2dc4.svg\",\"curry_rice\":\"a1d2dc4.svg\",\"sushi\":\"067e889.svg\",\"bento\":\"0fd2feb.svg\",\"bento_box\":\"0fd2feb.svg\",\"dumpling\":\"71491bf.svg\",\"oyster\":\"7c887a4.svg\",\"fried_shrimp\":\"04bd57d.svg\",\"rice_ball\":\"a6b77cf.svg\",\"rice\":\"fd4ae11.svg\",\"cooked_rice\":\"fd4ae11.svg\",\"rice_cracker\":\"77fbf2e.svg\",\"fish_cake\":\"a94c6f5.svg\",\"fortune_cookie\":\"adae735.svg\",\"moon_cake\":\"3cf1f6c.svg\",\"oden\":\"30afd74.svg\",\"dango\":\"71ba14b.svg\",\"shaved_ice\":\"41b99c7.svg\",\"ice_cream\":\"967e342.svg\",\"icecream\":\"a659029.svg\",\"pie\":\"26758e2.svg\",\"cupcake\":\"6e1882a.svg\",\"cake\":\"a5a0d93.svg\",\"shortcake\":\"a5a0d93.svg\",\"birthday\":\"ebfc760.svg\",\"birthday_cake\":\"ebfc760.svg\",\"custard\":\"7e61e0c.svg\",\"pudding\":\"7e61e0c.svg\",\"flan\":\"7e61e0c.svg\",\"lollipop\":\"2ca11ad.svg\",\"candy\":\"32f0f2e.svg\",\"chocolate_bar\":\"e60cdf7.svg\",\"popcorn\":\"ab01b78.svg\",\"doughnut\":\"c3385bc.svg\",\"cookie\":\"9d3f367.svg\",\"chestnut\":\"dd5851b.svg\",\"peanuts\":\"a20e792.svg\",\"shelled_peanut\":\"a20e792.svg\",\"beans\":\"b65fc0b.svg\",\"honey_pot\":\"a0bdfae.svg\",\"milk\":\"821274d.svg\",\"glass_of_milk\":\"821274d.svg\",\"pouring_liquid\":\"6775ee5.svg\",\"baby_bottle\":\"8a5b07d.svg\",\"teapot\":\"01e2f91.svg\",\"tea\":\"b321e0c.svg\",\"mate\":\"8dd46d2.svg\",\"beverage_box\":\"e4435be.svg\",\"cup_with_straw\":\"55bf11e.svg\",\"bubble_tea\":\"2051cef.svg\",\"sake\":\"5c5e3ba.svg\",\"beer\":\"95fb995.svg\",\"beer_mug\":\"95fb995.svg\",\"beers\":\"a3b4911.svg\",\"champagne_glass\":\"4b2aa03.svg\",\"clinking_glass\":\"4b2aa03.svg\",\"wine_glass\":\"3206d4e.svg\",\"tumbler_glass\":\"11bbc42.svg\",\"whisky\":\"11bbc42.svg\",\"cocktail\":\"3a21ef2.svg\",\"tropical_drink\":\"8d0ac3d.svg\",\"champagne\":\"f7cb49a.svg\",\"bottle_with_popping_cork\":\"f7cb49a.svg\",\"ice_cube\":\"3798289.svg\",\"spoon\":\"7f3b449.svg\",\"fork_and_knife\":\"410cb1a.svg\",\"fork_knife_plate\":\"54cfb15.svg\",\"fork_and_knife_with_plate\":\"54cfb15.svg\",\"bowl_with_spoon\":\"cea4b0b.svg\",\"takeout_box\":\"2b60e9b.svg\",\"chopsticks\":\"785de11.svg\",\"salt\":\"ec10ed1.svg\",\"soccer\":\"fe5016a.svg\",\"soccer_ball\":\"fe5016a.svg\",\"basketball\":\"0af3e2e.svg\",\"football\":\"613427a.svg\",\"baseball\":\"4e1371c.svg\",\"softball\":\"6da5625.svg\",\"tennis\":\"f1bc91d.svg\",\"volleyball\":\"6f326b4.svg\",\"rugby_football\":\"bf09743.svg\",\"flying_disc\":\"0d8a28d.svg\",\"8ball\":\"e1568b2.svg\",\"yo_yo\":\"9424c4a.svg\",\"ping_pong\":\"d4cd1c6.svg\",\"table_tennis\":\"d4cd1c6.svg\",\"badminton\":\"7a082b9.svg\",\"hockey\":\"4ec1cc9.svg\",\"ice_hockey\":\"4ec1cc9.svg\",\"field_hockey\":\"464cb70.svg\",\"lacrosse\":\"8e814bb.svg\",\"cricket_game\":\"4aae708.svg\",\"cricket_bat_ball\":\"4aae708.svg\",\"boomerang\":\"e2a13ed.svg\",\"goal\":\"08895cc.svg\",\"goal_net\":\"08895cc.svg\",\"golf\":\"6bbe5a3.svg\",\"flag_in_hole\":\"6bbe5a3.svg\",\"kite\":\"3821f31.svg\",\"playground_slide\":\"841888e.svg\",\"bow_and_arrow\":\"068e73e.svg\",\"archery\":\"068e73e.svg\",\"fishing_pole_and_fish\":\"8ec3056.svg\",\"fishing_pole\":\"8ec3056.svg\",\"diving_mask\":\"e49ef97.svg\",\"boxing_glove\":\"5e6de39.svg\",\"boxing_gloves\":\"5e6de39.svg\",\"martial_arts_uniform\":\"d9afc6f.svg\",\"karate_uniform\":\"d9afc6f.svg\",\"running_shirt_with_sash\":\"715d5c3.svg\",\"running_shirt\":\"715d5c3.svg\",\"skateboard\":\"7ea93e9.svg\",\"roller_skate\":\"f314913.svg\",\"sled\":\"aa00254.svg\",\"ice_skate\":\"d9d11f6.svg\",\"curling_stone\":\"8e27381.svg\",\"ski\":\"34ea7a2.svg\",\"skis\":\"34ea7a2.svg\",\"skier\":\"8e86867.svg\",\"snowboarder\":\"924f676.svg\",\"snowboarder_tone1\":\"6378d9c.svg\",\"snowboarder_light_skin_tone\":\"6378d9c.svg\",\"snowboarder_tone2\":\"a867bbf.svg\",\"snowboarder_medium_light_skin_tone\":\"a867bbf.svg\",\"snowboarder_tone3\":\"d53f50d.svg\",\"snowboarder_medium_skin_tone\":\"d53f50d.svg\",\"snowboarder_tone4\":\"3b89122.svg\",\"snowboarder_medium_dark_skin_tone\":\"3b89122.svg\",\"snowboarder_tone5\":\"bc52d26.svg\",\"snowboarder_dark_skin_tone\":\"bc52d26.svg\",\"parachute\":\"235aa80.svg\",\"person_lifting_weights\":\"b90ac11.svg\",\"lifter\":\"b90ac11.svg\",\"weight_lifter\":\"b90ac11.svg\",\"person_lifting_weights_tone1\":\"34d9b74.svg\",\"lifter_tone1\":\"34d9b74.svg\",\"weight_lifter_tone1\":\"34d9b74.svg\",\"person_lifting_weights_tone2\":\"f27c582.svg\",\"lifter_tone2\":\"f27c582.svg\",\"weight_lifter_tone2\":\"f27c582.svg\",\"person_lifting_weights_tone3\":\"dd131fc.svg\",\"lifter_tone3\":\"dd131fc.svg\",\"weight_lifter_tone3\":\"dd131fc.svg\",\"person_lifting_weights_tone4\":\"e57f8bb.svg\",\"lifter_tone4\":\"e57f8bb.svg\",\"weight_lifter_tone4\":\"e57f8bb.svg\",\"person_lifting_weights_tone5\":\"de9bcfd.svg\",\"lifter_tone5\":\"de9bcfd.svg\",\"weight_lifter_tone5\":\"de9bcfd.svg\",\"woman_lifting_weights\":\"62a33df.svg\",\"woman_lifting_weights_tone1\":\"3660157.svg\",\"woman_lifting_weights_light_skin_tone\":\"3660157.svg\",\"woman_lifting_weights_tone2\":\"e191ca6.svg\",\"woman_lifting_weights_medium_light_skin_tone\":\"e191ca6.svg\",\"woman_lifting_weights_tone3\":\"e09b339.svg\",\"woman_lifting_weights_medium_skin_tone\":\"e09b339.svg\",\"woman_lifting_weights_tone4\":\"62072c2.svg\",\"woman_lifting_weights_medium_dark_skin_tone\":\"62072c2.svg\",\"woman_lifting_weights_tone5\":\"91a30cb.svg\",\"woman_lifting_weights_dark_skin_tone\":\"91a30cb.svg\",\"man_lifting_weights\":\"b1c9983.svg\",\"man_lifting_weights_tone1\":\"9533af5.svg\",\"man_lifting_weights_light_skin_tone\":\"9533af5.svg\",\"man_lifting_weights_tone2\":\"ee2a6a9.svg\",\"man_lifting_weights_medium_light_skin_tone\":\"ee2a6a9.svg\",\"man_lifting_weights_tone3\":\"e5f3b8f.svg\",\"man_lifting_weights_medium_skin_tone\":\"e5f3b8f.svg\",\"man_lifting_weights_tone4\":\"9731124.svg\",\"man_lifting_weights_medium_dark_skin_tone\":\"9731124.svg\",\"man_lifting_weights_tone5\":\"cd99f79.svg\",\"man_lifting_weights_dark_skin_tone\":\"cd99f79.svg\",\"people_wrestling\":\"53c665d.svg\",\"wrestlers\":\"53c665d.svg\",\"wrestling\":\"53c665d.svg\",\"women_wrestling\":\"1353766.svg\",\"men_wrestling\":\"39251fc.svg\",\"person_doing_cartwheel\":\"ceaa20d.svg\",\"cartwheel\":\"ceaa20d.svg\",\"person_doing_cartwheel_tone1\":\"e0a4877.svg\",\"cartwheel_tone1\":\"e0a4877.svg\",\"person_doing_cartwheel_tone2\":\"20b9a39.svg\",\"cartwheel_tone2\":\"20b9a39.svg\",\"person_doing_cartwheel_tone3\":\"7003f2d.svg\",\"cartwheel_tone3\":\"7003f2d.svg\",\"person_doing_cartwheel_tone4\":\"2dce1a6.svg\",\"cartwheel_tone4\":\"2dce1a6.svg\",\"person_doing_cartwheel_tone5\":\"1fd5723.svg\",\"cartwheel_tone5\":\"1fd5723.svg\",\"woman_cartwheeling\":\"f9d123e.svg\",\"woman_cartwheeling_tone1\":\"937a8be.svg\",\"woman_cartwheeling_light_skin_tone\":\"937a8be.svg\",\"woman_cartwheeling_tone2\":\"08252f5.svg\",\"woman_cartwheeling_medium_light_skin_tone\":\"08252f5.svg\",\"woman_cartwheeling_tone3\":\"546ef7e.svg\",\"woman_cartwheeling_medium_skin_tone\":\"546ef7e.svg\",\"woman_cartwheeling_tone4\":\"0f82417.svg\",\"woman_cartwheeling_medium_dark_skin_tone\":\"0f82417.svg\",\"woman_cartwheeling_tone5\":\"2554418.svg\",\"woman_cartwheeling_dark_skin_tone\":\"2554418.svg\",\"man_cartwheeling\":\"a091dd5.svg\",\"man_cartwheeling_tone1\":\"f6ee5ef.svg\",\"man_cartwheeling_light_skin_tone\":\"f6ee5ef.svg\",\"man_cartwheeling_tone2\":\"0cc10b6.svg\",\"man_cartwheeling_medium_light_skin_tone\":\"0cc10b6.svg\",\"man_cartwheeling_tone3\":\"9a5c406.svg\",\"man_cartwheeling_medium_skin_tone\":\"9a5c406.svg\",\"man_cartwheeling_tone4\":\"b039a4a.svg\",\"man_cartwheeling_medium_dark_skin_tone\":\"b039a4a.svg\",\"man_cartwheeling_tone5\":\"b3a7e4c.svg\",\"man_cartwheeling_dark_skin_tone\":\"b3a7e4c.svg\",\"person_bouncing_ball\":\"c59fd96.svg\",\"basketball_player\":\"c59fd96.svg\",\"person_with_ball\":\"c59fd96.svg\",\"person_bouncing_ball_tone1\":\"b308087.svg\",\"basketball_player_tone1\":\"b308087.svg\",\"person_with_ball_tone1\":\"b308087.svg\",\"person_bouncing_ball_tone2\":\"95d1ab8.svg\",\"basketball_player_tone2\":\"95d1ab8.svg\",\"person_with_ball_tone2\":\"95d1ab8.svg\",\"person_bouncing_ball_tone3\":\"130e022.svg\",\"basketball_player_tone3\":\"130e022.svg\",\"person_with_ball_tone3\":\"130e022.svg\",\"person_bouncing_ball_tone4\":\"e1bcfae.svg\",\"basketball_player_tone4\":\"e1bcfae.svg\",\"person_with_ball_tone4\":\"e1bcfae.svg\",\"person_bouncing_ball_tone5\":\"048f5ff.svg\",\"basketball_player_tone5\":\"048f5ff.svg\",\"person_with_ball_tone5\":\"048f5ff.svg\",\"woman_bouncing_ball\":\"8c28093.svg\",\"woman_bouncing_ball_tone1\":\"9eef462.svg\",\"woman_bouncing_ball_light_skin_tone\":\"9eef462.svg\",\"woman_bouncing_ball_tone2\":\"2c4ab8d.svg\",\"woman_bouncing_ball_medium_light_skin_tone\":\"2c4ab8d.svg\",\"woman_bouncing_ball_tone3\":\"66fe37b.svg\",\"woman_bouncing_ball_medium_skin_tone\":\"66fe37b.svg\",\"woman_bouncing_ball_tone4\":\"c75a4e7.svg\",\"woman_bouncing_ball_medium_dark_skin_tone\":\"c75a4e7.svg\",\"woman_bouncing_ball_tone5\":\"506f725.svg\",\"woman_bouncing_ball_dark_skin_tone\":\"506f725.svg\",\"man_bouncing_ball\":\"b6a7c56.svg\",\"man_bouncing_ball_tone1\":\"322cb44.svg\",\"man_bouncing_ball_light_skin_tone\":\"322cb44.svg\",\"man_bouncing_ball_tone2\":\"50cbc45.svg\",\"man_bouncing_ball_medium_light_skin_tone\":\"50cbc45.svg\",\"man_bouncing_ball_tone3\":\"ef9c2e8.svg\",\"man_bouncing_ball_medium_skin_tone\":\"ef9c2e8.svg\",\"man_bouncing_ball_tone4\":\"e8fa7bf.svg\",\"man_bouncing_ball_medium_dark_skin_tone\":\"e8fa7bf.svg\",\"man_bouncing_ball_tone5\":\"dec8825.svg\",\"man_bouncing_ball_dark_skin_tone\":\"dec8825.svg\",\"person_fencing\":\"3f34bca.svg\",\"fencer\":\"3f34bca.svg\",\"fencing\":\"3f34bca.svg\",\"person_playing_handball\":\"b68a89f.svg\",\"handball\":\"b68a89f.svg\",\"person_playing_handball_tone1\":\"9589a8e.svg\",\"handball_tone1\":\"9589a8e.svg\",\"person_playing_handball_tone2\":\"838a0a1.svg\",\"handball_tone2\":\"838a0a1.svg\",\"person_playing_handball_tone3\":\"5c34d86.svg\",\"handball_tone3\":\"5c34d86.svg\",\"person_playing_handball_tone4\":\"b48abf5.svg\",\"handball_tone4\":\"b48abf5.svg\",\"person_playing_handball_tone5\":\"5ae9150.svg\",\"handball_tone5\":\"5ae9150.svg\",\"woman_playing_handball\":\"3d904f4.svg\",\"woman_playing_handball_tone1\":\"ce426bd.svg\",\"woman_playing_handball_light_skin_tone\":\"ce426bd.svg\",\"woman_playing_handball_tone2\":\"eaed791.svg\",\"woman_playing_handball_medium_light_skin_tone\":\"eaed791.svg\",\"woman_playing_handball_tone3\":\"96267aa.svg\",\"woman_playing_handball_medium_skin_tone\":\"96267aa.svg\",\"woman_playing_handball_tone4\":\"0688baa.svg\",\"woman_playing_handball_medium_dark_skin_tone\":\"0688baa.svg\",\"woman_playing_handball_tone5\":\"7d4d45a.svg\",\"woman_playing_handball_dark_skin_tone\":\"7d4d45a.svg\",\"man_playing_handball\":\"16e5ae3.svg\",\"man_playing_handball_tone1\":\"07d7439.svg\",\"man_playing_handball_light_skin_tone\":\"07d7439.svg\",\"man_playing_handball_tone2\":\"8ec0da9.svg\",\"man_playing_handball_medium_light_skin_tone\":\"8ec0da9.svg\",\"man_playing_handball_tone3\":\"0f401f9.svg\",\"man_playing_handball_medium_skin_tone\":\"0f401f9.svg\",\"man_playing_handball_tone4\":\"42a6db5.svg\",\"man_playing_handball_medium_dark_skin_tone\":\"42a6db5.svg\",\"man_playing_handball_tone5\":\"be6e83c.svg\",\"man_playing_handball_dark_skin_tone\":\"be6e83c.svg\",\"person_golfing\":\"7670549.svg\",\"golfer\":\"7670549.svg\",\"person_golfing_tone1\":\"aef1d45.svg\",\"person_golfing_light_skin_tone\":\"aef1d45.svg\",\"person_golfing_tone2\":\"0be94ad.svg\",\"person_golfing_medium_light_skin_tone\":\"0be94ad.svg\",\"person_golfing_tone3\":\"ed7649c.svg\",\"person_golfing_medium_skin_tone\":\"ed7649c.svg\",\"person_golfing_tone4\":\"5c3cba6.svg\",\"person_golfing_medium_dark_skin_tone\":\"5c3cba6.svg\",\"person_golfing_tone5\":\"5ea05fb.svg\",\"person_golfing_dark_skin_tone\":\"5ea05fb.svg\",\"woman_golfing\":\"b3abda4.svg\",\"woman_golfing_tone1\":\"b70878e.svg\",\"woman_golfing_light_skin_tone\":\"b70878e.svg\",\"woman_golfing_tone2\":\"b5598cf.svg\",\"woman_golfing_medium_light_skin_tone\":\"b5598cf.svg\",\"woman_golfing_tone3\":\"3ba78bf.svg\",\"woman_golfing_medium_skin_tone\":\"3ba78bf.svg\",\"woman_golfing_tone4\":\"891855f.svg\",\"woman_golfing_medium_dark_skin_tone\":\"891855f.svg\",\"woman_golfing_tone5\":\"dea660f.svg\",\"woman_golfing_dark_skin_tone\":\"dea660f.svg\",\"man_golfing\":\"318beb6.svg\",\"man_golfing_tone1\":\"ae64959.svg\",\"man_golfing_light_skin_tone\":\"ae64959.svg\",\"man_golfing_tone2\":\"953e4d1.svg\",\"man_golfing_medium_light_skin_tone\":\"953e4d1.svg\",\"man_golfing_tone3\":\"a490490.svg\",\"man_golfing_medium_skin_tone\":\"a490490.svg\",\"man_golfing_tone4\":\"6fec785.svg\",\"man_golfing_medium_dark_skin_tone\":\"6fec785.svg\",\"man_golfing_tone5\":\"fa6305a.svg\",\"man_golfing_dark_skin_tone\":\"fa6305a.svg\",\"horse_racing\":\"cf37033.svg\",\"horse_racing_tone1\":\"6655068.svg\",\"horse_racing_tone2\":\"8da15b8.svg\",\"horse_racing_tone3\":\"2e8ea94.svg\",\"horse_racing_tone4\":\"81e6ea9.svg\",\"horse_racing_tone5\":\"1dd66e6.svg\",\"person_in_lotus_position\":\"e7772e3.svg\",\"person_in_lotus_position_tone1\":\"085ede7.svg\",\"person_in_lotus_position_light_skin_tone\":\"085ede7.svg\",\"person_in_lotus_position_tone2\":\"b2de70b.svg\",\"person_in_lotus_position_medium_light_skin_tone\":\"b2de70b.svg\",\"person_in_lotus_position_tone3\":\"5a3f5ad.svg\",\"person_in_lotus_position_medium_skin_tone\":\"5a3f5ad.svg\",\"person_in_lotus_position_tone4\":\"f089de4.svg\",\"person_in_lotus_position_medium_dark_skin_tone\":\"f089de4.svg\",\"person_in_lotus_position_tone5\":\"40aac9b.svg\",\"person_in_lotus_position_dark_skin_tone\":\"40aac9b.svg\",\"woman_in_lotus_position\":\"32e01c8.svg\",\"woman_in_lotus_position_tone1\":\"60b3f38.svg\",\"woman_in_lotus_position_light_skin_tone\":\"60b3f38.svg\",\"woman_in_lotus_position_tone2\":\"b2fb18a.svg\",\"woman_in_lotus_position_medium_light_skin_tone\":\"b2fb18a.svg\",\"woman_in_lotus_position_tone3\":\"701c642.svg\",\"woman_in_lotus_position_medium_skin_tone\":\"701c642.svg\",\"woman_in_lotus_position_tone4\":\"cb3e88b.svg\",\"woman_in_lotus_position_medium_dark_skin_tone\":\"cb3e88b.svg\",\"woman_in_lotus_position_tone5\":\"21eb27c.svg\",\"woman_in_lotus_position_dark_skin_tone\":\"21eb27c.svg\",\"man_in_lotus_position\":\"8a422b1.svg\",\"man_in_lotus_position_tone1\":\"bd641d1.svg\",\"man_in_lotus_position_light_skin_tone\":\"bd641d1.svg\",\"man_in_lotus_position_tone2\":\"bc4c728.svg\",\"man_in_lotus_position_medium_light_skin_tone\":\"bc4c728.svg\",\"man_in_lotus_position_tone3\":\"462d985.svg\",\"man_in_lotus_position_medium_skin_tone\":\"462d985.svg\",\"man_in_lotus_position_tone4\":\"a0ec16e.svg\",\"man_in_lotus_position_medium_dark_skin_tone\":\"a0ec16e.svg\",\"man_in_lotus_position_tone5\":\"3edb59b.svg\",\"man_in_lotus_position_dark_skin_tone\":\"3edb59b.svg\",\"person_surfing\":\"c27cd92.svg\",\"surfer\":\"c27cd92.svg\",\"person_surfing_tone1\":\"f27cf26.svg\",\"surfer_tone1\":\"f27cf26.svg\",\"person_surfing_tone2\":\"3355d94.svg\",\"surfer_tone2\":\"3355d94.svg\",\"person_surfing_tone3\":\"46c6fb7.svg\",\"surfer_tone3\":\"46c6fb7.svg\",\"person_surfing_tone4\":\"2e67152.svg\",\"surfer_tone4\":\"2e67152.svg\",\"person_surfing_tone5\":\"b736746.svg\",\"surfer_tone5\":\"b736746.svg\",\"woman_surfing\":\"e72e11a.svg\",\"woman_surfing_tone1\":\"336b653.svg\",\"woman_surfing_light_skin_tone\":\"336b653.svg\",\"woman_surfing_tone2\":\"7685ea8.svg\",\"woman_surfing_medium_light_skin_tone\":\"7685ea8.svg\",\"woman_surfing_tone3\":\"763a75b.svg\",\"woman_surfing_medium_skin_tone\":\"763a75b.svg\",\"woman_surfing_tone4\":\"2095063.svg\",\"woman_surfing_medium_dark_skin_tone\":\"2095063.svg\",\"woman_surfing_tone5\":\"ecaab7e.svg\",\"woman_surfing_dark_skin_tone\":\"ecaab7e.svg\",\"man_surfing\":\"7f7d510.svg\",\"man_surfing_tone1\":\"0eea655.svg\",\"man_surfing_light_skin_tone\":\"0eea655.svg\",\"man_surfing_tone2\":\"ab7483c.svg\",\"man_surfing_medium_light_skin_tone\":\"ab7483c.svg\",\"man_surfing_tone3\":\"7919132.svg\",\"man_surfing_medium_skin_tone\":\"7919132.svg\",\"man_surfing_tone4\":\"d53f5ab.svg\",\"man_surfing_medium_dark_skin_tone\":\"d53f5ab.svg\",\"man_surfing_tone5\":\"cd6b5f3.svg\",\"man_surfing_dark_skin_tone\":\"cd6b5f3.svg\",\"person_swimming\":\"28777cf.svg\",\"swimmer\":\"28777cf.svg\",\"person_swimming_tone1\":\"df6d508.svg\",\"swimmer_tone1\":\"df6d508.svg\",\"person_swimming_tone2\":\"1bba0d0.svg\",\"swimmer_tone2\":\"1bba0d0.svg\",\"person_swimming_tone3\":\"b9edd35.svg\",\"swimmer_tone3\":\"b9edd35.svg\",\"person_swimming_tone4\":\"d37ded5.svg\",\"swimmer_tone4\":\"d37ded5.svg\",\"person_swimming_tone5\":\"a1071f0.svg\",\"swimmer_tone5\":\"a1071f0.svg\",\"woman_swimming\":\"49661b2.svg\",\"woman_swimming_tone1\":\"e79e53b.svg\",\"woman_swimming_light_skin_tone\":\"e79e53b.svg\",\"woman_swimming_tone2\":\"163be27.svg\",\"woman_swimming_medium_light_skin_tone\":\"163be27.svg\",\"woman_swimming_tone3\":\"b0f2942.svg\",\"woman_swimming_medium_skin_tone\":\"b0f2942.svg\",\"woman_swimming_tone4\":\"3b262f8.svg\",\"woman_swimming_medium_dark_skin_tone\":\"3b262f8.svg\",\"woman_swimming_tone5\":\"e9e3a6b.svg\",\"woman_swimming_dark_skin_tone\":\"e9e3a6b.svg\",\"man_swimming\":\"bf31394.svg\",\"man_swimming_tone1\":\"c59559e.svg\",\"man_swimming_light_skin_tone\":\"c59559e.svg\",\"man_swimming_tone2\":\"400e4cf.svg\",\"man_swimming_medium_light_skin_tone\":\"400e4cf.svg\",\"man_swimming_tone3\":\"779c541.svg\",\"man_swimming_medium_skin_tone\":\"779c541.svg\",\"man_swimming_tone4\":\"b02d784.svg\",\"man_swimming_medium_dark_skin_tone\":\"b02d784.svg\",\"man_swimming_tone5\":\"73eb78a.svg\",\"man_swimming_dark_skin_tone\":\"73eb78a.svg\",\"person_playing_water_polo\":\"06d4fe3.svg\",\"water_polo\":\"06d4fe3.svg\",\"person_playing_water_polo_tone1\":\"52d1e9b.svg\",\"water_polo_tone1\":\"52d1e9b.svg\",\"person_playing_water_polo_tone2\":\"2d709f9.svg\",\"water_polo_tone2\":\"2d709f9.svg\",\"person_playing_water_polo_tone3\":\"53b980a.svg\",\"water_polo_tone3\":\"53b980a.svg\",\"person_playing_water_polo_tone4\":\"057a799.svg\",\"water_polo_tone4\":\"057a799.svg\",\"person_playing_water_polo_tone5\":\"ddf84ba.svg\",\"water_polo_tone5\":\"ddf84ba.svg\",\"woman_playing_water_polo\":\"f46966d.svg\",\"woman_playing_water_polo_tone1\":\"567c0e1.svg\",\"woman_playing_water_polo_light_skin_tone\":\"567c0e1.svg\",\"woman_playing_water_polo_tone2\":\"c5c8263.svg\",\"woman_playing_water_polo_medium_light_skin_tone\":\"c5c8263.svg\",\"woman_playing_water_polo_tone3\":\"57dc235.svg\",\"woman_playing_water_polo_medium_skin_tone\":\"57dc235.svg\",\"woman_playing_water_polo_tone4\":\"177d57d.svg\",\"woman_playing_water_polo_medium_dark_skin_tone\":\"177d57d.svg\",\"woman_playing_water_polo_tone5\":\"596ba46.svg\",\"woman_playing_water_polo_dark_skin_tone\":\"596ba46.svg\",\"man_playing_water_polo\":\"ebc362c.svg\",\"man_playing_water_polo_tone1\":\"ead613e.svg\",\"man_playing_water_polo_light_skin_tone\":\"ead613e.svg\",\"man_playing_water_polo_tone2\":\"753c7f2.svg\",\"man_playing_water_polo_medium_light_skin_tone\":\"753c7f2.svg\",\"man_playing_water_polo_tone3\":\"666dcd9.svg\",\"man_playing_water_polo_medium_skin_tone\":\"666dcd9.svg\",\"man_playing_water_polo_tone4\":\"13a8332.svg\",\"man_playing_water_polo_medium_dark_skin_tone\":\"13a8332.svg\",\"man_playing_water_polo_tone5\":\"da368cd.svg\",\"man_playing_water_polo_dark_skin_tone\":\"da368cd.svg\",\"person_rowing_boat\":\"0ff3b31.svg\",\"rowboat\":\"0ff3b31.svg\",\"person_rowing_boat_tone1\":\"01fef47.svg\",\"rowboat_tone1\":\"01fef47.svg\",\"person_rowing_boat_tone2\":\"3d61432.svg\",\"rowboat_tone2\":\"3d61432.svg\",\"person_rowing_boat_tone3\":\"712d209.svg\",\"rowboat_tone3\":\"712d209.svg\",\"person_rowing_boat_tone4\":\"5549b7f.svg\",\"rowboat_tone4\":\"5549b7f.svg\",\"person_rowing_boat_tone5\":\"d1a1e9b.svg\",\"rowboat_tone5\":\"d1a1e9b.svg\",\"woman_rowing_boat\":\"2db7225.svg\",\"woman_rowing_boat_tone1\":\"28ce4ef.svg\",\"woman_rowing_boat_light_skin_tone\":\"28ce4ef.svg\",\"woman_rowing_boat_tone2\":\"319931f.svg\",\"woman_rowing_boat_medium_light_skin_tone\":\"319931f.svg\",\"woman_rowing_boat_tone3\":\"a4d57bd.svg\",\"woman_rowing_boat_medium_skin_tone\":\"a4d57bd.svg\",\"woman_rowing_boat_tone4\":\"0836442.svg\",\"woman_rowing_boat_medium_dark_skin_tone\":\"0836442.svg\",\"woman_rowing_boat_tone5\":\"126b354.svg\",\"woman_rowing_boat_dark_skin_tone\":\"126b354.svg\",\"man_rowing_boat\":\"9b50e6e.svg\",\"man_rowing_boat_tone1\":\"2111cad.svg\",\"man_rowing_boat_light_skin_tone\":\"2111cad.svg\",\"man_rowing_boat_tone2\":\"c96ba76.svg\",\"man_rowing_boat_medium_light_skin_tone\":\"c96ba76.svg\",\"man_rowing_boat_tone3\":\"8f39815.svg\",\"man_rowing_boat_medium_skin_tone\":\"8f39815.svg\",\"man_rowing_boat_tone4\":\"2447569.svg\",\"man_rowing_boat_medium_dark_skin_tone\":\"2447569.svg\",\"man_rowing_boat_tone5\":\"9f1fc73.svg\",\"man_rowing_boat_dark_skin_tone\":\"9f1fc73.svg\",\"person_climbing\":\"346ef3c.svg\",\"person_climbing_tone1\":\"21bf53e.svg\",\"person_climbing_light_skin_tone\":\"21bf53e.svg\",\"person_climbing_tone2\":\"7247dd3.svg\",\"person_climbing_medium_light_skin_tone\":\"7247dd3.svg\",\"person_climbing_tone3\":\"82d7d7d.svg\",\"person_climbing_medium_skin_tone\":\"82d7d7d.svg\",\"person_climbing_tone4\":\"5f96b71.svg\",\"person_climbing_medium_dark_skin_tone\":\"5f96b71.svg\",\"person_climbing_tone5\":\"9449a0b.svg\",\"person_climbing_dark_skin_tone\":\"9449a0b.svg\",\"woman_climbing\":\"e7b9c6e.svg\",\"woman_climbing_tone1\":\"d348f64.svg\",\"woman_climbing_light_skin_tone\":\"d348f64.svg\",\"woman_climbing_tone2\":\"ca220ab.svg\",\"woman_climbing_medium_light_skin_tone\":\"ca220ab.svg\",\"woman_climbing_tone3\":\"cbd19fd.svg\",\"woman_climbing_medium_skin_tone\":\"cbd19fd.svg\",\"woman_climbing_tone4\":\"adc0bf8.svg\",\"woman_climbing_medium_dark_skin_tone\":\"adc0bf8.svg\",\"woman_climbing_tone5\":\"0142ab2.svg\",\"woman_climbing_dark_skin_tone\":\"0142ab2.svg\",\"man_climbing\":\"87c7287.svg\",\"man_climbing_tone1\":\"12e1965.svg\",\"man_climbing_light_skin_tone\":\"12e1965.svg\",\"man_climbing_tone2\":\"63f594d.svg\",\"man_climbing_medium_light_skin_tone\":\"63f594d.svg\",\"man_climbing_tone3\":\"06891c1.svg\",\"man_climbing_medium_skin_tone\":\"06891c1.svg\",\"man_climbing_tone4\":\"814ac9f.svg\",\"man_climbing_medium_dark_skin_tone\":\"814ac9f.svg\",\"man_climbing_tone5\":\"3f6e241.svg\",\"man_climbing_dark_skin_tone\":\"3f6e241.svg\",\"person_mountain_biking\":\"890c347.svg\",\"mountain_bicyclist\":\"890c347.svg\",\"person_mountain_biking_tone1\":\"2d7f3f6.svg\",\"mountain_bicyclist_tone1\":\"2d7f3f6.svg\",\"person_mountain_biking_tone2\":\"3ae6862.svg\",\"mountain_bicyclist_tone2\":\"3ae6862.svg\",\"person_mountain_biking_tone3\":\"0da06a0.svg\",\"mountain_bicyclist_tone3\":\"0da06a0.svg\",\"person_mountain_biking_tone4\":\"77c8088.svg\",\"mountain_bicyclist_tone4\":\"77c8088.svg\",\"person_mountain_biking_tone5\":\"03a7b4f.svg\",\"mountain_bicyclist_tone5\":\"03a7b4f.svg\",\"woman_mountain_biking\":\"6a57fb1.svg\",\"woman_mountain_biking_tone1\":\"d80c94a.svg\",\"woman_mountain_biking_light_skin_tone\":\"d80c94a.svg\",\"woman_mountain_biking_tone2\":\"7689ca9.svg\",\"woman_mountain_biking_medium_light_skin_tone\":\"7689ca9.svg\",\"woman_mountain_biking_tone3\":\"8a0612e.svg\",\"woman_mountain_biking_medium_skin_tone\":\"8a0612e.svg\",\"woman_mountain_biking_tone4\":\"e74c90f.svg\",\"woman_mountain_biking_medium_dark_skin_tone\":\"e74c90f.svg\",\"woman_mountain_biking_tone5\":\"7e1cade.svg\",\"woman_mountain_biking_dark_skin_tone\":\"7e1cade.svg\",\"man_mountain_biking\":\"2672109.svg\",\"man_mountain_biking_tone1\":\"0313118.svg\",\"man_mountain_biking_light_skin_tone\":\"0313118.svg\",\"man_mountain_biking_tone2\":\"75b5216.svg\",\"man_mountain_biking_medium_light_skin_tone\":\"75b5216.svg\",\"man_mountain_biking_tone3\":\"00a2eaf.svg\",\"man_mountain_biking_medium_skin_tone\":\"00a2eaf.svg\",\"man_mountain_biking_tone4\":\"a595c8c.svg\",\"man_mountain_biking_medium_dark_skin_tone\":\"a595c8c.svg\",\"man_mountain_biking_tone5\":\"a4f8d93.svg\",\"man_mountain_biking_dark_skin_tone\":\"a4f8d93.svg\",\"person_biking\":\"6044207.svg\",\"bicyclist\":\"6044207.svg\",\"person_biking_tone1\":\"7444817.svg\",\"bicyclist_tone1\":\"7444817.svg\",\"person_biking_tone2\":\"c88dda5.svg\",\"bicyclist_tone2\":\"c88dda5.svg\",\"person_biking_tone3\":\"8647d8d.svg\",\"bicyclist_tone3\":\"8647d8d.svg\",\"person_biking_tone4\":\"1e876ca.svg\",\"bicyclist_tone4\":\"1e876ca.svg\",\"person_biking_tone5\":\"b32808a.svg\",\"bicyclist_tone5\":\"b32808a.svg\",\"woman_biking\":\"93a8bad.svg\",\"woman_biking_tone1\":\"b6049e8.svg\",\"woman_biking_light_skin_tone\":\"b6049e8.svg\",\"woman_biking_tone2\":\"0a5b09e.svg\",\"woman_biking_medium_light_skin_tone\":\"0a5b09e.svg\",\"woman_biking_tone3\":\"306a73e.svg\",\"woman_biking_medium_skin_tone\":\"306a73e.svg\",\"woman_biking_tone4\":\"7e7705a.svg\",\"woman_biking_medium_dark_skin_tone\":\"7e7705a.svg\",\"woman_biking_tone5\":\"e6189d9.svg\",\"woman_biking_dark_skin_tone\":\"e6189d9.svg\",\"man_biking\":\"6f05980.svg\",\"man_biking_tone1\":\"2b3276d.svg\",\"man_biking_light_skin_tone\":\"2b3276d.svg\",\"man_biking_tone2\":\"b6b8f8f.svg\",\"man_biking_medium_light_skin_tone\":\"b6b8f8f.svg\",\"man_biking_tone3\":\"226b02b.svg\",\"man_biking_medium_skin_tone\":\"226b02b.svg\",\"man_biking_tone4\":\"3c7d7e9.svg\",\"man_biking_medium_dark_skin_tone\":\"3c7d7e9.svg\",\"man_biking_tone5\":\"03c0dbb.svg\",\"man_biking_dark_skin_tone\":\"03c0dbb.svg\",\"trophy\":\"c3e6f70.svg\",\"first_place\":\"db793a8.svg\",\"first_place_medal\":\"db793a8.svg\",\"second_place\":\"e93fea1.svg\",\"second_place_medal\":\"e93fea1.svg\",\"third_place\":\"47d8c17.svg\",\"third_place_medal\":\"47d8c17.svg\",\"medal\":\"6779ec9.svg\",\"sports_medal\":\"6779ec9.svg\",\"military_medal\":\"fb6339d.svg\",\"rosette\":\"31f7d5f.svg\",\"reminder_ribbon\":\"bb34e42.svg\",\"ticket\":\"1deed76.svg\",\"tickets\":\"ffca92f.svg\",\"admission_tickets\":\"ffca92f.svg\",\"circus_tent\":\"b6b1de7.svg\",\"person_juggling\":\"82eeb05.svg\",\"juggling\":\"82eeb05.svg\",\"juggler\":\"82eeb05.svg\",\"person_juggling_tone1\":\"9b8710a.svg\",\"juggling_tone1\":\"9b8710a.svg\",\"juggler_tone1\":\"9b8710a.svg\",\"person_juggling_tone2\":\"6b046e1.svg\",\"juggling_tone2\":\"6b046e1.svg\",\"juggler_tone2\":\"6b046e1.svg\",\"person_juggling_tone3\":\"42af1b2.svg\",\"juggling_tone3\":\"42af1b2.svg\",\"juggler_tone3\":\"42af1b2.svg\",\"person_juggling_tone4\":\"106733f.svg\",\"juggling_tone4\":\"106733f.svg\",\"juggler_tone4\":\"106733f.svg\",\"person_juggling_tone5\":\"2bbbbe4.svg\",\"juggling_tone5\":\"2bbbbe4.svg\",\"juggler_tone5\":\"2bbbbe4.svg\",\"woman_juggling\":\"cc14be0.svg\",\"woman_juggling_tone1\":\"90866dc.svg\",\"woman_juggling_light_skin_tone\":\"90866dc.svg\",\"woman_juggling_tone2\":\"3baaaef.svg\",\"woman_juggling_medium_light_skin_tone\":\"3baaaef.svg\",\"woman_juggling_tone3\":\"f389b19.svg\",\"woman_juggling_medium_skin_tone\":\"f389b19.svg\",\"woman_juggling_tone4\":\"8f862bd.svg\",\"woman_juggling_medium_dark_skin_tone\":\"8f862bd.svg\",\"woman_juggling_tone5\":\"07ae5b7.svg\",\"woman_juggling_dark_skin_tone\":\"07ae5b7.svg\",\"man_juggling\":\"49fa575.svg\",\"man_juggling_tone1\":\"b6928e8.svg\",\"man_juggling_light_skin_tone\":\"b6928e8.svg\",\"man_juggling_tone2\":\"a8e2b25.svg\",\"man_juggling_medium_light_skin_tone\":\"a8e2b25.svg\",\"man_juggling_tone3\":\"37bf0a3.svg\",\"man_juggling_medium_skin_tone\":\"37bf0a3.svg\",\"man_juggling_tone4\":\"bf1af5b.svg\",\"man_juggling_medium_dark_skin_tone\":\"bf1af5b.svg\",\"man_juggling_tone5\":\"cd7490e.svg\",\"man_juggling_dark_skin_tone\":\"cd7490e.svg\",\"performing_arts\":\"d08e092.svg\",\"ballet_shoes\":\"ce680d6.svg\",\"art\":\"6347d5d.svg\",\"clapper\":\"38c53c4.svg\",\"clapper_board\":\"38c53c4.svg\",\"microphone\":\"0332817.svg\",\"headphones\":\"b75ccb1.svg\",\"headphone\":\"b75ccb1.svg\",\"musical_score\":\"9718ae8.svg\",\"musical_keyboard\":\"c127233.svg\",\"drum\":\"d34837b.svg\",\"drum_with_drumsticks\":\"d34837b.svg\",\"long_drum\":\"adfee2b.svg\",\"saxophone\":\"ea68fa3.svg\",\"trumpet\":\"cf8ad96.svg\",\"accordion\":\"d10245b.svg\",\"guitar\":\"b749b6d.svg\",\"banjo\":\"3c2cfe2.svg\",\"violin\":\"239b6a4.svg\",\"game_die\":\"cb770e2.svg\",\"chess_pawn\":\"ebef237.svg\",\"dart\":\"61b30d8.svg\",\"direct_hit\":\"61b30d8.svg\",\"bowling\":\"b15446c.svg\",\"video_game\":\"475d1d9.svg\",\"slot_machine\":\"99abb72.svg\",\"jigsaw\":\"09048a1.svg\",\"puzzle_piece\":\"09048a1.svg\",\"red_car\":\"4648f06.svg\",\"automobile\":\"4648f06.svg\",\"taxi\":\"096c8b6.svg\",\"blue_car\":\"73e65e4.svg\",\"pickup_truck\":\"4fc90c4.svg\",\"bus\":\"717af8d.svg\",\"trolleybus\":\"5fc4e9c.svg\",\"race_car\":\"cda42cb.svg\",\"racing_car\":\"cda42cb.svg\",\"police_car\":\"d10f0e6.svg\",\"ambulance\":\"766fae7.svg\",\"fire_engine\":\"7ea9b1c.svg\",\"minibus\":\"7f3d2f9.svg\",\"truck\":\"4c34438.svg\",\"articulated_lorry\":\"ab2711f.svg\",\"tractor\":\"65e7e6c.svg\",\"probing_cane\":\"6cf7b22.svg\",\"crutch\":\"0f9056b.svg\",\"manual_wheelchair\":\"f56cfd0.svg\",\"motorized_wheelchair\":\"35a9989.svg\",\"scooter\":\"4a5c78a.svg\",\"kick_scooter\":\"4a5c78a.svg\",\"bike\":\"4f666ce.svg\",\"bicycle\":\"4f666ce.svg\",\"motor_scooter\":\"029f569.svg\",\"motorbike\":\"029f569.svg\",\"motorcycle\":\"a5d6418.svg\",\"racing_motorcycle\":\"a5d6418.svg\",\"auto_rickshaw\":\"401f92e.svg\",\"wheel\":\"664c69f.svg\",\"rotating_light\":\"6e0b4fb.svg\",\"oncoming_police_car\":\"c2efc9d.svg\",\"oncoming_bus\":\"48172ac.svg\",\"oncoming_automobile\":\"24e53f0.svg\",\"oncoming_taxi\":\"913eb22.svg\",\"aerial_tramway\":\"b6f3c4d.svg\",\"mountain_cableway\":\"0afd8e2.svg\",\"suspension_railway\":\"5fe46e4.svg\",\"railway_car\":\"61192cb.svg\",\"train\":\"201aebe.svg\",\"tram_car\":\"201aebe.svg\",\"mountain_railway\":\"ff90e50.svg\",\"monorail\":\"b20874d.svg\",\"bullettrain_side\":\"7b850f3.svg\",\"bullettrain_front\":\"4b26830.svg\",\"bullet_train\":\"4b26830.svg\",\"light_rail\":\"27ee392.svg\",\"steam_locomotive\":\"cf2e7e4.svg\",\"locomotive\":\"cf2e7e4.svg\",\"train2\":\"f8defca.svg\",\"metro\":\"ba8bf59.svg\",\"tram\":\"15b1e38.svg\",\"station\":\"d6487f3.svg\",\"airplane_departure\":\"9f942b0.svg\",\"airplane_arriving\":\"ffe9ef5.svg\",\"airplane_small\":\"ca8c361.svg\",\"small_airplane\":\"ca8c361.svg\",\"seat\":\"fe25542.svg\",\"satellite_orbital\":\"f3b1fa1.svg\",\"rocket\":\"aa0d4e6.svg\",\"flying_saucer\":\"679db8c.svg\",\"helicopter\":\"19951f3.svg\",\"canoe\":\"f939398.svg\",\"kayak\":\"f939398.svg\",\"sailboat\":\"5246c7b.svg\",\"speedboat\":\"9ce4d8f.svg\",\"motorboat\":\"d1dae16.svg\",\"motor_boat\":\"d1dae16.svg\",\"cruise_ship\":\"b6bac4d.svg\",\"passenger_ship\":\"b6bac4d.svg\",\"ferry\":\"8d9fa6d.svg\",\"ship\":\"34984e4.svg\",\"ring_buoy\":\"6a7795b.svg\",\"hook\":\"7c8375e.svg\",\"fuelpump\":\"19b45a9.svg\",\"fuel_pump\":\"19b45a9.svg\",\"construction\":\"7161b1c.svg\",\"vertical_traffic_light\":\"70e5f1a.svg\",\"traffic_light\":\"1f2edbd.svg\",\"busstop\":\"18f7597.svg\",\"bus_stop\":\"18f7597.svg\",\"map\":\"0ebaa6e.svg\",\"world_map\":\"0ebaa6e.svg\",\"moyai\":\"bddc0b5.svg\",\"moai\":\"bddc0b5.svg\",\"statue_of_liberty\":\"46507e6.svg\",\"tokyo_tower\":\"64fdf85.svg\",\"european_castle\":\"37dbf79.svg\",\"castle\":\"37dbf79.svg\",\"japanese_castle\":\"c5c7e2d.svg\",\"stadium\":\"38115c3.svg\",\"ferris_wheel\":\"9de8642.svg\",\"roller_coaster\":\"b9e9c42.svg\",\"carousel_horse\":\"e64de10.svg\",\"fountain\":\"5aca3cd.svg\",\"beach_umbrella\":\"4156648.svg\",\"umbrella_on_ground\":\"4156648.svg\",\"beach\":\"9124dab.svg\",\"beach_with_umbrella\":\"9124dab.svg\",\"island\":\"73ce89c.svg\",\"desert_island\":\"73ce89c.svg\",\"desert\":\"e3ce8c9.svg\",\"volcano\":\"bf5d238.svg\",\"mountain\":\"1e77e79.svg\",\"mountain_snow\":\"1f23b37.svg\",\"snow_capped_mountain\":\"1f23b37.svg\",\"mount_fuji\":\"b436b7a.svg\",\"camping\":\"f6c6d51.svg\",\"tent\":\"6eb1399.svg\",\"house\":\"7affc4c.svg\",\"house_with_garden\":\"670d333.svg\",\"homes\":\"171dd2d.svg\",\"house_buildings\":\"171dd2d.svg\",\"houses\":\"171dd2d.svg\",\"house_abandoned\":\"6556bab.svg\",\"derelict_house_building\":\"6556bab.svg\",\"hut\":\"0287086.svg\",\"construction_site\":\"05a9407.svg\",\"building_construction\":\"05a9407.svg\",\"factory\":\"2ef3927.svg\",\"office\":\"49c6f4a.svg\",\"department_store\":\"a9826b1.svg\",\"post_office\":\"f5a09a8.svg\",\"european_post_office\":\"85a65b5.svg\",\"hospital\":\"61a201f.svg\",\"bank\":\"ec0d6b9.svg\",\"hotel\":\"2bd109e.svg\",\"convenience_store\":\"d94f921.svg\",\"school\":\"519ff41.svg\",\"love_hotel\":\"ab4d549.svg\",\"wedding\":\"3c54c5a.svg\",\"classical_building\":\"95e1830.svg\",\"church\":\"962f222.svg\",\"mosque\":\"d4d07fb.svg\",\"synagogue\":\"9120b90.svg\",\"hindu_temple\":\"f614b6d.svg\",\"kaaba\":\"8661a60.svg\",\"shinto_shrine\":\"ffc1cf2.svg\",\"railway_track\":\"45037f1.svg\",\"railroad_track\":\"45037f1.svg\",\"motorway\":\"8d46cb0.svg\",\"japan\":\"55121d5.svg\",\"map_of_japan\":\"55121d5.svg\",\"rice_scene\":\"c281ca8.svg\",\"park\":\"ca41c23.svg\",\"national_park\":\"ca41c23.svg\",\"sunrise\":\"c345c7f.svg\",\"sunrise_over_mountains\":\"daecba5.svg\",\"stars\":\"976c4b0.svg\",\"shooting_star\":\"976c4b0.svg\",\"sparkler\":\"5ae1115.svg\",\"fireworks\":\"c1504db.svg\",\"city_sunset\":\"add21f4.svg\",\"city_sunrise\":\"add21f4.svg\",\"sunset\":\"add21f4.svg\",\"city_dusk\":\"1615620.svg\",\"cityscape\":\"bcd1a03.svg\",\"night_with_stars\":\"b20b31d.svg\",\"milky_way\":\"7a8b8fe.svg\",\"bridge_at_night\":\"b3645d7.svg\",\"foggy\":\"7554b94.svg\",\"watch\":\"8cd2198.svg\",\"mobile_phone\":\"043a332.svg\",\"calling\":\"8093f31.svg\",\"computer\":\"a1cbd41.svg\",\"desktop\":\"49d1d8c.svg\",\"desktop_computer\":\"49d1d8c.svg\",\"printer\":\"0477c27.svg\",\"mouse_three_button\":\"e8bf4ae.svg\",\"three_button_mouse\":\"e8bf4ae.svg\",\"trackball\":\"eca4e5f.svg\",\"joystick\":\"31ffc51.svg\",\"compression\":\"2ae5c68.svg\",\"clamp\":\"2ae5c68.svg\",\"minidisc\":\"b857d2b.svg\",\"computer_disk\":\"b857d2b.svg\",\"floppy_disk\":\"724655d.svg\",\"cd\":\"19887b0.svg\",\"optical_disk\":\"19887b0.svg\",\"dvd\":\"2d1fb24.svg\",\"vhs\":\"69c1ca5.svg\",\"videocassette\":\"69c1ca5.svg\",\"camera\":\"f6b208b.svg\",\"camera_with_flash\":\"e69232c.svg\",\"video_camera\":\"0769511.svg\",\"movie_camera\":\"ada41ed.svg\",\"projector\":\"31e6fce.svg\",\"film_projector\":\"31e6fce.svg\",\"film_frames\":\"d0566b1.svg\",\"telephone_receiver\":\"d0cb02d.svg\",\"telephone\":\"b5bcee9.svg\",\"pager\":\"1508393.svg\",\"fax\":\"d03c69e.svg\",\"fax_machine\":\"d03c69e.svg\",\"tv\":\"8185cfd.svg\",\"television\":\"8185cfd.svg\",\"radio\":\"96aca60.svg\",\"microphone2\":\"edd109f.svg\",\"studio_microphone\":\"edd109f.svg\",\"level_slider\":\"5da41ef.svg\",\"control_knobs\":\"75bc99a.svg\",\"compass\":\"76c66a6.svg\",\"stopwatch\":\"8c25acf.svg\",\"timer\":\"29b66ab.svg\",\"timer_clock\":\"29b66ab.svg\",\"alarm_clock\":\"69d9e77.svg\",\"clock\":\"3c8b83f.svg\",\"mantlepiece_clock\":\"3c8b83f.svg\",\"hourglass\":\"ac8067d.svg\",\"hourglass_flowing_sand\":\"a93761d.svg\",\"satellite\":\"85da884.svg\",\"battery\":\"b2a3fa5.svg\",\"low_battery\":\"504a87f.svg\",\"electric_plug\":\"04bcd7b.svg\",\"bulb\":\"0310db5.svg\",\"light_bulb\":\"0310db5.svg\",\"flashlight\":\"491b3cc.svg\",\"candle\":\"e0102d6.svg\",\"diya_lamp\":\"e62bf44.svg\",\"fire_extinguisher\":\"859318c.svg\",\"oil\":\"85dca88.svg\",\"oil_drum\":\"85dca88.svg\",\"money_with_wings\":\"394e674.svg\",\"dollar\":\"e5da110.svg\",\"yen\":\"31e33a4.svg\",\"yen_banknote\":\"31e33a4.svg\",\"euro\":\"0526eb6.svg\",\"euro_banknote\":\"0526eb6.svg\",\"pound\":\"cb3cc79.svg\",\"coin\":\"1030e8c.svg\",\"moneybag\":\"5f37ed0.svg\",\"money_bag\":\"5f37ed0.svg\",\"credit_card\":\"00afcde.svg\",\"identification_card\":\"c8b9ad7.svg\",\"gem\":\"6ac2f69.svg\",\"gem_stone\":\"6ac2f69.svg\",\"ladder\":\"b52cf4f.svg\",\"toolbox\":\"949effe.svg\",\"screwdriver\":\"aa022d1.svg\",\"wrench\":\"1b0fc89.svg\",\"hammer\":\"c68f5bf.svg\",\"tools\":\"ced20a7.svg\",\"hammer_and_wrench\":\"ced20a7.svg\",\"pick\":\"8aaf7d2.svg\",\"carpentry_saw\":\"38a740a.svg\",\"nut_and_bolt\":\"e91cfa5.svg\",\"mouse_trap\":\"7580985.svg\",\"bricks\":\"af8390c.svg\",\"brick\":\"af8390c.svg\",\"chains\":\"34432a5.svg\",\"magnet\":\"d9d3c78.svg\",\"gun\":\"5401572.svg\",\"pistol\":\"5401572.svg\",\"bomb\":\"705a333.svg\",\"firecracker\":\"fc466b7.svg\",\"axe\":\"38a6e4c.svg\",\"knife\":\"3382c2c.svg\",\"kitchen_knife\":\"3382c2c.svg\",\"dagger\":\"f974ae3.svg\",\"dagger_knife\":\"f974ae3.svg\",\"shield\":\"0d534b0.svg\",\"smoking\":\"f709fc8.svg\",\"cigarette\":\"f709fc8.svg\",\"coffin\":\"0f45480.svg\",\"headstone\":\"5f2708d.svg\",\"urn\":\"6b8d9f1.svg\",\"funeral_urn\":\"6b8d9f1.svg\",\"amphora\":\"2a10a18.svg\",\"crystal_ball\":\"15d1b34.svg\",\"prayer_beads\":\"fecca1a.svg\",\"nazar_amulet\":\"6b02e26.svg\",\"hamsa\":\"eb16f78.svg\",\"barber\":\"54ba31e.svg\",\"barber_pole\":\"54ba31e.svg\",\"telescope\":\"625d524.svg\",\"microscope\":\"f1fd0f0.svg\",\"hole\":\"6e81e53.svg\",\"x_ray\":\"673885d.svg\",\"adhesive_bandage\":\"cc4d394.svg\",\"stethoscope\":\"3cd880e.svg\",\"pill\":\"06481bd.svg\",\"syringe\":\"3126fb2.svg\",\"drop_of_blood\":\"c214a30.svg\",\"dna\":\"bc1c9dc.svg\",\"microbe\":\"751fc12.svg\",\"petri_dish\":\"1dd0c34.svg\",\"test_tube\":\"3628ffc.svg\",\"thermometer\":\"aee2f27.svg\",\"broom\":\"2e58d3d.svg\",\"plunger\":\"f209c2f.svg\",\"basket\":\"d558daa.svg\",\"roll_of_paper\":\"4bb9b48.svg\",\"toilet\":\"9944889.svg\",\"potable_water\":\"0c357ca.svg\",\"shower\":\"ca42b84.svg\",\"bathtub\":\"cdc6826.svg\",\"bath\":\"b15ecb4.svg\",\"bath_tone1\":\"b73c83b.svg\",\"bath_tone2\":\"4dc5728.svg\",\"bath_tone3\":\"4a6dc70.svg\",\"bath_tone4\":\"ffca481.svg\",\"bath_tone5\":\"45d0461.svg\",\"soap\":\"54dd924.svg\",\"toothbrush\":\"09a491b.svg\",\"razor\":\"0d83e13.svg\",\"sponge\":\"8de141f.svg\",\"bucket\":\"8e9cdc0.svg\",\"squeeze_bottle\":\"2b63004.svg\",\"lotion_bottle\":\"2b63004.svg\",\"bellhop\":\"9e8511f.svg\",\"bellhop_bell\":\"9e8511f.svg\",\"key\":\"f024110.svg\",\"key2\":\"f7b6e6b.svg\",\"old_key\":\"f7b6e6b.svg\",\"door\":\"eec520d.svg\",\"chair\":\"bc332e6.svg\",\"couch\":\"ebb4f4d.svg\",\"couch_and_lamp\":\"ebb4f4d.svg\",\"bed\":\"722e9a2.svg\",\"sleeping_accommodation\":\"848e303.svg\",\"person_in_bed\":\"848e303.svg\",\"person_in_bed_tone1\":\"4e627cc.svg\",\"person_in_bed_light_skin_tone\":\"4e627cc.svg\",\"person_in_bed_tone2\":\"edb7a4c.svg\",\"person_in_bed_medium_light_skin_tone\":\"edb7a4c.svg\",\"person_in_bed_tone3\":\"66bcd2b.svg\",\"person_in_bed_medium_skin_tone\":\"66bcd2b.svg\",\"person_in_bed_tone4\":\"d9a1851.svg\",\"person_in_bed_medium_dark_skin_tone\":\"d9a1851.svg\",\"person_in_bed_tone5\":\"30e9323.svg\",\"person_in_bed_dark_skin_tone\":\"30e9323.svg\",\"teddy_bear\":\"1b3b59e.svg\",\"nesting_dolls\":\"e6ed873.svg\",\"frame_photo\":\"f773485.svg\",\"frame_with_picture\":\"f773485.svg\",\"mirror\":\"39db427.svg\",\"window\":\"33a5ce8.svg\",\"shopping_bags\":\"ee2a1bd.svg\",\"shopping_cart\":\"92bbb27.svg\",\"shopping_trolley\":\"92bbb27.svg\",\"gift\":\"667a23e.svg\",\"wrapped_gift\":\"667a23e.svg\",\"balloon\":\"c77e962.svg\",\"flags\":\"bee24a6.svg\",\"carp_streamer\":\"bee24a6.svg\",\"ribbon\":\"62342e3.svg\",\"magic_wand\":\"abcf317.svg\",\"pinata\":\"8449683.svg\",\"confetti_ball\":\"d060485.svg\",\"tada\":\"3eff897.svg\",\"party_popper\":\"3eff897.svg\",\"dolls\":\"f0f2c76.svg\",\"izakaya_lantern\":\"96d5937.svg\",\"wind_chime\":\"cb4b9cc.svg\",\"mirror_ball\":\"17dbd0f.svg\",\"red_envelope\":\"1b3bbc0.svg\",\"envelope_with_arrow\":\"2840e02.svg\",\"incoming_envelope\":\"0dc4ce5.svg\",\"e-mail\":\"8b97fb1.svg\",\"email\":\"8b97fb1.svg\",\"e_mail\":\"8b97fb1.svg\",\"love_letter\":\"8b99ce1.svg\",\"inbox_tray\":\"d2f41f2.svg\",\"outbox_tray\":\"34d71ce.svg\",\"package\":\"35b2169.svg\",\"label\":\"d4c5eb8.svg\",\"placard\":\"980cf8a.svg\",\"mailbox_closed\":\"5485425.svg\",\"mailbox\":\"f390395.svg\",\"mailbox_with_mail\":\"866cf4c.svg\",\"mailbox_with_no_mail\":\"81356e8.svg\",\"postbox\":\"ddcaa58.svg\",\"postal_horn\":\"5bb498a.svg\",\"scroll\":\"83ef1c5.svg\",\"page_with_curl\":\"715306e.svg\",\"page_facing_up\":\"f503e29.svg\",\"bookmark_tabs\":\"15c5d93.svg\",\"receipt\":\"e78618d.svg\",\"bar_chart\":\"d9f3686.svg\",\"chart_with_upwards_trend\":\"c2d2846.svg\",\"chart_with_downwards_trend\":\"b793d0e.svg\",\"notepad_spiral\":\"14933b2.svg\",\"spiral_note_pad\":\"14933b2.svg\",\"calendar_spiral\":\"e6b67b0.svg\",\"spiral_calendar_pad\":\"e6b67b0.svg\",\"calendar\":\"535e551.svg\",\"date\":\"b41658d.svg\",\"wastebasket\":\"8a4d76d.svg\",\"card_index\":\"d606c3a.svg\",\"card_box\":\"1410be1.svg\",\"card_file_box\":\"1410be1.svg\",\"ballot_box\":\"b77638a.svg\",\"ballot_box_with_ballot\":\"b77638a.svg\",\"file_cabinet\":\"c23e1f7.svg\",\"clipboard\":\"734d53a.svg\",\"file_folder\":\"7270d1a.svg\",\"open_file_folder\":\"17b8130.svg\",\"dividers\":\"a3166fb.svg\",\"card_index_dividers\":\"a3166fb.svg\",\"newspaper2\":\"78af43c.svg\",\"rolled_up_newspaper\":\"78af43c.svg\",\"newspaper\":\"33e45ff.svg\",\"notebook\":\"944dedb.svg\",\"notebook_with_decorative_cover\":\"7bf9b8b.svg\",\"ledger\":\"035d8fb.svg\",\"closed_book\":\"d191cf2.svg\",\"green_book\":\"1263d2d.svg\",\"blue_book\":\"c8f1aae.svg\",\"orange_book\":\"96acb2f.svg\",\"books\":\"de7b39d.svg\",\"book\":\"68ab4c4.svg\",\"open_book\":\"68ab4c4.svg\",\"bookmark\":\"5722afe.svg\",\"safety_pin\":\"02701ce.svg\",\"link\":\"64b8ced.svg\",\"paperclip\":\"a5cadec.svg\",\"paperclips\":\"ee9497c.svg\",\"linked_paperclips\":\"ee9497c.svg\",\"triangular_ruler\":\"70403b8.svg\",\"straight_ruler\":\"2ef34f4.svg\",\"abacus\":\"5736cb9.svg\",\"pushpin\":\"fe05cca.svg\",\"round_pushpin\":\"1cfaddc.svg\",\"pen_ballpoint\":\"68e2cd3.svg\",\"lower_left_ballpoint_pen\":\"68e2cd3.svg\",\"pen\":\"68e2cd3.svg\",\"pen_fountain\":\"438545d.svg\",\"lower_left_fountain_pen\":\"438545d.svg\",\"fountain_pen\":\"438545d.svg\",\"paintbrush\":\"d1c4b5e.svg\",\"lower_left_paintbrush\":\"d1c4b5e.svg\",\"crayon\":\"7230001.svg\",\"lower_left_crayon\":\"7230001.svg\",\"pencil\":\"c95a532.svg\",\"memo\":\"c95a532.svg\",\"pencil2\":\"c3fe3d3.svg\",\"mag\":\"4d82637.svg\",\"mag_right\":\"52b5e36.svg\",\"lock_with_ink_pen\":\"1e6575f.svg\",\"closed_lock_with_key\":\"38d17e7.svg\",\"lock\":\"d131271.svg\",\"locked\":\"d131271.svg\",\"unlock\":\"b7ccda7.svg\",\"unlocked\":\"b7ccda7.svg\",\"orange_heart\":\"f42c7a7.svg\",\"yellow_heart\":\"00ee6f2.svg\",\"green_heart\":\"6f33c33.svg\",\"blue_heart\":\"46cf244.svg\",\"purple_heart\":\"0514cbb.svg\",\"black_heart\":\"671d2be.svg\",\"brown_heart\":\"57627e2.svg\",\"white_heart\":\"9f3bddf.svg\",\"broken_heart\":\"e27c117.svg\",\"two_hearts\":\"230d425.svg\",\"revolving_hearts\":\"f1f519f.svg\",\"heartbeat\":\"95cf806.svg\",\"beating_heart\":\"95cf806.svg\",\"heartpulse\":\"9b2e17a.svg\",\"growing_heart\":\"9b2e17a.svg\",\"sparkling_heart\":\"383a7b6.svg\",\"cupid\":\"a708e66.svg\",\"gift_heart\":\"1a0c7fc.svg\",\"mending_heart\":\"bb2dee2.svg\",\"heart_on_fire\":\"686b568.svg\",\"heart_decoration\":\"9ee5106.svg\",\"peace\":\"81ac8f2.svg\",\"peace_symbol\":\"81ac8f2.svg\",\"cross\":\"0352b99.svg\",\"latin_cross\":\"0352b99.svg\",\"star_and_crescent\":\"87e2668.svg\",\"om_symbol\":\"fdbef1c.svg\",\"six_pointed_star\":\"6367072.svg\",\"menorah\":\"49fe2f3.svg\",\"yin_yang\":\"782b6e0.svg\",\"place_of_worship\":\"40e98b3.svg\",\"worship_symbol\":\"40e98b3.svg\",\"ophiuchus\":\"4be146d.svg\",\"gemini\":\"39ccf78.svg\",\"cancer\":\"1e6bf0d.svg\",\"leo\":\"571693e.svg\",\"virgo\":\"315b50a.svg\",\"libra\":\"59f58f6.svg\",\"scorpius\":\"b6e89bf.svg\",\"scorpio\":\"b6e89bf.svg\",\"id\":\"08f0aed.svg\",\"atom\":\"62bdeb7.svg\",\"atom_symbol\":\"62bdeb7.svg\",\"accept\":\"de5e369.svg\",\"mobile_phone_off\":\"0046ab1.svg\",\"vibration_mode\":\"fbee5ea.svg\",\"u6709\":\"7c32c00.svg\",\"u7121\":\"93bf37c.svg\",\"u7533\":\"c630391.svg\",\"u55b6\":\"765d280.svg\",\"u6708\":\"ff7053e.svg\",\"vs\":\"92b6e21.svg\",\"white_flower\":\"3561149.svg\",\"ideograph_advantage\":\"ce742e0.svg\",\"u5408\":\"2a415c0.svg\",\"u6e80\":\"079b9a5.svg\",\"u5272\":\"3abb1c3.svg\",\"u7981\":\"5f7fd48.svg\",\"a\":\"4d2357b.svg\",\"b\":\"15c3646.svg\",\"ab\":\"84f84e4.svg\",\"cl\":\"06c5b84.svg\",\"o2\":\"32f4bbe.svg\",\"sos\":\"9de07ec.svg\",\"x\":\"3a778be.svg\",\"cross_mark\":\"3a778be.svg\",\"o\":\"4407433.svg\",\"octagonal_sign\":\"db5dae1.svg\",\"stop_sign\":\"db5dae1.svg\",\"no_entry\":\"2431948.svg\",\"name_badge\":\"8e5412b.svg\",\"no_entry_sign\":\"6d87aae.svg\",\"prohibited\":\"6d87aae.svg\",\"anger\":\"05c2db1.svg\",\"no_pedestrians\":\"476e169.svg\",\"do_not_litter\":\"8c379b2.svg\",\"no_littering\":\"8c379b2.svg\",\"no_bicycles\":\"70b6a87.svg\",\"non-potable_water\":\"ac822b0.svg\",\"underage\":\"a0dc432.svg\",\"no_mobile_phones\":\"038ef1f.svg\",\"no_smoking\":\"4ef8a9d.svg\",\"bangbang\":\"62824e0.svg\",\"low_brightness\":\"118f858.svg\",\"high_brightness\":\"8ad70fe.svg\",\"part_alternation_mark\":\"4f63f69.svg\",\"warning\":\"8d54d46.svg\",\"children_crossing\":\"77b0db8.svg\",\"trident\":\"a7d3c5a.svg\",\"fleur-de-lis\":\"f1b7b1a.svg\",\"fleur_de_lis\":\"f1b7b1a.svg\",\"beginner\":\"8636018.svg\",\"recycle\":\"53bf457.svg\",\"u6307\":\"9922ede.svg\",\"chart\":\"23c755c.svg\",\"negative_squared_cross_mark\":\"b7ea18a.svg\",\"globe_with_meridians\":\"2e01a51.svg\",\"diamond_shape_with_a_dot_inside\":\"cf75eb9.svg\",\"m\":\"f62c2ef.svg\",\"circled_m\":\"f62c2ef.svg\",\"cyclone\":\"c59443e.svg\",\"zzz\":\"da19ffe.svg\",\"atm\":\"faef8df.svg\",\"wc\":\"6f23bcd.svg\",\"water_closet\":\"6f23bcd.svg\",\"wheelchair\":\"85c9f56.svg\",\"parking\":\"1d8a190.svg\",\"u7a7a\":\"5dfaae1.svg\",\"sa\":\"2a42295.svg\",\"passport_control\":\"6996331.svg\",\"customs\":\"87c1f0b.svg\",\"baggage_claim\":\"e0404d8.svg\",\"left_luggage\":\"fe66858.svg\",\"elevator\":\"4085820.svg\",\"mens\":\"baf6ba4.svg\",\"mens_room\":\"baf6ba4.svg\",\"womens\":\"4f3d3d3.svg\",\"womens_room\":\"4f3d3d3.svg\",\"baby_symbol\":\"dc8abeb.svg\",\"restroom\":\"1c1d4b1.svg\",\"put_litter_in_its_place\":\"5c8437b.svg\",\"cinema\":\"9229e02.svg\",\"signal_strength\":\"d77ae4f.svg\",\"antenna_bars\":\"d77ae4f.svg\",\"koko\":\"742a4da.svg\",\"symbols\":\"0675dde.svg\",\"input_symbols\":\"0675dde.svg\",\"abc\":\"f046fcb.svg\",\"abcd\":\"c50f908.svg\",\"capital_abcd\":\"0060d9a.svg\",\"ng\":\"eb732a9.svg\",\"ok\":\"f4bdfeb.svg\",\"up\":\"8149045.svg\",\"cool\":\"22331aa.svg\",\"new\":\"e1a41f7.svg\",\"free\":\"f942f77.svg\",\"keycap_ten\":\"156b08b.svg\",\"input_numbers\":\"cda85e0.svg\",\"eject\":\"c456e52.svg\",\"eject_symbol\":\"c456e52.svg\",\"arrow_forward\":\"ddc7d76.svg\",\"pause_button\":\"26e7adc.svg\",\"double_vertical_bar\":\"26e7adc.svg\",\"play_pause\":\"6ebd001.svg\",\"stop_button\":\"0e334b6.svg\",\"record_button\":\"00e7f17.svg\",\"track_next\":\"7773750.svg\",\"next_track\":\"7773750.svg\",\"track_previous\":\"e48c0e5.svg\",\"previous_track\":\"e48c0e5.svg\",\"fast_forward\":\"4e5cba4.svg\",\"rewind\":\"69e3a53.svg\",\"arrow_double_up\":\"3f5e2f1.svg\",\"arrow_double_down\":\"4457f0f.svg\",\"arrow_backward\":\"87c98dd.svg\",\"arrow_up_small\":\"d0d5c2c.svg\",\"arrow_down_small\":\"9e1110f.svg\",\"arrow_right\":\"7fd81bf.svg\",\"right_arrow\":\"7fd81bf.svg\",\"arrow_left\":\"a432020.svg\",\"left_arrow\":\"a432020.svg\",\"arrow_up\":\"145534d.svg\",\"up_arrow\":\"145534d.svg\",\"arrow_down\":\"31b41df.svg\",\"down_arrow\":\"31b41df.svg\",\"arrow_right_hook\":\"b5043ba.svg\",\"leftwards_arrow_with_hook\":\"2f11417.svg\",\"twisted_rightwards_arrows\":\"a88a7f5.svg\",\"repeat\":\"1543113.svg\",\"repeat_one\":\"c73671f.svg\",\"arrows_counterclockwise\":\"6416a28.svg\",\"arrows_clockwise\":\"8ccdeab.svg\",\"musical_note\":\"bd8cb8d.svg\",\"notes\":\"ac4a2ab.svg\",\"musical_notes\":\"ac4a2ab.svg\",\"heavy_equals_sign\":\"5dca87a.svg\",\"infinity\":\"9be29bc.svg\",\"heavy_dollar_sign\":\"ce4626a.svg\",\"currency_exchange\":\"f92fd67.svg\",\"curly_loop\":\"81f6081.svg\",\"loop\":\"db1d000.svg\",\"end\":\"f33a1a5.svg\",\"end_arrow\":\"f33a1a5.svg\",\"back\":\"5f9eccf.svg\",\"back_arrow\":\"5f9eccf.svg\",\"on\":\"e431464.svg\",\"on_arrow\":\"e431464.svg\",\"top\":\"907c2e4.svg\",\"top_arrow\":\"907c2e4.svg\",\"soon\":\"b03cc8c.svg\",\"soon_arrow\":\"b03cc8c.svg\",\"radio_button\":\"26d4f6c.svg\",\"white_circle\":\"878f00b.svg\",\"black_circle\":\"ee7749a.svg\",\"red_circle\":\"3e94570.svg\",\"blue_circle\":\"4bfbb7b.svg\",\"brown_circle\":\"0d2e831.svg\",\"purple_circle\":\"3e4174e.svg\",\"green_circle\":\"125b1ec.svg\",\"yellow_circle\":\"b86c5e4.svg\",\"orange_circle\":\"cf825eb.svg\",\"small_red_triangle\":\"00d21f8.svg\",\"small_red_triangle_down\":\"0bcf5ff.svg\",\"small_orange_diamond\":\"b80bfa0.svg\",\"small_blue_diamond\":\"660eb8d.svg\",\"large_orange_diamond\":\"73e4a33.svg\",\"large_blue_diamond\":\"2011e33.svg\",\"white_square_button\":\"7411701.svg\",\"black_square_button\":\"274717d.svg\",\"black_small_square\":\"fbabe68.svg\",\"white_small_square\":\"2e67568.svg\",\"black_medium_small_square\":\"3b4427b.svg\",\"white_medium_small_square\":\"00b5ec5.svg\",\"black_medium_square\":\"522667a.svg\",\"white_medium_square\":\"d1e58db.svg\",\"black_large_square\":\"637d2e5.svg\",\"white_large_square\":\"f05e212.svg\",\"orange_square\":\"006b61a.svg\",\"blue_square\":\"12b9986.svg\",\"red_square\":\"62ac584.svg\",\"brown_square\":\"6b19693.svg\",\"purple_square\":\"487d6ca.svg\",\"green_square\":\"3f5720c.svg\",\"yellow_square\":\"af8c2d4.svg\",\"speaker\":\"c02c90c.svg\",\"mute\":\"56c7c3c.svg\",\"muted_speaker\":\"56c7c3c.svg\",\"sound\":\"b493060.svg\",\"loud_sound\":\"0c1f211.svg\",\"bell\":\"afd3446.svg\",\"no_bell\":\"69d9d8b.svg\",\"mega\":\"342e222.svg\",\"megaphone\":\"342e222.svg\",\"loudspeaker\":\"3ae22f0.svg\",\"speech_left\":\"ef62b73.svg\",\"left_speech_bubble\":\"ef62b73.svg\",\"speech_balloon\":\"ca7bbec.svg\",\"thought_balloon\":\"31f13a5.svg\",\"anger_right\":\"83383b9.svg\",\"right_anger_bubble\":\"83383b9.svg\",\"black_joker\":\"848f060.svg\",\"joker\":\"848f060.svg\",\"flower_playing_cards\":\"e350d7d.svg\",\"mahjong\":\"eeca78a.svg\",\"clock1\":\"c21d8a7.svg\",\"one_oclock\":\"c21d8a7.svg\",\"clock2\":\"0570833.svg\",\"two_oclock\":\"0570833.svg\",\"clock3\":\"a40be16.svg\",\"three_oclock\":\"a40be16.svg\",\"clock4\":\"1f74d9f.svg\",\"four_oclock\":\"1f74d9f.svg\",\"clock5\":\"f864964.svg\",\"five_oclock\":\"f864964.svg\",\"clock6\":\"9f23d49.svg\",\"six_oclock\":\"9f23d49.svg\",\"clock7\":\"6fca2db.svg\",\"seven_oclock\":\"6fca2db.svg\",\"clock8\":\"1861145.svg\",\"eight_oclock\":\"1861145.svg\",\"clock9\":\"da17b83.svg\",\"nine_oclock\":\"da17b83.svg\",\"clock10\":\"64c8f11.svg\",\"ten_oclock\":\"64c8f11.svg\",\"clock11\":\"8635d2c.svg\",\"eleven_oclock\":\"8635d2c.svg\",\"clock12\":\"5f9757c.svg\",\"twelve_oclock\":\"5f9757c.svg\",\"clock130\":\"e289ef7.svg\",\"one_thirty\":\"e289ef7.svg\",\"clock230\":\"e6ebfa4.svg\",\"two_thirty\":\"e6ebfa4.svg\",\"clock330\":\"addac22.svg\",\"three_thirty\":\"addac22.svg\",\"clock430\":\"244dc36.svg\",\"four_thirty\":\"244dc36.svg\",\"clock530\":\"39990cf.svg\",\"five_thirty\":\"39990cf.svg\",\"clock630\":\"23376b9.svg\",\"six_thirty\":\"23376b9.svg\",\"clock730\":\"8d14ee4.svg\",\"seven_thirty\":\"8d14ee4.svg\",\"clock830\":\"e70ea22.svg\",\"eight_thirty\":\"e70ea22.svg\",\"clock930\":\"f40959f.svg\",\"nine_thirty\":\"f40959f.svg\",\"clock1030\":\"b07a3c9.svg\",\"ten_thirty\":\"b07a3c9.svg\",\"clock1130\":\"26233c1.svg\",\"eleven_thirty\":\"26233c1.svg\",\"clock1230\":\"9b4d7d3.svg\",\"twelve_thirty\":\"9b4d7d3.svg\",\"transgender_symbol\":\"ddf109e.svg\",\"flag_white\":\"a50f7fb.svg\",\"waving_white_flag\":\"a50f7fb.svg\",\"white_flag\":\"a50f7fb.svg\",\"flag_black\":\"c9ae19e.svg\",\"waving_black_flag\":\"c9ae19e.svg\",\"black_flag\":\"c9ae19e.svg\",\"checkered_flag\":\"3390133.svg\",\"triangular_flag_on_post\":\"16f482e.svg\",\"rainbow_flag\":\"6e96910.svg\",\"gay_pride_flag\":\"6e96910.svg\",\"transgender_flag\":\"f998d7c.svg\",\"pirate_flag\":\"9e00e92.svg\",\"flag_af\":\"021e19b.svg\",\"af\":\"021e19b.svg\",\"flag_ax\":\"7e7b820.svg\",\"ax\":\"7e7b820.svg\",\"flag_al\":\"16a82f9.svg\",\"al\":\"16a82f9.svg\",\"flag_dz\":\"d75256e.svg\",\"dz\":\"d75256e.svg\",\"flag_as\":\"9717b6c.svg\",\"as\":\"9717b6c.svg\",\"flag_ad\":\"f04fc99.svg\",\"ad\":\"f04fc99.svg\",\"flag_ao\":\"897dc1e.svg\",\"ao\":\"897dc1e.svg\",\"flag_ai\":\"f264d5f.svg\",\"ai\":\"f264d5f.svg\",\"flag_aq\":\"6ddd951.svg\",\"aq\":\"6ddd951.svg\",\"flag_ag\":\"43db600.svg\",\"ag\":\"43db600.svg\",\"flag_ar\":\"6400d86.svg\",\"ar\":\"6400d86.svg\",\"flag_am\":\"ca78cae.svg\",\"am\":\"ca78cae.svg\",\"flag_aw\":\"29c5ff8.svg\",\"aw\":\"29c5ff8.svg\",\"flag_au\":\"9d6fbca.svg\",\"au\":\"9d6fbca.svg\",\"flag_at\":\"df7fc82.svg\",\"at\":\"df7fc82.svg\",\"flag_az\":\"46f0416.svg\",\"az\":\"46f0416.svg\",\"flag_bs\":\"c0e2384.svg\",\"bs\":\"c0e2384.svg\",\"flag_bh\":\"f0bbd1c.svg\",\"bh\":\"f0bbd1c.svg\",\"flag_bd\":\"260e2c2.svg\",\"bd\":\"260e2c2.svg\",\"flag_bb\":\"78dfe57.svg\",\"bb\":\"78dfe57.svg\",\"flag_by\":\"86cf5da.svg\",\"by\":\"86cf5da.svg\",\"flag_be\":\"0c4ab23.svg\",\"be\":\"0c4ab23.svg\",\"flag_bz\":\"43c82a1.svg\",\"bz\":\"43c82a1.svg\",\"flag_bj\":\"4387163.svg\",\"bj\":\"4387163.svg\",\"flag_bm\":\"9afaba5.svg\",\"bm\":\"9afaba5.svg\",\"flag_bt\":\"a5aaec2.svg\",\"bt\":\"a5aaec2.svg\",\"flag_bo\":\"8f369cc.svg\",\"bo\":\"8f369cc.svg\",\"flag_ba\":\"c549423.svg\",\"ba\":\"c549423.svg\",\"flag_bw\":\"b68d515.svg\",\"bw\":\"b68d515.svg\",\"flag_br\":\"8807761.svg\",\"br\":\"8807761.svg\",\"flag_io\":\"80ba637.svg\",\"io\":\"80ba637.svg\",\"flag_vg\":\"9af55a7.svg\",\"vg\":\"9af55a7.svg\",\"flag_bn\":\"8921a94.svg\",\"bn\":\"8921a94.svg\",\"flag_bg\":\"9e2baa7.svg\",\"bg\":\"9e2baa7.svg\",\"flag_bf\":\"6efb5e6.svg\",\"bf\":\"6efb5e6.svg\",\"flag_bi\":\"c30fef5.svg\",\"bi\":\"c30fef5.svg\",\"flag_kh\":\"4fffe5d.svg\",\"kh\":\"4fffe5d.svg\",\"flag_cm\":\"85f707f.svg\",\"cm\":\"85f707f.svg\",\"flag_ca\":\"c8257e6.svg\",\"ca\":\"c8257e6.svg\",\"flag_ic\":\"ccd25a8.svg\",\"ic\":\"ccd25a8.svg\",\"flag_cv\":\"3601756.svg\",\"cv\":\"3601756.svg\",\"flag_bq\":\"895520d.svg\",\"bq\":\"895520d.svg\",\"flag_ky\":\"b42cd3d.svg\",\"ky\":\"b42cd3d.svg\",\"flag_cf\":\"0b6aa82.svg\",\"cf\":\"0b6aa82.svg\",\"flag_td\":\"3fb4d3b.svg\",\"td\":\"3fb4d3b.svg\",\"flag_cl\":\"736e4d4.svg\",\"chile\":\"736e4d4.svg\",\"flag_cn\":\"11fb0d7.svg\",\"cn\":\"11fb0d7.svg\",\"flag_cx\":\"3d3cf13.svg\",\"cx\":\"3d3cf13.svg\",\"flag_cc\":\"dab36e7.svg\",\"cc\":\"dab36e7.svg\",\"flag_co\":\"4779a07.svg\",\"co\":\"4779a07.svg\",\"flag_km\":\"281b7a8.svg\",\"km\":\"281b7a8.svg\",\"flag_cg\":\"02147fe.svg\",\"cg\":\"02147fe.svg\",\"flag_cd\":\"1570933.svg\",\"congo\":\"1570933.svg\",\"flag_ck\":\"d1ada81.svg\",\"ck\":\"d1ada81.svg\",\"flag_cr\":\"1fa2a8a.svg\",\"cr\":\"1fa2a8a.svg\",\"flag_ci\":\"c281f36.svg\",\"ci\":\"c281f36.svg\",\"flag_hr\":\"8e6c6f0.svg\",\"hr\":\"8e6c6f0.svg\",\"flag_cu\":\"c7a2da5.svg\",\"cu\":\"c7a2da5.svg\",\"flag_cw\":\"3c2dbfc.svg\",\"cw\":\"3c2dbfc.svg\",\"flag_cy\":\"5b42267.svg\",\"cy\":\"5b42267.svg\",\"flag_cz\":\"d2b9eed.svg\",\"cz\":\"d2b9eed.svg\",\"flag_dk\":\"450e300.svg\",\"dk\":\"450e300.svg\",\"flag_dj\":\"1c0c52c.svg\",\"dj\":\"1c0c52c.svg\",\"flag_dm\":\"babf9e7.svg\",\"dm\":\"babf9e7.svg\",\"flag_do\":\"5e49b01.svg\",\"do\":\"5e49b01.svg\",\"flag_ec\":\"a0d4fbd.svg\",\"ec\":\"a0d4fbd.svg\",\"flag_eg\":\"793c58c.svg\",\"eg\":\"793c58c.svg\",\"flag_sv\":\"60580e4.svg\",\"sv\":\"60580e4.svg\",\"flag_gq\":\"0b3f2c2.svg\",\"gq\":\"0b3f2c2.svg\",\"flag_er\":\"7797e8c.svg\",\"er\":\"7797e8c.svg\",\"flag_ee\":\"4fbd9a7.svg\",\"ee\":\"4fbd9a7.svg\",\"flag_et\":\"66fb1fd.svg\",\"et\":\"66fb1fd.svg\",\"flag_eu\":\"bdf20eb.svg\",\"eu\":\"bdf20eb.svg\",\"flag_fk\":\"5688b65.svg\",\"fk\":\"5688b65.svg\",\"flag_fo\":\"e06015c.svg\",\"fo\":\"e06015c.svg\",\"flag_fj\":\"724a378.svg\",\"fj\":\"724a378.svg\",\"flag_fi\":\"dbb78d5.svg\",\"fi\":\"dbb78d5.svg\",\"flag_fr\":\"5cff674.svg\",\"fr\":\"5cff674.svg\",\"flag_gf\":\"6036e01.svg\",\"gf\":\"6036e01.svg\",\"flag_pf\":\"1a3c99f.svg\",\"pf\":\"1a3c99f.svg\",\"flag_tf\":\"a103c9a.svg\",\"tf\":\"a103c9a.svg\",\"flag_ga\":\"2cb99a0.svg\",\"ga\":\"2cb99a0.svg\",\"flag_gm\":\"5818aec.svg\",\"gm\":\"5818aec.svg\",\"flag_ge\":\"4d9cdea.svg\",\"ge\":\"4d9cdea.svg\",\"flag_de\":\"1a8edb7.svg\",\"de\":\"1a8edb7.svg\",\"flag_gh\":\"59086bb.svg\",\"gh\":\"59086bb.svg\",\"flag_gi\":\"3ccc59a.svg\",\"gi\":\"3ccc59a.svg\",\"flag_gr\":\"7292d30.svg\",\"gr\":\"7292d30.svg\",\"flag_gl\":\"5f1fc89.svg\",\"gl\":\"5f1fc89.svg\",\"flag_gd\":\"56a6c04.svg\",\"gd\":\"56a6c04.svg\",\"flag_gp\":\"cce9290.svg\",\"gp\":\"cce9290.svg\",\"flag_gu\":\"861d7e0.svg\",\"gu\":\"861d7e0.svg\",\"flag_gt\":\"0c6496e.svg\",\"gt\":\"0c6496e.svg\",\"flag_gg\":\"cda502a.svg\",\"gg\":\"cda502a.svg\",\"flag_gn\":\"7ddeab1.svg\",\"gn\":\"7ddeab1.svg\",\"flag_gw\":\"dfccc52.svg\",\"gw\":\"dfccc52.svg\",\"flag_gy\":\"d5a6bef.svg\",\"gy\":\"d5a6bef.svg\",\"flag_ht\":\"7375ef7.svg\",\"ht\":\"7375ef7.svg\",\"flag_hn\":\"3e1122c.svg\",\"hn\":\"3e1122c.svg\",\"flag_hk\":\"647125f.svg\",\"hk\":\"647125f.svg\",\"flag_hu\":\"9193ed6.svg\",\"hu\":\"9193ed6.svg\",\"flag_is\":\"cfd6994.svg\",\"is\":\"cfd6994.svg\",\"flag_in\":\"41f09b0.svg\",\"in\":\"41f09b0.svg\",\"flag_id\":\"cec6ea4.svg\",\"indonesia\":\"cec6ea4.svg\",\"flag_ir\":\"79a52a6.svg\",\"ir\":\"79a52a6.svg\",\"flag_iq\":\"e61ee4a.svg\",\"iq\":\"e61ee4a.svg\",\"flag_ie\":\"c3b5afc.svg\",\"ie\":\"c3b5afc.svg\",\"flag_im\":\"4b596cd.svg\",\"im\":\"4b596cd.svg\",\"flag_il\":\"2210905.svg\",\"il\":\"2210905.svg\",\"flag_it\":\"e4a918d.svg\",\"it\":\"e4a918d.svg\",\"flag_jm\":\"8b3496f.svg\",\"jm\":\"8b3496f.svg\",\"flag_jp\":\"6648971.svg\",\"jp\":\"6648971.svg\",\"crossed_flags\":\"06a6bc5.svg\",\"flag_je\":\"4ddd431.svg\",\"je\":\"4ddd431.svg\",\"flag_jo\":\"1e7b07b.svg\",\"jo\":\"1e7b07b.svg\",\"flag_kz\":\"dc3d46c.svg\",\"kz\":\"dc3d46c.svg\",\"flag_ke\":\"7e58fbd.svg\",\"ke\":\"7e58fbd.svg\",\"flag_ki\":\"a738347.svg\",\"ki\":\"a738347.svg\",\"flag_xk\":\"232353a.svg\",\"xk\":\"232353a.svg\",\"flag_kw\":\"3d83192.svg\",\"kw\":\"3d83192.svg\",\"flag_kg\":\"f7a706f.svg\",\"kg\":\"f7a706f.svg\",\"flag_la\":\"c60a423.svg\",\"la\":\"c60a423.svg\",\"flag_lv\":\"29510db.svg\",\"lv\":\"29510db.svg\",\"flag_lb\":\"57c2b9b.svg\",\"lb\":\"57c2b9b.svg\",\"flag_ls\":\"ad8a2dc.svg\",\"ls\":\"ad8a2dc.svg\",\"flag_lr\":\"1a9ac5c.svg\",\"lr\":\"1a9ac5c.svg\",\"flag_ly\":\"a5fea03.svg\",\"ly\":\"a5fea03.svg\",\"flag_li\":\"94ed289.svg\",\"li\":\"94ed289.svg\",\"flag_lt\":\"cc86db2.svg\",\"lt\":\"cc86db2.svg\",\"flag_lu\":\"0ee6ec7.svg\",\"lu\":\"0ee6ec7.svg\",\"flag_mo\":\"5065e30.svg\",\"mo\":\"5065e30.svg\",\"flag_mk\":\"aeede56.svg\",\"mk\":\"aeede56.svg\",\"flag_mg\":\"82e95c1.svg\",\"mg\":\"82e95c1.svg\",\"flag_mw\":\"b18642d.svg\",\"mw\":\"b18642d.svg\",\"flag_my\":\"1689dc8.svg\",\"my\":\"1689dc8.svg\",\"flag_mv\":\"2ed1065.svg\",\"mv\":\"2ed1065.svg\",\"flag_ml\":\"6c80614.svg\",\"ml\":\"6c80614.svg\",\"flag_mt\":\"5c9fbf1.svg\",\"mt\":\"5c9fbf1.svg\",\"flag_mh\":\"be2f0bb.svg\",\"mh\":\"be2f0bb.svg\",\"flag_mq\":\"7a75dc9.svg\",\"mq\":\"7a75dc9.svg\",\"flag_mr\":\"dff1ba5.svg\",\"mr\":\"dff1ba5.svg\",\"flag_mu\":\"79cacd5.svg\",\"mu\":\"79cacd5.svg\",\"flag_yt\":\"30705e0.svg\",\"yt\":\"30705e0.svg\",\"flag_mx\":\"456b673.svg\",\"mx\":\"456b673.svg\",\"flag_fm\":\"6cbab14.svg\",\"fm\":\"6cbab14.svg\",\"flag_md\":\"ab95150.svg\",\"md\":\"ab95150.svg\",\"flag_mc\":\"11df3fe.svg\",\"mc\":\"11df3fe.svg\",\"flag_mn\":\"925fd1e.svg\",\"mn\":\"925fd1e.svg\",\"flag_me\":\"eb70192.svg\",\"me\":\"eb70192.svg\",\"flag_ms\":\"50fbe95.svg\",\"ms\":\"50fbe95.svg\",\"flag_ma\":\"17a17e2.svg\",\"ma\":\"17a17e2.svg\",\"flag_mz\":\"8dcf8bd.svg\",\"mz\":\"8dcf8bd.svg\",\"flag_mm\":\"3d0cb06.svg\",\"mm\":\"3d0cb06.svg\",\"flag_na\":\"3f08e8d.svg\",\"na\":\"3f08e8d.svg\",\"flag_nr\":\"a4b0613.svg\",\"nr\":\"a4b0613.svg\",\"flag_np\":\"7618ed2.svg\",\"np\":\"7618ed2.svg\",\"flag_nl\":\"2bf611b.svg\",\"nl\":\"2bf611b.svg\",\"flag_nc\":\"63c6363.svg\",\"nc\":\"63c6363.svg\",\"flag_nz\":\"143c6cb.svg\",\"nz\":\"143c6cb.svg\",\"flag_ni\":\"a4c869c.svg\",\"ni\":\"a4c869c.svg\",\"flag_ne\":\"264a3f7.svg\",\"ne\":\"264a3f7.svg\",\"flag_ng\":\"7aa6dd1.svg\",\"nigeria\":\"7aa6dd1.svg\",\"flag_nu\":\"a81d8cd.svg\",\"nu\":\"a81d8cd.svg\",\"flag_nf\":\"1f55bf8.svg\",\"nf\":\"1f55bf8.svg\",\"flag_kp\":\"22b01b7.svg\",\"kp\":\"22b01b7.svg\",\"flag_mp\":\"704174c.svg\",\"mp\":\"704174c.svg\",\"flag_no\":\"8ead297.svg\",\"no\":\"8ead297.svg\",\"flag_om\":\"83309b0.svg\",\"om\":\"83309b0.svg\",\"flag_pk\":\"63477da.svg\",\"pk\":\"63477da.svg\",\"flag_pw\":\"7806d88.svg\",\"pw\":\"7806d88.svg\",\"flag_ps\":\"ed1ab14.svg\",\"ps\":\"ed1ab14.svg\",\"flag_pa\":\"5300ebb.svg\",\"pa\":\"5300ebb.svg\",\"flag_pg\":\"b2d5ce6.svg\",\"pg\":\"b2d5ce6.svg\",\"flag_py\":\"4230491.svg\",\"py\":\"4230491.svg\",\"flag_pe\":\"a27ffb4.svg\",\"pe\":\"a27ffb4.svg\",\"flag_ph\":\"d66113b.svg\",\"ph\":\"d66113b.svg\",\"flag_pn\":\"27cadf4.svg\",\"pn\":\"27cadf4.svg\",\"flag_pl\":\"fca0605.svg\",\"pl\":\"fca0605.svg\",\"flag_pt\":\"f0fbb6a.svg\",\"pt\":\"f0fbb6a.svg\",\"flag_pr\":\"1f8701b.svg\",\"pr\":\"1f8701b.svg\",\"flag_qa\":\"c098ca4.svg\",\"qa\":\"c098ca4.svg\",\"flag_re\":\"13fdd39.svg\",\"re\":\"13fdd39.svg\",\"flag_ro\":\"b56504a.svg\",\"ro\":\"b56504a.svg\",\"flag_ru\":\"904f92c.svg\",\"ru\":\"904f92c.svg\",\"flag_rw\":\"ccce0f2.svg\",\"rw\":\"ccce0f2.svg\",\"flag_ws\":\"db45833.svg\",\"ws\":\"db45833.svg\",\"flag_sm\":\"9f22d88.svg\",\"sm\":\"9f22d88.svg\",\"flag_st\":\"c1570c6.svg\",\"st\":\"c1570c6.svg\",\"flag_sa\":\"a1b7982.svg\",\"saudiarabia\":\"a1b7982.svg\",\"saudi\":\"a1b7982.svg\",\"flag_sn\":\"840d9e2.svg\",\"sn\":\"840d9e2.svg\",\"flag_rs\":\"99cc773.svg\",\"rs\":\"99cc773.svg\",\"flag_sc\":\"55b9a97.svg\",\"sc\":\"55b9a97.svg\",\"flag_sl\":\"90325e9.svg\",\"sl\":\"90325e9.svg\",\"flag_sg\":\"9b25e68.svg\",\"sg\":\"9b25e68.svg\",\"flag_sx\":\"898d18c.svg\",\"sx\":\"898d18c.svg\",\"flag_sk\":\"93a9eef.svg\",\"sk\":\"93a9eef.svg\",\"flag_si\":\"5411747.svg\",\"si\":\"5411747.svg\",\"flag_gs\":\"ffbb640.svg\",\"gs\":\"ffbb640.svg\",\"flag_sb\":\"c95ec38.svg\",\"sb\":\"c95ec38.svg\",\"flag_so\":\"7152ad9.svg\",\"so\":\"7152ad9.svg\",\"flag_za\":\"1fdd78a.svg\",\"za\":\"1fdd78a.svg\",\"flag_kr\":\"8010072.svg\",\"kr\":\"8010072.svg\",\"flag_ss\":\"955766c.svg\",\"ss\":\"955766c.svg\",\"flag_es\":\"882b8a5.svg\",\"es\":\"882b8a5.svg\",\"flag_lk\":\"1ea9311.svg\",\"lk\":\"1ea9311.svg\",\"flag_bl\":\"65be4e2.svg\",\"bl\":\"65be4e2.svg\",\"flag_sh\":\"60f689f.svg\",\"sh\":\"60f689f.svg\",\"flag_kn\":\"ab7357a.svg\",\"kn\":\"ab7357a.svg\",\"flag_lc\":\"58f05bc.svg\",\"lc\":\"58f05bc.svg\",\"flag_pm\":\"793f2a1.svg\",\"pm\":\"793f2a1.svg\",\"flag_vc\":\"08c258a.svg\",\"vc\":\"08c258a.svg\",\"flag_sd\":\"c18be0c.svg\",\"sd\":\"c18be0c.svg\",\"flag_sr\":\"def026c.svg\",\"sr\":\"def026c.svg\",\"flag_sz\":\"90c9442.svg\",\"sz\":\"90c9442.svg\",\"flag_se\":\"db90821.svg\",\"se\":\"db90821.svg\",\"flag_ch\":\"583f42f.svg\",\"ch\":\"583f42f.svg\",\"flag_sy\":\"ee512bb.svg\",\"sy\":\"ee512bb.svg\",\"flag_tw\":\"7cb6090.svg\",\"tw\":\"7cb6090.svg\",\"flag_tj\":\"d422fb2.svg\",\"tj\":\"d422fb2.svg\",\"flag_tz\":\"fa1a399.svg\",\"tz\":\"fa1a399.svg\",\"flag_th\":\"a9413d5.svg\",\"th\":\"a9413d5.svg\",\"flag_tl\":\"393a39d.svg\",\"tl\":\"393a39d.svg\",\"flag_tg\":\"30d9a64.svg\",\"tg\":\"30d9a64.svg\",\"flag_tk\":\"6f952b9.svg\",\"tk\":\"6f952b9.svg\",\"flag_to\":\"9bd12aa.svg\",\"to\":\"9bd12aa.svg\",\"flag_tt\":\"23248eb.svg\",\"tt\":\"23248eb.svg\",\"flag_tn\":\"49a4f80.svg\",\"tn\":\"49a4f80.svg\",\"flag_tr\":\"38d8134.svg\",\"tr\":\"38d8134.svg\",\"flag_tm\":\"7855a69.svg\",\"turkmenistan\":\"7855a69.svg\",\"flag_tc\":\"f2246a1.svg\",\"tc\":\"f2246a1.svg\",\"flag_vi\":\"d3e3869.svg\",\"vi\":\"d3e3869.svg\",\"flag_tv\":\"e279f07.svg\",\"tuvalu\":\"e279f07.svg\",\"flag_ug\":\"b8a0b18.svg\",\"ug\":\"b8a0b18.svg\",\"flag_ua\":\"9a457bf.svg\",\"ua\":\"9a457bf.svg\",\"flag_ae\":\"3aaa070.svg\",\"ae\":\"3aaa070.svg\",\"flag_gb\":\"8769359.svg\",\"gb\":\"8769359.svg\",\"england\":\"9e4c2f7.svg\",\"scotland\":\"102beba.svg\",\"wales\":\"889e756.svg\",\"flag_us\":\"84b0e30.svg\",\"us\":\"84b0e30.svg\",\"flag_uy\":\"9245552.svg\",\"uy\":\"9245552.svg\",\"flag_uz\":\"ed83e3c.svg\",\"uz\":\"ed83e3c.svg\",\"flag_vu\":\"6bbb7d2.svg\",\"vu\":\"6bbb7d2.svg\",\"flag_va\":\"a1a2d63.svg\",\"va\":\"a1a2d63.svg\",\"flag_ve\":\"15397c2.svg\",\"ve\":\"15397c2.svg\",\"flag_vn\":\"59f29b4.svg\",\"vn\":\"59f29b4.svg\",\"flag_wf\":\"c070457.svg\",\"wf\":\"c070457.svg\",\"flag_eh\":\"ef917c3.svg\",\"eh\":\"ef917c3.svg\",\"flag_ye\":\"3dc1641.svg\",\"ye\":\"3dc1641.svg\",\"flag_zm\":\"d5aa7bf.svg\",\"zm\":\"d5aa7bf.svg\",\"flag_zw\":\"1339620.svg\",\"zw\":\"1339620.svg\",\"flag_ac\":\"8a4e07a.svg\",\"ac\":\"8a4e07a.svg\",\"flag_bv\":\"a57dbec.svg\",\"bv\":\"a57dbec.svg\",\"flag_cp\":\"5cff674.svg\",\"cp\":\"5cff674.svg\",\"flag_ea\":\"882b8a5.svg\",\"ea\":\"882b8a5.svg\",\"flag_dg\":\"80ba637.svg\",\"dg\":\"80ba637.svg\",\"flag_hm\":\"9d6fbca.svg\",\"hm\":\"9d6fbca.svg\",\"flag_mf\":\"5cff674.svg\",\"mf\":\"5cff674.svg\",\"flag_sj\":\"8ead297.svg\",\"sj\":\"8ead297.svg\",\"flag_ta\":\"48a59c7.svg\",\"ta\":\"48a59c7.svg\",\"flag_um\":\"84b0e30.svg\",\"um\":\"84b0e30.svg\",\"united_nations\":\"b78eaa7.svg\",\"tone1\":\"5c22a97.svg\",\"tone2\":\"1bde3f6.svg\",\"tone3\":\"30c76df.svg\",\"tone4\":\"e2c6475.svg\",\"tone5\":\"7a30939.svg\",\"regional_indicator_z\":\"ba4c07e.svg\",\"regional_indicator_y\":\"9ae7657.svg\",\"regional_indicator_x\":\"737ad95.svg\",\"regional_indicator_w\":\"fb4dbc8.svg\",\"regional_indicator_v\":\"edf1413.svg\",\"regional_indicator_u\":\"16f72a9.svg\",\"regional_indicator_t\":\"1fd0821.svg\",\"regional_indicator_s\":\"8cd4908.svg\",\"regional_indicator_r\":\"d3c6db1.svg\",\"regional_indicator_q\":\"531402c.svg\",\"regional_indicator_p\":\"973b3ec.svg\",\"regional_indicator_o\":\"a9fc48d.svg\",\"regional_indicator_n\":\"de42301.svg\",\"regional_indicator_m\":\"22dc734.svg\",\"regional_indicator_l\":\"f03a0fa.svg\",\"regional_indicator_k\":\"f873ac4.svg\",\"regional_indicator_j\":\"4241d63.svg\",\"regional_indicator_i\":\"2ac4206.svg\",\"regional_indicator_h\":\"42dc7d9.svg\",\"regional_indicator_g\":\"598a430.svg\",\"regional_indicator_f\":\"c68d66b.svg\",\"regional_indicator_e\":\"2ec6c44.svg\",\"regional_indicator_d\":\"a9d2a41.svg\",\"regional_indicator_c\":\"2d7b2d5.svg\",\"regional_indicator_b\":\"19bb970.svg\",\"regional_indicator_a\":\"c3eea8b.svg\"}"); \ No newline at end of file diff --git a/src/utils/fetch.ts b/src/utils/fetch.ts new file mode 100644 index 000000000..5ee1b9da8 --- /dev/null +++ b/src/utils/fetch.ts @@ -0,0 +1,71 @@ +import qsStringify from 'qs-stringify'; +import type { DocWithErrors, Errors } from 'jsonapi-typescript'; +import readApplicationConfig from './readApplicationConfig'; + +const clientOptions = readApplicationConfig(); + +export type ListResponse<Data> = { + data: Data[], + meta: { + offset: number, + pageSize: number, + results: number, + total: number, + }, + included: Record<string, object[]>, + links: { + self: string, + next?: string, + prev?: string, + }, +} + +class FetchError extends Error { + response?: Response; + + errors?: Errors; +} + +type FetchOptions = { + method?: 'get' | 'post' | 'put' | 'patch' | 'delete', + data?: object, + qs?: Parameters<typeof qsStringify>[0], + signal?: AbortSignal, +}; +async function uwFetch<T = object>(args: [path: string, options?: FetchOptions] | string) { + const path = typeof args === 'string' ? args : args[0]; + const options = (typeof args === 'string' ? undefined : args[1]) ?? {}; + + const url = new URL(`/api${path}`, clientOptions?.apiUrl ?? window.location.href); + if (options.qs) { + url.search = qsStringify(options.qs); + } + + const response = await fetch(url, { + method: options.method ?? 'get', + body: options.data ? JSON.stringify(options.data) : undefined, + headers: { + accept: 'application/json', + 'content-type': 'application/json', + }, + signal: options.signal, + }); + + if (response.status !== 200) { + const data = await response.json(); + if (!('errors' in data)) { + throw new Error('An unknown error occurred.'); + } + const { errors } = data as DocWithErrors; + const error = new FetchError(errors.map((err) => err.title).join(', ')); + error.response = response; + error.errors = errors; + throw error; + } + + const data = await response.json(); + + return data as T; +} + +export default uwFetch; diff --git a/src/utils/mergeIncludedModels.js b/src/utils/mergeIncludedModels.js index 3c0d565d2..6fd9bac4e 100644 --- a/src/utils/mergeIncludedModels.js +++ b/src/utils/mergeIncludedModels.js @@ -1,7 +1,12 @@ import dlv from 'dlv'; import { dset } from 'dset'; +import merge from 'deepmerge'; -function mergeIncludedModels({ data, meta, included }) { +/** + * @param {{ data: any[], meta: object, included: object }} response + */ +function mergeIncludedModels({ data: input, meta, included }) { + const data = merge({}, input, { clone: true }); Object.keys(meta.included ?? {}).forEach((type) => { meta.included[type].forEach((path) => { data.forEach((item) => { diff --git a/src/utils/readApplicationConfig.js b/src/utils/readApplicationConfig.js index 576fb47b5..aaf1b8e45 100644 --- a/src/utils/readApplicationConfig.js +++ b/src/utils/readApplicationConfig.js @@ -1,7 +1,11 @@ -import { initialState } from '../reducers/config'; +/** @typedef {import('../reducers/config').State} Config */ export default function readApplicationConfig(container = '#u-wave-config') { - const config = { ...initialState }; + /** @type {Config} */ + const config = { + roles: undefined, + emoji: {}, + }; try { Object.assign(config, JSON.parse(document.querySelector(container).textContent)); diff --git a/test/setup.mjs b/test/setup.mjs new file mode 100644 index 000000000..a4ef5c4a6 --- /dev/null +++ b/test/setup.mjs @@ -0,0 +1,9 @@ +import { afterEach } from 'vitest'; +import { cleanup } from '@testing-library/react'; +// extends Vitest's expect method with methods from react-testing-library +import '@testing-library/jest-dom/vitest'; + +// runs a cleanup after each test case (e.g. clearing jsdom) +afterEach(() => { + cleanup(); +}); diff --git a/test/yaml-transform.mjs b/test/yaml-transform.mjs deleted file mode 100644 index d4c1fc20f..000000000 --- a/test/yaml-transform.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import yaml from 'js-yaml'; - -function process(src) { - const json = yaml.load(src); - return { code: `module.exports = ${JSON.stringify(json)};` }; -} - -export default { process }; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..c7c684cb9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "esnext", + "useDefineForClassFields": true, + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"] +} diff --git a/vite.config.mjs b/vite.config.mjs index 35802b620..d78679f7c 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -9,6 +9,10 @@ const outputPkg = new URL('./npm/package.json', import.meta.url); export default defineConfig({ clearScreen: false, + legacy: { + // For the prerender plugin + proxySsrExternalModules: true, + }, resolve: { alias: { '@mui/base': '@mui/base/modern', @@ -45,9 +49,9 @@ export default defineConfig({ splitVendorChunkPlugin(), react(), yaml(), - prerender({ file: 'index.html', source: 'src/index.jsx' }), + prerender({ file: 'index.html', source: 'src/index.tsx' }), prerender({ file: 'password-reset.html', source: 'src/password-reset/index.jsx' }), - prerender({ file: 'privacy.html', source: 'src/markdown.jsx', props: { path: 'static/privacy.md' } }), + prerender({ file: 'privacy.html', source: 'src/markdown.tsx', props: { path: 'static/privacy.md' } }), { name: 'u-wave-write-package-version', apply: 'build', @@ -59,4 +63,10 @@ export default defineConfig({ }, }, ], + test: { + include: ['**/__tests__/*.{js,jsx,ts,tsx}'], + globals: true, + environment: 'jsdom', + setupFiles: './test/setup.mjs', + }, });