Add category filter to React UI

This commit is contained in:
Steve Paul
2023-12-19 00:49:07 +05:30
parent 5a30e2bed8
commit 983a456aaa
15 changed files with 427 additions and 199 deletions

View File

@@ -1,8 +1,11 @@
import { defineConfig } from 'astro/config';
import netlify from "@astrojs/netlify/functions";
import react from "@astrojs/react";
// https://astro.build/config
export default defineConfig({
output: "server",
adapter: netlify()
});
adapter: netlify(),
integrations: [react()]
});

285
package-lock.json generated
View File

@@ -9,7 +9,12 @@
"version": "0.1.0",
"dependencies": {
"@astrojs/netlify": "^3.1.1",
"astro": "^4.0.3"
"@astrojs/react": "^3.0.7",
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18",
"astro": "^4.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@new-ui/colors": "^1.2.11",
@@ -88,6 +93,24 @@
"node": ">=18.14.1"
}
},
"node_modules/@astrojs/react": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/@astrojs/react/-/react-3.0.7.tgz",
"integrity": "sha512-MpjuFw7YGta44OaQExKVCWyXjujUtUsp5Nst/wIjRHbkmBBlypdj+MF9/xqjsYM+vjcrByOGupmluRrFQO67YQ==",
"dependencies": {
"@vitejs/plugin-react": "^4.2.0",
"ultrahtml": "^1.3.0"
},
"engines": {
"node": ">=18.14.1"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",
"@types/react-dom": "^17.0.17 || ^18.0.6",
"react": "^17.0.2 || ^18.0.0",
"react-dom": "^17.0.2 || ^18.0.0"
}
},
"node_modules/@astrojs/telemetry": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.4.tgz",
@@ -111,9 +134,9 @@
"integrity": "sha512-qDAKhFO4M1KzP7mxoJfiehf8oyf3EB158MxAa6z10NeD2pR3o4K3LlOQI8CfJgXE+BDBQcnaLvVCg/Mz/Gkg4Q=="
},
"node_modules/@babel/code-frame": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz",
"integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==",
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
"integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
"dependencies": {
"@babel/highlight": "^7.23.4",
"chalk": "^2.4.2"
@@ -123,28 +146,28 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz",
"integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==",
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz",
"integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz",
"integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz",
"integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.23.3",
"@babel/helper-compilation-targets": "^7.22.15",
"@babel/code-frame": "^7.23.5",
"@babel/generator": "^7.23.6",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-module-transforms": "^7.23.3",
"@babel/helpers": "^7.23.2",
"@babel/parser": "^7.23.3",
"@babel/helpers": "^7.23.6",
"@babel/parser": "^7.23.6",
"@babel/template": "^7.22.15",
"@babel/traverse": "^7.23.3",
"@babel/types": "^7.23.3",
"@babel/traverse": "^7.23.6",
"@babel/types": "^7.23.6",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -168,11 +191,11 @@
}
},
"node_modules/@babel/generator": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.4.tgz",
"integrity": "sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz",
"integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
"dependencies": {
"@babel/types": "^7.23.4",
"@babel/types": "^7.23.6",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
@@ -193,13 +216,13 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
"integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz",
"integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==",
"dependencies": {
"@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.22.15",
"browserslist": "^4.21.9",
"@babel/compat-data": "^7.23.5",
"@babel/helper-validator-option": "^7.23.5",
"browserslist": "^4.22.2",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
@@ -322,21 +345,21 @@
}
},
"node_modules/@babel/helper-validator-option": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
"integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
"integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.4.tgz",
"integrity": "sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz",
"integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==",
"dependencies": {
"@babel/template": "^7.22.15",
"@babel/traverse": "^7.23.4",
"@babel/types": "^7.23.4"
"@babel/traverse": "^7.23.6",
"@babel/types": "^7.23.6"
},
"engines": {
"node": ">=6.9.0"
@@ -356,9 +379,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz",
"integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -398,6 +421,34 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-react-jsx-self": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz",
"integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-react-jsx-source": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz",
"integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/template": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
@@ -412,19 +463,19 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.4.tgz",
"integrity": "sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz",
"integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==",
"dependencies": {
"@babel/code-frame": "^7.23.4",
"@babel/generator": "^7.23.4",
"@babel/code-frame": "^7.23.5",
"@babel/generator": "^7.23.6",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.4",
"@babel/types": "^7.23.4",
"debug": "^4.1.0",
"@babel/parser": "^7.23.6",
"@babel/types": "^7.23.6",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
"engines": {
@@ -432,9 +483,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz",
"integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==",
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
"integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
"dependencies": {
"@babel/helper-string-parser": "^7.23.4",
"@babel/helper-validator-identifier": "^7.22.20",
@@ -1133,6 +1184,34 @@
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
},
"node_modules/@types/prop-types": {
"version": "15.7.11",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
},
"node_modules/@types/react": {
"version": "18.2.45",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz",
"integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==",
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.2.18",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz",
"integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/scheduler": {
"version": "0.16.8",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
},
"node_modules/@types/unist": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz",
@@ -1143,6 +1222,24 @@
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
},
"node_modules/@vitejs/plugin-react": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz",
"integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==",
"dependencies": {
"@babel/core": "^7.23.5",
"@babel/plugin-transform-react-jsx-self": "^7.23.3",
"@babel/plugin-transform-react-jsx-source": "^7.23.3",
"@types/babel__core": "^7.20.5",
"react-refresh": "^0.14.0"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"peerDependencies": {
"vite": "^4.2.0 || ^5.0.0"
}
},
"node_modules/acorn": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
@@ -1477,9 +1574,9 @@
}
},
"node_modules/browserslist": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
"integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
"version": "4.22.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
"integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
"funding": [
{
"type": "opencollective",
@@ -1495,9 +1592,9 @@
}
],
"dependencies": {
"caniuse-lite": "^1.0.30001541",
"electron-to-chromium": "^1.4.535",
"node-releases": "^2.0.13",
"caniuse-lite": "^1.0.30001565",
"electron-to-chromium": "^1.4.601",
"node-releases": "^2.0.14",
"update-browserslist-db": "^1.0.13"
},
"bin": {
@@ -1542,9 +1639,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001565",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz",
"integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==",
"version": "1.0.30001570",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz",
"integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==",
"funding": [
{
"type": "opencollective",
@@ -1793,6 +1890,11 @@
"node": ">= 8"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1917,9 +2019,9 @@
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.595",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.595.tgz",
"integrity": "sha512-+ozvXuamBhDOKvMNUQvecxfbyICmIAwS4GpLmR0bsiSBlGnLaOcs2Cj7J8XSbW+YEaN3Xl3ffgpm+srTUWFwFQ=="
"version": "1.4.614",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz",
"integrity": "sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ=="
},
"node_modules/emoji-regex": {
"version": "10.3.0",
@@ -2844,6 +2946,17 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -3785,9 +3898,9 @@
"optional": true
},
"node_modules/node-releases": {
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -4338,6 +4451,37 @@
"rc": "cli.js"
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
},
"peerDependencies": {
"react": "^18.2.0"
}
},
"node_modules/react-refresh": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
"integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -5033,6 +5177,14 @@
"resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz",
"integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA=="
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
@@ -5477,6 +5629,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ultrahtml": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.5.2.tgz",
"integrity": "sha512-qh4mBffhlkiXwDAOxvSGxhL0QEQsTbnP9BozOK3OYPEGvPvdWzvAUaXNtUSMdNsKDtuyjEbyVUPFZ52SSLhLqw=="
},
"node_modules/unherit": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz",

View File

@@ -11,7 +11,12 @@
},
"dependencies": {
"@astrojs/netlify": "^3.1.1",
"astro": "^4.0.3"
"@astrojs/react": "^3.0.7",
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.18",
"astro": "^4.0.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@new-ui/colors": "^1.2.11",

View File

@@ -1,63 +0,0 @@
---
export interface Props {
title: string;
body: string;
tag: string;
href: string;
}
const { href, title, body, tag } = Astro.props;
---
<li class="link-card">
<a href={href}>
<h6 class="nu-c-h6 nu-u-mt-1 nu-u-mb-1">
{title}
</h6>
<p class="nu-c-fs-small nu-u-mt-1 nu-u-mb-1">
{body}
</p>
<p class="distribution">
<span class="tag">{tag}</span>
</p>
</a>
</li>
<style>
.link-card {
list-style: none;
display: flex;
background-color: var(--background-secondary);
background-position: 100%;
border: 1px solid transparent;
border-radius: var(--spacing-03);
height: 136px;
position: relative;
box-shadow: 0px 2px 4px 0px rgba(22, 22, 22, 0.08), 0px 8px 12px -8px rgba(22, 22, 22, 0.08);
}
.link-card > a {
width: 100%;
text-decoration: none;
padding: 0.8rem 1.2rem;
color: var(--support-info);
}
p {
color: var(--text-secondary);
}
.link-card:is(:hover, :focus-within) {
background-position: 0;
border: 1px solid var(--border);
}
.link-card:is(:hover, :focus-within) h6 {}
p.distribution {margin: var(--spacing-00); position: absolute; bottom: var(--spacing-06);}
span.tag {
background-color: var(--background-selected);
padding: 2px 8px;
border-radius: 24px;
display: inline-block;
color: var(--text-primary-alt);
margin-top: var(--spacing-08);
font-size: var(--desktop-caption);
line-height: var(--lh-desktop-caption);
font-family: var(--system-ui);
}
</style>

47
src/components/Card.css Normal file
View File

@@ -0,0 +1,47 @@
.link-card {
list-style: none;
display: flex;
background-color: var(--background-secondary);
background-position: 100%;
border: 1px solid transparent;
border-radius: var(--spacing-03);
height: 136px;
position: relative;
box-shadow: 0px 2px 4px 0px rgba(22, 22, 22, 0.08), 0px 8px 12px -8px rgba(22, 22, 22, 0.08);
}
.link-card>a {
width: 100%;
text-decoration: none;
padding: 0.8rem 1.2rem;
color: var(--support-info);
}
p {
color: var(--text-secondary);
}
.link-card:is(:hover, :focus-within) {
background-position: 0;
border: 1px solid var(--border);
}
.link-card:is(:hover, :focus-within) h6 {}
p.distribution {
margin: var(--spacing-00);
position: absolute;
bottom: var(--spacing-06);
}
span.tag {
background-color: var(--background-selected);
padding: 2px 8px;
border-radius: 24px;
display: inline-block;
color: var(--text-primary-alt);
margin-top: var(--spacing-08);
font-size: var(--desktop-caption);
line-height: var(--lh-desktop-caption);
font-family: var(--system-ui);
}

19
src/components/Card.jsx Normal file
View File

@@ -0,0 +1,19 @@
import "./Card.css";
export default function Card(props) {
const {href, title, body, tag} = props;
return <li className="link-card">
<a href={href}>
<h6 className="nu-c-h6 nu-u-mt-1 nu-u-mb-1">
{title}
</h6>
<p className="nu-c-fs-small nu-u-mt-1 nu-u-mb-1">
{body}
</p>
<p className="distribution">
<span className="tag">{tag}</span>
</p>
</a>
</li>
}

View File

@@ -0,0 +1,6 @@
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: var(--spacing-05);
padding: var(--spacing-00);
}

