diff --git a/.github/workflows/bundlewatch.yml b/.github/workflows/bundlewatch.yml deleted file mode 100644 index c5435689..00000000 --- a/.github/workflows/bundlewatch.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: BundleWatch -on: - push: - branches: - - main - -jobs: - bundle: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - run: | - npm ci - npm run build - npx bundlewatch --max-size 100kb ./dist/**/*.js - env: - BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }} - CI_REPO_OWNER: cheeaun - CI_REPO_NAME: phanpy - CI_BRANCH_BASE: main - CI_BRANCH: main diff --git a/PRIVACY.MD b/PRIVACY.MD new file mode 100644 index 00000000..a2e9ae4e --- /dev/null +++ b/PRIVACY.MD @@ -0,0 +1,15 @@ +# Privacy Policy + +Phanpy does not collect or process any personal information from its users. The website is used to connect to third-party Mastodon servers that may or may not collect personal information and are not covered by this privacy policy. Each third-party Mastodon server comes equipped with its own privacy policy that can be viewed through that server's website. + +## Hosting + +Phanpy is hosted on [Cloudflare Pages](https://pages.cloudflare.com/) as a static website. Read more about [Cloudflare's privacy policy](https://www.cloudflare.com/privacypolicy/). + +## Error logging + +Phanpy dev site (*dev.phanpy.social*) uses [Rollbar](https://rollbar.com/) to log errors for debugging purposes. Read more about [Rollbar's privacy policy](https://rollbar.com/privacy/). The production site (*phanpy.social*) does not use error logging. + +## Analytics + +Phanpy uses [Cloudflare Web Analytics](https://www.cloudflare.com/web-analytics/) to collect anonymous usage statistics. Read more about [Cloudflare's privacy policy](https://www.cloudflare.com/privacypolicy/). diff --git a/README.md b/README.md index e24016ee..62500f20 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ This is an alternative web client for [Mastodon](https://joinmastodon.org/). - may break more often - may be fixed much faster too +🐘 Follow [@phanpy on Mastodon](https://hachyderm.io/@phanpy) for updates ✨ + Everything is designed and engineered for my own use case, following my taste and vision. This is a personal side project for me to learn about Mastodon and experiment with new UI/UX ideas. 🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 @@ -62,6 +64,7 @@ Prerequisites: Node.js 18+ - [Vite](https://vitejs.dev/) - Build tool - [Preact](https://preactjs.com/) - UI library - [Valtio](https://valtio.pmnd.rs/) - State management +- [React Router](https://reactrouter.com/) - Routing - [masto.js](https://github.com/neet/masto.js/) - Mastodon API client - [Iconify](https://iconify.design/) - Icon library - Vanilla CSS - *Yes, I'm old school.* @@ -90,14 +93,14 @@ And here I am. Building a Mastodon web client. ## Alternative web clients -- [Pinafore](https://pinafore.social/) ([retired](https://nolanlawson.com/2023/01/09/retiring-pinafore/)) +- [Pinafore](https://pinafore.social/) ([retired](https://nolanlawson.com/2023/01/09/retiring-pinafore/)) → [Semaphore](https://semaphore.social/) - [Cuckoo+](https://www.cuckoo.social/) - [Sengi](https://nicolasconstant.github.io/sengi/) - [Soapbox](https://fe.soapbox.pub/) - [Elk](https://elk.zone/) - [Mastodeck](https://mastodeck.com/) - [Tooty](https://github.com/n1k0/tooty) -- [More...](https://github.com/tleb/awesome-mastodon#clients) +- [More...](https://github.com/hueyy/awesome-mastodon/#clients) ## License diff --git a/index.html b/index.html index 4b81bc0e..a18f8685 100644 --- a/index.html +++ b/index.html @@ -45,62 +45,5 @@
- - - - - - - - - - - - diff --git a/package-lock.json b/package-lock.json index 7606458b..36ae48bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,32 +10,34 @@ "dependencies": { "@github/text-expander-element": "~2.3.0", "@iconify-icons/mingcute": "~1.2.3", + "@szhsin/react-menu": "~3.4.0", "dayjs": "~1.11.7", "dayjs-twitter": "~0.5.0", "fast-blurhash": "~1.1.2", "fast-deep-equal": "~3.1.3", - "history": "~5.3.0", "idb-keyval": "~6.2.0", "just-debounce-it": "~3.2.0", - "masto": "~5.5.0", + "masto": "~5.7.0", "mem": "~9.0.2", + "p-retry": "~5.1.2", "preact": "~10.11.3", - "preact-router": "~4.1.0", - "react-hotkeys-hook": "~4.3.2", + "react-hotkeys-hook": "~4.3.3", "react-intersection-observer": "~9.4.1", + "react-router-dom": "6.6.2", "string-length": "~5.0.1", "swiped-events": "~1.1.7", "toastify-js": "~1.12.0", "uid": "~2.0.1", + "use-debounce": "~9.0.3", "use-resize-observer": "~9.1.0", "valtio": "~1.9.0" }, "devDependencies": { "@preact/preset-vite": "~2.5.0", "@trivago/prettier-plugin-sort-imports": "~4.0.0", - "autoprefixer": "~10.4.13", "postcss": "~8.4.21", "postcss-dark-theme-class": "~0.7.3", + "postcss-preset-env": "~8.0.1", "twitter-text": "~3.1.0", "vite": "~4.0.4", "vite-plugin-html-config": "~1.0.11", @@ -1653,6 +1655,7 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "dev": true, "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -1709,6 +1712,448 @@ "node": ">=6.9.0" } }, + "node_modules/@csstools/cascade-layer-name-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.1.tgz", + "integrity": "sha512-SAAi5DpgJJWkfTvWSaqkgyIsTawa83hMwKrktkj6ra2h+q6ZN57vOGZ6ySHq6RSo+CbP64fA3aPChPBRDDUgtw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.0.1.tgz", + "integrity": "sha512-B9/8PmOtU6nBiibJg0glnNktQDZ3rZnGn/7UmDfrm2vMtrdlXO3p7ErE95N0up80IRk9YEtB5jyj/TmQ1WH3dw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.0.0" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.0.1.tgz", + "integrity": "sha512-sYD3H7ReR88S/4+V5VbKiBEUJF4FqvG+8aNJkxqoPAnbhFziDG22IDZc4+h+xA63SfgM+h15lq5OnLeCxQ9nPA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.1.tgz", + "integrity": "sha512-X2/OuzEbjaxhzm97UJ+95GrMeT29d1Ib+Pu+paGLuRWZnWRK9sI9r3ikmKXPWGA1C4y4JEdBEFpp9jEqCvLeRA==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0" + } + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-3.0.1.tgz", + "integrity": "sha512-dD8W98dOYNOH/yX4V4HXOhfCOnvVAg8TtsL+qCGNoKXuq5z2C/d026wGWgySgC8cajXXo/wNezS31Glj5GcqrA==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-2.0.1.tgz", + "integrity": "sha512-d7379loVBgIiKTQMOUduUctq3CWMeqNpGkLhzuejvuGyA+bWYT1p7n2GzmIwgXwP0CF8DIFtDgvrsvHn3i+tWw==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-2.0.1.tgz", + "integrity": "sha512-NRwT5g/L+lDkridDiHfjNGyHvdSHJOdcXPPZXZOpSfr/AwRxTJ+wsbKAzyBb1stalkr9KjICDr+ofpkk96r0Wg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-2.0.1.tgz", + "integrity": "sha512-IYoJZ/lDgbXr5iRxlIYdTirWRerrcpezfpP6Xr+bfu8KJRgSMQVOxmXpfJwEXQuTBiX+DyVcAz+IbDdOexHq9g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-2.0.1.tgz", + "integrity": "sha512-718aUIKZJDkbQrINOv6B0I70EZpTB9LzPykGVE/U3gnlXc4tjgvr6/r/G3Hopyn1D5R4BJYcMPI06tVzAgLSMQ==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-3.0.1.tgz", + "integrity": "sha512-N0GC8eRkHDsI8Y3AZ6HLJol1YANNk8PFWsUHOzuDkQW0zbrPL9arYpPTw4cr8yq0rkY/9TRaBDU74QA4ULmKHQ==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-float-and-clear": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-1.0.1.tgz", + "integrity": "sha512-eO9z2sMLddvlfFEW5Fxbjyd03zaO7cJafDurK4rCqyRt9P7aaWwha0LcSzoROlcZrw1NBV2JAp2vMKfPMQO1xw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-resize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-1.0.1.tgz", + "integrity": "sha512-x1ge74eCSvpBkDDWppl+7FuD2dL68WP+wwP2qvdUcKY17vJksz+XoE1ZRV38uJgS6FNUwC0AxrPW5gy3MxsDHQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-logical-viewport-units": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-1.0.2.tgz", + "integrity": "sha512-nnKFywBqRMYjv5jyjSplD/nbAnboUEGFfdxKw1o34Y1nvycgqjQavhKkmxbORxroBBIDwC5y6SfgENcPPUcOxQ==", + "dev": true, + "dependencies": { + "@csstools/css-tokenizer": "^2.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-1.0.1.tgz", + "integrity": "sha512-V9yQqXdje6OfqDf6EL5iGOpi6N0OEczwYK83rql9UapQwFEryXlAehR5AqH8QqLYb6+y31wUXK6vMxCp0920Zg==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "@csstools/media-query-list-parser": "^2.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-2.0.1.tgz", + "integrity": "sha512-6C5yoF99zFb/C2Sa9Y5V0Y/2dnrjK5xe+h59L0LfdVhfanmJPrttwmfTua9etFRA1TGV46aoVMLEZ1NoHjWikg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-2.0.1.tgz", + "integrity": "sha512-TQT5g3JQ5gPXC239YuRK8jFceXF9d25ZvBkyjzBGGoW5st5sPXFVQS8OjYb9IJ/K3CdfK4528y483cgS2DJR/w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-2.0.1.tgz", + "integrity": "sha512-MTj3w6G1TYW0k43sXjw25fY/S+LHXpFIym5NW0oO/hjHFzuz5Uwz93aUvdo/UrrFmxSQeQAYCxmq6NlH3Pf1Hw==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-2.0.1.tgz", + "integrity": "sha512-ImgaFLEOhH/EdcrqDF8GSYSlsVR8EQBJ1p9ZhzoHgDkL7/uuzvSZOlRw5dFGFGnjdi7EXK4gsUjy2HU7ChHh3w==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-scope-pseudo-class": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-2.0.1.tgz", + "integrity": "sha512-wf2dcsqSQlBHc4HMMqdXdxDx4uYuqH+L08kKj+pmT+743C06STcUEu7ORFFEnqGWlOJ1kmA5BJ3pQU0EdMuA+w==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-2.0.1.tgz", + "integrity": "sha512-VimD+M69GsZF/XssivjUwo6jXLgi86ar/gRSH7bautnCULSLxCr/HuY32N4rLRUr7qWF8oF/JTv06ceb66Q1jA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-2.1.0.tgz", + "integrity": "sha512-ARU7Oh9nplxt99cDONVrDt/c1osWRCtgAzegtvmkn6ed7wfmjeNOlXogK1SlAIfHl6X116kPTuFL7vuyDmlPQw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-2.0.1.tgz", + "integrity": "sha512-uGmmVWGHozyWe6+I4w321fKUC034OB1OYW0ZP4ySHA23n+r9y93K+1yrmW+hThpSfApKhaWySoD4I71LLlFUYQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-2.0.1.tgz", + "integrity": "sha512-oJ9Xl29/yU8U7/pnMJRqAZd4YXNCfGEdcP4ywREuqm/xMqcgDNDppYRoCGDt40aaZQIEKBS79LytUDN/DHf0Ew==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz", + "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4", + "postcss-selector-parser": "^6.0.10" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.16.7", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.7.tgz", @@ -2276,6 +2721,14 @@ "vite": ">=2.0.0-beta.3" } }, + "node_modules/@remix-run/router": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.2.1.tgz", + "integrity": "sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ==", + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/plugin-replace": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz", @@ -2356,6 +2809,19 @@ "string.prototype.matchall": "^4.0.6" } }, + "node_modules/@szhsin/react-menu": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-3.4.0.tgz", + "integrity": "sha512-BRxUF3BNmaQzL1z8UkS/eNFj+5ZPjBOpsYWP/ZtrzHNkkP6hUc+tYerBV4dwFiGYmWzkxyOP44ISn+EujwPpUw==", + "dependencies": { + "prop-types": "^15.7.2", + "react-transition-state": "^1.1.5" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.0.0.tgz", @@ -2516,6 +2982,11 @@ "@types/node": "*" } }, + "node_modules/@types/retry": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + }, "node_modules/@types/trusted-types": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", @@ -3015,6 +3486,84 @@ "node": ">=8" } }, + "node_modules/css-blank-pseudo": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-5.0.1.tgz", + "integrity": "sha512-uEWT+613bR0lxUAz7BDdk4yZJ1BfzIJ9rmyOFj+p53ZP8rm0BC3nA2YsyswyxjFZsrfRDxe2WERDfKiEZNSXag==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-has-pseudo": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-5.0.1.tgz", + "integrity": "sha512-zhsGCKVkBohliMlcsZsv5WF/i4FQ3pkVMtl4yYa7Qpv/PVQebTjh7cjMoT5grW+DBZzunmgHe6skdWawgCYuPQ==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.1", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-8.0.1.tgz", + "integrity": "sha512-RPRyqJsk5KIjP2+WGhcGCaAJB8ojLbX1mVE8fG9127jQmnp1FNMfNMkERk/w6c4smgC/i5KxcY+Rtaa6/bMdKQ==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/cssdb": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.4.1.tgz", + "integrity": "sha512-0Q8NOMpXJ3iTDDbUv9grcmQAfdDx4qz+fN/+Md2FGbevT+6+bJNQ2LjB2YIUlLbpBTM32idU1Sb+tb/uGt6/XQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/dayjs": { "version": "1.11.7", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", @@ -3607,14 +4156,6 @@ "tslib": "^2.0.3" } }, - "node_modules/history": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", - "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", - "dependencies": { - "@babel/runtime": "^7.7.6" - } - }, "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -4130,7 +4671,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -4178,9 +4718,9 @@ } }, "node_modules/masto": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/masto/-/masto-5.5.0.tgz", - "integrity": "sha512-EmAe76vYSR9tmUBiOqG7PwbrNFMVXaH7ce1LAr09MuXoS9RZfdEA4y7y3G0VhwTr4mGwnvWJu203CgAae7ZTEg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/masto/-/masto-5.7.0.tgz", + "integrity": "sha512-oCVReGLR9AoBSkShVgWrPb69xzfCpogiPH9wVT9AnPbM+CvjIqJuSaD1xgaEUi6jo66XGbhTC6UerSCVqq9emg==", "dependencies": { "@mastojs/ponyfills": "^1.0.4", "change-case": "^4.1.2", @@ -4370,6 +4910,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -4422,6 +4970,21 @@ "node": ">=4" } }, + "node_modules/p-retry": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-5.1.2.tgz", + "integrity": "sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==", + "dependencies": { + "@types/retry": "0.12.1", + "retry": "^0.13.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -4506,6 +5069,163 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.1.tgz", + "integrity": "sha512-XNVoIdu/Pskb5OhkM+iHicEVuASeqAjOTCaW8Wcbrd1UVwRukOJr5+zWzFjYxJj55Z/67ViVm9n/1hwF7MGByQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-5.0.1.tgz", + "integrity": "sha512-Q9YDNQddKrl6YBs3229v+ckQINLyAaPfjJqG3jp5NUlP0UMm9+JeuLO1IMpeZy0l+rIE64y4OjUq0o+xhrnnrA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.1.tgz", + "integrity": "sha512-1ZTJvmOZXTCsedKeY+Puqwx6AgoyB1KnzSD/CGDIl1NWvDfxi1jYky4R9konw2SAYw0SOeU33EU27ihE59Fp8Q==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-8.0.1.tgz", + "integrity": "sha512-bzZYxBDx/uUGW9HeldOA7J69GdymOZJNz3pG8av27YSgJt9dobl4l+hI/3KAosoRJml/iWceT97pJQj3O/dQDw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-media": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-9.1.1.tgz", + "integrity": "sha512-veQwzQkHgBkizxYCV/EBsiK8sFIJA0oQMQL9mpQ3gqFGc2dWlNWURHk4J44i9Q0dFeFCK81vV/Xpj7fyfNQKSA==", + "dev": true, + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.0", + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "@csstools/media-query-list-parser": "^2.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-properties": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.1.1.tgz", + "integrity": "sha512-FK4dBiHdzWOosLu3kEAHaYpfcrnMfVV4nP6PT6EFIfWXrtHH9LY8idfTYnEDpq/vgE33mr8ykhs7BjlgcT9agg==", + "dev": true, + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.0", + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.1.tgz", + "integrity": "sha512-CPs3BSdQfKqdrJ3d+3In9ppBPA8GpRy4Bd50jU+BDD6WEZOx8TTIB9i67BfRc2AVEAbRZwDMesreF95598dwhw==", + "dev": true, + "dependencies": { + "@csstools/cascade-layer-name-parser": "^1.0.0", + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "node_modules/postcss-dark-theme-class": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-0.7.3.tgz", @@ -4522,6 +5242,407 @@ "postcss": "^8.2.14" } }, + "node_modules/postcss-dir-pseudo-class": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-7.0.1.tgz", + "integrity": "sha512-VjiqVOTz1op7bsiw7qd5CjZ0txA5yJY/oo1wb3f37qdleRTZQ9hzhAtLDqXimn0ZKh9XbtYawc4pmVBnV+LyMA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-4.0.1.tgz", + "integrity": "sha512-XE+eKvX96E9cmldwKeRmK8AMxfQfuuHN9Yjerymau5i+fgC/vEY+B+Ke2vnEv4E8EXu8MKdLxi4DzmodusW19Q==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-8.0.1.tgz", + "integrity": "sha512-azd1NMrLBe5bfKyomui9AMcgIR2zzlqXCTnKjshNDSClmmSO5MauTyflJUqmIwjIhD16+FbPyGV8Nxsly87BjA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-7.0.1.tgz", + "integrity": "sha512-iSpk018Yqn0xwltFR7NHjagyt+e/6u8w50uEnGOcFOddLay5zQFjpJBg6euEZu7wY5WDq83DPpdO99eL+8Er8g==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-4.0.1.tgz", + "integrity": "sha512-V5OuQGw4lBumPlwHWk/PRfMKjaq/LTGR4WDTemIMCaMevArVfCCA9wBJiL1VjDAd+rzuCIlkRoRvDsSiAaZ4Fg==", + "dev": true, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-image-set-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-5.0.1.tgz", + "integrity": "sha512-JnmN9Wo7WjlvM7fg00wzC4d/1kOqau+6v6hteLLqEyBjCuzoFZUU0Te3JphDyxc65RtPNsCujDwYbbs6+vYxCQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-lab-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-5.0.1.tgz", + "integrity": "sha512-TuvrxsRIA3oWjjjI9T1ZEAolrtrLzYwYDw14GFivy0BkRqUTi4IithbM1aZkZGbAxV4lLwD6rL7MHhfDslUEzg==", + "dev": true, + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-logical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-6.0.1.tgz", + "integrity": "sha512-0LIzRgbT42n0q8txcM9SrLkYLjr1LTbRTy80bnKiYXY8tnYGdjkBymwb5XE87o4csW1z8dhKD1VRI6cHBQBQtw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nesting": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-11.0.1.tgz", + "integrity": "sha512-p/XiegrifL9CBwBiuJtFuUUvp8AgmxdyjNagmIjLEyJDUuo0JwbEgUsnQ99SzE7TRRXqXml7BFXkZpRhonE8rQ==", + "dev": true, + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "dev": true, + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-4.0.1.tgz", + "integrity": "sha512-HQZ0qi/9iSYHW4w3ogNqVNr2J49DHJAl7r8O2p0Meip38jsdnRPgiDW7r/LlLrrMBMe3KHkvNtAV2UmRVxzLIg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-8.0.1.tgz", + "integrity": "sha512-Ow2LedN8sL4pq8ubukO77phSVt4QyCm35ZGCYXKvRFayAwcpgB0sjNJglDoTuRdUL32q/ZC1VkPBo0AOEr4Uiw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-8.0.1.tgz", + "integrity": "sha512-IUbymw0JlUbyVG+I85963PNWgPp3KhnFa1sxU7M/2dGthxV8e297P0VV5W9XcyypoH4hirH2fp1c6fmqh6YnSg==", + "dev": true, + "dependencies": { + "@csstools/postcss-cascade-layers": "^3.0.0", + "@csstools/postcss-color-function": "^2.0.0", + "@csstools/postcss-font-format-keywords": "^2.0.0", + "@csstools/postcss-hwb-function": "^2.0.0", + "@csstools/postcss-ic-unit": "^2.0.0", + "@csstools/postcss-is-pseudo-class": "^3.0.0", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.0", + "@csstools/postcss-nested-calc": "^2.0.0", + "@csstools/postcss-normalize-display-values": "^2.0.0", + "@csstools/postcss-oklab-function": "^2.0.0", + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "@csstools/postcss-scope-pseudo-class": "^2.0.0", + "@csstools/postcss-stepped-value-functions": "^2.0.0", + "@csstools/postcss-text-decoration-shorthand": "^2.0.0", + "@csstools/postcss-trigonometric-functions": "^2.0.0", + "@csstools/postcss-unset-value": "^2.0.0", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^5.0.0", + "css-has-pseudo": "^5.0.0", + "css-prefers-color-scheme": "^8.0.0", + "cssdb": "^7.4.0", + "postcss-attribute-case-insensitive": "^6.0.0", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^5.0.0", + "postcss-color-hex-alpha": "^9.0.0", + "postcss-color-rebeccapurple": "^8.0.0", + "postcss-custom-media": "^9.1.0", + "postcss-custom-properties": "^13.1.0", + "postcss-custom-selectors": "^7.1.0", + "postcss-dir-pseudo-class": "^7.0.0", + "postcss-double-position-gradients": "^4.0.0", + "postcss-focus-visible": "^8.0.0", + "postcss-focus-within": "^7.0.0", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^4.0.0", + "postcss-image-set-function": "^5.0.0", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^5.0.0", + "postcss-logical": "^6.0.0", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^11.0.0", + "postcss-opacity-percentage": "^1.1.3", + "postcss-overflow-shorthand": "^4.0.0", + "postcss-page-break": "^3.0.4", + "postcss-place": "^8.0.0", + "postcss-pseudo-class-any-link": "^8.0.0", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^7.0.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-8.0.1.tgz", + "integrity": "sha512-CYcLGofbGDhx6BmNFQGFH0cqW+qlXVk9PR4LZ8Y7g24m6TopYKt6FSwhMGAIyme6lQxgB32XMhpYRwZAcPnMXA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.1.tgz", + "integrity": "sha512-1zT5C27b/zeJhchN7fP0kBr16Cc61mu7Si9uWWLoA3Px/D9tIJPKchJCkUH3tPO5D0pCFmGeApAv8XpXBQJ8SQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -4537,14 +5658,6 @@ "url": "https://opencollective.com/preact" } }, - "node_modules/preact-router": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.0.tgz", - "integrity": "sha512-y1w2YvVpKAju9FMV+fAVR1NpH4MW5q07BZrziMZeg6F/rGJ9KvLUZtjOqsy2I8fDYiX36AM1AQTXIIK3jigBhA==", - "peerDependencies": { - "preact": ">=10" - } - }, "node_modules/prettier": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", @@ -4573,6 +5686,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/proxy-compare": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.4.0.tgz", @@ -4656,9 +5779,9 @@ } }, "node_modules/react-hotkeys-hook": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.3.2.tgz", - "integrity": "sha512-ZA/li3kBDHuRTtJIf7Td41UU87bPtnt9xV4r+PlEzpnFoYRDVspk3B+mlaX75zowyQygMVmoaWnM4B88lkyExQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.3.3.tgz", + "integrity": "sha512-OYZCG2G+xLeiH0TkrW+v6eKFPvYq9iCA5sh9pwvnbGQaK86Lw/kWJDjjzSksFJoCk4K78OLe3MR1afNZH6+cLg==", "peerDependencies": { "react": ">=16.8.1", "react-dom": ">=16.8.1" @@ -4672,6 +5795,50 @@ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.6.2.tgz", + "integrity": "sha512-uJPG55Pek3orClbURDvfljhqFvMgJRo59Pktywkk8hUUkTY2aRfza8Yhl/vZQXs+TNQyr6tu+uqz/fLxPICOGQ==", + "dependencies": { + "@remix-run/router": "1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.6.2.tgz", + "integrity": "sha512-6SCDXxRQqW5af8ImOqKza7icmQ47/EMbz572uFjzvcArg3lZ+04PxSPp8qGs+p2Y+q+b+S/AjXv8m8dyLndIIA==", + "dependencies": { + "@remix-run/router": "1.2.1", + "react-router": "6.6.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-transition-state": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/react-transition-state/-/react-transition-state-1.1.5.tgz", + "integrity": "sha512-ITY2mZqc2dWG2eitJkYNdcSFW8aKeOlkL2A/vowRrLL8GH3J6Re/SpD/BLvQzrVOTqjsP0b5S9N10vgNNzwMUQ==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -4693,7 +5860,8 @@ "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true }, "node_modules/regenerator-transform": { "version": "0.15.1", @@ -4791,6 +5959,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5369,6 +6545,17 @@ "punycode": "^2.1.0" } }, + "node_modules/use-debounce": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.3.tgz", + "integrity": "sha512-FhtlbDtDXILJV7Lix5OZj5yX/fW1tzq+VrvK1fnT2bUrPOGruU9Rw8NCEn+UI9wopfERBEZAOQ8lfeCJPllgnw==", + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/use-resize-observer": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", @@ -5389,6 +6576,12 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/valtio": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.9.0.tgz", @@ -7013,6 +8206,7 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz", "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==", + "dev": true, "requires": { "regenerator-runtime": "^0.13.11" } @@ -7057,6 +8251,214 @@ "to-fast-properties": "^2.0.0" } }, + "@csstools/cascade-layer-name-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-1.0.1.tgz", + "integrity": "sha512-SAAi5DpgJJWkfTvWSaqkgyIsTawa83hMwKrktkj6ra2h+q6ZN57vOGZ6ySHq6RSo+CbP64fA3aPChPBRDDUgtw==", + "dev": true, + "requires": {} + }, + "@csstools/css-parser-algorithms": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.0.1.tgz", + "integrity": "sha512-B9/8PmOtU6nBiibJg0glnNktQDZ3rZnGn/7UmDfrm2vMtrdlXO3p7ErE95N0up80IRk9YEtB5jyj/TmQ1WH3dw==", + "dev": true, + "requires": {} + }, + "@csstools/css-tokenizer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.0.1.tgz", + "integrity": "sha512-sYD3H7ReR88S/4+V5VbKiBEUJF4FqvG+8aNJkxqoPAnbhFziDG22IDZc4+h+xA63SfgM+h15lq5OnLeCxQ9nPA==", + "dev": true + }, + "@csstools/media-query-list-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.0.1.tgz", + "integrity": "sha512-X2/OuzEbjaxhzm97UJ+95GrMeT29d1Ib+Pu+paGLuRWZnWRK9sI9r3ikmKXPWGA1C4y4JEdBEFpp9jEqCvLeRA==", + "dev": true, + "requires": {} + }, + "@csstools/postcss-cascade-layers": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-3.0.1.tgz", + "integrity": "sha512-dD8W98dOYNOH/yX4V4HXOhfCOnvVAg8TtsL+qCGNoKXuq5z2C/d026wGWgySgC8cajXXo/wNezS31Glj5GcqrA==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-color-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-2.0.1.tgz", + "integrity": "sha512-d7379loVBgIiKTQMOUduUctq3CWMeqNpGkLhzuejvuGyA+bWYT1p7n2GzmIwgXwP0CF8DIFtDgvrsvHn3i+tWw==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-font-format-keywords": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-2.0.1.tgz", + "integrity": "sha512-NRwT5g/L+lDkridDiHfjNGyHvdSHJOdcXPPZXZOpSfr/AwRxTJ+wsbKAzyBb1stalkr9KjICDr+ofpkk96r0Wg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-hwb-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-2.0.1.tgz", + "integrity": "sha512-IYoJZ/lDgbXr5iRxlIYdTirWRerrcpezfpP6Xr+bfu8KJRgSMQVOxmXpfJwEXQuTBiX+DyVcAz+IbDdOexHq9g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-ic-unit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-2.0.1.tgz", + "integrity": "sha512-718aUIKZJDkbQrINOv6B0I70EZpTB9LzPykGVE/U3gnlXc4tjgvr6/r/G3Hopyn1D5R4BJYcMPI06tVzAgLSMQ==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-is-pseudo-class": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-3.0.1.tgz", + "integrity": "sha512-N0GC8eRkHDsI8Y3AZ6HLJol1YANNk8PFWsUHOzuDkQW0zbrPL9arYpPTw4cr8yq0rkY/9TRaBDU74QA4ULmKHQ==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-logical-float-and-clear": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-float-and-clear/-/postcss-logical-float-and-clear-1.0.1.tgz", + "integrity": "sha512-eO9z2sMLddvlfFEW5Fxbjyd03zaO7cJafDurK4rCqyRt9P7aaWwha0LcSzoROlcZrw1NBV2JAp2vMKfPMQO1xw==", + "dev": true, + "requires": {} + }, + "@csstools/postcss-logical-resize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-resize/-/postcss-logical-resize-1.0.1.tgz", + "integrity": "sha512-x1ge74eCSvpBkDDWppl+7FuD2dL68WP+wwP2qvdUcKY17vJksz+XoE1ZRV38uJgS6FNUwC0AxrPW5gy3MxsDHQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-logical-viewport-units": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-logical-viewport-units/-/postcss-logical-viewport-units-1.0.2.tgz", + "integrity": "sha512-nnKFywBqRMYjv5jyjSplD/nbAnboUEGFfdxKw1o34Y1nvycgqjQavhKkmxbORxroBBIDwC5y6SfgENcPPUcOxQ==", + "dev": true, + "requires": { + "@csstools/css-tokenizer": "^2.0.0" + } + }, + "@csstools/postcss-media-queries-aspect-ratio-number-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-media-queries-aspect-ratio-number-values/-/postcss-media-queries-aspect-ratio-number-values-1.0.1.tgz", + "integrity": "sha512-V9yQqXdje6OfqDf6EL5iGOpi6N0OEczwYK83rql9UapQwFEryXlAehR5AqH8QqLYb6+y31wUXK6vMxCp0920Zg==", + "dev": true, + "requires": { + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "@csstools/media-query-list-parser": "^2.0.0" + } + }, + "@csstools/postcss-nested-calc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-2.0.1.tgz", + "integrity": "sha512-6C5yoF99zFb/C2Sa9Y5V0Y/2dnrjK5xe+h59L0LfdVhfanmJPrttwmfTua9etFRA1TGV46aoVMLEZ1NoHjWikg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-normalize-display-values": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-2.0.1.tgz", + "integrity": "sha512-TQT5g3JQ5gPXC239YuRK8jFceXF9d25ZvBkyjzBGGoW5st5sPXFVQS8OjYb9IJ/K3CdfK4528y483cgS2DJR/w==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-oklab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-2.0.1.tgz", + "integrity": "sha512-MTj3w6G1TYW0k43sXjw25fY/S+LHXpFIym5NW0oO/hjHFzuz5Uwz93aUvdo/UrrFmxSQeQAYCxmq6NlH3Pf1Hw==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-progressive-custom-properties": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-2.0.1.tgz", + "integrity": "sha512-ImgaFLEOhH/EdcrqDF8GSYSlsVR8EQBJ1p9ZhzoHgDkL7/uuzvSZOlRw5dFGFGnjdi7EXK4gsUjy2HU7ChHh3w==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-scope-pseudo-class": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-scope-pseudo-class/-/postcss-scope-pseudo-class-2.0.1.tgz", + "integrity": "sha512-wf2dcsqSQlBHc4HMMqdXdxDx4uYuqH+L08kKj+pmT+743C06STcUEu7ORFFEnqGWlOJ1kmA5BJ3pQU0EdMuA+w==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-stepped-value-functions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-2.0.1.tgz", + "integrity": "sha512-VimD+M69GsZF/XssivjUwo6jXLgi86ar/gRSH7bautnCULSLxCr/HuY32N4rLRUr7qWF8oF/JTv06ceb66Q1jA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-text-decoration-shorthand": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-2.1.0.tgz", + "integrity": "sha512-ARU7Oh9nplxt99cDONVrDt/c1osWRCtgAzegtvmkn6ed7wfmjeNOlXogK1SlAIfHl6X116kPTuFL7vuyDmlPQw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-trigonometric-functions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-2.0.1.tgz", + "integrity": "sha512-uGmmVWGHozyWe6+I4w321fKUC034OB1OYW0ZP4ySHA23n+r9y93K+1yrmW+hThpSfApKhaWySoD4I71LLlFUYQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-unset-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-2.0.1.tgz", + "integrity": "sha512-oJ9Xl29/yU8U7/pnMJRqAZd4YXNCfGEdcP4ywREuqm/xMqcgDNDppYRoCGDt40aaZQIEKBS79LytUDN/DHf0Ew==", + "dev": true, + "requires": {} + }, + "@csstools/selector-specificity": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz", + "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", + "dev": true, + "requires": {} + }, "@esbuild/android-arm": { "version": "0.16.7", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.7.tgz", @@ -7394,6 +8796,11 @@ "@rollup/pluginutils": "^4.1.0" } }, + "@remix-run/router": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.2.1.tgz", + "integrity": "sha512-XiY0IsyHR+DXYS5vBxpoBe/8veTeoRpMHP+vDosLZxL5bnpetzI0igkxkLZS235ldLzyfkxF+2divEwWHP3vMQ==" + }, "@rollup/plugin-replace": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.2.tgz", @@ -7448,6 +8855,15 @@ "string.prototype.matchall": "^4.0.6" } }, + "@szhsin/react-menu": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@szhsin/react-menu/-/react-menu-3.4.0.tgz", + "integrity": "sha512-BRxUF3BNmaQzL1z8UkS/eNFj+5ZPjBOpsYWP/ZtrzHNkkP6hUc+tYerBV4dwFiGYmWzkxyOP44ISn+EujwPpUw==", + "requires": { + "prop-types": "^15.7.2", + "react-transition-state": "^1.1.5" + } + }, "@trivago/prettier-plugin-sort-imports": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.0.0.tgz", @@ -7580,6 +8996,11 @@ "@types/node": "*" } }, + "@types/retry": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", + "integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==" + }, "@types/trusted-types": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", @@ -7965,6 +9386,45 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, + "css-blank-pseudo": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-5.0.1.tgz", + "integrity": "sha512-uEWT+613bR0lxUAz7BDdk4yZJ1BfzIJ9rmyOFj+p53ZP8rm0BC3nA2YsyswyxjFZsrfRDxe2WERDfKiEZNSXag==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "css-has-pseudo": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-5.0.1.tgz", + "integrity": "sha512-zhsGCKVkBohliMlcsZsv5WF/i4FQ3pkVMtl4yYa7Qpv/PVQebTjh7cjMoT5grW+DBZzunmgHe6skdWawgCYuPQ==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.1", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0" + } + }, + "css-prefers-color-scheme": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-8.0.1.tgz", + "integrity": "sha512-RPRyqJsk5KIjP2+WGhcGCaAJB8ojLbX1mVE8fG9127jQmnp1FNMfNMkERk/w6c4smgC/i5KxcY+Rtaa6/bMdKQ==", + "dev": true, + "requires": {} + }, + "cssdb": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.4.1.tgz", + "integrity": "sha512-0Q8NOMpXJ3iTDDbUv9grcmQAfdDx4qz+fN/+Md2FGbevT+6+bJNQ2LjB2YIUlLbpBTM32idU1Sb+tb/uGt6/XQ==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, "dayjs": { "version": "1.11.7", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", @@ -8413,14 +9873,6 @@ "tslib": "^2.0.3" } }, - "history": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", - "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", - "requires": { - "@babel/runtime": "^7.7.6" - } - }, "idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -8798,7 +10250,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "peer": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -8837,9 +10288,9 @@ } }, "masto": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/masto/-/masto-5.5.0.tgz", - "integrity": "sha512-EmAe76vYSR9tmUBiOqG7PwbrNFMVXaH7ce1LAr09MuXoS9RZfdEA4y7y3G0VhwTr4mGwnvWJu203CgAae7ZTEg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/masto/-/masto-5.7.0.tgz", + "integrity": "sha512-oCVReGLR9AoBSkShVgWrPb69xzfCpogiPH9wVT9AnPbM+CvjIqJuSaD1xgaEUi6jo66XGbhTC6UerSCVqq9emg==", "requires": { "@mastojs/ponyfills": "^1.0.4", "change-case": "^4.1.2", @@ -8980,6 +10431,11 @@ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -9017,6 +10473,15 @@ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" }, + "p-retry": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-5.1.2.tgz", + "integrity": "sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g==", + "requires": { + "@types/retry": "0.12.1", + "retry": "^0.13.1" + } + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -9079,6 +10544,87 @@ "source-map-js": "^1.0.2" } }, + "postcss-attribute-case-insensitive": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-6.0.1.tgz", + "integrity": "sha512-XNVoIdu/Pskb5OhkM+iHicEVuASeqAjOTCaW8Wcbrd1UVwRukOJr5+zWzFjYxJj55Z/67ViVm9n/1hwF7MGByQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-functional-notation": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-5.0.1.tgz", + "integrity": "sha512-Q9YDNQddKrl6YBs3229v+ckQINLyAaPfjJqG3jp5NUlP0UMm9+JeuLO1IMpeZy0l+rIE64y4OjUq0o+xhrnnrA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-hex-alpha": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.1.tgz", + "integrity": "sha512-1ZTJvmOZXTCsedKeY+Puqwx6AgoyB1KnzSD/CGDIl1NWvDfxi1jYky4R9konw2SAYw0SOeU33EU27ihE59Fp8Q==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-8.0.1.tgz", + "integrity": "sha512-bzZYxBDx/uUGW9HeldOA7J69GdymOZJNz3pG8av27YSgJt9dobl4l+hI/3KAosoRJml/iWceT97pJQj3O/dQDw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-media": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-9.1.1.tgz", + "integrity": "sha512-veQwzQkHgBkizxYCV/EBsiK8sFIJA0oQMQL9mpQ3gqFGc2dWlNWURHk4J44i9Q0dFeFCK81vV/Xpj7fyfNQKSA==", + "dev": true, + "requires": { + "@csstools/cascade-layer-name-parser": "^1.0.0", + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "@csstools/media-query-list-parser": "^2.0.0" + } + }, + "postcss-custom-properties": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-13.1.1.tgz", + "integrity": "sha512-FK4dBiHdzWOosLu3kEAHaYpfcrnMfVV4nP6PT6EFIfWXrtHH9LY8idfTYnEDpq/vgE33mr8ykhs7BjlgcT9agg==", + "dev": true, + "requires": { + "@csstools/cascade-layer-name-parser": "^1.0.0", + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-selectors": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-7.1.1.tgz", + "integrity": "sha512-CPs3BSdQfKqdrJ3d+3In9ppBPA8GpRy4Bd50jU+BDD6WEZOx8TTIB9i67BfRc2AVEAbRZwDMesreF95598dwhw==", + "dev": true, + "requires": { + "@csstools/cascade-layer-name-parser": "^1.0.0", + "@csstools/css-parser-algorithms": "^2.0.0", + "@csstools/css-tokenizer": "^2.0.0", + "postcss-selector-parser": "^6.0.4" + } + }, "postcss-dark-theme-class": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/postcss-dark-theme-class/-/postcss-dark-theme-class-0.7.3.tgz", @@ -9086,6 +10632,237 @@ "dev": true, "requires": {} }, + "postcss-dir-pseudo-class": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-7.0.1.tgz", + "integrity": "sha512-VjiqVOTz1op7bsiw7qd5CjZ0txA5yJY/oo1wb3f37qdleRTZQ9hzhAtLDqXimn0ZKh9XbtYawc4pmVBnV+LyMA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-double-position-gradients": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-4.0.1.tgz", + "integrity": "sha512-XE+eKvX96E9cmldwKeRmK8AMxfQfuuHN9Yjerymau5i+fgC/vEY+B+Ke2vnEv4E8EXu8MKdLxi4DzmodusW19Q==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-focus-visible": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-8.0.1.tgz", + "integrity": "sha512-azd1NMrLBe5bfKyomui9AMcgIR2zzlqXCTnKjshNDSClmmSO5MauTyflJUqmIwjIhD16+FbPyGV8Nxsly87BjA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-focus-within": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-7.0.1.tgz", + "integrity": "sha512-iSpk018Yqn0xwltFR7NHjagyt+e/6u8w50uEnGOcFOddLay5zQFjpJBg6euEZu7wY5WDq83DPpdO99eL+8Er8g==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "dev": true, + "requires": {} + }, + "postcss-gap-properties": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-4.0.1.tgz", + "integrity": "sha512-V5OuQGw4lBumPlwHWk/PRfMKjaq/LTGR4WDTemIMCaMevArVfCCA9wBJiL1VjDAd+rzuCIlkRoRvDsSiAaZ4Fg==", + "dev": true, + "requires": {} + }, + "postcss-image-set-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-5.0.1.tgz", + "integrity": "sha512-JnmN9Wo7WjlvM7fg00wzC4d/1kOqau+6v6hteLLqEyBjCuzoFZUU0Te3JphDyxc65RtPNsCujDwYbbs6+vYxCQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "dev": true, + "requires": {} + }, + "postcss-lab-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-5.0.1.tgz", + "integrity": "sha512-TuvrxsRIA3oWjjjI9T1ZEAolrtrLzYwYDw14GFivy0BkRqUTi4IithbM1aZkZGbAxV4lLwD6rL7MHhfDslUEzg==", + "dev": true, + "requires": { + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-logical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-6.0.1.tgz", + "integrity": "sha512-0LIzRgbT42n0q8txcM9SrLkYLjr1LTbRTy80bnKiYXY8tnYGdjkBymwb5XE87o4csW1z8dhKD1VRI6cHBQBQtw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "dev": true, + "requires": {} + }, + "postcss-nesting": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-11.0.1.tgz", + "integrity": "sha512-p/XiegrifL9CBwBiuJtFuUUvp8AgmxdyjNagmIjLEyJDUuo0JwbEgUsnQ99SzE7TRRXqXml7BFXkZpRhonE8rQ==", + "dev": true, + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "dev": true, + "requires": {} + }, + "postcss-overflow-shorthand": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-4.0.1.tgz", + "integrity": "sha512-HQZ0qi/9iSYHW4w3ogNqVNr2J49DHJAl7r8O2p0Meip38jsdnRPgiDW7r/LlLrrMBMe3KHkvNtAV2UmRVxzLIg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "dev": true, + "requires": {} + }, + "postcss-place": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-8.0.1.tgz", + "integrity": "sha512-Ow2LedN8sL4pq8ubukO77phSVt4QyCm35ZGCYXKvRFayAwcpgB0sjNJglDoTuRdUL32q/ZC1VkPBo0AOEr4Uiw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-preset-env": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-8.0.1.tgz", + "integrity": "sha512-IUbymw0JlUbyVG+I85963PNWgPp3KhnFa1sxU7M/2dGthxV8e297P0VV5W9XcyypoH4hirH2fp1c6fmqh6YnSg==", + "dev": true, + "requires": { + "@csstools/postcss-cascade-layers": "^3.0.0", + "@csstools/postcss-color-function": "^2.0.0", + "@csstools/postcss-font-format-keywords": "^2.0.0", + "@csstools/postcss-hwb-function": "^2.0.0", + "@csstools/postcss-ic-unit": "^2.0.0", + "@csstools/postcss-is-pseudo-class": "^3.0.0", + "@csstools/postcss-logical-float-and-clear": "^1.0.0", + "@csstools/postcss-logical-resize": "^1.0.0", + "@csstools/postcss-logical-viewport-units": "^1.0.0", + "@csstools/postcss-media-queries-aspect-ratio-number-values": "^1.0.0", + "@csstools/postcss-nested-calc": "^2.0.0", + "@csstools/postcss-normalize-display-values": "^2.0.0", + "@csstools/postcss-oklab-function": "^2.0.0", + "@csstools/postcss-progressive-custom-properties": "^2.0.0", + "@csstools/postcss-scope-pseudo-class": "^2.0.0", + "@csstools/postcss-stepped-value-functions": "^2.0.0", + "@csstools/postcss-text-decoration-shorthand": "^2.0.0", + "@csstools/postcss-trigonometric-functions": "^2.0.0", + "@csstools/postcss-unset-value": "^2.0.0", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^5.0.0", + "css-has-pseudo": "^5.0.0", + "css-prefers-color-scheme": "^8.0.0", + "cssdb": "^7.4.0", + "postcss-attribute-case-insensitive": "^6.0.0", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^5.0.0", + "postcss-color-hex-alpha": "^9.0.0", + "postcss-color-rebeccapurple": "^8.0.0", + "postcss-custom-media": "^9.1.0", + "postcss-custom-properties": "^13.1.0", + "postcss-custom-selectors": "^7.1.0", + "postcss-dir-pseudo-class": "^7.0.0", + "postcss-double-position-gradients": "^4.0.0", + "postcss-focus-visible": "^8.0.0", + "postcss-focus-within": "^7.0.0", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^4.0.0", + "postcss-image-set-function": "^5.0.0", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^5.0.0", + "postcss-logical": "^6.0.0", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^11.0.0", + "postcss-opacity-percentage": "^1.1.3", + "postcss-overflow-shorthand": "^4.0.0", + "postcss-page-break": "^3.0.4", + "postcss-place": "^8.0.0", + "postcss-pseudo-class-any-link": "^8.0.0", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^7.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-8.0.1.tgz", + "integrity": "sha512-CYcLGofbGDhx6BmNFQGFH0cqW+qlXVk9PR4LZ8Y7g24m6TopYKt6FSwhMGAIyme6lQxgB32XMhpYRwZAcPnMXA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "dev": true, + "requires": {} + }, + "postcss-selector-not": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.1.tgz", + "integrity": "sha512-1zT5C27b/zeJhchN7fP0kBr16Cc61mu7Si9uWWLoA3Px/D9tIJPKchJCkUH3tPO5D0pCFmGeApAv8XpXBQJ8SQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -9097,12 +10874,6 @@ "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==" }, - "preact-router": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.0.tgz", - "integrity": "sha512-y1w2YvVpKAju9FMV+fAVR1NpH4MW5q07BZrziMZeg6F/rGJ9KvLUZtjOqsy2I8fDYiX36AM1AQTXIIK3jigBhA==", - "requires": {} - }, "prettier": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", @@ -9116,6 +10887,16 @@ "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==", "dev": true }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "proxy-compare": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.4.0.tgz", @@ -9170,9 +10951,9 @@ } }, "react-hotkeys-hook": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.3.2.tgz", - "integrity": "sha512-ZA/li3kBDHuRTtJIf7Td41UU87bPtnt9xV4r+PlEzpnFoYRDVspk3B+mlaX75zowyQygMVmoaWnM4B88lkyExQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.3.3.tgz", + "integrity": "sha512-OYZCG2G+xLeiH0TkrW+v6eKFPvYq9iCA5sh9pwvnbGQaK86Lw/kWJDjjzSksFJoCk4K78OLe3MR1afNZH6+cLg==", "requires": {} }, "react-intersection-observer": { @@ -9181,6 +10962,34 @@ "integrity": "sha512-IXpIsPe6BleFOEHKzKh5UjwRUaz/JYS0lT/HPsupWEQou2hDqjhLMStc5zyE3eQVT4Fk3FufM8Fw33qW1uyeiw==", "requires": {} }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-router": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.6.2.tgz", + "integrity": "sha512-uJPG55Pek3orClbURDvfljhqFvMgJRo59Pktywkk8hUUkTY2aRfza8Yhl/vZQXs+TNQyr6tu+uqz/fLxPICOGQ==", + "requires": { + "@remix-run/router": "1.2.1" + } + }, + "react-router-dom": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.6.2.tgz", + "integrity": "sha512-6SCDXxRQqW5af8ImOqKza7icmQ47/EMbz572uFjzvcArg3lZ+04PxSPp8qGs+p2Y+q+b+S/AjXv8m8dyLndIIA==", + "requires": { + "@remix-run/router": "1.2.1", + "react-router": "6.6.2" + } + }, + "react-transition-state": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/react-transition-state/-/react-transition-state-1.1.5.tgz", + "integrity": "sha512-ITY2mZqc2dWG2eitJkYNdcSFW8aKeOlkL2A/vowRrLL8GH3J6Re/SpD/BLvQzrVOTqjsP0b5S9N10vgNNzwMUQ==", + "requires": {} + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -9199,7 +11008,8 @@ "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true }, "regenerator-transform": { "version": "0.15.1", @@ -9275,6 +11085,11 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -9694,6 +11509,12 @@ "punycode": "^2.1.0" } }, + "use-debounce": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.3.tgz", + "integrity": "sha512-FhtlbDtDXILJV7Lix5OZj5yX/fW1tzq+VrvK1fnT2bUrPOGruU9Rw8NCEn+UI9wopfERBEZAOQ8lfeCJPllgnw==", + "requires": {} + }, "use-resize-observer": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", @@ -9708,6 +11529,12 @@ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", "requires": {} }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "valtio": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.9.0.tgz", diff --git a/package.json b/package.json index 6a45033c..54a1a8ee 100644 --- a/package.json +++ b/package.json @@ -12,32 +12,34 @@ "dependencies": { "@github/text-expander-element": "~2.3.0", "@iconify-icons/mingcute": "~1.2.3", + "@szhsin/react-menu": "~3.4.0", "dayjs": "~1.11.7", "dayjs-twitter": "~0.5.0", "fast-blurhash": "~1.1.2", "fast-deep-equal": "~3.1.3", - "history": "~5.3.0", "idb-keyval": "~6.2.0", "just-debounce-it": "~3.2.0", - "masto": "~5.5.0", + "masto": "~5.7.0", "mem": "~9.0.2", + "p-retry": "~5.1.2", "preact": "~10.11.3", - "preact-router": "~4.1.0", - "react-hotkeys-hook": "~4.3.2", + "react-hotkeys-hook": "~4.3.3", "react-intersection-observer": "~9.4.1", + "react-router-dom": "6.6.2", "string-length": "~5.0.1", "swiped-events": "~1.1.7", "toastify-js": "~1.12.0", "uid": "~2.0.1", + "use-debounce": "~9.0.3", "use-resize-observer": "~9.1.0", "valtio": "~1.9.0" }, "devDependencies": { "@preact/preset-vite": "~2.5.0", "@trivago/prettier-plugin-sort-imports": "~4.0.0", - "autoprefixer": "~10.4.13", "postcss": "~8.4.21", "postcss-dark-theme-class": "~0.7.3", + "postcss-preset-env": "~8.0.1", "twitter-text": "~3.1.0", "vite": "~4.0.4", "vite-plugin-html-config": "~1.0.11", @@ -52,7 +54,7 @@ "postcss": { "plugins": { "postcss-dark-theme-class": {}, - "autoprefixer": {} + "postcss-preset-env": {} } }, "browserslist": [ diff --git a/src/app.css b/src/app.css index 38429db5..d92bd4b9 100644 --- a/src/app.css +++ b/src/app.css @@ -6,6 +6,9 @@ body { color: var(--text-color); overflow-x: hidden; } +body { + touch-action: pan-x pan-y; +} #app { min-height: 100vh; @@ -46,6 +49,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { transition: opacity 0.1s ease-in-out; overscroll-behavior: contain; scroll-behavior: smooth; + background-color: var(--bg-color); } .deck-container[hidden] { display: block; @@ -66,7 +70,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { min-height: 100dvh; margin: auto; width: 40em; - max-width: 100vw; + max-width: 100%; border-left: 1px solid rgba(0, 0, 0, 0.1); border-right: 1px solid rgba(0, 0, 0, 0.1); background-color: var(--bg-color); @@ -114,6 +118,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { padding: 0; font-size: 1.2em; text-align: center; + white-space: nowrap; } .deck > header h1:first-child { text-align: left; @@ -146,17 +151,26 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { border-bottom: none; } +.timeline.contextual { + --thread-start: 40px; + --line-start: 40px; + --line-width: 3px; + --line-end: calc(var(--line-start) + var(--line-width)); + --line-margin-end: 16px; + --line-radius: 10px; + --line-diameter: calc(var(--line-radius) * 2); + --avatar-size: 50px; + --avatar-margin-start: 16px; + --avatar-margin-end: 12px; +} .timeline.contextual > li { - --width: 3px; - --left: 40px; - --right: calc(var(--left) + var(--width)); background-image: linear-gradient( to right, transparent, - transparent var(--left), - var(--comment-line-color) var(--left), - var(--comment-line-color) var(--right), - transparent var(--right), + transparent var(--line-start), + var(--comment-line-color) var(--line-start), + var(--comment-line-color) var(--line-end), + transparent var(--line-end), transparent ); background-repeat: no-repeat; @@ -182,41 +196,127 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { > .status-link + .replies > summary { - margin-left: calc(50px + 16px + 12px); + margin-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + ); +} +.timeline.contextual + > li.descendant.thread + > .status-link + + .replies + .replies + > summary { + margin-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + var(--line-margin-end) + ); +} +.timeline.contextual + > li.descendant.thread + > .status-link + + .replies + .replies + .replies + > summary { + margin-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + (var(--line-margin-end) * 2) + ); } .timeline.contextual > li.descendant.thread > .status-link + .replies .status-link { - padding-left: calc(50px + 16px + 12px); + padding-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + ); +} +.timeline.contextual + > li.descendant.thread + > .status-link + + .replies + .replies + .status-link { + padding-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + var(--line-margin-end) + ); +} +.timeline.contextual + > li.descendant.thread + > .status-link + + .replies + .replies + .replies + .status-link { + padding-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + (var(--line-margin-end) * 2) + ); } .timeline.contextual > li.descendant:not(.thread) > .status-link + .replies > summary { - margin-left: calc(40px + 16px); + margin-left: calc(var(--thread-start) + var(--line-margin-end)); +} +.timeline.contextual + > li.descendant:not(.thread) + > .status-link + + .replies + .replies + > summary { + margin-left: calc( + var(--thread-start) + var(--line-margin-end) + var(--line-margin-end) + ); +} +.timeline.contextual + > li.descendant:not(.thread) + > .status-link + + .replies + .replies + .replies + > summary { + margin-left: calc( + var(--thread-start) + var(--line-margin-end) + (var(--line-margin-end) * 2) + ); } .timeline.contextual > li.descendant:not(.thread) > .status-link + .replies .status-link { - padding-left: calc(40px + 16px); + padding-left: calc(var(--thread-start) + var(--line-margin-end)); +} +.timeline.contextual + > li.descendant:not(.thread) + > .status-link + + .replies + .replies + .status-link { + padding-left: calc(var(--thread-start) + (var(--line-margin-end) * 2)); +} +.timeline.contextual + > li.descendant:not(.thread) + > .status-link + + .replies + .replies + .replies + .status-link { + padding-left: calc(var(--thread-start) + (var(--line-margin-end) * 3)); } .timeline.contextual > li.descendant:not(.thread):before { - --radius: 10px; - --diameter: calc(var(--radius) * 2); content: ''; position: absolute; top: 10px; - left: 40px; - width: var(--diameter); - height: var(--diameter); - border-radius: var(--radius); + left: var(--line-start); + width: var(--line-diameter); + height: var(--line-diameter); + border-radius: var(--line-radius); border-style: solid; - border-width: var(--width); + border-width: var(--line-width); border-color: transparent transparent var(--comment-line-color) transparent; transform: rotate(45deg); } @@ -228,7 +328,9 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { font-size: 90%; } .timeline.contextual > li.thread > .status-link .replies-link { - margin-left: calc(50px + 16px + 12px); + margin-left: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + ); } .timeline.contextual > li .replies-link * { vertical-align: middle; @@ -241,22 +343,33 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { padding: 0; list-style: none; } -.timeline.contextual > li .replies summary { - padding: 8px 16px; +.timeline.contextual > li .replies > summary { + padding: 8px; background-color: var(--bg-faded-color); display: inline-block; border-radius: 8px; cursor: pointer; text-transform: uppercase; - font-weight: bold; + font-weight: 500; font-size: 12px; color: var(--text-insignificant-color); user-select: none; box-shadow: 0 0 0 2px var(--bg-color); position: relative; + list-style: none; + white-space: nowrap; } -.timeline.contextual > li .replies summary:active, -.timeline.contextual > li .replies[open] summary { +.timeline.contextual > li .replies > summary::-webkit-details-marker { + display: none; +} +.timeline.contextual > li .replies > summary > * { + vertical-align: middle; +} +.timeline.contextual > li .replies > summary .avatars { + margin-right: 8px; +} +.timeline.contextual > li .replies > summary:active, +.timeline.contextual > li .replies[open] > summary { color: var(--text-color); background-color: var(--comment-line-color); background-image: linear-gradient( @@ -265,7 +378,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { var(--bg-faded-color) ); } -.timeline.contextual > li .replies[open] summary { +.timeline.contextual > li .replies[open] > summary { border-bottom-left-radius: 0; } .timeline.contextual > li .replies summary[hidden] { @@ -275,52 +388,89 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { position: relative; } .timeline.contextual > li .replies li { - --width: 3px; - --left: calc(40px + 16px); - --right: calc(var(--left) + var(--width)); + --line-start: calc(var(--thread-start) + var(--line-margin-end)); + --line-end: calc(var(--line-start) + var(--line-width)); background-image: linear-gradient( to right, transparent, - transparent var(--left), - var(--comment-line-color) var(--left), - var(--comment-line-color) var(--right), - transparent var(--right), + transparent var(--line-start), + var(--comment-line-color) var(--line-start), + var(--comment-line-color) var(--line-end), + transparent var(--line-end), transparent ); background-repeat: no-repeat; } +.timeline.contextual > li .replies .replies li { + --line-start: calc(var(--thread-start) + (var(--line-margin-end) * 2)); +} +.timeline.contextual > li .replies .replies .replies li { + --line-start: calc(var(--thread-start) + (var(--line-margin-end) * 3)); +} .timeline.contextual > li.thread .replies li { - --left: calc(50px + 16px + 12px); + --line-start: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + ); +} +.timeline.contextual > li.thread .replies .replies li { + --line-start: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + var(--line-margin-end) + ); +} +.timeline.contextual > li.thread .replies .replies .replies li { + --line-start: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + (var(--line-margin-end) * 2) + ); } .timeline.contextual > li .replies li:last-child { background-size: 100% 20px; } .timeline.contextual > li .replies li:before { - --radius: 10px; - --diameter: calc(var(--radius) * 2); content: ''; position: absolute; top: 10px; - left: calc(40px + 16px); - width: var(--diameter); - height: var(--diameter); - border-radius: var(--radius); + left: var(--line-start); + width: var(--line-diameter); + height: var(--line-diameter); + border-radius: var(--line-radius); border-style: solid; - border-width: var(--width); + border-width: var(--line-width); border-color: transparent transparent var(--comment-line-color) transparent; transform: rotate(45deg); } +.timeline.contextual > li .replies .replies li:before { + --line-start: calc( + var(--thread-start) + var(--line-margin-end) + var(--line-margin-end) + ); +} +.timeline.contextual > li .replies .replies .replies li:before { + --line-start: calc( + var(--thread-start) + var(--line-margin-end) + (var(--line-margin-end) * 2) + ); +} .timeline.contextual > li.thread .replies li:before { - left: calc(50px + 16px + 12px); + --line-start: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + ); +} +.timeline.contextual > li.thread .replies .replies li:before { + --line-start: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + var(--line-margin-end) + ); +} +.timeline.contextual > li.thread .replies .replies .replies li:before { + --line-start: calc( + var(--avatar-size) + var(--avatar-margin-start) + var(--avatar-margin-end) + + (var(--line-margin-end) * 2) + ); } .timeline.contextual.loading > li:not(.hero) { - opacity: 0.5; + /* opacity: 0.5; */ pointer-events: none; - /* background-image: none !important; */ } -/* .timeline.contextual.loading > li:not(.hero):before { - content: none !important; -} */ .timeline-deck.compact .status { max-height: max(25vh, 160px); @@ -364,10 +514,16 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { -webkit-tap-highlight-color: transparent; animation: appear 0.2s ease-out; } -.status-link:is(:hover, :focus) { +:is(.status-link, .status-focus):is(:focus, .is-active) { background-color: var(--link-bg-hover-color); outline-offset: -2px; } +@media (hover: hover) { + .status-link:hover { + background-color: var(--link-bg-hover-color); + outline-offset: -2px; + } +} .status-link:active:not(:has(:is(.media, button):active)) { filter: brightness(0.95); } @@ -467,9 +623,14 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { overflow: hidden; box-shadow: 0 1px var(--bg-color); } -.status-boost-link:is(:hover, :focus) { +.status-boost-link::focus { background-color: var(--link-bg-hover-color); } +@media (hover: hover) { + .status-boost-link:hover { + background-color: var(--link-bg-hover-color); + } +} .status-boost-link:active:not(:has(:is(.media, button):active)) { filter: brightness(0.95); } @@ -508,11 +669,6 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { max-width: 40em; } -.decks { - flex-grow: 1; - width: 100%; -} - .deck-close { color: var(--text-insignificant-color) !important; } @@ -582,6 +738,8 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { scrollbar-width: none; overscroll-behavior: contain; touch-action: pan-x; + user-select: none; + width: 100%; } .carousel::-webkit-scrollbar { display: none; @@ -593,7 +751,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { display: flex; justify-content: center; align-items: center; - width: 100vw; + width: 100%; height: 100vh; height: 100dvh; background-color: var(--average-color-alpha); @@ -606,7 +764,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { } .carousel > * :is(img, video) { width: auto; - max-width: 100vw; + max-width: 100%; height: auto; max-height: 100vh; max-height: 100dvh; @@ -621,10 +779,6 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { top: 0; top: env(safe-area-inset-top, 0); } -.carousel-controls { - bottom: 0; - bottom: env(safe-area-inset-bottom, 0); -} :is(.carousel-top-controls, .carousel-controls) { position: fixed; left: 0; @@ -654,26 +808,23 @@ button.carousel-dot { } .carousel-dots { border-radius: 999px; - backdrop-filter: blur(12px) invert(0.25) brightness(1.5); -} -@media (prefers-color-scheme: dark) { - .carousel-dots { - backdrop-filter: blur(12px) brightness(0.5); - } + backdrop-filter: blur(12px) invert(0.25); } button.carousel-dot { color: var(--text-insignificant-color) !important; font-weight: bold; backdrop-filter: none !important; + transition: all 0.2s; } -button.carousel-dot:is(:hover, :focus) button.carousel-dot.active, -button.carousel-dot[disabled].active { - color: var(--link-color) !important; +button.carousel-dot[disabled] { + pointer-events: none; } -button.carousel-dot.active, -button.carousel-dot[disabled].active { +button.carousel-dot:is(:hover, :focus, .active, [disabled].active) { + color: var(--button-text-color) !important; +} +button.carousel-dot:is(.active, [disabled].active) { opacity: 1; - transform: scale(2) translateY(-0.5px); + transform: scale(2.2) translateY(-0.5px); } @media (hover: hover) { .carousel-top-controls { @@ -681,8 +832,8 @@ button.carousel-dot[disabled].active { transition: transform 0.2s ease-in-out; } .carousel-controls { - transform: translateY(100%); - transition: transform 0.2s ease-in-out; + transform: scale(0); + /* transition: transform 0.2s ease-in-out; */ } :is(.carousel-top-controls, .carousel-controls)[hidden] { opacity: 1; @@ -696,10 +847,33 @@ button.carousel-dot[disabled].active { transform: translateY(0); } } -@media (prefers-color-scheme: dark) { - .carousel :is(img, video) { - /* No need fade out if inside carousel */ - filter: none; + +/* CAROUSEL + STATUS PAGE COMBO */ + +.media-post-link .button-label { + display: none; +} + +@media (min-width: calc(40em + 350px)) { + .media-post-link .button-label { + display: inline; + } + #modal-container > div, + .status-deck { + transition: all 0.3s ease-in-out; + } + /* Don't do this if there's a modal sheet (.sheet) */ + :has(#modal-container .carousel):has(.status-deck):not(:has(.sheet)) + .status-deck { + width: 350px; + min-width: 0; + } + :has(#modal-container .carousel):has(.status-deck):not(:has(.sheet)) + #modal-container + > div { + left: 0; + right: 350px; + width: auto; } } @@ -806,54 +980,30 @@ button.carousel-dot[disabled].active { /* MENU POPUP */ -.menu-container { - position: relative; -} -.menu-container button { - color: inherit !important; -} -.menu-container button:is(:hover, :active, :focus) { - background-color: var(--button-plain-bg-hover-color); -} -.menu-container menu { - position: absolute; - right: 0; - top: 0; - transform: translateY(-100%); - opacity: 0; - pointer-events: none; - padding: 8px 0; +.szh-menu { + padding: 8px 0 !important; margin: 0; font-size: 16px; - background-color: var(--bg-color); - width: 10em; - list-style: none; - z-index: 100; - border: 1px solid var(--outline-color); + background-color: var(--bg-color) !important; + border: 1px solid var(--outline-color) !important; border-radius: 8px; - transition: all 0.2s ease-in-out; - box-shadow: 0 0 8px var(--bg-faded-color), 0 4px 8px var(--bg-faded-color), - 0 2px 4px var(--bg-faded-color); -} -.menu-container menu li { - margin: 0; - padding: 0; - list-style: none; -} -.menu-container > button:is(:hover, :active, :focus) + menu, -.menu-container menu:is(:hover, :active) { - opacity: 1; - pointer-events: auto; -} -.menu-container menu button { - width: 100%; + box-shadow: 0 3px 6px var(--drop-shadow-color); text-align: left; - color: var(--text-color) !important; - border-radius: 0; + animation: appear 0.15s ease-in-out; } -.menu-container menu button:is(:hover, :focus) { - color: var(--bg-color) !important; - background-color: var(--link-color); +.szh-menu .szh-menu__item { + padding: 8px 16px !important; +} +.szh-menu .szh-menu__item * { + vertical-align: middle; +} +.szh-menu + .szh-menu__item:not(.szh-menu__item--disabled, .szh-menu__item--hover) { + color: var(--text-color); +} +.szh-menu .szh-menu__item--hover { + color: var(--button-text-color); + background-color: var(--button-bg-color); } /* DONUT METER */ @@ -943,19 +1093,109 @@ meter.donut:is(.danger, .explode):after { flex-wrap: wrap; gap: 4px; } +/* I'm just feeling bored, so having fun here */ +@media (hover: hover) { + .avatars-stack > * { + transition: transform 0.3s ease-in-out; + } + .avatars-stack:hover > *:nth-of-type(odd) { + transform: rotate(15deg); + } + .avatars-stack:hover > *:nth-of-type(even) { + transform: rotate(-15deg); + } +} + +.deck-container { + width: 100%; + flex-grow: 1; +} +#home-page ~ .deck-container { + z-index: 10; + position: fixed; + inset: 0; +} +#home-page:has(~ .deck-container) { + display: block; + position: absolute; + user-select: none; + pointer-events: none; + opacity: 0; + content-visibility: hidden; +} + +/* TAB BAR */ + +#tab-bar:not([hidden]) { + position: fixed; + bottom: 16px; + bottom: max(16px, env(safe-area-inset-bottom)); + width: calc(100% - 32px); + max-width: calc(40em - 32px); + z-index: 100; + display: flex; + background-color: var(--bg-blur-color); + backdrop-filter: blur(16px) saturate(3); + border: var(--hairline-width) solid var(--outline-color); + border-radius: 16px; + box-shadow: 0 8px 32px var(--outline-color); +} +#tab-bar li { + flex-grow: 1; + margin: 0; + padding: 0; + list-style: none; +} +#tab-bar li a { + text-align: center; + padding: 16px 0; + display: block; +} + +/* 404 */ + +#not-found-page { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + overflow: hidden; + cursor: default; + color: var(--text-insignificant-color); + background-image: radial-gradient( + circle at 50% 50%, + var(--bg-color) 25%, + var(--bg-faded-color) + ); + text-shadow: 0 1px var(--bg-color); +} + +/* ACCOUNT STATUSES */ + +.header-account { + font-size: 90% !important; + cursor: pointer; +} +.header-account div { + font-weight: normal; + color: var(--text-insignificant-color); +} @media (min-width: 40em) { html, body { background-color: var(--bg-faded-color); } + .deck-container { + background-color: var(--bg-faded-color); + } #app { display: flex; } - .decks { + .deck-container { transition: transform 0.4s var(--timing-function); } - .decks:has(~ .deck-backdrop) { + .deck-container:has(~ .deck-backdrop) { transition: transform 0.4s ease-out; transform: translate3d(-5vw, 0, 0); } @@ -969,25 +1209,25 @@ meter.donut:is(.danger, .explode):after { background-color: transparent; } .timeline-deck > header { - min-height: 6em; + --margin-top: 8px; + min-height: 4em; + top: var(--margin-top); border-bottom: 0; background-color: var(--bg-faded-blur-color); - background-image: linear-gradient( - to bottom, - var(--bg-faded-color), - transparent 50% - ); + background-image: none; border-bottom: 0; - mask-image: linear-gradient( - rgba(0, 0, 0, 1) 50%, - rgba(0, 0, 0, 0.7) 80%, - rgba(0, 0, 0, 0.5) 90%, - transparent - ); + border-radius: 16px; + margin-inline: 8px; + } + .timeline-deck > header[hidden] { + transform: translate3d(0, calc((100% + var(--margin-top)) * -1), 0); } .deck > header h1 { font-size: 1.5em; } + .updates-button { + margin-top: 24px; + } .timeline-deck .timeline:not(.flat) > li { border: 1px solid var(--divider-color); margin: 16px 0; @@ -995,15 +1235,32 @@ meter.donut:is(.danger, .explode):after { border-radius: 16px; overflow: hidden; box-shadow: 0px 1px var(--bg-blur-color); + transition: transform 0.4s var(--timing-function); + --back-transition: transform 0.4s ease-out; + } + .timeline-deck .timeline:not(.flat) > li:has(.status-link.is-active) { + transition: var(--back-transition); + transform: translate3d(-2.5vw, 0, 0); + } + .timeline-deck + .timeline:not(.flat) + > li:not(:has(.boost-carousel)):has(+ li .status-link.is-active), + .timeline-deck + .timeline:not(.flat) + > li:not(:has(.boost-carousel)):has(.status-link.is-active) + + li { + transition: var(--back-transition); + transform: translate3d(-1.25vw, 0, 0); } .box { padding: 32px; } - :is(.carousel-top-controls, .carousel-controls) { + /* :is(.carousel-top-controls, .carousel-controls) { padding: 32px; - } + } */ li:has(.boost-carousel) { width: 95vw; + max-width: calc(320px * 3.3); transform: translateX(calc(-50% + 20em)); } } diff --git a/src/app.jsx b/src/app.jsx index bd4f553c..f69c1964 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,22 +1,37 @@ import './app.css'; import 'toastify-js/src/toastify.css'; -import { createHashHistory } from 'history'; import debounce from 'just-debounce-it'; -import { login } from 'masto'; -import Router, { route } from 'preact-router'; -import { useEffect, useLayoutEffect, useState } from 'preact/hooks'; +import { createClient } from 'masto'; +import { + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState, +} from 'preact/hooks'; +import { Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import Toastify from 'toastify-js'; import { useSnapshot } from 'valtio'; import Account from './components/account'; import Compose from './components/compose'; import Drafts from './components/drafts'; +import Icon from './components/icon'; +import Link from './components/link'; import Loader from './components/loader'; +import MediaModal from './components/media-modal'; import Modal from './components/modal'; +import NotFound from './pages/404'; +import AccountStatuses from './pages/account-statuses'; +import Bookmarks from './pages/bookmarks'; +import Favourites from './pages/favourites'; +import Hashtags from './pages/hashtags'; import Home from './pages/home'; +import Lists from './pages/lists'; import Login from './pages/login'; import Notifications from './pages/notifications'; +import Public from './pages/public'; import Settings from './pages/settings'; import Status from './pages/status'; import Welcome from './pages/welcome'; @@ -24,14 +39,13 @@ import { getAccessToken } from './utils/auth'; import states, { saveStatus } from './utils/states'; import store from './utils/store'; -const { VITE_CLIENT_NAME: CLIENT_NAME } = import.meta.env; - window.__STATES__ = states; function App() { const snapStates = useSnapshot(states); const [isLoggedIn, setIsLoggedIn] = useState(false); const [uiState, setUIState] = useState('loading'); + const navigate = useNavigate(); useLayoutEffect(() => { const theme = store.local.get('theme'); @@ -67,11 +81,9 @@ function App() { const { access_token: accessToken } = tokenJSON; store.session.set('accessToken', accessToken); - window.masto = await login({ + initMasto({ url: `https://${instanceURL}`, accessToken, - disableVersionCheck: true, - timeout: 30_000, }); const mastoAccount = await masto.v1.accounts.verifyCredentials(); @@ -105,41 +117,35 @@ function App() { const instanceURL = account.instanceURL; const accessToken = account.accessToken; store.session.set('currentAccount', account.info.id); + if (accessToken) setIsLoggedIn(true); - (async () => { - try { - setUIState('loading'); - window.masto = await login({ - url: `https://${instanceURL}`, - accessToken, - disableVersionCheck: true, - timeout: 30_000, - }); - setIsLoggedIn(true); - } catch (e) { - setIsLoggedIn(false); - } - setUIState('default'); - })(); + initMasto({ + url: `https://${instanceURL}`, + accessToken, + }); } else { setUIState('default'); } }, []); - const [currentDeck, setCurrentDeck] = useState('home'); - const [currentModal, setCurrentModal] = useState(null); + let location = useLocation(); + states.currentLocation = location.pathname; + + const locationDeckMap = { + '/': 'home-page', + '/notifications': 'notifications-page', + }; const focusDeck = () => { - if (currentModal) return; let timer = setTimeout(() => { - const page = document.getElementById(`${currentDeck}-page`); - console.debug('FOCUS', currentDeck, page); + const page = document.getElementById(locationDeckMap[location.pathname]); + console.debug('FOCUS', location.pathname, page); if (page) { page.focus(); } }, 100); return () => clearTimeout(timer); }; - useEffect(focusDeck, [currentDeck, currentModal]); + useEffect(focusDeck, [location]); useEffect(() => { if ( !snapStates.showCompose && @@ -153,64 +159,80 @@ function App() { useEffect(() => { // HACK: prevent this from running again due to HMR if (states.init) return; - if (isLoggedIn) { - requestAnimationFrame(() => { - startStream(); - startVisibility(); - - // Collect instance info - (async () => { - const info = await masto.v1.instances.fetch(); - console.log(info); - const { uri, domain } = info; - const instances = store.local.getJSON('instances') || {}; - instances[(domain || uri).toLowerCase()] = info; - store.local.setJSON('instances', instances); - })(); - }); + requestAnimationFrame(startVisibility); states.init = true; } }, [isLoggedIn]); + const { prevLocation } = snapStates; + const backgroundLocation = useRef(prevLocation || null); + const isModalPage = /^\/s\//i.test(location.pathname); + if (isModalPage) { + if (!backgroundLocation.current) backgroundLocation.current = prevLocation; + } else { + backgroundLocation.current = null; + } + console.debug({ + backgroundLocation: backgroundLocation.current, + location, + }); + + const nonRootLocation = useMemo(() => { + const { pathname } = location; + return !/^\/(login|welcome|p)/.test(pathname); + }, [location]); + return ( <> - {isLoggedIn && currentDeck && ( -
- {/* Home will never be unmounted */} -
- )} - {!isLoggedIn && uiState === 'loading' && } - { - console.debug('ROUTER onChange', e); - // Special handling for Home and Notifications - const { url } = e; - if (/notifications/i.test(url)) { - setCurrentDeck('notifications'); - setCurrentModal(null); - } else if (url === '/') { - setCurrentDeck('home'); - document.title = `Home / ${CLIENT_NAME}`; - setCurrentModal(null); - } else if (/^\/s\//i.test(url)) { - setCurrentModal('status'); - } else { - setCurrentModal(null); - setCurrentDeck(null); + + + ) : uiState === 'loading' ? ( + + ) : ( + + ) } - states.history.push(url); - }} - > - {!isLoggedIn && uiState !== 'loading' && } - - {isLoggedIn && } - - + /> + } /> + } /> + + + {isLoggedIn && ( + } /> + )} + {isLoggedIn && } />} + {isLoggedIn && } />} + {isLoggedIn && } />} + {isLoggedIn && } />} + {isLoggedIn && } />} + } /> + {/* } /> */} + + + {isLoggedIn && } />} + + {!!snapStates.showCompose && ( { toast.hideToast(); - route(`/s/${newStatus.id}`); + states.prevLocation = location; + navigate(`/s/${newStatus.id}`); }, }); toast.showToast(); @@ -278,7 +301,12 @@ function App() { } }} > - + { + states.showAccount = false; + }} + /> )} {!!snapStates.showDrafts && ( @@ -292,24 +320,109 @@ function App() { )} + {!!snapStates.showMediaModal && ( + { + if ( + e.target === e.currentTarget || + e.target.classList.contains('media') + ) { + states.showMediaModal = false; + } + }} + > + { + states.showMediaModal = false; + }} + /> + + )} ); } +function initMasto(params) { + const clientParams = { + url: params.url || 'https://mastodon.social', + accessToken: params.accessToken || null, + disableVersionCheck: true, + timeout: 30_000, + }; + window.masto = createClient(clientParams); + + (async () => { + // Request v2, fallback to v1 if fail + let info; + try { + info = await masto.v2.instance.fetch(); + } catch (e) {} + if (!info) { + try { + info = await masto.v1.instances.fetch(); + } catch (e) {} + } + if (!info) return; + console.log(info); + const { + // v1 + uri, + urls: { streamingApi } = {}, + // v2 + domain, + configuration: { urls: { streaming } = {} } = {}, + } = info; + if (uri || domain) { + const instances = store.local.getJSON('instances') || {}; + instances[ + (domain || uri) + .replace(/^https?:\/\//, '') + .replace(/\/+$/, '') + .toLowerCase() + ] = info; + store.local.setJSON('instances', instances); + } + if (streamingApi || streaming) { + window.masto = createClient({ + ...clientParams, + streamingApiUrl: streaming || streamingApi, + }); + } + })(); +} + +let ws; async function startStream() { + if ( + ws && + (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN) + ) { + return; + } + const stream = await masto.v1.stream.streamUser(); console.log('STREAM START', { stream }); + ws = stream.ws; + const handleNewStatus = debounce((status) => { console.log('UPDATE', status); const inHomeNew = states.homeNew.find((s) => s.id === status.id); - const inHome = states.home.find((s) => s.id === status.id); + const inHome = status.id === states.homeLast?.id; if (!inHomeNew && !inHome) { - states.homeNew.unshift({ - id: status.id, - reblog: status.reblog?.id, - reply: !!status.inReplyToAccountId, - }); + if (states.settings.boostsCarousel && status.reblog) { + // do nothing + } else { + states.homeNew.unshift({ + id: status.id, + reblog: status.reblog?.id, + reply: !!status.inReplyToAccountId, + }); + console.log('homeNew 1', [...states.homeNew]); + } } saveStatus(status); @@ -331,9 +444,7 @@ async function startStream() { const inNotificationsNew = states.notificationsNew.find( (n) => n.id === notification.id, ); - const inNotifications = states.notifications.find( - (n) => n.id === notification.id, - ); + const inNotifications = notification.id === states.notificationLast?.id; if (!inNotificationsNew && !inNotifications) { states.notificationsNew.unshift(notification); } @@ -343,10 +454,9 @@ async function startStream() { stream.ws.onclose = () => { console.log('STREAM CLOSED!'); - - requestAnimationFrame(() => { + if (document.visibilityState !== 'hidden') { startStream(); - }); + } }; return { @@ -357,38 +467,38 @@ async function startStream() { }; } +let lastHidden; function startVisibility() { - const handleVisibilityChange = () => { - if (document.visibilityState === 'hidden') { + const handleVisible = (visible) => { + if (!visible) { const timestamp = Date.now(); - store.session.set('lastHidden', timestamp); + lastHidden = timestamp; } else { const timestamp = Date.now(); - const lastHidden = store.session.get('lastHidden'); const diff = timestamp - lastHidden; const diffMins = Math.round(diff / 1000 / 60); - if (diffMins > 1) { - console.log('visible', { lastHidden, diffMins }); - setTimeout(() => { - // Buffer for WS reconnect - (async () => { - try { - const firstStatusID = states.home[0]?.id; - const firstNotificationID = states.notifications[0]?.id; - const fetchHome = masto.v1.timelines.listHome({ - limit: 1, - ...(firstStatusID && { sinceId: firstStatusID }), - }); - const fetchNotifications = masto.v1.notifications.list({ - limit: 1, - ...(firstNotificationID && { sinceId: firstNotificationID }), - }); + console.log(`visible: ${visible}`, { lastHidden, diffMins }); + if (!lastHidden || diffMins > 1) { + (async () => { + try { + const firstStatusID = states.homeLast?.id; + const firstNotificationID = states.notificationsLast?.id; + const fetchHome = masto.v1.timelines.listHome({ + limit: 5, + ...(firstStatusID && { sinceId: firstStatusID }), + }); + const fetchNotifications = masto.v1.notifications.list({ + limit: 1, + ...(firstNotificationID && { sinceId: firstNotificationID }), + }); - const newStatuses = await fetchHome; - if ( - newStatuses.length && - newStatuses[0].id !== states.home[0].id - ) { + const newStatuses = await fetchHome; + const hasOneAndReblog = + newStatuses.length === 1 && newStatuses?.[0]?.reblog; + if (newStatuses.length) { + if (states.settings.boostsCarousel && hasOneAndReblog) { + // do nothing + } else { states.homeNew = newStatuses.map((status) => { saveStatus(status); return { @@ -397,33 +507,42 @@ function startVisibility() { reply: !!status.inReplyToAccountId, }; }); + console.log('homeNew 2', [...states.homeNew]); } - - const newNotifications = await fetchNotifications; - if (newNotifications.length) { - const notification = newNotifications[0]; - const inNotificationsNew = states.notificationsNew.find( - (n) => n.id === notification.id, - ); - const inNotifications = states.notifications.find( - (n) => n.id === notification.id, - ); - if (!inNotificationsNew && !inNotifications) { - states.notificationsNew.unshift(notification); - } - - saveStatus(notification.status, { override: false }); - } - } catch (e) { - // Silently fail - console.error(e); } - })(); - }, 100); + + const newNotifications = await fetchNotifications; + if (newNotifications.length) { + const notification = newNotifications[0]; + const inNotificationsNew = states.notificationsNew.find( + (n) => n.id === notification.id, + ); + const inNotifications = + notification.id === states.notificationLast?.id; + if (!inNotificationsNew && !inNotifications) { + states.notificationsNew.unshift(notification); + } + + saveStatus(notification.status, { override: false }); + } + } catch (e) { + // Silently fail + console.error(e); + } finally { + startStream(); + } + })(); } } }; + + const handleVisibilityChange = () => { + const hidden = document.visibilityState === 'hidden'; + handleVisible(!hidden); + console.log('VISIBILITY: ' + (hidden ? 'hidden' : 'visible')); + }; document.addEventListener('visibilitychange', handleVisibilityChange); + requestAnimationFrame(handleVisibilityChange); return { stop: () => { document.removeEventListener('visibilitychange', handleVisibilityChange); diff --git a/src/components/account.css b/src/components/account.css index 276cac63..2d66c31b 100644 --- a/src/components/account.css +++ b/src/components/account.css @@ -20,10 +20,20 @@ #account-container .stats { display: flex; flex-wrap: wrap; - column-gap: 16px; - row-gap: 4px; + justify-content: space-around; + gap: 16px; opacity: 0.75; font-size: 90%; + background-color: var(--bg-faded-color); + padding: 12px; + border-radius: 8px; + line-height: 1.25; +} +#account-container .stats > * { + text-align: center; +} +#account-container .stats a { + color: inherit; } #account-container .actions { @@ -70,3 +80,12 @@ #account-container .profile-field p { margin: 0; } + +#account-container .common-followers { + border-top: 1px solid var(--outline-color); + border-bottom: 1px solid var(--outline-color); + padding: 8px 0; + font-size: 90%; + line-height: 1.5; + color: var(--text-insignificant-color); +} diff --git a/src/components/account.jsx b/src/components/account.jsx index 075421fb..87feb00f 100644 --- a/src/components/account.jsx +++ b/src/components/account.jsx @@ -2,15 +2,19 @@ import './account.css'; import { useEffect, useState } from 'preact/hooks'; +import emojifyText from '../utils/emojify-text'; import enhanceContent from '../utils/enhance-content'; +import handleContentLinks from '../utils/handle-content-links'; import shortenNumber from '../utils/shorten-number'; +import states from '../utils/states'; import store from '../utils/store'; import Avatar from './avatar'; import Icon from './icon'; +import Link from './link'; import NameText from './name-text'; -function Account({ account }) { +function Account({ account, onClose }) { const [uiState, setUIState] = useState('default'); const isString = typeof account === 'string'; const [info, setInfo] = useState(isString ? null : account); @@ -27,12 +31,29 @@ function Account({ account }) { setInfo(info); setUIState('default'); } catch (e) { - alert(e); - setUIState('error'); + try { + const result = await masto.v2.search({ + q: account, + type: 'accounts', + limit: 1, + resolve: true, + }); + if (result.accounts.length) { + setInfo(result.accounts[0]); + setUIState('default'); + return; + } + setUIState('error'); + } catch (err) { + console.error(err); + setUIState('error'); + } } })(); + } else { + setInfo(account); } - }, []); + }, [account]); const { acct, @@ -59,6 +80,7 @@ function Account({ account }) { const [relationshipUIState, setRelationshipUIState] = useState('default'); const [relationship, setRelationship] = useState(null); + const [familiarFollowers, setFamiliarFollowers] = useState([]); useEffect(() => { if (info) { const currentAccount = store.session.get('currentAccount'); @@ -67,14 +89,29 @@ function Account({ account }) { return; } setRelationshipUIState('loading'); + setFamiliarFollowers([]); + (async () => { + const fetchRelationships = masto.v1.accounts.fetchRelationships([id]); + const fetchFamiliarFollowers = + masto.v1.accounts.fetchFamiliarFollowers(id); + try { - const relationships = await masto.v1.accounts.fetchRelationships([ - id, - ]); + const relationships = await fetchRelationships; console.log('fetched relationship', relationships); if (relationships.length) { - setRelationship(relationships[0]); + const relationship = relationships[0]; + setRelationship(relationship); + + if (!relationship.following) { + try { + const followers = await fetchFamiliarFollowers; + console.log('fetched familiar followers', followers); + setFamiliarFollowers(followers[0].accounts.slice(0, 10)); + } catch (e) { + console.error(e); + } + } } setRelationshipUIState('default'); } catch (e) { @@ -104,7 +141,17 @@ function Account({ account }) { id="account-container" class={`sheet ${uiState === 'loading' ? 'skeleton' : ''}`} > - {!info || uiState === 'loading' ? ( + {uiState === 'error' && ( +
+

Unable to load account.

+

+ + Go to account page + +

+
+ )} + {uiState === 'loading' ? ( <>
@@ -123,133 +170,174 @@ function Account({ account }) { ) : ( - <> -
- - -
-
- {bot && ( - <> - - Automated - - - )} -
- {fields?.length > 0 && ( - - )} -

- - {shortenNumber(statusesCount)}{' '} - Posts - - - {shortenNumber(followingCount)}{' '} - Following - - - {shortenNumber(followersCount)}{' '} - Followers - - {!!createdAt && ( - - Joined:{' '} - - - - + info && ( + <> +

+ + +
+
+ {bot && ( + <> + + Automated + + )} -

-

- {followedBy ? Following you : }{' '} - {relationshipUIState !== 'loading' && relationship && ( - - )} -

-
- + })(); + }} + > + {following ? ( + <> + Following + Unfollow… + + ) : requested ? ( + <> + Requested + Withdraw… + + ) : locked ? ( + <> + Follow + + ) : ( + 'Follow' + )} + + )} +

