diff --git a/.changeset/smart-roses-trade.md b/.changeset/smart-roses-trade.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/smart-roses-trade.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/biome.json b/biome.json index bf47d25e..aae3e9ff 100644 --- a/biome.json +++ b/biome.json @@ -38,6 +38,12 @@ "useIgnoreFile": true }, "files": { - "ignore": ["**/node_modules", "**/.turbo", "**/build", "pnpm-lock.yaml"] + "ignore": [ + "**/node_modules", + "**/.turbo", + "**/build", + "**/contracts", + "pnpm-lock.yaml" + ] } } diff --git a/examples/nodejs/package.json b/examples/nodejs/package.json deleted file mode 100644 index 6e5eb69b..00000000 --- a/examples/nodejs/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "nodejs", - "private": true, - "version": "0.0.0", - "main": "./src/index.ts", - "scripts": { - "build": "tsup", - "dev": "tsx watch src/index.ts" - }, - "dependencies": { - "@fuels/connectors": "workspace:*", - "fuels": "0.79.0" - }, - "devDependencies": { - "tsup": "8.0.2", - "tsx": "4.7.1", - "typescript": "5.4.3" - } -} diff --git a/examples/nodejs/src/index.ts b/examples/nodejs/src/index.ts deleted file mode 100644 index 4eb52a60..00000000 --- a/examples/nodejs/src/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { FuelWalletConnector } from '@fuels/connectors'; -import { Fuel, Mnemonic, WalletManager } from 'fuels'; - -const main = async () => { - // Mnemonic - const WALLET_PASSWORD = 'Qwe1234567$'; - const mnemonic = Mnemonic.generate(16); - - // Vault with initial account - const manager = new WalletManager(); - await manager.unlock(WALLET_PASSWORD); - await manager.addVault({ - title: '@fuels/connectors', - type: 'mnemonic', - secret: mnemonic, - }); - - // Adding second account - await manager.addAccount({ vaultId: 0 }); - - // Listing accounts - const accounts = manager.getAccounts(); - console.log('mnenomic\n', mnemonic, '\n\naccounts'); - console.log(accounts.map((ac) => ac.address.toString())); - - // Listing available connectors - const fuel = new Fuel({ - connectors: [new FuelWalletConnector()], // Build and check "dist" to confirm only this connector was bundled - }); - const connectors = await fuel.connectors(); - console.log( - '\navailable connectors\n', - connectors.map((c) => c.name), - ); -}; - -main(); diff --git a/examples/nodejs/tsconfig.json b/examples/nodejs/tsconfig.json deleted file mode 100644 index 8a0f2ffa..00000000 --- a/examples/nodejs/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./dist", - "baseUrl": "." - }, - "exclude": ["dist"] -} diff --git a/examples/nodejs/tsup.config.js b/examples/nodejs/tsup.config.js deleted file mode 100644 index fad046da..00000000 --- a/examples/nodejs/tsup.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import baseConfig from '@fuels/tsup-config'; -import { defineConfig } from 'tsup'; - -export default defineConfig((options) => ({ - ...baseConfig(options, { withReact: false }), - entry: ['src/index.ts'], - noExternal: ['@fuels/connectors'], - minify: false, - splitting: true, - metafile: true, -})); diff --git a/examples/react-app/index.html b/examples/react-app/index.html index 8af9404d..52f64961 100644 --- a/examples/react-app/index.html +++ b/examples/react-app/index.html @@ -1,12 +1,17 @@ - - - - Fuel Connectors - - -
- - - + + + + + + + Fuel Connectors + + + +
+ + + + \ No newline at end of file diff --git a/examples/react-app/package.json b/examples/react-app/package.json index 59309ae6..19e22be0 100644 --- a/examples/react-app/package.json +++ b/examples/react-app/package.json @@ -8,10 +8,12 @@ "build": "vite build" }, "dependencies": { + "@radix-ui/react-toast": "1.1.5", + "clsx": "2.1.0", + "fuels": "0.79.0", "@fuels/connectors": "workspace:*", "@fuels/react": "0.18.0", "@tanstack/react-query": "5.28.8", - "fuels": "0.79.0", "react": "18.2.0", "react-dom": "18.2.0" }, @@ -20,6 +22,9 @@ "@types/react": "18.2.71", "@types/react-dom": "18.2.22", "@vitejs/plugin-react": "4.2.1", + "tailwindcss": "3.4.1", + "autoprefixer": "10.4.19", + "postcss": "8.4.38", "typescript": "5.4.3", "vite": "5.2.6" } diff --git a/examples/react-app/postcss.config.cjs b/examples/react-app/postcss.config.cjs new file mode 100644 index 00000000..12a703d9 --- /dev/null +++ b/examples/react-app/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/examples/react-app/public/Fuel_Logo_White_RGB.svg b/examples/react-app/public/Fuel_Logo_White_RGB.svg new file mode 100644 index 00000000..7d775ca3 --- /dev/null +++ b/examples/react-app/public/Fuel_Logo_White_RGB.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/examples/react-app/public/connectors/fuel-wallet-dev.svg b/examples/react-app/public/connectors/fuel-wallet-dev.svg new file mode 100644 index 00000000..64a26389 --- /dev/null +++ b/examples/react-app/public/connectors/fuel-wallet-dev.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/examples/react-app/public/connectors/fuel-wallet.svg b/examples/react-app/public/connectors/fuel-wallet.svg new file mode 100644 index 00000000..972f5bf1 --- /dev/null +++ b/examples/react-app/public/connectors/fuel-wallet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/examples/react-app/public/connectors/fuelet-dark.svg b/examples/react-app/public/connectors/fuelet-dark.svg new file mode 100644 index 00000000..e8548fb0 --- /dev/null +++ b/examples/react-app/public/connectors/fuelet-dark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/examples/react-app/public/logo.png b/examples/react-app/public/logo.png new file mode 100644 index 00000000..00777b33 Binary files /dev/null and b/examples/react-app/public/logo.png differ diff --git a/examples/react-app/public/logo_black.png b/examples/react-app/public/logo_black.png new file mode 100644 index 00000000..025e4449 Binary files /dev/null and b/examples/react-app/public/logo_black.png differ diff --git a/examples/react-app/public/logo_white.png b/examples/react-app/public/logo_white.png new file mode 100644 index 00000000..39bfbae8 Binary files /dev/null and b/examples/react-app/public/logo_white.png differ diff --git a/examples/react-app/public/robots.txt b/examples/react-app/public/robots.txt new file mode 100644 index 00000000..e9e57dc4 --- /dev/null +++ b/examples/react-app/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/examples/react-app/src/App.css b/examples/react-app/src/App.css deleted file mode 100644 index 6cdc4b4c..00000000 --- a/examples/react-app/src/App.css +++ /dev/null @@ -1,64 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -body { - max-width: 100vw; - overflow-x: hidden; -} - -.App { - display: flex; - flex-direction: column; - align-items: center; - box-sizing: border-box; - padding-top: 100px; - height: 100vh; - width: 100vw; -} - -.App[data-theme="dark"] { - background-color: #282c34; - color: white; -} - -button { - all: unset; - border: 1px solid black; - padding: 10px 20px; - border-radius: 4px; - box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.2); - transition: box-shadow 0.2s ease-in-out; - cursor: pointer; -} - -button:active { - box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.2); -} - -.Actions { - display: flex; - flex-direction: row; - align-items: center; - gap: 10px; -} - -.Accounts { - margin-top: 20px; - text-align: center; -} - -.Accounts > div { - font-style: italic; -} - -.Error { - color: #d60000; - width: 100%; - text-align: center; -} diff --git a/examples/react-app/src/App.tsx b/examples/react-app/src/App.tsx index 56517b8d..acdfb07d 100644 --- a/examples/react-app/src/App.tsx +++ b/examples/react-app/src/App.tsx @@ -1,55 +1,112 @@ -import { - useAccounts, - useConnectUI, - useDisconnect, - useIsConnected, -} from '@fuels/react'; -import './App.css'; +import Account from './components/account'; +import Balance from './components/balance'; +import Button from './components/button'; +import Counter from './components/counter'; +import Transfer from './components/transfer'; +import { useWallet } from './hooks/useWallet'; -function App() { - const { connect, error, isError, theme, setTheme, isConnecting } = - useConnectUI(); - const { disconnect } = useDisconnect(); - const { isConnected } = useIsConnected(); - const { accounts } = useAccounts(); - const lightTheme = theme === 'light'; +export default function App() { + const { + currentConnector, + isConnected, + isConnecting, + isLoading, + isFetching, + connect, + } = useWallet(); return ( -
-
- - {isConnected && ( - - )} - -
- {isError &&

{error?.message}

} - {isConnected && ( -
-

Connected accounts

- {accounts?.map((account) => ( -
- Account: {account} + + Fuel Logo + + + +
+
+
+
+
+ {currentConnector.logo && ( + {currentConnector.title} + )} +
+

+ {currentConnector.title} +

+

+ Fuel enables developers to build integrations with any wallet. +

+ +
    +
  • Reduce friction for users
  • +
  • Build using any signature scheme
  • +
  • + Use predicates, a new type of stateless smart contract +
  • +
+ + Build your own wallet integration + +
+ +
+
+ {!isConnected && ( +
+ +
+ )} + + {(isLoading ?? isFetching) && ( +
+

Loading...

+
+ )} + + {isConnected && !isLoading && ( +
+ + + + +
+ )} +
+
- ))} +
- )} -
+
+ ); } - -export default App; diff --git a/examples/react-app/src/components/account.tsx b/examples/react-app/src/components/account.tsx new file mode 100644 index 00000000..6da9bc26 --- /dev/null +++ b/examples/react-app/src/components/account.tsx @@ -0,0 +1,25 @@ +import { useDisconnect } from '@fuels/react'; +import { useWallet } from '../hooks/useWallet'; +import Button from './button'; +import Feature from './feature'; + +export default function ConnectedAccount() { + const { address } = useWallet(); + + const { disconnect } = useDisconnect(); + + return ( + + {truncAddressMiddle(address, 4)} + {truncAddressMiddle(address, 8)} + + + ); +} + +function truncAddressMiddle(address: string, size: number) { + if (!address) return ''; + return `${address.slice(0, size)}...${address.slice(-size)}`; +} diff --git a/examples/react-app/src/components/balance.tsx b/examples/react-app/src/components/balance.tsx new file mode 100644 index 00000000..d648a2a8 --- /dev/null +++ b/examples/react-app/src/components/balance.tsx @@ -0,0 +1,33 @@ +import { bn } from 'fuels'; +import { useEffect } from 'react'; +import { useWallet } from '../hooks/useWallet'; +import Feature from './feature'; + +export const DEFAULT_AMOUNT = bn.parseUnits('0.0001'); + +const BalanceSkeleton = () => ( +
+); + +export default function Balance() { + const { refetchWallet, balance, address } = useWallet(); + + useEffect(() => { + const interval = setInterval(() => refetchWallet(), 5000); + return () => clearInterval(interval); + }, [refetchWallet]); + + return ( + + {balance ? `${balance?.format()} ETH` : } + + Get coins + + + ); +} diff --git a/examples/react-app/src/components/button.tsx b/examples/react-app/src/components/button.tsx new file mode 100644 index 00000000..1b3d3707 --- /dev/null +++ b/examples/react-app/src/components/button.tsx @@ -0,0 +1,36 @@ +import clsx from 'clsx'; + +export type Props = { + color?: 'primary' | 'secondary'; + loading?: boolean; + loadingText?: string; +} & React.ComponentProps<'button'>; + +export default function Button(props: Props) { + const { + color = 'primary', + children, + disabled, + loading, + loadingText, + className, + ...rest + } = props; + + return ( + + ); +} diff --git a/examples/react-app/src/components/counter.tsx b/examples/react-app/src/components/counter.tsx new file mode 100644 index 00000000..c49ed6f0 --- /dev/null +++ b/examples/react-app/src/components/counter.tsx @@ -0,0 +1,118 @@ +import { useEffect, useState } from 'react'; +import { CounterContractAbi__factory } from '../contracts'; +import { useLogEvents } from '../hooks/use-log-events'; +import { useWallet } from '../hooks/useWallet'; +import type { CustomError } from '../utils/customError'; +import { DEFAULT_AMOUNT } from './balance'; +import Button from './button'; +import Feature from './feature'; +import Notification, { type Props as NotificationProps } from './notification'; + +export const COUNTER_CONTRACT_ID = + '0x0a46aafb83b387155222893b52ed12e5a4b9d6cd06770786f2b5e4307a63b65c'; + +export default function ContractCounter() { + const { balance, wallet } = useWallet(); + + const [toast, setToast] = useState>({ + open: false, + }); + + const [isLoading, setLoading] = useState(false); + const [counter, setCounter] = useState(0); + + const hasBalance = balance?.gte(DEFAULT_AMOUNT); + + useLogEvents(); + + useEffect(() => { + if (wallet) { + getCount(); + } + }, [wallet]); + + return ( + + {counter} +
+ + + setToast({ ...toast, open: false })} + {...toast} + /> +
+
+ ); + + async function increment() { + if (wallet) { + setLoading(true); + const contract = CounterContractAbi__factory.connect( + COUNTER_CONTRACT_ID, + wallet, + ); + try { + await contract.functions + .increment() + .txParams({ gasPrice: 1, gasLimit: 100_000 }) + .call(); + + getCount(); + + setToast({ + open: true, + type: 'success', + children: 'Counter incremented!', + }); + } catch (err) { + const error = err as CustomError; + + console.error('error sending transaction...', error.message); + setToast({ + open: true, + type: 'error', + children: `The counter could not be incremented: ${error.message.substring( + 0, + 32, + )}...`, + }); + } finally { + setLoading(false); + } + } + } + + async function getCount() { + if (!wallet) return; + + const counterContract = CounterContractAbi__factory.connect( + COUNTER_CONTRACT_ID, + wallet, + ); + + try { + const { value } = await counterContract.functions + .count() + .txParams({ gasPrice: 1, gasLimit: 100_000 }) + .get(); + setCounter(value.toNumber()); + } catch (error) { + console.error(error); + } + } +} diff --git a/examples/react-app/src/components/feature.tsx b/examples/react-app/src/components/feature.tsx new file mode 100644 index 00000000..97014645 --- /dev/null +++ b/examples/react-app/src/components/feature.tsx @@ -0,0 +1,19 @@ +import type React from 'react'; + +type Props = { + title: string; +} & React.HTMLAttributes; + +export default function Feature(props: Props) { + const { title, children, ...rest } = props; + return ( +
+

+ {title} +

+
+ {children} +
+
+ ); +} diff --git a/examples/react-app/src/components/notification.tsx b/examples/react-app/src/components/notification.tsx new file mode 100644 index 00000000..7f49eac5 --- /dev/null +++ b/examples/react-app/src/components/notification.tsx @@ -0,0 +1,52 @@ +import * as Toast from '@radix-ui/react-toast'; +import clsx from 'clsx'; +import React from 'react'; + +export type Props = { + open: boolean; + setOpen: React.Dispatch>; + type?: 'success' | 'error' | 'info'; + duration?: number; +} & React.PropsWithChildren; + +export default function Notification(props: Props) { + const { open, setOpen, type, duration, children } = props; + return ( + + +
+
+ + {type === 'success' && 'Succes'} + {type === 'error' && 'Error'} + + + + +
+ + {children} + +
+
+
+ ); +} diff --git a/examples/react-app/src/components/screensize-indicator.tsx b/examples/react-app/src/components/screensize-indicator.tsx new file mode 100644 index 00000000..4662d296 --- /dev/null +++ b/examples/react-app/src/components/screensize-indicator.tsx @@ -0,0 +1,14 @@ +export default function ScreenSizeIndicator() { + if (process.env.NODE_ENV === 'production') return null; + + return ( +
+
xs
+
sm
+
md
+
lg
+
xl
+
2xl
+
+ ); +} diff --git a/examples/react-app/src/components/transfer.tsx b/examples/react-app/src/components/transfer.tsx new file mode 100644 index 00000000..bf677e99 --- /dev/null +++ b/examples/react-app/src/components/transfer.tsx @@ -0,0 +1,94 @@ +import { Address, BaseAssetId } from 'fuels'; +import { useState } from 'react'; +import { useWallet } from '../hooks/useWallet'; +import type { CustomError } from '../utils/customError'; +import { DEFAULT_AMOUNT } from './balance'; +import Button from './button'; +import Feature from './feature'; +import Notification, { type Props as NotificationProps } from './notification'; + +const DEFAULT_ADDRESS = Address.fromRandom().toString(); + +export default function Transfer() { + const { balance, wallet, refetchWallet } = useWallet(); + + const [receiver, setReceiver] = useState(DEFAULT_ADDRESS); + const [isLoading, setLoading] = useState(false); + const [toast, setToast] = useState>({ + open: false, + }); + + const hasBalance = balance?.gte(DEFAULT_AMOUNT); + + const handleTransfer = async () => { + setLoading(true); + try { + const receiverAddress = Address.fromString(receiver || DEFAULT_ADDRESS); + + const resp = await wallet?.transfer( + receiverAddress, + DEFAULT_AMOUNT, + BaseAssetId, + { + gasPrice: 1, + gasLimit: 10_000, + }, + ); + + await resp?.waitForResult(); + + setToast({ + open: true, + type: 'success', + children: ( +

+ Transfer successful! View it on the{' '} + + block explorer + +

+ ), + }); + } catch (err) { + const error = err as CustomError; + console.error(error.message); + setToast({ + open: true, + type: 'error', + children: `The transfer could not be processed: ${error.message.substring( + 0, + 32, + )}...`, + }); + } finally { + setLoading(false); + refetchWallet(); + } + }; + + return ( + + setReceiver(e.target.value)} + className="-ml-1 mr-2 mt-1 w-2/3 shrink basis-2/3 rounded-lg border border-zinc-500/25 p-1 font-mono outline-none md:-ml-2 md:mt-2 md:p-2 dark:bg-transparent" + /> + + + setToast({ ...toast, open: false })} + {...toast} + /> + + ); +} diff --git a/examples/react-app/src/contracts/CounterContractAbi.d.ts b/examples/react-app/src/contracts/CounterContractAbi.d.ts new file mode 100644 index 00000000..b43e7a0e --- /dev/null +++ b/examples/react-app/src/contracts/CounterContractAbi.d.ts @@ -0,0 +1,45 @@ +/* Autogenerated file. Do not edit manually. */ + +/* tslint:disable */ +/* eslint-disable */ + +/* + Fuels version: 0.73.0 + Forc version: 0.49.2 + Fuel-Core version: 0.22.0 +*/ + +import type { + BN, + BigNumberish, + BytesLike, + Contract, + DecodedValue, + FunctionFragment, + Interface, + InvokeFunction, +} from 'fuels'; + +interface CounterContractAbiInterface extends Interface { + functions: { + count: FunctionFragment; + increment: FunctionFragment; + }; + + encodeFunctionData(functionFragment: 'count', values: []): Uint8Array; + encodeFunctionData(functionFragment: 'increment', values: []): Uint8Array; + + decodeFunctionData(functionFragment: 'count', data: BytesLike): DecodedValue; + decodeFunctionData( + functionFragment: 'increment', + data: BytesLike, + ): DecodedValue; +} + +export class CounterContractAbi extends Contract { + interface: CounterContractAbiInterface; + functions: { + count: InvokeFunction<[], BN>; + increment: InvokeFunction<[], void>; + }; +} diff --git a/examples/react-app/src/contracts/CounterContractAbi.hex.ts b/examples/react-app/src/contracts/CounterContractAbi.hex.ts new file mode 100644 index 00000000..4f72b9f7 --- /dev/null +++ b/examples/react-app/src/contracts/CounterContractAbi.hex.ts @@ -0,0 +1,12 @@ +/* Autogenerated file. Do not edit manually. */ + +/* tslint:disable */ +/* eslint-disable */ + +/* + Fuels version: 0.73.0 + Forc version: 0.49.2 + Fuel-Core version: 0.22.0 +*/ + +export default '0x7400000347000000000000000000059c5dfcc00110fff3005d4060495d47f00913490440764800055d47f00a134904407648007172f0007b36f000001aec5000910002185d43f00b104103005d47f00b104513007248002028ed04805fec0004504bb028724c0020284914c05d4fb0045d47f0041b4534405d4bf004104514805d4bf005104514805d4bf0061f4514805d4bf00719493480504fb09872500020284d05005043b1f872500020284135005043b1f8504fb1f85053b0e81ae910001ae5400020f8330058fbe00250fbe004740001131a47d0005053b1081ae810001ae5400020f8330058fbe00250fbe0047400010b1a53d0005057b13872580020285515805047b1b872580020284545805053b178a35154615047b1587250002028453500504fb1785053b198a35114e072440020284144405043b0b872440020284144405047b048724c0020284504c05fec100d5fed200e5043b0485047b1d872480020284504805d43b00d5d47b00e5d4bf0081b4904805d4ff0041b493480264800001a487000504fb1d8394904d0764000065043b0885fec0011504bb12872440010284904407400000a5043b0785fec100f5d4ff0041b453440104524405d4510005fed1010504bb12872440010284904405043b0d872440010284124405d43b0251341004076400001360000005d43b01c244000001aec5000910003f05d53f00b105143005d43f00b104103007244002028ed44405fec00045047b02872480020284504805d4bb0045d43f0041b4124005d47f004104104405d47f005104104405d47f0061f4104405d47f00719452440504bb110724c0020284944c0504fb39072500020284d2500504bb390504fb3905053b1a01ae900001ae5400020f8330058fbe00250fbe004740000a41a43d0005053b1c01ae810001ae5400020f8330058fbe00250fbe0047400009c1a53d0005057b23072580020285505805043b33072580020284145805053b2b0a35154215043b2507250002028413500504fb2b05053b2d0a35104e072400020284944005043b1307248002028414480504bb048724c0020284904c05fec100d5fed100e5043b0485047b37072480020284504805d43b00d5d47b00e5d4bf0081b4904805d4ff0041b493480264800001a487000504fb370394904d0764000065043b1005fec0020504bb22072440010284904407400000a5043b0f05fec101e5d4ff0041b453440104524405d4510005fed101f504bb22072440010284904405043b19072440010284124405d43b0441341004076400001360000005d43f00b104103005d47f00b104513005d4bb033105d2040504bb0a8724c0020284904c05fec001950492028724c0020284914c05d47b0195d4bf0041b4914805d4ff004104924c05d4ff005104924c05d4ff0061f4924c05d4ff007194514c0504fb15072500020284d05005043b3b072500020284135005043b3b0504fb3b05053b1e01ae920001ae5400020f8330058fbe00250fbe004740000361a4bd0005053b2001ae810001ae5400020f8330058fbe00250fbe0047400002e1a53d0005057b2707258002028552580504bb35072580020284945805053b2f0a35154a1504bb2907250002028493500504fb2f05053b310a35124e072480020284144805043b1707248002028414480504bb078724c0020284904c05fec10135fed10145043b0785047b3d072480020284504805d43b0135d47b0145d4bf0081b4904805d4ff0041b493480264800001a487000504fb3d0394934d05d4ff0041b453440104524405f4570005047b3d03b450490240000001af05000910000285ff100005ff110015ff120025ff130035ff3b0041aec5000910000201a43a0001a4790001a4be0005fec00005fec00015fec00025fed00031a43b000724c0020284504c01af51000920000201af9200059f050285d43c0005d47c0015d4bc0025d4fc0035defc004920000284af8000047000000f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed0000000000000008000000000000001f000000000000000500000000000000040000000000000020000000003c5bb3f2000000005842f1be000000000000059c'; diff --git a/examples/react-app/src/contracts/factories/CounterContractAbi__factory.ts b/examples/react-app/src/contracts/factories/CounterContractAbi__factory.ts new file mode 100644 index 00000000..24a42b31 --- /dev/null +++ b/examples/react-app/src/contracts/factories/CounterContractAbi__factory.ts @@ -0,0 +1,121 @@ +/* Autogenerated file. Do not edit manually. */ + +/* tslint:disable */ +/* eslint-disable */ + +/* + Fuels version: 0.73.0 + Forc version: 0.49.2 + Fuel-Core version: 0.22.0 +*/ + +import { Contract, ContractFactory, Interface } from 'fuels'; +import type { + AbstractAddress, + Account, + BytesLike, + DeployContractOptions, + Provider, + StorageSlot, +} from 'fuels'; +import type { + CounterContractAbi, + CounterContractAbiInterface, +} from '../CounterContractAbi'; + +const _abi = { + types: [ + { + typeId: 0, + type: '()', + components: [], + typeParameters: null, + }, + { + typeId: 1, + type: 'u64', + components: null, + typeParameters: null, + }, + ], + functions: [ + { + inputs: [], + name: 'count', + output: { + name: '', + type: 1, + typeArguments: null, + }, + attributes: [ + { + name: 'storage', + arguments: ['read'], + }, + ], + }, + { + inputs: [], + name: 'increment', + output: { + name: '', + type: 0, + typeArguments: null, + }, + attributes: [ + { + name: 'storage', + arguments: ['read', 'write'], + }, + ], + }, + ], + loggedTypes: [], + messagesTypes: [], + configurables: [], +}; + +const _storageSlots: StorageSlot[] = [ + { + key: 'f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed', + value: '0000000000000000000000000000000000000000000000000000000000000000', + }, +]; + +export class CounterContractAbi__factory { + static readonly abi = _abi; + + static readonly storageSlots = _storageSlots; + + static createInterface(): CounterContractAbiInterface { + return new Interface(_abi) as unknown as CounterContractAbiInterface; + } + + static connect( + id: string | AbstractAddress, + accountOrProvider: Account | Provider, + ): CounterContractAbi { + return new Contract( + id, + _abi, + accountOrProvider, + ) as unknown as CounterContractAbi; + } + + static async deployContract( + bytecode: BytesLike, + wallet: Account, + options: DeployContractOptions = {}, + ): Promise { + const factory = new ContractFactory(bytecode, _abi, wallet); + + const { storageSlots } = CounterContractAbi__factory; + + const contract = await factory.deployContract({ + storageSlots, + ...options, + }); + + return contract as unknown as CounterContractAbi; + } +} diff --git a/examples/react-app/src/contracts/index.ts b/examples/react-app/src/contracts/index.ts new file mode 100644 index 00000000..7216704b --- /dev/null +++ b/examples/react-app/src/contracts/index.ts @@ -0,0 +1,14 @@ +/* Autogenerated file. Do not edit manually. */ + +/* tslint:disable */ +/* eslint-disable */ + +/* + Fuels version: 0.73.0 + Forc version: 0.49.2 + Fuel-Core version: 0.22.0 +*/ + +export type { CounterContractAbi } from './CounterContractAbi'; + +export { CounterContractAbi__factory } from './factories/CounterContractAbi__factory'; diff --git a/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.html b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.html new file mode 100644 index 00000000..22dc5af1 --- /dev/null +++ b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.html @@ -0,0 +1,369 @@ + + + + Px Grotesk Mono Regular Web Specimen + + + + + + + + + +
+
Px Grotesk Mono Regular
+
+
+
+
+ + +
+
+
+ Legal Disclaimer +
+ Optimo webfonts are protected by copyright law and provided under license. To modify, alter, translate, convert, decode or reverse engineer in any manner whatsoever, including converting the Font Software into a different format is strictly prohibited. The webfont files are not to be used for anything other than web font use.

