{"version":3,"file":"react-node.cjs","names":[],"sources":["../../src/utils/react-node.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\n\nconst PORTAL_KEY = \"$$typeof\" as const;\nconst REACT_PORTAL_TYPE = Symbol.for(\"react.portal\");\n\n/** ---------------------------------------------------------\n * * **Utility: `isReactNode`**\n * ----------------------------------------------------------\n * **Determines whether a given value is a valid**\n * **[`ReactNode`](https://react-typescript-cheatsheet.netlify.app/docs/react-types/reactnode/)** **and therefore safely render-able by React.**\n *\n * - **ReactNode includes:**\n *    - `null` and `undefined`\n *    - Primitive renderables: `string`, `number`, `boolean`\n *      (booleans are ignored by React but allowed as children)\n *    - Any valid `ReactElement` (JSX, Fragment, memo, forwardRef, etc.)\n *    - React Portals\n *    - Arrays of ReactNode (nested arbitrarily deep)\n *    - Generic **iterables** whose elements are ReactNode\n *      (e.g. `Set`, `Map.values()`, generators)\n *\n * - **❌ Values that are **NOT** valid ReactNode:**\n *    - `bigint`, `symbol`, `function` (including async components as raw functions)\n *    - Plain objects (`{}`), unless they are valid ReactElement\n *    - `Date`, `RegExp`, `Promise`, `Map`, `WeakMap`, `WeakSet`\n *    - Any iterable whose items contain invalid ReactNode entries\n *\n * - **✔️ Behavior:**\n *    - Performs **deep recursive** validation for arrays and nested iterables.\n *    - Detects React portals via the internal `$$typeof` symbol.\n *    - Gracefully handles iteration errors—if iteration fails, returns `false`.\n *    - Fully compatible with **React 18 & 19** (including concurrent & streaming mode).\n *\n * @param {unknown} value - The input to test for ReactNode compatibility.\n *\n * @returns {boolean} - `true` if the value can be safely rendered by React, otherwise `false`.\n *\n * @example\n * isReactNode(null);                // ➔ true\n * isReactNode(undefined);           // ➔ true\n * isReactNode(<></>);               // ➔ true\n * isReactNode(\"hello\");             // ➔ true\n * isReactNode(123);                 // ➔ true\n * isReactNode(<div />);             // ➔ true\n * isReactNode([<span key=\"1\" />]);  // ➔ true\n * isReactNode(new Set([\"a\", \"b\"])); // ➔ true\n *\n * @example\n * isReactNode({});                  // ➔ false\n * isReactNode(Symbol(\"x\"));         // ➔ false\n * isReactNode(() => <div />);       // ➔ false (functions are not nodes)\n * isReactNode(async () => <div />); // ➔ false (async components are functions)\n * isReactNode(new Date());          // ➔ false\n * isReactNode(Promise.resolve(1));  // ➔ false\n *\n * @example\n * // Iterable example:\n * const items = {\n *   *[Symbol.iterator]() {\n *     yield \"a\";\n *     yield <div />;\n *   }\n * };\n * isReactNode(items); // ➔ true\n */\nexport function isReactNode(value: unknown): value is ReactNode {\n  return baseIsReactNode(value, new WeakSet());\n}\n\n/** @internal */\nfunction baseIsReactNode(value: unknown, cache: WeakSet<object>): boolean {\n  // null / undefined\n  if (value == null) return true;\n\n  switch (typeof value) {\n    case \"string\":\n    case \"number\":\n    case \"boolean\":\n      return true;\n\n    // Explicit invalid primitives\n    case \"bigint\":\n    case \"symbol\":\n    case \"function\":\n      return false;\n\n    case \"object\":\n      break;\n  }\n\n  // ReactElement\n  if (isValidElement(value)) return true;\n\n  const obj = value as Record<string, unknown>;\n\n  // Avoid re-processing (cycles)\n  if (cache.has(obj)) return true;\n  cache.add(obj);\n\n  // React Portal\n  if (obj?.[PORTAL_KEY] === REACT_PORTAL_TYPE) return true;\n\n  // Non-renderable instances\n  if (\n    value instanceof Date ||\n    value instanceof RegExp ||\n    value instanceof Promise ||\n    value instanceof Map ||\n    value instanceof WeakMap ||\n    value instanceof WeakSet\n  ) {\n    return false;\n  }\n\n  // Array\n  if (Array.isArray(value)) {\n    for (const item of value) {\n      if (!baseIsReactNode(item, cache)) return false;\n    }\n    return true;\n  }\n\n  // Iterable (exclude string — already handled earlier)\n  const iterator = (value as { [Symbol.iterator]?: unknown })?.[\n    Symbol.iterator\n  ];\n  if (typeof iterator === \"function\") {\n    try {\n      for (const item of value as Iterable<unknown>) {\n        if (!baseIsReactNode(item, cache)) return false;\n      }\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  return false;\n}\n"],"mappings":";;;;;;;;;;;;;;AAEA,MAAM,aAAa;AACnB,MAAM,oBAAoB,OAAO,IAAI,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DnD,SAAgB,YAAY,OAAoC;CAC9D,OAAO,gBAAgB,uBAAO,IAAI,QAAQ,CAAC;AAC7C;;AAGA,SAAS,gBAAgB,OAAgB,OAAiC;CAExE,IAAI,SAAS,MAAM,OAAO;CAE1B,QAAQ,OAAO,OAAf;EACE,KAAK;EACL,KAAK;EACL,KAAK,WACH,OAAO;EAGT,KAAK;EACL,KAAK;EACL,KAAK,YACH,OAAO;EAET,KAAK,UACH;CACJ;CAGA,8BAAmB,KAAK,GAAG,OAAO;CAElC,MAAM,MAAM;CAGZ,IAAI,MAAM,IAAI,GAAG,GAAG,OAAO;CAC3B,MAAM,IAAI,GAAG;CAGb,IAAI,MAAM,gBAAgB,mBAAmB,OAAO;CAGpD,IACE,iBAAiB,QACjB,iBAAiB,UACjB,iBAAiB,WACjB,iBAAiB,OACjB,iBAAiB,WACjB,iBAAiB,SAEjB,OAAO;CAIT,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,gBAAgB,MAAM,KAAK,GAAG,OAAO;EAE5C,OAAO;CACT;CAMA,IAAI,OAHc,QAChB,OAAO,cAEe,YACtB,IAAI;EACF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,gBAAgB,MAAM,KAAK,GAAG,OAAO;EAE5C,OAAO;CACT,QAAQ;EACN,OAAO;CACT;CAGF,OAAO;AACT"}
