Add category filter to React UI
This commit is contained in:
@@ -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
285
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
47
src/components/Card.css
Normal 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
19
src/components/Card.jsx
Normal 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>
|
||||
}
|
||||
6
src/components/CardsContainer.css
Normal file
6
src/components/CardsContainer.css
Normal 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);
|
||||
}
|
||||
33
src/components/CardsContainer.jsx
Normal file
33
src/components/CardsContainer.jsx
Normal 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>
|
||||
}
|
||||
3
src/components/CategoryNav.css
Normal file
3
src/components/CategoryNav.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.nav {
|
||||
box-shadow: inset 0px -1px 0px var(--border-muted);
|
||||
}
|
||||
23
src/components/CategoryNav.jsx
Normal file
23
src/components/CategoryNav.jsx
Normal 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>
|
||||
}
|
||||
18
src/components/CategoryNavItem.css
Normal file
18
src/components/CategoryNavItem.css
Normal 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);
|
||||
}
|
||||
26
src/components/CategoryNavItem.jsx
Normal file
26
src/components/CategoryNavItem.jsx
Normal 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>
|
||||
}
|
||||
13
src/components/Dashboard.jsx
Normal file
13
src/components/Dashboard.jsx
Normal 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} />
|
||||
</>
|
||||
}
|
||||
@@ -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>
|
||||
@@ -1,3 +1,7 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user