{"version":3,"file":"hoc-DmokEoKK.cjs","names":["Suspense"],"sources":["../src/hoc/withSuspense/index.tsx","../src/hoc/withMemo/index.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport {\n  type ComponentType,\n  type FC,\n  forwardRef,\n  type ForwardRefExoticComponent,\n  type PropsWithoutRef,\n  type RefAttributes,\n  Suspense,\n  type SuspenseProps\n} from \"react\";\n\ntype SuspensedExoticComponent<P> = FC<P>;\ntype SuspensedForwardRefExoticComponent<P, R> = ForwardRefExoticComponent<\n  PropsWithoutRef<P> & RefAttributes<R>\n>;\n\n/** -------------------------------------------------------------\n * * ***Higher-Order Component (HOC): `WithSuspense`.***\n * -------------------------------------------------------------\n * Wraps a React component with a `<Suspense>` boundary.\n *\n * This allows the wrapped component to be lazy-loaded or deferred,\n * while providing a configurable `fallback` UI via React Suspense.\n *\n * -------------------------------------------------------------\n * **Type Inference Notes.**\n *\n * `WithSuspense` preserves the original component’s props type (`P`)\n * through generic inference. This works automatically for components\n * with **required** props, for example:\n *\n * ```tsx\n * const UserCard = (props: { id: string }) => <>...</>;\n * const Wrapped = WithSuspense(UserCard);\n * //               ^? FC<{ id: string }>  ✅ inferred correctly\n * ```\n *\n * However, TypeScript may fail to infer `P` precisely if the\n * component’s props are **fully optional**, such as:\n *\n * - `props?: P`\n * - `props: P = defaultValue`\n *\n * In such cases, TypeScript widens the type to `object`, so it is\n * recommended to **pass `<P>` explicitly**:\n *\n * ```tsx\n * const Profile = (props?: ProfileProps) => <>...</>;\n * const Broken = WithSuspense(Profile);\n * //              ^? FC<object>        ❌ incorrect\n *\n * const Fixed = WithSuspense<ProfileProps>(Profile);\n * //              ^? FC<ProfileProps>  ✅ correct\n * ```\n *\n * -------------------------------------------------------------\n * **ForwardRef Support.**\n *\n * `WithSuspense` includes a dedicated overload for components using\n * `React.forwardRef`, the returned HOC preserves:\n *\n * - `P` — the component’s props\n * - `R` — the forwarded ref type\n *\n * Example:\n *\n * ```tsx\n * const Input = React.forwardRef<HTMLInputElement, { label: string }>(\n *   (props, ref) => <input ref={ref} />\n * );\n *\n * const SuspenseInput = WithSuspense(Input);\n * //     ^? ForwardRefExoticComponent<{ label: string } & RefAttributes<HTMLInputElement>>\n * ```\n *\n * -------------------------------------------------------------\n * **React 19 Compatibility.**\n *\n * React 19 introduces automatic ref forwarding for function components, however, for full compatibility with both React 18 *and* React 19,\n * this HOC:\n *\n * - Detects `forwardRef` components via the internal `$$typeof` symbol\n * - Passes refs only when supported\n *\n * This ensures consistent runtime behavior across both versions.\n *\n * -------------------------------------------------------------\n * **Suspense Configuration (`suspenseProps`).**\n *\n * The second argument, `suspenseProps`, allows customizing behavior\n * of the `<Suspense>` boundary used to wrap the component.\n *\n * Example:\n *\n * ```tsx\n * const Wrapped = WithSuspense(UserCard, {\n *   fallback: <Spinner />,\n *   unstable_expectedLoadTime: 300, // React 19+\n * });\n * ```\n *\n * Any prop supported by `React.SuspenseProps` may be passed here.\n *\n * -------------------------------------------------------------\n * @template P - Props type of the wrapped component.\n * @template R - Ref type (only used when `Component` is forwardRef).\n *\n * @param Component - The React component to wrap with `<Suspense>`.\n * @param suspenseProps - Optional props forwarded to the `<Suspense>`\n *   wrapper (e.g. `fallback`, `unstable_expectedLoadTime`).\n *\n * @returns\n * A new component wrapped with `<Suspense>`, preserving its props\n * and (when applicable) its forwarded ref type.\n *\n * -------------------------------------------------------------\n */\nexport function WithSuspense<P>(\n  Component: ComponentType<P>,\n  suspenseProps?: Partial<SuspenseProps>\n): SuspensedExoticComponent<Exclude<P, undefined>>;\n\nexport function WithSuspense<P, R>(\n  Component: ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<R>>,\n  suspenseProps?: Partial<SuspenseProps>\n): SuspensedForwardRefExoticComponent<P, R>;\n\n// Disable lint rule for this line because:\n//\n// 1. This function implements a Higher-Order Component (HOC) that wraps\n//    a given component with React.Suspense and conditionally forwards refs.\n//\n// 2. The lint rule 'no-react19-api' is designed to forbid usage of React 19\n//    APIs to ensure React 18 compatibility.\n//\n// 3. However, here we intentionally detect at runtime whether the wrapped\n//    component supports refs (via internal $$typeof symbol for forwardRef).\n//\n// 4. The ref forwarding is implemented properly using React.forwardRef,\n//    but the lint rule might falsely flag this pattern since it inspects\n//    static declarations or certain heuristics that do not recognize\n//    this dynamic/ref-forwarding logic.\n//\n// 5. Disabling the rule here avoids false positives, while keeping\n//    the runtime behavior compatible with both React 18 and React 19.\n//\n// 6. This pattern is deliberate and safe as it maintains correct ref\n//    forwarding only when supported, preserving backward compatibility.\n\n// eslint-disable-next-line @rzl-zone/eslint/no-react19-api\nexport function WithSuspense<T>(\n  Component: React.ComponentType<T>,\n  suspenseProps?: Partial<SuspenseProps>\n) {\n  const Wrapped = forwardRef((props: any, ref) => {\n    const supportsRef =\n      \"$$typeof\" in Component &&\n      Component?.$$typeof === Symbol?.for?.(\"react.forward_ref\");\n\n    return (\n      <Suspense {...suspenseProps}>\n        {supportsRef ? (\n          <Component\n            {...props}\n            ref={ref}\n          />\n        ) : (\n          <Component {...props} />\n        )}\n      </Suspense>\n    );\n  });\n\n  Wrapped.displayName = `RzlzoneWithSuspense(${\n    Component.displayName ?? Component.name ?? \"Component\"\n  })`;\n\n  return Wrapped;\n}\n","import { type ComponentType, memo } from \"react\";\nimport { shallowCompareProps } from \"@rzl-zone/core/comparison/shallow-compare-props\";\n\n/** ------------------------------------------\n * * **Higher-Order Component (HOC): `withMemo`.**\n * ------------------------------------------\n * Enhances any React component with **automatic memoization**\n * using `React.memo`, with additional custom controls:\n *\n * - `memo?: boolean` — Disable memoization per instance\n *   (when set to `false`).\n * - `shouldCompareComplexProps?: boolean` — Enable/disable\n *   detailed shallow comparison for props.\n *\n * This HOC is useful for fine-grained re-render control while\n * keeping the wrapped component's API clean and predictable.\n *\n * @template P - Props type of the wrapped component.\n *               Must include optional `memo` and\n *               `shouldCompareComplexProps`.\n *\n * @param Component - The React component to wrap.\n *\n * @param [ignoreKeys=[\"memo\", \"shouldCompareComplexProps\"]]\n * Keys that should be excluded from shallow comparison.\n *\n * @returns The memoized version of the component, respecting the\n *          custom memoization rules.\n *\n * @example\n * interface Props {\n *   title: string;\n *   memo?: boolean;\n *   shouldCompareComplexProps?: boolean;\n * }\n *\n * function Title({ title }: Props) {\n *   return <h1>{title}</h1>;\n * }\n *\n * const MemoTitle = withMemo(Title);\n *\n * // Memoization ON (default)\n * <MemoTitle title=\"Hello\" />;\n *\n * // Disable memoization (force re-render)\n * <MemoTitle title=\"Hello\" memo={false} />;\n *\n * // Enable shallow comparison for complex props\n * <MemoTitle title=\"Hello\" shouldCompareComplexProps={true} />;\n */\nexport function withMemo<\n  P extends { memo?: boolean; shouldCompareComplexProps?: boolean }\n>(\n  Component: ComponentType<P>,\n  ignoreKeys: string[] = [\"memo\", \"shouldCompareComplexProps\"]\n) {\n  return memo(Component, (prevProps, nextProps) => {\n    if (nextProps.memo === false) return false;\n    if (!nextProps.shouldCompareComplexProps) return true;\n    return shallowCompareProps(prevProps, nextProps, ignoreKeys);\n  });\n}\n"],"mappings":";;;;;;;;;;;;;;;AAwJA,SAAgB,aACd,WACA,eACA;CACA,MAAM,iCAAsB,OAAY,QAAQ;EAC9C,MAAM,cACJ,cAAc,aACd,WAAW,aAAa,QAAQ,MAAM,mBAAmB;EAE3D,OACE,2CAACA,gBAAD;GAAU,GAAI;aACX,cACC,2CAAC,WAAD;IACE,GAAI;IACC;GACN,KAED,2CAAC,WAAD,EAAW,GAAI,MAAQ;EAEjB;CAEd,CAAC;CAED,QAAQ,cAAc,uBACpB,UAAU,eAAe,UAAU,QAAQ,YAC5C;CAED,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjIA,SAAgB,SAGd,WACA,aAAuB,CAAC,QAAQ,2BAA2B,GAC3D;CACA,uBAAY,YAAY,WAAW,cAAc;EAC/C,IAAI,UAAU,SAAS,OAAO,OAAO;EACrC,IAAI,CAAC,UAAU,2BAA2B,OAAO;EACjD,gFAA2B,WAAW,WAAW,UAAU;CAC7D,CAAC;AACH"}
