{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "use-document-title",
  "title": "useDocumentTitle",
  "description": "Sets document.title for as long as a component is mounted and restores the pre-mount title on unmount.",
  "files": [
    {
      "path": "src/registry/hooks/use-document-title.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nexport interface UseDocumentTitleOptions {\n  /** Restore `document.title` to the snapshot taken at mount when unmounting. Defaults to `true`. */\n  restoreOnUnmount?: boolean\n}\n\n/**\n * Sets `document.title` to `title` and keeps it in sync on every change. At mount\n * the title as it stands **at that instant** is snapshotted into a ref; at unmount\n * it is restored from that snapshot when `restoreOnUnmount` (default `true`), and\n * left at the last title this hook wrote when `false`.\n *\n * `document` is only read and written inside effects — never during render or on\n * the server — so the hook is safe in server-rendered components.\n *\n * Nested instances (say a route layout and a page component that both call it):\n * each instance only remembers the title that was on the page when *it* mounted,\n * and knows nothing about the others. Mount order decides what you see — the one\n * that mounts last writes `document.title` last, so it wins. But if unmount order\n * isn't strictly last-in-first-out (an outer instance unmounting before an inner\n * one), the snapshot the outer instance restores is older than the title the inner\n * one set, and the title \"jumps back\" further than expected instead of to the\n * enclosing title. That is deliberate, simplified semantics, not a bug — when you\n * genuinely need strict restore ordering across levels, use one shared title stack\n * rather than several independent hook instances (see Customization levers in the\n * docs).\n */\nexport function useDocumentTitle(\n  title: string,\n  options: UseDocumentTitleOptions = {},\n): void {\n  const { restoreOnUnmount = true } = options\n  const restoreOnUnmountRef = React.useRef(restoreOnUnmount)\n  const previousTitleRef = React.useRef<string | null>(null)\n\n  // Keep restoreOnUnmountRef on the latest option — the unmount cleanup runs once\n  // and must read the current value, not the one closed over at mount.\n  React.useEffect(() => {\n    restoreOnUnmountRef.current = restoreOnUnmount\n  }, [restoreOnUnmount])\n\n  // Snapshot the title at mount and restore it at unmount; empty deps so it fires\n  // once on a real mount/unmount instead of re-snapshotting on every title change.\n  React.useEffect(() => {\n    previousTitleRef.current = document.title\n    return () => {\n      if (restoreOnUnmountRef.current && previousTitleRef.current !== null) {\n        document.title = previousTitleRef.current\n      }\n    }\n  }, [])\n\n  React.useEffect(() => {\n    document.title = title\n  }, [title])\n}\n\nexport default useDocumentTitle\n",
      "type": "registry:hook"
    }
  ],
  "type": "registry:hook"
}