summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gui/package-lock.json697
-rw-r--r--gui/package.json3
-rw-r--r--gui/src/renderer/app.tsx29
-rw-r--r--gui/src/renderer/components/Accordion.tsx10
-rw-r--r--gui/src/renderer/components/AppButton.tsx16
-rw-r--r--gui/src/renderer/components/AppButtonStyles.tsx6
-rw-r--r--gui/src/renderer/components/ConnectionPanelDisclosure.tsx10
-rw-r--r--gui/src/renderer/components/CustomDnsSettings.tsx10
-rw-r--r--gui/src/renderer/components/CustomDnsSettingsStyles.tsx25
-rw-r--r--gui/src/renderer/components/CustomScrollbars.tsx46
-rw-r--r--gui/src/renderer/components/Filter.tsx14
-rw-r--r--gui/src/renderer/components/FormattableTextInput.tsx6
-rw-r--r--gui/src/renderer/components/HeaderBar.tsx20
-rw-r--r--gui/src/renderer/components/ImageView.tsx25
-rw-r--r--gui/src/renderer/components/Launch.tsx6
-rw-r--r--gui/src/renderer/components/Login.tsx12
-rw-r--r--gui/src/renderer/components/LoginStyles.tsx30
-rw-r--r--gui/src/renderer/components/MacOsScrollbarDetection.tsx5
-rw-r--r--gui/src/renderer/components/Marquee.tsx14
-rw-r--r--gui/src/renderer/components/Modal.tsx22
-rw-r--r--gui/src/renderer/components/NavigationBar.tsx2
-rw-r--r--gui/src/renderer/components/NavigationBarStyles.tsx6
-rw-r--r--gui/src/renderer/components/NotificationArea.tsx2
-rw-r--r--gui/src/renderer/components/NotificationBanner.tsx21
-rw-r--r--gui/src/renderer/components/RedeemVoucherStyles.tsx2
-rw-r--r--gui/src/renderer/components/RelayStatusIndicator.tsx6
-rw-r--r--gui/src/renderer/components/SearchBar.tsx27
-rw-r--r--gui/src/renderer/components/SecuredLabel.tsx11
-rw-r--r--gui/src/renderer/components/SelectLanguage.tsx2
-rw-r--r--gui/src/renderer/components/SettingsHeader.tsx2
-rw-r--r--gui/src/renderer/components/SplitTunnelingSettings.tsx30
-rw-r--r--gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx35
-rw-r--r--gui/src/renderer/components/Switch.tsx12
-rw-r--r--gui/src/renderer/components/TransitionContainer.tsx57
-rw-r--r--gui/src/renderer/components/cell/CellButton.tsx20
-rw-r--r--gui/src/renderer/components/cell/Group.tsx6
-rw-r--r--gui/src/renderer/components/cell/Input.tsx40
-rw-r--r--gui/src/renderer/components/cell/Label.tsx8
-rw-r--r--gui/src/renderer/components/cell/Row.tsx11
-rw-r--r--gui/src/renderer/components/cell/Section.tsx10
-rw-r--r--gui/src/renderer/components/cell/Selector.tsx19
-rw-r--r--gui/src/renderer/components/select-location/CustomLists.tsx22
-rw-r--r--gui/src/renderer/components/select-location/LocationRow.tsx50
-rw-r--r--gui/src/renderer/components/select-location/RelayLocationList.tsx2
-rw-r--r--gui/src/renderer/components/select-location/ScopeBar.tsx4
-rw-r--r--gui/src/renderer/components/select-location/ScrollPositionContext.tsx4
-rw-r--r--gui/src/renderer/components/select-location/SpecialLocationList.tsx4
-rw-r--r--gui/src/renderer/lib/styles.ts9
-rw-r--r--gui/src/renderer/lib/utilityHooks.ts4
49 files changed, 623 insertions, 811 deletions
diff --git a/gui/package-lock.json b/gui/package-lock.json
index 034b8c609d..bdd3476016 100644
--- a/gui/package-lock.json
+++ b/gui/package-lock.json
@@ -24,7 +24,7 @@
"react-simple-maps": "^3.0.0",
"redux": "^4.2.0",
"sprintf-js": "^1.1.2",
- "styled-components": "^5.1.1"
+ "styled-components": "^6.1.0"
},
"devDependencies": {
"@electron/notarize": "^2.1.0",
@@ -46,7 +46,6 @@
"@types/react-simple-maps": "^1.0.8",
"@types/sinon": "^10.0.13",
"@types/sprintf-js": "^1.1.2",
- "@types/styled-components": "^5.1.26",
"@types/topojson-specification": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
@@ -89,18 +88,11 @@
"nseventmonitor": "^1.0.3"
}
},
- "node_modules/@babel/code-frame": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
- "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
- "dependencies": {
- "@babel/highlight": "^7.10.4"
- }
- },
"node_modules/@babel/generator": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz",
"integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.18.2",
"@jridgewell/gen-mapping": "^0.3.0",
@@ -110,70 +102,20 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
- "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
- "dependencies": {
- "@babel/types": "^7.10.4"
- }
- },
- "node_modules/@babel/helper-function-name": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
- "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
- "dependencies": {
- "@babel/helper-get-function-arity": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "node_modules/@babel/helper-get-function-arity": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
- "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
- "dependencies": {
- "@babel/types": "^7.10.4"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.12.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz",
- "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==",
- "dependencies": {
- "@babel/types": "^7.12.5"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
- "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
- "dependencies": {
- "@babel/types": "^7.11.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==",
+ "dev": true,
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/highlight": {
- "version": "7.14.0",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
- "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.14.0",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- }
- },
"node_modules/@babel/parser": {
"version": "7.18.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
"integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==",
+ "dev": true,
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -192,60 +134,11 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/template": {
- "version": "7.12.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz",
- "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==",
- "dependencies": {
- "@babel/code-frame": "^7.10.4",
- "@babel/parser": "^7.12.7",
- "@babel/types": "^7.12.7"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.12.9",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz",
- "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==",
- "dependencies": {
- "@babel/code-frame": "^7.10.4",
- "@babel/generator": "^7.12.5",
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.11.0",
- "@babel/parser": "^7.12.7",
- "@babel/types": "^7.12.7",
- "debug": "^4.1.0",
- "globals": "^11.1.0",
- "lodash": "^4.17.19"
- }
- },
- "node_modules/@babel/traverse/node_modules/debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- }
- },
- "node_modules/@babel/traverse/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==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/traverse/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/@babel/types": {
"version": "7.18.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz",
"integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==",
+ "dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.16.7",
"to-fast-properties": "^2.0.0"
@@ -486,27 +379,22 @@
}
},
"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==",
+ "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": {
- "@emotion/memoize": "^0.8.0"
+ "@emotion/memoize": "^0.8.1"
}
},
"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/@emotion/stylis": {
- "version": "0.8.5",
- "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
- "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
+ "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/unitless": {
- "version": "0.7.5",
- "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
- "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.3.0",
@@ -784,6 +672,7 @@
"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,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -797,6 +686,7 @@
"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"
}
@@ -805,6 +695,7 @@
"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": ">=6.0.0"
}
@@ -812,12 +703,14 @@
"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=="
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@@ -1568,16 +1461,10 @@
"integrity": "sha512-hkgzYF+qnIl8uTO8rmUSVSfQ8BIfMXC4yJAF4n8BE758YsKBZvFC4NumnAegj7KmylP0liEZNpb9RRGFMbFejA==",
"dev": true
},
- "node_modules/@types/styled-components": {
- "version": "5.1.26",
- "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz",
- "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==",
- "dev": true,
- "dependencies": {
- "@types/hoist-non-react-statics": "*",
- "@types/react": "*",
- "csstype": "^3.0.2"
- }
+ "node_modules/@types/stylis": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.2.tgz",
+ "integrity": "sha512-Rm17MsTpQQP5Jq4BF7CdrxJsDufoiL/q5IbJZYZmOZAJALyijgF7BzLgobXUqraNcQdqFYLYGeglDp6QzaxPpg=="
},
"node_modules/@types/topojson-specification": {
"version": "1.0.2",
@@ -2059,17 +1946,6 @@
"node": ">=0.10.0"
}
},
- "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": ">=4"
- }
- },
"node_modules/ansi-wrap": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
@@ -2683,22 +2559,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/babel-plugin-styled-components": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz",
- "integrity": "sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.0.0",
- "@babel/helper-module-imports": "^7.0.0",
- "babel-plugin-syntax-jsx": "^6.18.0",
- "lodash": "^4.17.11"
- }
- },
- "node_modules/babel-plugin-syntax-jsx": {
- "version": "6.18.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
- "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
- },
"node_modules/bach": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
@@ -3404,9 +3264,12 @@
}
},
"node_modules/camelize": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
- "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/chai": {
"version": "4.3.6",
@@ -3444,19 +3307,6 @@
"node": ">= 4.0.0"
}
},
- "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/check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
@@ -3704,19 +3554,6 @@
"node": ">=0.10.0"
}
},
- "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": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
- },
"node_modules/color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
@@ -4017,7 +3854,7 @@
"node_modules/css-color-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
- "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
"engines": {
"node": ">=4"
}
@@ -4032,9 +3869,9 @@
]
},
"node_modules/css-to-react-native": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
- "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
"dependencies": {
"camelize": "^1.0.0",
"css-color-keywords": "^1.0.0",
@@ -4062,9 +3899,9 @@
}
},
"node_modules/csstype": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz",
- "integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA=="
+ "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",
@@ -5340,14 +5177,6 @@
"node": ">=6"
}
},
- "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": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/eslint": {
"version": "8.36.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
@@ -7339,14 +7168,6 @@
"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": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/has-property-descriptors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
@@ -8470,6 +8291,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
"bin": {
"jsesc": "bin/jsesc"
},
@@ -8755,7 +8577,8 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
},
"node_modules/lodash.camelcase": {
"version": "4.3.0",
@@ -11079,9 +10902,9 @@
}
},
"node_modules/postcss-value-parser": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
- "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/postcss/node_modules/source-map": {
"version": "0.6.1",
@@ -12501,6 +12324,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/source-map-resolve": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
@@ -12903,24 +12734,22 @@
}
},
"node_modules/styled-components": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.6.tgz",
- "integrity": "sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==",
- "hasInstallScript": true,
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.0.tgz",
+ "integrity": "sha512-VWNfYYBuXzuLS/QYEeoPgMErP26WL+dX9//rEh80B2mmlS1yRxRxuL5eax4m6ybYEUoHWlTy2XOU32767mlMkg==",
"dependencies": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/traverse": "^7.4.5",
- "@emotion/is-prop-valid": "^1.1.0",
- "@emotion/stylis": "^0.8.4",
- "@emotion/unitless": "^0.7.4",
- "babel-plugin-styled-components": ">= 1.12.0",
- "css-to-react-native": "^3.0.0",
- "hoist-non-react-statics": "^3.0.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/unitless": "^0.8.0",
+ "@types/stylis": "^4.0.2",
+ "css-to-react-native": "^3.2.0",
+ "csstype": "^3.1.2",
+ "postcss": "^8.4.31",
"shallowequal": "^1.1.0",
- "supports-color": "^5.5.0"
+ "stylis": "^4.3.0",
+ "tslib": "^2.5.0"
},
"engines": {
- "node": ">=10"
+ "node": ">= 16"
},
"funding": {
"type": "opencollective",
@@ -12928,10 +12757,68 @@
},
"peerDependencies": {
"react": ">= 16.8.0",
- "react-dom": ">= 16.8.0",
- "react-is": ">= 16.8.0"
+ "react-dom": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-components/node_modules/nanoid": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/styled-components/node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
}
},
+ "node_modules/styled-components/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "node_modules/stylis": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz",
+ "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ=="
+ },
"node_modules/subarg": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
@@ -12976,17 +12863,6 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
- "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": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"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",
@@ -13251,6 +13127,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true,
"engines": {
"node": ">=4"
}
@@ -14381,85 +14258,28 @@
}
},
"dependencies": {
- "@babel/code-frame": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
- "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
- "requires": {
- "@babel/highlight": "^7.10.4"
- }
- },
"@babel/generator": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz",
"integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==",
+ "dev": true,
"requires": {
"@babel/types": "^7.18.2",
"@jridgewell/gen-mapping": "^0.3.0",
"jsesc": "^2.5.1"
}
},
- "@babel/helper-annotate-as-pure": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz",
- "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==",
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-function-name": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
- "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
- "requires": {
- "@babel/helper-get-function-arity": "^7.10.4",
- "@babel/template": "^7.10.4",
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-get-function-arity": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
- "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
- "requires": {
- "@babel/types": "^7.10.4"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.12.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz",
- "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==",
- "requires": {
- "@babel/types": "^7.12.5"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
- "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
- "requires": {
- "@babel/types": "^7.11.0"
- }
- },
"@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=="
- },
- "@babel/highlight": {
- "version": "7.14.0",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
- "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
- "requires": {
- "@babel/helper-validator-identifier": "^7.14.0",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- }
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "dev": true
},
"@babel/parser": {
"version": "7.18.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz",
- "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow=="
+ "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==",
+ "dev": true
},
"@babel/runtime": {
"version": "7.19.0",
@@ -14469,56 +14289,11 @@
"regenerator-runtime": "^0.13.4"
}
},
- "@babel/template": {
- "version": "7.12.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz",
- "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==",
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/parser": "^7.12.7",
- "@babel/types": "^7.12.7"
- }
- },
- "@babel/traverse": {
- "version": "7.12.9",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz",
- "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==",
- "requires": {
- "@babel/code-frame": "^7.10.4",
- "@babel/generator": "^7.12.5",
- "@babel/helper-function-name": "^7.10.4",
- "@babel/helper-split-export-declaration": "^7.11.0",
- "@babel/parser": "^7.12.7",
- "@babel/types": "^7.12.7",
- "debug": "^4.1.0",
- "globals": "^11.1.0",
- "lodash": "^4.17.19"
- },
- "dependencies": {
- "debug": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
- "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
- "requires": {
- "ms": "2.1.2"
- }
- },
- "globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- }
- }
- },
"@babel/types": {
"version": "7.18.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz",
"integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==",
+ "dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.16.7",
"to-fast-properties": "^2.0.0"
@@ -14699,27 +14474,22 @@
}
},
"@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==",
+ "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==",
"requires": {
- "@emotion/memoize": "^0.8.0"
+ "@emotion/memoize": "^0.8.1"
}
},
"@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=="
- },
- "@emotion/stylis": {
- "version": "0.8.5",
- "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
- "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ=="
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"@emotion/unitless": {
- "version": "0.7.5",
- "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
- "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
},
"@eslint-community/eslint-utils": {
"version": "4.3.0",
@@ -14922,6 +14692,7 @@
"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,
"requires": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -14931,22 +14702,26 @@
"@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=="
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true
},
"@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=="
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true
},
"@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=="
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
},
"@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@@ -15610,16 +15385,10 @@
"integrity": "sha512-hkgzYF+qnIl8uTO8rmUSVSfQ8BIfMXC4yJAF4n8BE758YsKBZvFC4NumnAegj7KmylP0liEZNpb9RRGFMbFejA==",
"dev": true
},
- "@types/styled-components": {
- "version": "5.1.26",
- "resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.26.tgz",
- "integrity": "sha512-KuKJ9Z6xb93uJiIyxo/+ksS7yLjS1KzG6iv5i78dhVg/X3u5t1H7juRWqVmodIdz6wGVaIApo1u01kmFRdJHVw==",
- "dev": true,
- "requires": {
- "@types/hoist-non-react-statics": "*",
- "@types/react": "*",
- "csstype": "^3.0.2"
- }
+ "@types/stylis": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.2.tgz",
+ "integrity": "sha512-Rm17MsTpQQP5Jq4BF7CdrxJsDufoiL/q5IbJZYZmOZAJALyijgF7BzLgobXUqraNcQdqFYLYGeglDp6QzaxPpg=="
},
"@types/topojson-specification": {
"version": "1.0.2",
@@ -15954,14 +15723,6 @@
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"devOptional": true
},
- "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==",
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
"ansi-wrap": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
@@ -16448,22 +16209,6 @@
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
"dev": true
},
- "babel-plugin-styled-components": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz",
- "integrity": "sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA==",
- "requires": {
- "@babel/helper-annotate-as-pure": "^7.0.0",
- "@babel/helper-module-imports": "^7.0.0",
- "babel-plugin-syntax-jsx": "^6.18.0",
- "lodash": "^4.17.11"
- }
- },
- "babel-plugin-syntax-jsx": {
- "version": "6.18.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
- "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
- },
"bach": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
@@ -17078,9 +16823,9 @@
"dev": true
},
"camelize": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
- "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="
},
"chai": {
"version": "4.3.6",
@@ -17112,16 +16857,6 @@
"integrity": "sha512-elF2ZUczBsFoP07qCfMO/zeggs8pqCf3fZGyK5+2X4AndS8jycZYID91ztD9oQ7d/0tnS963dPkd0frQEThDsg==",
"dev": true
},
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
@@ -17317,19 +17052,6 @@
"object-visit": "^1.0.0"
}
},
- "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==",
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
- },
"color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
@@ -17611,7 +17333,7 @@
"css-color-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
- "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU="
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="
},
"css-selector-parser": {
"version": "1.3.0",
@@ -17620,9 +17342,9 @@
"dev": true
},
"css-to-react-native": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz",
- "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
"requires": {
"camelize": "^1.0.0",
"css-color-keywords": "^1.0.0",
@@ -17630,9 +17352,9 @@
}
},
"csstype": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz",
- "integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA=="
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
+ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
"d": {
"version": "1.0.1",
@@ -18677,11 +18399,6 @@
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
- },
"eslint": {
"version": "8.36.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
@@ -20241,11 +19958,6 @@
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true
},
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
- },
"has-property-descriptors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
@@ -21091,7 +20803,8 @@
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
},
"json-buffer": {
"version": "3.0.1",
@@ -21320,7 +21033,8 @@
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
},
"lodash.camelcase": {
"version": "4.3.0",
@@ -23093,9 +22807,9 @@
}
},
"postcss-value-parser": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
- "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"prebuild-install": {
"version": "6.1.4",
@@ -24219,6 +23933,11 @@
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
},
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
+ },
"source-map-resolve": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
@@ -24565,22 +24284,53 @@
"dev": true
},
"styled-components": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.6.tgz",
- "integrity": "sha512-hGTZquGAaTqhGWldX7hhfzjnIYBZ0IXQXkCYdvF1Sq3DsUaLx6+NTHC5Jj1ooM2F68sBiVz3lvhfwQs/S3l6qg==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.0.tgz",
+ "integrity": "sha512-VWNfYYBuXzuLS/QYEeoPgMErP26WL+dX9//rEh80B2mmlS1yRxRxuL5eax4m6ybYEUoHWlTy2XOU32767mlMkg==",
"requires": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/traverse": "^7.4.5",
- "@emotion/is-prop-valid": "^1.1.0",
- "@emotion/stylis": "^0.8.4",
- "@emotion/unitless": "^0.7.4",
- "babel-plugin-styled-components": ">= 1.12.0",
- "css-to-react-native": "^3.0.0",
- "hoist-non-react-statics": "^3.0.0",
+ "@emotion/is-prop-valid": "^1.2.1",
+ "@emotion/unitless": "^0.8.0",
+ "@types/stylis": "^4.0.2",
+ "css-to-react-native": "^3.2.0",
+ "csstype": "^3.1.2",
+ "postcss": "^8.4.31",
"shallowequal": "^1.1.0",
- "supports-color": "^5.5.0"
+ "stylis": "^4.3.0",
+ "tslib": "^2.5.0"
+ },
+ "dependencies": {
+ "nanoid": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA=="
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "requires": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ }
}
},
+ "stylis": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz",
+ "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ=="
+ },
"subarg": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
@@ -24616,14 +24366,6 @@
}
}
},
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
"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",
@@ -24846,7 +24588,8 @@
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
},
"to-object-path": {
"version": "0.3.0",
diff --git a/gui/package.json b/gui/package.json
index 1ca1192cbe..cae1ec64c9 100644
--- a/gui/package.json
+++ b/gui/package.json
@@ -26,7 +26,7 @@
"react-simple-maps": "^3.0.0",
"redux": "^4.2.0",
"sprintf-js": "^1.1.2",
- "styled-components": "^5.1.1"
+ "styled-components": "^6.1.0"
},
"optionalDependencies": {
"grpc-tools": "^1.12.4",
@@ -52,7 +52,6 @@
"@types/react-simple-maps": "^1.0.8",
"@types/sinon": "^10.0.13",
"@types/sprintf-js": "^1.1.2",
- "@types/styled-components": "^5.1.26",
"@types/topojson-specification": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^5.56.0",
"@typescript-eslint/parser": "^5.56.0",
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index 7c7df73796..bab17524d6 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -1,6 +1,7 @@
import { batch, Provider } from 'react-redux';
import { Router } from 'react-router';
import { bindActionCreators } from 'redux';
+import { StyleSheetManager } from 'styled-components';
import { hasExpired } from '../shared/account-expiry';
import { ILinuxSplitTunnelingApplication, IWindowsApplication } from '../shared/application-types';
@@ -276,19 +277,21 @@ export default class AppRenderer {
return (
<AppContext.Provider value={{ app: this }}>
<Provider store={this.reduxStore}>
- <Lang>
- <Router history={this.history.asHistory}>
- <ErrorBoundary>
- <ModalContainer>
- <KeyboardNavigation>
- <AppRouter />
- <Changelog />
- </KeyboardNavigation>
- {window.env.platform === 'darwin' && <MacOsScrollbarDetection />}
- </ModalContainer>
- </ErrorBoundary>
- </Router>
- </Lang>
+ <StyleSheetManager enableVendorPrefixes>
+ <Lang>
+ <Router history={this.history.asHistory}>
+ <ErrorBoundary>
+ <ModalContainer>
+ <KeyboardNavigation>
+ <AppRouter />
+ <Changelog />
+ </KeyboardNavigation>
+ {window.env.platform === 'darwin' && <MacOsScrollbarDetection />}
+ </ModalContainer>
+ </ErrorBoundary>
+ </Router>
+ </Lang>
+ </StyleSheetManager>
</Provider>
</AppContext.Provider>
);
diff --git a/gui/src/renderer/components/Accordion.tsx b/gui/src/renderer/components/Accordion.tsx
index 682f5aa779..f70258f103 100644
--- a/gui/src/renderer/components/Accordion.tsx
+++ b/gui/src/renderer/components/Accordion.tsx
@@ -14,11 +14,11 @@ interface IState {
containerHeight: string;
}
-const Container = styled.div((props: { height: string; animationDuration: number }) => ({
+const Container = styled.div<{ $height: string; $animationDuration: number }>((props) => ({
display: 'flex',
- height: props.height,
+ height: props.$height,
overflow: 'hidden',
- transition: `height ${props.animationDuration}ms ease-in-out`,
+ transition: `height ${props.$animationDuration}ms ease-in-out`,
}));
const Content = styled.div({
@@ -55,8 +55,8 @@ export default class Accordion extends React.Component<IProps, IState> {
return (
<Container
ref={this.containerRef}
- height={this.state.containerHeight}
- animationDuration={this.props.animationDuration}
+ $height={this.state.containerHeight}
+ $animationDuration={this.props.animationDuration}
onTransitionEnd={this.onTransitionEnd}>
<Content ref={this.contentRef}>{this.state.mountChildren && this.props.children}</Content>
</Container>
diff --git a/gui/src/renderer/components/AppButton.tsx b/gui/src/renderer/components/AppButton.tsx
index 45c93e1b2a..753f64745e 100644
--- a/gui/src/renderer/components/AppButton.tsx
+++ b/gui/src/renderer/components/AppButton.tsx
@@ -22,7 +22,7 @@ interface ILabelProps {
}
export function Label(props: ILabelProps) {
- return <StyledLabel textOffset={props.textOffset ?? 0}>{props.children}</StyledLabel>;
+ return <StyledLabel $textOffset={props.textOffset ?? 0}>{props.children}</StyledLabel>;
}
interface IIconProps {
@@ -108,7 +108,7 @@ const StyledSimpleButton = styled(SimpleButton)({
borderRadius: 4,
border: 'none',
padding: 0,
- ':disabled': {
+ '&&:disabled': {
opacity: 0.5,
},
});
@@ -156,35 +156,35 @@ export function BlockingButton(props: IBlockingProps) {
export const RedButton = styled(BaseButton)({
backgroundColor: colors.red,
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: colors.red95,
},
});
export const GreenButton = styled(BaseButton)({
backgroundColor: colors.green,
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: colors.green90,
},
});
export const BlueButton = styled(BaseButton)({
backgroundColor: colors.blue80,
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: colors.blue60,
},
});
export const TransparentButton = styled(BaseButton)(transparentButton, {
backgroundColor: colors.white20,
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: colors.white40,
},
});
export const RedTransparentButton = styled(BaseButton)(transparentButton, {
backgroundColor: colors.red60,
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: colors.red80,
},
});
@@ -193,7 +193,7 @@ const StyledButtonWrapper = styled.div({
display: 'flex',
flexDirection: 'column',
flex: 0,
- ':not(:last-child)': {
+ '&&:not(:last-child)': {
marginBottom: measurements.buttonVerticalMargin,
},
});
diff --git a/gui/src/renderer/components/AppButtonStyles.tsx b/gui/src/renderer/components/AppButtonStyles.tsx
index f22eb3473a..ac65f951f6 100644
--- a/gui/src/renderer/components/AppButtonStyles.tsx
+++ b/gui/src/renderer/components/AppButtonStyles.tsx
@@ -2,9 +2,9 @@ import styled from 'styled-components';
import { buttonText } from './common-styles';
-export const StyledLabel = styled.span(buttonText, (props: { textOffset: number }) => ({
- paddingLeft: props.textOffset > 0 ? `${props.textOffset}px` : 0,
- paddingRight: props.textOffset < 0 ? `${-props.textOffset}px` : 0,
+export const StyledLabel = styled.span<{ $textOffset: number }>(buttonText, (props) => ({
+ paddingLeft: props.$textOffset > 0 ? `${props.$textOffset}px` : 0,
+ paddingRight: props.$textOffset < 0 ? `${-props.$textOffset}px` : 0,
textAlign: 'center',
wordBreak: 'break-word',
}));
diff --git a/gui/src/renderer/components/ConnectionPanelDisclosure.tsx b/gui/src/renderer/components/ConnectionPanelDisclosure.tsx
index 11ec9a0136..3941c3d88f 100644
--- a/gui/src/renderer/components/ConnectionPanelDisclosure.tsx
+++ b/gui/src/renderer/components/ConnectionPanelDisclosure.tsx
@@ -11,18 +11,18 @@ const Container = styled.div({
width: '100%',
});
-const Caption = styled.span(normalText, (props: { open: boolean }) => ({
+const Caption = styled.span<{ $open: boolean }>(normalText, (props) => ({
fontWeight: 600,
lineHeight: '20px',
minWidth: '0px',
- color: props.open ? colors.white : colors.white40,
- [Container + ':hover &']: {
+ color: props.$open ? colors.white : colors.white40,
+ [Container + ':hover &&']: {
color: colors.white,
},
}));
const Chevron = styled(ImageView)({
- [Container + ':hover &']: {
+ [Container + ':hover &&']: {
backgroundColor: colors.white,
},
});
@@ -37,7 +37,7 @@ interface IProps {
export default function ConnectionPanelDisclosure(props: IProps) {
return (
<Container className={props.className} onClick={props.onToggle}>
- <Caption open={props.pointsUp}>{props.children}</Caption>
+ <Caption $open={props.pointsUp}>{props.children}</Caption>
<Chevron
source={props.pointsUp ? 'icon-chevron-up' : 'icon-chevron-down'}
width={22}
diff --git a/gui/src/renderer/components/CustomDnsSettings.tsx b/gui/src/renderer/components/CustomDnsSettings.tsx
index 824e010970..6b8024c9e2 100644
--- a/gui/src/renderer/components/CustomDnsSettings.tsx
+++ b/gui/src/renderer/components/CustomDnsSettings.tsx
@@ -6,7 +6,7 @@ import { messages } from '../../shared/gettext';
import { useAppContext } from '../context';
import { formatHtml } from '../lib/html-formatter';
import { IpAddress } from '../lib/ip';
-import { useBoolean, useMounted } from '../lib/utilityHooks';
+import { useBoolean, useMounted, useStyledRef } from '../lib/utilityHooks';
import { useSelector } from '../redux/store';
import Accordion from './Accordion';
import * as AppButton from './AppButton';
@@ -57,9 +57,9 @@ export default function CustomDnsSettings() {
[dns],
);
- const switchRef = useRef() as React.RefObject<HTMLDivElement>;
- const addButtonRef = useRef() as React.RefObject<HTMLButtonElement>;
- const inputContainerRef = useRef() as React.RefObject<HTMLDivElement>;
+ const switchRef = useStyledRef<HTMLDivElement>();
+ const addButtonRef = useStyledRef<HTMLButtonElement>();
+ const inputContainerRef = useStyledRef<HTMLDivElement>();
const confirm = useCallback(() => {
void confirmAction?.();
@@ -323,7 +323,7 @@ function CellListItem(props: ICellListItemProps) {
const [invalid, setInvalid, setValid] = useBoolean(false);
const isMounted = useMounted();
- const inputContainerRef = useRef() as React.RefObject<HTMLDivElement>;
+ const inputContainerRef = useStyledRef<HTMLDivElement>();
const onRemove = useCallback(() => props.onRemove(props.children), [
props.onRemove,
diff --git a/gui/src/renderer/components/CustomDnsSettingsStyles.tsx b/gui/src/renderer/components/CustomDnsSettingsStyles.tsx
index b660504a01..b8fdc7fd38 100644
--- a/gui/src/renderer/components/CustomDnsSettingsStyles.tsx
+++ b/gui/src/renderer/components/CustomDnsSettingsStyles.tsx
@@ -12,19 +12,16 @@ export const StyledAddCustomDnsButton = styled(Cell.CellButton)({
backgroundColor: colors.blue40,
});
-export const StyledAddCustomDnsLabel = styled(Cell.Label)(
- {},
- (props: { paddingLeft?: number }) => ({
- fontFamily: 'Open Sans',
- fontWeight: 400,
- fontSize: '16px',
- paddingLeft: (props.paddingLeft ?? 32) + 'px',
- whiteSpace: 'pre-wrap',
- overflowWrap: 'break-word',
- width: '171px',
- marginRight: '25px',
- }),
-);
+export const StyledAddCustomDnsLabel = styled(Cell.Label)<{ $paddingLeft?: number }>((props) => ({
+ fontFamily: 'Open Sans',
+ fontWeight: 400,
+ fontSize: '16px',
+ paddingLeft: (props.$paddingLeft ?? 32) + 'px',
+ whiteSpace: 'pre-wrap',
+ overflowWrap: 'break-word',
+ width: '171px',
+ marginRight: '25px',
+}));
export const StyledContainer = styled(Cell.Container)({
display: 'flex',
@@ -59,7 +56,7 @@ export const StyledRemoveButton = styled.button({
});
export const StyledRemoveIcon = styled(ImageView)({
- [StyledRemoveButton + ':hover &']: {
+ [StyledRemoveButton + ':hover &&']: {
backgroundColor: colors.white80,
},
});
diff --git a/gui/src/renderer/components/CustomScrollbars.tsx b/gui/src/renderer/components/CustomScrollbars.tsx
index ab95d66511..65db8c87fe 100644
--- a/gui/src/renderer/components/CustomScrollbars.tsx
+++ b/gui/src/renderer/components/CustomScrollbars.tsx
@@ -19,44 +19,44 @@ const StyledCustomScrollbars = styled.div({
overflow: 'hidden',
});
-const StyledScrollable = styled.div((props: { fillContainer?: boolean }) => ({
- flex: props.fillContainer ? '1' : undefined,
+const StyledScrollable = styled.div<{ $fillContainer?: boolean }>((props) => ({
+ flex: props.$fillContainer ? '1' : undefined,
width: '100%',
overflow: 'auto',
- '::-webkit-scrollbar': {
+ '&&::-webkit-scrollbar': {
display: 'none',
},
}));
-const StyledTrack = styled.div({}, (props: { canScroll: boolean; show: boolean }) => ({
+const StyledTrack = styled.div<{ $canScroll: boolean; $show: boolean }>((props) => ({
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
width: '16px',
- backgroundColor: props.show ? 'rgba(0, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0)',
+ backgroundColor: props.$show ? 'rgba(0, 0, 0, 0.2)' : 'rgba(0, 0, 0, 0)',
borderRadius: '8px',
transition: 'width 0.1s ease-in-out, background-color 0.25s ease-in-out',
zIndex: 99,
- pointerEvents: props.canScroll ? 'auto' : 'none',
- // Thumb should be less transparent when track is hovered.
- [`&:hover ${StyledThumb}`]: {
- backgroundColor: 'rgba(255, 255, 255, 0.65)',
- },
+ pointerEvents: props.$canScroll ? 'auto' : 'none',
}));
-const StyledThumb = styled.div(
- {},
- (props: { show: boolean; isDragging: boolean; wide: boolean }) => ({
+const StyledThumb = styled.div<{ $show: boolean; $isDragging: boolean; $wide: boolean }>(
+ (props) => ({
position: 'absolute',
top: 0,
right: 0,
- borderRadius: props.wide ? '6px' : '4px',
- width: props.wide ? '12px' : '8px',
+ borderRadius: props.$wide ? '6px' : '4px',
+ width: props.$wide ? '12px' : '8px',
transition:
'width 0.25s ease-in-out, border-radius 0.25s ease-in-out, height 0.25s ease-in-out, opacity 0.25s ease-in-out, background-color 0.1s ease-in-out',
- opacity: props.show ? 1 : 0,
- backgroundColor: props.isDragging ? 'rgba(255, 255, 255, 0.65)' : 'rgba(255, 255, 255, 0.4)',
+ opacity: props.$show ? 1 : 0,
+ backgroundColor: props.$isDragging ? 'rgba(255, 255, 255, 0.65)' : 'rgba(255, 255, 255, 0.4)',
+
+ // Thumb should be less transparent when track is hovered.
+ [`${StyledTrack}:hover &&`]: {
+ backgroundColor: 'rgba(255, 255, 255, 0.65)',
+ },
}),
);
@@ -260,20 +260,20 @@ class CustomScrollbars extends React.Component<IProps, IState> {
<StyledCustomScrollbars {...otherProps}>
<StyledTrack
ref={this.trackRef}
- show={showScrollbars && this.state.active}
- canScroll={this.state.canScroll}
+ $show={showScrollbars && this.state.active}
+ $canScroll={this.state.canScroll}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}>
<StyledThumb
ref={this.thumbRef}
- show={showScrollbars}
- isDragging={this.state.isDragging}
- wide={this.state.active}
+ $show={showScrollbars}
+ $isDragging={this.state.isDragging}
+ $wide={this.state.active}
onMouseDown={this.handleMouseDown}
/>
</StyledTrack>
<StyledScrollable
- fillContainer={fillContainer}
+ $fillContainer={fillContainer}
onScroll={this.onScroll}
ref={this.scrollableRef}>
<StyledScrollableContent ref={this.scrollableContentRef}>
diff --git a/gui/src/renderer/components/Filter.tsx b/gui/src/renderer/components/Filter.tsx
index a8e67b3f9c..2cbc9ab239 100644
--- a/gui/src/renderer/components/Filter.tsx
+++ b/gui/src/renderer/components/Filter.tsx
@@ -201,7 +201,7 @@ function providersSelector(state: IReduxState): Record<string, boolean> {
const StyledSelector = styled(Selector)({
marginBottom: 0,
-}) as typeof Selector;
+});
interface IFilterByOwnershipProps {
ownership: Ownership;
@@ -290,7 +290,7 @@ function FilterByProvider(props: IFilterByProviderProps) {
<Accordion expanded={expanded}>
<CheckboxRow
label={messages.pgettext('filter-view', 'All providers')}
- bold
+ $bold
checked={Object.values(props.providers).every((value) => value)}
onChange={toggleAll}
/>
@@ -310,7 +310,7 @@ function toggleAllProviders(providers: Record<string, boolean>, value?: boolean)
}
interface IStyledRowTitleProps {
- bold?: boolean;
+ $bold?: boolean;
}
const StyledCheckbox = styled.div({
@@ -325,13 +325,13 @@ const StyledCheckbox = styled.div({
const StyledRow = styled(Cell.Row)({
backgroundColor: colors.blue40,
- ':hover': {
+ '&&:hover': {
backgroundColor: colors.blue80,
},
});
-const StyledRowTitle = styled.label(normalText, (props: IStyledRowTitleProps) => ({
- fontWeight: props.bold ? 600 : 400,
+const StyledRowTitle = styled.label<IStyledRowTitleProps>(normalText, (props) => ({
+ fontWeight: props.$bold ? 600 : 400,
color: colors.white,
marginLeft: '22px',
}));
@@ -350,7 +350,7 @@ function CheckboxRow(props: ICheckboxRowProps) {
<StyledCheckbox role="checkbox" aria-label={props.label} aria-checked={props.checked}>
{props.checked && <ImageView source="icon-tick" width={18} tintColor={colors.green} />}
</StyledCheckbox>
- <StyledRowTitle aria-hidden bold={props.bold}>
+ <StyledRowTitle aria-hidden $bold={props.$bold}>
{props.label}
</StyledRowTitle>
</StyledRow>
diff --git a/gui/src/renderer/components/FormattableTextInput.tsx b/gui/src/renderer/components/FormattableTextInput.tsx
index 133a6692e0..f6c259c4c4 100644
--- a/gui/src/renderer/components/FormattableTextInput.tsx
+++ b/gui/src/renderer/components/FormattableTextInput.tsx
@@ -1,6 +1,6 @@
-import React, { useCallback, useEffect, useRef } from 'react';
+import React, { useCallback, useEffect } from 'react';
-import { useCombinedRefs } from '../lib/utilityHooks';
+import { useCombinedRefs, useStyledRef } from '../lib/utilityHooks';
interface IFormattableTextInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
allowedCharacters: string;
@@ -28,7 +28,7 @@ function FormattableTextInput(
...otherProps
} = props;
- const ref = useRef() as React.RefObject<HTMLInputElement>;
+ const ref = useStyledRef<HTMLInputElement>();
const combinedRef = useCombinedRefs(ref, forwardedRef);
const unformat = useCallback(
diff --git a/gui/src/renderer/components/HeaderBar.tsx b/gui/src/renderer/components/HeaderBar.tsx
index a5c3969f08..98502a6346 100644
--- a/gui/src/renderer/components/HeaderBar.tsx
+++ b/gui/src/renderer/components/HeaderBar.tsx
@@ -29,16 +29,16 @@ const headerBarStyleColorMap = {
};
interface IHeaderBarContainerProps {
- barStyle?: HeaderBarStyle;
- accountInfoVisible: boolean;
- unpinnedWindow: boolean;
+ $barStyle?: HeaderBarStyle;
+ $accountInfoVisible: boolean;
+ $unpinnedWindow: boolean;
}
-const HeaderBarContainer = styled.header({}, (props: IHeaderBarContainerProps) => ({
+const HeaderBarContainer = styled.header<IHeaderBarContainerProps>((props) => ({
padding: '15px 11px 0px 16px',
- minHeight: props.accountInfoVisible ? '80px' : '68px',
- height: props.accountInfoVisible ? '80px' : '68px',
- backgroundColor: headerBarStyleColorMap[props.barStyle ?? HeaderBarStyle.default],
+ minHeight: props.$accountInfoVisible ? '80px' : '68px',
+ height: props.$accountInfoVisible ? '80px' : '68px',
+ backgroundColor: headerBarStyleColorMap[props.$barStyle ?? HeaderBarStyle.default],
transitionProperty: 'height, min-height',
transitionDuration: '250ms',
transitionTimingFunction: 'ease-in-out',
@@ -63,10 +63,10 @@ export default function HeaderBar(props: IHeaderBarProps) {
return (
<HeaderBarContainer
- barStyle={props.barStyle}
+ $barStyle={props.barStyle}
className={props.className}
- accountInfoVisible={props.showAccountInfo ?? false}
- unpinnedWindow={unpinnedWindow}>
+ $accountInfoVisible={props.showAccountInfo ?? false}
+ $unpinnedWindow={unpinnedWindow}>
<HeaderBarContent>{props.children}</HeaderBarContent>
{props.showAccountInfo && <HeaderBarDeviceInfo />}
</HeaderBarContainer>
diff --git a/gui/src/renderer/components/ImageView.tsx b/gui/src/renderer/components/ImageView.tsx
index 3be04159a2..fa3855b21a 100644
--- a/gui/src/renderer/components/ImageView.tsx
+++ b/gui/src/renderer/components/ImageView.tsx
@@ -1,7 +1,10 @@
import React, { useMemo } from 'react';
import styled from 'styled-components';
-export interface IImageViewProps extends IImageMaskProps {
+import { NonTransientProps } from '../lib/styles';
+
+export interface IImageViewProps
+ extends NonTransientProps<IImageMaskProps, 'tintColor' | 'tintHoverColor'> {
source: string;
onClick?: (event: React.MouseEvent) => void;
className?: string;
@@ -11,8 +14,8 @@ interface IImageMaskProps extends React.HTMLAttributes<HTMLElement> {
width?: number;
height?: number;
disabled?: boolean;
- tintColor?: string;
- tintHoverColor?: string;
+ $tintColor?: string;
+ $tintHoverColor?: string;
}
const Wrapper = styled.div({
@@ -21,7 +24,7 @@ const Wrapper = styled.div({
justifyContent: 'center',
});
-const ImageMask = styled.div((props: IImageMaskProps) => {
+const ImageMask = styled.div<IImageMaskProps>((props) => {
const maskWidth = props.width ? `${props.width}px` : 'auto';
const maskHeight = props.height ? `${props.height}px` : 'auto';
return {
@@ -29,9 +32,9 @@ const ImageMask = styled.div((props: IImageMaskProps) => {
maskSize: `${maskWidth} ${maskHeight}`,
maskPosition: 'center',
lineHeight: 0,
- backgroundColor: props.tintColor,
- ':hover': {
- backgroundColor: (!props.disabled && props.tintHoverColor) || props.tintColor,
+ backgroundColor: props.$tintColor,
+ '&&:hover': {
+ backgroundColor: (!props.disabled && props.$tintHoverColor) || props.$tintColor,
},
};
});
@@ -47,9 +50,13 @@ export default function ImageView(props: IImageViewProps) {
const style = useMemo(() => ({ WebkitMaskImage: `url('${url}')` }), [url]);
if (props.tintColor) {
- const { source: _source, ...otherProps } = props;
+ const { source: _source, tintColor, tintHoverColor, ...otherProps } = props;
return (
- <ImageMask style={style} {...otherProps}>
+ <ImageMask
+ style={style}
+ $tintColor={tintColor}
+ $tintHoverColor={tintHoverColor}
+ {...otherProps}>
<HiddenImage src={url} width={props.width} height={props.height} />
</ImageMask>
);
diff --git a/gui/src/renderer/components/Launch.tsx b/gui/src/renderer/components/Launch.tsx
index 5f12fcce8f..3f86e4d19c 100644
--- a/gui/src/renderer/components/Launch.tsx
+++ b/gui/src/renderer/components/Launch.tsx
@@ -21,10 +21,10 @@ export default function Launch() {
);
}
-const StyledFooter = styled(Footer)({}, (props: { show: boolean }) => ({
+const StyledFooter = styled(Footer)<{ $show: boolean }>((props) => ({
backgroundColor: colors.blue,
padding: `0 14px ${measurements.viewMargin}`,
- opacity: props.show ? 1 : 0,
+ opacity: props.$show ? 1 : 0,
transition: 'opacity 250ms ease-in-out',
}));
@@ -55,7 +55,7 @@ function SettingsFooter(props: ISettingsFooterProps) {
}, []);
return (
- <StyledFooter show={props.show}>
+ <StyledFooter $show={props.show}>
<StyledSystemSettingsContainer>
<StyledLaunchFooterPrompt>
{messages.pgettext(
diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx
index 07d4814f1b..32eb5bbe82 100644
--- a/gui/src/renderer/components/Login.tsx
+++ b/gui/src/renderer/components/Login.tsx
@@ -108,7 +108,7 @@ export default class Login extends React.Component<IProps, IState> {
{this.createLoginForm()}
</StyledLoginForm>
- <StyledFooter show={allowInteraction}>{this.createFooter()}</StyledFooter>
+ <StyledFooter $show={allowInteraction}>{this.createFooter()}</StyledFooter>
</Container>
</Layout>
);
@@ -297,9 +297,9 @@ export default class Login extends React.Component<IProps, IState> {
<>
<StyledSubtitle data-testid="subtitle">{this.formSubtitle()}</StyledSubtitle>
<StyledAccountInputGroup
- active={allowInteraction && this.state.isActive}
- editable={allowInteraction}
- error={hasError}
+ $active={allowInteraction && this.state.isActive}
+ $editable={allowInteraction}
+ $error={hasError}
onSubmit={this.onSubmit}>
<StyledAccountInputBackdrop>
<StyledInput
@@ -318,14 +318,14 @@ export default class Login extends React.Component<IProps, IState> {
/>
<StyledInputButton
type="submit"
- visible={allowLogin}
+ $visible={allowLogin}
disabled={!allowLogin}
aria-label={
// TRANSLATORS: This is used by screenreaders to communicate the login button.
messages.pgettext('accessibility', 'Login')
}>
<StyledInputSubmitIcon
- visible={
+ $visible={
this.props.loginState.type !== 'logging in' && !this.props.isPerformingPostUpgrade
}
source="icon-arrow"
diff --git a/gui/src/renderer/components/LoginStyles.tsx b/gui/src/renderer/components/LoginStyles.tsx
index cff3cdfc67..4a597b07b3 100644
--- a/gui/src/renderer/components/LoginStyles.tsx
+++ b/gui/src/renderer/components/LoginStyles.tsx
@@ -26,13 +26,13 @@ export const StyledAccountDropdownRemoveIcon = styled(ImageView)({
marginLeft: '0px',
});
-export const StyledInputSubmitIcon = styled(ImageView)((props: { visible: boolean }) => ({
+export const StyledInputSubmitIcon = styled(ImageView)<{ $visible: boolean }>((props) => ({
flex: 0,
borderWidth: '0px',
width: '48px',
alignItems: 'center',
justifyContent: 'center',
- opacity: props.visible ? 1 : 0,
+ opacity: props.$visible ? 1 : 0,
}));
export const StyledAccountDropdownItem = styled.li({
@@ -40,7 +40,7 @@ export const StyledAccountDropdownItem = styled.li({
flex: 1,
backgroundColor: colors.white60,
cursor: 'default',
- ':hover': {
+ '&&:hover': {
backgroundColor: colors.white40,
},
});
@@ -51,7 +51,7 @@ export const StyledAccountDropdownItemButton = styled(Cell.CellButton)({
flexDirection: 'row',
alignItems: 'stretch',
backgroundColor: 'transparent',
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: 'transparent',
},
});
@@ -75,11 +75,11 @@ export const StyledTopInfo = styled.div({
flex: 1,
});
-export const StyledFooter = styled(Footer)({}, (props: { show: boolean }) => ({
+export const StyledFooter = styled(Footer)<{ $show: boolean }>((props) => ({
position: 'relative',
width: '100%',
bottom: 0,
- transform: `translateY(${props.show ? 0 : 100}%)`,
+ transform: `translateY(${props.$show ? 0 : 100}%)`,
backgroundColor: colors.darkBlue,
transition: 'transform 250ms ease-in-out',
}));
@@ -103,18 +103,18 @@ export const StyledLoginForm = styled.div({
});
interface IStyledAccountInputGroupProps {
- editable: boolean;
- active: boolean;
- error: boolean;
+ $editable: boolean;
+ $active: boolean;
+ $error: boolean;
}
-export const StyledAccountInputGroup = styled.form((props: IStyledAccountInputGroupProps) => ({
+export const StyledAccountInputGroup = styled.form<IStyledAccountInputGroupProps>((props) => ({
borderWidth: '2px',
borderStyle: 'solid',
borderRadius: '8px',
overflow: 'hidden',
- borderColor: props.error ? colors.red40 : props.active ? colors.darkBlue : 'transparent',
- opacity: props.editable ? 1 : 0.6,
+ borderColor: props.$error ? colors.red40 : props.$active ? colors.darkBlue : 'transparent',
+ opacity: props.$editable ? 1 : 0.6,
}));
export const StyledAccountInputBackdrop = styled.div({
@@ -123,14 +123,14 @@ export const StyledAccountInputBackdrop = styled.div({
borderColor: colors.darkBlue,
});
-export const StyledInputButton = styled.button((props: { visible: boolean }) => ({
+export const StyledInputButton = styled.button<{ $visible: boolean }>((props) => ({
display: 'flex',
flex: 0,
borderWidth: 0,
width: '48px',
alignItems: 'center',
justifyContent: 'center',
- opacity: props.visible ? 1 : 0,
+ opacity: props.$visible ? 1 : 0,
transition: 'opacity 250ms ease-in-out',
backgroundColor: colors.green,
}));
@@ -165,7 +165,7 @@ export const StyledInput = styled(FormattableTextInput)(largeText, {
color: colors.blue,
backgroundColor: 'transparent',
flex: 1,
- '::placeholder': {
+ '&&::placeholder': {
color: colors.blue40,
},
});
diff --git a/gui/src/renderer/components/MacOsScrollbarDetection.tsx b/gui/src/renderer/components/MacOsScrollbarDetection.tsx
index de636827bd..aebb144f9b 100644
--- a/gui/src/renderer/components/MacOsScrollbarDetection.tsx
+++ b/gui/src/renderer/components/MacOsScrollbarDetection.tsx
@@ -1,8 +1,9 @@
-import React, { useEffect, useRef } from 'react';
+import { useEffect } from 'react';
import styled from 'styled-components';
import { MacOsScrollbarVisibility } from '../../shared/ipc-schema';
import useActions from '../lib/actionsHook';
+import { useStyledRef } from '../lib/utilityHooks';
import { useSelector } from '../redux/store';
import userInterface from '../redux/userinterface/actions';
@@ -21,7 +22,7 @@ const StyledContainer = styled.div({
export default function MacOsScrollbarDetection() {
const visibility = useSelector((state) => state.userInterface.macOsScrollbarVisibility);
const { setMacOsScrollbarVisibility } = useActions(userInterface);
- const ref = useRef() as React.RefObject<HTMLDivElement>;
+ const ref = useStyledRef<HTMLDivElement>();
useEffect(() => {
if (visibility === MacOsScrollbarVisibility.automatic) {
diff --git a/gui/src/renderer/components/Marquee.tsx b/gui/src/renderer/components/Marquee.tsx
index 5175fdc4a0..c654e473d2 100644
--- a/gui/src/renderer/components/Marquee.tsx
+++ b/gui/src/renderer/components/Marquee.tsx
@@ -7,14 +7,16 @@ const Container = styled.div({
overflow: 'hidden',
});
-const Text = styled.span({}, (props: { overflow: number; alignRight: boolean }) => ({
+const Text = styled.span<{ $overflow: number; $alignRight: boolean }>((props) => ({
display: 'inline-block',
// Prevents Container from adding 2px below the text.
verticalAlign: 'middle',
whiteSpace: 'nowrap',
- willChange: props.overflow > 0 ? 'transform' : 'auto',
- transform: props.alignRight ? `translate3d(${-props.overflow}px, 0, 0)` : 'translate3d(0, 0, 0)',
- transition: `transform linear ${props.overflow * 80}ms`,
+ willChange: props.$overflow > 0 ? 'transform' : 'auto',
+ transform: props.$alignRight
+ ? `translate3d(${-props.$overflow}px, 0, 0)`
+ : 'translate3d(0, 0, 0)',
+ transition: `transform linear ${props.$overflow * 80}ms`,
}));
interface IMarqueeProps {
@@ -67,8 +69,8 @@ export default class Marquee extends React.Component<IMarqueeProps, IMarqueeStat
<Text
key={this.state.uniqueKey}
ref={this.textRef}
- overflow={this.calculateOverflow()}
- alignRight={this.state.alignRight}
+ $overflow={this.calculateOverflow()}
+ $alignRight={this.state.alignRight}
onTransitionEnd={this.scheduleToggleAlignRight}
{...otherProps}>
{children}
diff --git a/gui/src/renderer/components/Modal.tsx b/gui/src/renderer/components/Modal.tsx
index d9be9e767d..e87e2113f2 100644
--- a/gui/src/renderer/components/Modal.tsx
+++ b/gui/src/renderer/components/Modal.tsx
@@ -25,9 +25,9 @@ const ModalContent = styled.div({
overflow: 'hidden',
});
-const ModalBackground = styled.div({}, (props: { visible: boolean }) => ({
- backgroundColor: props.visible ? 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0)',
- backdropFilter: props.visible ? 'blur(1.5px)' : '',
+const ModalBackground = styled.div<{ $visible: boolean }>((props) => ({
+ backgroundColor: props.$visible ? 'rgba(0,0,0,0.5)' : 'rgba(0,0,0,0)',
+ backdropFilter: props.$visible ? 'blur(1.5px)' : '',
position: 'absolute',
display: 'flex',
flexDirection: 'column',
@@ -37,7 +37,7 @@ const ModalBackground = styled.div({}, (props: { visible: boolean }) => ({
right: 0,
bottom: 0,
transition: 'background-color 150ms ease-out',
- pointerEvents: props.visible ? 'auto' : 'none',
+ pointerEvents: props.$visible ? 'auto' : 'none',
zIndex: 2,
}));
@@ -111,11 +111,11 @@ const ModalAlertContainer = styled.div({
padding: '14px',
});
-const StyledModalAlert = styled.div({}, (props: { visible: boolean; closing: boolean }) => {
+const StyledModalAlert = styled.div<{ $visible: boolean; $closing: boolean }>((props) => {
let transform = '';
- if (props.visible && props.closing) {
+ if (props.$visible && props.$closing) {
transform = 'scale(80%)';
- } else if (!props.visible) {
+ } else if (!props.$visible) {
transform = 'translateY(10px) scale(98%)';
}
@@ -126,7 +126,7 @@ const StyledModalAlert = styled.div({}, (props: { visible: boolean; closing: boo
borderRadius: '11px',
padding: '16px 0 16px 16px',
maxHeight: '80vh',
- opacity: props.visible && !props.closing ? 1 : 0,
+ opacity: props.$visible && !props.$closing ? 1 : 0,
transform,
boxShadow: ' 0px 15px 35px 5px rgba(0,0,0,0.5)',
transition: 'all 150ms ease-out',
@@ -254,15 +254,15 @@ class ModalAlertImpl extends React.Component<IModalAlertImplProps, IModalAlertSt
private renderModal() {
return (
<BackAction action={this.close}>
- <ModalBackground visible={this.state.visible && !this.props.closing}>
+ <ModalBackground $visible={this.state.visible && !this.props.closing}>
<ModalAlertContainer>
<StyledModalAlert
ref={this.modalRef}
tabIndex={-1}
role="dialog"
aria-modal
- visible={this.state.visible}
- closing={this.props.closing}
+ $visible={this.state.visible}
+ $closing={this.props.closing}
onTransitionEnd={this.onTransitionEnd}>
<StyledCustomScrollbars>
{this.props.type && (
diff --git a/gui/src/renderer/components/NavigationBar.tsx b/gui/src/renderer/components/NavigationBar.tsx
index 56c3d2b8a3..d375fc34d6 100644
--- a/gui/src/renderer/components/NavigationBar.tsx
+++ b/gui/src/renderer/components/NavigationBar.tsx
@@ -180,7 +180,7 @@ interface ITitleBarItemProps {
export const TitleBarItem = React.memo(function TitleBarItemT(props: ITitleBarItemProps) {
const { visible } = useContext(TitleBarItemContext);
- return <StyledTitleBarItemLabel visible={visible}>{props.children}</StyledTitleBarItemLabel>;
+ return <StyledTitleBarItemLabel $visible={visible}>{props.children}</StyledTitleBarItemLabel>;
});
export function BackBarItem() {
diff --git a/gui/src/renderer/components/NavigationBarStyles.tsx b/gui/src/renderer/components/NavigationBarStyles.tsx
index d773c868d8..eb4472c900 100644
--- a/gui/src/renderer/components/NavigationBarStyles.tsx
+++ b/gui/src/renderer/components/NavigationBarStyles.tsx
@@ -25,7 +25,7 @@ export const StyledNavigationBar = styled.nav({
padding: '12px',
});
-export const StyledTitleBarItemLabel = styled.h1(normalText, (props: { visible?: boolean }) => ({
+export const StyledTitleBarItemLabel = styled.h1<{ $visible?: boolean }>(normalText, (props) => ({
fontWeight: 400,
lineHeight: '22px',
color: colors.white,
@@ -33,7 +33,7 @@ export const StyledTitleBarItemLabel = styled.h1(normalText, (props: { visible?:
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
- opacity: props.visible ? 1 : 0,
+ opacity: props.$visible ? 1 : 0,
transition: 'opacity 250ms ease-in-out',
}));
@@ -51,7 +51,7 @@ export const StyledBackBarItemButton = styled.button({
export const StyledBackBarItemIcon = styled(ImageView)({
marginRight: '8px',
- [StyledBackBarItemButton + ':hover &']: {
+ [StyledBackBarItemButton + ':hover &&']: {
backgroundColor: colors.white60,
},
});
diff --git a/gui/src/renderer/components/NotificationArea.tsx b/gui/src/renderer/components/NotificationArea.tsx
index 79fb3ef17c..9bce47eea6 100644
--- a/gui/src/renderer/components/NotificationArea.tsx
+++ b/gui/src/renderer/components/NotificationArea.tsx
@@ -97,7 +97,7 @@ export default function NotificationArea(props: IProps) {
if (notification) {
return (
<NotificationBanner className={props.className}>
- <NotificationIndicator type={notification.indicator} />
+ <NotificationIndicator $type={notification.indicator} />
<NotificationContent role="status" aria-live="polite">
<NotificationTitle>{notification.title}</NotificationTitle>
<NotificationSubtitle>{formatHtml(notification.subtitle ?? '')}</NotificationSubtitle>
diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx
index 18e18ce4f5..3b66abb204 100644
--- a/gui/src/renderer/components/NotificationBanner.tsx
+++ b/gui/src/renderer/components/NotificationBanner.tsx
@@ -4,6 +4,7 @@ import styled from 'styled-components';
import { colors } from '../../config.json';
import { messages } from '../../shared/gettext';
import { InAppNotificationIndicatorType } from '../../shared/notifications/notification';
+import { useStyledRef } from '../lib/utilityHooks';
import * as AppButton from './AppButton';
import { tinyText } from './common-styles';
import ImageView from './ImageView';
@@ -104,7 +105,7 @@ export const NotificationActions = styled.div({
});
interface INotificationIndicatorProps {
- type?: InAppNotificationIndicatorType;
+ $type?: InAppNotificationIndicatorType;
}
const notificationIndicatorTypeColorMap = {
@@ -113,29 +114,29 @@ const notificationIndicatorTypeColorMap = {
error: colors.red,
};
-export const NotificationIndicator = styled.div((props: INotificationIndicatorProps) => ({
+export const NotificationIndicator = styled.div<INotificationIndicatorProps>((props) => ({
width: '10px',
height: '10px',
borderRadius: '5px',
marginTop: '4px',
marginRight: '8px',
- backgroundColor: props.type ? notificationIndicatorTypeColorMap[props.type] : 'transparent',
+ backgroundColor: props.$type ? notificationIndicatorTypeColorMap[props.$type] : 'transparent',
}));
interface ICollapsibleProps {
- alignBottom: boolean;
- height?: number;
+ $alignBottom: boolean;
+ $height?: number;
}
-const Collapsible = styled.div({}, (props: ICollapsibleProps) => {
+const Collapsible = styled.div<ICollapsibleProps>((props) => {
return {
display: 'flex',
flexDirection: 'column',
- justifyContent: props.alignBottom ? 'flex-end' : 'flex-start',
+ justifyContent: props.$alignBottom ? 'flex-end' : 'flex-start',
backgroundColor: 'rgba(25, 38, 56, 0.95)',
overflow: 'hidden',
// Using auto as the initial value prevents transition if a notification is visible on mount.
- height: props.height === undefined ? 'auto' : `${props.height}px`,
+ height: props.$height === undefined ? 'auto' : `${props.$height}px`,
transition: 'height 250ms ease-in-out',
};
});
@@ -156,7 +157,7 @@ export function NotificationBanner(props: INotificationBannerProps) {
const [contentHeight, setContentHeight] = useState<number>();
const [alignBottom, setAlignBottom] = useState(false);
- const contentRef = useRef() as React.RefObject<HTMLDivElement>;
+ const contentRef = useStyledRef<HTMLDivElement>();
// Save last non-undefined children to be able to show them during the hide-transition.
const prevChildren = useRef<React.ReactNode>();
@@ -174,7 +175,7 @@ export function NotificationBanner(props: INotificationBannerProps) {
});
return (
- <Collapsible height={contentHeight} className={props.className} alignBottom={alignBottom}>
+ <Collapsible $height={contentHeight} className={props.className} $alignBottom={alignBottom}>
<Content ref={contentRef}>{props.children ?? prevChildren.current}</Content>
</Collapsible>
);
diff --git a/gui/src/renderer/components/RedeemVoucherStyles.tsx b/gui/src/renderer/components/RedeemVoucherStyles.tsx
index 2ef0cc2634..37f51ee5e4 100644
--- a/gui/src/renderer/components/RedeemVoucherStyles.tsx
+++ b/gui/src/renderer/components/RedeemVoucherStyles.tsx
@@ -20,7 +20,7 @@ export const StyledInput = styled(FormattableTextInput)(normalText, {
backgroundColor: colors.white,
border: 'none',
borderRadius: '4px',
- '::placeholder': {
+ '&&::placeholder': {
color: colors.blue40,
},
});
diff --git a/gui/src/renderer/components/RelayStatusIndicator.tsx b/gui/src/renderer/components/RelayStatusIndicator.tsx
index 7d90e1491d..549fec4e70 100644
--- a/gui/src/renderer/components/RelayStatusIndicator.tsx
+++ b/gui/src/renderer/components/RelayStatusIndicator.tsx
@@ -3,12 +3,12 @@ import styled from 'styled-components';
import { colors } from '../../config.json';
import * as Cell from './cell';
-const StyledRelayStatus = styled.div((props: { active: boolean }) => ({
+const StyledRelayStatus = styled.div<{ $active: boolean }>((props) => ({
width: '16px',
height: '16px',
borderRadius: '8px',
margin: '0 12px 0 4px',
- backgroundColor: props.active ? colors.green90 : colors.red95,
+ backgroundColor: props.$active ? colors.green90 : colors.red95,
}));
const TickIcon = styled(Cell.Icon)({
@@ -25,6 +25,6 @@ export default function RelayStatusIndicator(props: IProps) {
return props.selected ? (
<TickIcon tintColor={colors.white} source="icon-tick" width={18} />
) : (
- <StyledRelayStatus active={props.active} />
+ <StyledRelayStatus $active={props.active} />
);
}
diff --git a/gui/src/renderer/components/SearchBar.tsx b/gui/src/renderer/components/SearchBar.tsx
index 7983441ed8..e21439fbbf 100644
--- a/gui/src/renderer/components/SearchBar.tsx
+++ b/gui/src/renderer/components/SearchBar.tsx
@@ -1,8 +1,9 @@
-import { useCallback, useEffect, useRef } from 'react';
+import { useCallback, useEffect } from 'react';
import styled from 'styled-components';
import { colors } from '../../config.json';
import { messages } from '../../shared/gettext';
+import { useStyledRef } from '../lib/utilityHooks';
import { normalText } from './common-styles';
import ImageView from './ImageView';
@@ -21,15 +22,15 @@ export const StyledSearchInput = styled.input.attrs({ type: 'text' })({
lineHeight: '24px',
color: colors.white60,
backgroundColor: colors.white10,
- '::placeholder': {
+ '&&::placeholder': {
color: colors.white60,
},
- ':focus': {
+ '&&:focus': {
color: colors.blue,
backgroundColor: colors.white,
- '::placeholder': {
- color: colors.blue40,
- },
+ },
+ '&&:focus::placeholder': {
+ color: colors.blue40,
},
});
@@ -48,20 +49,20 @@ export const StyledSearchIcon = styled(ImageView)({
top: '50%',
transform: 'translateY(-50%)',
left: '9px',
- [`${StyledSearchInput}:focus ~ &`]: {
+ [`${StyledSearchInput}:focus ~ &&`]: {
backgroundColor: colors.blue,
},
});
export const StyledClearIcon = styled(ImageView)({
- ':hover': {
+ '&&:hover': {
backgroundColor: colors.white60,
},
- [`${StyledSearchInput}:focus ~ ${StyledClearButton} &`]: {
+ [`${StyledSearchInput}:focus ~ ${StyledClearButton} &&`]: {
backgroundColor: colors.blue40,
- ':hover': {
- backgroundColor: colors.blue,
- },
+ },
+ [`${StyledSearchInput}:focus ~ ${StyledClearButton} &&:hover`]: {
+ backgroundColor: colors.blue,
},
});
@@ -73,7 +74,7 @@ interface ISearchBarProps {
}
export default function SearchBar(props: ISearchBarProps) {
- const inputRef = useRef() as React.RefObject<HTMLInputElement>;
+ const inputRef = useStyledRef<HTMLInputElement>();
const onInput = useCallback(
(event: React.FormEvent) => {
diff --git a/gui/src/renderer/components/SecuredLabel.tsx b/gui/src/renderer/components/SecuredLabel.tsx
index 736297b480..534a01a58c 100644
--- a/gui/src/renderer/components/SecuredLabel.tsx
+++ b/gui/src/renderer/components/SecuredLabel.tsx
@@ -25,10 +25,10 @@ const securedDisplayStyleColorMap = {
[SecuredDisplayStyle.failedToSecure]: colors.red,
};
-const StyledSecuredLabel = styled.span((props: { displayStyle: SecuredDisplayStyle }) => ({
+const StyledSecuredLabel = styled.span<{ $displayStyle: SecuredDisplayStyle }>((props) => ({
display: 'inline-block',
minHeight: '22px',
- color: securedDisplayStyleColorMap[props.displayStyle],
+ color: securedDisplayStyleColorMap[props.$displayStyle],
}));
interface ISecuredLabelProps {
@@ -37,8 +37,13 @@ interface ISecuredLabelProps {
}
export default function SecuredLabel(props: ISecuredLabelProps) {
+ const { displayStyle, ...otherProps } = props;
return (
- <StyledSecuredLabel {...props} role="status" aria-live="polite">
+ <StyledSecuredLabel
+ $displayStyle={displayStyle}
+ {...otherProps}
+ role="status"
+ aria-live="polite">
{getLabelText(props.displayStyle)}
</StyledSecuredLabel>
);
diff --git a/gui/src/renderer/components/SelectLanguage.tsx b/gui/src/renderer/components/SelectLanguage.tsx
index b97243a456..eb0ad038da 100644
--- a/gui/src/renderer/components/SelectLanguage.tsx
+++ b/gui/src/renderer/components/SelectLanguage.tsx
@@ -21,7 +21,7 @@ import SettingsHeader, { HeaderTitle } from './SettingsHeader';
const StyledSelector = styled(Selector)({
marginBottom: 0,
-}) as typeof Selector;
+});
export default function SelectLanguage() {
const history = useHistory();
diff --git a/gui/src/renderer/components/SettingsHeader.tsx b/gui/src/renderer/components/SettingsHeader.tsx
index 8724ea93d9..47e1f47f7b 100644
--- a/gui/src/renderer/components/SettingsHeader.tsx
+++ b/gui/src/renderer/components/SettingsHeader.tsx
@@ -13,7 +13,7 @@ export const Container = styled.div({
});
export const ContentWrapper = styled.div({
- ':not(:first-child)': {
+ '&&:not(:first-child)': {
paddingTop: '8px',
},
});
diff --git a/gui/src/renderer/components/SplitTunnelingSettings.tsx b/gui/src/renderer/components/SplitTunnelingSettings.tsx
index c8242cdd88..cb4de70deb 100644
--- a/gui/src/renderer/components/SplitTunnelingSettings.tsx
+++ b/gui/src/renderer/components/SplitTunnelingSettings.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { sprintf } from 'sprintf-js';
@@ -12,7 +12,7 @@ import { messages } from '../../shared/gettext';
import { useAppContext } from '../context';
import { useHistory } from '../lib/history';
import { formatHtml } from '../lib/html-formatter';
-import { useAsyncEffect } from '../lib/utilityHooks';
+import { useAsyncEffect, useStyledRef } from '../lib/utilityHooks';
import { IReduxState } from '../redux/store';
import Accordion from './Accordion';
import * as AppButton from './AppButton';
@@ -49,13 +49,13 @@ import Switch from './Switch';
export default function SplitTunneling() {
const { pop } = useHistory();
const [browsing, setBrowsing] = useState(false);
- const scrollbarsRef = useRef() as React.RefObject<CustomScrollbarsRef>;
+ const scrollbarsRef = useStyledRef<CustomScrollbarsRef>();
const scrollToTop = useCallback(() => scrollbarsRef.current?.scrollToTop(true), [scrollbarsRef]);
return (
<>
- <StyledPageCover show={browsing} />
+ <StyledPageCover $show={browsing} />
<BackAction action={pop}>
<Layout>
<SettingsContainer>
@@ -173,7 +173,21 @@ function LinuxSplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsProps
</SettingsHeader>
<StyledSearchBar searchTerm={searchTerm} onSearch={setSearchTerm} />
- <ApplicationList applications={filteredApplications} rowRenderer={rowRenderer} />
+ {filteredApplications !== undefined && filteredApplications.length > 0 && (
+ <ApplicationList applications={filteredApplications} rowRenderer={rowRenderer} />
+ )}
+
+ {searchTerm !== '' &&
+ (filteredApplications === undefined || filteredApplications.length === 0) && (
+ <StyledNoResult>
+ <StyledNoResultText>
+ {formatHtml(
+ sprintf(messages.gettext('No result for <b>%(searchTerm)s</b>.'), { searchTerm }),
+ )}
+ </StyledNoResultText>
+ <StyledNoResultText>{messages.gettext('Try a different search.')}</StyledNoResultText>
+ </StyledNoResult>
+ )}
<StyledBrowseButton onClick={launchWithFilePicker}>
{messages.pgettext('split-tunneling-view', 'Find another app')}
@@ -258,18 +272,18 @@ function LinuxApplicationRow(props: ILinuxApplicationRowProps) {
<>
<StyledCellButton
onClick={props.application.warning ? showWarningDialog : launch}
- lookDisabled={disabled}>
+ $lookDisabled={disabled}>
{props.application.icon ? (
<StyledIcon
source={props.application.icon}
width={35}
height={35}
- lookDisabled={disabled}
+ $lookDisabled={disabled}
/>
) : (
<StyledIconPlaceholder />
)}
- <StyledCellLabel lookDisabled={disabled}>{props.application.name}</StyledCellLabel>
+ <StyledCellLabel $lookDisabled={disabled}>{props.application.name}</StyledCellLabel>
{props.application.warning && (
<StyledCellWarningIcon source="icon-alert" tintColor={warningColor} width={18} />
)}
diff --git a/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx b/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx
index 028fac30a3..1aea5108a1 100644
--- a/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx
+++ b/gui/src/renderer/components/SplitTunnelingSettingsStyles.tsx
@@ -9,7 +9,7 @@ import { NavigationScrollbars } from './NavigationBar';
import SearchBar from './SearchBar';
import { HeaderTitle } from './SettingsHeader';
-export const StyledPageCover = styled.div({}, (props: { show: boolean }) => ({
+export const StyledPageCover = styled.div<{ $show: boolean }>((props) => ({
position: 'absolute',
zIndex: 2,
top: 0,
@@ -18,7 +18,7 @@ export const StyledPageCover = styled.div({}, (props: { show: boolean }) => ({
bottom: 0,
backgroundColor: colors.black,
opacity: 0.5,
- display: props.show ? 'block' : 'none',
+ display: props.$show ? 'block' : 'none',
}));
export const StyledNavigationScrollbars = styled(NavigationScrollbars)({
@@ -31,17 +31,21 @@ export const StyledContent = styled.div({
flex: 1,
});
-export const StyledCellButton = styled(Cell.CellButton)((props: { lookDisabled?: boolean }) => ({
- ':not(:disabled):hover': {
- backgroundColor: props.lookDisabled ? colors.blue : undefined,
+export const StyledCellButton = styled(Cell.CellButton)<{ $lookDisabled?: boolean }>((props) => ({
+ '&&:not(:disabled):hover': {
+ backgroundColor: props.$lookDisabled ? colors.blue : undefined,
},
}));
-const disabledApplication = (props: { lookDisabled?: boolean }) => ({
- opacity: props.lookDisabled ? 0.6 : undefined,
+interface DisabledApplicationProps {
+ $lookDisabled?: boolean;
+}
+
+const disabledApplication = (props: DisabledApplicationProps) => ({
+ opacity: props.$lookDisabled ? 0.6 : undefined,
});
-export const StyledIcon = styled(Cell.UntintedIcon)(disabledApplication, {
+export const StyledIcon = styled(Cell.UntintedIcon)<DisabledApplicationProps>(disabledApplication, {
marginRight: '12px',
});
@@ -54,11 +58,15 @@ export const StyledCellWarningIcon = styled(Cell.Icon)({
marginRight: '3px',
});
-export const StyledCellLabel = styled(Cell.Label)(disabledApplication, normalText, {
- fontWeight: 400,
- wordWrap: 'break-word',
- overflow: 'hidden',
-});
+export const StyledCellLabel = styled(Cell.Label)<DisabledApplicationProps>(
+ disabledApplication,
+ normalText,
+ {
+ fontWeight: 400,
+ wordWrap: 'break-word',
+ overflow: 'hidden',
+ },
+);
export const StyledIconPlaceholder = styled.div({
width: '35px',
@@ -93,6 +101,7 @@ export const StyledNoResult = styled(Cell.CellFooter)({
flexDirection: 'column',
paddingTop: 0,
marginTop: 0,
+ marginBottom: '69px',
});
export const StyledNoResultText = styled(Cell.CellFooterText)({
diff --git a/gui/src/renderer/components/Switch.tsx b/gui/src/renderer/components/Switch.tsx
index cb9e86b219..e5aaec4bb0 100644
--- a/gui/src/renderer/components/Switch.tsx
+++ b/gui/src/renderer/components/Switch.tsx
@@ -14,7 +14,7 @@ interface IProps {
innerRef?: React.Ref<HTMLDivElement>;
}
-const SwitchContainer = styled.div({}, (props: { disabled: boolean }) => ({
+const SwitchContainer = styled.div<{ disabled: boolean }>((props) => ({
position: 'relative',
width: '48px',
height: '30px',
@@ -25,10 +25,10 @@ const SwitchContainer = styled.div({}, (props: { disabled: boolean }) => ({
padding: '2px',
}));
-const Knob = styled.div({}, (props: { isOn: boolean; disabled: boolean }) => {
- let backgroundColor = props.isOn ? colors.green : colors.red;
+const Knob = styled.div<{ $isOn: boolean; disabled: boolean }>((props) => {
+ let backgroundColor = props.$isOn ? colors.green : colors.red;
if (props.disabled) {
- backgroundColor = props.isOn ? colors.green40 : colors.red40;
+ backgroundColor = props.$isOn ? colors.green40 : colors.red40;
}
return {
@@ -40,7 +40,7 @@ const Knob = styled.div({}, (props: { isOn: boolean; disabled: boolean }) => {
backgroundColor,
// When enabled the button should be placed all the way to the right (100%) minus padding (2px)
// minus it's own width (22px).
- left: props.isOn ? 'calc(100% - 2px - 22px)' : '2px',
+ left: props.$isOn ? 'calc(100% - 2px - 22px)' : '2px',
};
});
@@ -59,7 +59,7 @@ export default class Switch extends React.PureComponent<IProps> {
aria-disabled={this.props.disabled ?? false}
tabIndex={-1}
className={this.props.className}>
- <Knob disabled={this.props.disabled ?? false} isOn={this.props.isOn} />
+ <Knob disabled={this.props.disabled ?? false} $isOn={this.props.isOn} />
</SwitchContainer>
);
}
diff --git a/gui/src/renderer/components/TransitionContainer.tsx b/gui/src/renderer/components/TransitionContainer.tsx
index 56315d5dcb..b9a60185ed 100644
--- a/gui/src/renderer/components/TransitionContainer.tsx
+++ b/gui/src/renderer/components/TransitionContainer.tsx
@@ -41,29 +41,36 @@ interface IState {
export const StyledTransitionContainer = styled.div({ flex: 1 });
-export const StyledTransitionContent = styled.div.attrs({ 'data-testid': 'transition-content' })(
- {},
- (props: { transition?: IItemStyle; disableUserInteraction?: boolean }) => {
- const x = `${props.transition?.x ?? 0}%`;
- const y = `${props.transition?.y ?? 0}%`;
- const duration = props.transition?.duration ?? 450;
+interface StyledTransitionContentProps {
+ $transition?: IItemStyle;
+ $disableUserInteraction?: boolean;
+}
- return {
- display: 'flex',
- flexDirection: 'column',
- position: 'absolute',
- left: 0,
- right: 0,
- top: 0,
- bottom: 0,
- zIndex: props.transition?.inFront ? 1 : 0,
- willChange: 'transform',
- transform: `translate3d(${x}, ${y}, 0)`,
- transition: `transform ${duration}ms ease-in-out`,
- pointerEvents: props.disableUserInteraction ? 'none' : undefined,
- };
- },
-);
+export const StyledTransitionContent = styled.div.attrs<
+ StyledTransitionContentProps,
+ { 'data-testid': string }
+>({
+ 'data-testid': 'transition-content',
+})((props) => {
+ const x = `${props.$transition?.x ?? 0}%`;
+ const y = `${props.$transition?.y ?? 0}%`;
+ const duration = props.$transition?.duration ?? 450;
+
+ return {
+ display: 'flex',
+ flexDirection: 'column',
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ zIndex: props.$transition?.inFront ? 1 : 0,
+ willChange: 'transform',
+ transform: `translate3d(${x}, ${y}, 0)`,
+ transition: `transform ${duration}ms ease-in-out`,
+ pointerEvents: props.$disableUserInteraction ? 'none' : undefined,
+ };
+});
export const StyledTransitionView = styled.div({
display: 'flex',
@@ -132,9 +139,9 @@ export default class TransitionContainer extends React.Component<IProps, IState>
<WillExit key={this.state.currentItem.view.props.routePath} value={willExit}>
<StyledTransitionContent
ref={this.setCurrentContentRef}
- transition={this.state.currentItemStyle}
+ $transition={this.state.currentItemStyle}
onTransitionEnd={this.onTransitionEnd}
- disableUserInteraction={willExit}>
+ $disableUserInteraction={willExit}>
{this.state.currentItem.view}
</StyledTransitionContent>
</WillExit>
@@ -144,7 +151,7 @@ export default class TransitionContainer extends React.Component<IProps, IState>
<WillExit key={this.state.nextItem.view.props.routePath} value={false}>
<StyledTransitionContent
ref={this.setNextContentRef}
- transition={this.state.nextItemStyle}
+ $transition={this.state.nextItemStyle}
onTransitionEnd={this.onTransitionEnd}>
{this.state.nextItem.view}
</StyledTransitionContent>
diff --git a/gui/src/renderer/components/cell/CellButton.tsx b/gui/src/renderer/components/cell/CellButton.tsx
index 0111574f70..b0079226f3 100644
--- a/gui/src/renderer/components/cell/CellButton.tsx
+++ b/gui/src/renderer/components/cell/CellButton.tsx
@@ -8,17 +8,17 @@ import { Row } from './Row';
import { CellSectionContext } from './Section';
interface IStyledCellButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
- selected?: boolean;
- containedInSection: boolean;
+ $selected?: boolean;
+ $containedInSection: boolean;
}
-const StyledCellButton = styled(Row)({}, (props: IStyledCellButtonProps) => {
- const backgroundColor = props.selected
+const StyledCellButton = styled(Row)<IStyledCellButtonProps>((props) => {
+ const backgroundColor = props.$selected
? colors.green
- : props.containedInSection
+ : props.$containedInSection
? colors.blue40
: colors.blue;
- const backgroundColorHover = props.selected ? colors.green : colors.blue80;
+ const backgroundColorHover = props.$selected ? colors.green : colors.blue80;
return {
paddingRight: '16px',
@@ -27,7 +27,7 @@ const StyledCellButton = styled(Row)({}, (props: IStyledCellButtonProps) => {
cursor: 'default',
border: 'none',
backgroundColor,
- ':not(:disabled):hover': {
+ '&&:not(:disabled):hover': {
backgroundColor: props.onClick ? backgroundColorHover : backgroundColor,
},
};
@@ -39,14 +39,16 @@ interface ICellButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
export const CellButton = styled(
React.forwardRef(function Button(props: ICellButtonProps, ref: React.Ref<HTMLButtonElement>) {
+ const { selected, ...otherProps } = props;
const containedInSection = useContext(CellSectionContext);
return (
<CellDisabledContext.Provider value={props.disabled ?? false}>
<StyledCellButton
as="button"
ref={ref}
- containedInSection={containedInSection}
- {...props}
+ $selected={selected}
+ $containedInSection={containedInSection}
+ {...otherProps}
/>
</CellDisabledContext.Provider>
);
diff --git a/gui/src/renderer/components/cell/Group.tsx b/gui/src/renderer/components/cell/Group.tsx
index a3198cabb0..86d95f0a33 100644
--- a/gui/src/renderer/components/cell/Group.tsx
+++ b/gui/src/renderer/components/cell/Group.tsx
@@ -3,12 +3,12 @@ import styled from 'styled-components';
import { measurements } from '../common-styles';
interface IStyledGroupProps {
- noMarginBottom?: boolean;
+ $noMarginBottom?: boolean;
}
-export const Group = styled.div({}, (props: IStyledGroupProps) => ({
+export const Group = styled.div<IStyledGroupProps>((props) => ({
display: 'flex',
flexDirection: 'column',
flex: 1,
- marginBottom: props.noMarginBottom ? '0px' : measurements.rowVerticalMargin,
+ marginBottom: props.$noMarginBottom ? '0px' : measurements.rowVerticalMargin,
}));
diff --git a/gui/src/renderer/components/cell/Input.tsx b/gui/src/renderer/components/cell/Input.tsx
index bff8364d21..97fe01a185 100644
--- a/gui/src/renderer/components/cell/Input.tsx
+++ b/gui/src/renderer/components/cell/Input.tsx
@@ -1,8 +1,8 @@
-import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
+import React, { useCallback, useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import { colors } from '../../../config.json';
-import { useBoolean, useCombinedRefs } from '../../lib/utilityHooks';
+import { useBoolean, useCombinedRefs, useStyledRef } from '../../lib/utilityHooks';
import { normalText } from '../common-styles';
import ImageView from '../ImageView';
import { BackAction } from '../KeyboardNavigation';
@@ -24,15 +24,15 @@ const inputTextStyles: React.CSSProperties = {
padding: '0px',
};
-const StyledInput = styled.input({}, (props: { focused: boolean; valid?: boolean }) => ({
+const StyledInput = styled.input<{ $focused: boolean; $valid?: boolean }>((props) => ({
...inputTextStyles,
backgroundColor: 'transparent',
border: 'none',
width: '100%',
height: '100%',
- color: props.valid === false ? colors.red : props.focused ? colors.blue : colors.white,
- '::placeholder': {
- color: props.focused ? colors.blue60 : colors.white60,
+ color: props.$valid === false ? colors.red : props.$focused ? colors.blue : colors.white,
+ '&&::placeholder': {
+ color: props.$focused ? colors.blue60 : colors.white60,
},
}));
@@ -68,7 +68,7 @@ function InputWithRef(props: IInputProps, forwardedRef: React.Ref<HTMLInputEleme
const [internalValue, setInternalValue] = useState(props.value ?? props.initialValue ?? '');
const value = props.value ?? internalValue;
- const inputRef = useRef() as React.RefObject<HTMLInputElement>;
+ const inputRef = useStyledRef<HTMLInputElement>();
const combinedRef = useCombinedRefs(inputRef, forwardedRef);
const onSubmit = useCallback(
@@ -150,8 +150,8 @@ function InputWithRef(props: IInputProps, forwardedRef: React.Ref<HTMLInputEleme
{...otherProps}
ref={combinedRef}
type="text"
- valid={valid}
- focused={isFocused}
+ $valid={valid}
+ $focused={isFocused}
aria-invalid={!valid}
onChange={onChange}
onFocus={onFocus}
@@ -167,10 +167,10 @@ function InputWithRef(props: IInputProps, forwardedRef: React.Ref<HTMLInputEleme
export const Input = React.memo(React.forwardRef(InputWithRef));
-const InputFrame = styled.div((props: { focused: boolean }) => ({
+const InputFrame = styled.div<{ $focused: boolean }>((props) => ({
display: 'flex',
flexGrow: 0,
- backgroundColor: props.focused ? colors.white : 'rgba(255,255,255,0.1)',
+ backgroundColor: props.$focused ? colors.white : 'rgba(255,255,255,0.1)',
borderRadius: '4px',
padding: '6px 8px',
}));
@@ -197,7 +197,7 @@ function AutoSizingTextInputWithRef(props: IInputProps, forwardedRef: React.Ref<
const { onFocus, onBlur, ...otherProps } = props;
const [focused, setFocused, setBlurred] = useBoolean(false);
- const inputRef = useRef() as React.RefObject<HTMLInputElement>;
+ const inputRef = useStyledRef<HTMLInputElement>();
const combinedRef = useCombinedRefs(inputRef, forwardedRef);
const onBlurWrapper = useCallback(
@@ -222,7 +222,7 @@ function AutoSizingTextInputWithRef(props: IInputProps, forwardedRef: React.Ref<
return (
<BackAction disabled={!focused} action={blur}>
- <InputFrame focused={focused}>
+ <InputFrame $focused={focused}>
<StyledAutoSizingTextInputContainer>
<StyledAutoSizingTextInputWrapper>
<Input
@@ -254,11 +254,11 @@ const StyledSubmitButton = styled.button({
padding: '10px 0',
});
-const StyledInputWrapper = styled.div(normalText, (props: { marginLeft: number }) => ({
+const StyledInputWrapper = styled.div<{ $marginLeft: number }>(normalText, (props) => ({
position: 'relative',
flex: 1,
width: '171px',
- marginLeft: props.marginLeft + 'px',
+ marginLeft: props.$marginLeft + 'px',
lineHeight: '24px',
minHeight: '24px',
fontWeight: 400,
@@ -266,7 +266,7 @@ const StyledInputWrapper = styled.div(normalText, (props: { marginLeft: number }
maxWidth: '100%',
}));
-const StyledTextArea = styled.textarea(normalText, (props: { invalid?: boolean }) => ({
+const StyledTextArea = styled.textarea<{ $invalid?: boolean }>(normalText, (props) => ({
position: 'absolute',
top: 0,
left: 0,
@@ -279,7 +279,7 @@ const StyledTextArea = styled.textarea(normalText, (props: { invalid?: boolean }
fontWeight: 400,
resize: 'none',
padding: '10px 25px 10px 0',
- color: props.invalid ? colors.red : 'auto',
+ color: props.$invalid ? colors.red : 'auto',
}));
const StyledInputFiller = styled.div({
@@ -304,7 +304,7 @@ interface IRowInputProps {
export function RowInput(props: IRowInputProps) {
const [value, setValue] = useState(props.initialValue ?? '');
- const textAreaRef = useRef() as React.RefObject<HTMLTextAreaElement>;
+ const textAreaRef = useStyledRef<HTMLTextAreaElement>();
const [focused, setFocused, setBlurred] = useBoolean(false);
const submit = useCallback(() => props.onSubmit(value), [props.onSubmit, value]);
@@ -366,7 +366,7 @@ export function RowInput(props: IRowInputProps) {
return (
<BackAction disabled={!focused} action={blur}>
<StyledCellInputRowContainer>
- <StyledInputWrapper marginLeft={props.paddingLeft ?? 0}>
+ <StyledInputWrapper $marginLeft={props.paddingLeft ?? 0}>
<StyledInputFiller>{value}</StyledInputFiller>
<StyledTextArea
ref={textAreaRef}
@@ -374,7 +374,7 @@ export function RowInput(props: IRowInputProps) {
onKeyDown={onKeyDown}
rows={1}
value={value}
- invalid={props.invalid}
+ $invalid={props.invalid}
onFocus={onFocus}
onBlur={onBlur}
placeholder={props.placeholder}
diff --git a/gui/src/renderer/components/cell/Label.tsx b/gui/src/renderer/components/cell/Label.tsx
index f3d3624d45..5e9963ded9 100644
--- a/gui/src/renderer/components/cell/Label.tsx
+++ b/gui/src/renderer/components/cell/Label.tsx
@@ -7,14 +7,14 @@ import ImageView, { IImageViewProps } from '../ImageView';
import { CellButton } from './CellButton';
import { CellDisabledContext } from './Container';
-const StyledLabel = styled.div(buttonText, (props: { disabled: boolean }) => ({
+const StyledLabel = styled.div<{ disabled: boolean }>(buttonText, (props) => ({
margin: '10px 0',
flex: 1,
color: props.disabled ? colors.white40 : colors.white,
textAlign: 'left',
}));
-const StyledSubText = styled.span(tinyText, (props: { disabled: boolean }) => ({
+const StyledSubText = styled.span<{ disabled: boolean }>(tinyText, (props) => ({
color: props.disabled ? colors.white20 : colors.white60,
flex: -1,
textAlign: 'right',
@@ -22,7 +22,7 @@ const StyledSubText = styled.span(tinyText, (props: { disabled: boolean }) => ({
marginRight: '8px',
}));
-const StyledIconContainer = styled.div((props: { disabled: boolean }) => ({
+const StyledIconContainer = styled.div<{ disabled: boolean }>((props) => ({
opacity: props.disabled ? 0.4 : 1,
}));
@@ -30,7 +30,7 @@ const StyledTintedIcon = styled(ImageView).attrs((props: IImageViewProps) => ({
tintColor: props.tintColor ?? colors.white60,
tintHoverColor: props.tintHoverColor ?? props.tintColor ?? colors.white60,
}))((props: IImageViewProps) => ({
- ':hover': {
+ '&&:hover': {
backgroundColor: props.tintColor,
},
[`${CellButton}:not(:disabled):hover &&`]: {
diff --git a/gui/src/renderer/components/cell/Row.tsx b/gui/src/renderer/components/cell/Row.tsx
index 08309d6843..9aca25d3a0 100644
--- a/gui/src/renderer/components/cell/Row.tsx
+++ b/gui/src/renderer/components/cell/Row.tsx
@@ -1,10 +1,17 @@
+import React from 'react';
import styled from 'styled-components';
import { colors } from '../../../config.json';
import { measurements } from '../common-styles';
import { Group } from './Group';
-export const Row = styled.div((props: { includeMarginBottomOnLast?: boolean }) => ({
+interface RowProps extends React.HTMLAttributes<HTMLDivElement> {
+ includeMarginBottomOnLast?: boolean;
+}
+
+export const Row = styled.div.withConfig({
+ shouldForwardProp: (prop) => prop !== 'includeMarginBottomOnLast',
+})<RowProps>((props) => ({
display: 'flex',
alignItems: 'center',
backgroundColor: colors.blue,
@@ -12,7 +19,7 @@ export const Row = styled.div((props: { includeMarginBottomOnLast?: boolean }) =
paddingLeft: measurements.viewMargin,
paddingRight: measurements.viewMargin,
marginBottom: '1px',
- [`${Group} > &:last-child`]: {
+ [`${Group} > &&:last-child`]: {
marginBottom: props.includeMarginBottomOnLast ? '1px' : '0px',
},
}));
diff --git a/gui/src/renderer/components/cell/Section.tsx b/gui/src/renderer/components/cell/Section.tsx
index 8ba5975476..056aa8ceac 100644
--- a/gui/src/renderer/components/cell/Section.tsx
+++ b/gui/src/renderer/components/cell/Section.tsx
@@ -18,15 +18,15 @@ const StyledSection = styled.div({
interface SectionTitleProps {
disabled?: boolean;
- thin?: boolean;
+ $thin?: boolean;
}
-export const SectionTitle = styled(Row)(buttonText, (props: SectionTitleProps) => ({
+export const SectionTitle = styled(Row)<SectionTitleProps>(buttonText, (props) => ({
paddingRight: '16px',
color: props.disabled ? colors.white20 : colors.white,
- fontWeight: props.thin ? 400 : 600,
- fontSize: props.thin ? '15px' : '18px',
- ...(props.thin ? openSans : sourceSansPro),
+ fontWeight: props.$thin ? 400 : 600,
+ fontSize: props.$thin ? '15px' : '18px',
+ ...(props.$thin ? openSans : sourceSansPro),
}));
export const CellSectionContext = React.createContext<boolean>(false);
diff --git a/gui/src/renderer/components/cell/Selector.tsx b/gui/src/renderer/components/cell/Selector.tsx
index 5eb9762eb3..f1d9e14360 100644
--- a/gui/src/renderer/components/cell/Selector.tsx
+++ b/gui/src/renderer/components/cell/Selector.tsx
@@ -3,6 +3,7 @@ import styled from 'styled-components';
import { colors } from '../../../config.json';
import { messages } from '../../../shared/gettext';
+import { useStyledRef } from '../../lib/utilityHooks';
import { AriaDetails, AriaInput, AriaLabel } from '../AriaGroup';
import { normalText } from '../common-styles';
import InfoButton from '../InfoButton';
@@ -76,7 +77,7 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) {
const title = props.title ? (
<>
<AriaLabel>
- <StyledTitleLabel as="label" disabled={props.disabled} thin={props.thinTitle}>
+ <StyledTitleLabel as="label" disabled={props.disabled} $thin={props.thinTitle}>
{props.title}
</StyledTitleLabel>
</AriaLabel>
@@ -90,7 +91,7 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) {
// Add potential additional items to the list. Used for custom entry.
const children = (
- <Cell.Group noMarginBottom>
+ <Cell.Group $noMarginBottom>
{items}
{props.children}
</Cell.Group>
@@ -120,8 +121,8 @@ export default function Selector<T, U>(props: SelectorProps<T, U>) {
}
}
-const StyledCellIcon = styled(Cell.Icon)((props: { visible: boolean }) => ({
- opacity: props.visible ? 1 : 0,
+const StyledCellIcon = styled(Cell.Icon)<{ $visible: boolean }>((props) => ({
+ opacity: props.$visible ? 1 : 0,
marginRight: '8px',
}));
@@ -155,7 +156,7 @@ function SelectorCell<T>(props: SelectorCellProps<T>) {
aria-selected={props.isSelected}
aria-disabled={props.disabled}>
<StyledCellIcon
- visible={props.isSelected}
+ $visible={props.isSelected}
source="icon-tick"
width={18}
tintColor={colors.white}
@@ -169,9 +170,9 @@ interface StyledCustomContainerProps {
selected: boolean;
}
-const StyledCustomContainer = styled(Cell.Container)((props: StyledCustomContainerProps) => ({
+const StyledCustomContainer = styled(Cell.Container)<StyledCustomContainerProps>((props) => ({
backgroundColor: props.selected ? colors.green : colors.blue40,
- ':hover': {
+ '&&:hover': {
backgroundColor: props.selected ? colors.green : colors.blue,
},
}));
@@ -212,7 +213,7 @@ export function SelectorWithCustomItem<T, U>(props: SelectorWithCustomItemProps<
const [customValue, setCustomValue] = useState(itemIsSelected ? undefined : `${value}`);
const customIsSelected = customValue !== undefined;
- const inputRef = useRef() as React.RefObject<HTMLInputElement>;
+ const inputRef = useStyledRef<HTMLInputElement>();
const handleClickCustom = useCallback(() => {
inputRef.current?.focus();
@@ -285,7 +286,7 @@ export function SelectorWithCustomItem<T, U>(props: SelectorWithCustomItemProps<
aria-selected={customIsSelected}
aria-disabled={props.disabled}>
<StyledCellIcon
- visible={customIsSelected}
+ $visible={customIsSelected}
source="icon-tick"
width={18}
tintColor={colors.white}
diff --git a/gui/src/renderer/components/select-location/CustomLists.tsx b/gui/src/renderer/components/select-location/CustomLists.tsx
index b87de1fe46..7fb66f630e 100644
--- a/gui/src/renderer/components/select-location/CustomLists.tsx
+++ b/gui/src/renderer/components/select-location/CustomLists.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
import styled from 'styled-components';
import { colors } from '../../../config.json';
@@ -6,7 +6,7 @@ import { CustomListError, CustomLists, RelayLocation } from '../../../shared/dae
import { messages } from '../../../shared/gettext';
import log from '../../../shared/logging';
import { useAppContext } from '../../context';
-import { useBoolean } from '../../lib/utilityHooks';
+import { useBoolean, useStyledRef } from '../../lib/utilityHooks';
import Accordion from '../Accordion';
import * as Cell from '../cell';
import { measurements } from '../common-styles';
@@ -57,8 +57,8 @@ const StyledSideButtonIcon = styled(Cell.Icon)({
},
});
-const StyledInput = styled(SimpleInput)((props: { error: boolean }) => ({
- color: props.error ? colors.red : 'auto',
+const StyledInput = styled(SimpleInput)<{ $error: boolean }>((props) => ({
+ color: props.$error ? colors.red : 'auto',
}));
interface CustomListsProps {
@@ -93,8 +93,8 @@ export default function CustomLists(props: CustomListsProps) {
{messages.pgettext('select-location-view', 'Custom lists')}
</StyledHeaderLabel>
<StyledCellButton
- backgroundColor={colors.blue}
- backgroundColorHover={colors.blue80}
+ $backgroundColor={colors.blue}
+ $backgroundColorHover={colors.blue80}
onClick={showAddList}>
<StyledSideButtonIcon source="icon-add" tintColor={colors.white60} width={18} />
</StyledCellButton>
@@ -118,8 +118,8 @@ interface AddListFormProps {
function AddListForm(props: AddListFormProps) {
const [name, setName] = useState('');
const [error, setError, unsetError] = useBoolean();
- const containerRef = useRef<HTMLDivElement>() as React.RefObject<HTMLDivElement>;
- const inputRef = useRef<HTMLInputElement>() as React.RefObject<HTMLInputElement>;
+ const containerRef = useStyledRef<HTMLDivElement>();
+ const inputRef = useStyledRef<HTMLInputElement>();
// Errors should be reset when editing the value
const onChange = useCallback((value: string) => {
@@ -172,14 +172,14 @@ function AddListForm(props: AddListFormProps) {
onSubmitValue={createList}
onBlur={onBlur}
maxLength={30}
- error={error}
+ $error={error}
autoFocus
/>
</StyledInputContainer>
<StyledAddListCellButton
- backgroundColor={colors.blue}
- backgroundColorHover={colors.blue80}
+ $backgroundColor={colors.blue}
+ $backgroundColorHover={colors.blue80}
onClick={createList}>
<StyledSideButtonIcon source="icon-check" tintColor={colors.white60} width={18} />
</StyledAddListCellButton>
diff --git a/gui/src/renderer/components/select-location/LocationRow.tsx b/gui/src/renderer/components/select-location/LocationRow.tsx
index 514fd19207..97c8528fa9 100644
--- a/gui/src/renderer/components/select-location/LocationRow.tsx
+++ b/gui/src/renderer/components/select-location/LocationRow.tsx
@@ -11,7 +11,7 @@ import {
import { messages } from '../../../shared/gettext';
import log from '../../../shared/logging';
import { useAppContext } from '../../context';
-import { useBoolean } from '../../lib/utilityHooks';
+import { useBoolean, useStyledRef } from '../../lib/utilityHooks';
import { useSelector } from '../../redux/store';
import Accordion from '../Accordion';
import * as Cell from '../cell';
@@ -29,15 +29,15 @@ import {
} from './select-location-types';
interface IButtonColorProps {
- backgroundColor: string;
- backgroundColorHover: string;
+ $backgroundColor: string;
+ $backgroundColorHover: string;
}
const buttonColor = (props: IButtonColorProps) => {
return {
- backgroundColor: props.backgroundColor,
- ':not(:disabled):hover': {
- backgroundColor: props.backgroundColorHover,
+ backgroundColor: props.$backgroundColor,
+ '&&:not(:disabled):hover': {
+ backgroundColor: props.$backgroundColorHover,
},
};
};
@@ -48,10 +48,10 @@ export const StyledLocationRowContainer = styled(Cell.Container)({
background: 'none',
});
-export const StyledLocationRowButton = styled(Cell.Row)(
+export const StyledLocationRowButton = styled(Cell.Row)<IButtonColorProps & { $level: number }>(
buttonColor,
- (props: IButtonColorProps & { level: number }) => {
- const paddingLeft = (props.level + 1) * 16 + 2;
+ (props) => {
+ const paddingLeft = (props.$level + 1) * 16 + 2;
return {
display: 'flex',
@@ -64,13 +64,13 @@ export const StyledLocationRowButton = styled(Cell.Row)(
},
);
-export const StyledLocationRowIcon = styled.button(buttonColor, {
+export const StyledLocationRowIcon = styled.button<IButtonColorProps>(buttonColor, {
position: 'relative',
alignSelf: 'stretch',
paddingLeft: measurements.viewMargin,
paddingRight: measurements.viewMargin,
- '&::before': {
+ '&&::before': {
content: '""',
position: 'absolute',
margin: 'auto',
@@ -93,26 +93,26 @@ export const StyledLocationRowLabel = styled(Cell.Label)(normalText, {
whiteSpace: 'nowrap',
});
-const StyledHoverIconButton = styled.button(
+const StyledHoverIconButton = styled.button<IButtonColorProps & { $isLast?: boolean }>(
buttonColor,
- (props: { isLast?: boolean } & IButtonColorProps) => ({
+ (props) => ({
flex: 0,
display: 'none',
padding: '0 10px',
- paddingRight: props.isLast ? '17px' : '10px',
+ paddingRight: props.$isLast ? '17px' : '10px',
margin: 0,
border: 0,
height: measurements.rowMinHeight,
appearance: 'none',
- ':not(:disabled):hover': {
- backgroundColor: props.backgroundColor,
+ '&&:not(:disabled):hover': {
+ backgroundColor: props.$backgroundColor,
},
[`${StyledLocationRowContainer}:hover &&`]: {
display: 'block',
},
[`${StyledLocationRowButton}:hover ~ &&`]: {
- backgroundColor: props.backgroundColorHover,
+ backgroundColor: props.$backgroundColorHover,
},
}),
);
@@ -152,7 +152,7 @@ interface IProps<C extends LocationSpecification> {
// Renders the rows and its children for countries, cities and relays
function LocationRow<C extends LocationSpecification>(props: IProps<C>) {
const hasChildren = getLocationChildren(props.source).some((child) => child.visible);
- const buttonRef = useRef<HTMLButtonElement>() as React.RefObject<HTMLButtonElement>;
+ const buttonRef = useStyledRef<HTMLButtonElement>();
const userInvokedExpand = useRef(false);
const { updateCustomList, deleteCustomList } = useAppContext();
@@ -240,7 +240,7 @@ function LocationRow<C extends LocationSpecification>(props: IProps<C>) {
as="button"
ref={buttonRef}
onClick={handleClick}
- level={props.level}
+ $level={props.level}
disabled={props.source.disabled}
includeMarginBottomOnLast
{...background}>
@@ -249,7 +249,7 @@ function LocationRow<C extends LocationSpecification>(props: IProps<C>) {
</StyledLocationRowButton>
{props.allowAddToCustomList ? (
- <StyledHoverIconButton onClick={showAddToListDialog} isLast {...background}>
+ <StyledHoverIconButton onClick={showAddToListDialog} $isLast {...background}>
<StyledHoverIcon source="icon-add" />
</StyledHoverIconButton>
) : null}
@@ -258,7 +258,7 @@ function LocationRow<C extends LocationSpecification>(props: IProps<C>) {
{'customList' in props.source.location &&
'country' in props.source.location &&
props.level === 1 ? (
- <StyledHoverIconButton onClick={onRemoveFromList} isLast {...background}>
+ <StyledHoverIconButton onClick={onRemoveFromList} $isLast {...background}>
<StyledHoverIcon source="icon-remove" />
</StyledHoverIconButton>
) : null}
@@ -269,7 +269,7 @@ function LocationRow<C extends LocationSpecification>(props: IProps<C>) {
<StyledHoverIconButton onClick={showEditDialog} {...background}>
<StyledHoverIcon source="icon-edit" />
</StyledHoverIconButton>
- <StyledHoverIconButton onClick={onRemoveCustomList} isLast {...background}>
+ <StyledHoverIconButton onClick={onRemoveCustomList} $isLast {...background}>
<StyledHoverIcon source="icon-close" />
</StyledHoverIconButton>
</>
@@ -297,7 +297,7 @@ function LocationRow<C extends LocationSpecification>(props: IProps<C>) {
onWillExpand={onWillExpand}
onTransitionEnd={props.onTransitionEnd}
animationDuration={150}>
- <Cell.Group noMarginBottom>{props.children}</Cell.Group>
+ <Cell.Group $noMarginBottom>{props.children}</Cell.Group>
</Accordion>
)}
@@ -333,8 +333,8 @@ export function getButtonColor(selected: boolean, level: number, disabled?: bool
}
return {
- backgroundColor,
- backgroundColorHover: selected || disabled ? backgroundColor : colors.blue80,
+ $backgroundColor: backgroundColor,
+ $backgroundColorHover: selected || disabled ? backgroundColor : colors.blue80,
};
}
diff --git a/gui/src/renderer/components/select-location/RelayLocationList.tsx b/gui/src/renderer/components/select-location/RelayLocationList.tsx
index 27fe75ea50..49e1f2a38c 100644
--- a/gui/src/renderer/components/select-location/RelayLocationList.tsx
+++ b/gui/src/renderer/components/select-location/RelayLocationList.tsx
@@ -25,7 +25,7 @@ interface RelayLocationsProps extends CommonProps {
export default function RelayLocationList({ source, ...props }: RelayLocationsProps) {
return (
- <Cell.Group noMarginBottom>
+ <Cell.Group $noMarginBottom>
{source.map((country) => (
<RelayLocation
key={getLocationKey(country.location)}
diff --git a/gui/src/renderer/components/select-location/ScopeBar.tsx b/gui/src/renderer/components/select-location/ScopeBar.tsx
index 94c80dea7c..bbe4935993 100644
--- a/gui/src/renderer/components/select-location/ScopeBar.tsx
+++ b/gui/src/renderer/components/select-location/ScopeBar.tsx
@@ -35,7 +35,7 @@ export function ScopeBar(props: IScopeBarProps) {
return <StyledScopeBar className={props.className}>{children}</StyledScopeBar>;
}
-const StyledScopeBarItem = styled.button(smallText, (props: { selected?: boolean }) => ({
+const StyledScopeBarItem = styled.button<{ selected?: boolean }>(smallText, (props) => ({
cursor: 'default',
flex: 1,
flexBasis: 0,
@@ -44,7 +44,7 @@ const StyledScopeBarItem = styled.button(smallText, (props: { selected?: boolean
textAlign: 'center',
border: 'none',
backgroundColor: props.selected ? colors.green : 'transparent',
- ':hover': {
+ '&&:hover': {
backgroundColor: props.selected ? colors.green : colors.blue40,
},
}));
diff --git a/gui/src/renderer/components/select-location/ScrollPositionContext.tsx b/gui/src/renderer/components/select-location/ScrollPositionContext.tsx
index 973e4484b6..04fcd0bccc 100644
--- a/gui/src/renderer/components/select-location/ScrollPositionContext.tsx
+++ b/gui/src/renderer/components/select-location/ScrollPositionContext.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'react';
-import { useNormalRelaySettings } from '../../lib/utilityHooks';
+import { useNormalRelaySettings, useStyledRef } from '../../lib/utilityHooks';
import { CustomScrollbarsRef } from '../CustomScrollbars';
import { LocationType } from './select-location-types';
import { useSelectLocationContext } from './SelectLocationContainer';
@@ -39,7 +39,7 @@ export function ScrollPositionContextProvider(props: ScrollPositionContextProps)
const scrollPositions = useRef<Partial<Record<LocationType, ScrollPosition>>>({});
const scrollViewRef = useRef<CustomScrollbarsRef>(null);
- const spacePreAllocationViewRef = useRef() as React.RefObject<SpacePreAllocationView>;
+ const spacePreAllocationViewRef = useStyledRef<SpacePreAllocationView>();
const selectedLocationRef = useRef<HTMLDivElement>(null);
const saveScrollPosition = useCallback(() => {
diff --git a/gui/src/renderer/components/select-location/SpecialLocationList.tsx b/gui/src/renderer/components/select-location/SpecialLocationList.tsx
index c8c0c8e787..030520fc73 100644
--- a/gui/src/renderer/components/select-location/SpecialLocationList.tsx
+++ b/gui/src/renderer/components/select-location/SpecialLocationList.tsx
@@ -64,7 +64,7 @@ function SpecialLocationRow<T>(props: SpecialLocationRowProps<T>) {
const background = getButtonColor(props.source.selected, 0, props.source.disabled);
return (
<StyledLocationRowContainerWithMargin ref={selectedRef}>
- <StyledLocationRowButton onClick={onSelect} level={0} {...background}>
+ <StyledLocationRowButton onClick={onSelect} $level={0} {...background}>
{icon && (
<StyledSpecialLocationIcon
source={icon}
@@ -79,8 +79,8 @@ function SpecialLocationRow<T>(props: SpecialLocationRowProps<T>) {
<StyledLocationRowIcon
as={StyledSpecialLocationInfoButton}
message={props.source.info}
- selected={props.source.selected}
aria-label={messages.pgettext('accessibility', 'info')}
+ {...background}
/>
)}
</StyledLocationRowContainerWithMargin>
diff --git a/gui/src/renderer/lib/styles.ts b/gui/src/renderer/lib/styles.ts
new file mode 100644
index 0000000000..554e669373
--- /dev/null
+++ b/gui/src/renderer/lib/styles.ts
@@ -0,0 +1,9 @@
+type NonTransientPropKey<K> = K extends `$${infer L}` ? L : K;
+
+export type NonTransientProps<T, K extends NonTransientPropKey<keyof T>> = {
+ [P in keyof T as NonTransientPropKey<P> extends K ? NonTransientPropKey<P> : P]: T[P];
+};
+
+export type TransientProps<T, K extends keyof T> = {
+ [P in keyof T as P extends K ? `$${P & string}` : P]: T[P];
+};
diff --git a/gui/src/renderer/lib/utilityHooks.ts b/gui/src/renderer/lib/utilityHooks.ts
index 378a6d5ae5..49f508a883 100644
--- a/gui/src/renderer/lib/utilityHooks.ts
+++ b/gui/src/renderer/lib/utilityHooks.ts
@@ -16,6 +16,10 @@ export function useMounted() {
return isMounted;
}
+export function useStyledRef<T>(): React.RefObject<T> {
+ return useRef() as React.RefObject<T>;
+}
+
export function useCombinedRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> {
return useCallback((element: T | null) => refs.forEach((ref) => assignToRef(element, ref)), []);
}