diff --git a/package.json b/package.json index 1b34cc78..07cd469d 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@wcj/markdown-to-html": "^2.2.1", "client-only": "^0.0.1", "client-zip": "2.3.0", + "cmdk": "^0.1.22", "jest": "^29.4.3", "lodash.debounce": "^4.0.8", "next": "13.2.2-canary.0", @@ -61,6 +62,10 @@ "eslint": "8.33.0", "eslint-config-next": "13.1.7-canary.26", "next-unused": "0.0.6", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-hover-media-feature": "^1.0.2", + "postcss-nested": "^6.0.1", + "postcss-preset-env": "^8.0.1", "prettier": "2.8.3", "prisma": "^4.10.1", "typescript": "4.9.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3bde9bc6..2b1bc651 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,7 @@ specifiers: client-only: ^0.0.1 client-zip: 2.3.0 clsx: ^1.2.1 + cmdk: ^0.1.22 cross-env: 7.0.3 csstype: ^3.1.1 eslint: 8.33.0 @@ -35,6 +36,10 @@ specifiers: next-auth: ^4.19.2 next-themes: ^0.2.1 next-unused: 0.0.6 + postcss-flexbugs-fixes: ^5.0.2 + postcss-hover-media-feature: ^1.0.2 + postcss-nested: ^6.0.1 + postcss-preset-env: ^8.0.1 prettier: 2.8.3 prisma: ^4.10.1 react: 18.2.0 @@ -66,6 +71,7 @@ dependencies: '@wcj/markdown-to-html': 2.2.1 client-only: 0.0.1 client-zip: 2.3.0 + cmdk: 0.1.22_5ndqzdd6t4rivxsukjv3i3ak2q jest: 29.4.3_@types+node@18.11.18 lodash.debounce: 4.0.8 next: 13.2.2-canary.0_biqbaboplfbrettd7655fr4n2y @@ -105,6 +111,10 @@ devDependencies: eslint: 8.33.0 eslint-config-next: 13.1.7-canary.26_zkdaqh7it7uc4cvz2haft7rc6u next-unused: 0.0.6 + postcss-flexbugs-fixes: 5.0.2 + postcss-hover-media-feature: 1.0.2 + postcss-nested: 6.0.1 + postcss-preset-env: 8.0.1 prettier: 2.8.3 prisma: 4.10.1 typescript: 4.9.4 @@ -478,6 +488,248 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: false + /@csstools/cascade-layer-name-parser/1.0.1_ppok7cytzjc65mcyxmtit3wdyi: + resolution: {integrity: sha512-SAAi5DpgJJWkfTvWSaqkgyIsTawa83hMwKrktkj6ra2h+q6ZN57vOGZ6ySHq6RSo+CbP64fA3aPChPBRDDUgtw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-parser-algorithms': ^2.0.0 + '@csstools/css-tokenizer': ^2.0.0 + dependencies: + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + dev: true + + /@csstools/color-helpers/1.0.0: + resolution: {integrity: sha512-tgqtiV8sU/VaWYjOB3O7PWs7HR/MmOLl2kTYRW2qSsTSEniJq7xmyAYFB1LPpXvvQcE5u2ih2dK9fyc8BnrAGQ==} + engines: {node: ^14 || ^16 || >=18} + dev: true + + /@csstools/css-calc/1.0.0_ppok7cytzjc65mcyxmtit3wdyi: + resolution: {integrity: sha512-Xw0b/Jr+vLGGYD8cxsGWPaY5n1GtVC6G4tcga+eZPXZzRjjZHorPwW739UgtXzL2Da1RLxNE73c0r/KvmizPsw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-parser-algorithms': ^2.0.1 + '@csstools/css-tokenizer': ^2.0.1 + dependencies: + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + dev: true + + /@csstools/css-parser-algorithms/2.0.1_5vzy4lghjvuzkedkkk4tqwjftm: + resolution: {integrity: sha512-B9/8PmOtU6nBiibJg0glnNktQDZ3rZnGn/7UmDfrm2vMtrdlXO3p7ErE95N0up80IRk9YEtB5jyj/TmQ1WH3dw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-tokenizer': ^2.0.0 + dependencies: + '@csstools/css-tokenizer': 2.1.0 + dev: true + + /@csstools/css-tokenizer/2.1.0: + resolution: {integrity: sha512-dtqFyoJBHUxGi9zPZdpCKP1xk8tq6KPHJ/NY4qWXiYo6IcSGwzk3L8x2XzZbbyOyBs9xQARoGveU2AsgLj6D2A==} + engines: {node: ^14 || ^16 || >=18} + dev: true + + /@csstools/media-query-list-parser/2.0.1_ppok7cytzjc65mcyxmtit3wdyi: + resolution: {integrity: sha512-X2/OuzEbjaxhzm97UJ+95GrMeT29d1Ib+Pu+paGLuRWZnWRK9sI9r3ikmKXPWGA1C4y4JEdBEFpp9jEqCvLeRA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-parser-algorithms': ^2.0.0 + '@csstools/css-tokenizer': ^2.0.0 + dependencies: + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + dev: true + + /@csstools/postcss-cascade-layers/3.0.1: + resolution: {integrity: sha512-dD8W98dOYNOH/yX4V4HXOhfCOnvVAg8TtsL+qCGNoKXuq5z2C/d026wGWgySgC8cajXXo/wNezS31Glj5GcqrA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/selector-specificity': 2.1.1_laljekdltgzr3kfi7r4exvsr5a + postcss-selector-parser: 6.0.11 + dev: true + + /@csstools/postcss-color-function/2.1.0: + resolution: {integrity: sha512-XBoCClLyWchlYGHGlmMOa6M2UXZNrZm63HVfsvgD/z1RPm/s3+FhHyT6VkDo+OvEBPhCgn6xz4IeCu4pRctKDQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/color-helpers': 1.0.0 + '@csstools/postcss-progressive-custom-properties': 2.1.0 + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-font-format-keywords/2.0.2: + resolution: {integrity: sha512-iKYZlIs6JsNT7NKyRjyIyezTCHLh4L4BBB3F5Nx7Dc4Z/QmBgX+YJFuUSar8IM6KclGiAUFGomXFdYxAwJydlA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-hwb-function/2.1.1: + resolution: {integrity: sha512-XijKzdxBdH2hU6IcPWmnaU85FKEF1XE5hGy0d6dQC6XznFUIRu1T4uebL3krayX40m4xIcxfCBsQm5zphzVrtg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/color-helpers': 1.0.0 + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-ic-unit/2.0.2: + resolution: {integrity: sha512-N84qGTJkfLTPj2qOG5P4CIqGjpZBbjOEMKMn+UjO5wlb9lcBTfBsxCF0lQsFdWJUzBHYFOz19dL66v71WF3Pig==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/postcss-progressive-custom-properties': 2.1.0 + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-is-pseudo-class/3.1.1: + resolution: {integrity: sha512-hhiacuby4YdUnnxfCYCRMBIobyJImozf0u+gHSbQ/tNOdwvmrZtVROvgW7zmfYuRkHVDNZJWZslq2v5jOU+j/A==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/selector-specificity': 2.1.1_laljekdltgzr3kfi7r4exvsr5a + postcss-selector-parser: 6.0.11 + dev: true + + /@csstools/postcss-logical-float-and-clear/1.0.1: + resolution: {integrity: sha512-eO9z2sMLddvlfFEW5Fxbjyd03zaO7cJafDurK4rCqyRt9P7aaWwha0LcSzoROlcZrw1NBV2JAp2vMKfPMQO1xw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dev: true + + /@csstools/postcss-logical-resize/1.0.1: + resolution: {integrity: sha512-x1ge74eCSvpBkDDWppl+7FuD2dL68WP+wwP2qvdUcKY17vJksz+XoE1ZRV38uJgS6FNUwC0AxrPW5gy3MxsDHQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-logical-viewport-units/1.0.2: + resolution: {integrity: sha512-nnKFywBqRMYjv5jyjSplD/nbAnboUEGFfdxKw1o34Y1nvycgqjQavhKkmxbORxroBBIDwC5y6SfgENcPPUcOxQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/css-tokenizer': 2.1.0 + dev: true + + /@csstools/postcss-media-queries-aspect-ratio-number-values/1.0.1: + resolution: {integrity: sha512-V9yQqXdje6OfqDf6EL5iGOpi6N0OEczwYK83rql9UapQwFEryXlAehR5AqH8QqLYb6+y31wUXK6vMxCp0920Zg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + '@csstools/media-query-list-parser': 2.0.1_ppok7cytzjc65mcyxmtit3wdyi + dev: true + + /@csstools/postcss-nested-calc/2.0.2: + resolution: {integrity: sha512-jbwrP8rN4e7LNaRcpx3xpMUjhtt34I9OV+zgbcsYAAk6k1+3kODXJBf95/JMYWhu9g1oif7r06QVUgfWsKxCFw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-normalize-display-values/2.0.1: + resolution: {integrity: sha512-TQT5g3JQ5gPXC239YuRK8jFceXF9d25ZvBkyjzBGGoW5st5sPXFVQS8OjYb9IJ/K3CdfK4528y483cgS2DJR/w==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-oklab-function/2.1.0: + resolution: {integrity: sha512-U/odSNjOVhagNRu+RDaNVbn8vaqA9GyCOoneQA2je7697KOrtRDc7/POrYsP7QioO2aaezDzKNX02wBzc99fkQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/color-helpers': 1.0.0 + '@csstools/postcss-progressive-custom-properties': 2.1.0 + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-progressive-custom-properties/2.1.0: + resolution: {integrity: sha512-tRX1rinsXajZlc4WiU7s9Y6O9EdSHScT997zDsvDUjQ1oZL2nvnL6Bt0s9KyQZZTdC3lrG2PIdBqdOIWXSEPlQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-scope-pseudo-class/2.0.2: + resolution: {integrity: sha512-6Pvo4uexUCXt+Hz5iUtemQAcIuCYnL+ePs1khFR6/xPgC92aQLJ0zGHonWoewiBE+I++4gXK3pr+R1rlOFHe5w==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /@csstools/postcss-stepped-value-functions/2.1.0: + resolution: {integrity: sha512-CkEo9BF8fQeMoXW3biXjlgTLY7PA4UFihn6leq7hPoRzIguLUI0WZIVgsITGXfX8LXmkhCSTjXO2DLYu/LUixQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/css-calc': 1.0.0_ppok7cytzjc65mcyxmtit3wdyi + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + dev: true + + /@csstools/postcss-text-decoration-shorthand/2.2.1: + resolution: {integrity: sha512-Ow6/cWWdjjVvA83mkm3kLRvvWsbzoe1AbJCxkpC+c9ibUjyS8pifm+LpZslQUKcxRVQ69ztKHDBEbFGTDhNeUw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/color-helpers': 1.0.0 + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-trigonometric-functions/2.0.1: + resolution: {integrity: sha512-uGmmVWGHozyWe6+I4w321fKUC034OB1OYW0ZP4ySHA23n+r9y93K+1yrmW+hThpSfApKhaWySoD4I71LLlFUYQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /@csstools/postcss-unset-value/2.0.1: + resolution: {integrity: sha512-oJ9Xl29/yU8U7/pnMJRqAZd4YXNCfGEdcP4ywREuqm/xMqcgDNDppYRoCGDt40aaZQIEKBS79LytUDN/DHf0Ew==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dev: true + + /@csstools/selector-specificity/2.1.1_laljekdltgzr3kfi7r4exvsr5a: + resolution: {integrity: sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + postcss-selector-parser: ^6.0.10 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + /@eslint/eslintrc/1.4.1: resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1075,6 +1327,33 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-dialog/1.0.0_5ndqzdd6t4rivxsukjv3i3ak2q: + resolution: {integrity: sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/primitive': 1.0.0 + '@radix-ui/react-compose-refs': 1.0.0_react@18.2.0 + '@radix-ui/react-context': 1.0.0_react@18.2.0 + '@radix-ui/react-dismissable-layer': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-focus-guards': 1.0.0_react@18.2.0 + '@radix-ui/react-focus-scope': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-id': 1.0.0_react@18.2.0 + '@radix-ui/react-portal': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-presence': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-primitive': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-slot': 1.0.0_react@18.2.0 + '@radix-ui/react-use-controllable-state': 1.0.0_react@18.2.0 + aria-hidden: 1.2.2_3stiutgnnbnfnf3uowm5cip22i + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-remove-scroll: 2.5.4_3stiutgnnbnfnf3uowm5cip22i + transitivePeerDependencies: + - '@types/react' + dev: false + /@radix-ui/react-dialog/1.0.2_5ndqzdd6t4rivxsukjv3i3ak2q: resolution: {integrity: sha512-EKxxp2WNSmUPkx4trtWNmZ4/vAYEg7JkAfa1HKBUnaubw9eHzf1Orr9B472lJYaYz327RHDrd4R95fsw7VR8DA==} peerDependencies: @@ -1111,6 +1390,22 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-dismissable-layer/1.0.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-n7kDRfx+LB1zLueRDvZ1Pd0bxdJWDUZNQ/GWoxDn2prnuJKRdxsjulejX/ePkOsLi2tTm6P24mDqlMSgQpsT6g==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/primitive': 1.0.0 + '@radix-ui/react-compose-refs': 1.0.0_react@18.2.0 + '@radix-ui/react-primitive': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-use-callback-ref': 1.0.0_react@18.2.0 + '@radix-ui/react-use-escape-keydown': 1.0.0_react@18.2.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + /@radix-ui/react-dismissable-layer/1.0.2_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg==} peerDependencies: @@ -1156,6 +1451,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-focus-scope/1.0.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-C4SWtsULLGf/2L4oGeIHlvWQx7Rf+7cX/vKOAD2dXW0A1b5QXwi3wWeaEgW+wn+SEVrraMUk05vLU9fZZz5HbQ==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/react-compose-refs': 1.0.0_react@18.2.0 + '@radix-ui/react-primitive': 1.0.0_biqbaboplfbrettd7655fr4n2y + '@radix-ui/react-use-callback-ref': 1.0.0_react@18.2.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + /@radix-ui/react-focus-scope/1.0.1_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ==} peerDependencies: @@ -1262,6 +1571,18 @@ packages: - '@types/react' dev: false + /@radix-ui/react-portal/1.0.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-a8qyFO/Xb99d8wQdu4o7qnigNjTPG123uADNecz0eX4usnQEj7o+cG4ZX4zkqq98NYekT7UoEQIjxBNWIFuqTA==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/react-primitive': 1.0.0_biqbaboplfbrettd7655fr4n2y + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + /@radix-ui/react-portal/1.0.1_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig==} peerDependencies: @@ -1287,6 +1608,18 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false + /@radix-ui/react-primitive/1.0.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/react-slot': 1.0.0_react@18.2.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + /@radix-ui/react-primitive/1.0.1_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==} peerDependencies: @@ -1319,6 +1652,16 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false + /@radix-ui/react-slot/1.0.0_react@18.2.0: + resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/react-compose-refs': 1.0.0_react@18.2.0 + react: 18.2.0 + dev: false + /@radix-ui/react-slot/1.0.1_react@18.2.0: resolution: {integrity: sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==} peerDependencies: @@ -1392,6 +1735,16 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-escape-keydown/1.0.0_react@18.2.0: + resolution: {integrity: sha512-JwfBCUIfhXRxKExgIqGa4CQsiMemo1Xt0W/B4ei3fpzpvPENKpMKQ8mZSB6Acj3ebrAEgi2xiQvcI1PAAodvyg==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 + dependencies: + '@babel/runtime': 7.20.13 + '@radix-ui/react-use-callback-ref': 1.0.0_react@18.2.0 + react: 18.2.0 + dev: false + /@radix-ui/react-use-escape-keydown/1.0.2_react@18.2.0: resolution: {integrity: sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA==} peerDependencies: @@ -2023,6 +2376,21 @@ packages: engines: {node: '>=4'} dev: false + /autoprefixer/10.4.13: + resolution: {integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.21.5 + caniuse-lite: 1.0.30001458 + fraction.js: 4.2.0 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss-value-parser: 4.2.0 + dev: true + /available-typed-arrays/1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -2170,7 +2538,6 @@ packages: electron-to-chromium: 1.4.311 node-releases: 2.0.10 update-browserslist-db: 1.0.10_browserslist@4.21.5 - dev: false /bs-logger/0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} @@ -2226,7 +2593,6 @@ packages: /caniuse-lite/1.0.30001458: resolution: {integrity: sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==} - dev: false /ccount/2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2345,6 +2711,20 @@ packages: engines: {node: '>=6'} dev: true + /cmdk/0.1.22_5ndqzdd6t4rivxsukjv3i3ak2q: + resolution: {integrity: sha512-F0ffliBO/U6SXKGRud9AjsNuINvfF+d9BVUgi/y2+v3TSBHVOmIXl43CWLEyEEIOwc2DTnlXvIQenhGAEpwW0Q==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + dependencies: + '@radix-ui/react-dialog': 1.0.0_5ndqzdd6t4rivxsukjv3i3ak2q + command-score: 0.1.2 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + transitivePeerDependencies: + - '@types/react' + dev: false + /co/4.6.0: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -2392,6 +2772,10 @@ packages: resolution: {integrity: sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==} dev: false + /command-score/0.1.2: + resolution: {integrity: sha512-VtDvQpIJBvBatnONUsPzXYFVKQQAhuf3XTNOAsdBxCNO/QCtUUd8LSgjn0GVarBkCad6aJCZfXgrjYbl/KRr7w==} + dev: false + /commander/2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: true @@ -2461,6 +2845,15 @@ packages: resolution: {integrity: sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==} dev: false + /css-blank-pseudo/5.0.2: + resolution: {integrity: sha512-aCU4AZ7uEcVSUzagTlA9pHciz7aWPKA/YzrEkpdSopJ2pvhIxiQ5sYeMz1/KByxlIo4XBdvMNJAVKMg/GRnhfw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + /css-box-shadow/1.0.0-3: resolution: {integrity: sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==} dev: false @@ -2470,6 +2863,24 @@ packages: engines: {node: '>=4'} dev: false + /css-has-pseudo/5.0.2: + resolution: {integrity: sha512-q+U+4QdwwB7T9VEW/LyO6CFrLAeLqOykC5mDqJXc7aKZAhDbq7BvGT13VGJe+IwBfdN2o3Xdw2kJ5IxwV1Sc9Q==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/selector-specificity': 2.1.1_laljekdltgzr3kfi7r4exvsr5a + postcss-selector-parser: 6.0.11 + postcss-value-parser: 4.2.0 + dev: true + + /css-prefers-color-scheme/8.0.2: + resolution: {integrity: sha512-OvFghizHJ45x7nsJJUSYLyQNTzsCU8yWjxAc/nhPQg1pbs18LMoET8N3kOweFDPy0JV0OSXN2iqRFhPBHYOeMA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dev: true + /css-selector-parser/1.4.1: resolution: {integrity: sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==} dev: false @@ -2489,6 +2900,10 @@ packages: postcss-value-parser: 4.2.0 dev: false + /cssdb/7.4.1: + resolution: {integrity: sha512-0Q8NOMpXJ3iTDDbUv9grcmQAfdDx4qz+fN/+Md2FGbevT+6+bJNQ2LjB2YIUlLbpBTM32idU1Sb+tb/uGt6/XQ==} + dev: true + /cssesc/3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2774,7 +3189,6 @@ packages: /electron-to-chromium/1.4.311: resolution: {integrity: sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw==} - dev: false /emittery/0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -2920,7 +3334,6 @@ packages: /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} - dev: false /escape-string-regexp/1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} @@ -3421,6 +3834,10 @@ packages: is-callable: 1.2.7 dev: true + /fraction.js/4.2.0: + resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} + dev: true + /fs-constants/1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: false @@ -5570,7 +5987,6 @@ packages: /node-releases/2.0.10: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} - dev: false /node-source-walk/4.3.0: resolution: {integrity: sha512-8Q1hXew6ETzqKRAs3jjLioSxNfT1cx74ooiF8RlAONwVMcfq+UdzLC2eB5qcPldUxaE5w3ytLkrmV1TGddhZTA==} @@ -5583,6 +5999,11 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + /normalize-range/0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + /not/0.1.0: resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} dev: false @@ -5882,12 +6303,158 @@ packages: engines: {node: '>=4'} dev: true + /postcss-attribute-case-insensitive/6.0.2: + resolution: {integrity: sha512-IRuCwwAAQbgaLhxQdQcIIK0dCVXg3XDUnzgKD8iwdiYdwU4rMWRWyl/W9/0nA4ihVpq5pyALiHB2veBJ0292pw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-clamp/4.1.0: + resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} + engines: {node: '>=7.6.0'} + peerDependencies: + postcss: ^8.4.6 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-color-functional-notation/5.0.2: + resolution: {integrity: sha512-M6ygxWOyd6eWf3sd1Lv8xi4SeF4iBPfJvkfMU4ITh8ExJc1qhbvh/U8Cv/uOvBgUVOMDdScvCdlg8+hREQzs7w==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-color-hex-alpha/9.0.2: + resolution: {integrity: sha512-SfPjgr//VQ/DOCf80STIAsdAs7sbIbxATvVmd+Ec7JvR8onz9pjawhq3BJM3Pie40EE3TyB0P6hft16D33Nlyg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-color-rebeccapurple/8.0.2: + resolution: {integrity: sha512-xWf/JmAxVoB5bltHpXk+uGRoGFwu4WDAR7210el+iyvTdqiKpDhtcT8N3edXMoVJY0WHFMrKMUieql/wRNiXkw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-custom-media/9.1.2: + resolution: {integrity: sha512-osM9g4UKq4XKimAC7RAXroqi3BXpxfwTswAJQiZdrBjWGFGEyxQrY5H2eDWI8F+MEvEUfYDxA8scqi3QWROCSw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/cascade-layer-name-parser': 1.0.1_ppok7cytzjc65mcyxmtit3wdyi + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + '@csstools/media-query-list-parser': 2.0.1_ppok7cytzjc65mcyxmtit3wdyi + dev: true + + /postcss-custom-properties/13.1.4: + resolution: {integrity: sha512-iSAdaZrM3KMec8cOSzeTUNXPYDlhqsMJHpt62yrjwG6nAnMtRHPk5JdMzGosBJtqEahDolvD5LNbcq+EZ78o5g==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/cascade-layer-name-parser': 1.0.1_ppok7cytzjc65mcyxmtit3wdyi + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-custom-selectors/7.1.2: + resolution: {integrity: sha512-jX7VlE3jrgfBIOfxiGNRFq81xUoHSZhvxhQurzE7ZFRv+bUmMwB7/XnA0nNlts2CwNtbXm4Ozy0ZAYKHlCRmBQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/cascade-layer-name-parser': 1.0.1_ppok7cytzjc65mcyxmtit3wdyi + '@csstools/css-parser-algorithms': 2.0.1_5vzy4lghjvuzkedkkk4tqwjftm + '@csstools/css-tokenizer': 2.1.0 + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-dir-pseudo-class/7.0.2: + resolution: {integrity: sha512-cMnslilYxBf9k3qejnovrUONZx1rXeUZJw06fgIUBzABJe3D2LiLL5WAER7Imt3nrkaIgG05XZBztueLEf5P8w==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-double-position-gradients/4.0.2: + resolution: {integrity: sha512-GXL1RmFREDK4Q9aYvI2RhVrA6a6qqSMQQ5ke8gSH1xgV6exsqbcJpIumC7AOgooH6/WIG3/K/T8xxAiVHy/tJg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/postcss-progressive-custom-properties': 2.1.0 + postcss-value-parser: 4.2.0 + dev: true + /postcss-filter-plugins/3.0.1: resolution: {integrity: sha512-tRKbW4wWBEkSSFuJtamV2wkiV9rj6Yy7P3Y13+zaynlPEEZt8EgYKn3y/RBpMeIhNmHXFlSdzofml65hD5OafA==} dependencies: postcss: 6.0.23 dev: true + /postcss-flexbugs-fixes/5.0.2: + resolution: {integrity: sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==} + peerDependencies: + postcss: ^8.1.4 + dev: true + + /postcss-focus-visible/8.0.2: + resolution: {integrity: sha512-f/Vd+EC/GaKElknU59esVcRYr/Y3t1ZAQyL4u2xSOgkDy4bMCmG7VP5cGvj3+BTLNE9ETfEuz2nnt4qkZwTTeA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-focus-within/7.0.2: + resolution: {integrity: sha512-AHAJ89UQBcqBvFgQJE9XasGuwMNkKsGj4D/f9Uk60jFmEBHpAL14DrnSk3Rj+SwZTr/WUG+mh+Rvf8fid/346w==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-font-variant/5.0.0: + resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} + peerDependencies: + postcss: ^8.1.0 + dev: true + + /postcss-gap-properties/4.0.1: + resolution: {integrity: sha512-V5OuQGw4lBumPlwHWk/PRfMKjaq/LTGR4WDTemIMCaMevArVfCCA9wBJiL1VjDAd+rzuCIlkRoRvDsSiAaZ4Fg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dev: true + + /postcss-hover-media-feature/1.0.2: + resolution: {integrity: sha512-o5xDUqCQ4xtilWOcvo5LKYxFVSLWcBN0IlTqa0IJwAwHTd4pxKmX4c0fGIpgLQCcBB/+aFizt2NVWNGJWG4Izg==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + /postcss-icss-keyframes/0.2.1: resolution: {integrity: sha512-4m+hLY5TVqoTM198KKnzdNudyu1OvtqwD+8kVZ9PNiEO4+IfHYoyVvEXsOHjV8nZ1k6xowf+nY4HlUfZhOFvvw==} dependencies: @@ -5906,6 +6473,32 @@ packages: postcss: 6.0.23 dev: true + /postcss-image-set-function/5.0.2: + resolution: {integrity: sha512-Sszjwo0ubETX0Fi5MvpYzsONwrsjeabjMoc5YqHvURFItXgIu3HdCjcVuVKGMPGzKRhgaknmdM5uVWInWPJmeg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-initial/4.0.1: + resolution: {integrity: sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==} + peerDependencies: + postcss: ^8.0.0 + dev: true + + /postcss-lab-function/5.1.0: + resolution: {integrity: sha512-iZApRTNcpc71uTn7PkzjHtj5cmuZpvu6okX4jHnM5OFi2fG97sodjxkq6SpL65xhW0NviQrAMSX97ntyGVRV0w==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/color-helpers': 1.0.0 + '@csstools/postcss-progressive-custom-properties': 2.1.0 + postcss-value-parser: 4.2.0 + dev: true + /postcss-load-config/3.1.4_postcss@8.4.21: resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} @@ -5923,13 +6516,171 @@ packages: yaml: 1.10.2 dev: true + /postcss-logical/6.1.0: + resolution: {integrity: sha512-qb1+LpClhYjxac8SfOcWotnY3unKZesDqIOm+jnGt8rTl7xaIWpE2bPGZHxflOip1E/4ETo79qlJyRL3yrHn1g==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-media-minmax/5.0.0: + resolution: {integrity: sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.1.0 + dev: true + + /postcss-nested/6.0.1: + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-nesting/11.2.1: + resolution: {integrity: sha512-E6Jq74Jo/PbRAtZioON54NPhUNJYxVWhwxbweYl1vAoBYuGlDIts5yhtKiZFLvkvwT73e/9nFrW3oMqAtgG+GQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/selector-specificity': 2.1.1_laljekdltgzr3kfi7r4exvsr5a + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-opacity-percentage/1.1.3: + resolution: {integrity: sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + dev: true + + /postcss-overflow-shorthand/4.0.1: + resolution: {integrity: sha512-HQZ0qi/9iSYHW4w3ogNqVNr2J49DHJAl7r8O2p0Meip38jsdnRPgiDW7r/LlLrrMBMe3KHkvNtAV2UmRVxzLIg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-page-break/3.0.4: + resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} + peerDependencies: + postcss: ^8 + dev: true + + /postcss-place/8.0.1: + resolution: {integrity: sha512-Ow2LedN8sL4pq8ubukO77phSVt4QyCm35ZGCYXKvRFayAwcpgB0sjNJglDoTuRdUL32q/ZC1VkPBo0AOEr4Uiw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-value-parser: 4.2.0 + dev: true + + /postcss-preset-env/8.0.1: + resolution: {integrity: sha512-IUbymw0JlUbyVG+I85963PNWgPp3KhnFa1sxU7M/2dGthxV8e297P0VV5W9XcyypoH4hirH2fp1c6fmqh6YnSg==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + '@csstools/postcss-cascade-layers': 3.0.1 + '@csstools/postcss-color-function': 2.1.0 + '@csstools/postcss-font-format-keywords': 2.0.2 + '@csstools/postcss-hwb-function': 2.1.1 + '@csstools/postcss-ic-unit': 2.0.2 + '@csstools/postcss-is-pseudo-class': 3.1.1 + '@csstools/postcss-logical-float-and-clear': 1.0.1 + '@csstools/postcss-logical-resize': 1.0.1 + '@csstools/postcss-logical-viewport-units': 1.0.2 + '@csstools/postcss-media-queries-aspect-ratio-number-values': 1.0.1 + '@csstools/postcss-nested-calc': 2.0.2 + '@csstools/postcss-normalize-display-values': 2.0.1 + '@csstools/postcss-oklab-function': 2.1.0 + '@csstools/postcss-progressive-custom-properties': 2.1.0 + '@csstools/postcss-scope-pseudo-class': 2.0.2 + '@csstools/postcss-stepped-value-functions': 2.1.0 + '@csstools/postcss-text-decoration-shorthand': 2.2.1 + '@csstools/postcss-trigonometric-functions': 2.0.1 + '@csstools/postcss-unset-value': 2.0.1 + autoprefixer: 10.4.13 + browserslist: 4.21.5 + css-blank-pseudo: 5.0.2 + css-has-pseudo: 5.0.2 + css-prefers-color-scheme: 8.0.2 + cssdb: 7.4.1 + postcss-attribute-case-insensitive: 6.0.2 + postcss-clamp: 4.1.0 + postcss-color-functional-notation: 5.0.2 + postcss-color-hex-alpha: 9.0.2 + postcss-color-rebeccapurple: 8.0.2 + postcss-custom-media: 9.1.2 + postcss-custom-properties: 13.1.4 + postcss-custom-selectors: 7.1.2 + postcss-dir-pseudo-class: 7.0.2 + postcss-double-position-gradients: 4.0.2 + postcss-focus-visible: 8.0.2 + postcss-focus-within: 7.0.2 + postcss-font-variant: 5.0.0 + postcss-gap-properties: 4.0.1 + postcss-image-set-function: 5.0.2 + postcss-initial: 4.0.1 + postcss-lab-function: 5.1.0 + postcss-logical: 6.1.0 + postcss-media-minmax: 5.0.0 + postcss-nesting: 11.2.1 + postcss-opacity-percentage: 1.1.3 + postcss-overflow-shorthand: 4.0.1 + postcss-page-break: 3.0.4 + postcss-place: 8.0.1 + postcss-pseudo-class-any-link: 8.0.2 + postcss-replace-overflow-wrap: 4.0.0 + postcss-selector-not: 7.0.1 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-pseudo-class-any-link/8.0.2: + resolution: {integrity: sha512-FYTIuRE07jZ2CW8POvctRgArQJ43yxhr5vLmImdKUvjFCkR09kh8pIdlCwdx/jbFm7MiW4QP58L4oOUv3grQYA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-replace-overflow-wrap/4.0.0: + resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} + peerDependencies: + postcss: ^8.0.3 + dev: true + + /postcss-selector-not/7.0.1: + resolution: {integrity: sha512-1zT5C27b/zeJhchN7fP0kBr16Cc61mu7Si9uWWLoA3Px/D9tIJPKchJCkUH3tPO5D0pCFmGeApAv8XpXBQJ8SQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.4 + dependencies: + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-selector-parser/6.0.11: + resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + /postcss-value-parser/3.3.1: resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==} dev: true /postcss-value-parser/4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: false /postcss-values-parser/2.0.1: resolution: {integrity: sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==} @@ -6260,6 +7011,25 @@ packages: tslib: 2.5.0 dev: false + /react-remove-scroll/2.5.4_3stiutgnnbnfnf3uowm5cip22i: + resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.0.27 + react: 18.2.0 + react-remove-scroll-bar: 2.3.4_3stiutgnnbnfnf3uowm5cip22i + react-style-singleton: 2.2.1_3stiutgnnbnfnf3uowm5cip22i + tslib: 2.5.0 + use-callback-ref: 1.3.0_3stiutgnnbnfnf3uowm5cip22i + use-sidecar: 1.1.2_3stiutgnnbnfnf3uowm5cip22i + dev: false + /react-remove-scroll/2.5.5_3stiutgnnbnfnf3uowm5cip22i: resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} engines: {node: '>=10'} @@ -7329,7 +8099,6 @@ packages: browserslist: 4.21.5 escalade: 3.1.1 picocolors: 1.0.0 - dev: false /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 00000000..93076637 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,17 @@ +module.exports = { + plugins: [ + "postcss-nested", + "postcss-flexbugs-fixes", + "postcss-hover-media-feature", + [ + "postcss-preset-env", + { + stage: 3, + features: { + "custom-media-queries": true, + "custom-properties": false + } + } + ] + ] +} diff --git a/src/app/(drift)/(posts)/new/components/new.tsx b/src/app/(drift)/(posts)/new/components/new.tsx index 5c5f74a5..9b78e927 100644 --- a/src/app/(drift)/(posts)/new/components/new.tsx +++ b/src/app/(drift)/(posts)/new/components/new.tsx @@ -269,7 +269,8 @@ function Post({ ]) }} style={{ - flex: 1 + flex: 1, + minWidth: 120 }} > Add a File diff --git a/src/app/(drift)/(posts)/new/components/post.module.css b/src/app/(drift)/(posts)/new/components/post.module.css index 3db64707..4d7758c0 100644 --- a/src/app/(drift)/(posts)/new/components/post.module.css +++ b/src/app/(drift)/(posts)/new/components/post.module.css @@ -37,7 +37,7 @@ .buttons .rightButtons { flex-direction: column; - align-items: flex-end; + align-items: flex-start; } .buttons .rightButtons > * { diff --git a/src/app/(drift)/layout.tsx b/src/app/(drift)/layout.tsx index e3c6ce56..c2cec48c 100644 --- a/src/app/(drift)/layout.tsx +++ b/src/app/(drift)/layout.tsx @@ -5,9 +5,13 @@ import { Toasts } from "@components/toasts" import Header from "@components/header" import { Inter } from "next/font/google" import { getMetadata } from "src/app/lib/metadata" +import dynamic from "next/dynamic" const inter = Inter({ subsets: ["latin"], variable: "--inter-font" }) +// const CmdK = dynamic(() => import("@components/cmdk"), { ssr: false }) +import CmdK from "@components/cmdk" + export default async function RootLayout({ children }: { @@ -18,12 +22,13 @@ export default async function RootLayout({ - - + + +
{children} - - + + ) diff --git a/src/app/components/cmdk/cmdk.module.css b/src/app/components/cmdk/cmdk.module.css new file mode 100644 index 00000000..4436b9e6 --- /dev/null +++ b/src/app/components/cmdk/cmdk.module.css @@ -0,0 +1,165 @@ +/** Based on https://github.com/pacocoursey/cmdk **/ +.cmdk[cmdk-root] { + overflow: hidden; + font-family: var(--font-sans); + box-shadow: 0 0 0 1px var(--lighter-gray), 0 4px 16px rgba(0, 0, 0, 0.2); + transition: transform 100ms ease; + border-radius: var(--radius); + + .dark & { + background: rgba(22, 22, 22, 0.7); + } +} + +.cmdk { + /* centered */ + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 999999; + /* size */ + max-width: 640px; + width: 100%; + + [cmdk-list] { + background: var(--bg); + height: 500px; + overflow: auto; + overscroll-behavior: contain; + } + + [cmdk-input] { + font-family: var(--font-sans); + width: 100%; + font-size: 17px; + padding: 8px 8px 16px 8px; + outline: none; + /* background: var(--lightest-gray); */ + color: var(--fg); + + &::placeholder { + color: var(--gray); + } + } + + [cmdk-badge] { + height: 20px; + background: var(--grayA3); + display: inline-flex; + align-items: center; + padding: 0 8px; + font-size: 12px; + color: var(--grayA11); + border-radius: 4px; + margin: 4px 0 4px 4px; + user-select: none; + text-transform: capitalize; + font-weight: 500; + } + + [cmdk-item] { + content-visibility: auto; + + cursor: pointer; + height: 48px; + border-radius: 8px; + font-size: 14px; + display: flex; + align-items: center; + gap: 8px; + padding: 0 16px; + color: var(--darker-gray); + user-select: none; + will-change: background, color; + transition: all 150ms ease; + transition-property: none; + background: var(--bg); + + &[aria-selected="true"] { + background: var(--lightest-gray); + color: var(--fg); + } + + &[aria-disabled="true"] { + /* TODO: improve this */ + color: var(--bg); + cursor: not-allowed; + } + + &:active { + transition-property: background; + background: var(--bg); + } + + & + [cmdk-item] { + margin-top: 4px; + } + + svg { + width: 18px; + height: 18px; + } + } + + [cmdk-list] { + max-height: 400px; + overflow: auto; + overscroll-behavior: contain; + transition: 100ms ease; + transition-property: height; + } + + [cmdk-shortcuts] { + display: flex; + margin-left: auto; + gap: 8px; + + kbd { + font-family: var(--font-sans); + font-size: 12px; + min-width: 20px; + padding: var(--gap-half); + height: 20px; + border-radius: 4px; + color: var(--fg); + background: var(--light-gray); + display: inline-flex; + align-items: center; + justify-content: center; + text-transform: uppercase; + } + } + + [cmdk-separator] { + height: 1px; + width: 100%; + background: var(--light-gray); + margin: 4px 0; + } + + *:not([hidden]) + [cmdk-group] { + margin-top: var(--gap); + } + + [cmdk-group-heading] { + user-select: none; + font-size: 12px; + color: var(--gray); + padding: 0 var(--gap); + display: flex; + align-items: center; + margin-bottom: var(--gap); + margin-top: var(--gap); + } + + [cmdk-empty] { + font-size: 14px; + display: flex; + align-items: center; + justify-content: center; + height: 48px; + white-space: pre-wrap; + color: var(--gray); + } +} diff --git a/src/app/components/cmdk/dialog.css b/src/app/components/cmdk/dialog.css new file mode 100644 index 00000000..5e75a6dc --- /dev/null +++ b/src/app/components/cmdk/dialog.css @@ -0,0 +1,16 @@ +body [cmdk-dialog] { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 999999; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.5); + /* backdrop-filter: blur(4px); */ + transition: opacity 100ms ease; + pointer-events: none; + will-change: opacity; +} diff --git a/src/app/components/cmdk/index.tsx b/src/app/components/cmdk/index.tsx new file mode 100644 index 00000000..cbfe6989 --- /dev/null +++ b/src/app/components/cmdk/index.tsx @@ -0,0 +1,74 @@ +"use client" + +import FadeIn from "@components/fade-in" +import { Command } from "cmdk" +import { useEffect, useRef, useState } from "react" +import styles from "./cmdk.module.css" +import "./dialog.css" +import HomePage from "./pages/home" +import PostsPage from "./pages/posts" + +export type CmdKPage = "home" | "posts" +export default function CmdK() { + const [open, setOpen] = useState(false) + const ref = useRef(null) + const [page, setPage] = useState("home") + + // Toggle the menu when ⌘K is pressed + useEffect(() => { + const openCloseListener = (e: KeyboardEvent) => { + if (e.key === "k" && e.metaKey) { + e.preventDefault() + setOpen((open) => !open) + } else if (e.key === "Escape") { + e.preventDefault() + if (page !== "home") { + setPage("home") + // TODO: this shouldn't be necessary? + setOpen(true) + } else { + setOpen(false) + } + } + } + + document.addEventListener("keydown", openCloseListener) + return () => { + document.removeEventListener("keydown", openCloseListener) + } + }, [page]) + + function bounce() { + if (ref.current) { + ref.current.style.transform = "translate(-50%, -50%) scale(0.96)" + setTimeout(() => { + if (ref.current) { + ref.current.style.transform = "" + } + }, 100) + } + } + // bounce on page change + useEffect(() => { + bounce() + }, [page]) + + return ( + + + No results found. + {page === "home" ? ( + + ) : null} + {page === "posts" ? : null} + + + + ) +} diff --git a/src/app/components/cmdk/item.tsx b/src/app/components/cmdk/item.tsx new file mode 100644 index 00000000..ca337a88 --- /dev/null +++ b/src/app/components/cmdk/item.tsx @@ -0,0 +1,27 @@ +import { Command } from "cmdk" + +export default function Item({ + children, + shortcut, + onSelect, + icon +}: { + children: React.ReactNode + shortcut?: string + onSelect: (value: string) => void + icon: React.ReactNode +}): JSX.Element { + return ( + + {icon} + {children} + {shortcut ? ( +
+ {shortcut.split(" ").map((key) => { + return {key} + })} +
+ ) : null} +
+ ) +} diff --git a/src/app/components/cmdk/pages/home.tsx b/src/app/components/cmdk/pages/home.tsx new file mode 100644 index 00000000..68980b37 --- /dev/null +++ b/src/app/components/cmdk/pages/home.tsx @@ -0,0 +1,64 @@ +import { Command } from "cmdk" +import { useTheme } from "next-themes" +import { useRouter } from "next/navigation" +import { FilePlus, Moon, Search, Settings, Sun } from "react-feather" +import { CmdKPage } from ".." +import Item from "../item" + +export default function HomePage({ + setOpen, + setPage +}: { + setOpen: (open: boolean) => void + setPage: (page: CmdKPage) => void +}) { + const router = useRouter() + const { setTheme, resolvedTheme } = useTheme() + return ( + <> + + { + setPage("posts") + }} + icon={} + > + Your Recent Posts + + { + router.push("/new") + setOpen(false) + }} + icon={} + > + New Post + + + + { + console.log("toggle theme", resolvedTheme) + setTheme(resolvedTheme === "dark" ? "light" : "dark") + }} + icon={resolvedTheme === "dark" ? : } + > + Toggle Theme + + { + router.push("/settings") + setOpen(false) + }} + icon={} + > + Go to Settings + + + + ) +} diff --git a/src/app/components/cmdk/pages/posts.tsx b/src/app/components/cmdk/pages/posts.tsx new file mode 100644 index 00000000..86ebc954 --- /dev/null +++ b/src/app/components/cmdk/pages/posts.tsx @@ -0,0 +1,53 @@ +import { Spinner } from "@components/spinner" +import { PostWithFiles } from "@lib/server/prisma" +import { useSessionSWR } from "@lib/use-session-swr" +import { useRouter } from "next/navigation" +import { useEffect, useState } from "react" +import { File } from "react-feather" +import { fetchWithUser } from "src/app/lib/fetch-with-user" +import Item from "../item" + +export default function PostsPage({ setOpen }: { + setOpen: (open: boolean) => void +}) { + const { session } = useSessionSWR() + const [posts, setPosts] = useState() + const [isLoading, setLoading] = useState(true) + + useEffect(() => { + async function getPosts() { + if (!session) return + const data = await fetchWithUser(`/api/user/${session?.user.id}/posts/`, { + method: "GET" + }) + + const posts = (await data.json()) as PostWithFiles[] + setPosts(posts) + setLoading(false) + } + getPosts() + }, [session]) + + const router = useRouter() + return ( + <> + {isLoading && ( +
+ +
+ )} + {posts?.map((post) => ( + { + router.push(`/post/${post.id}`) + setOpen(false) + }} + key={post.id} + icon={} + > + {post.title} + + ))} + + ) +} diff --git a/src/app/styles/globals.css b/src/app/styles/globals.css index 038067a3..eaf51623 100644 --- a/src/app/styles/globals.css +++ b/src/app/styles/globals.css @@ -16,8 +16,9 @@ --gap-quarter-negative: calc(-1 * var(--gap-quarter)); /* Typography */ - --font-sans: var(--inter-font), -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --font-sans: var(--inter-font), -apple-system, BlinkMacSystemFont, Segoe UI, + Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, + sans-serif; --font-mono: ui-monospace, "SFMono-Regular", "Consolas", "Liberation Mono", "Menlo", monospace; @@ -69,11 +70,10 @@ --article-color: #212121; --header-bg: rgba(255, 255, 255, 0.8); --gray-alpha: rgba(19, 20, 21, 0.5); - --selection: var(0, 0, 0, .6); + --selection: var(0, 0, 0, 0.6); color-scheme: light; } - * { box-sizing: border-box; } @@ -207,7 +207,7 @@ h6 { margin: 0; } -h1, +h1, h2, h3, h4, diff --git a/src/pages/api/user/[id].ts b/src/pages/api/user/[userId]/index.ts similarity index 71% rename from src/pages/api/user/[id].ts rename to src/pages/api/user/[userId]/index.ts index c30c500e..ec04ff37 100644 --- a/src/pages/api/user/[id].ts +++ b/src/pages/api/user/[userId]/index.ts @@ -1,33 +1,31 @@ -import { parseQueryParam } from "@lib/server/parse-query-param" import { getUserById } from "@lib/server/prisma" import { NextApiRequest, NextApiResponse } from "next" import { prisma } from "src/lib/server/prisma" import { withMethods } from "@lib/api-middleware/with-methods" import { getSession } from "next-auth/react" +import { verifyApiUser } from "@lib/server/verify-api-user" const handler = async (req: NextApiRequest, res: NextApiResponse) => { - const id = parseQueryParam(req.query.id) - if (!id) { - return res.status(400).json({ error: "Missing id" }) + const userId = await verifyApiUser(req, res) + + if (!userId) { + return res.status(400).json({ error: "Missing userId or auth token" }) } - const user = await getUserById(id) - const currUser = (await getSession({ req }))?.user + const [session, user] = await Promise.all([ + // TODO; this call is duplicated in veryfiyApiUser + getSession({ req }), + getUserById(userId) + ]) - if (!user) { - return res.status(404).json({ message: "User not found" }) - } - - if (user.id !== currUser?.id) { - return res.status(403).json({ message: "Unauthorized" }) - } + const currUser = session?.user switch (req.method) { case "PUT": { const { displayName } = req.body const updatedUser = await prisma.user.update({ where: { - id + id: userId }, data: { displayName @@ -44,14 +42,14 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { case "GET": return res.json({ ...currUser, - displayName: user.displayName + displayName: user?.displayName }) case "DELETE": - if (currUser?.role !== "admin" && currUser?.id !== id) { + if (currUser?.role !== "admin") { return res.status(403).json({ message: "Unauthorized" }) } - await deleteUser(id) + await deleteUser(userId) break default: return res.status(405).json({ message: "Method not allowed" }) diff --git a/src/pages/api/user/[userId]/posts/index.ts b/src/pages/api/user/[userId]/posts/index.ts new file mode 100644 index 00000000..3ba6570c --- /dev/null +++ b/src/pages/api/user/[userId]/posts/index.ts @@ -0,0 +1,43 @@ +import { verifyApiUser } from "@lib/server/verify-api-user" +import { NextApiRequest, NextApiResponse } from "next" +import { prisma } from "@lib/server/prisma" + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const userId = await verifyApiUser(req, res) + if (!userId) { + return res.status(400).json({ error: "Missing userId or auth token" }) + } + + const userPosts = await prisma.post.findMany({ + where: { + authorId: userId + }, + select: { + id: true, + title: true, + files: { + select: { + id: true, + content: true, + title: true, + sha: true, + updatedAt: true, + createdAt: true, + deletedAt: true + } + }, + createdAt: true, + updatedAt: true, + deletedAt: true, + authorId: true, + parentId: true, + description: true, + visibility: true + } + }) + + res.status(200).json(userPosts) +}