View File

@@ -0,0 +1,33 @@
import Card from "./Card";
import "./CardsContainer.css";
import data from "../data/tools.json"
export default function CardsContainer(props) {
const { filter } = props;
return <section>
<ul role="list" className="link-card-grid">
{data.tools
.filter(item => {
if (filter === "all" || filter === item.category) {
return item;
}
})
.flatMap(item => item.content)
.sort((a, b) => {
return a.title < b.title ? -1 : 1;
})
.map(({url, title, body, tag}, i) => {
return <Card
key={i}
href={url}
title={title}
body={body}
tag={tag}
/>
})
}
</ul>
</section>
}

View File

@@ -0,0 +1,3 @@
.nav {
box-shadow: inset 0px -1px 0px var(--border-muted);
}

View File

@@ -0,0 +1,23 @@
import "./CategoryNav.css";
import data from "../data/tools.json";
import CategoryNavItem from "./CategoryNavItem";
export default function CategoryNav({ filter, setFilter }) {
const navItems = [
{title: "🔥 All", category: "all"},
...data.tools
];
return <nav className="nav">
{navItems.map((c, i) => {
return <CategoryNavItem
key={i}
title={c.title}
category={c.category}
filter={filter}
setFilter={setFilter}
/>
})}
</nav>
}

View File

@@ -0,0 +1,18 @@
.nav__item {
display: inline-block;
text-decoration: none;
border: none;
outline: none;
background: none;
cursor: pointer;
}
.nav__item:hover {
color: var(--text-secondary);
}
.nav__item.is-active {
color: var(--text-primary);
font-weight: 500;
border-bottom: 2px solid var(--icon-primary);
}

View File

@@ -0,0 +1,26 @@
import { useState, useEffect, useCallback } from "react";
import "./CategoryNavItem.css";
export default function CategoryNavItem(props) {
const { title, category, filter, setFilter } = props;
const [isActive, setIsActive] = useState(false);
useEffect(() => {
let subscription = true;
if (filter === category) {
setIsActive(true);
} else {
setIsActive(false);
}
return (() => (subscription = !subscription));
}, [filter]);
return <button
onClick={() => setFilter(category)}
className={`nav__item nu-u-text--secondary-alt nu-c-fs-normal nu-u-py-5 nu-u-px-0 nu-u-me-8 nav__item--filter ${isActive ? 'is-active' : ''}`}
dangerouslySetInnerHTML={{__html: title}}
>
</button>
}

View File

@@ -0,0 +1,13 @@
import { useState } from "react";
import CategoryNav from "./CategoryNav";
import CardsContainer from "./CardsContainer";
export default function Dashboard() {
const [filter, setFilter] = useState("all");
return <>
<CategoryNav filter={filter} setFilter={setFilter} />
<CardsContainer filter={filter} />
</>
}