+ ยฉ 1998โ€”2022 Optimo Sร rl +
+
+ + diff --git a/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.otf b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.otf new file mode 100755 index 00000000..30417eb2 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.otf differ diff --git a/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.woff b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.woff new file mode 100755 index 00000000..9e515180 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.woff differ diff --git a/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.woff2 b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.woff2 new file mode 100755 index 00000000..7916dae8 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/Px-Grotesk-Mono-Regular.woff2 differ diff --git a/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/fonts.css b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/fonts.css new file mode 100644 index 00000000..fe8de640 --- /dev/null +++ b/examples/react-app/src/fonts/Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/fonts.css @@ -0,0 +1,30 @@ +/* LEGAL DISCLAIMER + * + * These Fonts are licensed only for use on these domains and their subdomains: + * fuel.network + * + * It is illegal to download or use them on other websites. + * + * While the @font-face statements below may be modified by the client, this + * disclaimer may not be removed. + * + * Optimo webfonts are protected by copyright law and provided under license. To modify, alter, translate, convert, decode or reverse engineer in any manner whatsoever, including converting the Font Software into a different format is strictly prohibited. The webfont files are not to be used for anything other than web font use. + * + * optimo.ch + */ + +/* INSTRUCTIONS + * + * Copy the Legal Disclaimer, the domains name and the @font-faces statements to your regular CSS file. The fonts folder(s) should be placed relative to the regular CSS file. + */ + +@font-face { + font-family: 'Px Grotesk Mono'; + /* src: url('Px-Grotesk-Mono-Regular.eot'); */ + src: + url('Px-Grotesk-Mono-Regular.woff2') format('woff2'), + url('Px-Grotesk-Mono-Regular.woff') format('woff'); + /* url('Px-Grotesk-Mono-Regular.eot?#iefix') format('embedded-opentype'), */ + font-weight: 400; + font-style: normal; +} diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.html b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.html new file mode 100644 index 00000000..2005c784 --- /dev/null +++ b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.html @@ -0,0 +1,369 @@ + + + + Px Grotesk Bold Web Specimen + + + + + + + + + +
+
Px Grotesk Bold
+
+
+
+
+ + +
+
+
+ Legal Disclaimer +
+ Optimo webfonts are protected by copyright law and provided under license. To modify, alter, translate, convert, decode or reverse engineer in any manner whatsoever, including converting the Font Software into a different format is strictly prohibited. The webfont files are not to be used for anything other than web font use.