+
+ + ) )} ); diff --git a/src/components/avatar.jsx b/src/components/avatar.jsx index f8e1ca29..1ceb7fe4 100644 --- a/src/components/avatar.jsx +++ b/src/components/avatar.jsx @@ -9,7 +9,7 @@ const SIZES = { xxxl: 64, }; -function Avatar({ url, size, alt = '' }) { +function Avatar({ url, size, alt = '', ...props }) { size = SIZES[size] || size || SIZES.m; return ( {!!url && ( {alt} diff --git a/src/components/compose.css b/src/components/compose.css index 0d69efd1..5bdb8cd3 100644 --- a/src/components/compose.css +++ b/src/components/compose.css @@ -199,21 +199,22 @@ #compose-container text-expander { position: relative; + display: block; } #compose-container .text-expander-menu { color: var(--text-color); background-color: var(--bg-color); position: absolute; - margin: 0 0 0 -8px; + margin-top: 2em; padding: 0; list-style: none; border: 1px solid var(--outline-color); - /* box-shadow: 0 0 12px var(--outline-color); */ + box-shadow: 0 4px 24px var(--drop-shadow-color); border-radius: 8px; overflow: hidden; - top: 0 !important; z-index: 100; - min-width: 50vw; + min-width: 10em; + max-width: 90vw; } #compose-container .text-expander-menu li { white-space: nowrap; @@ -235,10 +236,16 @@ width: 2.2em; height: 2.2em; } -#compose-container .text-expander-menu li:is(:hover, :focus) { +#compose-container .text-expander-menu li:is(:hover, :focus, [aria-selected]) { color: var(--bg-color); background-color: var(--link-color); } +#compose-container + .text-expander-menu:hover + li[aria-selected]:not(:hover, :focus) { + color: var(--text-color); + background-color: var(--bg-color); +} #compose-container .media-attachments { background-color: var(--bg-faded-color); @@ -324,6 +331,16 @@ margin-bottom: 4px; } +#compose-container .media-sensitive { + padding: 8px; + background-color: var(--bg-blur-color); + border-radius: 8px; + cursor: pointer; +} +#compose-container .media-sensitive > * { + vertical-align: middle; +} + #compose-container form .poll { background-color: var(--bg-faded-color); border-radius: 8px; diff --git a/src/components/compose.jsx b/src/components/compose.jsx index 78453357..fd170e93 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -7,6 +7,7 @@ import { useEffect, useMemo, useRef, useState } from 'preact/hooks'; import { useHotkeys } from 'react-hotkeys-hook'; import stringLength from 'string-length'; import { uid } from 'uid/single'; +import { useDebouncedCallback } from 'use-debounce'; import { useSnapshot } from 'valtio'; import supportedLanguages from '../data/status-supported-languages'; @@ -17,7 +18,6 @@ import openCompose from '../utils/open-compose'; import states from '../utils/states'; import store from '../utils/store'; import { getCurrentAccount, getCurrentAccountNS } from '../utils/store-utils'; -import useDebouncedCallback from '../utils/useDebouncedCallback'; import useInterval from '../utils/useInterval'; import visibilityIconsMap from '../utils/visibility-icons-map'; @@ -45,6 +45,7 @@ const expiryOptions = { '30 minutes': 30 * 60, '1 hour': 60 * 60, '6 hours': 6 * 60 * 60, + '12 hours': 12 * 60 * 60, '1 day': 24 * 60 * 60, '3 days': 3 * 24 * 60 * 60, '7 days': 7 * 24 * 60 * 60, @@ -62,6 +63,21 @@ const menu = document.createElement('ul'); menu.role = 'listbox'; menu.className = 'text-expander-menu'; +// Set IntersectionObserver on menu, reposition it because text-expander doesn't handle it +const windowMargin = 16; +const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const { left, width } = entry.boundingClientRect; + const { innerWidth } = window; + if (left + width > innerWidth) { + menu.style.left = innerWidth - width - windowMargin + 'px'; + } + } + }); +}); +observer.observe(menu); + const DEFAULT_LANG = 'en'; // https://github.com/mastodon/mastodon/blob/c4a429ed47e85a6bbf0d470a41cc2f64cf120c19/app/javascript/mastodon/features/compose/util/counter.js @@ -779,9 +795,10 @@ function Compose({ ref={spoilerTextRef} type="text" name="spoilerText" - placeholder="Spoiler text" + placeholder="Content warning" disabled={uiState === 'loading'} class="spoiler-text-field" + lang={language} style={{ opacity: sensitive ? 1 : 0, pointerEvents: sensitive ? 'auto' : 'none', @@ -846,6 +863,7 @@ function Compose({ } required={mediaAttachments.length === 0} disabled={uiState === 'loading'} + lang={language} onInput={() => { updateCharCount(); }} @@ -861,6 +879,7 @@ function Compose({ key={id || fileID || i} attachment={attachment} disabled={uiState === 'loading'} + lang={language} onDescriptionChange={(value) => { setMediaAttachments((attachments) => { const newAttachments = [...attachments]; @@ -876,10 +895,25 @@ function Compose({ /> ); })} + )} {!!poll && ( @@ -1218,6 +1254,7 @@ function CharCountMeter({ maxCharacters = 500 }) { function MediaAttachment({ attachment, disabled, + lang, onDescriptionChange = () => {}, onRemove = () => {}, }) { @@ -1257,6 +1294,7 @@ function MediaAttachment({