diff --git a/README.md b/README.md index a77a4f0..3828d71 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,4 @@ Run development Server ```bash yarn start ``` +# keplr-example diff --git a/package.json b/package.json index 1aa17e9..7101b26 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@types/react-dom": "^18.2.7", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.21.3", "react-scripts": "5.0.1", "typescript": "^4.9.5" }, @@ -42,12 +43,14 @@ "devDependencies": { "buffer": "^6.0.3", "crypto-browserify": "^3.12.0", + "daisyui": "^4.6.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "process": "^0.11.10", "react-app-rewired": "^2.2.1", "stream-browserify": "^3.0.0", "stream-http": "^3.2.0", + "tailwindcss": "^3.4.1", "ts-proto": "^1.157.0", "zx": "^7.2.3" } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..8ff29e0 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + tailwindcss: {}, + + autoprefixer: {}, + }, +}; diff --git a/public/fakeData.json b/public/fakeData.json new file mode 100644 index 0000000..3f7fd96 --- /dev/null +++ b/public/fakeData.json @@ -0,0 +1,23 @@ +[ + { + "id": "1", + "name": "Widget A", + "description": "A high-quality widget with advanced features.", + "amount": 15, + "price": 29.99 + }, + { + "id": "2", + "name": "Gizmo B", + "description": "An innovative gizmo for everyday use.", + "amount": 8, + "price": 49.99 + }, + { + "id": "3", + "name": "Doohickey C", + "description": "The latest doohickey with cutting-edge technology.", + "amount": 20, + "price": 39.99 + } +] diff --git a/public/index.html b/public/index.html index 0e4f9c5..ae6d041 100644 --- a/public/index.html +++ b/public/index.html @@ -9,6 +9,7 @@ content="Web site created using create-react-app" /> Keplr Example App +
diff --git a/src/App.tsx b/src/App.tsx index 71d3871..0fce5b4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,185 +1,9 @@ -import React, {useEffect} from 'react'; -import {getKeplrFromWindow} from "./util/getKeplrFromWindow"; -import {OsmosisChainInfo} from "./constants"; -import {Balances} from "./types/balance"; -import {Dec, DecUtils} from "@keplr-wallet/unit"; -import {sendMsgs} from "./util/sendMsgs"; -import {api} from "./util/api"; -import {simulateMsgs} from "./util/simulateMsgs"; -import {MsgSend} from "./proto-types-gen/src/cosmos/bank/v1beta1/tx"; import "./styles/container.css"; import "./styles/button.css"; import "./styles/item.css"; function App() { - const [address, setAddress] = React.useState(''); - const [balance, setBalance] = React.useState(''); - - const [recipient, setRecipient] = React.useState(''); - const [amount, setAmount] = React.useState(''); - - useEffect(() => { - init(); - }, []); - - const init = async () => { - const keplr = await getKeplrFromWindow(); - - if(keplr) { - try { - await keplr.experimentalSuggestChain(OsmosisChainInfo); - } catch (e) { - if (e instanceof Error) { - console.log(e.message); - } - } - } - } - - const getKeyFromKeplr = async () => { - const key = await window.keplr?.getKey(OsmosisChainInfo.chainId); - if (key) { - setAddress(key.bech32Address) - } - } - - const getBalance = async () => { - const key = await window.keplr?.getKey(OsmosisChainInfo.chainId); - - if (key) { - const uri = `${OsmosisChainInfo.rest}/cosmos/bank/v1beta1/balances/${key.bech32Address}?pagination.limit=1000`; - - const data = await api(uri); - const balance = data.balances.find((balance) => balance.denom === "uosmo"); - const osmoDecimal = OsmosisChainInfo.currencies.find((currency) => currency.coinMinimalDenom === "uosmo")?.coinDecimals; - - if(balance) { - const amount = new Dec(balance.amount, osmoDecimal); - setBalance(`${amount.toString(osmoDecimal)} OSMO`) - } else { - setBalance(`0 OSMO`) - } - } - } - - const sendBalance = async () => { - if (window.keplr) { - const key = await window.keplr.getKey(OsmosisChainInfo.chainId); - const protoMsgs = { - typeUrl: "/cosmos.bank.v1beta1.MsgSend", - value: MsgSend.encode({ - fromAddress: key.bech32Address, - toAddress: recipient, - amount: [ - { - denom: "uosmo", - amount: DecUtils.getTenExponentN(6).mul(new Dec(amount)).truncate().toString(), - }, - ], - }).finish(), - } - - try { - const gasUsed = await simulateMsgs( - OsmosisChainInfo, - key.bech32Address, - [protoMsgs], - [{denom: "uosmo", - amount: "236",}] - ); - - if(gasUsed) { - await sendMsgs( - window.keplr, - OsmosisChainInfo, - key.bech32Address, - [protoMsgs], - { - amount: [{denom: "uosmo", - amount: "236",}], - gas: Math.floor(gasUsed * 1.5).toString(), - }) - } - } catch (e) { - if (e instanceof Error) { - console.log(e.message); - } - } - - } - } - - - return ( -
-
- keplr-logo -
- - - -
-
-
- Get OSMO Address -
- -
-
- Address: {address} -
- -
- -
-
-
- -
-
- Get OSMO Balance -
- -
- Balance: {balance} - - -
-
- -
-
- Send OSMO -
- -
-
- Recipient: - setRecipient(e.target.value)} /> -
- -
- Amount: - setAmount(e.target.value)} /> -
- - -
- -
-
-
- ); + return
; } export default App; diff --git a/src/components/Details/Details.tsx b/src/components/Details/Details.tsx new file mode 100644 index 0000000..c765624 --- /dev/null +++ b/src/components/Details/Details.tsx @@ -0,0 +1,150 @@ +import React, { useEffect } from "react"; +import { getKeplrFromWindow } from "../../util/getKeplrFromWindow"; +import { OsmosisChainInfo } from "../../constants"; +import { MsgSend } from "../../proto-types-gen/src/cosmos/bank/v1beta1/tx"; +import { Dec, DecUtils } from "@keplr-wallet/unit"; +import { simulateMsgs } from "../../util/simulateMsgs"; +import { sendMsgs } from "../../util/sendMsgs"; +import { IData } from "../../types/ItemType"; +import { useParams } from "react-router-dom"; +import { fakeData } from "../../util/fakeData"; +import ProductQuantityProgressBar from "../Home/ProductQuantityProgressBar"; + +type DetailsProps = {}; + +const Details: React.FC = () => { + const { id } = useParams(); + useEffect(() => { + init(); + }, []); + + const init = async () => { + const keplr = await getKeplrFromWindow(); + + if (keplr) { + try { + await keplr.experimentalSuggestChain(OsmosisChainInfo); + } catch (e) { + if (e instanceof Error) { + console.log(e.message); + } + } + } + }; + + const sendBalance = async (amount: string) => { + if (window.keplr) { + const key = await window.keplr.getKey(OsmosisChainInfo.chainId); + const protoMsgs = { + typeUrl: "/cosmos.bank.v1beta1.MsgSend", + value: MsgSend.encode({ + fromAddress: key.bech32Address, + toAddress: "", + amount: [ + { + denom: "uosmo", + amount: DecUtils.getTenExponentN(6) + .mul(new Dec(amount)) + .truncate() + .toString(), + }, + ], + }).finish(), + }; + + try { + const gasUsed = await simulateMsgs( + OsmosisChainInfo, + key.bech32Address, + [protoMsgs], + [{ denom: "uosmo", amount }] + ); + + if (gasUsed) { + await sendMsgs( + window.keplr, + OsmosisChainInfo, + key.bech32Address, + [protoMsgs], + { + amount: [{ denom: "uosmo", amount }], + gas: Math.floor(gasUsed * 1.5).toString(), + } + ); + } + } catch (e) { + if (e instanceof Error) { + console.log(e.message); + } + } + } + }; + + return ( +
+
+
+ {fakeData + .filter((item: IData) => item.id === id) + .map((item: IData) => ( +
+
+ +
+
+
+
+ + + +
+
+

{item.name}

+
+

{item.description}

+
+

Price {item.price}

+ + +
+
+
+
+ ))} +
+
+
+ ); +}; +export default Details; diff --git a/src/components/Home/AllData.tsx b/src/components/Home/AllData.tsx new file mode 100644 index 0000000..0c491fe --- /dev/null +++ b/src/components/Home/AllData.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { IData } from "../../types/ItemType"; +import { fakeData } from "../../util/fakeData"; +import ProductQuantityProgressBar from "./ProductQuantityProgressBar"; + +type AllDataProps = {}; + +const AllData: React.FC = () => { + return ( +
+
+ {fakeData.map((item: IData) => ( +
+
+
+ +

{item.name}

+
+

{item.description}

+
+
+

Price {item.price}

+

Quantity {item.quantity}

+ +
+ +
+
+
+
+
+ ))} +
+
+ ); +}; +export default AllData; diff --git a/src/components/Home/Home.tsx b/src/components/Home/Home.tsx new file mode 100644 index 0000000..9eb353c --- /dev/null +++ b/src/components/Home/Home.tsx @@ -0,0 +1,123 @@ +import React, { useEffect } from "react"; +import AllData from "./AllData"; +import { OsmosisChainInfo } from "../../constants"; +import { sendMsgs } from "../../util/sendMsgs"; +import { simulateMsgs } from "../../util/simulateMsgs"; +import { Dec, DecUtils } from "@keplr-wallet/unit"; +import { MsgSend } from "../../proto-types-gen/src/cosmos/bank/v1beta1/tx"; +import { api } from "../../util/api"; +import { Balances } from "../../types/balance"; +import { getKeplrFromWindow } from "../../util/getKeplrFromWindow"; + +type HomeProps = {}; + +const Home: React.FC = () => { + /* const [recipient, setRecipient] = React.useState(""); + const [amount, setAmount] = React.useState(""); + useEffect(() => { + init(); + }, []); + + const init = async () => { + const keplr = await getKeplrFromWindow(); + + if (keplr) { + try { + await keplr.experimentalSuggestChain(OsmosisChainInfo); + } catch (e) { + if (e instanceof Error) { + console.log(e.message); + } + } + } + }; + + const sendBalance = async () => { + if (window.keplr) { + const key = await window.keplr.getKey(OsmosisChainInfo.chainId); + const protoMsgs = { + typeUrl: "/cosmos.bank.v1beta1.MsgSend", + value: MsgSend.encode({ + fromAddress: key.bech32Address, + toAddress: recipient, + amount: [ + { + denom: "uosmo", + amount: DecUtils.getTenExponentN(6) + .mul(new Dec(amount)) + .truncate() + .toString(), + }, + ], + }).finish(), + }; + + try { + const gasUsed = await simulateMsgs( + OsmosisChainInfo, + key.bech32Address, + [protoMsgs], + [{ denom: "uosmo", amount: "236" }] + ); + + if (gasUsed) { + await sendMsgs( + window.keplr, + OsmosisChainInfo, + key.bech32Address, + [protoMsgs], + { + amount: [{ denom: "uosmo", amount: "236" }], + gas: Math.floor(gasUsed * 1.5).toString(), + } + ); + } + } catch (e) { + if (e instanceof Error) { + console.log(e.message); + } + } + } + }; */ + return ( +
+ {/*
+
+
Send OSMO
+ +
+
+
+ setRecipient(e.target.value)} + /> +
+ +
+ setAmount(e.target.value)} + /> +
+ +
+
+
+
*/} + +
+ ); +}; +export default Home; diff --git a/src/components/Home/ProductQuantityProgressBar.tsx b/src/components/Home/ProductQuantityProgressBar.tsx new file mode 100644 index 0000000..29bed87 --- /dev/null +++ b/src/components/Home/ProductQuantityProgressBar.tsx @@ -0,0 +1,41 @@ +import React from "react"; + +interface ProductQuantityProgressBarProps { + currentQuantity: number; + maxQuantityPerBlock: number; +} + +const ProductQuantityProgressBar: React.FC = ({ + currentQuantity, + maxQuantityPerBlock, +}) => { + const calculateProgress = (): number => { + const progress = (currentQuantity / maxQuantityPerBlock) * 100; + return Math.min(progress, 100); // Ensure progress does not exceed 100% + }; + + return ( +
+

Product Quantity Progress:

+
+
+ + {currentQuantity}/{maxQuantityPerBlock} + +
+
+
+
+
+
+
+
+
+
+ ); +}; + +export default ProductQuantityProgressBar; diff --git a/src/components/Layout/Main.tsx b/src/components/Layout/Main.tsx new file mode 100644 index 0000000..e82d5b9 --- /dev/null +++ b/src/components/Layout/Main.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import Nav from "../shared/Nav"; +import { Outlet } from "react-router-dom"; + +type MainProps = {}; + +const Main: React.FC = () => { + return ( +
+
+ ); +}; +export default Main; diff --git a/src/components/shared/Nav.tsx b/src/components/shared/Nav.tsx new file mode 100644 index 0000000..83f3b43 --- /dev/null +++ b/src/components/shared/Nav.tsx @@ -0,0 +1,139 @@ +import React, { useEffect } from "react"; +import { OsmosisChainInfo } from "../../constants"; +import { Balances } from "../../types/balance"; +import { sendMsgs } from "../../util/sendMsgs"; +import { simulateMsgs } from "../../util/simulateMsgs"; +import { Dec, DecUtils } from "@keplr-wallet/unit"; +import { MsgSend } from "../../proto-types-gen/src/cosmos/bank/v1beta1/tx"; +import { api } from "../../util/api"; +import { getKeplrFromWindow } from "../../util/getKeplrFromWindow"; +import { Link } from "react-router-dom"; + +type NavProps = {}; + +const Nav: React.FC = () => { + const [address, setAddress] = React.useState(""); + const [balance, setBalance] = React.useState(""); + + const [open, setOpen] = React.useState(false); + useEffect(() => { + init(); + }, []); + + const init = async () => { + const keplr = await getKeplrFromWindow(); + + if (keplr) { + try { + await keplr.experimentalSuggestChain(OsmosisChainInfo); + } catch (e) { + if (e instanceof Error) { + console.log(e.message); + } + } + } + }; + + const getKeyFromKeplr = async () => { + const key = await window.keplr?.getKey(OsmosisChainInfo.chainId); + if (key) { + setAddress(key.bech32Address); + } + }; + + const getBalance = async () => { + const key = await window.keplr?.getKey(OsmosisChainInfo.chainId); + + if (key) { + const uri = `${OsmosisChainInfo.rest}/cosmos/bank/v1beta1/balances/${key.bech32Address}?pagination.limit=1000`; + + const data = await api(uri); + const balance = data.balances.find( + (balance) => balance.denom === "uosmo" + ); + const osmoDecimal = OsmosisChainInfo.currencies.find( + (currency) => currency.coinMinimalDenom === "uosmo" + )?.coinDecimals; + + if (balance) { + const amount = new Dec(balance.amount, osmoDecimal); + setBalance(`${amount.toString(osmoDecimal)} OSMO`); + } else { + setBalance(`0 OSMO`); + } + } + }; + + return ( +
+ {/* header start */} +
+
+ +
+ keplr-logo +
+ +
+ +
+
+ {open && ( +
+
+
+ Get OSMO Address +
+ +
+

+ Address: + {address} +

+ +
+ +
+
+
+
+
+ Get OSMO Balance +
+ +
+

+ Balance:{" "} + {balance} +

+ +
+
+
+ )} +
+ {/* header end */} + {/* transfer */} +
+ ); +}; +export default Nav; diff --git a/src/index.tsx b/src/index.tsx index 88e8a31..16a7fa1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,12 +1,15 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App'; +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./styles/index.css"; +import { RouterProvider } from "react-router-dom"; +import { router } from "./util/Routes"; const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById("root") as HTMLElement ); root.render( - + ); diff --git a/src/styles/index.css b/src/styles/index.css new file mode 100644 index 0000000..969ba50 --- /dev/null +++ b/src/styles/index.css @@ -0,0 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + background: white; +} diff --git a/src/styles/item.css b/src/styles/item.css index 456062f..e7190c5 100644 --- a/src/styles/item.css +++ b/src/styles/item.css @@ -1,31 +1,31 @@ .item { - display: flex; - flex-direction: column; - justify-content: center; + display: flex; + flex-direction: column; + justify-content: center; - border: 1px solid #ccc; - border-radius: 5px; + border: 1px solid #ccc; + border-radius: 5px; } .item-title { - padding: 12px; - font-size: 20px; + padding: 12px; + font-size: 20px; - background: #F2F2F6; + background: #f2f2f6; } .item-content { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; - gap: 12px; - padding: 16px; + gap: 12px; + padding: 16px; } input { - margin: 0; - border: 1px solid #09090A; - border-radius: 0.5rem; + margin: 0; + border: 1px solid #09090a; + border-radius: 0.5rem; - padding: 0.75rem 0.75rem; + padding: 0.75rem 0.75rem; } diff --git a/src/types/ItemType.ts b/src/types/ItemType.ts new file mode 100644 index 0000000..ba51014 --- /dev/null +++ b/src/types/ItemType.ts @@ -0,0 +1,10 @@ +export type IData = { + id: string; + name: string; + description: string; + amount: number; + price: number; + quantity: number; + totalQuantity: number; + image: string; +}; diff --git a/src/util/Routes.tsx b/src/util/Routes.tsx new file mode 100644 index 0000000..54750c9 --- /dev/null +++ b/src/util/Routes.tsx @@ -0,0 +1,22 @@ +import { ReactElement } from "react"; +import { createBrowserRouter } from "react-router-dom"; +import Home from "../components/Home/Home"; +import Main from "../components/Layout/Main"; +import Details from "../components/Details/Details"; + +export const router = createBrowserRouter([ + { + path: "/", + element: (
) as ReactElement, + children: [ + { + path: "/", + element: () as ReactElement, + }, + { + path: "details/:id", + element: (
) as ReactElement, + }, + ], + }, +]); diff --git a/src/util/fakeData.ts b/src/util/fakeData.ts new file mode 100644 index 0000000..b5facb0 --- /dev/null +++ b/src/util/fakeData.ts @@ -0,0 +1,37 @@ +import { IData } from "../types/ItemType"; + +export const fakeData: IData[] = [ + { + id: "1", + name: "Widget A", + description: "A high-quality widget with advanced features.", + amount: 15, + price: 29.99, + quantity: 10, + totalQuantity: 15, + image: + "https://images.unsplash.com/photo-1518546305927-5a555bb7020d?q=80&w=2069&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + }, + { + id: "2", + name: "Gizmo B", + description: "An innovative gizmo for everyday use.", + amount: 8, + price: 49.99, + quantity: 20, + totalQuantity: 50, + image: + "https://images.unsplash.com/photo-1518478021985-13055115e310?q=80&w=2069&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + }, + { + id: "3", + name: "Doohickey C", + description: "The latest doohickey with cutting-edge technology.", + amount: 20, + price: 39.99, + quantity: 21, + totalQuantity: 50, + image: + "https://images.unsplash.com/photo-1609554496796-c345a5335ceb?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", + }, +]; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..19973dd --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{html,js}"], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/yarn.lock b/yarn.lock index 32e49ed..ee69710 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1800,6 +1800,11 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== +"@remix-run/router@1.14.2": + version "1.14.2" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.14.2.tgz#4d58f59908d9197ba3179310077f25c88e49ed17" + integrity sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg== + "@rollup/plugin-babel@^5.2.0": version "5.3.1" resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz" @@ -3838,6 +3843,14 @@ css-select@^4.1.3: domutils "^2.8.0" nth-check "^2.0.1" +css-selector-tokenizer@^0.8: + version "0.8.0" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz#88267ef6238e64f2215ea2764b3e2cf498b845dd" + integrity sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg== + dependencies: + cssesc "^3.0.0" + fastparse "^1.1.2" + css-tree@1.0.0-alpha.37: version "1.0.0-alpha.37" resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz" @@ -3952,6 +3965,21 @@ csstype@^3.0.2: resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== +culori@^3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/culori/-/culori-3.3.0.tgz#e33530adbd124d53bd6550394397e695eaaed739" + integrity sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ== + +daisyui@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-4.6.0.tgz#3b2d34ba2995633530b510ebaf9fbc6ed03374c1" + integrity sha512-B5ZB/sczXpp4LMdo/SZrtYY/U2hq+Vr9I15QawuWZ0VwgtSAbuZpAZUftKVryEsPuv3BM0yVlBED0nAmtis/dw== + dependencies: + css-selector-tokenizer "^0.8" + culori "^3" + picocolors "^1" + postcss-js "^4" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz" @@ -4855,6 +4883,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fastparse@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + fastq@^1.6.0: version "1.15.0" resolved "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" @@ -6427,6 +6460,11 @@ jiti@^1.18.2: resolved "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz" integrity sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w== +jiti@^1.19.1: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" + integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" @@ -7353,7 +7391,7 @@ picocolors@^0.2.1: resolved "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz" integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== -picocolors@^1.0.0: +picocolors@^1, picocolors@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== @@ -7566,7 +7604,7 @@ postcss-initial@^4.0.1: resolved "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz" integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ== -postcss-js@^4.0.1: +postcss-js@^4, postcss-js@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz" integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== @@ -8225,6 +8263,21 @@ react-refresh@^0.11.0: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== +react-router-dom@^6.21.3: + version "6.21.3" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.21.3.tgz#ef3a7956a3699c7b82c21fcb3dbc63c313ed8c5d" + integrity sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g== + dependencies: + "@remix-run/router" "1.14.2" + react-router "6.21.3" + +react-router@6.21.3: + version "6.21.3" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.21.3.tgz#8086cea922c2bfebbb49c6594967418f1f167d70" + integrity sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg== + dependencies: + "@remix-run/router" "1.14.2" + react-scripts@5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz" @@ -9195,6 +9248,34 @@ tailwindcss@^3.0.2: resolve "^1.22.2" sucrase "^3.32.0" +tailwindcss@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d" + integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.19.1" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + tapable@^1.0.0: version "1.1.3" resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz"