diff --git a/README.md b/README.md
index 15b5d15..a6f9f93 100644
--- a/README.md
+++ b/README.md
@@ -15,9 +15,11 @@
+
+
-
+
@@ -86,6 +88,10 @@ function Component() {
> ๐ Full docs with a **page per hook** and **live demos**:
+
+
+### State (19)
+
- **[`useToggle`](https://hookli.vercel.app/docs/use-toggle)** โ Boolean state with toggle and explicit set.
- **[`useForm`](https://hookli.vercel.app/docs/use-form)** โ Controlled form state with one change handler.
- **[`useLocalStorage`](https://hookli.vercel.app/docs/use-local-storage)** โ State persisted to localStorage.
@@ -99,6 +105,15 @@ function Component() {
- **[`useStep`](https://hookli.vercel.app/docs/use-step)** โ 1-indexed step counter for wizards and steppers.
- **[`useCountdown`](https://hookli.vercel.app/docs/use-countdown)** โ Self-stopping countdown or count-up timer.
- **[`useMap`](https://hookli.vercel.app/docs/use-map)** โ Manage a Map as immutable React state.
+- **[`usePrevious`](https://hookli.vercel.app/docs/use-previous)** โ Track a value from the previous render.
+- **[`useList`](https://hookli.vercel.app/docs/use-list)** โ Array state with push, insert, update, remove, and clear helpers.
+- **[`useSet`](https://hookli.vercel.app/docs/use-set)** โ Set state with add, remove, toggle, has, and clear helpers.
+- **[`useQueue`](https://hookli.vercel.app/docs/use-queue)** โ FIFO queue state with add, remove, clear, and first/last/size.
+- **[`useDefault`](https://hookli.vercel.app/docs/use-default)** โ useState that falls back to a default when the value is nullish.
+- **[`useRafState`](https://hookli.vercel.app/docs/use-raf-state)** โ useState whose updates are batched to the next animation frame.
+
+### Effects (16)
+
- **[`useDebounce`](https://hookli.vercel.app/docs/use-debounce)** โ Debounces a changing value.
- **[`useDebounceValue`](https://hookli.vercel.app/docs/use-debounce-value)** โ State whose debounced copy updates after a pause.
- **[`useDebounceCallback`](https://hookli.vercel.app/docs/use-debounce-callback)** โ Debounces a callback, with cancel, flush and isPending.
@@ -110,6 +125,14 @@ function Component() {
- **[`useIsClient`](https://hookli.vercel.app/docs/use-is-client)** โ Reports false on the server and true after hydration.
- **[`useIsMounted`](https://hookli.vercel.app/docs/use-is-mounted)** โ A stable getter for whether the component is still mounted.
- **[`useDocumentTitle`](https://hookli.vercel.app/docs/use-document-title)** โ Keeps document.title in sync with a value, SSR-safe.
+- **[`useThrottle`](https://hookli.vercel.app/docs/use-throttle)** โ Throttle a fast-changing value to at most one update per interval.
+- **[`useUpdateEffect`](https://hookli.vercel.app/docs/use-update-effect)** โ A useEffect that skips the initial mount and runs only on updates.
+- **[`useEffectOnce`](https://hookli.vercel.app/docs/use-effect-once)** โ Run an effect exactly once, on mount.
+- **[`usePageVisibility`](https://hookli.vercel.app/docs/use-page-visibility)** โ Track whether the page/tab is currently visible.
+- **[`useDeepCompareEffect`](https://hookli.vercel.app/docs/use-deep-compare-effect)** โ useEffect that compares dependencies by deep structural equality.
+
+### DOM (22)
+
- **[`useEventListener`](https://hookli.vercel.app/docs/use-event-listener)** โ Subscribe to a window, document or element event with cleanup.
- **[`useClickOutside`](https://hookli.vercel.app/docs/use-click-outside)** โ Runs a callback on outside click.
- **[`useMousePosition`](https://hookli.vercel.app/docs/use-mouse-position)** โ Cursor coordinates within an element.
@@ -125,33 +148,27 @@ function Component() {
- **[`useWindowSize`](https://hookli.vercel.app/docs/use-window-size)** โ Tracks the viewport's { width, height }, updated on resize.
- **[`useCopyToClipboard`](https://hookli.vercel.app/docs/use-copy-to-clipboard)** โ Copy text to the clipboard, tracking the last copied value.
- **[`useScript`](https://hookli.vercel.app/docs/use-script)** โ Load an external script and report its load status.
-- **[`useFetch`](https://hookli.vercel.app/docs/use-fetch)** โ Declarative fetch with loading and error status.
-- **[`useGeoLocation`](https://hookli.vercel.app/docs/use-geo-location)** โ Browser geolocation state.
-- **[`usePrevious`](https://hookli.vercel.app/docs/use-previous)** โ Track a value from the previous render.
-- **[`useList`](https://hookli.vercel.app/docs/use-list)** โ Array state with push, insert, update, remove, and clear helpers.
-- **[`useSet`](https://hookli.vercel.app/docs/use-set)** โ Set state with add, remove, toggle, has, and clear helpers.
-- **[`useThrottle`](https://hookli.vercel.app/docs/use-throttle)** โ Throttle a fast-changing value to at most one update per interval.
-- **[`useUpdateEffect`](https://hookli.vercel.app/docs/use-update-effect)** โ A useEffect that skips the initial mount and runs only on updates.
-- **[`useEffectOnce`](https://hookli.vercel.app/docs/use-effect-once)** โ Run an effect exactly once, on mount.
- **[`useKeyPress`](https://hookli.vercel.app/docs/use-key-press)** โ Track whether a specific key is currently held down.
- **[`useWindowScroll`](https://hookli.vercel.app/docs/use-window-scroll)** โ Track the window scroll position reactively.
-- **[`useAsync`](https://hookli.vercel.app/docs/use-async)** โ Run an async function and track its loading, error, and value state.
-- **[`useMutation`](https://hookli.vercel.app/docs/use-mutation)** โ Run an async write action on demand and track status, data, and error.
-- **[`usePagination`](https://hookli.vercel.app/docs/use-pagination)** โ Page, page size, total pages, navigation helpers, and the current item range.
-- **[`useNetworkState`](https://hookli.vercel.app/docs/use-network-state)** โ Track online/offline status and connection details.
-- **[`usePageVisibility`](https://hookli.vercel.app/docs/use-page-visibility)** โ Track whether the page/tab is currently visible.
- **[`useIdle`](https://hookli.vercel.app/docs/use-idle)** โ Detect user inactivity after a configurable threshold.
-- **[`useQueue`](https://hookli.vercel.app/docs/use-queue)** โ FIFO queue state with add, remove, clear, and first/last/size.
-- **[`useDefault`](https://hookli.vercel.app/docs/use-default)** โ useState that falls back to a default when the value is nullish.
-- **[`useRafState`](https://hookli.vercel.app/docs/use-raf-state)** โ useState whose updates are batched to the next animation frame.
-- **[`useDeepCompareEffect`](https://hookli.vercel.app/docs/use-deep-compare-effect)** โ useEffect that compares dependencies by deep structural equality.
- **[`useTextSelection`](https://hookli.vercel.app/docs/use-text-selection)** โ Track the text the user has currently selected on the page.
- **[`useLongPress`](https://hookli.vercel.app/docs/use-long-press)** โ Detect a long press (mouse or touch) via spreadable handlers.
- **[`useHotkeys`](https://hookli.vercel.app/docs/use-hotkeys)** โ Bind a keyboard shortcut combo (e.g. ctrl+k) to a callback.
- **[`useFullscreen`](https://hookli.vercel.app/docs/use-fullscreen)** โ Control the Fullscreen API for an element and track its state.
+
+### Data (8)
+
+- **[`useFetch`](https://hookli.vercel.app/docs/use-fetch)** โ Declarative fetch with loading and error status.
+- **[`useGeoLocation`](https://hookli.vercel.app/docs/use-geo-location)** โ Browser geolocation state.
+- **[`useAsync`](https://hookli.vercel.app/docs/use-async)** โ Run an async function and track its loading, error, and value state.
+- **[`useMutation`](https://hookli.vercel.app/docs/use-mutation)** โ Run an async write action on demand and track status, data, and error.
+- **[`usePagination`](https://hookli.vercel.app/docs/use-pagination)** โ Page, page size, total pages, navigation helpers, and the current item range.
+- **[`useNetworkState`](https://hookli.vercel.app/docs/use-network-state)** โ Track online/offline status and connection details.
- **[`useBattery`](https://hookli.vercel.app/docs/use-battery)** โ Read device battery level and charging state (where supported).
- **[`usePermission`](https://hookli.vercel.app/docs/use-permission)** โ Query a Permissions API permission and track its state.
+
+
## ๐งช TypeScript
Every hook ships its own declarations โ no `@types/hookli` needed. Data hooks are generic,
diff --git a/packages/hookli/README.md b/packages/hookli/README.md
index 383f534..2fc5ae8 100644
--- a/packages/hookli/README.md
+++ b/packages/hookli/README.md
@@ -13,9 +13,11 @@
+
+
-
+
@@ -84,6 +86,10 @@ function Component() {
> ๐ Full docs with a **page per hook** and **live demos**:
+
+
+### State (19)
+
- **[`useToggle`](https://hookli.vercel.app/docs/use-toggle)** โ Boolean state with toggle and explicit set.
- **[`useForm`](https://hookli.vercel.app/docs/use-form)** โ Controlled form state with one change handler.
- **[`useLocalStorage`](https://hookli.vercel.app/docs/use-local-storage)** โ State persisted to localStorage.
@@ -97,6 +103,15 @@ function Component() {
- **[`useStep`](https://hookli.vercel.app/docs/use-step)** โ 1-indexed step counter for wizards and steppers.
- **[`useCountdown`](https://hookli.vercel.app/docs/use-countdown)** โ Self-stopping countdown or count-up timer.
- **[`useMap`](https://hookli.vercel.app/docs/use-map)** โ Manage a Map as immutable React state.
+- **[`usePrevious`](https://hookli.vercel.app/docs/use-previous)** โ Track a value from the previous render.
+- **[`useList`](https://hookli.vercel.app/docs/use-list)** โ Array state with push, insert, update, remove, and clear helpers.
+- **[`useSet`](https://hookli.vercel.app/docs/use-set)** โ Set state with add, remove, toggle, has, and clear helpers.
+- **[`useQueue`](https://hookli.vercel.app/docs/use-queue)** โ FIFO queue state with add, remove, clear, and first/last/size.
+- **[`useDefault`](https://hookli.vercel.app/docs/use-default)** โ useState that falls back to a default when the value is nullish.
+- **[`useRafState`](https://hookli.vercel.app/docs/use-raf-state)** โ useState whose updates are batched to the next animation frame.
+
+### Effects (16)
+
- **[`useDebounce`](https://hookli.vercel.app/docs/use-debounce)** โ Debounces a changing value.
- **[`useDebounceValue`](https://hookli.vercel.app/docs/use-debounce-value)** โ State whose debounced copy updates after a pause.
- **[`useDebounceCallback`](https://hookli.vercel.app/docs/use-debounce-callback)** โ Debounces a callback, with cancel, flush and isPending.
@@ -108,6 +123,14 @@ function Component() {
- **[`useIsClient`](https://hookli.vercel.app/docs/use-is-client)** โ Reports false on the server and true after hydration.
- **[`useIsMounted`](https://hookli.vercel.app/docs/use-is-mounted)** โ A stable getter for whether the component is still mounted.
- **[`useDocumentTitle`](https://hookli.vercel.app/docs/use-document-title)** โ Keeps document.title in sync with a value, SSR-safe.
+- **[`useThrottle`](https://hookli.vercel.app/docs/use-throttle)** โ Throttle a fast-changing value to at most one update per interval.
+- **[`useUpdateEffect`](https://hookli.vercel.app/docs/use-update-effect)** โ A useEffect that skips the initial mount and runs only on updates.
+- **[`useEffectOnce`](https://hookli.vercel.app/docs/use-effect-once)** โ Run an effect exactly once, on mount.
+- **[`usePageVisibility`](https://hookli.vercel.app/docs/use-page-visibility)** โ Track whether the page/tab is currently visible.
+- **[`useDeepCompareEffect`](https://hookli.vercel.app/docs/use-deep-compare-effect)** โ useEffect that compares dependencies by deep structural equality.
+
+### DOM (22)
+
- **[`useEventListener`](https://hookli.vercel.app/docs/use-event-listener)** โ Subscribe to a window, document or element event with cleanup.
- **[`useClickOutside`](https://hookli.vercel.app/docs/use-click-outside)** โ Runs a callback on outside click.
- **[`useMousePosition`](https://hookli.vercel.app/docs/use-mouse-position)** โ Cursor coordinates within an element.
@@ -123,33 +146,27 @@ function Component() {
- **[`useWindowSize`](https://hookli.vercel.app/docs/use-window-size)** โ Tracks the viewport's { width, height }, updated on resize.
- **[`useCopyToClipboard`](https://hookli.vercel.app/docs/use-copy-to-clipboard)** โ Copy text to the clipboard, tracking the last copied value.
- **[`useScript`](https://hookli.vercel.app/docs/use-script)** โ Load an external script and report its load status.
-- **[`useFetch`](https://hookli.vercel.app/docs/use-fetch)** โ Declarative fetch with loading and error status.
-- **[`useGeoLocation`](https://hookli.vercel.app/docs/use-geo-location)** โ Browser geolocation state.
-- **[`usePrevious`](https://hookli.vercel.app/docs/use-previous)** โ Track a value from the previous render.
-- **[`useList`](https://hookli.vercel.app/docs/use-list)** โ Array state with push, insert, update, remove, and clear helpers.
-- **[`useSet`](https://hookli.vercel.app/docs/use-set)** โ Set state with add, remove, toggle, has, and clear helpers.
-- **[`useThrottle`](https://hookli.vercel.app/docs/use-throttle)** โ Throttle a fast-changing value to at most one update per interval.
-- **[`useUpdateEffect`](https://hookli.vercel.app/docs/use-update-effect)** โ A useEffect that skips the initial mount and runs only on updates.
-- **[`useEffectOnce`](https://hookli.vercel.app/docs/use-effect-once)** โ Run an effect exactly once, on mount.
- **[`useKeyPress`](https://hookli.vercel.app/docs/use-key-press)** โ Track whether a specific key is currently held down.
- **[`useWindowScroll`](https://hookli.vercel.app/docs/use-window-scroll)** โ Track the window scroll position reactively.
-- **[`useAsync`](https://hookli.vercel.app/docs/use-async)** โ Run an async function and track its loading, error, and value state.
-- **[`useMutation`](https://hookli.vercel.app/docs/use-mutation)** โ Run an async write action on demand and track status, data, and error.
-- **[`usePagination`](https://hookli.vercel.app/docs/use-pagination)** โ Page, page size, total pages, navigation helpers, and the current item range.
-- **[`useNetworkState`](https://hookli.vercel.app/docs/use-network-state)** โ Track online/offline status and connection details.
-- **[`usePageVisibility`](https://hookli.vercel.app/docs/use-page-visibility)** โ Track whether the page/tab is currently visible.
- **[`useIdle`](https://hookli.vercel.app/docs/use-idle)** โ Detect user inactivity after a configurable threshold.
-- **[`useQueue`](https://hookli.vercel.app/docs/use-queue)** โ FIFO queue state with add, remove, clear, and first/last/size.
-- **[`useDefault`](https://hookli.vercel.app/docs/use-default)** โ useState that falls back to a default when the value is nullish.
-- **[`useRafState`](https://hookli.vercel.app/docs/use-raf-state)** โ useState whose updates are batched to the next animation frame.
-- **[`useDeepCompareEffect`](https://hookli.vercel.app/docs/use-deep-compare-effect)** โ useEffect that compares dependencies by deep structural equality.
- **[`useTextSelection`](https://hookli.vercel.app/docs/use-text-selection)** โ Track the text the user has currently selected on the page.
- **[`useLongPress`](https://hookli.vercel.app/docs/use-long-press)** โ Detect a long press (mouse or touch) via spreadable handlers.
- **[`useHotkeys`](https://hookli.vercel.app/docs/use-hotkeys)** โ Bind a keyboard shortcut combo (e.g. ctrl+k) to a callback.
- **[`useFullscreen`](https://hookli.vercel.app/docs/use-fullscreen)** โ Control the Fullscreen API for an element and track its state.
+
+### Data (8)
+
+- **[`useFetch`](https://hookli.vercel.app/docs/use-fetch)** โ Declarative fetch with loading and error status.
+- **[`useGeoLocation`](https://hookli.vercel.app/docs/use-geo-location)** โ Browser geolocation state.
+- **[`useAsync`](https://hookli.vercel.app/docs/use-async)** โ Run an async function and track its loading, error, and value state.
+- **[`useMutation`](https://hookli.vercel.app/docs/use-mutation)** โ Run an async write action on demand and track status, data, and error.
+- **[`usePagination`](https://hookli.vercel.app/docs/use-pagination)** โ Page, page size, total pages, navigation helpers, and the current item range.
+- **[`useNetworkState`](https://hookli.vercel.app/docs/use-network-state)** โ Track online/offline status and connection details.
- **[`useBattery`](https://hookli.vercel.app/docs/use-battery)** โ Read device battery level and charging state (where supported).
- **[`usePermission`](https://hookli.vercel.app/docs/use-permission)** โ Query a Permissions API permission and track its state.
+
+
## ๐งช TypeScript
Every hook ships its own declarations โ no `@types/hookli` needed. Data hooks are generic,
diff --git a/packages/hookli/scripts/gen-readme.mjs b/packages/hookli/scripts/gen-readme.mjs
index af2af74..58a29c4 100644
--- a/packages/hookli/scripts/gen-readme.mjs
+++ b/packages/hookli/scripts/gen-readme.mjs
@@ -1,6 +1,7 @@
-// Regenerate the README's "Available hooks" list + hook-count badge from the
+// Regenerate the README's category-grouped hook index + hook-count badge from the
// single source of truth: hooks.manifest.json. Run via `pnpm --filter hookli gen:manifest`
-// (also runs on prepublishOnly). Do NOT hand-edit the generated list.
+// (also runs on prepublishOnly). Do NOT hand-edit the generated index โ everything
+// between the HOOKS:START / HOOKS:END markers is overwritten.
import { readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
@@ -9,6 +10,10 @@ const root = join(dirname(fileURLToPath(import.meta.url)), "..");
const { hooks } = JSON.parse(readFileSync(join(root, "hooks.manifest.json"), "utf8"));
const count = hooks.length;
+// Category order + labels mirror apps/docs/lib/hooks-registry.ts (CATEGORY_ORDER / CATEGORY_LABELS).
+const CATEGORY_ORDER = ["state", "effects", "dom", "data"];
+const CATEGORY_LABELS = { state: "State", effects: "Effects", dom: "DOM", data: "Data" };
+
const readmePath = join(root, "README.md");
let md = readFileSync(readmePath, "utf8");
@@ -16,13 +21,26 @@ let md = readFileSync(readmePath, "utf8");
md = md.replace(/badge\/\d+_hooks-/g, `badge/${count}_hooks-`);
md = md.replace(/alt="\d+ hooks"/g, `alt="${count} hooks"`);
-// 2) the "Available hooks" bullet block (a contiguous run of `- **[`useX`](โฆ)** โ โฆ` lines)
-const list = hooks
- .map((h) => `- **[\`${h.name}\`](https://hookli.vercel.app/docs/${h.slug})** โ ${h.description}`)
- .join("\n");
-const block = /(?:^- \*\*\[`use.*\r?\n?)+/m;
-if (!block.test(md)) throw new Error("gen-readme: could not find the hook bullet block in README.md");
-md = md.replace(block, list + "\n");
+// 2) the category-grouped hook index, between the HOOKS:START / HOOKS:END markers.
+// A hook whose category is not one we know would be silently dropped โ fail loudly.
+const known = new Set(CATEGORY_ORDER);
+const orphan = hooks.find((h) => !known.has(h.category));
+if (orphan) {
+ throw new Error(`gen-readme: hook "${orphan.name}" has unknown category "${orphan.category}"`);
+}
+
+const bullet = (h) =>
+ `- **[\`${h.name}\`](https://hookli.vercel.app/docs/${h.slug})** โ ${h.description}`;
+const grouped = CATEGORY_ORDER.map((cat) => {
+ const items = hooks.filter((h) => h.category === cat);
+ return `### ${CATEGORY_LABELS[cat]} (${items.length})\n\n${items.map(bullet).join("\n")}`;
+}).join("\n\n");
+
+const region = /()[\s\S]*?()/;
+if (!region.test(md)) {
+ throw new Error("gen-readme: could not find the HOOKS:START / HOOKS:END markers in README.md");
+}
+md = md.replace(region, `$1\n\n${grouped}\n\n$2`);
writeFileSync(readmePath, md);