From faa5623390000989e4fef4ee8422bef101989173 Mon Sep 17 00:00:00 2001 From: Gonzalo D'elia Date: Thu, 26 Mar 2026 14:20:56 -0300 Subject: [PATCH 1/3] Move files into folders --- .knip.json | 2 +- package.json | 4 ++-- src/{useAddTokenToWallet.ts => useAddTokenToWallet/index.ts} | 2 +- src/{useAllowance.ts => useAllowance/index.ts} | 0 src/{useDebounce.ts => useDebounce/index.ts} | 0 .../index.ts} | 0 .../index.ts} | 2 +- src/{useEstimateFees.ts => useEstimateFees/index.ts} | 2 +- src/{useNativeBalance.ts => useNativeBalance/index.ts} | 0 src/{useNeedsApproval.ts => useNeedsApproval/index.ts} | 2 +- src/{useOnClickOutside.ts => useOnClickOutside/index.ts} | 0 src/{useOnKeyUp.ts => useOnKeyUp/index.ts} | 0 src/{useTokenBalance.ts => useTokenBalance/index.ts} | 0 src/{useTotalSupply.ts => useTotalSupply/index.ts} | 0 .../index.ts} | 2 +- src/{useWindowSize.ts => useWindowSize/index.ts} | 0 16 files changed, 8 insertions(+), 8 deletions(-) rename src/{useAddTokenToWallet.ts => useAddTokenToWallet/index.ts} (95%) rename src/{useAllowance.ts => useAllowance/index.ts} (100%) rename src/{useDebounce.ts => useDebounce/index.ts} (100%) rename src/{useEnsureConnectedTo.ts => useEnsureConnectedTo/index.ts} (100%) rename src/{useEstimateApproveErc20Fees.ts => useEstimateApproveErc20Fees/index.ts} (93%) rename src/{useEstimateFees.ts => useEstimateFees/index.ts} (98%) rename src/{useNativeBalance.ts => useNativeBalance/index.ts} (100%) rename src/{useNeedsApproval.ts => useNeedsApproval/index.ts} (93%) rename src/{useOnClickOutside.ts => useOnClickOutside/index.ts} (100%) rename src/{useOnKeyUp.ts => useOnKeyUp/index.ts} (100%) rename src/{useTokenBalance.ts => useTokenBalance/index.ts} (100%) rename src/{useTotalSupply.ts => useTotalSupply/index.ts} (100%) rename src/{useUpdateNativeBalanceAfterReceipt.ts => useUpdateNativeBalanceAfterReceipt/index.ts} (94%) rename src/{useWindowSize.ts => useWindowSize/index.ts} (100%) diff --git a/.knip.json b/.knip.json index e71daeb..ef01f77 100644 --- a/.knip.json +++ b/.knip.json @@ -1,4 +1,4 @@ { - "entry": ["src/*.ts"], + "entry": ["src/*/index.ts"], "ignoreDependencies": ["eslint-config-prettier"] } diff --git a/package.json b/package.json index 02ab968..b88e95a 100644 --- a/package.json +++ b/package.json @@ -75,8 +75,8 @@ "type": "module", "exports": { "./*": { - "types": "./_types/*.d.ts", - "import": "./_esm/*.js" + "types": "./_types/*/index.d.ts", + "import": "./_esm/*/index.js" } }, "sideEffects": false diff --git a/src/useAddTokenToWallet.ts b/src/useAddTokenToWallet/index.ts similarity index 95% rename from src/useAddTokenToWallet.ts rename to src/useAddTokenToWallet/index.ts index b34f4f2..6f6d676 100644 --- a/src/useAddTokenToWallet.ts +++ b/src/useAddTokenToWallet/index.ts @@ -3,7 +3,7 @@ import { type Address, type Chain } from "viem"; import { useAccount, useWalletClient } from "wagmi"; import watchAsset from "@hemilabs/wallet-watch-asset"; -import { useEnsureConnectedTo } from "./useEnsureConnectedTo"; +import { useEnsureConnectedTo } from "../useEnsureConnectedTo"; type Token = { address: Address; diff --git a/src/useAllowance.ts b/src/useAllowance/index.ts similarity index 100% rename from src/useAllowance.ts rename to src/useAllowance/index.ts diff --git a/src/useDebounce.ts b/src/useDebounce/index.ts similarity index 100% rename from src/useDebounce.ts rename to src/useDebounce/index.ts diff --git a/src/useEnsureConnectedTo.ts b/src/useEnsureConnectedTo/index.ts similarity index 100% rename from src/useEnsureConnectedTo.ts rename to src/useEnsureConnectedTo/index.ts diff --git a/src/useEstimateApproveErc20Fees.ts b/src/useEstimateApproveErc20Fees/index.ts similarity index 93% rename from src/useEstimateApproveErc20Fees.ts rename to src/useEstimateApproveErc20Fees/index.ts index 6afccf8..3c2b25f 100644 --- a/src/useEstimateApproveErc20Fees.ts +++ b/src/useEstimateApproveErc20Fees/index.ts @@ -1,7 +1,7 @@ import { type Address, type Chain, encodeFunctionData, erc20Abi } from "viem"; import { useEstimateGas } from "wagmi"; -import { useEstimateFees } from "./useEstimateFees"; +import { useEstimateFees } from "../useEstimateFees"; export const useEstimateApproveErc20Fees = function ({ amount, diff --git a/src/useEstimateFees.ts b/src/useEstimateFees/index.ts similarity index 98% rename from src/useEstimateFees.ts rename to src/useEstimateFees/index.ts index 2aaa803..cfed2f5 100644 --- a/src/useEstimateFees.ts +++ b/src/useEstimateFees/index.ts @@ -12,7 +12,7 @@ import { import { parseEther } from "viem/utils"; import { useConfig } from "wagmi"; -import { estimateTotalFee } from "./utils/fees"; +import { estimateTotalFee } from "../utils/fees"; const defaultBlockCount = 4; const defaultOverEstimation = 1.5; diff --git a/src/useNativeBalance.ts b/src/useNativeBalance/index.ts similarity index 100% rename from src/useNativeBalance.ts rename to src/useNativeBalance/index.ts diff --git a/src/useNeedsApproval.ts b/src/useNeedsApproval/index.ts similarity index 93% rename from src/useNeedsApproval.ts rename to src/useNeedsApproval/index.ts index 137d373..ef943e1 100644 --- a/src/useNeedsApproval.ts +++ b/src/useNeedsApproval/index.ts @@ -1,7 +1,7 @@ import type { Address, Chain } from "viem"; import { useAccount } from "wagmi"; -import { useAllowance } from "./useAllowance"; +import { useAllowance } from "../useAllowance"; type UseNeedsApprovalParameters = { amount: bigint; diff --git a/src/useOnClickOutside.ts b/src/useOnClickOutside/index.ts similarity index 100% rename from src/useOnClickOutside.ts rename to src/useOnClickOutside/index.ts diff --git a/src/useOnKeyUp.ts b/src/useOnKeyUp/index.ts similarity index 100% rename from src/useOnKeyUp.ts rename to src/useOnKeyUp/index.ts diff --git a/src/useTokenBalance.ts b/src/useTokenBalance/index.ts similarity index 100% rename from src/useTokenBalance.ts rename to src/useTokenBalance/index.ts diff --git a/src/useTotalSupply.ts b/src/useTotalSupply/index.ts similarity index 100% rename from src/useTotalSupply.ts rename to src/useTotalSupply/index.ts diff --git a/src/useUpdateNativeBalanceAfterReceipt.ts b/src/useUpdateNativeBalanceAfterReceipt/index.ts similarity index 94% rename from src/useUpdateNativeBalanceAfterReceipt.ts rename to src/useUpdateNativeBalanceAfterReceipt/index.ts index 20080c5..ff89ce4 100644 --- a/src/useUpdateNativeBalanceAfterReceipt.ts +++ b/src/useUpdateNativeBalanceAfterReceipt/index.ts @@ -3,7 +3,7 @@ import { type GetBalanceReturnType } from "@wagmi/core"; import { useCallback } from "react"; import type { Chain, TransactionReceipt } from "viem"; -import { useNativeBalance } from "./useNativeBalance"; +import { useNativeBalance } from "../useNativeBalance"; /** * Returns a function that updates the native token balance after a transaction receipt. diff --git a/src/useWindowSize.ts b/src/useWindowSize/index.ts similarity index 100% rename from src/useWindowSize.ts rename to src/useWindowSize/index.ts From 2e2b3002830d1bdf340627b10e9983a16752d528 Mon Sep 17 00:00:00 2001 From: Gonzalo D'elia Date: Thu, 26 Mar 2026 14:47:51 -0300 Subject: [PATCH 2/3] Add README.md to each hook Closes #9 Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 32 ++++++------ src/useAddTokenToWallet/README.md | 41 ++++++++++++++++ src/useAllowance/README.md | 47 ++++++++++++++++++ src/useDebounce/README.md | 38 ++++++++++++++ src/useEnsureConnectedTo/README.md | 39 +++++++++++++++ src/useEstimateApproveErc20Fees/README.md | 43 ++++++++++++++++ src/useEstimateFees/README.md | 49 +++++++++++++++++++ src/useNativeBalance/README.md | 35 +++++++++++++ src/useNeedsApproval/README.md | 39 +++++++++++++++ src/useOnClickOutside/README.md | 37 ++++++++++++++ src/useOnKeyUp/README.md | 41 ++++++++++++++++ src/useTokenBalance/README.md | 43 ++++++++++++++++ src/useTotalSupply/README.md | 41 ++++++++++++++++ .../README.md | 41 ++++++++++++++++ src/useWindowSize/README.md | 39 +++++++++++++++ 15 files changed, 589 insertions(+), 16 deletions(-) create mode 100644 src/useAddTokenToWallet/README.md create mode 100644 src/useAllowance/README.md create mode 100644 src/useDebounce/README.md create mode 100644 src/useEnsureConnectedTo/README.md create mode 100644 src/useEstimateApproveErc20Fees/README.md create mode 100644 src/useEstimateFees/README.md create mode 100644 src/useNativeBalance/README.md create mode 100644 src/useNeedsApproval/README.md create mode 100644 src/useOnClickOutside/README.md create mode 100644 src/useOnKeyUp/README.md create mode 100644 src/useTokenBalance/README.md create mode 100644 src/useTotalSupply/README.md create mode 100644 src/useUpdateNativeBalanceAfterReceipt/README.md create mode 100644 src/useWindowSize/README.md diff --git a/README.md b/README.md index e04084f..e7099a0 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,19 @@ npm install @hemilabs/react-hooks ## Hooks Reference -| Hook Name | Source File | -| ---------------------------------- | --------------------------------------------------------------------------------- | -| useAddTokenToWallet | [useAddTokenToWallet](./src/useAddTokenToWallet.ts) | -| useAllowance | [useAllowance](./src/useAllowance.ts) | -| useDebounce | [useDebounce](./src/useDebounce.ts) | -| useEnsureConnectedTo | [useEnsureConnectedTo](./src/useEnsureConnectedTo.ts) | -| useEstimateApproveErc20Fees | [useEstimateApproveErc20Fees](./src/useEstimateApproveErc20Fees.ts) | -| useEstimateFees | [useEstimateFees](./src/useEstimateFees.ts) | -| useNativeBalance | [useNativeBalance](./src/useNativeBalance.ts) | -| useTokenBalance | [useTokenBalance](./src/useTokenBalance.ts) | -| useUpdateNativeBalanceAfterReceipt | [useUpdateNativeBalanceAfterReceipt](./src/useUpdateNativeBalanceAfterReceipt.ts) | -| useNeedsApproval | [useNeedsApproval](./src/useNeedsApproval.ts) | -| useOnClickOutside | [useOnClickOutside](./src/useOnClickOutside.ts) | -| useOnKeyUp | [useOnKeyUp](./src/useOnKeyUp.ts) | -| useTotalSupply | [useTotalSupply](./src/useTotalSupply.ts) | -| useWindowSize | [useWindowSize](./src/useWindowSize.ts) | +| Hook Name | Docs | +| ---------------------------------- | ------------------------------------------------------------------------------ | +| useAddTokenToWallet | [useAddTokenToWallet](./src/useAddTokenToWallet) | +| useAllowance | [useAllowance](./src/useAllowance) | +| useDebounce | [useDebounce](./src/useDebounce) | +| useEnsureConnectedTo | [useEnsureConnectedTo](./src/useEnsureConnectedTo) | +| useEstimateApproveErc20Fees | [useEstimateApproveErc20Fees](./src/useEstimateApproveErc20Fees) | +| useEstimateFees | [useEstimateFees](./src/useEstimateFees) | +| useNativeBalance | [useNativeBalance](./src/useNativeBalance) | +| useNeedsApproval | [useNeedsApproval](./src/useNeedsApproval) | +| useOnClickOutside | [useOnClickOutside](./src/useOnClickOutside) | +| useOnKeyUp | [useOnKeyUp](./src/useOnKeyUp) | +| useTokenBalance | [useTokenBalance](./src/useTokenBalance) | +| useTotalSupply | [useTotalSupply](./src/useTotalSupply) | +| useUpdateNativeBalanceAfterReceipt | [useUpdateNativeBalanceAfterReceipt](./src/useUpdateNativeBalanceAfterReceipt) | +| useWindowSize | [useWindowSize](./src/useWindowSize) | diff --git a/src/useAddTokenToWallet/README.md b/src/useAddTokenToWallet/README.md new file mode 100644 index 0000000..e486408 --- /dev/null +++ b/src/useAddTokenToWallet/README.md @@ -0,0 +1,41 @@ +# useAddTokenToWallet + +Provides a mutation to add a token to the user's wallet. Ensures the wallet is connected to the correct chain before adding. + +## Import + +```ts +import { useAddTokenToWallet } from "@hemilabs/react-hooks/useAddTokenToWallet"; +``` + +## Parameters + +Takes an options object: + +| Parameter | Type | Required | Description | +| ------------------------ | --------- | -------- | -------------------------- | +| token.address | `Address` | Yes | Token contract address | +| token.chainId | `number` | Yes | Chain ID where token lives | +| token.extensions.logoURI | `string` | No | Token logo URL | + +## Return Value + +Returns a `UseMutationResult` from TanStack React Query. Call `mutate()` or `mutateAsync()` to trigger the wallet prompt. + +## Usage + +```tsx +import { useAddTokenToWallet } from "@hemilabs/react-hooks/useAddTokenToWallet"; + +function AddToken() { + const { mutate: addToken } = useAddTokenToWallet({ + token: { + address: "0x...", + chainId: 1, + extensions: { logoURI: "https://example.com/logo.png" }, + }, + }); + + return ; +} +``` diff --git a/src/useAllowance/README.md b/src/useAllowance/README.md new file mode 100644 index 0000000..d99c1c8 --- /dev/null +++ b/src/useAllowance/README.md @@ -0,0 +1,47 @@ +# useAllowance + +Fetches the ERC20 token allowance for an owner-spender pair. + +## Import + +```ts +import { + useAllowance, + allowanceQueryKey, + allowanceQueryOptions, +} from "@hemilabs/react-hooks/useAllowance"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| --------- | --------------------------------------- | -------- | --------------------------------------------------------------------- | +| owner | `Address \| undefined` | No | Token owner address | +| spender | `Address \| undefined` | No | Spender address | +| token | `{ address: Address; chainId: number }` | Yes | Token contract info | +| query | `UseQueryOptions` | No | Additional query options (excluding `queryFn`, `queryKey`, `enabled`) | + +## Return Value + +Returns `UseQueryResult` with the allowance amount. + +## Exported Helpers + +- **`allowanceQueryKey({ owner, spender, token })`** - Generates a query key for cache management. +- **`allowanceQueryOptions({ client, owner, spender, token, query })`** - Generates query options for use with `queryClient.ensureQueryData`. + +## Usage + +```tsx +import { useAllowance } from "@hemilabs/react-hooks/useAllowance"; + +function Allowance() { + const { data: allowance } = useAllowance({ + owner: "0x...", + spender: "0x...", + token: { address: "0x...", chainId: 1 }, + }); + + return Allowance: {allowance?.toString()}; +} +``` diff --git a/src/useDebounce/README.md b/src/useDebounce/README.md new file mode 100644 index 0000000..535e38e --- /dev/null +++ b/src/useDebounce/README.md @@ -0,0 +1,38 @@ +# useDebounce + +Debounces a value, returning the updated value only after a specified delay has passed without changes. + +## Import + +```ts +import { useDebounce } from "@hemilabs/react-hooks/useDebounce"; +``` + +## Parameters + +| Parameter | Type | Required | Default | Description | +| --------- | -------- | -------- | ------- | --------------------- | +| value | `T` | Yes | - | The value to debounce | +| delay | `number` | No | `300` | Delay in milliseconds | + +## Return Value + +Returns the debounced value of type `T`. + +## Usage + +```tsx +import { useDebounce } from "@hemilabs/react-hooks/useDebounce"; + +function Search() { + const [query, setQuery] = useState(""); + const debouncedQuery = useDebounce(query, 500); + + useEffect(() => { + // Only fires 500ms after the user stops typing + fetchResults(debouncedQuery); + }, [debouncedQuery]); + + return setQuery(e.target.value)} />; +} +``` diff --git a/src/useEnsureConnectedTo/README.md b/src/useEnsureConnectedTo/README.md new file mode 100644 index 0000000..9a5d06c --- /dev/null +++ b/src/useEnsureConnectedTo/README.md @@ -0,0 +1,39 @@ +# useEnsureConnectedTo + +Returns a function that ensures the wallet is connected to a specific chain. Throws an error if no account is connected, or switches chains if needed. + +## Import + +```ts +import { useEnsureConnectedTo } from "@hemilabs/react-hooks/useEnsureConnectedTo"; +``` + +## Parameters + +None. + +## Return Value + +Returns an async function: `(targetChainId: number) => Promise` + +- Throws if no wallet account is connected. +- Switches chain if the wallet is connected to a different chain. + +## Usage + +```tsx +import { useEnsureConnectedTo } from "@hemilabs/react-hooks/useEnsureConnectedTo"; +import { optimism } from "viem/chains"; + +function ChainSwitch() { + const ensureConnectedTo = useEnsureConnectedTo(); + + const handleClick = async () => { + // Switch to Optimism if not connected + await ensureConnectedTo(optimism.id); + // Do another op now in the OP chain + }; + + return ; +} +``` diff --git a/src/useEstimateApproveErc20Fees/README.md b/src/useEstimateApproveErc20Fees/README.md new file mode 100644 index 0000000..e1a0b47 --- /dev/null +++ b/src/useEstimateApproveErc20Fees/README.md @@ -0,0 +1,43 @@ +# useEstimateApproveErc20Fees + +Estimates the total transaction fees for approving an ERC20 token. + +## Import + +```ts +import { useEstimateApproveErc20Fees } from "@hemilabs/react-hooks/useEstimateApproveErc20Fees"; +``` + +## Parameters + +| Parameter | Type | Required | Default | Description | +| ------------- | --------- | -------- | ------- | -------------------------------- | +| amount | `bigint` | Yes | - | Amount to approve | +| spender | `Address` | Yes | - | Spender address | +| token.address | `Address` | Yes | - | Token contract address | +| token.chainId | `number` | Yes | - | Chain ID | +| enabled | `boolean` | No | `true` | Whether to enable the estimation | + +## Return Value + +| Property | Type | Description | +| -------- | --------------------- | ------------------------------------- | +| fees | `bigint \| undefined` | Estimated total fee in wei | +| isError | `boolean` | Whether there was an estimation error | + +## Usage + +```tsx +import { useEstimateApproveErc20Fees } from "@hemilabs/react-hooks/useEstimateApproveErc20Fees"; + +function ApproveFees() { + const { fees, isError } = useEstimateApproveErc20Fees({ + amount: 1000000n, + spender: "0x...", + token: { address: "0x...", chainId: 1 }, + }); + + if (isError) return Error estimating fees; + return Estimated fee: {fees?.toString()} wei; +} +``` diff --git a/src/useEstimateFees/README.md b/src/useEstimateFees/README.md new file mode 100644 index 0000000..30dda31 --- /dev/null +++ b/src/useEstimateFees/README.md @@ -0,0 +1,49 @@ +# useEstimateFees + +Estimates the total transaction fee for an EIP-1559 compatible network. Uses recent base fee history and a suggested or fallback `maxPriorityFeePerGas` to calculate a conservative `maxFeePerGas`, multiplied by the estimated gas units. + +## Import + +```ts +import { + useEstimateFees, + estimateFeesQueryOptions, +} from "@hemilabs/react-hooks/useEstimateFees"; +``` + +## Parameters + +| Parameter | Type | Required | Default | Description | +| ------------------- | --------- | -------- | ---------------------- | ----------------------------------------------- | +| chainId | `number` | Yes | - | Chain ID of the target network | +| fallbackPriorityFee | `bigint` | No | `1000000000n` (1 gwei) | Fallback priority fee when unavailable | +| gasUnits | `bigint` | No | - | Estimated gas units for the transaction | +| isGasUnitsError | `boolean` | No | `false` | Whether there was an error estimating gas units | +| overEstimation | `number` | No | `1.5` | Multiplier to pad the estimated fee | + +## Return Value + +| Property | Type | Description | +| -------- | --------------------- | ------------------------------------- | +| fees | `bigint \| undefined` | Estimated total fee in wei | +| isError | `boolean` | Whether there was an estimation error | + +## Exported Helpers + +- **`estimateFeesQueryOptions({ chainId, config, gasUnits, queryClient, ... })`** - Generates query options for use with `queryClient.ensureQueryData` or `queryClient.fetchQuery` outside of React. + +## Usage + +```tsx +import { useEstimateFees } from "@hemilabs/react-hooks/useEstimateFees"; + +function TransactionFee() { + const { fees, isError } = useEstimateFees({ + chainId: 1, + gasUnits: 21000n, + }); + + if (isError) return Error estimating fees; + return Estimated fee: {fees?.toString()} wei; +} +``` diff --git a/src/useNativeBalance/README.md b/src/useNativeBalance/README.md new file mode 100644 index 0000000..d4283b1 --- /dev/null +++ b/src/useNativeBalance/README.md @@ -0,0 +1,35 @@ +# useNativeBalance + +Fetches the native token balance for the connected account on a specific chain. + +## Import + +```ts +import { useNativeBalance } from "@hemilabs/react-hooks/useNativeBalance"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| --------- | -------- | -------- | ----------- | +| chainId | `number` | Yes | Chain ID | + +## Return Value + +Returns the result from wagmi's `useBalance` hook. + +## Usage + +```tsx +import { useNativeBalance } from "@hemilabs/react-hooks/useNativeBalance"; + +function Balance() { + const { data: balance } = useNativeBalance({ chainId: 1 }); + + return ( + + Balance: {balance?.formatted} {balance?.symbol} + + ); +} +``` diff --git a/src/useNeedsApproval/README.md b/src/useNeedsApproval/README.md new file mode 100644 index 0000000..84f19f8 --- /dev/null +++ b/src/useNeedsApproval/README.md @@ -0,0 +1,39 @@ +# useNeedsApproval + +Checks if an ERC20 token needs approval for a specific amount. Returns `true` if the current allowance is less than the required amount. + +## Import + +```ts +import { useNeedsApproval } from "@hemilabs/react-hooks/useNeedsApproval"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| ------------- | --------- | -------- | ----------------------- | +| amount | `bigint` | Yes | Amount to check against | +| spender | `Address` | Yes | Spender address | +| token.address | `Address` | Yes | Token contract address | +| token.chainId | `number` | Yes | Chain ID | + +## Return Value + +Returns `UseQueryResult` - `true` if approval is needed. + +## Usage + +```tsx +import { useNeedsApproval } from "@hemilabs/react-hooks/useNeedsApproval"; + +function ApproveButton() { + const { data: needsApproval } = useNeedsApproval({ + amount: 1000000n, + spender: "0x...", + token: { address: "0x...", chainId: 1 }, + }); + + if (!needsApproval) return null; + return ; +} +``` diff --git a/src/useOnClickOutside/README.md b/src/useOnClickOutside/README.md new file mode 100644 index 0000000..b6fd91a --- /dev/null +++ b/src/useOnClickOutside/README.md @@ -0,0 +1,37 @@ +# useOnClickOutside + +Calls a handler when clicking or touching outside the referenced element. + +## Import + +```ts +import { useOnClickOutside } from "@hemilabs/react-hooks/useOnClickOutside"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| ---------- | --------------------------------------- | -------- | ------------------------------ | +| handler | `(e: MouseEvent \| TouchEvent) => void` | No | Callback when clicking outside | +| initialRef | `RefObject` | No | Optional existing ref to use | + +> **Note:** Wrap `handler` in `useCallback` to avoid re-attaching listeners on every render. + +## Return Value + +Returns a `RefObject` to attach to the target element. + +## Usage + +```tsx +import { useOnClickOutside } from "@hemilabs/react-hooks/useOnClickOutside"; + +function Dropdown() { + const [open, setOpen] = useState(false); + const ref = useOnClickOutside( + useCallback(() => setOpen(false), []), + ); + + return
{open &&
    ...
}
; +} +``` diff --git a/src/useOnKeyUp/README.md b/src/useOnKeyUp/README.md new file mode 100644 index 0000000..f3689ce --- /dev/null +++ b/src/useOnKeyUp/README.md @@ -0,0 +1,41 @@ +# useOnKeyUp + +Attaches a `keyup` event listener to the document. + +## Import + +```ts +import { useOnKeyUp } from "@hemilabs/react-hooks/useOnKeyUp"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| ---------- | ---------------------------- | -------- | ---------------------------- | +| handler | `(e: KeyboardEvent) => void` | Yes | Callback on keyup event | +| initialRef | `RefObject` | No | Optional existing ref to use | + +## Return Value + +Returns a `RefObject` for optional element tracking. + +## Usage + +```tsx +import { useCallback, useState } from "react"; +import { useOnKeyUp } from "@hemilabs/react-hooks/useOnKeyUp"; + +function Modal() { + const [open, setOpen] = useState(true); + const ref = useOnKeyUp( + useCallback((e) => { + if (e.key === "Escape") { + setOpen(false); + } + }, []), + ); + + if (!open) return null; + return
Press Escape to close
; +} +``` diff --git a/src/useTokenBalance/README.md b/src/useTokenBalance/README.md new file mode 100644 index 0000000..3362d55 --- /dev/null +++ b/src/useTokenBalance/README.md @@ -0,0 +1,43 @@ +# useTokenBalance + +Fetches the ERC20 token balance for the connected account. + +## Import + +```ts +import { + useTokenBalance, + tokenBalanceQueryKey, + tokenBalanceQueryOptions, +} from "@hemilabs/react-hooks/useTokenBalance"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| ------------- | --------- | -------- | ---------------------- | +| token.address | `Address` | Yes | Token contract address | +| token.chainId | `number` | Yes | Chain ID | + +## Return Value + +Returns `UseQueryResult` with the token balance. + +## Exported Helpers + +- **`tokenBalanceQueryKey({ account, token })`** - Generates a query key for cache management. +- **`tokenBalanceQueryOptions({ account, client, token })`** - Generates query options for use with `queryClient.ensureQueryData`. + +## Usage + +```tsx +import { useTokenBalance } from "@hemilabs/react-hooks/useTokenBalance"; + +function TokenBalance() { + const { data: balance } = useTokenBalance({ + token: { address: "0x...", chainId: 1 }, + }); + + return Balance: {balance?.toString()}; +} +``` diff --git a/src/useTotalSupply/README.md b/src/useTotalSupply/README.md new file mode 100644 index 0000000..a691a36 --- /dev/null +++ b/src/useTotalSupply/README.md @@ -0,0 +1,41 @@ +# useTotalSupply + +Fetches the total supply of an ERC20 token. + +## Import + +```ts +import { + useTotalSupply, + totalSupplyQueryKey, +} from "@hemilabs/react-hooks/useTotalSupply"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| ------------- | --------- | -------- | ---------------------- | +| token.address | `Address` | Yes | Token contract address | +| token.chainId | `number` | Yes | Chain ID | + +## Return Value + +Returns `UseQueryResult` with the total supply. + +## Exported Helpers + +- **`totalSupplyQueryKey({ token })`** - Generates a query key for cache management. + +## Usage + +```tsx +import { useTotalSupply } from "@hemilabs/react-hooks/useTotalSupply"; + +function TotalSupply() { + const { data: totalSupply } = useTotalSupply({ + token: { address: "0x...", chainId: 1 }, + }); + + return Total Supply: {totalSupply?.toString()}; +} +``` diff --git a/src/useUpdateNativeBalanceAfterReceipt/README.md b/src/useUpdateNativeBalanceAfterReceipt/README.md new file mode 100644 index 0000000..555bffe --- /dev/null +++ b/src/useUpdateNativeBalanceAfterReceipt/README.md @@ -0,0 +1,41 @@ +# useUpdateNativeBalanceAfterReceipt + +Returns a function that updates the cached native token balance after a transaction receipt. Subtracts gas costs and an optional amount from the cached balance. + +## Import + +```ts +import { useUpdateNativeBalanceAfterReceipt } from "@hemilabs/react-hooks/useUpdateNativeBalanceAfterReceipt"; +``` + +## Parameters + +| Parameter | Type | Required | Description | +| --------- | -------- | -------- | ----------- | +| chainId | `number` | Yes | Chain ID | + +## Return Value + +Returns a function: `(receipt: TransactionReceipt, amount?: bigint) => void` + +| Parameter | Type | Required | Default | Description | +| --------- | -------------------- | -------- | ----------- | --------------------------------- | +| receipt | `TransactionReceipt` | Yes | - | Transaction receipt with gas info | +| amount | `bigint` | No | `BigInt(0)` | Additional amount to subtract | + +## Usage + +```tsx +import { useUpdateNativeBalanceAfterReceipt } from "@hemilabs/react-hooks/useUpdateNativeBalanceAfterReceipt"; + +function Transaction() { + const updateBalance = useUpdateNativeBalanceAfterReceipt({ chainId: 1 }); + + const onSuccess = (receipt: TransactionReceipt) => { + // Updates cached balance by subtracting gas + amount sent + updateBalance(receipt, parseEther("0.1")); + }; + + return ; +} +``` diff --git a/src/useWindowSize/README.md b/src/useWindowSize/README.md new file mode 100644 index 0000000..1747538 --- /dev/null +++ b/src/useWindowSize/README.md @@ -0,0 +1,39 @@ +# useWindowSize + +Returns the current window dimensions. Updates automatically when the window is resized. + +## Import + +```ts +import { useWindowSize } from "@hemilabs/react-hooks/useWindowSize"; +``` + +## Parameters + +None. + +## Return Value + +| Property | Type | Description | +| -------- | -------- | ------------------------------- | +| height | `number` | Current window height in pixels | +| width | `number` | Current window width in pixels | + +Both values default to `0` during server-side rendering. + +## Usage + +```tsx +import { useWindowSize } from "@hemilabs/react-hooks/useWindowSize"; + +function ResponsiveLayout() { + const { width, height } = useWindowSize(); + + return ( +
+ Window: {width}x{height} + {width < 768 && } +
+ ); +} +``` From c26ab8659562665209ddbf411a64e05a27e6f7b1 Mon Sep 17 00:00:00 2001 From: Gonzalo D'elia Date: Thu, 26 Mar 2026 15:20:51 -0300 Subject: [PATCH 3/3] Fix hook signatures in READMEs Co-Authored-By: Claude Opus 4.6 (1M context) --- src/useNativeBalance/README.md | 2 +- src/useTokenBalance/README.md | 15 +++++++++------ src/useTotalSupply/README.md | 15 +++++++++------ src/useUpdateNativeBalanceAfterReceipt/README.md | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/useNativeBalance/README.md b/src/useNativeBalance/README.md index d4283b1..e700255 100644 --- a/src/useNativeBalance/README.md +++ b/src/useNativeBalance/README.md @@ -24,7 +24,7 @@ Returns the result from wagmi's `useBalance` hook. import { useNativeBalance } from "@hemilabs/react-hooks/useNativeBalance"; function Balance() { - const { data: balance } = useNativeBalance({ chainId: 1 }); + const { data: balance } = useNativeBalance(1); return ( diff --git a/src/useTokenBalance/README.md b/src/useTokenBalance/README.md index 3362d55..c2b5d04 100644 --- a/src/useTokenBalance/README.md +++ b/src/useTokenBalance/README.md @@ -14,10 +14,12 @@ import { ## Parameters -| Parameter | Type | Required | Description | -| ------------- | --------- | -------- | ---------------------- | -| token.address | `Address` | Yes | Token contract address | -| token.chainId | `number` | Yes | Chain ID | +Takes a `token` object directly (not wrapped): + +| Parameter | Type | Required | Description | +| --------- | --------- | -------- | ---------------------- | +| address | `Address` | Yes | Token contract address | +| chainId | `number` | Yes | Chain ID | ## Return Value @@ -25,7 +27,7 @@ Returns `UseQueryResult` with the token balance. ## Exported Helpers -- **`tokenBalanceQueryKey({ account, token })`** - Generates a query key for cache management. +- **`tokenBalanceQueryKey(token, account)`** - Generates a query key for cache management. - **`tokenBalanceQueryOptions({ account, client, token })`** - Generates query options for use with `queryClient.ensureQueryData`. ## Usage @@ -35,7 +37,8 @@ import { useTokenBalance } from "@hemilabs/react-hooks/useTokenBalance"; function TokenBalance() { const { data: balance } = useTokenBalance({ - token: { address: "0x...", chainId: 1 }, + address: "0x...", + chainId: 1, }); return Balance: {balance?.toString()}; diff --git a/src/useTotalSupply/README.md b/src/useTotalSupply/README.md index a691a36..30c25cc 100644 --- a/src/useTotalSupply/README.md +++ b/src/useTotalSupply/README.md @@ -13,10 +13,12 @@ import { ## Parameters -| Parameter | Type | Required | Description | -| ------------- | --------- | -------- | ---------------------- | -| token.address | `Address` | Yes | Token contract address | -| token.chainId | `number` | Yes | Chain ID | +Takes a `token` object directly (not wrapped): + +| Parameter | Type | Required | Description | +| --------- | --------- | -------- | ---------------------- | +| address | `Address` | Yes | Token contract address | +| chainId | `number` | Yes | Chain ID | ## Return Value @@ -24,7 +26,7 @@ Returns `UseQueryResult` with the total supply. ## Exported Helpers -- **`totalSupplyQueryKey({ token })`** - Generates a query key for cache management. +- **`totalSupplyQueryKey(token)`** - Generates a query key for cache management. ## Usage @@ -33,7 +35,8 @@ import { useTotalSupply } from "@hemilabs/react-hooks/useTotalSupply"; function TotalSupply() { const { data: totalSupply } = useTotalSupply({ - token: { address: "0x...", chainId: 1 }, + address: "0x...", + chainId: 1, }); return Total Supply: {totalSupply?.toString()}; diff --git a/src/useUpdateNativeBalanceAfterReceipt/README.md b/src/useUpdateNativeBalanceAfterReceipt/README.md index 555bffe..3b4aa96 100644 --- a/src/useUpdateNativeBalanceAfterReceipt/README.md +++ b/src/useUpdateNativeBalanceAfterReceipt/README.md @@ -29,7 +29,7 @@ Returns a function: `(receipt: TransactionReceipt, amount?: bigint) => void` import { useUpdateNativeBalanceAfterReceipt } from "@hemilabs/react-hooks/useUpdateNativeBalanceAfterReceipt"; function Transaction() { - const updateBalance = useUpdateNativeBalanceAfterReceipt({ chainId: 1 }); + const updateBalance = useUpdateNativeBalanceAfterReceipt(1); const onSuccess = (receipt: TransactionReceipt) => { // Updates cached balance by subtracting gas + amount sent