+ ยฉ 1998โ€”2022 Optimo Sร rl +
+
+ + diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.otf b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.otf new file mode 100755 index 00000000..9eed5480 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.otf differ diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.woff b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.woff new file mode 100755 index 00000000..3c8b7e47 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.woff differ diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.woff2 b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.woff2 new file mode 100755 index 00000000..5f968f96 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/Px-Grotesk-Bold.woff2 differ diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/fonts.css b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/fonts.css new file mode 100644 index 00000000..06d3d094 --- /dev/null +++ b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Bold/fonts.css @@ -0,0 +1,30 @@ +/* LEGAL DISCLAIMER + * + * These Fonts are licensed only for use on these domains and their subdomains: + * fuel.network + * + * It is illegal to download or use them on other websites. + * + * While the @font-face statements below may be modified by the client, this + * disclaimer may not be removed. + * + * Optimo webfonts are protected by copyright law and provided under license. To modify, alter, translate, convert, decode or reverse engineer in any manner whatsoever, including converting the Font Software into a different format is strictly prohibited. The webfont files are not to be used for anything other than web font use. + * + * optimo.ch + */ + +/* INSTRUCTIONS + * + * Copy the Legal Disclaimer, the domains name and the @font-faces statements to your regular CSS file. The fonts folder(s) should be placed relative to the regular CSS file. + */ + +@font-face { + font-family: 'Px Grotesk'; + /* src: url('Px-Grotesk-Bold.eot'); */ + src: + url('Px-Grotesk-Bold.woff2') format('woff2'), + url('Px-Grotesk-Bold.woff') format('woff'); + /* url('Px-Grotesk-Bold.eot?#iefix') format('embedded-opentype'), */ + font-weight: 700; + font-style: normal; +} diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.html b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.html new file mode 100644 index 00000000..7dcc5f87 --- /dev/null +++ b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.html @@ -0,0 +1,369 @@ + + + + Px Grotesk Regular Web Specimen + + + + + + + + + +
+
Px Grotesk Regular
+
+
+
+
+ + +
+
+
+ Legal Disclaimer +
+ Optimo webfonts are protected by copyright law and provided under license. To modify, alter, translate, convert, decode or reverse engineer in any manner whatsoever, including converting the Font Software into a different format is strictly prohibited. The webfont files are not to be used for anything other than web font use.

