{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "api-react-utils-docs",
  "title": "React Utils",
  "description": "API reference for @udecode/react-utils.",
  "files": [
    {
      "path": "../../content/docs/api/react-utils.mdx",
      "content": "---\ntitle: React Utils\ndescription: API reference for @udecode/react-utils.\n---\n\n`@udecode/react-utils` provides small React primitives used across Plate UI packages. It is also re-exported from `platejs/react` and `@udecode/cn`.\n\n## Installation\n\n```bash\nnpm install @udecode/react-utils\n```\n\nUse direct imports in shared UI packages. Use `platejs/react` when you are already inside a Plate app surface.\n\n## Components\n\n| Component | Renders | Notes |\n| --- | --- | --- |\n| `PortalBody` | `ReactDOM.createPortal(children, element ?? document.body)` | Returns children directly when no DOM container is available. |\n| `Box` | Slot-aware `div` | Created with `createSlotComponent('div')`. Supports `as` and `asChild`. |\n| `Text` | Slot-aware `span` | Created with `createSlotComponent('span')`. Supports `as` and `asChild`. |\n| `MemoizedChildren` | `React.memo(({ children }) => <>{children}</>)` | Prevents child-only rerenders when parent props are stable. |\n\n```tsx title=\"Portal to body\"\nimport { PortalBody } from '@udecode/react-utils';\n\nexport function BodyOverlay() {\n  return (\n    <PortalBody>\n      <div role=\"status\">Saving</div>\n    </PortalBody>\n  );\n}\n```\n\n## Primitive Factories\n\nUse primitive factories when a component needs `asChild`, composed refs, hook-provided props, or hook-provided state.\n\n<API name=\"createSlotComponent\">\n<APIParameters>\n  <APIItem name=\"element\" type=\"React.ElementType\">\n    Default element or component.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"React.ForwardRefExoticComponent\">\n  A component that renders `Slot` when `asChild` is true, `as` when provided, otherwise the default element.\n</APIReturns>\n</API>\n\n<API name=\"createPrimitiveElement\">\n<APIParameters>\n  <APIItem name=\"tag\" type=\"keyof HTMLElementTagNameMap\">\n    HTML tag to render.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"React.ForwardRefExoticComponent\">\n  A typed `forwardRef` component for that intrinsic element.\n</APIReturns>\n</API>\n\n<API name=\"createPrimitiveComponent\">\n<APIParameters>\n  <APIItem name=\"element\" type=\"React.ElementType\">\n    Default element or component.\n  </APIItem>\n  <APIItem name=\"stateHook\" type=\"(options: any) => any\" optional>\n    Hook used to create state when the caller does not provide `state`.\n  </APIItem>\n  <APIItem name=\"propsHook\" type=\"(state: any) => { hidden?: boolean; props?: object; ref?: React.Ref<any> }\" optional>\n    Hook used to derive props, hidden state, and a ref from state.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"React.ForwardRefExoticComponent\">\n  A primitive component with `as`, `asChild`, `options`, `state`, `className`, `style`, and `setProps`.\n</APIReturns>\n</API>\n\n`createPrimitiveComponent` merges hook class names before consumer class names, merges hook style before consumer style, composes forwarded refs with hook refs, and returns `null` when `hidden` is true unless `asChild` is set.\n\n## Ref and Effect Hooks\n\n| API | Type | Behavior |\n| --- | --- | --- |\n| `composeRefs(...refs)` | `(...refs) => (node) => cleanup?` | Sets callback refs and ref objects to the same node. If refs return cleanup functions, the composed ref returns a cleanup. |\n| `useComposedRef(...refs)` | `(...refs) => refCallback` | Memoized `composeRefs` callback. |\n| `useStableFn(fn, deps?)` | `(fn, deps = []) => stableFn` | Returns a stable function that calls the latest `fn`. |\n| `useStableMemo(producer, deps?)` | `(producer, deps?) => value` | Stores a produced value in state and updates it in a layout effect. |\n| `useEffectOnce(effect, deps)` | `(effect, deps) => void` | Runs the effect on first render and again when the dependency values change. |\n| `useIsomorphicLayoutEffect` | `React.useLayoutEffect \\| React.useEffect` | Uses layout effect in the browser and effect during SSR. |\n\n```tsx title=\"Compose refs\"\nimport * as React from 'react';\nimport { useComposedRef } from '@udecode/react-utils';\n\nexport const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n  (props, ref) => {\n    const localRef = React.useRef<HTMLInputElement>(null);\n    const composedRef = useComposedRef(ref, localRef);\n\n    return <input ref={composedRef} {...props} />;\n  }\n);\n```\n\n## Outside Click\n\n`useOnClickOutside` returns a callback ref unless you pass explicit refs.\n\n<API name=\"useOnClickOutside\">\n<APIParameters>\n  <APIItem name=\"callback\" type=\"(event: Event) => void\">\n    Called when a configured event lands outside every tracked element.\n  </APIItem>\n  <APIItem name=\"options.disabled\" type=\"boolean\" optional>\n    Removes listeners while true.\n  </APIItem>\n  <APIItem name=\"options.eventTypes\" type=\"string[]\" optional>\n    Defaults to `['mousedown', 'touchstart']`.\n  </APIItem>\n  <APIItem name=\"options.ignoreClass\" type=\"string | string[]\" optional>\n    Defaults to `ignore-onclickoutside`. Matching ancestors are ignored.\n  </APIItem>\n  <APIItem name=\"options.excludeScrollbar\" type=\"boolean\" optional>\n    Ignores scrollbar clicks.\n  </APIItem>\n  <APIItem name=\"options.detectIFrame\" type=\"boolean\" optional>\n    Defaults to `true`. Uses window blur to detect iframe focus.\n  </APIItem>\n  <APIItem name=\"options.refs\" type=\"React.RefObject<HTMLElement | null>[]\" optional>\n    Explicit refs to observe instead of the returned callback ref.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"(element: HTMLElement | null) => void\">\n  Callback ref that registers an element for outside-click detection.\n</APIReturns>\n</API>\n\n## Memo and Event Helpers\n\n| API | Type | Behavior |\n| --- | --- | --- |\n| `useMemoizedSelector(selector, deps, equalityFn?)` | `(selector, deps, equalityFn?) => value` | Re-renders only when the selector result changes. The default equality is strict equality. |\n| `composeEventHandlers(original, next, options?)` | `(event) => void` | Calls `original`, then calls `next` unless `event.defaultPrevented` and `checkForDefaultPrevented` is true. |\n\n## Component Wrappers\n\n<API name=\"withRef\">\n<APIParameters>\n  <APIItem name=\"renderFunction\" type=\"React.ForwardRefRenderFunction\">\n    Forward-ref render function.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"React.ForwardRefExoticComponent\">\n  Typed `React.forwardRef` result.\n</APIReturns>\n</API>\n\n<API name=\"withProviders\">\n<APIParameters>\n  <APIItem name=\"...providers\" type=\"React.ComponentType | [React.ComponentType, props][]\">\n    Providers to wrap around the component. Array entries pass props to a provider.\n  </APIItem>\n  <APIItem name=\"WrappedComponent\" type=\"React.FC<T>\">\n    Component to wrap.\n  </APIItem>\n</APIParameters>\n<APIReturns type=\"(props: T) => React.ReactElement\">\n  Component wrapped by the providers from right to left.\n</APIReturns>\n</API>\n\n```tsx title=\"Wrap providers\"\nimport { withProviders } from '@udecode/react-utils';\n\nconst ThemeProvider = ({ children }: { children: React.ReactNode }) => (\n  <div data-theme=\"dark\">{children}</div>\n);\n\nconst Page = () => <main>Docs</main>;\n\nexport const ThemedPage = withProviders(ThemeProvider)(Page);\n```\n\n## Related APIs\n\n- [cn](/docs/api/cn) covers `@udecode/cn`, which re-exports this package.\n- [Plate](/docs/api/plate) covers the `platejs/react` umbrella export.\n",
      "type": "registry:file",
      "target": "content/docs/plate/api/react-utils.mdx"
    }
  ],
  "type": "registry:file"
}