diff --git a/package.json b/package.json index 277ab40af..1114c275c 100644 --- a/package.json +++ b/package.json @@ -140,6 +140,7 @@ "@discordapp/twemoji": "15.1.0", "@electron/notarize": "2.5.0", "@primer/octicons-react": "19.14.0", + "@primer/react": "36.27.0", "@testing-library/react": "16.2.0", "@types/jest": "29.5.14", "@types/node": "22.10.7", @@ -150,7 +151,6 @@ "@types/semver": "7.5.8", "autoprefixer": "10.4.20", "axios": "1.7.9", - "class-variance-authority": "0.7.1", "clsx": "2.1.1", "concurrently": "9.1.2", "copy-webpack-plugin": "12.0.2", @@ -173,6 +173,7 @@ "react-final-form": "6.5.9", "rimraf": "6.0.1", "semver": "7.6.3", + "styled-components": "6.1.13", "tailwind-merge": "2.6.0", "tailwindcss": "3.4.17", "terser-webpack-plugin": "5.3.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d90501b8d..d228ac79e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,6 +45,9 @@ importers: '@primer/octicons-react': specifier: 19.14.0 version: 19.14.0(react@19.0.0) + '@primer/react': + specifier: 36.27.0 + version: 36.27.0(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(styled-components@6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)) '@testing-library/react': specifier: 16.2.0 version: 16.2.0(@testing-library/dom@10.0.0)(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -75,9 +78,6 @@ importers: axios: specifier: 1.7.9 version: 1.7.9 - class-variance-authority: - specifier: 0.7.1 - version: 0.7.1 clsx: specifier: 2.1.1 version: 2.1.1 @@ -144,6 +144,9 @@ importers: semver: specifier: 7.6.3 version: 7.6.3 + styled-components: + specifier: 6.1.13 + version: 6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0) tailwind-merge: specifier: 2.6.0 version: 2.6.0 @@ -472,9 +475,33 @@ packages: resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==} engines: {node: '>=16.4'} + '@emotion/is-prop-valid@1.2.2': + resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} + + '@emotion/memoize@0.8.1': + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + + '@emotion/unitless@0.8.1': + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + '@gar/promisify@1.1.3': resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + '@github/combobox-nav@2.3.1': + resolution: {integrity: sha512-gwxPzLw8XKecy1nP63i9lOBritS3bWmxl02UX6G0TwMQZbMem1BCS1tEZgYd3mkrkiDrUMWaX+DbFCuDFo3K+A==} + + '@github/markdown-toolbar-element@2.2.3': + resolution: {integrity: sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A==} + + '@github/paste-markdown@1.5.3': + resolution: {integrity: sha512-PzZ1b3PaqBzYqbT4fwKEhiORf38h2OcGp2+JdXNNM7inZ7egaSmfmhyNkQILpqWfS0AYtRS3CDq6z03eZ8yOMQ==} + + '@github/relative-time-element@4.4.3': + resolution: {integrity: sha512-EVKokqx9/DdUAZ2l9WVyY51EtRCO2gQWWMvsRIn7r4glJ91q9CXcnILVHZVCpfD52ucXUhUvtYsAjNJ4qP4uIg==} + + '@github/tab-container-element@4.8.2': + resolution: {integrity: sha512-WkaM4mfs8x7dXRWEaDb5deC0OhH6sGQ5cw8i/sVw25gikl4f8C7mHj0kihL5k3eKIIqmGT1Fdswdoi+9ZLDpRA==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -577,6 +604,12 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@lit-labs/react@1.2.1': + resolution: {integrity: sha512-DiZdJYFU0tBbdQkfwwRSwYyI/mcWkg3sWesKRsHUd4G+NekTmmeq9fzsurvcKTNVa0comNljwtg4Hvi1ds3V+A==} + + '@lit-labs/ssr-dom-shim@1.2.1': + resolution: {integrity: sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==} + '@malept/cross-spawn-promise@1.1.1': resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==} engines: {node: '>= 10'} @@ -610,16 +643,52 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This functionality has been moved to @npmcli/fs + '@oddbird/popover-polyfill@0.3.8': + resolution: {integrity: sha512-+aK7EHL3VggfsWGVqUwvtli2+kP5OWyseAsrefhzR2XWoi2oALUCeoDn63i5WS3ZOmLiXHRNBwHPeta8w+aM1g==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@primer/behaviors@1.8.0': + resolution: {integrity: sha512-ZUfhWVY4ZBKc2Fh3fIa2Qwwa3SnOi914lY5wcmN+UNtsBxeXsjWNwpohJbwRwWZm+nJ3C1n9qJFWpHuBlDVU1A==} + + '@primer/live-region-element@0.7.1': + resolution: {integrity: sha512-9uQCeBCb3wefz3kJNSo+PECc7T7TNB3k22JUdHY08Zlv9bd1rtsQgpazM5umcbZQrACzGbgufAfdbhGUBXI3jA==} + + '@primer/octicons-react@19.12.0': + resolution: {integrity: sha512-xnVzFmeWqqiiv9XYZ0hrlytAlCrSZ+HM3JrRzmD/LiPgdyEhyG/qb/ewMukiDoF9Ckwy4rkd1zuDd3KAx4DIAw==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.3' + '@primer/octicons-react@19.14.0': resolution: {integrity: sha512-EKeavGV7s2HYac3ybb+6vfyqHGMUeG+OlZAus5ORfEjzXlorDAIjZ59fszVJj9DI6ArfFK/Cvg8V4JRfeUHjcw==} engines: {node: '>=8'} peerDependencies: react: '>=16.3' + '@primer/primitives@7.17.1': + resolution: {integrity: sha512-SiPzEb+up1nDpV2NGwNiY8m6sGnF3OUqRb0has5s6T40vq6Li/g3cYVgl+oolEa4DUoNygEPs09jwJt24f/3zg==} + + '@primer/react@36.27.0': + resolution: {integrity: sha512-dVyp0f9zbbQYQZ6ztfMET43vVaWhvSz+qWirBzpRjDxvCk8vCQsvWrVGUU/PR0kAxxDHf6hqeLG7vcDL229NLA==} + engines: {node: '>=12', npm: '>=7'} + peerDependencies: + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 + '@types/styled-components': ^5.1.11 + react: ^18.0.0 + react-dom: ^18.0.0 + styled-components: 5.x + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@types/styled-components': + optional: true + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -637,6 +706,51 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@styled-system/background@5.1.2': + resolution: {integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==} + + '@styled-system/border@5.1.5': + resolution: {integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==} + + '@styled-system/color@5.1.2': + resolution: {integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==} + + '@styled-system/core@5.1.2': + resolution: {integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==} + + '@styled-system/css@5.1.5': + resolution: {integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==} + + '@styled-system/flexbox@5.1.2': + resolution: {integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==} + + '@styled-system/grid@5.1.2': + resolution: {integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==} + + '@styled-system/layout@5.1.2': + resolution: {integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==} + + '@styled-system/position@5.1.2': + resolution: {integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==} + + '@styled-system/props@5.1.5': + resolution: {integrity: sha512-FXhbzq2KueZpGaHxaDm8dowIEWqIMcgsKs6tBl6Y6S0njG9vC8dBMI6WSLDnzMoSqIX3nSKHmOmpzpoihdDewg==} + + '@styled-system/shadow@5.1.2': + resolution: {integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==} + + '@styled-system/space@5.1.2': + resolution: {integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==} + + '@styled-system/theme-get@5.1.2': + resolution: {integrity: sha512-afAYdRqrKfNIbVgmn/2Qet1HabxmpRnzhFwttbGr6F/mJ4RDS/Cmn+KHwHvNXangQsWw/5TfjpWV+rgcqqIcJQ==} + + '@styled-system/typography@5.1.2': + resolution: {integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==} + + '@styled-system/variant@5.1.5': + resolution: {integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==} + '@szmarczak/http-timer@4.0.6': resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} @@ -722,6 +836,9 @@ packages: '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/hast@2.3.10': + resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} + '@types/history@4.7.11': resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} @@ -752,6 +869,9 @@ packages: '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/mdast@3.0.15': + resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} @@ -767,11 +887,17 @@ packages: '@types/plist@3.0.5': resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} + '@types/prop-types@15.7.14': + resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + '@types/react-dom@19.0.3': resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} peerDependencies: '@types/react': ^19.0.0 + '@types/react-is@18.3.0': + resolution: {integrity: sha512-KZJpHUkAdzyKj/kUHJDc6N7KyidftICufJfOFpiG6haL/BDQNQt5i4n1XDUL/nDZAtGLHDSWRYpLzKTAKSvX6w==} + '@types/react-router-dom@5.3.3': resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} @@ -790,9 +916,24 @@ packages: '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/styled-system@5.1.23': + resolution: {integrity: sha512-mIwCCdhDa2ifdQCEm8ZeD8m4UEbFsokqEoT9YNOUv4alUJ8jbMKxvpr+oOwfuZgwqLh5HjWuEzwnX7DzWvjFBg==} + + '@types/styled-system__css@5.0.21': + resolution: {integrity: sha512-8S1lPbUbrE8U/2btqjh9X6pK9//kQdbQDe9z3vQl4SWtxtqoAVnrFZE6Xs+IHM7NMZ1uC68XrF9nLdzRHm3VyA==} + + '@types/styled-system__theme-get@5.0.4': + resolution: {integrity: sha512-dbzwxQ+8x6Bo3EKZMo9M3Knzo77ukwoC/isKW+GAuF5TenXlPkvgzx4t4+Lp0+fKs2M4owSef0KO3gtGW3Hpkw==} + + '@types/stylis@4.2.5': + resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} + '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + '@types/verror@1.10.10': resolution: {integrity: sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==} @@ -1096,6 +1237,9 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1207,6 +1351,9 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + camelize@1.0.1: + resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} @@ -1228,6 +1375,9 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -1250,9 +1400,6 @@ packages: cjs-module-lexer@1.2.3: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} - class-variance-authority@0.7.1: - resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - clean-css@5.3.3: resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} engines: {node: '>= 10.0'} @@ -1288,6 +1435,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -1316,6 +1467,9 @@ packages: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true + color2k@2.0.3: + resolution: {integrity: sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog==} + colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} @@ -1326,6 +1480,9 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -1426,6 +1583,10 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-color-keywords@1.0.0: + resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} + engines: {node: '>=4'} + css-declaration-sorter@7.2.0: resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==} engines: {node: ^14 || ^16 || >=18} @@ -1475,6 +1636,9 @@ packages: css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + css-to-react-native@3.2.0: + resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + css-tree@2.2.1: resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} @@ -1546,6 +1710,9 @@ packages: decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -1610,6 +1777,10 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dir-compare@3.3.0: resolution: {integrity: sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==} @@ -1844,6 +2015,9 @@ packages: exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -1898,6 +2072,9 @@ packages: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} hasBin: true + focus-visible@5.2.1: + resolution: {integrity: sha512-8Bx950VD1bWTQJEH/AM6SpEk+SU55aVnp4Ujhuuxy3eMEBCRwBnTBnVXr9YAPvZL3/CNjCa8u4IWfNmEO53whA==} + follow-redirects@1.15.6: resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} @@ -1952,6 +2129,9 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + fzy.js@0.4.1: + resolution: {integrity: sha512-4sPVXf+9oGhzg2tYzgWe4hgAY0wEbkqeuKVEgdnqX8S8VcLosQsDjb0jV+f5uoQlf8INWId1w0IGoufAoik1TA==} + gauge@4.0.4: resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -2075,10 +2255,16 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hast-util-whitespace@2.0.1: + resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} + he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + history@5.3.0: + resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==} + hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} @@ -2194,6 +2380,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + interpret@3.1.1: resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} engines: {node: '>=10.13.0'} @@ -2209,6 +2398,10 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} + is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + is-ci@3.0.1: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true @@ -2243,6 +2436,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} @@ -2533,6 +2730,10 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} @@ -2575,9 +2776,15 @@ packages: lodash.flatten@4.4.0: resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + lodash.isempty@4.4.0: + resolution: {integrity: sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==} + lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + lodash.isobject@3.0.2: + resolution: {integrity: sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==} + lodash.isplainobject@4.0.6: resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} @@ -2597,6 +2804,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -2645,6 +2856,18 @@ packages: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} + mdast-util-definitions@5.1.2: + resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} + + mdast-util-from-markdown@1.3.1: + resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} + + mdast-util-to-hast@12.3.0: + resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} + + mdast-util-to-string@3.2.0: + resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} + mdn-data@2.0.28: resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} @@ -2663,6 +2886,69 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + micromark-core-commonmark@1.1.0: + resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} + + micromark-factory-destination@1.1.0: + resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} + + micromark-factory-label@1.1.0: + resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==} + + micromark-factory-space@1.1.0: + resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} + + micromark-factory-title@1.1.0: + resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==} + + micromark-factory-whitespace@1.1.0: + resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==} + + micromark-util-character@1.2.0: + resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==} + + micromark-util-chunked@1.1.0: + resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} + + micromark-util-classify-character@1.1.0: + resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==} + + micromark-util-combine-extensions@1.1.0: + resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==} + + micromark-util-decode-numeric-character-reference@1.1.0: + resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==} + + micromark-util-decode-string@1.1.0: + resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==} + + micromark-util-encode@1.1.0: + resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} + + micromark-util-html-tag-name@1.2.0: + resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} + + micromark-util-normalize-identifier@1.1.0: + resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==} + + micromark-util-resolve-all@1.1.0: + resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==} + + micromark-util-sanitize-uri@1.2.0: + resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==} + + micromark-util-subtokenize@1.1.0: + resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} + + micromark-util-symbol@1.1.0: + resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} + + micromark-util-types@1.1.0: + resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} + + micromark@3.2.0: + resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -2757,6 +3043,10 @@ packages: engines: {node: '>=10'} hasBin: true + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -3208,6 +3498,10 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.1: resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==} engines: {node: ^10 || ^12 || >=14} @@ -3246,10 +3540,16 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + propagate@2.0.1: resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==} engines: {node: '>= 8'} + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} @@ -3290,12 +3590,30 @@ packages: final-form: ^4.20.4 react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-intersection-observer@9.13.1: + resolution: {integrity: sha512-tSzDaTy0qwNPLJHg8XZhlyHTgGW6drFKTtvjdL+p6um12rcnp8Z5XstE+QNBJ7c64n5o0Lj4ilUleA41bmDoMw==} + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react-dom: + optional: true + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react-markdown@8.0.7: + resolution: {integrity: sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + react-router-dom@7.1.3: resolution: {integrity: sha512-qQGTE+77hleBzv9SIUIkGRvuFBQGagW+TQKy53UTZAO/3+YFNBYvRsNIZ1GT17yHbc63FylMOdS+m3oUriF1GA==} engines: {node: '>=20.0.0'} @@ -3353,6 +3671,12 @@ packages: resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} engines: {node: '>= 0.10'} + remark-parse@10.0.2: + resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} + + remark-rehype@10.1.0: + resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + renderkid@3.0.0: resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} @@ -3429,6 +3753,10 @@ packages: rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -3492,6 +3820,9 @@ packages: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} + shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -3559,6 +3890,9 @@ packages: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -3615,12 +3949,28 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + style-to-object@0.4.4: + resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + + styled-components@6.1.13: + resolution: {integrity: sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==} + engines: {node: '>= 16'} + peerDependencies: + react: '>= 16.8.0' + react-dom: '>= 16.8.0' + + styled-system@5.1.5: + resolution: {integrity: sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==} + stylehacks@7.0.4: resolution: {integrity: sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==} engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} peerDependencies: postcss: ^8.4.31 + stylis@4.3.2: + resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==} + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -3747,6 +4097,12 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + truncate-utf8-bytes@1.0.2: resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} @@ -3831,6 +4187,9 @@ packages: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} + unified@10.1.2: + resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + unique-filename@2.0.1: resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -3839,6 +4198,24 @@ packages: resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + unist-util-generated@2.0.1: + resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} + + unist-util-is@5.2.1: + resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} + + unist-util-position@4.0.4: + resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} + + unist-util-stringify-position@3.0.3: + resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} + + unist-util-visit-parents@5.1.3: + resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} + + unist-util-visit@4.1.2: + resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -3881,6 +4258,11 @@ packages: utila@0.4.0: resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} + uvu@0.5.6: + resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} + engines: {node: '>=8'} + hasBin: true + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -3892,6 +4274,12 @@ packages: resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} engines: {node: '>=0.6.0'} + vfile-message@3.1.4: + resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} + + vfile@5.3.7: + resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} + w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} @@ -4415,8 +4803,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@emotion/is-prop-valid@1.2.2': + dependencies: + '@emotion/memoize': 0.8.1 + + '@emotion/memoize@0.8.1': {} + + '@emotion/unitless@0.8.1': {} + '@gar/promisify@1.1.3': {} + '@github/combobox-nav@2.3.1': {} + + '@github/markdown-toolbar-element@2.2.3': {} + + '@github/paste-markdown@1.5.3': {} + + '@github/relative-time-element@4.4.3': {} + + '@github/tab-container-element@4.8.2': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -4625,6 +5031,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + '@lit-labs/react@1.2.1': {} + + '@lit-labs/ssr-dom-shim@1.2.1': {} + '@malept/cross-spawn-promise@1.1.1': dependencies: cross-spawn: 7.0.6 @@ -4664,13 +5074,68 @@ snapshots: mkdirp: 1.0.4 rimraf: 3.0.2 + '@oddbird/popover-polyfill@0.3.8': {} + '@pkgjs/parseargs@0.11.0': optional: true + '@primer/behaviors@1.8.0': {} + + '@primer/live-region-element@0.7.1': + dependencies: + '@lit-labs/ssr-dom-shim': 1.2.1 + + '@primer/octicons-react@19.12.0(react@19.0.0)': + dependencies: + react: 19.0.0 + '@primer/octicons-react@19.14.0(react@19.0.0)': dependencies: react: 19.0.0 + '@primer/primitives@7.17.1': {} + + '@primer/react@36.27.0(@types/react-dom@19.0.3(@types/react@19.0.7))(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(styled-components@6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0))': + dependencies: + '@github/combobox-nav': 2.3.1 + '@github/markdown-toolbar-element': 2.2.3 + '@github/paste-markdown': 1.5.3 + '@github/relative-time-element': 4.4.3 + '@github/tab-container-element': 4.8.2 + '@lit-labs/react': 1.2.1 + '@oddbird/popover-polyfill': 0.3.8 + '@primer/behaviors': 1.8.0 + '@primer/live-region-element': 0.7.1 + '@primer/octicons-react': 19.12.0(react@19.0.0) + '@primer/primitives': 7.17.1 + '@styled-system/css': 5.1.5 + '@styled-system/props': 5.1.5 + '@styled-system/theme-get': 5.1.2 + '@types/react-is': 18.3.0 + '@types/styled-system': 5.1.23 + '@types/styled-system__css': 5.0.21 + '@types/styled-system__theme-get': 5.0.4 + clsx: 1.2.1 + color2k: 2.0.3 + deepmerge: 4.3.1 + focus-visible: 5.2.1 + fzy.js: 0.4.1 + history: 5.3.0 + lodash.isempty: 4.4.0 + lodash.isobject: 3.0.2 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-intersection-observer: 9.13.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react-is: 18.2.0 + react-markdown: 8.0.7(@types/react@19.0.7)(react@19.0.0) + styled-components: 6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + styled-system: 5.1.5 + optionalDependencies: + '@types/react': 19.0.7 + '@types/react-dom': 19.0.3(@types/react@19.0.7) + transitivePeerDependencies: + - supports-color + '@sinclair/typebox@0.27.8': {} '@sindresorhus/is@4.6.0': {} @@ -4685,6 +5150,65 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@styled-system/background@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/border@5.1.5': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/color@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/core@5.1.2': + dependencies: + object-assign: 4.1.1 + + '@styled-system/css@5.1.5': {} + + '@styled-system/flexbox@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/grid@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/layout@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/position@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/props@5.1.5': + dependencies: + styled-system: 5.1.5 + + '@styled-system/shadow@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/space@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/theme-get@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/typography@5.1.2': + dependencies: + '@styled-system/core': 5.1.2 + + '@styled-system/variant@5.1.5': + dependencies: + '@styled-system/core': 5.1.2 + '@styled-system/css': 5.1.5 + '@szmarczak/http-timer@4.0.6': dependencies: defer-to-connect: 2.0.1 @@ -4780,6 +5304,10 @@ snapshots: dependencies: '@types/node': 22.10.7 + '@types/hast@2.3.10': + dependencies: + '@types/unist': 2.0.11 + '@types/history@4.7.11': {} '@types/html-minifier-terser@6.1.0': {} @@ -4813,6 +5341,10 @@ snapshots: dependencies: '@types/node': 22.10.7 + '@types/mdast@3.0.15': + dependencies: + '@types/unist': 2.0.11 + '@types/ms@0.7.34': {} '@types/node@20.17.1': @@ -4831,10 +5363,16 @@ snapshots: xmlbuilder: 15.1.1 optional: true + '@types/prop-types@15.7.14': {} + '@types/react-dom@19.0.3(@types/react@19.0.7)': dependencies: '@types/react': 19.0.7 + '@types/react-is@18.3.0': + dependencies: + '@types/react': 19.0.7 + '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 @@ -4858,8 +5396,22 @@ snapshots: '@types/stack-utils@2.0.3': {} + '@types/styled-system@5.1.23': + dependencies: + csstype: 3.1.3 + + '@types/styled-system__css@5.0.21': + dependencies: + csstype: 3.1.3 + + '@types/styled-system__theme-get@5.0.4': {} + + '@types/stylis@4.2.5': {} + '@types/tough-cookie@4.0.5': {} + '@types/unist@2.0.11': {} + '@types/verror@1.10.10': optional: true @@ -5280,6 +5832,8 @@ snapshots: babel-plugin-jest-hoist: 29.6.3 babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.3) + bail@2.0.2: {} + balanced-match@1.0.2: {} base64-js@1.5.1: {} @@ -5453,6 +6007,8 @@ snapshots: camelcase@6.3.0: {} + camelize@1.0.1: {} + caniuse-api@3.0.0: dependencies: browserslist: 4.24.2 @@ -5477,6 +6033,8 @@ snapshots: char-regex@1.0.2: {} + character-entities@2.0.2: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -5499,10 +6057,6 @@ snapshots: cjs-module-lexer@1.2.3: {} - class-variance-authority@0.7.1: - dependencies: - clsx: 2.1.1 - clean-css@5.3.3: dependencies: source-map: 0.6.1 @@ -5539,6 +6093,8 @@ snapshots: clone@1.0.4: {} + clsx@1.2.1: {} + clsx@2.1.1: {} co@4.6.0: {} @@ -5559,6 +6115,8 @@ snapshots: color-support@1.1.3: {} + color2k@2.0.3: {} + colord@2.9.3: {} colorette@2.0.20: {} @@ -5567,6 +6125,8 @@ snapshots: dependencies: delayed-stream: 1.0.0 + comma-separated-tokens@2.0.3: {} + commander@12.1.0: {} commander@2.20.3: {} @@ -5675,6 +6235,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-color-keywords@1.0.0: {} + css-declaration-sorter@7.2.0(postcss@8.5.1): dependencies: postcss: 8.5.1 @@ -5718,6 +6280,12 @@ snapshots: domutils: 3.1.0 nth-check: 2.1.1 + css-to-react-native@3.2.0: + dependencies: + camelize: 1.0.1 + css-color-keywords: 1.0.0 + postcss-value-parser: 4.2.0 + css-tree@2.2.1: dependencies: mdn-data: 2.0.28 @@ -5804,6 +6372,10 @@ snapshots: decimal.js@10.4.3: {} + decode-named-character-reference@1.0.2: + dependencies: + character-entities: 2.0.2 + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -5851,6 +6423,8 @@ snapshots: diff@4.0.2: {} + diff@5.2.0: {} + dir-compare@3.3.0: dependencies: buffer-equal: 1.0.1 @@ -6142,6 +6716,8 @@ snapshots: exponential-backoff@3.1.1: {} + extend@3.0.2: {} + extract-zip@2.0.1: dependencies: debug: 4.3.4 @@ -6202,6 +6778,8 @@ snapshots: flat@5.0.2: {} + focus-visible@5.2.1: {} + follow-redirects@1.15.6: {} foreground-child@3.1.1: @@ -6255,6 +6833,8 @@ snapshots: function-bind@1.1.2: {} + fzy.js@0.4.1: {} + gauge@4.0.4: dependencies: aproba: 2.0.0 @@ -6411,8 +6991,14 @@ snapshots: dependencies: function-bind: 1.1.2 + hast-util-whitespace@2.0.1: {} + he@1.2.0: {} + history@5.3.0: + dependencies: + '@babel/runtime': 7.24.1 + hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 @@ -6535,6 +7121,8 @@ snapshots: inherits@2.0.4: {} + inline-style-parser@0.1.1: {} + interpret@3.1.1: {} ip-address@9.0.5: @@ -6548,6 +7136,8 @@ snapshots: dependencies: binary-extensions: 2.3.0 + is-buffer@2.0.5: {} + is-ci@3.0.1: dependencies: ci-info: 3.9.0 @@ -6572,6 +7162,8 @@ snapshots: is-number@7.0.0: {} + is-plain-obj@4.1.0: {} + is-plain-object@2.0.4: dependencies: isobject: 3.0.1 @@ -7072,6 +7664,8 @@ snapshots: kleur@3.0.3: {} + kleur@4.1.5: {} + lazy-val@1.0.5: {} lazystream@1.0.1: @@ -7100,8 +7694,12 @@ snapshots: lodash.flatten@4.4.0: {} + lodash.isempty@4.4.0: {} + lodash.isequal@4.5.0: {} + lodash.isobject@3.0.2: {} + lodash.isplainobject@4.0.6: {} lodash.memoize@4.1.2: {} @@ -7117,6 +7715,10 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + lower-case@2.0.2: dependencies: tslib: 2.6.2 @@ -7176,6 +7778,44 @@ snapshots: escape-string-regexp: 4.0.0 optional: true + mdast-util-definitions@5.1.2: + dependencies: + '@types/mdast': 3.0.15 + '@types/unist': 2.0.11 + unist-util-visit: 4.1.2 + + mdast-util-from-markdown@1.3.1: + dependencies: + '@types/mdast': 3.0.15 + '@types/unist': 2.0.11 + decode-named-character-reference: 1.0.2 + mdast-util-to-string: 3.2.0 + micromark: 3.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-decode-string: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-stringify-position: 3.0.3 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + + mdast-util-to-hast@12.3.0: + dependencies: + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + mdast-util-definitions: 5.1.2 + micromark-util-sanitize-uri: 1.2.0 + trim-lines: 3.0.1 + unist-util-generated: 2.0.1 + unist-util-position: 4.0.4 + unist-util-visit: 4.1.2 + + mdast-util-to-string@3.2.0: + dependencies: + '@types/mdast': 3.0.15 + mdn-data@2.0.28: {} mdn-data@2.0.30: {} @@ -7189,6 +7829,139 @@ snapshots: merge2@1.4.1: {} + micromark-core-commonmark@1.1.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-factory-destination: 1.1.0 + micromark-factory-label: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-factory-title: 1.1.0 + micromark-factory-whitespace: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-html-tag-name: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-factory-destination@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-label@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-factory-space@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-types: 1.1.0 + + micromark-factory-title@1.1.0: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-whitespace@1.1.0: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-character@1.2.0: + dependencies: + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-chunked@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-classify-character@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-combine-extensions@1.1.0: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-decode-numeric-character-reference@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-decode-string@1.1.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 1.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-symbol: 1.1.0 + + micromark-util-encode@1.1.0: {} + + micromark-util-html-tag-name@1.2.0: {} + + micromark-util-normalize-identifier@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-resolve-all@1.1.0: + dependencies: + micromark-util-types: 1.1.0 + + micromark-util-sanitize-uri@1.2.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-encode: 1.1.0 + micromark-util-symbol: 1.1.0 + + micromark-util-subtokenize@1.1.0: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-util-symbol@1.1.0: {} + + micromark-util-types@1.1.0: {} + + micromark@3.2.0: + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.4 + decode-named-character-reference: 1.0.2 + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-combine-extensions: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-encode: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -7271,6 +8044,8 @@ snapshots: mkdirp@1.0.4: {} + mri@1.2.0: {} + ms@2.1.2: {} mz@2.7.0: @@ -7697,6 +8472,12 @@ snapshots: postcss-value-parser@4.2.0: {} + postcss@8.4.38: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.1: dependencies: nanoid: 3.3.8 @@ -7736,8 +8517,16 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + propagate@2.0.1: {} + property-information@6.5.0: {} + proxy-from-env@1.1.0: {} psl@1.9.0: {} @@ -7772,10 +8561,40 @@ snapshots: final-form: 4.20.10 react: 19.0.0 + react-intersection-observer@9.13.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + react: 19.0.0 + optionalDependencies: + react-dom: 19.0.0(react@19.0.0) + + react-is@16.13.1: {} + react-is@17.0.2: {} react-is@18.2.0: {} + react-markdown@8.0.7(@types/react@19.0.7)(react@19.0.0): + dependencies: + '@types/hast': 2.3.10 + '@types/prop-types': 15.7.14 + '@types/react': 19.0.7 + '@types/unist': 2.0.11 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 2.0.1 + prop-types: 15.8.1 + property-information: 6.5.0 + react: 19.0.0 + react-is: 18.2.0 + remark-parse: 10.0.2 + remark-rehype: 10.1.0 + space-separated-tokens: 2.0.2 + style-to-object: 0.4.4 + unified: 10.1.2 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + transitivePeerDependencies: + - supports-color + react-router-dom@7.1.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: react: 19.0.0 @@ -7845,6 +8664,21 @@ snapshots: relateurl@0.2.7: {} + remark-parse@10.0.2: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-from-markdown: 1.3.1 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + + remark-rehype@10.1.0: + dependencies: + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + mdast-util-to-hast: 12.3.0 + unified: 10.1.2 + renderkid@3.0.0: dependencies: css-select: 4.3.0 @@ -7921,6 +8755,10 @@ snapshots: dependencies: tslib: 2.6.2 + sade@1.8.1: + dependencies: + mri: 1.2.0 + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -7983,6 +8821,8 @@ snapshots: dependencies: kind-of: 6.0.3 + shallowequal@1.1.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -8043,6 +8883,8 @@ snapshots: source-map@0.7.4: {} + space-separated-tokens@2.0.2: {} + sprintf-js@1.0.3: {} sprintf-js@1.1.3: {} @@ -8096,12 +8938,48 @@ snapshots: strip-json-comments@3.1.1: {} + style-to-object@0.4.4: + dependencies: + inline-style-parser: 0.1.1 + + styled-components@6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@emotion/is-prop-valid': 1.2.2 + '@emotion/unitless': 0.8.1 + '@types/stylis': 4.2.5 + css-to-react-native: 3.2.0 + csstype: 3.1.3 + postcss: 8.4.38 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + shallowequal: 1.1.0 + stylis: 4.3.2 + tslib: 2.6.2 + + styled-system@5.1.5: + dependencies: + '@styled-system/background': 5.1.2 + '@styled-system/border': 5.1.5 + '@styled-system/color': 5.1.2 + '@styled-system/core': 5.1.2 + '@styled-system/flexbox': 5.1.2 + '@styled-system/grid': 5.1.2 + '@styled-system/layout': 5.1.2 + '@styled-system/position': 5.1.2 + '@styled-system/shadow': 5.1.2 + '@styled-system/space': 5.1.2 + '@styled-system/typography': 5.1.2 + '@styled-system/variant': 5.1.5 + object-assign: 4.1.1 + stylehacks@7.0.4(postcss@8.5.1): dependencies: browserslist: 4.24.2 postcss: 8.5.1 postcss-selector-parser: 6.1.2 + stylis@4.3.2: {} + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -8263,6 +9141,10 @@ snapshots: tree-kill@1.2.2: {} + trim-lines@3.0.1: {} + + trough@2.2.0: {} + truncate-utf8-bytes@1.0.2: dependencies: utf8-byte-length: 1.0.4 @@ -8335,6 +9217,16 @@ snapshots: unicorn-magic@0.1.0: {} + unified@10.1.2: + dependencies: + '@types/unist': 2.0.11 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 5.3.7 + unique-filename@2.0.1: dependencies: unique-slug: 3.0.0 @@ -8343,6 +9235,31 @@ snapshots: dependencies: imurmurhash: 0.1.4 + unist-util-generated@2.0.1: {} + + unist-util-is@5.2.1: + dependencies: + '@types/unist': 2.0.11 + + unist-util-position@4.0.4: + dependencies: + '@types/unist': 2.0.11 + + unist-util-stringify-position@3.0.3: + dependencies: + '@types/unist': 2.0.11 + + unist-util-visit-parents@5.1.3: + dependencies: + '@types/unist': 2.0.11 + unist-util-is: 5.2.1 + + unist-util-visit@4.1.2: + dependencies: + '@types/unist': 2.0.11 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + universalify@0.1.2: {} universalify@0.2.0: {} @@ -8381,6 +9298,13 @@ snapshots: utila@0.4.0: {} + uvu@0.5.6: + dependencies: + dequal: 2.0.3 + diff: 5.2.0 + kleur: 4.1.5 + sade: 1.8.1 + v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.2.0: @@ -8396,6 +9320,18 @@ snapshots: extsprintf: 1.4.1 optional: true + vfile-message@3.1.4: + dependencies: + '@types/unist': 2.0.11 + unist-util-stringify-position: 3.0.3 + + vfile@5.3.7: + dependencies: + '@types/unist': 2.0.11 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.3 + vfile-message: 3.1.4 + w3c-xmlserializer@4.0.0: dependencies: xml-name-validator: 4.0.0 diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 86a47b86d..b885e6aa2 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -6,6 +6,9 @@ import { Routes, useLocation, } from 'react-router-dom'; + +import { BaseStyles, ThemeProvider } from '@primer/react'; + import { Loading } from './components/Loading'; import { Sidebar } from './components/Sidebar'; import { AppContext, AppProvider } from './context/App'; @@ -16,6 +19,7 @@ import { LoginWithOAuthAppRoute } from './routes/LoginWithOAuthApp'; import { LoginWithPersonalAccessTokenRoute } from './routes/LoginWithPersonalAccessToken'; import { NotificationsRoute } from './routes/Notifications'; import { SettingsRoute } from './routes/Settings'; + import './App.css'; function RequireAuth({ children }) { @@ -31,56 +35,60 @@ function RequireAuth({ children }) { export const App = () => { return ( - - -
- - - - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - } /> - } - /> - } - /> - -
-
-
+ + + + +
+ + + + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + } /> + } + /> + } + /> + +
+
+
+
+
); }; diff --git a/src/renderer/__helpers__/jest.setup.ts b/src/renderer/__helpers__/jest.setup.ts index 1fb4bea3f..658eb3613 100644 --- a/src/renderer/__helpers__/jest.setup.ts +++ b/src/renderer/__helpers__/jest.setup.ts @@ -1,11 +1,11 @@ import { TextDecoder, TextEncoder } from 'node:util'; -/** - * Prevent the following errors with jest: - * - ReferenceError: TextEncoder is not defined - * - ReferenceError: TextDecoder is not defined - */ if (!global.TextEncoder || !global.TextDecoder) { + /** + * Prevent the following errors with jest: + * - ReferenceError: TextEncoder is not defined + * - ReferenceError: TextDecoder is not defined + */ global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; } @@ -13,3 +13,20 @@ if (!global.TextEncoder || !global.TextDecoder) { // Mock OAuth client ID and secret process.env.OAUTH_CLIENT_ID = 'FAKE_CLIENT_ID_123'; process.env.OAUTH_CLIENT_SECRET = 'FAKE_CLIENT_SECRET_123'; + +/** + * Primer Setup + */ +if (typeof CSS === 'undefined') { + global.CSS = {} as typeof CSS; +} + +if (!CSS.supports) { + CSS.supports = () => true; +} + +global.ResizeObserver = class { + observe() {} + unobserve() {} + disconnect() {} +}; diff --git a/src/renderer/components/AllRead.test.tsx b/src/renderer/components/AllRead.test.tsx index a818c607e..23afec8c1 100644 --- a/src/renderer/components/AllRead.test.tsx +++ b/src/renderer/components/AllRead.test.tsx @@ -1,5 +1,8 @@ import { render } from '@testing-library/react'; +import { MemoryRouter } from 'react-router-dom'; +import { mockSettings } from '../__mocks__/state-mocks'; import { ensureStableEmojis } from '../__mocks__/utils'; +import { AppContext } from '../context/App'; import { AllRead } from './AllRead'; describe('renderer/components/AllRead.tsx', () => { @@ -7,8 +10,40 @@ describe('renderer/components/AllRead.tsx', () => { ensureStableEmojis(); }); - it('should render itself & its children', () => { - const tree = render(); + it('should render itself & its children - no filters', () => { + const tree = render( + + + + + , + ); + + expect(tree).toMatchSnapshot(); + }); + + it('should render itself & its children - with filters', () => { + const tree = render( + + + + + , + ); expect(tree).toMatchSnapshot(); }); diff --git a/src/renderer/components/AllRead.tsx b/src/renderer/components/AllRead.tsx index 206c31c43..37b08c7db 100644 --- a/src/renderer/components/AllRead.tsx +++ b/src/renderer/components/AllRead.tsx @@ -1,8 +1,18 @@ -import { type FC, useMemo } from 'react'; +import { type FC, useContext, useMemo } from 'react'; + +import { Stack } from '@primer/react'; + +import { AppContext } from '../context/App'; import { Constants } from '../utils/constants'; -import { EmojiText } from './EmojiText'; +import { hasFiltersSet } from '../utils/filters'; +import { Centered } from './primitives/Centered'; +import { EmojiText } from './primitives/EmojiText'; export const AllRead: FC = () => { + const { settings } = useContext(AppContext); + + const hasFilters = hasFiltersSet(settings); + const emoji = useMemo( () => Constants.ALL_READ_EMOJIS[ @@ -12,12 +22,20 @@ export const AllRead: FC = () => { ); return ( -
-
- -
+ + +
+ +
-
No new notifications.
-
+ {hasFilters ? ( +
+ No new filtered notifications +
+ ) : ( +
No new notifications
+ )} + + ); }; diff --git a/src/renderer/components/Header.tsx b/src/renderer/components/Header.tsx deleted file mode 100644 index 3ecddb9e4..000000000 --- a/src/renderer/components/Header.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { ArrowLeftIcon, type Icon } from '@primer/octicons-react'; -import { type FC, useContext } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { AppContext } from '../context/App'; -import { Size } from '../types'; -import { Legend } from './settings/Legend'; - -interface IHeader { - icon: Icon; - children: string; - fetchOnBack?: boolean; -} - -export const Header: FC = (props: IHeader) => { - const navigate = useNavigate(); - - const { fetchNotifications } = useContext(AppContext); - - return ( -
- - -

- {props.children} -

-
- ); -}; diff --git a/src/renderer/components/HoverGroup.tsx b/src/renderer/components/HoverGroup.tsx deleted file mode 100644 index 0d238d381..000000000 --- a/src/renderer/components/HoverGroup.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { FC, ReactNode } from 'react'; - -interface IHoverGroup { - children: ReactNode; -} - -export const HoverGroup: FC = ({ children }: IHoverGroup) => { - return ( -
- {children} -
- ); -}; diff --git a/src/renderer/components/Loading.tsx b/src/renderer/components/Loading.tsx index e008c7fa1..882f085be 100644 --- a/src/renderer/components/Loading.tsx +++ b/src/renderer/components/Loading.tsx @@ -1,5 +1,7 @@ -import NProgress from 'nprogress'; import { type FC, useContext, useEffect } from 'react'; + +import NProgress from 'nprogress'; + import { AppContext } from '../context/App'; export const Loading: FC = () => { diff --git a/src/renderer/components/Oops.tsx b/src/renderer/components/Oops.tsx index 8161eff65..ad543cecd 100644 --- a/src/renderer/components/Oops.tsx +++ b/src/renderer/components/Oops.tsx @@ -1,6 +1,9 @@ import { type FC, useMemo } from 'react'; + +import { Stack } from '@primer/react'; import type { GitifyError } from '../types'; -import { EmojiText } from './EmojiText'; +import { Centered } from './primitives/Centered'; +import { EmojiText } from './primitives/EmojiText'; interface IOops { error: GitifyError; @@ -13,20 +16,22 @@ export const Oops: FC = ({ error }: IOops) => { ); return ( -
-
- -
+ + +
+ +
-
{error.title}
- {error.descriptions.map((description, i) => { - return ( - // biome-ignore lint/suspicious/noArrayIndexKey: using index for key to keep the error constants clean -
- {description} -
- ); - })} -
+
{error.title}
+ {error.descriptions.map((description, i) => { + return ( + // biome-ignore lint/suspicious/noArrayIndexKey: using index for key to keep the error constants clean +
+ {description} +
+ ); + })} + + ); }; diff --git a/src/renderer/components/Sidebar.test.tsx b/src/renderer/components/Sidebar.test.tsx index c3960d25f..cb80eb6e1 100644 --- a/src/renderer/components/Sidebar.test.tsx +++ b/src/renderer/components/Sidebar.test.tsx @@ -3,7 +3,6 @@ import { MemoryRouter } from 'react-router-dom'; import { mockAccountNotifications } from '../__mocks__/notifications-mocks'; import { mockAuth, mockSettings } from '../__mocks__/state-mocks'; import { AppContext } from '../context/App'; -import { IconColor } from '../types'; import * as comms from '../utils/comms'; import { Sidebar } from './Sidebar'; @@ -76,125 +75,36 @@ describe('renderer/components/Sidebar.tsx', () => { , ); - fireEvent.click(screen.getByTitle('Home')); + fireEvent.click(screen.getByTestId('sidebar-home')); expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true }); }); - describe('quick links', () => { - describe('notifications icon', () => { - it('when there are 0 notifications', () => { - render( - - - - - , - ); - - const notificationsIcon = screen.getByTitle('0 unread notifications'); - - expect(notificationsIcon.className).toContain('text-white'); - expect(notificationsIcon.childNodes.length).toBe(1); - expect(notificationsIcon.childNodes[0].nodeName).toBe('svg'); - - fireEvent.click(screen.getByLabelText('0 unread notifications')); - - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/notifications', - ); - }); - - it('when there are more than 0 notifications', () => { - render( - - - - - , - ); - - const notificationsIcon = screen.getByTitle('4 unread notifications'); - - expect(notificationsIcon.className).toContain(IconColor.GREEN); - expect(notificationsIcon.childNodes.length).toBe(2); - expect(notificationsIcon.childNodes[0].nodeName).toBe('svg'); - expect(notificationsIcon.childNodes[1].nodeValue).toBe('4'); - - fireEvent.click(screen.getByLabelText('4 unread notifications')); - - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/notifications', - ); - }); - }); - }); - - it('opens my github issues page', () => { - render( - - - - - , - ); - - fireEvent.click(screen.getByLabelText('My issues')); - - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/issues', - ); - }); - - it('opens my github pull requests page', () => { - render( - - - - - , - ); + describe('notifications icon', () => { + it('opens notifications home when clicked', () => { + render( + + + + + , + ); - fireEvent.click(screen.getByLabelText('My pull requests')); + fireEvent.click(screen.getByTestId('sidebar-notifications')); - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/pulls', - ); - }); + expect(openExternalLinkMock).toHaveBeenCalledTimes(1); + expect(openExternalLinkMock).toHaveBeenCalledWith( + 'https://github.com/notifications', + ); + }); - describe('Refresh Notifications', () => { - it('should refresh the notifications when status is not loading', () => { + it('renders correct icon when there are no notifications', () => { render( { notifications: [], auth: mockAuth, settings: mockSettings, - fetchNotifications, - status: 'success', }} > @@ -212,12 +120,10 @@ describe('renderer/components/Sidebar.tsx', () => { , ); - fireEvent.click(screen.getByTitle('Refresh notifications')); - - expect(fetchNotifications).toHaveBeenCalledTimes(1); + expect(screen.getByTestId('sidebar-notifications')).toMatchSnapshot(); }); - it('should not refresh the notifications when status is loading', () => { + it('renders correct icon when there are notifications', () => { render( { notifications: [], auth: mockAuth, settings: mockSettings, - fetchNotifications, - status: 'loading', }} > @@ -235,13 +139,11 @@ describe('renderer/components/Sidebar.tsx', () => { , ); - fireEvent.click(screen.getByTitle('Refresh notifications')); - - expect(fetchNotifications).not.toHaveBeenCalled(); + expect(screen.getByTestId('sidebar-notifications')).toMatchSnapshot(); }); }); - describe('Filters', () => { + describe('Filter notifications', () => { it('go to the filters route', () => { render( { , ); - fireEvent.click(screen.getByTitle('Filters')); + + fireEvent.click(screen.getByTestId('sidebar-filter-notifications')); + expect(mockNavigate).toHaveBeenNthCalledWith(1, '/filters'); }); @@ -276,18 +180,20 @@ describe('renderer/components/Sidebar.tsx', () => { , ); - fireEvent.click(screen.getByTitle('Filters')); + + fireEvent.click(screen.getByTestId('sidebar-filter-notifications')); + expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true }); }); }); - describe('Settings', () => { - it('go to the settings route', () => { + describe('quick links', () => { + it('opens my github issues page', () => { render( { , ); - fireEvent.click(screen.getByTitle('Settings')); + fireEvent.click(screen.getByTestId('sidebar-my-issues')); - expect(mockNavigate).toHaveBeenNthCalledWith(1, '/settings'); + expect(openExternalLinkMock).toHaveBeenCalledTimes(1); + expect(openExternalLinkMock).toHaveBeenCalledWith( + 'https://github.com/issues', + ); }); - it('go to the home if settings path already shown', () => { + it('opens my github pull requests page', () => { render( - + , ); - fireEvent.click(screen.getByTitle('Settings')); + fireEvent.click(screen.getByTestId('sidebar-my-pull-requests')); - expect(fetchNotifications).toHaveBeenCalledTimes(1); - expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true }); + expect(openExternalLinkMock).toHaveBeenCalledTimes(1); + expect(openExternalLinkMock).toHaveBeenCalledWith( + 'https://github.com/pulls', + ); }); }); - it('opens github in the notifications page', () => { - const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink'); - - render( - - - - - , - ); - fireEvent.click(screen.getByLabelText('4 unread notifications')); - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/notifications', - ); - }); - - it('opens my github issues page', () => { - const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink'); - - render( - - - - - , - ); - fireEvent.click(screen.getByLabelText('My issues')); - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/issues', - ); - }); - - it('opens my github pull requests page', () => { - const openExternalLinkMock = jest.spyOn(comms, 'openExternalLink'); + describe('Refresh Notifications', () => { + it('should refresh the notifications when status is not loading', () => { + render( + + + + + , + ); - render( - - - - - , - ); - fireEvent.click(screen.getByLabelText('My pull requests')); - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - expect(openExternalLinkMock).toHaveBeenCalledWith( - 'https://github.com/pulls', - ); - }); + fireEvent.click(screen.getByTestId('sidebar-refresh')); - it('should quit the app', () => { - const quitAppMock = jest.spyOn(comms, 'quitApp'); + expect(fetchNotifications).toHaveBeenCalledTimes(1); + }); - render( - - - - - , - ); + it('should not refresh the notifications when status is loading', () => { + render( + + + + + , + ); - fireEvent.click(screen.getByTitle('Quit Gitify')); + fireEvent.click(screen.getByTestId('sidebar-refresh')); - expect(quitAppMock).toHaveBeenCalledTimes(1); + expect(fetchNotifications).not.toHaveBeenCalled(); + }); }); - describe('should render the notifications icon', () => { - it('when there are 0 notifications', () => { + describe('Settings', () => { + it('go to the settings route', () => { render( { , ); - const notificationsIcon = screen.getByTitle('0 unread notifications'); - expect(notificationsIcon.className).toContain('text-white'); - expect(notificationsIcon.childNodes.length).toBe(1); - expect(notificationsIcon.childNodes[0].nodeName).toBe('svg'); + fireEvent.click(screen.getByTestId('sidebar-settings')); + + expect(mockNavigate).toHaveBeenNthCalledWith(1, '/settings'); }); - it('when there are more than 0 notifications', () => { + it('go to the home if settings path already shown', () => { render( - + , ); - const notificationsIcon = screen.getByTitle('4 unread notifications'); - expect(notificationsIcon.className).toContain(IconColor.GREEN); - expect(notificationsIcon.childNodes.length).toBe(2); - expect(notificationsIcon.childNodes[0].nodeName).toBe('svg'); - expect(notificationsIcon.childNodes[1].nodeValue).toBe('4'); + fireEvent.click(screen.getByTestId('sidebar-settings')); + + expect(fetchNotifications).toHaveBeenCalledTimes(1); + expect(mockNavigate).toHaveBeenNthCalledWith(1, '/', { replace: true }); }); }); + + it('should quit the app', () => { + const quitAppMock = jest.spyOn(comms, 'quitApp'); + + render( + + + + + , + ); + + fireEvent.click(screen.getByTestId('sidebar-quit')); + + expect(quitAppMock).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/renderer/components/Sidebar.tsx b/src/renderer/components/Sidebar.tsx index 6536d45a6..bb47aca2d 100644 --- a/src/renderer/components/Sidebar.tsx +++ b/src/renderer/components/Sidebar.tsx @@ -1,3 +1,6 @@ +import { type FC, useContext, useMemo } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; + import { BellIcon, FilterIcon, @@ -7,21 +10,19 @@ import { SyncIcon, XCircleIcon, } from '@primer/octicons-react'; -import { type FC, useContext, useMemo } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; +import { IconButton, Stack } from '@primer/react'; + import { APPLICATION } from '../../shared/constants'; import { AppContext } from '../context/App'; -import { Size } from '../types'; import { quitApp } from '../utils/comms'; import { Constants } from '../utils/constants'; -import { getFilterCount } from '../utils/helpers'; +import { hasFiltersSet } from '../utils/filters'; import { openGitHubIssues, openGitHubNotifications, openGitHubPulls, } from '../utils/links'; import { getNotificationCount } from '../utils/notifications'; -import { SidebarButton } from './buttons/SidebarButton'; import { LogoIcon } from './icons/LogoIcon'; export const Sidebar: FC = () => { @@ -67,80 +68,133 @@ export const Sidebar: FC = () => { return getNotificationCount(notifications); }, [notifications]); - const filterCount = useMemo(() => { - return getFilterCount(settings); - }, [settings]); - return ( -
-
- - - openGitHubNotifications(primaryAccountHostname)} - /> - - openGitHubIssues(primaryAccountHostname)} - /> - - openGitHubPulls(primaryAccountHostname)} - /> + navigate('/', { replace: true })} + data-testid="sidebar-home" + /> + + 0 ? 'primary' : 'invisible'} + tooltipDirection="e" + onClick={() => openGitHubNotifications(primaryAccountHostname)} + data-testid="sidebar-notifications" + sx={{ color: 'white' }} + /> + + {/* TODO - explore https://primer.style/components/selectpanel/react/alpha/ for a better UI for filters */} + {isLoggedIn && ( + toggleFilters()} + data-testid="sidebar-filter-notifications" + sx={{ color: 'white' }} + /> + )} + + openGitHubIssues(primaryAccountHostname)} + data-testid="sidebar-my-issues" + sx={{ color: 'white' }} + /> + + openGitHubPulls(primaryAccountHostname)} + data-testid="sidebar-my-pull-requests" + sx={{ color: 'white' }} + /> +
-
+ {isLoggedIn && ( <> - refreshNotifications()} + data-testid="sidebar-refresh" + sx={{ color: 'white' }} /> - toggleFilters()} - /> - - toggleSettings()} + data-testid="sidebar-settings" + sx={{ color: 'white' }} /> )} {!isLoggedIn && ( - quitApp()} + data-testid="sidebar-quit" + sx={{ color: 'white' }} /> )} -
+
); }; diff --git a/src/renderer/components/__snapshots__/AccountNotifications.test.tsx.snap b/src/renderer/components/__snapshots__/AccountNotifications.test.tsx.snap deleted file mode 100644 index 28cfdc05f..000000000 --- a/src/renderer/components/__snapshots__/AccountNotifications.test.tsx.snap +++ /dev/null @@ -1,2575 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderer/components/AccountNotifications.tsx should render itself - account error 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- -
-
- - - - - - -
-
-
-
- - 🔥 - -
-
- Error title -
-
- Error description -
-
-
- , - "container":
-
-
- -
-
- - - - - - -
-
-
-
- - 🔥 - -
-
- Error title -
-
- Error description -
-
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/AccountNotifications.tsx should render itself - group notifications by date 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- -
-
- - - - - - -
-
-
-
- - - - -
-
-
- - gitify-app/notifications-test's avatar - - - gitify-app/notifications-test - -
-
- - I am a robot and this is a test! - - -
-
- -
- Updated -
-
- 8 years ago -
-
- - -
-
-
-
- - - -
-
-
-
- - - - -
-
-
- - gitify-app/notifications-test's avatar - - - gitify-app/notifications-test - -
-
- - Improve the UI - - -
-
-
- -
-
- Authored -
-
- 8 years ago -
-
-
-
-
- - - -
-
-
- , - "container":
-
-
- -
-
- - - - - - -
-
-
-
- - - - -
-
-
- - gitify-app/notifications-test's avatar - - - gitify-app/notifications-test - -
-
- - I am a robot and this is a test! - - -
-
- -
- Updated -
-
- 8 years ago -
-
- - -
-
-
-
- - - -
-
-
-
- - - - -
-
-
- - gitify-app/notifications-test's avatar - - - gitify-app/notifications-test - -
-
- - Improve the UI - - -
-
-
- -
-
- Authored -
-
- 8 years ago -
-
-
-
-
- - - -
-
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/AccountNotifications.tsx should render itself - group notifications by repositories 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- -
-
- - - - - - -
-
-
- Repository Notifications -
-
- , - "container":
-
-
- -
-
- - - - - - -
-
-
- Repository Notifications -
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/AccountNotifications.tsx should render itself - no notifications 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- -
-
- - - - - - -
-
-
-
- - 🎊 - -
-
- No new notifications. -
-
-
- , - "container":
-
-
- -
-
- - - - - - -
-
-
-
- - 🎊 - -
-
- No new notifications. -
-
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/AccountNotifications.tsx should toggle account notifications visibility 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- -
-
- - - - - - -
-
-
-
-
-
- -
-
- - - - - - -
-
-
- Repository Notifications -
-
- , - "container":
-
-
- -
-
- - - - - - -
-
-
- Repository Notifications -
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/src/renderer/components/__snapshots__/AllRead.test.tsx.snap b/src/renderer/components/__snapshots__/AllRead.test.tsx.snap index d3366fcbb..b28381556 100644 --- a/src/renderer/components/__snapshots__/AllRead.test.tsx.snap +++ b/src/renderer/components/__snapshots__/AllRead.test.tsx.snap @@ -1,12 +1,53 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renderer/components/AllRead.tsx should render itself & its children 1`] = ` +exports[`renderer/components/AllRead.tsx should render itself & its children - no filters 1`] = ` { "asFragment": [Function], "baseElement":
+
+
+ + 🎊 + +
+
+ No new notifications +
+
+
+
+ , + "container":
+
+
- No new notifications. + No new notifications +
+
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`renderer/components/AllRead.tsx should render itself & its children - with filters 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
+
+
+ + 🎊 + +
+
+ No new filtered notifications +
, "container":
- - 🎊 - -
-
- No new notifications. +
+ + 🎊 + +
+
+ No new filtered notifications +
, diff --git a/src/renderer/components/__snapshots__/NotificationRow.test.tsx.snap b/src/renderer/components/__snapshots__/NotificationRow.test.tsx.snap deleted file mode 100644 index 448f5cf4f..000000000 --- a/src/renderer/components/__snapshots__/NotificationRow.test.tsx.snap +++ /dev/null @@ -1,1412 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderer/components/NotificationRow.tsx should render itself & its children - group by date 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- - - - -
-
-
- - gitify-app/notifications-test's avatar - - - gitify-app/notifications-test - -
-
- - I am a robot and this is a test! - - -
-
- -
- Updated -
-
- 7 years ago -
-
- - -
-
-
-
- - - -
-
-
- , - "container":
-
-
- - - - -
-
-
- - gitify-app/notifications-test's avatar - - - gitify-app/notifications-test - -
-
- - I am a robot and this is a test! - - -
-
- -
- Updated -
-
- 7 years ago -
-
- - -
-
-
-
- - - -
-
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/NotificationRow.tsx should render itself & its children - group by repositories 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- - - - -
-
-
- - I am a robot and this is a test! - - -
-
- -
- Updated -
-
- 7 years ago -
-
- - -
-
-
-
- - - -
-
-
- , - "container":
-
-
- - - - -
-
-
- - I am a robot and this is a test! - - -
-
- -
- Updated -
-
- 7 years ago -
-
- - -
-
-
-
- - - -
-
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/NotificationRow.tsx should render itself & its children - hide numbers 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- - - - -
-
-
- - I am a robot and this is a test! - -
-
- -
- Updated -
-
- 7 years ago -
-
- - -
-
-
-
- - - -
-
-
- , - "container":
-
-
- - - - -
-
-
- - I am a robot and this is a test! - -
-
- -
- Updated -
-
- 7 years ago -
-
- - -
-
-
-
- - - -
-
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/src/renderer/components/__snapshots__/Oops.test.tsx.snap b/src/renderer/components/__snapshots__/Oops.test.tsx.snap index fba1b4179..2bae40bfd 100644 --- a/src/renderer/components/__snapshots__/Oops.test.tsx.snap +++ b/src/renderer/components/__snapshots__/Oops.test.tsx.snap @@ -6,7 +6,53 @@ exports[`renderer/components/Oops.tsx should render itself & its children 1`] = "baseElement":
+
+
+ + 🔥 + +
+
+ Error title +
+
+ Error description +
+
+
+
+ , + "container":
+
+
- , - "container":
-
-
- - 🔥 - -
-
- Error title -
-
- Error description -
-
, "debug": [Function], "findAllByAltText": [Function], diff --git a/src/renderer/components/__snapshots__/RepositoryNotifications.test.tsx.snap b/src/renderer/components/__snapshots__/RepositoryNotifications.test.tsx.snap deleted file mode 100644 index 310c5f7fc..000000000 --- a/src/renderer/components/__snapshots__/RepositoryNotifications.test.tsx.snap +++ /dev/null @@ -1,920 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderer/components/RepositoryNotifications.tsx should render itself & its children 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- gitify-app/notifications-test's avatar - - gitify-app/notifications-test - -
-
- - - -
-
-
- NotificationRow -
-
- NotificationRow -
-
- , - "container":
-
-
- gitify-app/notifications-test's avatar - - gitify-app/notifications-test - -
-
- - - -
-
-
- NotificationRow -
-
- NotificationRow -
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/RepositoryNotifications.tsx should toggle repository notifications visibility 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- - - gitify-app/notifications-test - -
-
- - - -
-
-
-
-
-
- - - gitify-app/notifications-test - -
-
- - - -
-
-
- NotificationRow -
-
- NotificationRow -
-
- , - "container":
-
-
- - - gitify-app/notifications-test - -
-
- - - -
-
-
- NotificationRow -
-
- NotificationRow -
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/RepositoryNotifications.tsx should use default repository icon when avatar is not available 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
-
-
- - - gitify-app/notifications-test - -
-
- - - -
-
-
- NotificationRow -
-
- NotificationRow -
-
- , - "container":
-
-
- - - gitify-app/notifications-test - -
-
- - - -
-
-
- NotificationRow -
-
- NotificationRow -
-
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/src/renderer/components/__snapshots__/Sidebar.test.tsx.snap b/src/renderer/components/__snapshots__/Sidebar.test.tsx.snap index 35a1f78ee..ef57c69b6 100644 --- a/src/renderer/components/__snapshots__/Sidebar.test.tsx.snap +++ b/src/renderer/components/__snapshots__/Sidebar.test.tsx.snap @@ -1,23 +1,355 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`renderer/components/Sidebar.tsx notifications icon renders correct icon when there are no notifications 1`] = ` + +`; + +exports[`renderer/components/Sidebar.tsx notifications icon renders correct icon when there are notifications 1`] = ` + +`; + exports[`renderer/components/Sidebar.tsx should render itself & its children (logged in) 1`] = ` { "asFragment": [Function], "baseElement":
+
+ + + Home + + + + 4 unread notifications + + + + + +
+
+
+ +
+
+
+ , + "container":
+
+
+
+ + + Home + + + 4 unread notifications + - -
-
+ My issues + -
-
-
- , - "container":
-
-
- - - - + My pull requests + +
+
, @@ -383,18 +631,286 @@ exports[`renderer/components/Sidebar.tsx should render itself & its children (lo "baseElement":
+
+ + + Home + + + + 4 unread notifications + + + + + +
+
+
+ +
+
+
+ , + "container":
+
+
+
+ + + Home + + + 4 unread notifications + - -
-
+ My issues + -
-
-
- , - "container":
-
-
- - - - + My pull requests + +
+
, diff --git a/src/renderer/components/buttons/Button.test.tsx b/src/renderer/components/buttons/Button.test.tsx deleted file mode 100644 index cd6db0f87..000000000 --- a/src/renderer/components/buttons/Button.test.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { MarkGithubIcon } from '@primer/octicons-react'; -import { fireEvent, render, screen } from '@testing-library/react'; -import type { Link } from '../../types'; -import * as comms from '../../utils/comms'; -import { Button, type IButton } from './Button'; - -describe('renderer/components/buttons/Button.tsx', () => { - const openExternalLinkMock = jest - .spyOn(comms, 'openExternalLink') - .mockImplementation(); - - const props: IButton = { - label: 'button', - }; - - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should render without icon', () => { - const tree = render(); - expect(tree).toMatchSnapshot(); - }); - - it('should render with icon', () => { - const tree = render( - , - ); - expect(tree).toMatchSnapshot(); - }); - - it('should render with url', () => { - render( - , - ); - - const buttonElement = screen.getByLabelText('button'); - - fireEvent.click(buttonElement); - expect(openExternalLinkMock).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/renderer/components/buttons/Button.tsx b/src/renderer/components/buttons/Button.tsx deleted file mode 100644 index 0b7e0054a..000000000 --- a/src/renderer/components/buttons/Button.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import type { Icon } from '@primer/octicons-react'; -import { type VariantProps, cva } from 'class-variance-authority'; -import { type ButtonHTMLAttributes, forwardRef } from 'react'; -import { type Link, Size } from '../../types'; -import { cn } from '../../utils/cn'; -import { openExternalLink } from '../../utils/comms'; - -const buttonVariants = cva( - 'ring-offset-background focus-visible:ring-ring inline-flex w-fit items-center justify-center whitespace-nowrap rounded text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', - { - variants: { - variant: { - default: 'bg-gray-300 dark:text-black hover:opacity-90', - destructive: 'bg-red-600 text-white hover:opacity-90', - outline: - 'border-zinc-300 hover:text-inherit dark:hover:text-white border bg-transparent hover:bg-zinc-100 dark:hover:bg-zinc-600', - ghost: 'hover:bg-zinc-100 dark:hover:bg-zinc-600 dark:hover:text-white', - link: 'underline-offset-2 hover:underline', - }, - size: { - default: 'min-w-20 h-10 px-4 py-1', - inline: 'h-5 rounded-md px-2 py-1', - xs: 'h-7 rounded-md px-2 py-1', - sm: 'h-9 rounded-md px-2 py-1', - lg: 'h-11 rounded-md px-8', - icon: 'h-10 w-10', - }, - }, - defaultVariants: { - variant: 'default', - size: 'default', - }, - }, -); - -export interface IButton - extends ButtonHTMLAttributes, - VariantProps { - icon?: { icon: Icon; size?: Size }; - url?: Link; - onClick?: () => void; - label: string; -} - -const Button = forwardRef( - ({ className, variant, size, label, url, onClick, ...props }, ref) => { - return ( - - ); - }, -); -Button.displayName = 'Button'; - -export { Button, buttonVariants }; diff --git a/src/renderer/components/buttons/InteractionButton.test.tsx b/src/renderer/components/buttons/InteractionButton.test.tsx deleted file mode 100644 index 1acc4a087..000000000 --- a/src/renderer/components/buttons/InteractionButton.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { MarkGithubIcon } from '@primer/octicons-react'; -import { render } from '@testing-library/react'; -import { Size } from '../../types'; -import { - type IInteractionButton, - InteractionButton, -} from './InteractionButton'; - -describe('renderer/components/buttons/InteractionButton.tsx', () => { - it('should render', () => { - const props: IInteractionButton = { - title: 'Mock Interaction Button', - icon: MarkGithubIcon, - size: Size.SMALL, - onClick: () => () => {}, - }; - const tree = render(); - expect(tree).toMatchSnapshot(); - }); -}); diff --git a/src/renderer/components/buttons/InteractionButton.tsx b/src/renderer/components/buttons/InteractionButton.tsx deleted file mode 100644 index 94bd9745b..000000000 --- a/src/renderer/components/buttons/InteractionButton.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { Icon } from '@primer/octicons-react'; -import type { FC, MouseEvent } from 'react'; -import type { Size } from '../../types'; - -export interface IInteractionButton { - title: string; - icon: Icon; - size: Size; - onClick: (event?: MouseEvent) => void; -} - -export const InteractionButton: FC = ( - props: IInteractionButton, -) => { - return ( - - ); -}; diff --git a/src/renderer/components/buttons/PillButton.test.tsx b/src/renderer/components/buttons/PillButton.test.tsx index f3ca4cd6b..9d446c4e4 100644 --- a/src/renderer/components/buttons/PillButton.test.tsx +++ b/src/renderer/components/buttons/PillButton.test.tsx @@ -4,7 +4,7 @@ import { IconColor } from '../../types'; import { type IPillButton, PillButton } from './PillButton'; describe('renderer/components/buttons/PillButton.tsx', () => { - it('should render', () => { + it('should render with metric', () => { const props: IPillButton = { title: 'Mock Pill', metric: 1, @@ -14,4 +14,14 @@ describe('renderer/components/buttons/PillButton.tsx', () => { const tree = render(); expect(tree).toMatchSnapshot(); }); + + it('should render without metric', () => { + const props: IPillButton = { + title: 'Mock Pill', + icon: MarkGithubIcon, + color: IconColor.GREEN, + }; + const tree = render(); + expect(tree).toMatchSnapshot(); + }); }); diff --git a/src/renderer/components/buttons/PillButton.tsx b/src/renderer/components/buttons/PillButton.tsx index 0c1be3f29..d9735c2e7 100644 --- a/src/renderer/components/buttons/PillButton.tsx +++ b/src/renderer/components/buttons/PillButton.tsx @@ -1,5 +1,8 @@ -import type { Icon } from '@primer/octicons-react'; import type { FC } from 'react'; + +import type { Icon } from '@primer/octicons-react'; +import { Octicon, Stack, Text } from '@primer/react'; + import { type IconColor, Size } from '../../types'; export interface IPillButton { @@ -15,14 +18,12 @@ export const PillButton: FC = (props: IPillButton) => { ); }; diff --git a/src/renderer/components/buttons/SidebarButton.test.tsx b/src/renderer/components/buttons/SidebarButton.test.tsx deleted file mode 100644 index e3c0f68f0..000000000 --- a/src/renderer/components/buttons/SidebarButton.test.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { MarkGithubIcon } from '@primer/octicons-react'; -import { render } from '@testing-library/react'; -import { Size } from '../../types'; -import { type ISidebarButton, SidebarButton } from './SidebarButton'; - -describe('renderer/components/buttons/SidebarButton.tsx', () => { - it('should render with metric', () => { - const props: ISidebarButton = { - title: 'Mock Sidebar Button', - metric: 1, - icon: MarkGithubIcon, - }; - const tree = render(); - expect(tree).toMatchSnapshot(); - }); - - it('should render without metric', () => { - const props: ISidebarButton = { - title: 'Mock Sidebar Button', - metric: 0, - icon: MarkGithubIcon, - }; - const tree = render(); - expect(tree).toMatchSnapshot(); - }); - - it('should render - with specific size', () => { - const props: ISidebarButton = { - title: 'Mock Sidebar Button', - metric: 0, - icon: MarkGithubIcon, - size: Size.MEDIUM, - }; - const tree = render(); - expect(tree).toMatchSnapshot(); - }); -}); diff --git a/src/renderer/components/buttons/SidebarButton.tsx b/src/renderer/components/buttons/SidebarButton.tsx deleted file mode 100644 index ea9c11398..000000000 --- a/src/renderer/components/buttons/SidebarButton.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import type { Icon } from '@primer/octicons-react'; -import type { FC } from 'react'; -import { IconColor, Size } from '../../types'; -import { cn } from '../../utils/cn'; - -export interface ISidebarButton { - title: string; - metric?: number; - icon: Icon; - onClick?: () => void; - size?: Size; - loading?: boolean; - disabled?: boolean; -} - -export const SidebarButton: FC = (props: ISidebarButton) => { - const hasMetric = props?.metric > 0; - - return ( - - ); -}; diff --git a/src/renderer/components/buttons/__snapshots__/Button.test.tsx.snap b/src/renderer/components/buttons/__snapshots__/Button.test.tsx.snap deleted file mode 100644 index 947b0397a..000000000 --- a/src/renderer/components/buttons/__snapshots__/Button.test.tsx.snap +++ /dev/null @@ -1,185 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderer/components/buttons/Button.tsx should render with icon 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
- -
- , - "container":
- -
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/buttons/Button.tsx should render without icon 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
- -
- , - "container":
- -
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/src/renderer/components/buttons/__snapshots__/InteractionButton.test.tsx.snap b/src/renderer/components/buttons/__snapshots__/InteractionButton.test.tsx.snap deleted file mode 100644 index 6bf8b1322..000000000 --- a/src/renderer/components/buttons/__snapshots__/InteractionButton.test.tsx.snap +++ /dev/null @@ -1,110 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderer/components/buttons/InteractionButton.tsx should render 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
- -
- , - "container":
- -
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/src/renderer/components/buttons/__snapshots__/PillButton.test.tsx.snap b/src/renderer/components/buttons/__snapshots__/PillButton.test.tsx.snap index ea085941b..c0017bb51 100644 --- a/src/renderer/components/buttons/__snapshots__/PillButton.test.tsx.snap +++ b/src/renderer/components/buttons/__snapshots__/PillButton.test.tsx.snap @@ -1,24 +1,72 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renderer/components/buttons/PillButton.tsx should render 1`] = ` +exports[`renderer/components/buttons/PillButton.tsx should render with metric 1`] = ` { "asFragment": [Function], "baseElement":
+
+ , + "container":
+ +
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`renderer/components/buttons/PillButton.tsx should render without metric 1`] = ` +{ + "asFragment": [Function], + "baseElement": +
+
, "container":
, "debug": [Function], diff --git a/src/renderer/components/buttons/__snapshots__/SidebarButton.test.tsx.snap b/src/renderer/components/buttons/__snapshots__/SidebarButton.test.tsx.snap deleted file mode 100644 index d2ff2431a..000000000 --- a/src/renderer/components/buttons/__snapshots__/SidebarButton.test.tsx.snap +++ /dev/null @@ -1,330 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renderer/components/buttons/SidebarButton.tsx should render - with specific size 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
- -
- , - "container":
- -
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/buttons/SidebarButton.tsx should render with metric 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
- -
- , - "container":
- -
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`renderer/components/buttons/SidebarButton.tsx should render without metric 1`] = ` -{ - "asFragment": [Function], - "baseElement": -
- -
- , - "container":
- -
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/src/renderer/components/fields/Checkbox.tsx b/src/renderer/components/fields/Checkbox.tsx index 02b5f549e..923365eba 100644 --- a/src/renderer/components/fields/Checkbox.tsx +++ b/src/renderer/components/fields/Checkbox.tsx @@ -18,7 +18,7 @@ export const Checkbox: FC = (props: ICheckbox) => { = (props: ICheckbox) => {
)} diff --git a/src/renderer/components/fields/RadioGroup.tsx b/src/renderer/components/fields/RadioGroup.tsx index 605b0d2b1..2c60b6b59 100644 --- a/src/renderer/components/fields/RadioGroup.tsx +++ b/src/renderer/components/fields/RadioGroup.tsx @@ -22,7 +22,7 @@ export const RadioGroup: FC = (props: IRadioGroup) => {
-
-
- - +
- - + Enable keyboard shortcut + + + + +
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - +
- - + Use alternate idle icon + + + + +
-
-
-
-
-
- -
+
- Restore settings to their defaults - + +
- -
- + +
+
+ - - - - - + + - - - - + + +
diff --git a/src/renderer/styles/gitify.ts b/src/renderer/styles/gitify.ts deleted file mode 100644 index d6a2e6d47..000000000 --- a/src/renderer/styles/gitify.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const BUTTON_CLASS_NAME = - 'hover:text-gray-500 py-1 px-2 my-1 mx-2 focus:outline-none'; diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 12739bb21..ce08e3729 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -157,12 +157,11 @@ export interface FormattedReason { } export enum IconColor { - GRAY = 'text-gray-500 dark:text-gray-300', - GREEN = 'text-green-500', - PURPLE = 'text-purple-500', - RED = 'text-red-500', - YELLOW = 'text-yellow-500 dark:text-yellow-300', - WHITE = 'text-white', + GRAY = 'text-primer-muted', + GREEN = 'text-primer-open', + PURPLE = 'text-primer-done', + RED = 'text-primer-closed', + YELLOW = 'text-primer-attention', } export enum Opacity { diff --git a/src/renderer/typesGitHub.ts b/src/renderer/typesGitHub.ts index 95e6b2ffc..f2da59075 100644 --- a/src/renderer/typesGitHub.ts +++ b/src/renderer/typesGitHub.ts @@ -248,7 +248,7 @@ export interface Owner { repos_url: Link; events_url: Link; received_events_url: Link; - type: string; + type: UserType; site_admin: boolean; } diff --git a/src/renderer/utils/__snapshots__/icons.test.ts.snap b/src/renderer/utils/__snapshots__/icons.test.ts.snap index 401c10eb5..0eeb80dd5 100644 --- a/src/renderer/utils/__snapshots__/icons.test.ts.snap +++ b/src/renderer/utils/__snapshots__/icons.test.ts.snap @@ -1,31 +1,66 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 1`] = `"text-gray-500 dark:text-gray-300"`; +exports[` 1`] = ` +{ + "$$typeof": Symbol(react.forward_ref), + "render": [Function], +} +`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 2`] = `"text-red-500"`; +exports[` 2`] = ` +{ + "$$typeof": Symbol(react.forward_ref), + "render": [Function], +} +`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 3`] = `"text-gray-500 dark:text-gray-300"`; +exports[` 3`] = ` +{ + "$$typeof": Symbol(react.forward_ref), + "render": [Function], +} +`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 4`] = `"text-green-500"`; +exports[` 4`] = ` +{ + "$$typeof": Symbol(react.forward_ref), + "render": [Function], +} +`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 5`] = `"text-gray-500 dark:text-gray-300"`; +exports[` 5`] = ` +{ + "$$typeof": Symbol(react.forward_ref), + "render": [Function], +} +`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 1`] = `"text-green-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 1`] = `"text-primer-muted"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 2`] = `"text-red-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 2`] = `"text-primer-closed"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 3`] = `"text-purple-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 3`] = `"text-primer-muted"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 4`] = `"text-gray-500 dark:text-gray-300"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 4`] = `"text-primer-open"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 5`] = `"text-purple-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for check suite 5`] = `"text-primer-muted"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 6`] = `"text-gray-500 dark:text-gray-300"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 1`] = `"text-primer-open"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 7`] = `"text-green-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 2`] = `"text-primer-closed"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 8`] = `"text-green-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 3`] = `"text-primer-done"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 9`] = `"text-purple-500"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 4`] = `"text-primer-muted"`; -exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 10`] = `"text-gray-500 dark:text-gray-300"`; +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 5`] = `"text-primer-done"`; + +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 6`] = `"text-primer-muted"`; + +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 7`] = `"text-primer-open"`; + +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 8`] = `"text-primer-open"`; + +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 9`] = `"text-primer-done"`; + +exports[`renderer/utils/icons.ts getNotificationTypeIconColor should format the notification color for state 10`] = `"text-primer-muted"`; diff --git a/src/renderer/utils/filters.test.ts b/src/renderer/utils/filters.test.ts new file mode 100644 index 000000000..3293e62d7 --- /dev/null +++ b/src/renderer/utils/filters.test.ts @@ -0,0 +1,28 @@ +import { defaultSettings } from '../context/App'; +import type { SettingsState } from '../types'; +import { getFilterCount, hasFiltersSet } from './filters'; + +describe('renderer/utils/filters.ts', () => { + it('default filter settings', () => { + expect(getFilterCount(defaultSettings)).toBe(0); + expect(hasFiltersSet(defaultSettings)).toBe(false); + }); + + it('non-default reason filters', () => { + const settings = { + ...defaultSettings, + filterReasons: ['subscribed', 'manual'], + } as SettingsState; + expect(getFilterCount(settings)).toBe(2); + expect(hasFiltersSet(settings)).toBe(true); + }); + + it('non-default bot filters', () => { + const settings = { + ...defaultSettings, + hideBots: true, + } as SettingsState; + expect(getFilterCount(settings)).toBe(1); + expect(hasFiltersSet(settings)).toBe(true); + }); +}); diff --git a/src/renderer/utils/filters.ts b/src/renderer/utils/filters.ts new file mode 100644 index 000000000..921b0e1b8 --- /dev/null +++ b/src/renderer/utils/filters.ts @@ -0,0 +1,23 @@ +import { defaultSettings } from '../context/App'; +import type { SettingsState } from '../types'; + +export function getFilterCount(settings: SettingsState): number { + let count = 0; + + if (settings.filterReasons.length !== defaultSettings.filterReasons.length) { + count += settings.filterReasons.length; + } + + if ( + settings.detailedNotifications && + settings.hideBots !== defaultSettings.hideBots + ) { + count += 1; + } + + return count; +} + +export function hasFiltersSet(settings: SettingsState): boolean { + return getFilterCount(settings) > 0; +} diff --git a/src/renderer/utils/helpers.test.ts b/src/renderer/utils/helpers.test.ts index 8bb76ff99..b1abe7b8f 100644 --- a/src/renderer/utils/helpers.test.ts +++ b/src/renderer/utils/helpers.test.ts @@ -6,9 +6,9 @@ import { ChevronLeftIcon, ChevronRightIcon, } from '@primer/octicons-react'; + import * as logger from '../../shared/logger'; -import { defaultSettings } from '../context/App'; -import type { Hostname, Link, SettingsState } from '../types'; +import type { Hostname, Link } from '../types'; import type { SubjectType } from '../typesGitHub'; import { mockGraphQLResponse, @@ -22,9 +22,9 @@ import { generateGitHubWebUrl, generateNotificationReferrerId, getChevronDetails, - getFilterCount, getPlatformFromHostname, isEnterpriseServerHost, + isNonHumanUser, } from './helpers'; describe('renderer/utils/helpers.ts', () => { @@ -568,28 +568,6 @@ describe('renderer/utils/helpers.ts', () => { }); }); - describe('filter count', () => { - it('default filter settings', () => { - expect(getFilterCount(defaultSettings)).toBe(0); - }); - - it('non-default reason filters', () => { - const settings = { - ...defaultSettings, - filterReasons: ['subscribed', 'manual'], - } as SettingsState; - expect(getFilterCount(settings)).toBe(2); - }); - - it('non-default bot filters', () => { - const settings = { - ...defaultSettings, - hideBots: true, - } as SettingsState; - expect(getFilterCount(settings)).toBe(1); - }); - }); - describe('getChevronDetails', () => { it('should return correct chevron details', () => { expect(getChevronDetails(true, true, 'account')).toEqual({ @@ -608,4 +586,12 @@ describe('renderer/utils/helpers.ts', () => { }); }); }); + + it('isNonHumanUser', () => { + expect(isNonHumanUser('User')).toBe(false); + expect(isNonHumanUser('EnterpriseUserAccount')).toBe(false); + expect(isNonHumanUser('Bot')).toBe(true); + expect(isNonHumanUser('Organization')).toBe(true); + expect(isNonHumanUser('Mannequin')).toBe(true); + }); }); diff --git a/src/renderer/utils/helpers.ts b/src/renderer/utils/helpers.ts index 6954f13e6..c95b8f7ab 100644 --- a/src/renderer/utils/helpers.ts +++ b/src/renderer/utils/helpers.ts @@ -6,9 +6,8 @@ import { import { formatDistanceToNowStrict, parseISO } from 'date-fns'; import { logError, logWarn } from '../../shared/logger'; -import { defaultSettings } from '../context/App'; -import type { Chevron, Hostname, Link, SettingsState } from '../types'; -import type { Notification } from '../typesGitHub'; +import type { Chevron, Hostname, Link } from '../types'; +import type { Notification, UserType } from '../typesGitHub'; import { getHtmlUrl, getLatestDiscussion } from './api/client'; import type { PlatformType } from './auth/types'; import { Constants } from './constants'; @@ -200,23 +199,6 @@ export function formatNotificationUpdatedAt( return ''; } -export function getFilterCount(settings: SettingsState): number { - let count = 0; - - if (settings.filterReasons.length !== defaultSettings.filterReasons.length) { - count += settings.filterReasons.length; - } - - if ( - settings.detailedNotifications && - settings.hideBots !== defaultSettings.hideBots - ) { - count += 1; - } - - return count; -} - export function getChevronDetails( hasNotifications: boolean, isVisible: boolean, @@ -241,3 +223,7 @@ export function getChevronDetails( label: `Show ${type} notifications`, }; } + +export function isNonHumanUser(type: UserType): boolean { + return type === 'Bot' || type === 'Organization' || type === 'Mannequin'; +} diff --git a/src/renderer/utils/icons.test.ts b/src/renderer/utils/icons.test.ts index 825aeac99..4c935f6a1 100644 --- a/src/renderer/utils/icons.test.ts +++ b/src/renderer/utils/icons.test.ts @@ -7,8 +7,10 @@ import type { SubjectType, } from '../typesGitHub'; import { + getAuthMethodIcon, getNotificationTypeIcon, getNotificationTypeIconColor, + getPlatformIcon, getPullRequestReviewIcon, } from './icons'; @@ -19,6 +21,7 @@ describe('renderer/utils/icons.ts', () => { createSubjectMock({ type: 'CheckSuite', state: null }), ).displayName, ).toBe('RocketIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -27,6 +30,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('StopIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -35,6 +39,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('XIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -43,6 +48,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('SkipIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -51,37 +57,45 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('CheckIcon'); + expect( getNotificationTypeIcon(createSubjectMock({ type: 'Commit' })) .displayName, ).toBe('GitCommitIcon'); + expect( getNotificationTypeIcon(createSubjectMock({ type: 'Discussion' })) .displayName, ).toBe('CommentDiscussionIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ type: 'Discussion', state: 'DUPLICATE' }), ).displayName, ).toBe('DiscussionDuplicateIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ type: 'Discussion', state: 'OUTDATED' }), ).displayName, ).toBe('DiscussionOutdatedIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ type: 'Discussion', state: 'RESOLVED' }), ).displayName, ).toBe('DiscussionClosedIcon'); + expect( getNotificationTypeIcon(createSubjectMock({ type: 'Issue' })).displayName, ).toBe('IssueOpenedIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ type: 'Issue', state: 'draft' }), ).displayName, ).toBe('IssueDraftIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -90,6 +104,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('IssueClosedIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -98,6 +113,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('IssueClosedIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -106,6 +122,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('SkipIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -114,10 +131,12 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('IssueReopenedIcon'); + expect( getNotificationTypeIcon(createSubjectMock({ type: 'PullRequest' })) .displayName, ).toBe('GitPullRequestIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -126,6 +145,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('GitPullRequestDraftIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -134,6 +154,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('GitPullRequestClosedIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -142,6 +163,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('GitMergeIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -149,6 +171,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('TagIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -156,6 +179,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('AlertIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -163,6 +187,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('MailIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -170,6 +195,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('AlertIcon'); + expect( getNotificationTypeIcon( createSubjectMock({ @@ -177,6 +203,7 @@ describe('renderer/utils/icons.ts', () => { }), ).displayName, ).toBe('RocketIcon'); + expect(getNotificationTypeIcon(createSubjectMock({})).displayName).toBe( 'QuestionIcon', ); @@ -192,6 +219,7 @@ describe('renderer/utils/icons.ts', () => { }), ), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor( createSubjectMock({ @@ -209,6 +237,7 @@ describe('renderer/utils/icons.ts', () => { }), ), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor( createSubjectMock({ @@ -217,6 +246,7 @@ describe('renderer/utils/icons.ts', () => { }), ), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor( createSubjectMock({ @@ -231,32 +261,41 @@ describe('renderer/utils/icons.ts', () => { expect( getNotificationTypeIconColor(createSubjectMock({ state: 'ANSWERED' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'closed' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'completed' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'draft' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'merged' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor( createSubjectMock({ state: 'not_planned' }), ), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'open' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'reopened' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor(createSubjectMock({ state: 'RESOLVED' })), ).toMatchSnapshot(); + expect( getNotificationTypeIconColor( createSubjectMock({ @@ -359,6 +398,20 @@ describe('renderer/utils/icons.ts', () => { expect(getPullRequestReviewIcon(mockReviewMultipleReviewer)).toBeNull(); }); }); + + describe('getAuthMethodIcon', () => { + expect(getAuthMethodIcon('GitHub App')).toMatchSnapshot(); + + expect(getAuthMethodIcon('OAuth App')).toMatchSnapshot(); + + expect(getAuthMethodIcon('Personal Access Token')).toMatchSnapshot(); + }); + + describe('getPlatformIcon', () => { + expect(getPlatformIcon('GitHub Cloud')).toMatchSnapshot(); + + expect(getPlatformIcon('GitHub Enterprise Server')).toMatchSnapshot(); + }); }); function createSubjectMock(mocks: { diff --git a/src/renderer/utils/icons.ts b/src/renderer/utils/icons.ts index f6ae990bd..8641f913e 100644 --- a/src/renderer/utils/icons.ts +++ b/src/renderer/utils/icons.ts @@ -1,5 +1,6 @@ import { AlertIcon, + AppsIcon, CheckIcon, CommentDiscussionIcon, CommentIcon, @@ -16,10 +17,14 @@ import { IssueDraftIcon, IssueOpenedIcon, IssueReopenedIcon, + KeyIcon, MailIcon, + MarkGithubIcon, type OcticonProps, + PersonIcon, QuestionIcon, RocketIcon, + ServerIcon, SkipIcon, StopIcon, TagIcon, @@ -28,6 +33,7 @@ import { import type { FC } from 'react'; import { IconColor, type PullRequestApprovalIcon } from '../types'; import type { GitifyPullRequestReview, Subject } from '../typesGitHub'; +import type { AuthMethod, PlatformType } from './auth/types'; export function getNotificationTypeIcon(subject: Subject): FC { switch (subject.type) { @@ -152,3 +158,25 @@ export function getPullRequestReviewIcon( return null; } } + +export function getAuthMethodIcon(method: AuthMethod): FC | null { + switch (method) { + case 'GitHub App': + return AppsIcon; + case 'OAuth App': + return PersonIcon; + default: + return KeyIcon; + } +} + +export function getPlatformIcon( + platform: PlatformType, +): FC | null { + switch (platform) { + case 'GitHub Enterprise Server': + return ServerIcon; + default: + return MarkGithubIcon; + } +} diff --git a/src/renderer/utils/theme.test.ts b/src/renderer/utils/theme.test.ts index 441a7131f..9d99370b4 100644 --- a/src/renderer/utils/theme.test.ts +++ b/src/renderer/utils/theme.test.ts @@ -1,5 +1,5 @@ import { Theme } from '../types'; -import { getTheme, setTheme } from './theme'; +import { getColorModeFromTheme, getTheme, setTheme } from './theme'; describe('renderer/utils/theme.ts', () => { const htmlElement = document.createElement('html'); @@ -39,4 +39,10 @@ describe('renderer/utils/theme.ts', () => { setTheme(); expect(getTheme()).toBe(Theme.DARK); }); + + it('should get color mode from theme', () => { + expect(getColorModeFromTheme(Theme.LIGHT)).toBe('light'); + expect(getColorModeFromTheme(Theme.DARK)).toBe('night'); + expect(getColorModeFromTheme(Theme.SYSTEM)).toBe('auto'); + }); }); diff --git a/src/renderer/utils/theme.ts b/src/renderer/utils/theme.ts index 25a261f0d..9cc10a55e 100644 --- a/src/renderer/utils/theme.ts +++ b/src/renderer/utils/theme.ts @@ -1,5 +1,10 @@ +import type { ColorModeWithAuto } from '@primer/react/lib/ThemeProvider'; import { Theme } from '../types'; +// TODO - Replace fully with Octicon primer theme provider +/** + * @deprecated + */ export function getTheme(): Theme { if (document.querySelector('html').classList.contains('dark')) { return Theme.DARK; @@ -8,16 +13,22 @@ export function getTheme(): Theme { return Theme.LIGHT; } +/** + * @deprecated + */ export function setLightMode() { document.querySelector('html').classList.remove('dark'); } +/** + * @deprecated + */ export function setDarkMode() { document.querySelector('html').classList.add('dark'); } -export function setTheme(mode?: Theme) { - switch (mode) { +export function setTheme(theme?: Theme) { + switch (theme) { case Theme.LIGHT: setLightMode(); break; @@ -34,3 +45,14 @@ export function setTheme(mode?: Theme) { } } } + +export function getColorModeFromTheme(theme: Theme): ColorModeWithAuto { + switch (theme) { + case Theme.LIGHT: + return 'light'; + case Theme.DARK: + return 'night'; + default: + return 'auto'; + } +} diff --git a/tailwind.config.ts b/tailwind.config.ts index e27beff2c..676b41d3b 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,4 +1,5 @@ import type { Config } from 'tailwindcss'; +import colors from 'tailwindcss/colors'; const config: Config = { content: ['./src/**/*.js', './src/**/*.ts', './src/**/*.tsx'], @@ -9,11 +10,45 @@ const config: Config = { xxs: '0.625rem', // 10px }, colors: { - gray: { + /** + * Temporary solution until we migrate to using GitHub Primer Design Tokens Directly. + * + * See https://primer.style/foundations/primitives/color + */ + primer: { + attention: '#9a6700', + closed: '#cf222e', + done: '#8250df', + muted: '#59636e', + open: '#1f883d', + }, + gitify: { + background: 'var(--color-gitify-background)', + font: 'var(--color-gitify-font)', + error: colors.red[500], sidebar: '#24292e', - dark: '#161b22', - darker: '#090E15', - darkest: '#000209', + footer: 'var(--color-gitify-footer)', + accounts: { + rest: 'var(--color-gitify-accounts-rest)', + error: 'var(--color-gitify-accounts-error)', + }, + repositories: 'var(--color-gitify-repositories)', + notifications: { + border: 'var(--color-gitify-notifications-border)', + rest: 'var(--color-gitify-notifications-rest)', + hover: 'var(--color-gitify-notifications-hover)', + }, + tooltip: { + icon: colors.blue[500], + popout: 'var(--color-gitify-tooltip-popout)', + }, + link: colors.blue[500], + caution: colors.orange[600], + settings: colors.blue[600], + pill: { + rest: 'var(--color-gitify-pill-rest)', + hover: 'var(--color-gitify-pill-hover)', + }, }, }, }, @@ -21,7 +56,40 @@ const config: Config = { variants: { extend: {}, }, - plugins: [], + plugins: [ + ({ addBase }) => { + addBase({ + ':root': { + '--color-gitify-background': colors.white, + '--color-gitify-font': colors.gray[700], + '--color-gitify-footer': colors.gray[200], + '--color-gitify-accounts-rest': colors.gray[300], + '--color-gitify-accounts-error': colors.red[300], + '--color-gitify-repositories': colors.gray[100], + '--color-gitify-notifications-border': colors.gray[100], + '--color-gitify-notifications-rest': colors.white, + '--color-gitify-notifications-hover': colors.gray[100], + '--color-gitify-tooltip-popout': colors.white, + '--color-gitify-pill-rest': colors.gray[100], + '--color-gitify-pill-hover': colors.gray[200], + }, + '.dark': { + '--color-gitify-background': '#161b22', + '--color-gitify-font': colors.gray[100], + '--color-gitify-footer': '#000209', + '--color-gitify-accounts-rest': '#000209', + '--color-gitify-accounts-error': colors.red[500], + '--color-gitify-repositories': '#090e15', + '--color-gitify-notifications-border': '#090e15', + '--color-gitify-notifications-rest': '#161b22', + '--color-gitify-notifications-hover': '#090e15', + '--color-gitify-tooltip-popout': '#24292e', + '--color-gitify-pill-rest': colors.gray[800], + '--color-gitify-pill-hover': colors.gray[700], + }, + }); + }, + ], }; export default config;