+ ยฉ 1998โ€”2022 Optimo Sร rl +
+
+ + diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.otf b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.otf new file mode 100755 index 00000000..ee1d3b07 Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.otf differ diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.woff b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.woff new file mode 100755 index 00000000..48d9901c Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.woff differ diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.woff2 b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.woff2 new file mode 100755 index 00000000..754d356a Binary files /dev/null and b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/Px-Grotesk-Regular.woff2 differ diff --git a/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/fonts.css b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/fonts.css new file mode 100644 index 00000000..ca94d717 --- /dev/null +++ b/examples/react-app/src/fonts/Px-Grotesk/Px-Grotesk-Regular/fonts.css @@ -0,0 +1,30 @@ +/* LEGAL DISCLAIMER + * + * These Fonts are licensed only for use on these domains and their subdomains: + * fuel.network + * + * It is illegal to download or use them on other websites. + * + * While the @font-face statements below may be modified by the client, this + * disclaimer may not be removed. + * + * Optimo webfonts are protected by copyright law and provided under license. To modify, alter, translate, convert, decode or reverse engineer in any manner whatsoever, including converting the Font Software into a different format is strictly prohibited. The webfont files are not to be used for anything other than web font use. + * + * optimo.ch + */ + +/* INSTRUCTIONS + * + * Copy the Legal Disclaimer, the domains name and the @font-faces statements to your regular CSS file. The fonts folder(s) should be placed relative to the regular CSS file. + */ + +@font-face { + font-family: 'Px Grotesk'; + /* src: url('Px-Grotesk-Regular.eot'); */ + src: + url('Px-Grotesk-Regular.woff2') format('woff2'), + url('Px-Grotesk-Regular.woff') format('woff'); + /* url('Px-Grotesk-Regular.eot?#iefix') format('embedded-opentype'), */ + font-weight: 400; + font-style: normal; +} diff --git a/examples/react-app/src/fonts/index.css b/examples/react-app/src/fonts/index.css new file mode 100644 index 00000000..ddc881cf --- /dev/null +++ b/examples/react-app/src/fonts/index.css @@ -0,0 +1,6 @@ +/* Sans */ +@import url('./Px-Grotesk/Px-Grotesk-Regular/fonts.css'); +@import url('./Px-Grotesk/Px-Grotesk-Bold/fonts.css'); + +/* Mono */ +@import url('./Px-Grotesk-Mono/Px-Grotesk-Mono-Regular/fonts.css'); diff --git a/examples/react-app/src/hooks/use-log-events.ts b/examples/react-app/src/hooks/use-log-events.ts new file mode 100644 index 00000000..b5d51629 --- /dev/null +++ b/examples/react-app/src/hooks/use-log-events.ts @@ -0,0 +1,26 @@ +import { useFuel } from '@fuels/react'; +import { useEffect } from 'react'; + +export function useLogEvents() { + const { fuel } = useFuel(); + + useEffect(() => { + const log = (prefix: string) => (data: unknown) => { + console.log(prefix, data); + }; + const logAccounts = log('accounts'); + const logConnection = log('connection'); + const logCurrentAccount = log('currentAccount'); + + fuel.on(fuel.events.accounts, logAccounts); + fuel.on(fuel.events.connection, logConnection); + fuel.on(fuel.events.currentAccount, logCurrentAccount); + return () => { + fuel.off(fuel.events.accounts, logAccounts); + fuel.off(fuel.events.connection, logConnection); + fuel.off(fuel.events.currentAccount, logCurrentAccount); + }; + }, [fuel]); + + return null; +} diff --git a/examples/react-app/src/hooks/useWallet.ts b/examples/react-app/src/hooks/useWallet.ts new file mode 100644 index 00000000..e681adf5 --- /dev/null +++ b/examples/react-app/src/hooks/useWallet.ts @@ -0,0 +1,80 @@ +import { + useAccounts, + useBalance, + useConnectUI, + useFuel, + useWallet as useFuelWallet, + useIsConnected, +} from '@fuels/react'; +import { useEffect, useState } from 'react'; + +interface ICurrentConnector { + logo: string; + title: string; +} + +export const useWallet = () => { + const { fuel } = useFuel(); + const { connect, isConnecting } = useConnectUI(); + const { isConnected, refetch: refetchConnected } = useIsConnected(); + const { + accounts, + isLoading: isLoadingAccounts, + isFetching: isFetchingAccounts, + } = useAccounts(); + + const address = accounts[0]; + const { wallet, refetch: refetchWallet } = useFuelWallet(address); + + const { + balance, + isLoading: isLoadingBalance, + isFetching: isFetchingBalance, + } = useBalance({ address }); + + const [currentConnector, setCurrentConnector] = useState({ + logo: '', + title: 'Fuel Wallet', + }); + + useEffect(() => { + refetchConnected(); + }, [refetchConnected]); + + useEffect(() => { + if (!isConnected) { + setCurrentConnector({ logo: '', title: 'Fuel Wallet' }); + return; + } + + const currentConnector = fuel.currentConnector(); + + const title = currentConnector?.name ?? 'Fuel Wallet'; + + const logo = + currentConnector && typeof currentConnector.metadata?.image === 'object' + ? currentConnector.metadata.image.dark ?? '' + : (currentConnector?.metadata?.image as string) ?? ''; + + setCurrentConnector({ logo, title }); + }, [fuel.currentConnector, isConnected]); + + const isLoading = [isLoadingAccounts, isLoadingBalance].some(Boolean); + + const isFetching = [isFetchingAccounts, isFetchingBalance].some(Boolean); + + return { + address, + accounts, + balance, + currentConnector, + isConnected, + isConnecting, + isLoading, + isFetching, + wallet, + connect, + refetchConnected, + refetchWallet, + }; +}; diff --git a/examples/react-app/src/index.css b/examples/react-app/src/index.css new file mode 100644 index 00000000..4d446ec7 --- /dev/null +++ b/examples/react-app/src/index.css @@ -0,0 +1,66 @@ +@import './fonts/index.css'; + +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap'); */ + +body { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + @apply m-0 bg-black; +} + +/* Button */ +.btn { + @apply rounded-md px-3 py-1.5 font-mono text-sm font-medium transition-all duration-200 md:px-6 md:py-2.5; +} + +.btn-primary { + @apply border border-green-400/10 bg-green-900/50 text-green-400 hover:border-green-400/20 hover:bg-green-900/60; +} + +.btn-primary:disabled { + @apply cursor-not-allowed border border-zinc-400/25 bg-zinc-950 text-zinc-400; +} + +.btn-secondary { + @apply border border-indigo-400/10 bg-indigo-950 text-indigo-400 hover:border-indigo-400/25; +} + +/* Grain */ + +/* zinc-800 #27272a */ +/* zinc-700 #3f3f46 */ +/* zinc-600 #52525b */ + +.grain { + @apply dark:bg-zinc-900; + /* Graph Paper */ + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%233f3f46' fill-opacity='0.4'%3E%3Cpath opacity='.5' d='M96 95h4v1h-4v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9zm-1 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9z'/%3E%3Cpath d='M6 5V0H5v5H0v1h5v94h1V6h94V5H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); +} + +/* Gradient border */ +.gradient-border { + position: relative; + background-clip: padding-box; + border: solid 1px transparent; +} + +.gradient-border::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: -1; + margin: -1px; + border-radius: inherit; + background: linear-gradient( + to bottom, + theme('colors.zinc.600 / 0.8'), + theme('colors.zinc.800 / 0.9') + ); +} diff --git a/examples/react-app/src/main.tsx b/examples/react-app/src/main.tsx index afcca6e2..b33d1f13 100644 --- a/examples/react-app/src/main.tsx +++ b/examples/react-app/src/main.tsx @@ -7,7 +7,11 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { defaultConnectors } from '@fuels/connectors'; import { FuelProvider } from '@fuels/react'; +import * as Toast from '@radix-ui/react-toast'; + import App from './App.tsx'; +import ScreenSizeIndicator from './components/screensize-indicator.tsx'; +import './index.css'; const queryClient = new QueryClient(); @@ -15,11 +19,19 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - + + + + + diff --git a/examples/react-app/src/utils/customError.ts b/examples/react-app/src/utils/customError.ts new file mode 100644 index 00000000..82aab03d --- /dev/null +++ b/examples/react-app/src/utils/customError.ts @@ -0,0 +1,3 @@ +export interface CustomError extends Error { + message: string; +} diff --git a/examples/react-app/tailwind.config.js b/examples/react-app/tailwind.config.js new file mode 100644 index 00000000..c98e8457 --- /dev/null +++ b/examples/react-app/tailwind.config.js @@ -0,0 +1,35 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./index.html', './src/**/*.{js,jsx,ts,tsx}'], + darkMode: ['selector', '[data-theme="dark"]'], + theme: { + fontFamily: { + sans: ['Px Grotesk', 'Segoe UI', 'Roboto', 'sans-serif'], + mono: ['Px Grotesk Mono', 'monospace'], + }, + extend: { + keyframes: { + hide: { + from: { opacity: '1' }, + to: { opacity: '0' }, + }, + slideIn: { + from: { + transform: 'translateX(calc(100% + var(--viewport-padding)))', + }, + to: { transform: 'translateX(0)' }, + }, + swipeOut: { + from: { transform: 'translateX(var(--radix-toast-swipe-end-x))' }, + to: { transform: 'translateX(calc(100% + var(--viewport-padding)))' }, + }, + }, + animation: { + hide: 'hide 100ms ease-in', + slideIn: 'slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1)', + swipeOut: 'swipeOut 100ms ease-out', + }, + }, + }, + plugins: [], +}; diff --git a/examples/react-app/vite.config.ts b/examples/react-app/vite.config.ts index 4e7004eb..2959e11c 100644 --- a/examples/react-app/vite.config.ts +++ b/examples/react-app/vite.config.ts @@ -1,7 +1,13 @@ import react from '@vitejs/plugin-react'; +import tailwindcss from 'tailwindcss'; import { defineConfig } from 'vite'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [react()], + css: { + postcss: { + plugins: [tailwindcss()], + }, + }, }); diff --git a/packages/connectors/package.json b/packages/connectors/package.json index 7ccd448e..085a39c5 100644 --- a/packages/connectors/package.json +++ b/packages/connectors/package.json @@ -11,9 +11,7 @@ "types": "./dist/index.d.ts" } }, - "files": [ - "dist" - ], + "files": ["dist"], "scripts": { "build": "tsup", "build:watch": "tsup --watch", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b039aebb..551d9a53 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,25 +42,6 @@ importers: specifier: 1.4.0 version: 1.4.0 - examples/nodejs: - dependencies: - '@fuels/connectors': - specifier: workspace:* - version: link:../../packages/connectors - fuels: - specifier: 0.79.0 - version: 0.79.0(dexie@4.0.1) - devDependencies: - tsup: - specifier: 8.0.2 - version: 8.0.2(typescript@5.4.3) - tsx: - specifier: 4.7.1 - version: 4.7.1 - typescript: - specifier: 5.4.3 - version: 5.4.3 - examples/react-app: dependencies: '@fuels/connectors': @@ -69,9 +50,15 @@ importers: '@fuels/react': specifier: 0.18.0 version: 0.18.0(@tanstack/react-query@5.28.8)(@types/react-dom@18.2.22)(@types/react@18.2.71)(fuels@0.79.0)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-toast': + specifier: 1.1.5 + version: 1.1.5(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) '@tanstack/react-query': specifier: 5.28.8 version: 5.28.8(react@18.2.0) + clsx: + specifier: 2.1.0 + version: 2.1.0 fuels: specifier: 0.79.0 version: 0.79.0(dexie@4.0.1) @@ -94,6 +81,15 @@ importers: '@vitejs/plugin-react': specifier: 4.2.1 version: 4.2.1(vite@5.2.6) + autoprefixer: + specifier: 10.4.19 + version: 10.4.19(postcss@8.4.38) + postcss: + specifier: 8.4.38 + version: 8.4.38 + tailwindcss: + specifier: 3.4.1 + version: 3.4.1 typescript: specifier: 5.4.3 version: 5.4.3 @@ -197,6 +193,11 @@ packages: /@adraffy/ens-normalize@1.10.1: resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: true + /@ampproject/remapping@2.3.0: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -1750,6 +1751,30 @@ packages: '@babel/runtime': 7.24.1 dev: false + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.71)(react@18.2.0) + '@types/react': 18.2.71 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.71)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -1968,6 +1993,38 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-toast@1.1.5(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fRLn227WHIBRSzuRzGJ8W+5YALxofH23y0MlPLddaIpLpCDqdE0NZlS2NRQDRiptfxDeeCjgFIpexB1/zkxDlw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.1 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.71)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.71 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.71)(react@18.2.0): resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} peerDependencies: @@ -2026,6 +2083,27 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.1 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.71)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.71 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@rollup/rollup-android-arm-eabi@4.13.0: resolution: {integrity: sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==} cpu: [arm] @@ -2397,6 +2475,10 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} dependencies: @@ -2464,6 +2546,22 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + /autoprefixer@10.4.19(postcss@8.4.38): + resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.23.0 + caniuse-lite: 1.0.30001600 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.38 + postcss-value-parser: 4.2.0 + dev: true + /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -2564,6 +2662,11 @@ packages: set-function-length: 1.2.2 dev: true + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: true + /camelcase-keys@6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} @@ -2688,6 +2791,11 @@ packages: engines: {node: '>=0.8'} dev: true + /clsx@2.1.0: + resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==} + engines: {node: '>=6'} + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -2773,6 +2881,12 @@ packages: shebang-command: 2.0.0 which: 2.0.2 + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -2918,6 +3032,10 @@ packages: /dexie@4.0.1: resolution: {integrity: sha512-wSNn+TcCh+DuE2pdg058K3MhxA4g+IiZlW7yGz4cMd/t3z2rJXZcV3HDxZljbrICU2Iq0qY4UHnbolTMK/+bcA==} + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2930,6 +3048,10 @@ packages: path-type: 4.0.0 dev: true + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + /dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} @@ -3316,6 +3438,10 @@ packages: combined-stream: 1.0.8 mime-types: 2.1.35 + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + dev: true + /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -3460,28 +3586,17 @@ packages: get-intrinsic: 1.2.4 dev: true - /get-tsconfig@4.7.3: - resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} - dependencies: - resolve-pkg-maps: 1.0.0 - dev: true - /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 + is-glob: 4.0.3 dev: true /glob@10.3.12: @@ -3914,6 +4029,11 @@ packages: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + /joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -3972,6 +4092,11 @@ packages: engines: {node: '>=6'} dev: true + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: true + /lilconfig@3.0.0: resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} engines: {node: '>=14'} @@ -4216,13 +4341,6 @@ packages: dependencies: brace-expansion: 1.1.11 - /minimatch@9.0.3: - resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -4325,6 +4443,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 + /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -4344,6 +4467,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: true + /object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} dev: true @@ -4475,14 +4603,6 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true - /path-scurry@1.10.2: resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} engines: {node: '>=16 || 14 >=14.17'} @@ -4517,6 +4637,11 @@ packages: hasBin: true dev: true + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + /pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -4557,7 +4682,29 @@ packages: engines: {node: '>= 0.4'} dev: true - /postcss-load-config@4.0.2: + /postcss-import@15.1.0(postcss@8.4.38): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.38 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: true + + /postcss-js@4.0.1(postcss@8.4.38): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.38 + dev: true + + /postcss-load-config@4.0.2(postcss@8.4.38): resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} engines: {node: '>= 14'} peerDependencies: @@ -4570,9 +4717,32 @@ packages: optional: true dependencies: lilconfig: 3.1.1 + postcss: 8.4.38 yaml: 2.4.1 dev: true + /postcss-nested@6.0.1(postcss@8.4.38): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.38 + postcss-selector-parser: 6.0.16 + dev: true + + /postcss-selector-parser@6.0.16: + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + /postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} @@ -4707,6 +4877,12 @@ packages: dependencies: loose-envify: 1.4.0 + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: true + /read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -4777,10 +4953,6 @@ packages: engines: {node: '>=8'} dev: true - /resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true - /resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -5174,7 +5346,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.5 commander: 4.1.1 - glob: 10.3.10 + glob: 10.3.12 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.6 @@ -5206,6 +5378,37 @@ packages: '@types/node': 10.12.18 long: 4.0.0 + /tailwindcss@3.4.1: + resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + 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.38 + postcss-import: 15.1.0(postcss@8.4.38) + postcss-js: 4.0.1(postcss@8.4.38) + postcss-load-config: 4.0.2(postcss@8.4.38) + postcss-nested: 6.0.1(postcss@8.4.38) + postcss-selector-parser: 6.0.16 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + dev: true + /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -5334,7 +5537,7 @@ packages: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2 + postcss-load-config: 4.0.2(postcss@8.4.38) resolve-from: 5.0.0 rollup: 3.29.4 source-map: 0.8.0-beta.0 @@ -5373,7 +5576,7 @@ packages: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.2 + postcss-load-config: 4.0.2(postcss@8.4.38) resolve-from: 5.0.0 rollup: 4.13.0 source-map: 0.8.0-beta.0 @@ -5385,17 +5588,6 @@ packages: - ts-node dev: true - /tsx@4.7.1: - resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==} - engines: {node: '>=18.0.0'} - hasBin: true - dependencies: - esbuild: 0.19.12 - get-tsconfig: 4.7.3 - optionalDependencies: - fsevents: 2.3.3 - dev: true - /tty-table@4.2.3: resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} engines: {node: '>=8.0.0'} @@ -5625,6 +5817,10 @@ packages: tslib: 2.6.2 dev: false + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + /uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true