View File

@@ -1,13 +1,11 @@
---
import Layout from "../layouts/Layout.astro";
import Card from "../components/Card.astro";
import data from "../data/tools.json";
import "@new-ui/colors";
import "@new-ui/typography";
import "@new-ui/effects";
import "@new-ui/spacings";
import Dashboard from "../components/Dashboard";
---
<Layout
@@ -16,46 +14,7 @@ import "@new-ui/spacings";
tagline="A curated set of powerful AI tools for makers."
>
<main>
<nav class="nav">
{
[{title: "🔥 All", category: "all"}, ...data.tools]
.map(section => ({title: section.title, category: section.category}))
.map(navItem => {
let classNames = "nav__item nu-u-text--secondary-alt nu-c-fs-normal nu-u-py-5 nu-u-px-0 nu-u-me-8";
if (navItem.category === "all") {
classNames += " is-active"
}
return <button
class={classNames}
set:html={navItem.title}
>
</button>
})
}
</nav>
<section>
<ul role="list" class="link-card-grid">
{data.tools
.filter(item => {
if (true) {
return item;
}
})
.flatMap(item => item.content)
.sort((a, b) => {
return a.title < b.title ? -1 : 1;
})
.map(({url, title, body, tag}) => {
return <Card
href={url}
title={title}
body={body}
tag={tag}
/>
})
}
</ul>
</section>
<Dashboard client:load />
</main>
</Layout>
@@ -81,29 +40,4 @@ import "@new-ui/spacings";
h6.separator:after {
left: 1%;
}
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: var(--spacing-05);
padding: var(--spacing-00);
}
.nav {
box-shadow: inset 0px -1px 0px var(--border-muted);
}
.nav .nav__item {
display: inline-block;
text-decoration: none;
border: none;
outline: none;
background: none;
cursor: pointer;
}
.nav .nav__item:hover {
color: var(--text-secondary);
}
.nav .nav__item.is-active {
color: var(--text-primary);
font-weight: 500;
border-bottom: 2px solid var(--icon-primary);
}
</style>

View File

@@ -1,3 +1,7 @@
{
"extends": "astro/tsconfigs/strict"
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}