1import { isValidElement, type ReactElement } from "react";
2
3/**
4 * Depth-first search over a React element tree produced by calling a component
5 * as a plain function (see `reactHookHarness`). Descends through props so
6 * render-prop and slot-style children are reachable. Returns the first element
7 * the visitor accepts, or null.
8 */
9export function visitElements(
10 node: unknown,
11 visitor: (element: ReactElement<Record<string, unknown>>) => boolean,
12): ReactElement<Record<string, unknown>> | null {
13 if (Array.isArray(node)) {
14 for (const child of node) {
15 const found = visitElements(child, visitor);
16 if (found) return found;
17 }
18 return null;
19 }
20 if (!isValidElement<Record<string, unknown>>(node)) return null;
21 if (visitor(node)) return node;
22 for (const value of Object.values(node.props)) {
23 const found = visitElements(value, visitor);
24 if (found) return found;
25 }
26 return null;
27}