@rzl-zone/core-react
Advanced tools
| /*! | ||
| * ======================================================================== | ||
| * @rzl-zone/core-react | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
| * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| * ======================================================================== | ||
| */ | ||
| "use strict"; | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) { | ||
| __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| Object.defineProperty(exports, '__toESM', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __toESM; | ||
| } | ||
| }); |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -14,3 +14,3 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_chunk = require('../chunk-DZH3KJL-.cjs'); | ||
| const require_chunk = require('../chunk-Bfh80tNm.cjs'); | ||
| let _rzl_zone_utils_js_predicates = require("@rzl-zone/utils-js/predicates"); | ||
@@ -17,0 +17,0 @@ let react = require("react"); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"required-context.cjs","names":["React"],"sources":["../../src/context/required-context.tsx"],"sourcesContent":["\"use client\";\n\nimport { isNonEmptyString } from \"@rzl-zone/utils-js/predicates\";\nimport React, { createContext, useContext, type ReactNode } from \"react\";\n\ntype UnwrapPromise<T> = ContextValue<T extends Promise<infer U> ? U : T>;\ntype ContextValue<T> = T extends undefined ? never : T;\n\ntype RequiredContextProviderProps<T> = {\n readonly value: T;\n readonly children: ReactNode;\n};\n\ntype RequiredContextProvider<T> = {\n (props: RequiredContextProviderProps<T>): ReactNode;\n displayName?: string;\n};\n\ntype RequiredContextReturn<T> = {\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n *\n * ⚠️ **Advanced usage only**\n *\n * - ***This context is exposed for:***\n * - Integration with third-party libraries.\n * - Adapter layers.\n * - Testing or devtools.\n *\n * - ***Important notes:***\n * - The value type is `T | undefined`.\n * - `undefined` is reserved internally to detect missing Providers.\n * - Consumers SHOULD prefer `use()` or `useSuspense()` instead of\n * calling `useContext(Context)` directly.\n *\n * @example\n * **1. Adapter / integration layer.**\n * ```tsx\n * // Example: integrating with a third-party hook\n * // that requires a raw React Context instance.\n *\n * import { useContext } from \"react\";\n *\n * type AuthState = { user: { name: string, email: string } };\n *\n * function useAuthFromAdapter(AuthContext: {\n * Context: React.Context<AuthState | undefined>;\n * }) {\n * const value = useContext(AuthContext.Context);\n *\n * // Adapter is responsible for handling `undefined`\n * if (value === undefined) {\n * throw new Error(\"AuthContext.Provider is missing\");\n * }\n *\n * return value;\n * }\n * ```\n *\n * @example\n * **2. Testing or devtools.**\n * ```tsx\n * import { render } from \"@testing-library/react\";\n *\n * render(\n * <AuthContext.Context.Provider value={{ user: { name: \"Rzl\" } }}>\n * <ComponentUnderTest />\n * </AuthContext.Context.Provider>\n * );\n * ```\n */\n Context: React.Context<T | undefined>;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n *\n * Provides the context value to the component subtree.\n *\n * - ⚠️ ***Important:***\n * - `undefined` is **reserved internally** to detect missing Providers.\n * - Do **NOT** pass `undefined` as a valid value.\n * - If you need to represent an “empty” or “not yet available” state,\n * use `null` instead and handle it explicitly in consumers.\n *\n * @example\n * ```tsx\n * type AuthState = { user: { name: string } } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n */\n Provider: RequiredContextProvider<T>;\n\n /** ------------------------------------------------------------------------\n * * ***Classic context consumer (non-Suspense).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value synchronously using `useContext`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`** (used internally to detect missing Provider).\n * - `null` is treated as a valid value and is **not** filtered.\n * - Never suspends.\n * - Does NOT require `<Suspense>`.\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n *\n * @throws {Error} Thrown when used outside its corresponding Provider.\n *\n * @returns The context value of type `T`.\n *\n * @example\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n */\n use(missingProviderMessage?: string): ContextValue<T>;\n\n /** ------------------------------------------------------------------------\n * * ***React 19 `use()`-powered context consumer (Promise-aware).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value using React 19 `use(Context)`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`**.\n * - If the value is a Promise, rendering suspends until it resolves.\n * - If the value is synchronous, behaves like `useContext`.\n *\n * - ***⚠️ When the value is a Promise:***\n * - A `<Suspense>` boundary is ***REQUIRED***.\n * - The Promise must come from a Suspense-compatible source\n * (*not created during render*).\n *\n * ---\n *\n * ⚠️ This hook **requires** ***React 19*** or ***newer***, If used in an older React version, it will throw an error.\n *\n * ---\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n * @param unsupportedReactErrorMessage - Optional custom error message when `use()` is not supported (React < 19).\n *\n * @throws {Error}\n * Thrown when:\n * - Used outside its corresponding Provider.\n * - React version is older than 19 and does not support `use`.\n *\n * @returns The resolved context value.\n *\n * @example\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\n useSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T>;\n};\n\n/** --------------------------------------------------------------------------\n * * ***Create a React Context with a required Provider.***\n * --------------------------------------------------------------------------\n *\n * - ***This utility enforces that:***\n * - The context **must** be wrapped with its Provider.\n * - Using the context without a Provider throws a clear runtime error.\n *\n * - ⚠️ ***Important behavior:***\n * - Only **`undefined`** is treated as an invalid value.\n * - Passing `undefined` (explicitly or implicitly) will cause the consumer\n * to throw a runtime error.\n * - **`null` is allowed** and will be returned as-is.\n *\n * ---\n *\n * ℹ️ If you need an “empty” or “initial” state, prefer `null` instead of `undefined`.\n *\n * ---\n *\n * - ***Supports two consumption modes:***\n * - `use()` ➔ classic `useContext` (non-suspending, filters `undefined`).\n * - `useSuspense()` ➔ React 19 `use()` (Promise-aware, filters `undefined`).\n *\n * - ***Designed for:***\n * - Application-level state.\n * - Shared library contexts.\n * - Fail-fast enforcement of required Providers.\n *\n * @template T - The context value type, `undefined` is reserved internally to detect missing Providers.\n *\n * @param name - Human-readable context name (used in error messages and React DevTools).\n *\n * @returns An object containing:\n * - `Context` — the raw React Context instance (advanced usage).\n * - `Provider` — the required Provider component.\n * - `use` — classic context consumer hook, throws if Provider is missing.\n * - `useSuspense` — React 19+ Suspense-aware consumer hook, throws if Provider is missing or React version is too old.\n *\n * @example\n * **1. Context with a default value.**\n * ```tsx\n * type AuthState = {\n * user: {\n * name: string\n * }\n * } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n *\n * @example\n * **2. Context without a default value (Provider required).**\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n *\n * @example\n * **3. Async (Promise) context with Suspense.**\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\nexport function createRequiredContext<T>(\n name: string,\n defaultValue: T\n): RequiredContextReturn<T>;\nexport function createRequiredContext<T>(\n name: string\n): RequiredContextReturn<T | undefined>;\nexport function createRequiredContext<T>(\n name: string,\n defaultValue?: T\n): RequiredContextReturn<T | undefined> {\n if (!isNonEmptyString(name)) {\n throw new Error(\n \"Invalid `context` name passed to `createRequiredContext`: expected a non-empty string.\"\n );\n }\n\n name = name.trim();\n\n const { contextDisplayName, providerDisplayName } =\n normalizeContextNames(name);\n\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n */\n const Context = createContext<T | undefined>(defaultValue);\n Context.displayName = contextDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n */\n function Provider(props: RequiredContextProviderProps<T | undefined>) {\n return (\n <Context.Provider value={props.value}>{props.children}</Context.Provider>\n );\n }\n\n Provider.displayName = providerDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Hook to consume the context value safely.***\n * ------------------------------------------------------------------------\n */\n function useRequiredContext(\n missingProviderMessage?: string\n ): ContextValue<T> {\n const value = useContext(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as ContextValue<T>;\n }\n\n /** ------------------------------------------------------------------------\n * * ***Suspense consumer (React 19).***\n * ----------------------------------------------------------------------\n */\n function useRequiredContextSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T> {\n //\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n if (typeof React?.use !== \"function\" || !(\"use\" in React)) {\n throw new Error(\n unsupportedReactErrorMessage ??\n \"This feature requires `React 19` or `newer`, please upgrade your React version to use Suspense-enabled context.\"\n );\n }\n\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n const value = React.use(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as UnwrapPromise<T>;\n }\n\n return {\n Context,\n Provider,\n use: useRequiredContext,\n useSuspense: useRequiredContextSuspense\n };\n}\n\nfunction normalizeContextNames(name: string) {\n const trimmed = name.trim();\n\n const baseName = /context$/i.test(trimmed)\n ? trimmed.replace(/context$/i, \"\")\n : trimmed;\n\n const contextDisplayName = `${baseName}Context`;\n const providerDisplayName = `${baseName}Provider`;\n\n return {\n baseName,\n contextDisplayName,\n providerDisplayName\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmVA,SAAgB,sBACd,MACA,cACsC;CACtC,IAAI,qDAAkB,KAAK,EACzB,MAAM,IAAI,MACR,yFACD;CAGH,OAAO,KAAK,MAAM;CAElB,MAAM,EAAE,oBAAoB,wBAC1B,sBAAsB,KAAK;;;;;CAM7B,MAAM,mCAAuC,aAAa;CAC1D,QAAQ,cAAc;;;;;CAMtB,SAAS,SAAS,OAAoD;EACpE,OACE,CAAC,QAAQ,SAAS,OAAO,MAAM,QAAQ,MAAM,SAAS,EAAE,QAAQ;;CAIpE,SAAS,cAAc;;;;;CAMvB,SAAS,mBACP,wBACiB;EACjB,MAAM,8BAAmB,QAAQ;EAEjC,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,2BACnD;EAGH,OAAO;;;;;;CAOT,SAAS,2BACP,wBACA,8BACkB;EAGlB,IAAI,OAAOA,eAAO,QAAQ,cAAc,EAAE,SAASA,gBACjD,MAAM,IAAI,MACR,gCACE,kHACH;EAIH,MAAM,QAAQA,cAAM,IAAI,QAAQ;EAEhC,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,2BACnD;EAGH,OAAO;;CAGT,OAAO;EACL;EACA;EACA,KAAK;EACL,aAAa;EACd;;AAGH,SAAS,sBAAsB,MAAc;CAC3C,MAAM,UAAU,KAAK,MAAM;CAE3B,MAAM,WAAW,YAAY,KAAK,QAAQ,GACtC,QAAQ,QAAQ,aAAa,GAAG,GAChC;CAKJ,OAAO;EACL;EACA,uBAL4B,SAAS;EAMrC,wBAL6B,SAAS;EAMvC"} | ||
| {"version":3,"file":"required-context.cjs","names":["React"],"sources":["../../src/context/required-context.tsx"],"sourcesContent":["\"use client\";\n\nimport { isNonEmptyString } from \"@rzl-zone/utils-js/predicates\";\nimport React, { createContext, useContext, type ReactNode } from \"react\";\n\ntype UnwrapPromise<T> = ContextValue<T extends Promise<infer U> ? U : T>;\ntype ContextValue<T> = T extends undefined ? never : T;\n\ntype RequiredContextProviderProps<T> = {\n readonly value: T;\n readonly children: ReactNode;\n};\n\ntype RequiredContextProvider<T> = {\n (props: RequiredContextProviderProps<T>): ReactNode;\n displayName?: string;\n};\n\ntype RequiredContextReturn<T> = {\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n *\n * ⚠️ **Advanced usage only**\n *\n * - ***This context is exposed for:***\n * - Integration with third-party libraries.\n * - Adapter layers.\n * - Testing or devtools.\n *\n * - ***Important notes:***\n * - The value type is `T | undefined`.\n * - `undefined` is reserved internally to detect missing Providers.\n * - Consumers SHOULD prefer `use()` or `useSuspense()` instead of\n * calling `useContext(Context)` directly.\n *\n * @example\n * **1. Adapter / integration layer.**\n * ```tsx\n * // Example: integrating with a third-party hook\n * // that requires a raw React Context instance.\n *\n * import { useContext } from \"react\";\n *\n * type AuthState = { user: { name: string, email: string } };\n *\n * function useAuthFromAdapter(AuthContext: {\n * Context: React.Context<AuthState | undefined>;\n * }) {\n * const value = useContext(AuthContext.Context);\n *\n * // Adapter is responsible for handling `undefined`\n * if (value === undefined) {\n * throw new Error(\"AuthContext.Provider is missing\");\n * }\n *\n * return value;\n * }\n * ```\n *\n * @example\n * **2. Testing or devtools.**\n * ```tsx\n * import { render } from \"@testing-library/react\";\n *\n * render(\n * <AuthContext.Context.Provider value={{ user: { name: \"Rzl\" } }}>\n * <ComponentUnderTest />\n * </AuthContext.Context.Provider>\n * );\n * ```\n */\n Context: React.Context<T | undefined>;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n *\n * Provides the context value to the component subtree.\n *\n * - ⚠️ ***Important:***\n * - `undefined` is **reserved internally** to detect missing Providers.\n * - Do **NOT** pass `undefined` as a valid value.\n * - If you need to represent an “empty” or “not yet available” state,\n * use `null` instead and handle it explicitly in consumers.\n *\n * @example\n * ```tsx\n * type AuthState = { user: { name: string } } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n */\n Provider: RequiredContextProvider<T>;\n\n /** ------------------------------------------------------------------------\n * * ***Classic context consumer (non-Suspense).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value synchronously using `useContext`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`** (used internally to detect missing Provider).\n * - `null` is treated as a valid value and is **not** filtered.\n * - Never suspends.\n * - Does NOT require `<Suspense>`.\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n *\n * @throws {Error} Thrown when used outside its corresponding Provider.\n *\n * @returns The context value of type `T`.\n *\n * @example\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n */\n use(missingProviderMessage?: string): ContextValue<T>;\n\n /** ------------------------------------------------------------------------\n * * ***React 19 `use()`-powered context consumer (Promise-aware).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value using React 19 `use(Context)`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`**.\n * - If the value is a Promise, rendering suspends until it resolves.\n * - If the value is synchronous, behaves like `useContext`.\n *\n * - ***⚠️ When the value is a Promise:***\n * - A `<Suspense>` boundary is ***REQUIRED***.\n * - The Promise must come from a Suspense-compatible source\n * (*not created during render*).\n *\n * ---\n *\n * ⚠️ This hook **requires** ***React 19*** or ***newer***, If used in an older React version, it will throw an error.\n *\n * ---\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n * @param unsupportedReactErrorMessage - Optional custom error message when `use()` is not supported (React < 19).\n *\n * @throws {Error}\n * Thrown when:\n * - Used outside its corresponding Provider.\n * - React version is older than 19 and does not support `use`.\n *\n * @returns The resolved context value.\n *\n * @example\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\n useSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T>;\n};\n\n/** --------------------------------------------------------------------------\n * * ***Create a React Context with a required Provider.***\n * --------------------------------------------------------------------------\n *\n * - ***This utility enforces that:***\n * - The context **must** be wrapped with its Provider.\n * - Using the context without a Provider throws a clear runtime error.\n *\n * - ⚠️ ***Important behavior:***\n * - Only **`undefined`** is treated as an invalid value.\n * - Passing `undefined` (explicitly or implicitly) will cause the consumer\n * to throw a runtime error.\n * - **`null` is allowed** and will be returned as-is.\n *\n * ---\n *\n * ℹ️ If you need an “empty” or “initial” state, prefer `null` instead of `undefined`.\n *\n * ---\n *\n * - ***Supports two consumption modes:***\n * - `use()` ➔ classic `useContext` (non-suspending, filters `undefined`).\n * - `useSuspense()` ➔ React 19 `use()` (Promise-aware, filters `undefined`).\n *\n * - ***Designed for:***\n * - Application-level state.\n * - Shared library contexts.\n * - Fail-fast enforcement of required Providers.\n *\n * @template T - The context value type, `undefined` is reserved internally to detect missing Providers.\n *\n * @param name - Human-readable context name (used in error messages and React DevTools).\n *\n * @returns An object containing:\n * - `Context` — the raw React Context instance (advanced usage).\n * - `Provider` — the required Provider component.\n * - `use` — classic context consumer hook, throws if Provider is missing.\n * - `useSuspense` — React 19+ Suspense-aware consumer hook, throws if Provider is missing or React version is too old.\n *\n * @example\n * **1. Context with a default value.**\n * ```tsx\n * type AuthState = {\n * user: {\n * name: string\n * }\n * } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n *\n * @example\n * **2. Context without a default value (Provider required).**\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n *\n * @example\n * **3. Async (Promise) context with Suspense.**\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\nexport function createRequiredContext<T>(\n name: string,\n defaultValue: T\n): RequiredContextReturn<T>;\nexport function createRequiredContext<T>(\n name: string\n): RequiredContextReturn<T | undefined>;\nexport function createRequiredContext<T>(\n name: string,\n defaultValue?: T\n): RequiredContextReturn<T | undefined> {\n if (!isNonEmptyString(name)) {\n throw new Error(\n \"Invalid `context` name passed to `createRequiredContext`: expected a non-empty string.\"\n );\n }\n\n name = name.trim();\n\n const { contextDisplayName, providerDisplayName } =\n normalizeContextNames(name);\n\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n */\n const Context = createContext<T | undefined>(defaultValue);\n Context.displayName = contextDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n */\n function Provider(props: RequiredContextProviderProps<T | undefined>) {\n return (\n <Context.Provider value={props.value}>{props.children}</Context.Provider>\n );\n }\n\n Provider.displayName = providerDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Hook to consume the context value safely.***\n * ------------------------------------------------------------------------\n */\n function useRequiredContext(\n missingProviderMessage?: string\n ): ContextValue<T> {\n const value = useContext(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as ContextValue<T>;\n }\n\n /** ------------------------------------------------------------------------\n * * ***Suspense consumer (React 19).***\n * ----------------------------------------------------------------------\n */\n function useRequiredContextSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T> {\n //\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n if (typeof React?.use !== \"function\" || !(\"use\" in React)) {\n throw new Error(\n unsupportedReactErrorMessage ??\n \"This feature requires `React 19` or `newer`, please upgrade your React version to use Suspense-enabled context.\"\n );\n }\n\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n const value = React.use(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as UnwrapPromise<T>;\n }\n\n return {\n Context,\n Provider,\n use: useRequiredContext,\n useSuspense: useRequiredContextSuspense\n };\n}\n\nfunction normalizeContextNames(name: string) {\n const trimmed = name.trim();\n\n const baseName = /context$/i.test(trimmed)\n ? trimmed.replace(/context$/i, \"\")\n : trimmed;\n\n const contextDisplayName = `${baseName}Context`;\n const providerDisplayName = `${baseName}Provider`;\n\n return {\n baseName,\n contextDisplayName,\n providerDisplayName\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmVA,SAAgB,sBACd,MACA,cACsC;CACtC,IAAI,qDAAkB,IAAI,GACxB,MAAM,IAAI,MACR,wFACF;CAGF,OAAO,KAAK,KAAK;CAEjB,MAAM,EAAE,oBAAoB,wBAC1B,sBAAsB,IAAI;;;;;CAM5B,MAAM,mCAAuC,YAAY;CACzD,QAAQ,cAAc;;;;;CAMtB,SAAS,SAAS,OAAoD;EACpE,OACE,CAAC,QAAQ,SAAS,OAAO,MAAM,QAAQ,MAAM,SAAS,EAAE,QAAQ;CAEpE;CAEA,SAAS,cAAc;;;;;CAMvB,SAAS,mBACP,wBACiB;EACjB,MAAM,8BAAmB,OAAO;EAEhC,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,0BACpD;EAGF,OAAO;CACT;;;;;CAMA,SAAS,2BACP,wBACA,8BACkB;EAGlB,IAAI,OAAOA,eAAO,QAAQ,cAAc,EAAE,SAASA,gBACjD,MAAM,IAAI,MACR,gCACE,iHACJ;EAIF,MAAM,QAAQA,cAAM,IAAI,OAAO;EAE/B,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,0BACpD;EAGF,OAAO;CACT;CAEA,OAAO;EACL;EACA;EACA,KAAK;EACL,aAAa;CACf;AACF;AAEA,SAAS,sBAAsB,MAAc;CAC3C,MAAM,UAAU,KAAK,KAAK;CAE1B,MAAM,WAAW,YAAY,KAAK,OAAO,IACrC,QAAQ,QAAQ,aAAa,EAAE,IAC/B;CAKJ,OAAO;EACL;EACA,uBAL4B,SAAS;EAMrC,wBAL6B,SAAS;CAMxC;AACF"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"required-context.js","names":[],"sources":["../../src/context/required-context.tsx"],"sourcesContent":["\"use client\";\n\nimport { isNonEmptyString } from \"@rzl-zone/utils-js/predicates\";\nimport React, { createContext, useContext, type ReactNode } from \"react\";\n\ntype UnwrapPromise<T> = ContextValue<T extends Promise<infer U> ? U : T>;\ntype ContextValue<T> = T extends undefined ? never : T;\n\ntype RequiredContextProviderProps<T> = {\n readonly value: T;\n readonly children: ReactNode;\n};\n\ntype RequiredContextProvider<T> = {\n (props: RequiredContextProviderProps<T>): ReactNode;\n displayName?: string;\n};\n\ntype RequiredContextReturn<T> = {\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n *\n * ⚠️ **Advanced usage only**\n *\n * - ***This context is exposed for:***\n * - Integration with third-party libraries.\n * - Adapter layers.\n * - Testing or devtools.\n *\n * - ***Important notes:***\n * - The value type is `T | undefined`.\n * - `undefined` is reserved internally to detect missing Providers.\n * - Consumers SHOULD prefer `use()` or `useSuspense()` instead of\n * calling `useContext(Context)` directly.\n *\n * @example\n * **1. Adapter / integration layer.**\n * ```tsx\n * // Example: integrating with a third-party hook\n * // that requires a raw React Context instance.\n *\n * import { useContext } from \"react\";\n *\n * type AuthState = { user: { name: string, email: string } };\n *\n * function useAuthFromAdapter(AuthContext: {\n * Context: React.Context<AuthState | undefined>;\n * }) {\n * const value = useContext(AuthContext.Context);\n *\n * // Adapter is responsible for handling `undefined`\n * if (value === undefined) {\n * throw new Error(\"AuthContext.Provider is missing\");\n * }\n *\n * return value;\n * }\n * ```\n *\n * @example\n * **2. Testing or devtools.**\n * ```tsx\n * import { render } from \"@testing-library/react\";\n *\n * render(\n * <AuthContext.Context.Provider value={{ user: { name: \"Rzl\" } }}>\n * <ComponentUnderTest />\n * </AuthContext.Context.Provider>\n * );\n * ```\n */\n Context: React.Context<T | undefined>;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n *\n * Provides the context value to the component subtree.\n *\n * - ⚠️ ***Important:***\n * - `undefined` is **reserved internally** to detect missing Providers.\n * - Do **NOT** pass `undefined` as a valid value.\n * - If you need to represent an “empty” or “not yet available” state,\n * use `null` instead and handle it explicitly in consumers.\n *\n * @example\n * ```tsx\n * type AuthState = { user: { name: string } } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n */\n Provider: RequiredContextProvider<T>;\n\n /** ------------------------------------------------------------------------\n * * ***Classic context consumer (non-Suspense).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value synchronously using `useContext`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`** (used internally to detect missing Provider).\n * - `null` is treated as a valid value and is **not** filtered.\n * - Never suspends.\n * - Does NOT require `<Suspense>`.\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n *\n * @throws {Error} Thrown when used outside its corresponding Provider.\n *\n * @returns The context value of type `T`.\n *\n * @example\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n */\n use(missingProviderMessage?: string): ContextValue<T>;\n\n /** ------------------------------------------------------------------------\n * * ***React 19 `use()`-powered context consumer (Promise-aware).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value using React 19 `use(Context)`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`**.\n * - If the value is a Promise, rendering suspends until it resolves.\n * - If the value is synchronous, behaves like `useContext`.\n *\n * - ***⚠️ When the value is a Promise:***\n * - A `<Suspense>` boundary is ***REQUIRED***.\n * - The Promise must come from a Suspense-compatible source\n * (*not created during render*).\n *\n * ---\n *\n * ⚠️ This hook **requires** ***React 19*** or ***newer***, If used in an older React version, it will throw an error.\n *\n * ---\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n * @param unsupportedReactErrorMessage - Optional custom error message when `use()` is not supported (React < 19).\n *\n * @throws {Error}\n * Thrown when:\n * - Used outside its corresponding Provider.\n * - React version is older than 19 and does not support `use`.\n *\n * @returns The resolved context value.\n *\n * @example\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\n useSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T>;\n};\n\n/** --------------------------------------------------------------------------\n * * ***Create a React Context with a required Provider.***\n * --------------------------------------------------------------------------\n *\n * - ***This utility enforces that:***\n * - The context **must** be wrapped with its Provider.\n * - Using the context without a Provider throws a clear runtime error.\n *\n * - ⚠️ ***Important behavior:***\n * - Only **`undefined`** is treated as an invalid value.\n * - Passing `undefined` (explicitly or implicitly) will cause the consumer\n * to throw a runtime error.\n * - **`null` is allowed** and will be returned as-is.\n *\n * ---\n *\n * ℹ️ If you need an “empty” or “initial” state, prefer `null` instead of `undefined`.\n *\n * ---\n *\n * - ***Supports two consumption modes:***\n * - `use()` ➔ classic `useContext` (non-suspending, filters `undefined`).\n * - `useSuspense()` ➔ React 19 `use()` (Promise-aware, filters `undefined`).\n *\n * - ***Designed for:***\n * - Application-level state.\n * - Shared library contexts.\n * - Fail-fast enforcement of required Providers.\n *\n * @template T - The context value type, `undefined` is reserved internally to detect missing Providers.\n *\n * @param name - Human-readable context name (used in error messages and React DevTools).\n *\n * @returns An object containing:\n * - `Context` — the raw React Context instance (advanced usage).\n * - `Provider` — the required Provider component.\n * - `use` — classic context consumer hook, throws if Provider is missing.\n * - `useSuspense` — React 19+ Suspense-aware consumer hook, throws if Provider is missing or React version is too old.\n *\n * @example\n * **1. Context with a default value.**\n * ```tsx\n * type AuthState = {\n * user: {\n * name: string\n * }\n * } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n *\n * @example\n * **2. Context without a default value (Provider required).**\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n *\n * @example\n * **3. Async (Promise) context with Suspense.**\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\nexport function createRequiredContext<T>(\n name: string,\n defaultValue: T\n): RequiredContextReturn<T>;\nexport function createRequiredContext<T>(\n name: string\n): RequiredContextReturn<T | undefined>;\nexport function createRequiredContext<T>(\n name: string,\n defaultValue?: T\n): RequiredContextReturn<T | undefined> {\n if (!isNonEmptyString(name)) {\n throw new Error(\n \"Invalid `context` name passed to `createRequiredContext`: expected a non-empty string.\"\n );\n }\n\n name = name.trim();\n\n const { contextDisplayName, providerDisplayName } =\n normalizeContextNames(name);\n\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n */\n const Context = createContext<T | undefined>(defaultValue);\n Context.displayName = contextDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n */\n function Provider(props: RequiredContextProviderProps<T | undefined>) {\n return (\n <Context.Provider value={props.value}>{props.children}</Context.Provider>\n );\n }\n\n Provider.displayName = providerDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Hook to consume the context value safely.***\n * ------------------------------------------------------------------------\n */\n function useRequiredContext(\n missingProviderMessage?: string\n ): ContextValue<T> {\n const value = useContext(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as ContextValue<T>;\n }\n\n /** ------------------------------------------------------------------------\n * * ***Suspense consumer (React 19).***\n * ----------------------------------------------------------------------\n */\n function useRequiredContextSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T> {\n //\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n if (typeof React?.use !== \"function\" || !(\"use\" in React)) {\n throw new Error(\n unsupportedReactErrorMessage ??\n \"This feature requires `React 19` or `newer`, please upgrade your React version to use Suspense-enabled context.\"\n );\n }\n\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n const value = React.use(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as UnwrapPromise<T>;\n }\n\n return {\n Context,\n Provider,\n use: useRequiredContext,\n useSuspense: useRequiredContextSuspense\n };\n}\n\nfunction normalizeContextNames(name: string) {\n const trimmed = name.trim();\n\n const baseName = /context$/i.test(trimmed)\n ? trimmed.replace(/context$/i, \"\")\n : trimmed;\n\n const contextDisplayName = `${baseName}Context`;\n const providerDisplayName = `${baseName}Provider`;\n\n return {\n baseName,\n contextDisplayName,\n providerDisplayName\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmVA,SAAgB,sBACd,MACA,cACsC;CACtC,IAAI,CAAC,iBAAiB,KAAK,EACzB,MAAM,IAAI,MACR,yFACD;CAGH,OAAO,KAAK,MAAM;CAElB,MAAM,EAAE,oBAAoB,wBAC1B,sBAAsB,KAAK;;;;;CAM7B,MAAM,UAAU,cAA6B,aAAa;CAC1D,QAAQ,cAAc;;;;;CAMtB,SAAS,SAAS,OAAoD;EACpE,OACE,CAAC,QAAQ,SAAS,OAAO,MAAM,QAAQ,MAAM,SAAS,EAAE,QAAQ;;CAIpE,SAAS,cAAc;;;;;CAMvB,SAAS,mBACP,wBACiB;EACjB,MAAM,QAAQ,WAAW,QAAQ;EAEjC,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,2BACnD;EAGH,OAAO;;;;;;CAOT,SAAS,2BACP,wBACA,8BACkB;EAGlB,IAAI,OAAO,OAAO,QAAQ,cAAc,EAAE,SAAS,QACjD,MAAM,IAAI,MACR,gCACE,kHACH;EAIH,MAAM,QAAQ,MAAM,IAAI,QAAQ;EAEhC,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,2BACnD;EAGH,OAAO;;CAGT,OAAO;EACL;EACA;EACA,KAAK;EACL,aAAa;EACd;;AAGH,SAAS,sBAAsB,MAAc;CAC3C,MAAM,UAAU,KAAK,MAAM;CAE3B,MAAM,WAAW,YAAY,KAAK,QAAQ,GACtC,QAAQ,QAAQ,aAAa,GAAG,GAChC;CAKJ,OAAO;EACL;EACA,uBAL4B,SAAS;EAMrC,wBAL6B,SAAS;EAMvC"} | ||
| {"version":3,"file":"required-context.js","names":[],"sources":["../../src/context/required-context.tsx"],"sourcesContent":["\"use client\";\n\nimport { isNonEmptyString } from \"@rzl-zone/utils-js/predicates\";\nimport React, { createContext, useContext, type ReactNode } from \"react\";\n\ntype UnwrapPromise<T> = ContextValue<T extends Promise<infer U> ? U : T>;\ntype ContextValue<T> = T extends undefined ? never : T;\n\ntype RequiredContextProviderProps<T> = {\n readonly value: T;\n readonly children: ReactNode;\n};\n\ntype RequiredContextProvider<T> = {\n (props: RequiredContextProviderProps<T>): ReactNode;\n displayName?: string;\n};\n\ntype RequiredContextReturn<T> = {\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n *\n * ⚠️ **Advanced usage only**\n *\n * - ***This context is exposed for:***\n * - Integration with third-party libraries.\n * - Adapter layers.\n * - Testing or devtools.\n *\n * - ***Important notes:***\n * - The value type is `T | undefined`.\n * - `undefined` is reserved internally to detect missing Providers.\n * - Consumers SHOULD prefer `use()` or `useSuspense()` instead of\n * calling `useContext(Context)` directly.\n *\n * @example\n * **1. Adapter / integration layer.**\n * ```tsx\n * // Example: integrating with a third-party hook\n * // that requires a raw React Context instance.\n *\n * import { useContext } from \"react\";\n *\n * type AuthState = { user: { name: string, email: string } };\n *\n * function useAuthFromAdapter(AuthContext: {\n * Context: React.Context<AuthState | undefined>;\n * }) {\n * const value = useContext(AuthContext.Context);\n *\n * // Adapter is responsible for handling `undefined`\n * if (value === undefined) {\n * throw new Error(\"AuthContext.Provider is missing\");\n * }\n *\n * return value;\n * }\n * ```\n *\n * @example\n * **2. Testing or devtools.**\n * ```tsx\n * import { render } from \"@testing-library/react\";\n *\n * render(\n * <AuthContext.Context.Provider value={{ user: { name: \"Rzl\" } }}>\n * <ComponentUnderTest />\n * </AuthContext.Context.Provider>\n * );\n * ```\n */\n Context: React.Context<T | undefined>;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n *\n * Provides the context value to the component subtree.\n *\n * - ⚠️ ***Important:***\n * - `undefined` is **reserved internally** to detect missing Providers.\n * - Do **NOT** pass `undefined` as a valid value.\n * - If you need to represent an “empty” or “not yet available” state,\n * use `null` instead and handle it explicitly in consumers.\n *\n * @example\n * ```tsx\n * type AuthState = { user: { name: string } } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n */\n Provider: RequiredContextProvider<T>;\n\n /** ------------------------------------------------------------------------\n * * ***Classic context consumer (non-Suspense).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value synchronously using `useContext`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`** (used internally to detect missing Provider).\n * - `null` is treated as a valid value and is **not** filtered.\n * - Never suspends.\n * - Does NOT require `<Suspense>`.\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n *\n * @throws {Error} Thrown when used outside its corresponding Provider.\n *\n * @returns The context value of type `T`.\n *\n * @example\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n */\n use(missingProviderMessage?: string): ContextValue<T>;\n\n /** ------------------------------------------------------------------------\n * * ***React 19 `use()`-powered context consumer (Promise-aware).***\n * ------------------------------------------------------------------------\n *\n * Reads the context value using React 19 `use(Context)`.\n *\n * - ***Behavior:***\n * - Throws if the Provider is missing.\n * - Filters **only `undefined`**.\n * - If the value is a Promise, rendering suspends until it resolves.\n * - If the value is synchronous, behaves like `useContext`.\n *\n * - ***⚠️ When the value is a Promise:***\n * - A `<Suspense>` boundary is ***REQUIRED***.\n * - The Promise must come from a Suspense-compatible source\n * (*not created during render*).\n *\n * ---\n *\n * ⚠️ This hook **requires** ***React 19*** or ***newer***, If used in an older React version, it will throw an error.\n *\n * ---\n *\n * @param missingProviderMessage - Optional custom error message when used outside its Provider.\n * @param unsupportedReactErrorMessage - Optional custom error message when `use()` is not supported (React < 19).\n *\n * @throws {Error}\n * Thrown when:\n * - Used outside its corresponding Provider.\n * - React version is older than 19 and does not support `use`.\n *\n * @returns The resolved context value.\n *\n * @example\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\n useSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T>;\n};\n\n/** --------------------------------------------------------------------------\n * * ***Create a React Context with a required Provider.***\n * --------------------------------------------------------------------------\n *\n * - ***This utility enforces that:***\n * - The context **must** be wrapped with its Provider.\n * - Using the context without a Provider throws a clear runtime error.\n *\n * - ⚠️ ***Important behavior:***\n * - Only **`undefined`** is treated as an invalid value.\n * - Passing `undefined` (explicitly or implicitly) will cause the consumer\n * to throw a runtime error.\n * - **`null` is allowed** and will be returned as-is.\n *\n * ---\n *\n * ℹ️ If you need an “empty” or “initial” state, prefer `null` instead of `undefined`.\n *\n * ---\n *\n * - ***Supports two consumption modes:***\n * - `use()` ➔ classic `useContext` (non-suspending, filters `undefined`).\n * - `useSuspense()` ➔ React 19 `use()` (Promise-aware, filters `undefined`).\n *\n * - ***Designed for:***\n * - Application-level state.\n * - Shared library contexts.\n * - Fail-fast enforcement of required Providers.\n *\n * @template T - The context value type, `undefined` is reserved internally to detect missing Providers.\n *\n * @param name - Human-readable context name (used in error messages and React DevTools).\n *\n * @returns An object containing:\n * - `Context` — the raw React Context instance (advanced usage).\n * - `Provider` — the required Provider component.\n * - `use` — classic context consumer hook, throws if Provider is missing.\n * - `useSuspense` — React 19+ Suspense-aware consumer hook, throws if Provider is missing or React version is too old.\n *\n * @example\n * **1. Context with a default value.**\n * ```tsx\n * type AuthState = {\n * user: {\n * name: string\n * }\n * } | null;\n *\n * const AuthContext =\n * createRequiredContext<AuthState>(\"AuthContext\", null);\n *\n * function App() {\n * return (\n * <AuthContext.Provider value={{ user: { name: \"Rzl\" } }}>\n * <UserComponent />\n * </AuthContext.Provider>\n * );\n * }\n *\n * function UserComponent() {\n * const userContext = AuthContext.use();\n *\n * if (userContext === null) throw new Error(\"UserContext is null\");\n *\n * return <div>{userContext.user.name}</div>;\n * }\n * ```\n *\n * @example\n * **2. Context without a default value (Provider required).**\n * ```tsx\n * type Theme = { theme: \"light\" | \"dark\" };\n *\n * const ThemeContext = createRequiredContext<Theme>(\"ThemeContext\");\n *\n * function App() {\n * return (\n * <ThemeContext.Provider value={{ theme: \"dark\" }}>\n * <ThemeToggle />\n * </ThemeContext.Provider>\n * );\n * }\n *\n * function ThemeToggle() {\n * const { theme } = ThemeContext.use();\n * return <button data-theme={theme} />;\n * }\n * ```\n *\n * @example\n * **3. Async (Promise) context with Suspense.**\n * ```tsx\n * type User = { name: string };\n *\n * const userPromise: Promise<User> = fetch(\"/api/user\").then(r => r.json());\n *\n * const UserContext =\n * createRequiredContext<Promise<User>>(\"UserContext\");\n *\n * function App() {\n * return (\n * <UserContext.Provider value={userPromise}>\n * <Suspense fallback=\"Loading...\">\n * <Profile />\n * </Suspense>\n * </UserContext.Provider>\n * );\n * }\n *\n * function Profile() {\n * const user = UserContext.useSuspense();\n * return <div>{user.name}</div>;\n * }\n * ```\n */\nexport function createRequiredContext<T>(\n name: string,\n defaultValue: T\n): RequiredContextReturn<T>;\nexport function createRequiredContext<T>(\n name: string\n): RequiredContextReturn<T | undefined>;\nexport function createRequiredContext<T>(\n name: string,\n defaultValue?: T\n): RequiredContextReturn<T | undefined> {\n if (!isNonEmptyString(name)) {\n throw new Error(\n \"Invalid `context` name passed to `createRequiredContext`: expected a non-empty string.\"\n );\n }\n\n name = name.trim();\n\n const { contextDisplayName, providerDisplayName } =\n normalizeContextNames(name);\n\n /** ------------------------------------------------------------------------\n * * ***React Context instance (advanced usage).***\n * ------------------------------------------------------------------------\n */\n const Context = createContext<T | undefined>(defaultValue);\n Context.displayName = contextDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Context Provider component.***\n * ------------------------------------------------------------------------\n */\n function Provider(props: RequiredContextProviderProps<T | undefined>) {\n return (\n <Context.Provider value={props.value}>{props.children}</Context.Provider>\n );\n }\n\n Provider.displayName = providerDisplayName;\n\n /** ------------------------------------------------------------------------\n * * ***Hook to consume the context value safely.***\n * ------------------------------------------------------------------------\n */\n function useRequiredContext(\n missingProviderMessage?: string\n ): ContextValue<T> {\n const value = useContext(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as ContextValue<T>;\n }\n\n /** ------------------------------------------------------------------------\n * * ***Suspense consumer (React 19).***\n * ----------------------------------------------------------------------\n */\n function useRequiredContextSuspense(\n missingProviderMessage?: string,\n unsupportedReactErrorMessage?: string\n ): UnwrapPromise<T> {\n //\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n if (typeof React?.use !== \"function\" || !(\"use\" in React)) {\n throw new Error(\n unsupportedReactErrorMessage ??\n \"This feature requires `React 19` or `newer`, please upgrade your React version to use Suspense-enabled context.\"\n );\n }\n\n // eslint-disable-next-line @rzl-zone/eslint/no-react19-api\n const value = React.use(Context);\n\n if (value === undefined) {\n throw new Error(\n missingProviderMessage ??\n `You are using \\`${contextDisplayName}\\`, but your component is not wrapped with <${providerDisplayName}>.\\n` +\n `Did you forget to add <${providerDisplayName}> to your component tree?`\n );\n }\n\n return value as UnwrapPromise<T>;\n }\n\n return {\n Context,\n Provider,\n use: useRequiredContext,\n useSuspense: useRequiredContextSuspense\n };\n}\n\nfunction normalizeContextNames(name: string) {\n const trimmed = name.trim();\n\n const baseName = /context$/i.test(trimmed)\n ? trimmed.replace(/context$/i, \"\")\n : trimmed;\n\n const contextDisplayName = `${baseName}Context`;\n const providerDisplayName = `${baseName}Provider`;\n\n return {\n baseName,\n contextDisplayName,\n providerDisplayName\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmVA,SAAgB,sBACd,MACA,cACsC;CACtC,IAAI,CAAC,iBAAiB,IAAI,GACxB,MAAM,IAAI,MACR,wFACF;CAGF,OAAO,KAAK,KAAK;CAEjB,MAAM,EAAE,oBAAoB,wBAC1B,sBAAsB,IAAI;;;;;CAM5B,MAAM,UAAU,cAA6B,YAAY;CACzD,QAAQ,cAAc;;;;;CAMtB,SAAS,SAAS,OAAoD;EACpE,OACE,CAAC,QAAQ,SAAS,OAAO,MAAM,QAAQ,MAAM,SAAS,EAAE,QAAQ;CAEpE;CAEA,SAAS,cAAc;;;;;CAMvB,SAAS,mBACP,wBACiB;EACjB,MAAM,QAAQ,WAAW,OAAO;EAEhC,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,0BACpD;EAGF,OAAO;CACT;;;;;CAMA,SAAS,2BACP,wBACA,8BACkB;EAGlB,IAAI,OAAO,OAAO,QAAQ,cAAc,EAAE,SAAS,QACjD,MAAM,IAAI,MACR,gCACE,iHACJ;EAIF,MAAM,QAAQ,MAAM,IAAI,OAAO;EAE/B,IAAI,UAAU,QACZ,MAAM,IAAI,MACR,0BACE,mBAAmB,mBAAmB,8CAA8C,oBAAoB,6BAC5E,oBAAoB,0BACpD;EAGF,OAAO;CACT;CAEA,OAAO;EACL;EACA;EACA,KAAK;EACL,aAAa;CACf;AACF;AAEA,SAAS,sBAAsB,MAAc;CAC3C,MAAM,UAAU,KAAK,KAAK;CAE1B,MAAM,WAAW,YAAY,KAAK,OAAO,IACrC,QAAQ,QAAQ,aAAa,EAAE,IAC/B;CAKJ,OAAO;EACL;EACA,uBAL4B,SAAS;EAMrC,wBAL6B,SAAS;CAMxC;AACF"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -14,3 +14,3 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_chunk = require('../chunk-DZH3KJL-.cjs'); | ||
| const require_chunk = require('../chunk-Bfh80tNm.cjs'); | ||
| let react = require("react"); | ||
@@ -17,0 +17,0 @@ react = require_chunk.__toESM(react, 1); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"use-effect-event.cjs","names":["React"],"sources":["../../src/hooks/use-effect-event.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\ntype UseEffectEvent = <F extends (...params: never[]) => unknown>(\n callback: F\n) => F;\n\n/** --------------------------------------------------------------------------\n * * ***Stable event callback hook (React 19 `useEffectEvent` polyfill).***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Provides a **stable function reference** whose implementation\n * always reflects the **latest callback**.\n * - Prevents stale-closure issues in effects, subscriptions,\n * event listeners, and external APIs.\n *\n * - ***Behavior guarantees:***\n * - The returned function identity is **stable** across renders.\n * - The callback logic is **always up-to-date**.\n * - Does **not** cause re-subscriptions or effect re-runs.\n *\n * ---\n *\n * - ***React version support:***\n * - **React ≥ 19.2.x**\n * ➔ Delegates directly to `React.useEffectEvent`.\n * - **React < 19**\n * ➔ Uses a safe fallback implementation based on:\n * - `useRef` for mutable callback storage\n * - `useCallback` for stable identity\n *\n * ---\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only**.\n * - The returned function **must not** be used during render\n * for reading reactive values.\n * - Intended for **event handlers**, not render logic.\n *\n * ---\n *\n * - ***Designed for:***\n * - Event listeners (`addEventListener`)\n * - Subscriptions (WebSocket, observers, stores)\n * - Imperative APIs requiring stable callbacks\n * - Avoiding dependency explosion in `useEffect`\n *\n * - ❌ ***Not intended for:***\n * - Rendering-time computations\n * - Derived state\n * - Server Components\n *\n * @template F - Any function type with arbitrary parameters and return value.\n *\n * @param callback - The callback whose latest version should always be invoked.\n *\n * @returns\n * A **stable function reference** that always calls the latest callback.\n *\n * @example\n * **Event listener without re-subscription.**\n * ```tsx\n * const onResize = useEffectEvent(() => {\n * console.log(window.innerWidth);\n * });\n *\n * useEffect(() => {\n * window.addEventListener(\"resize\", onResize);\n * return () => window.removeEventListener(\"resize\", onResize);\n * }, []);\n * ```\n *\n * @example\n * **Safe usage inside effects.**\n * ```tsx\n * const onMessage = useEffectEvent((msg: Message) => {\n * setMessages(m => [...m, msg]);\n * });\n *\n * useEffect(() => {\n * socket.subscribe(onMessage);\n * return () => socket.unsubscribe(onMessage);\n * }, []);\n * ```\n */\nexport const useEffectEvent: UseEffectEvent =\n \"useEffectEvent\" in React\n ? { ...React }.useEffectEvent\n : <F extends (...params: never[]) => unknown>(callback: F) => {\n const ref = React.useRef(callback);\n ref.current = callback;\n\n return React.useCallback(\n ((...params) => ref.current(...params)) as F,\n []\n );\n };\n\n/** --------------------------------------------------------------------------\n * * ***Legacy fallback for `useEffectEvent` (DEPRECATED).***\n * --------------------------------------------------------------------------\n *\n * ⚠️ **Deprecated**\n * - Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n *\n * ---\n *\n * - ***Why this exists:***\n * - Supports older React versions where `useEffectEvent`\n * is not available.\n * - Uses `useEffect` to sync the callback reference.\n *\n * ---\n *\n * - ***Key differences from React's implementation:***\n * - Callback updates happen **after render**.\n * - Slightly higher overhead due to `useEffect`.\n * - Still guarantees a **stable function identity**.\n *\n * ---\n *\n * - ***Behavior guarantees:***\n * - Returned function identity is stable.\n * - Always invokes the latest callback.\n * - Safe for effects and event handlers.\n *\n * ---\n *\n * - ❌ ***Limitations:***\n * - Not concurrent-safe like the native hook.\n * - Not recommended for new code.\n *\n * @template F - Function type to stabilize.\n *\n * @param callback - Callback whose latest version should be invoked.\n *\n * @returns\n * A stable function reference invoking the latest callback.\n *\n * @deprecated Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n */\nexport function useEffectEventCustom<F extends (...args: never[]) => unknown>(\n callback: F\n): F {\n // const ref = useRef(callback);\n // ref.current = callback;\n\n // return useCallback(((...params) => ref.current(...params)) as F, []);\n\n const ref = React.useRef(callback);\n\n React.useEffect(() => {\n ref.current = callback;\n }, [callback]);\n\n const fn = React.useCallback((...args: never[]) => {\n return ref.current(...args) as F;\n }, []);\n\n return fn as F;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,MAAa,iBACX,oBAAoBA,QAChB,EAAE,GAAGA,OAAO,CAAC,kBAC+B,aAAgB;CAC1D,MAAM,MAAMA,MAAM,OAAO,SAAS;CAClC,IAAI,UAAU;CAEd,OAAOA,MAAM,cACT,GAAG,WAAW,IAAI,QAAQ,GAAG,OAAO,GACtC,EAAE,CACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CT,SAAgB,qBACd,UACG;CAMH,MAAM,MAAMA,MAAM,OAAO,SAAS;CAElC,MAAM,gBAAgB;EACpB,IAAI,UAAU;IACb,CAAC,SAAS,CAAC;CAMd,OAJWA,MAAM,aAAa,GAAG,SAAkB;EACjD,OAAO,IAAI,QAAQ,GAAG,KAAK;IAC1B,EAAE,CAEI"} | ||
| {"version":3,"file":"use-effect-event.cjs","names":["React"],"sources":["../../src/hooks/use-effect-event.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\ntype UseEffectEvent = <F extends (...params: never[]) => unknown>(\n callback: F\n) => F;\n\n/** --------------------------------------------------------------------------\n * * ***Stable event callback hook (React 19 `useEffectEvent` polyfill).***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Provides a **stable function reference** whose implementation\n * always reflects the **latest callback**.\n * - Prevents stale-closure issues in effects, subscriptions,\n * event listeners, and external APIs.\n *\n * - ***Behavior guarantees:***\n * - The returned function identity is **stable** across renders.\n * - The callback logic is **always up-to-date**.\n * - Does **not** cause re-subscriptions or effect re-runs.\n *\n * ---\n *\n * - ***React version support:***\n * - **React ≥ 19.2.x**\n * ➔ Delegates directly to `React.useEffectEvent`.\n * - **React < 19**\n * ➔ Uses a safe fallback implementation based on:\n * - `useRef` for mutable callback storage\n * - `useCallback` for stable identity\n *\n * ---\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only**.\n * - The returned function **must not** be used during render\n * for reading reactive values.\n * - Intended for **event handlers**, not render logic.\n *\n * ---\n *\n * - ***Designed for:***\n * - Event listeners (`addEventListener`)\n * - Subscriptions (WebSocket, observers, stores)\n * - Imperative APIs requiring stable callbacks\n * - Avoiding dependency explosion in `useEffect`\n *\n * - ❌ ***Not intended for:***\n * - Rendering-time computations\n * - Derived state\n * - Server Components\n *\n * @template F - Any function type with arbitrary parameters and return value.\n *\n * @param callback - The callback whose latest version should always be invoked.\n *\n * @returns\n * A **stable function reference** that always calls the latest callback.\n *\n * @example\n * **Event listener without re-subscription.**\n * ```tsx\n * const onResize = useEffectEvent(() => {\n * console.log(window.innerWidth);\n * });\n *\n * useEffect(() => {\n * window.addEventListener(\"resize\", onResize);\n * return () => window.removeEventListener(\"resize\", onResize);\n * }, []);\n * ```\n *\n * @example\n * **Safe usage inside effects.**\n * ```tsx\n * const onMessage = useEffectEvent((msg: Message) => {\n * setMessages(m => [...m, msg]);\n * });\n *\n * useEffect(() => {\n * socket.subscribe(onMessage);\n * return () => socket.unsubscribe(onMessage);\n * }, []);\n * ```\n */\nexport const useEffectEvent: UseEffectEvent =\n \"useEffectEvent\" in React\n ? { ...React }.useEffectEvent\n : <F extends (...params: never[]) => unknown>(callback: F) => {\n const ref = React.useRef(callback);\n ref.current = callback;\n\n return React.useCallback(\n ((...params) => ref.current(...params)) as F,\n []\n );\n };\n\n/** --------------------------------------------------------------------------\n * * ***Legacy fallback for `useEffectEvent` (DEPRECATED).***\n * --------------------------------------------------------------------------\n *\n * ⚠️ **Deprecated**\n * - Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n *\n * ---\n *\n * - ***Why this exists:***\n * - Supports older React versions where `useEffectEvent`\n * is not available.\n * - Uses `useEffect` to sync the callback reference.\n *\n * ---\n *\n * - ***Key differences from React's implementation:***\n * - Callback updates happen **after render**.\n * - Slightly higher overhead due to `useEffect`.\n * - Still guarantees a **stable function identity**.\n *\n * ---\n *\n * - ***Behavior guarantees:***\n * - Returned function identity is stable.\n * - Always invokes the latest callback.\n * - Safe for effects and event handlers.\n *\n * ---\n *\n * - ❌ ***Limitations:***\n * - Not concurrent-safe like the native hook.\n * - Not recommended for new code.\n *\n * @template F - Function type to stabilize.\n *\n * @param callback - Callback whose latest version should be invoked.\n *\n * @returns\n * A stable function reference invoking the latest callback.\n *\n * @deprecated Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n */\nexport function useEffectEventCustom<F extends (...args: never[]) => unknown>(\n callback: F\n): F {\n // const ref = useRef(callback);\n // ref.current = callback;\n\n // return useCallback(((...params) => ref.current(...params)) as F, []);\n\n const ref = React.useRef(callback);\n\n React.useEffect(() => {\n ref.current = callback;\n }, [callback]);\n\n const fn = React.useCallback((...args: never[]) => {\n return ref.current(...args) as F;\n }, []);\n\n return fn as F;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,MAAa,iBACX,oBAAoBA,QAChB,EAAE,GAAGA,MAAM,EAAE,kBAC+B,aAAgB;CAC1D,MAAM,MAAMA,MAAM,OAAO,QAAQ;CACjC,IAAI,UAAU;CAEd,OAAOA,MAAM,cACT,GAAG,WAAW,IAAI,QAAQ,GAAG,MAAM,IACrC,CAAC,CACH;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CN,SAAgB,qBACd,UACG;CAMH,MAAM,MAAMA,MAAM,OAAO,QAAQ;CAEjC,MAAM,gBAAgB;EACpB,IAAI,UAAU;CAChB,GAAG,CAAC,QAAQ,CAAC;CAMb,OAJWA,MAAM,aAAa,GAAG,SAAkB;EACjD,OAAO,IAAI,QAAQ,GAAG,IAAI;CAC5B,GAAG,CAAC,CAEI;AACV"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"use-effect-event.js","names":["React"],"sources":["../../src/hooks/use-effect-event.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\ntype UseEffectEvent = <F extends (...params: never[]) => unknown>(\n callback: F\n) => F;\n\n/** --------------------------------------------------------------------------\n * * ***Stable event callback hook (React 19 `useEffectEvent` polyfill).***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Provides a **stable function reference** whose implementation\n * always reflects the **latest callback**.\n * - Prevents stale-closure issues in effects, subscriptions,\n * event listeners, and external APIs.\n *\n * - ***Behavior guarantees:***\n * - The returned function identity is **stable** across renders.\n * - The callback logic is **always up-to-date**.\n * - Does **not** cause re-subscriptions or effect re-runs.\n *\n * ---\n *\n * - ***React version support:***\n * - **React ≥ 19.2.x**\n * ➔ Delegates directly to `React.useEffectEvent`.\n * - **React < 19**\n * ➔ Uses a safe fallback implementation based on:\n * - `useRef` for mutable callback storage\n * - `useCallback` for stable identity\n *\n * ---\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only**.\n * - The returned function **must not** be used during render\n * for reading reactive values.\n * - Intended for **event handlers**, not render logic.\n *\n * ---\n *\n * - ***Designed for:***\n * - Event listeners (`addEventListener`)\n * - Subscriptions (WebSocket, observers, stores)\n * - Imperative APIs requiring stable callbacks\n * - Avoiding dependency explosion in `useEffect`\n *\n * - ❌ ***Not intended for:***\n * - Rendering-time computations\n * - Derived state\n * - Server Components\n *\n * @template F - Any function type with arbitrary parameters and return value.\n *\n * @param callback - The callback whose latest version should always be invoked.\n *\n * @returns\n * A **stable function reference** that always calls the latest callback.\n *\n * @example\n * **Event listener without re-subscription.**\n * ```tsx\n * const onResize = useEffectEvent(() => {\n * console.log(window.innerWidth);\n * });\n *\n * useEffect(() => {\n * window.addEventListener(\"resize\", onResize);\n * return () => window.removeEventListener(\"resize\", onResize);\n * }, []);\n * ```\n *\n * @example\n * **Safe usage inside effects.**\n * ```tsx\n * const onMessage = useEffectEvent((msg: Message) => {\n * setMessages(m => [...m, msg]);\n * });\n *\n * useEffect(() => {\n * socket.subscribe(onMessage);\n * return () => socket.unsubscribe(onMessage);\n * }, []);\n * ```\n */\nexport const useEffectEvent: UseEffectEvent =\n \"useEffectEvent\" in React\n ? { ...React }.useEffectEvent\n : <F extends (...params: never[]) => unknown>(callback: F) => {\n const ref = React.useRef(callback);\n ref.current = callback;\n\n return React.useCallback(\n ((...params) => ref.current(...params)) as F,\n []\n );\n };\n\n/** --------------------------------------------------------------------------\n * * ***Legacy fallback for `useEffectEvent` (DEPRECATED).***\n * --------------------------------------------------------------------------\n *\n * ⚠️ **Deprecated**\n * - Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n *\n * ---\n *\n * - ***Why this exists:***\n * - Supports older React versions where `useEffectEvent`\n * is not available.\n * - Uses `useEffect` to sync the callback reference.\n *\n * ---\n *\n * - ***Key differences from React's implementation:***\n * - Callback updates happen **after render**.\n * - Slightly higher overhead due to `useEffect`.\n * - Still guarantees a **stable function identity**.\n *\n * ---\n *\n * - ***Behavior guarantees:***\n * - Returned function identity is stable.\n * - Always invokes the latest callback.\n * - Safe for effects and event handlers.\n *\n * ---\n *\n * - ❌ ***Limitations:***\n * - Not concurrent-safe like the native hook.\n * - Not recommended for new code.\n *\n * @template F - Function type to stabilize.\n *\n * @param callback - Callback whose latest version should be invoked.\n *\n * @returns\n * A stable function reference invoking the latest callback.\n *\n * @deprecated Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n */\nexport function useEffectEventCustom<F extends (...args: never[]) => unknown>(\n callback: F\n): F {\n // const ref = useRef(callback);\n // ref.current = callback;\n\n // return useCallback(((...params) => ref.current(...params)) as F, []);\n\n const ref = React.useRef(callback);\n\n React.useEffect(() => {\n ref.current = callback;\n }, [callback]);\n\n const fn = React.useCallback((...args: never[]) => {\n return ref.current(...args) as F;\n }, []);\n\n return fn as F;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,MAAa,iBACX,oBAAoBA,UAChB,EAAE,GAAGA,SAAO,CAAC,kBAC+B,aAAgB;CAC1D,MAAM,MAAMA,QAAM,OAAO,SAAS;CAClC,IAAI,UAAU;CAEd,OAAOA,QAAM,cACT,GAAG,WAAW,IAAI,QAAQ,GAAG,OAAO,GACtC,EAAE,CACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CT,SAAgB,qBACd,UACG;CAMH,MAAM,MAAMA,QAAM,OAAO,SAAS;CAElC,QAAM,gBAAgB;EACpB,IAAI,UAAU;IACb,CAAC,SAAS,CAAC;CAMd,OAJWA,QAAM,aAAa,GAAG,SAAkB;EACjD,OAAO,IAAI,QAAQ,GAAG,KAAK;IAC1B,EAAE,CAEI"} | ||
| {"version":3,"file":"use-effect-event.js","names":["React"],"sources":["../../src/hooks/use-effect-event.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\ntype UseEffectEvent = <F extends (...params: never[]) => unknown>(\n callback: F\n) => F;\n\n/** --------------------------------------------------------------------------\n * * ***Stable event callback hook (React 19 `useEffectEvent` polyfill).***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Provides a **stable function reference** whose implementation\n * always reflects the **latest callback**.\n * - Prevents stale-closure issues in effects, subscriptions,\n * event listeners, and external APIs.\n *\n * - ***Behavior guarantees:***\n * - The returned function identity is **stable** across renders.\n * - The callback logic is **always up-to-date**.\n * - Does **not** cause re-subscriptions or effect re-runs.\n *\n * ---\n *\n * - ***React version support:***\n * - **React ≥ 19.2.x**\n * ➔ Delegates directly to `React.useEffectEvent`.\n * - **React < 19**\n * ➔ Uses a safe fallback implementation based on:\n * - `useRef` for mutable callback storage\n * - `useCallback` for stable identity\n *\n * ---\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only**.\n * - The returned function **must not** be used during render\n * for reading reactive values.\n * - Intended for **event handlers**, not render logic.\n *\n * ---\n *\n * - ***Designed for:***\n * - Event listeners (`addEventListener`)\n * - Subscriptions (WebSocket, observers, stores)\n * - Imperative APIs requiring stable callbacks\n * - Avoiding dependency explosion in `useEffect`\n *\n * - ❌ ***Not intended for:***\n * - Rendering-time computations\n * - Derived state\n * - Server Components\n *\n * @template F - Any function type with arbitrary parameters and return value.\n *\n * @param callback - The callback whose latest version should always be invoked.\n *\n * @returns\n * A **stable function reference** that always calls the latest callback.\n *\n * @example\n * **Event listener without re-subscription.**\n * ```tsx\n * const onResize = useEffectEvent(() => {\n * console.log(window.innerWidth);\n * });\n *\n * useEffect(() => {\n * window.addEventListener(\"resize\", onResize);\n * return () => window.removeEventListener(\"resize\", onResize);\n * }, []);\n * ```\n *\n * @example\n * **Safe usage inside effects.**\n * ```tsx\n * const onMessage = useEffectEvent((msg: Message) => {\n * setMessages(m => [...m, msg]);\n * });\n *\n * useEffect(() => {\n * socket.subscribe(onMessage);\n * return () => socket.unsubscribe(onMessage);\n * }, []);\n * ```\n */\nexport const useEffectEvent: UseEffectEvent =\n \"useEffectEvent\" in React\n ? { ...React }.useEffectEvent\n : <F extends (...params: never[]) => unknown>(callback: F) => {\n const ref = React.useRef(callback);\n ref.current = callback;\n\n return React.useCallback(\n ((...params) => ref.current(...params)) as F,\n []\n );\n };\n\n/** --------------------------------------------------------------------------\n * * ***Legacy fallback for `useEffectEvent` (DEPRECATED).***\n * --------------------------------------------------------------------------\n *\n * ⚠️ **Deprecated**\n * - Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n *\n * ---\n *\n * - ***Why this exists:***\n * - Supports older React versions where `useEffectEvent`\n * is not available.\n * - Uses `useEffect` to sync the callback reference.\n *\n * ---\n *\n * - ***Key differences from React's implementation:***\n * - Callback updates happen **after render**.\n * - Slightly higher overhead due to `useEffect`.\n * - Still guarantees a **stable function identity**.\n *\n * ---\n *\n * - ***Behavior guarantees:***\n * - Returned function identity is stable.\n * - Always invokes the latest callback.\n * - Safe for effects and event handlers.\n *\n * ---\n *\n * - ❌ ***Limitations:***\n * - Not concurrent-safe like the native hook.\n * - Not recommended for new code.\n *\n * @template F - Function type to stabilize.\n *\n * @param callback - Callback whose latest version should be invoked.\n *\n * @returns\n * A stable function reference invoking the latest callback.\n *\n * @deprecated Use `useEffectEvent` from `@rzl-zone/core-react/hooks` instead.\n */\nexport function useEffectEventCustom<F extends (...args: never[]) => unknown>(\n callback: F\n): F {\n // const ref = useRef(callback);\n // ref.current = callback;\n\n // return useCallback(((...params) => ref.current(...params)) as F, []);\n\n const ref = React.useRef(callback);\n\n React.useEffect(() => {\n ref.current = callback;\n }, [callback]);\n\n const fn = React.useCallback((...args: never[]) => {\n return ref.current(...args) as F;\n }, []);\n\n return fn as F;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,MAAa,iBACX,oBAAoBA,UAChB,EAAE,GAAGA,QAAM,EAAE,kBAC+B,aAAgB;CAC1D,MAAM,MAAMA,QAAM,OAAO,QAAQ;CACjC,IAAI,UAAU;CAEd,OAAOA,QAAM,cACT,GAAG,WAAW,IAAI,QAAQ,GAAG,MAAM,IACrC,CAAC,CACH;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CN,SAAgB,qBACd,UACG;CAMH,MAAM,MAAMA,QAAM,OAAO,QAAQ;CAEjC,QAAM,gBAAgB;EACpB,IAAI,UAAU;CAChB,GAAG,CAAC,QAAQ,CAAC;CAMb,OAJWA,QAAM,aAAa,GAAG,SAAkB;EACjD,OAAO,IAAI,QAAQ,GAAG,IAAI;CAC5B,GAAG,CAAC,CAEI;AACV"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -14,3 +14,2 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_chunk = require('../chunk-DZH3KJL-.cjs'); | ||
| let react = require("react"); | ||
@@ -17,0 +16,0 @@ function useMediaQuery(query, disabled = false) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"use-media-query.cjs","names":[],"sources":["../../src/hooks/use-media-query.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***React hook for tracking CSS media query matches.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Observes a CSS media query using `window.matchMedia`.\n * - Reactively updates when the media query match state changes.\n *\n * - ***Return behavior:***\n * - `true` ➔ media query **matches**\n * - `false` ➔ media query **does not match**\n * - `null` ➔ state not yet evaluated (initial / disabled)\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only** (`\"use client\"`).\n * - The initial value is **`null`** to avoid:\n * - SSR hydration mismatches\n * - Accessing `window` during render\n *\n * ---\n *\n * - ***Disabled mode:***\n * - When `disabled === true`:\n * - No `matchMedia` listener is registered.\n * - No state updates occur.\n * - The hook always returns `null`.\n *\n * ---\n *\n * - ***Designed for:***\n * - Responsive UI logic.\n * - Conditional rendering based on viewport size.\n * - Feature toggles tied to media queries.\n *\n * - ❌ **Not intended for:**\n * - Server Components.\n * - Layout decisions that must be static during SSR.\n *\n * @param query - A valid CSS media query string.\n * @param disabled - Disables the media query listener when `true`.\n *\n * @returns\n * - `boolean` ➔ when the query has been evaluated.\n * - `null` ➔ before first evaluation or when disabled.\n *\n * @example\n * **Basic usage.**\n * ```tsx\n * const isDesktop = useMediaQuery(\"(min-width: 1024px)\");\n *\n * if (isDesktop === null) return null;\n *\n * return <div>{isDesktop ? \"Desktop\" : \"Mobile\"}</div>;\n * ```\n *\n * @example\n * **Conditional logic with null guard.**\n * ```tsx\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n *\n * useEffect(() => {\n * if (isDark === true) enableDarkMode();\n * if (isDark === false) enableLightMode();\n * }, [isDark]);\n * ```\n *\n * @example\n * **Disabled dynamically.**\n * ```tsx\n * const isMobile = useMediaQuery(\n * \"(max-width: 640px)\",\n * isPreviewMode\n * );\n * ```\n */\nexport function useMediaQuery(query: string, disabled = false): boolean | null {\n const [isMatch, setMatch] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (disabled) return;\n const mediaQueryList = window.matchMedia(query);\n\n const handleChange = () => {\n setMatch(mediaQueryList.matches);\n };\n handleChange();\n mediaQueryList.addEventListener(\"change\", handleChange);\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [disabled, query]);\n\n return isMatch;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,SAAgB,cAAc,OAAe,WAAW,OAAuB;CAC7E,MAAM,CAAC,SAAS,gCAAqC,KAAK;CAE1D,2BAAgB;EACd,IAAI,UAAU;EACd,MAAM,iBAAiB,OAAO,WAAW,MAAM;EAE/C,MAAM,qBAAqB;GACzB,SAAS,eAAe,QAAQ;;EAElC,cAAc;EACd,eAAe,iBAAiB,UAAU,aAAa;EACvD,aAAa;GACX,eAAe,oBAAoB,UAAU,aAAa;;IAE3D,CAAC,UAAU,MAAM,CAAC;CAErB,OAAO"} | ||
| {"version":3,"file":"use-media-query.cjs","names":[],"sources":["../../src/hooks/use-media-query.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***React hook for tracking CSS media query matches.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Observes a CSS media query using `window.matchMedia`.\n * - Reactively updates when the media query match state changes.\n *\n * - ***Return behavior:***\n * - `true` ➔ media query **matches**\n * - `false` ➔ media query **does not match**\n * - `null` ➔ state not yet evaluated (initial / disabled)\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only** (`\"use client\"`).\n * - The initial value is **`null`** to avoid:\n * - SSR hydration mismatches\n * - Accessing `window` during render\n *\n * ---\n *\n * - ***Disabled mode:***\n * - When `disabled === true`:\n * - No `matchMedia` listener is registered.\n * - No state updates occur.\n * - The hook always returns `null`.\n *\n * ---\n *\n * - ***Designed for:***\n * - Responsive UI logic.\n * - Conditional rendering based on viewport size.\n * - Feature toggles tied to media queries.\n *\n * - ❌ **Not intended for:**\n * - Server Components.\n * - Layout decisions that must be static during SSR.\n *\n * @param query - A valid CSS media query string.\n * @param disabled - Disables the media query listener when `true`.\n *\n * @returns\n * - `boolean` ➔ when the query has been evaluated.\n * - `null` ➔ before first evaluation or when disabled.\n *\n * @example\n * **Basic usage.**\n * ```tsx\n * const isDesktop = useMediaQuery(\"(min-width: 1024px)\");\n *\n * if (isDesktop === null) return null;\n *\n * return <div>{isDesktop ? \"Desktop\" : \"Mobile\"}</div>;\n * ```\n *\n * @example\n * **Conditional logic with null guard.**\n * ```tsx\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n *\n * useEffect(() => {\n * if (isDark === true) enableDarkMode();\n * if (isDark === false) enableLightMode();\n * }, [isDark]);\n * ```\n *\n * @example\n * **Disabled dynamically.**\n * ```tsx\n * const isMobile = useMediaQuery(\n * \"(max-width: 640px)\",\n * isPreviewMode\n * );\n * ```\n */\nexport function useMediaQuery(query: string, disabled = false): boolean | null {\n const [isMatch, setMatch] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (disabled) return;\n const mediaQueryList = window.matchMedia(query);\n\n const handleChange = () => {\n setMatch(mediaQueryList.matches);\n };\n handleChange();\n mediaQueryList.addEventListener(\"change\", handleChange);\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [disabled, query]);\n\n return isMatch;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,SAAgB,cAAc,OAAe,WAAW,OAAuB;CAC7E,MAAM,CAAC,SAAS,gCAAqC,IAAI;CAEzD,2BAAgB;EACd,IAAI,UAAU;EACd,MAAM,iBAAiB,OAAO,WAAW,KAAK;EAE9C,MAAM,qBAAqB;GACzB,SAAS,eAAe,OAAO;EACjC;EACA,aAAa;EACb,eAAe,iBAAiB,UAAU,YAAY;EACtD,aAAa;GACX,eAAe,oBAAoB,UAAU,YAAY;EAC3D;CACF,GAAG,CAAC,UAAU,KAAK,CAAC;CAEpB,OAAO;AACT"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"use-media-query.js","names":[],"sources":["../../src/hooks/use-media-query.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***React hook for tracking CSS media query matches.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Observes a CSS media query using `window.matchMedia`.\n * - Reactively updates when the media query match state changes.\n *\n * - ***Return behavior:***\n * - `true` ➔ media query **matches**\n * - `false` ➔ media query **does not match**\n * - `null` ➔ state not yet evaluated (initial / disabled)\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only** (`\"use client\"`).\n * - The initial value is **`null`** to avoid:\n * - SSR hydration mismatches\n * - Accessing `window` during render\n *\n * ---\n *\n * - ***Disabled mode:***\n * - When `disabled === true`:\n * - No `matchMedia` listener is registered.\n * - No state updates occur.\n * - The hook always returns `null`.\n *\n * ---\n *\n * - ***Designed for:***\n * - Responsive UI logic.\n * - Conditional rendering based on viewport size.\n * - Feature toggles tied to media queries.\n *\n * - ❌ **Not intended for:**\n * - Server Components.\n * - Layout decisions that must be static during SSR.\n *\n * @param query - A valid CSS media query string.\n * @param disabled - Disables the media query listener when `true`.\n *\n * @returns\n * - `boolean` ➔ when the query has been evaluated.\n * - `null` ➔ before first evaluation or when disabled.\n *\n * @example\n * **Basic usage.**\n * ```tsx\n * const isDesktop = useMediaQuery(\"(min-width: 1024px)\");\n *\n * if (isDesktop === null) return null;\n *\n * return <div>{isDesktop ? \"Desktop\" : \"Mobile\"}</div>;\n * ```\n *\n * @example\n * **Conditional logic with null guard.**\n * ```tsx\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n *\n * useEffect(() => {\n * if (isDark === true) enableDarkMode();\n * if (isDark === false) enableLightMode();\n * }, [isDark]);\n * ```\n *\n * @example\n * **Disabled dynamically.**\n * ```tsx\n * const isMobile = useMediaQuery(\n * \"(max-width: 640px)\",\n * isPreviewMode\n * );\n * ```\n */\nexport function useMediaQuery(query: string, disabled = false): boolean | null {\n const [isMatch, setMatch] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (disabled) return;\n const mediaQueryList = window.matchMedia(query);\n\n const handleChange = () => {\n setMatch(mediaQueryList.matches);\n };\n handleChange();\n mediaQueryList.addEventListener(\"change\", handleChange);\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [disabled, query]);\n\n return isMatch;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,SAAgB,cAAc,OAAe,WAAW,OAAuB;CAC7E,MAAM,CAAC,SAAS,YAAY,SAAyB,KAAK;CAE1D,gBAAgB;EACd,IAAI,UAAU;EACd,MAAM,iBAAiB,OAAO,WAAW,MAAM;EAE/C,MAAM,qBAAqB;GACzB,SAAS,eAAe,QAAQ;;EAElC,cAAc;EACd,eAAe,iBAAiB,UAAU,aAAa;EACvD,aAAa;GACX,eAAe,oBAAoB,UAAU,aAAa;;IAE3D,CAAC,UAAU,MAAM,CAAC;CAErB,OAAO"} | ||
| {"version":3,"file":"use-media-query.js","names":[],"sources":["../../src/hooks/use-media-query.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***React hook for tracking CSS media query matches.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Observes a CSS media query using `window.matchMedia`.\n * - Reactively updates when the media query match state changes.\n *\n * - ***Return behavior:***\n * - `true` ➔ media query **matches**\n * - `false` ➔ media query **does not match**\n * - `null` ➔ state not yet evaluated (initial / disabled)\n *\n * - ⚠️ ***Important behavior:***\n * - This hook is **client-only** (`\"use client\"`).\n * - The initial value is **`null`** to avoid:\n * - SSR hydration mismatches\n * - Accessing `window` during render\n *\n * ---\n *\n * - ***Disabled mode:***\n * - When `disabled === true`:\n * - No `matchMedia` listener is registered.\n * - No state updates occur.\n * - The hook always returns `null`.\n *\n * ---\n *\n * - ***Designed for:***\n * - Responsive UI logic.\n * - Conditional rendering based on viewport size.\n * - Feature toggles tied to media queries.\n *\n * - ❌ **Not intended for:**\n * - Server Components.\n * - Layout decisions that must be static during SSR.\n *\n * @param query - A valid CSS media query string.\n * @param disabled - Disables the media query listener when `true`.\n *\n * @returns\n * - `boolean` ➔ when the query has been evaluated.\n * - `null` ➔ before first evaluation or when disabled.\n *\n * @example\n * **Basic usage.**\n * ```tsx\n * const isDesktop = useMediaQuery(\"(min-width: 1024px)\");\n *\n * if (isDesktop === null) return null;\n *\n * return <div>{isDesktop ? \"Desktop\" : \"Mobile\"}</div>;\n * ```\n *\n * @example\n * **Conditional logic with null guard.**\n * ```tsx\n * const isDark = useMediaQuery(\"(prefers-color-scheme: dark)\");\n *\n * useEffect(() => {\n * if (isDark === true) enableDarkMode();\n * if (isDark === false) enableLightMode();\n * }, [isDark]);\n * ```\n *\n * @example\n * **Disabled dynamically.**\n * ```tsx\n * const isMobile = useMediaQuery(\n * \"(max-width: 640px)\",\n * isPreviewMode\n * );\n * ```\n */\nexport function useMediaQuery(query: string, disabled = false): boolean | null {\n const [isMatch, setMatch] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (disabled) return;\n const mediaQueryList = window.matchMedia(query);\n\n const handleChange = () => {\n setMatch(mediaQueryList.matches);\n };\n handleChange();\n mediaQueryList.addEventListener(\"change\", handleChange);\n return () => {\n mediaQueryList.removeEventListener(\"change\", handleChange);\n };\n }, [disabled, query]);\n\n return isMatch;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,SAAgB,cAAc,OAAe,WAAW,OAAuB;CAC7E,MAAM,CAAC,SAAS,YAAY,SAAyB,IAAI;CAEzD,gBAAgB;EACd,IAAI,UAAU;EACd,MAAM,iBAAiB,OAAO,WAAW,KAAK;EAE9C,MAAM,qBAAqB;GACzB,SAAS,eAAe,OAAO;EACjC;EACA,aAAa;EACb,eAAe,iBAAiB,UAAU,YAAY;EACtD,aAAa;GACX,eAAe,oBAAoB,UAAU,YAAY;EAC3D;CACF,GAAG,CAAC,UAAU,KAAK,CAAC;CAEpB,OAAO;AACT"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -14,3 +14,2 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_chunk = require('../chunk-DZH3KJL-.cjs'); | ||
| let react = require("react"); | ||
@@ -17,0 +16,0 @@ function isDifferent(a, b) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"use-on-change.cjs","names":[],"sources":["../../src/hooks/use-on-change.ts"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***Performs a shallow-to-recursive difference check between two values.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Detects whether two values are **different**.\n * - Designed as a **lightweight comparator** for state-change detection.\n *\n * - ***Comparison behavior:***\n * - Uses **strict inequality (`!==`)** for non-array values.\n * - Recursively compares **arrays by index and length**.\n *\n * - ⚠️ ***Important limitations:***\n * - ❌ Does **NOT** perform deep object comparison.\n * - ❌ Plain objects are compared by **reference**, not by structure.\n * - ❌ Functions, Maps, Sets, Dates, etc. are compared by reference.\n *\n * - ✅ **Safe for:**\n * - Primitive values (`string`, `number`, `boolean`, `null`, `undefined`)\n * - Arrays of primitives\n * - Nested arrays (recursive)\n *\n * ---\n *\n * ℹ️ This function is intentionally simple and predictable.\n * If you need structural deep equality, use a dedicated deep-compare utility.\n *\n * ---\n *\n * - ***Common use cases:***\n * - Detecting state changes in custom React hooks.\n * - Lightweight comparison for dependency tracking.\n * - Guarding side-effects against unnecessary executions.\n *\n * @param a - Previous value to compare.\n * @param b - Current value to compare.\n *\n * @returns\n * - `true` ➔ values are different\n * - `false` ➔ values are considered equal\n *\n * @example\n * **Primitive comparison.**\n * ```ts\n * isDifferent(1, 1); // false\n * isDifferent(1, 2); // true\n * isDifferent(\"a\", \"a\"); // false\n * isDifferent(\"a\", \"b\"); // true\n * ```\n *\n * @example\n * **Array comparison.**\n * ```ts\n * isDifferent([1, 2], [1, 2]); // false\n * isDifferent([1, 2], [2, 1]); // true\n * isDifferent([1, 2], [1, 2, 3]); // true\n * ```\n *\n * @example\n * **Nested arrays.**\n * ```ts\n * isDifferent([[1], [2]], [[1], [2]]); // false\n * isDifferent([[1], [2]], [[1], [3]]); // true\n * ```\n *\n * @example\n * **Object references.**\n * ```ts\n * isDifferent({ a: 1 }, { a: 1 }); // true (different references)\n *\n * const obj = { a: 1 };\n * isDifferent(obj, obj); // false\n * ```\n *\n * @internal\n */\nfunction isDifferent(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n }\n\n return a !== b;\n}\n\n/** --------------------------------------------------------------------------\n * * ***Run a side-effect when a value changes (manual change detection).***\n * --------------------------------------------------------------------------\n *\n * A lightweight hook to detect changes between renders and execute\n * a callback **only when the value is considered \"updated\"**.\n *\n * ---\n *\n * - ***Core behavior:***\n * - Stores the previous value internally.\n * - Compares `previous` and `current` values on every render.\n * - Executes `onChange(current, previous)` **synchronously**\n * when `isUpdated(previous, current)` returns `true`.\n *\n * ---\n *\n * - ⚠️ ***Important notes:***\n * - This hook **does NOT use `useEffect`**.\n * - The comparison and callback run during render.\n * - Make sure `onChange` does **not cause infinite re-renders**.\n *\n * ---\n *\n * - ***Default comparison strategy:***\n * - Uses a shallow `!==` comparison.\n * - Supports basic deep comparison for arrays.\n *\n * ---\n *\n * - ***Designed for:***\n * - Lightweight change tracking.\n * - Controlled state synchronization.\n * - Custom state diffing logic without `useEffect`.\n *\n * ---\n *\n * @template T - The watched value type.\n *\n * @param value\n * The current value to observe.\n *\n * @param onChange\n * Callback invoked when the value is considered changed.\n *\n * Receives:\n * - `current` — the new value.\n * - `previous` — the previous value.\n *\n * @param isUpdated\n * Optional custom comparison function.\n *\n * Determines whether the value has changed.\n * Defaults to a shallow comparison with array support.\n *\n * ---\n *\n * @example\n * **1. Detect primitive value changes.**\n * ```tsx\n * const [count, setCount] = useState(0);\n *\n * useOnChange(count, (current, prev) => {\n * console.log(\"Count changed:\", prev, \"➔\", current);\n * });\n * ```\n *\n * @example\n * **2. Detect object changes with custom comparator.**\n * ```tsx\n * type User = { id: number; name: string };\n *\n * useOnChange(\n * user,\n * (current, prev) => {\n * console.log(\"User updated\", prev, current);\n * },\n * (prev, current) => prev.id !== current.id\n * );\n * ```\n *\n * @example\n * **3. Sync external state without `useEffect`.**\n * ```tsx\n * useOnChange(value, (current) => {\n * localStorage.setItem(\"value\", JSON.stringify(current));\n * });\n * ```\n */\nexport function useOnChange<T>(\n value: T,\n onChange: (current: T, previous: T) => void,\n isUpdated: (prev: T, current: T) => boolean = isDifferent\n): void {\n const [prev, setPrev] = useState<T>(value);\n\n if (isUpdated(prev, value)) {\n onChange(value, prev);\n setPrev(value);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAS,YAAY,GAAY,GAAqB;CACpD,IAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,EACtC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,GAAG,CAAC;CAGxE,OAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4Ff,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,+BAAuB,MAAM;CAE1C,IAAI,UAAU,MAAM,MAAM,EAAE;EAC1B,SAAS,OAAO,KAAK;EACrB,QAAQ,MAAM"} | ||
| {"version":3,"file":"use-on-change.cjs","names":[],"sources":["../../src/hooks/use-on-change.ts"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***Performs a shallow-to-recursive difference check between two values.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Detects whether two values are **different**.\n * - Designed as a **lightweight comparator** for state-change detection.\n *\n * - ***Comparison behavior:***\n * - Uses **strict inequality (`!==`)** for non-array values.\n * - Recursively compares **arrays by index and length**.\n *\n * - ⚠️ ***Important limitations:***\n * - ❌ Does **NOT** perform deep object comparison.\n * - ❌ Plain objects are compared by **reference**, not by structure.\n * - ❌ Functions, Maps, Sets, Dates, etc. are compared by reference.\n *\n * - ✅ **Safe for:**\n * - Primitive values (`string`, `number`, `boolean`, `null`, `undefined`)\n * - Arrays of primitives\n * - Nested arrays (recursive)\n *\n * ---\n *\n * ℹ️ This function is intentionally simple and predictable.\n * If you need structural deep equality, use a dedicated deep-compare utility.\n *\n * ---\n *\n * - ***Common use cases:***\n * - Detecting state changes in custom React hooks.\n * - Lightweight comparison for dependency tracking.\n * - Guarding side-effects against unnecessary executions.\n *\n * @param a - Previous value to compare.\n * @param b - Current value to compare.\n *\n * @returns\n * - `true` ➔ values are different\n * - `false` ➔ values are considered equal\n *\n * @example\n * **Primitive comparison.**\n * ```ts\n * isDifferent(1, 1); // false\n * isDifferent(1, 2); // true\n * isDifferent(\"a\", \"a\"); // false\n * isDifferent(\"a\", \"b\"); // true\n * ```\n *\n * @example\n * **Array comparison.**\n * ```ts\n * isDifferent([1, 2], [1, 2]); // false\n * isDifferent([1, 2], [2, 1]); // true\n * isDifferent([1, 2], [1, 2, 3]); // true\n * ```\n *\n * @example\n * **Nested arrays.**\n * ```ts\n * isDifferent([[1], [2]], [[1], [2]]); // false\n * isDifferent([[1], [2]], [[1], [3]]); // true\n * ```\n *\n * @example\n * **Object references.**\n * ```ts\n * isDifferent({ a: 1 }, { a: 1 }); // true (different references)\n *\n * const obj = { a: 1 };\n * isDifferent(obj, obj); // false\n * ```\n *\n * @internal\n */\nfunction isDifferent(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n }\n\n return a !== b;\n}\n\n/** --------------------------------------------------------------------------\n * * ***Run a side-effect when a value changes (manual change detection).***\n * --------------------------------------------------------------------------\n *\n * A lightweight hook to detect changes between renders and execute\n * a callback **only when the value is considered \"updated\"**.\n *\n * ---\n *\n * - ***Core behavior:***\n * - Stores the previous value internally.\n * - Compares `previous` and `current` values on every render.\n * - Executes `onChange(current, previous)` **synchronously**\n * when `isUpdated(previous, current)` returns `true`.\n *\n * ---\n *\n * - ⚠️ ***Important notes:***\n * - This hook **does NOT use `useEffect`**.\n * - The comparison and callback run during render.\n * - Make sure `onChange` does **not cause infinite re-renders**.\n *\n * ---\n *\n * - ***Default comparison strategy:***\n * - Uses a shallow `!==` comparison.\n * - Supports basic deep comparison for arrays.\n *\n * ---\n *\n * - ***Designed for:***\n * - Lightweight change tracking.\n * - Controlled state synchronization.\n * - Custom state diffing logic without `useEffect`.\n *\n * ---\n *\n * @template T - The watched value type.\n *\n * @param value\n * The current value to observe.\n *\n * @param onChange\n * Callback invoked when the value is considered changed.\n *\n * Receives:\n * - `current` — the new value.\n * - `previous` — the previous value.\n *\n * @param isUpdated\n * Optional custom comparison function.\n *\n * Determines whether the value has changed.\n * Defaults to a shallow comparison with array support.\n *\n * ---\n *\n * @example\n * **1. Detect primitive value changes.**\n * ```tsx\n * const [count, setCount] = useState(0);\n *\n * useOnChange(count, (current, prev) => {\n * console.log(\"Count changed:\", prev, \"➔\", current);\n * });\n * ```\n *\n * @example\n * **2. Detect object changes with custom comparator.**\n * ```tsx\n * type User = { id: number; name: string };\n *\n * useOnChange(\n * user,\n * (current, prev) => {\n * console.log(\"User updated\", prev, current);\n * },\n * (prev, current) => prev.id !== current.id\n * );\n * ```\n *\n * @example\n * **3. Sync external state without `useEffect`.**\n * ```tsx\n * useOnChange(value, (current) => {\n * localStorage.setItem(\"value\", JSON.stringify(current));\n * });\n * ```\n */\nexport function useOnChange<T>(\n value: T,\n onChange: (current: T, previous: T) => void,\n isUpdated: (prev: T, current: T) => boolean = isDifferent\n): void {\n const [prev, setPrev] = useState<T>(value);\n\n if (isUpdated(prev, value)) {\n onChange(value, prev);\n setPrev(value);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAS,YAAY,GAAY,GAAqB;CACpD,IAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GACrC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,EAAE,CAAC;CAGvE,OAAO,MAAM;AACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,+BAAuB,KAAK;CAEzC,IAAI,UAAU,MAAM,KAAK,GAAG;EAC1B,SAAS,OAAO,IAAI;EACpB,QAAQ,KAAK;CACf;AACF"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"use-on-change.js","names":[],"sources":["../../src/hooks/use-on-change.ts"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***Performs a shallow-to-recursive difference check between two values.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Detects whether two values are **different**.\n * - Designed as a **lightweight comparator** for state-change detection.\n *\n * - ***Comparison behavior:***\n * - Uses **strict inequality (`!==`)** for non-array values.\n * - Recursively compares **arrays by index and length**.\n *\n * - ⚠️ ***Important limitations:***\n * - ❌ Does **NOT** perform deep object comparison.\n * - ❌ Plain objects are compared by **reference**, not by structure.\n * - ❌ Functions, Maps, Sets, Dates, etc. are compared by reference.\n *\n * - ✅ **Safe for:**\n * - Primitive values (`string`, `number`, `boolean`, `null`, `undefined`)\n * - Arrays of primitives\n * - Nested arrays (recursive)\n *\n * ---\n *\n * ℹ️ This function is intentionally simple and predictable.\n * If you need structural deep equality, use a dedicated deep-compare utility.\n *\n * ---\n *\n * - ***Common use cases:***\n * - Detecting state changes in custom React hooks.\n * - Lightweight comparison for dependency tracking.\n * - Guarding side-effects against unnecessary executions.\n *\n * @param a - Previous value to compare.\n * @param b - Current value to compare.\n *\n * @returns\n * - `true` ➔ values are different\n * - `false` ➔ values are considered equal\n *\n * @example\n * **Primitive comparison.**\n * ```ts\n * isDifferent(1, 1); // false\n * isDifferent(1, 2); // true\n * isDifferent(\"a\", \"a\"); // false\n * isDifferent(\"a\", \"b\"); // true\n * ```\n *\n * @example\n * **Array comparison.**\n * ```ts\n * isDifferent([1, 2], [1, 2]); // false\n * isDifferent([1, 2], [2, 1]); // true\n * isDifferent([1, 2], [1, 2, 3]); // true\n * ```\n *\n * @example\n * **Nested arrays.**\n * ```ts\n * isDifferent([[1], [2]], [[1], [2]]); // false\n * isDifferent([[1], [2]], [[1], [3]]); // true\n * ```\n *\n * @example\n * **Object references.**\n * ```ts\n * isDifferent({ a: 1 }, { a: 1 }); // true (different references)\n *\n * const obj = { a: 1 };\n * isDifferent(obj, obj); // false\n * ```\n *\n * @internal\n */\nfunction isDifferent(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n }\n\n return a !== b;\n}\n\n/** --------------------------------------------------------------------------\n * * ***Run a side-effect when a value changes (manual change detection).***\n * --------------------------------------------------------------------------\n *\n * A lightweight hook to detect changes between renders and execute\n * a callback **only when the value is considered \"updated\"**.\n *\n * ---\n *\n * - ***Core behavior:***\n * - Stores the previous value internally.\n * - Compares `previous` and `current` values on every render.\n * - Executes `onChange(current, previous)` **synchronously**\n * when `isUpdated(previous, current)` returns `true`.\n *\n * ---\n *\n * - ⚠️ ***Important notes:***\n * - This hook **does NOT use `useEffect`**.\n * - The comparison and callback run during render.\n * - Make sure `onChange` does **not cause infinite re-renders**.\n *\n * ---\n *\n * - ***Default comparison strategy:***\n * - Uses a shallow `!==` comparison.\n * - Supports basic deep comparison for arrays.\n *\n * ---\n *\n * - ***Designed for:***\n * - Lightweight change tracking.\n * - Controlled state synchronization.\n * - Custom state diffing logic without `useEffect`.\n *\n * ---\n *\n * @template T - The watched value type.\n *\n * @param value\n * The current value to observe.\n *\n * @param onChange\n * Callback invoked when the value is considered changed.\n *\n * Receives:\n * - `current` — the new value.\n * - `previous` — the previous value.\n *\n * @param isUpdated\n * Optional custom comparison function.\n *\n * Determines whether the value has changed.\n * Defaults to a shallow comparison with array support.\n *\n * ---\n *\n * @example\n * **1. Detect primitive value changes.**\n * ```tsx\n * const [count, setCount] = useState(0);\n *\n * useOnChange(count, (current, prev) => {\n * console.log(\"Count changed:\", prev, \"➔\", current);\n * });\n * ```\n *\n * @example\n * **2. Detect object changes with custom comparator.**\n * ```tsx\n * type User = { id: number; name: string };\n *\n * useOnChange(\n * user,\n * (current, prev) => {\n * console.log(\"User updated\", prev, current);\n * },\n * (prev, current) => prev.id !== current.id\n * );\n * ```\n *\n * @example\n * **3. Sync external state without `useEffect`.**\n * ```tsx\n * useOnChange(value, (current) => {\n * localStorage.setItem(\"value\", JSON.stringify(current));\n * });\n * ```\n */\nexport function useOnChange<T>(\n value: T,\n onChange: (current: T, previous: T) => void,\n isUpdated: (prev: T, current: T) => boolean = isDifferent\n): void {\n const [prev, setPrev] = useState<T>(value);\n\n if (isUpdated(prev, value)) {\n onChange(value, prev);\n setPrev(value);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAS,YAAY,GAAY,GAAqB;CACpD,IAAI,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE,EACtC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,GAAG,CAAC;CAGxE,OAAO,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4Ff,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,WAAW,SAAY,MAAM;CAE1C,IAAI,UAAU,MAAM,MAAM,EAAE;EAC1B,SAAS,OAAO,KAAK;EACrB,QAAQ,MAAM"} | ||
| {"version":3,"file":"use-on-change.js","names":[],"sources":["../../src/hooks/use-on-change.ts"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\n\n/** --------------------------------------------------------------------------\n * * ***Performs a shallow-to-recursive difference check between two values.***\n * --------------------------------------------------------------------------\n *\n * - ***Primary purpose:***\n * - Detects whether two values are **different**.\n * - Designed as a **lightweight comparator** for state-change detection.\n *\n * - ***Comparison behavior:***\n * - Uses **strict inequality (`!==`)** for non-array values.\n * - Recursively compares **arrays by index and length**.\n *\n * - ⚠️ ***Important limitations:***\n * - ❌ Does **NOT** perform deep object comparison.\n * - ❌ Plain objects are compared by **reference**, not by structure.\n * - ❌ Functions, Maps, Sets, Dates, etc. are compared by reference.\n *\n * - ✅ **Safe for:**\n * - Primitive values (`string`, `number`, `boolean`, `null`, `undefined`)\n * - Arrays of primitives\n * - Nested arrays (recursive)\n *\n * ---\n *\n * ℹ️ This function is intentionally simple and predictable.\n * If you need structural deep equality, use a dedicated deep-compare utility.\n *\n * ---\n *\n * - ***Common use cases:***\n * - Detecting state changes in custom React hooks.\n * - Lightweight comparison for dependency tracking.\n * - Guarding side-effects against unnecessary executions.\n *\n * @param a - Previous value to compare.\n * @param b - Current value to compare.\n *\n * @returns\n * - `true` ➔ values are different\n * - `false` ➔ values are considered equal\n *\n * @example\n * **Primitive comparison.**\n * ```ts\n * isDifferent(1, 1); // false\n * isDifferent(1, 2); // true\n * isDifferent(\"a\", \"a\"); // false\n * isDifferent(\"a\", \"b\"); // true\n * ```\n *\n * @example\n * **Array comparison.**\n * ```ts\n * isDifferent([1, 2], [1, 2]); // false\n * isDifferent([1, 2], [2, 1]); // true\n * isDifferent([1, 2], [1, 2, 3]); // true\n * ```\n *\n * @example\n * **Nested arrays.**\n * ```ts\n * isDifferent([[1], [2]], [[1], [2]]); // false\n * isDifferent([[1], [2]], [[1], [3]]); // true\n * ```\n *\n * @example\n * **Object references.**\n * ```ts\n * isDifferent({ a: 1 }, { a: 1 }); // true (different references)\n *\n * const obj = { a: 1 };\n * isDifferent(obj, obj); // false\n * ```\n *\n * @internal\n */\nfunction isDifferent(a: unknown, b: unknown): boolean {\n if (Array.isArray(a) && Array.isArray(b)) {\n return b.length !== a.length || a.some((v, i) => isDifferent(v, b[i]));\n }\n\n return a !== b;\n}\n\n/** --------------------------------------------------------------------------\n * * ***Run a side-effect when a value changes (manual change detection).***\n * --------------------------------------------------------------------------\n *\n * A lightweight hook to detect changes between renders and execute\n * a callback **only when the value is considered \"updated\"**.\n *\n * ---\n *\n * - ***Core behavior:***\n * - Stores the previous value internally.\n * - Compares `previous` and `current` values on every render.\n * - Executes `onChange(current, previous)` **synchronously**\n * when `isUpdated(previous, current)` returns `true`.\n *\n * ---\n *\n * - ⚠️ ***Important notes:***\n * - This hook **does NOT use `useEffect`**.\n * - The comparison and callback run during render.\n * - Make sure `onChange` does **not cause infinite re-renders**.\n *\n * ---\n *\n * - ***Default comparison strategy:***\n * - Uses a shallow `!==` comparison.\n * - Supports basic deep comparison for arrays.\n *\n * ---\n *\n * - ***Designed for:***\n * - Lightweight change tracking.\n * - Controlled state synchronization.\n * - Custom state diffing logic without `useEffect`.\n *\n * ---\n *\n * @template T - The watched value type.\n *\n * @param value\n * The current value to observe.\n *\n * @param onChange\n * Callback invoked when the value is considered changed.\n *\n * Receives:\n * - `current` — the new value.\n * - `previous` — the previous value.\n *\n * @param isUpdated\n * Optional custom comparison function.\n *\n * Determines whether the value has changed.\n * Defaults to a shallow comparison with array support.\n *\n * ---\n *\n * @example\n * **1. Detect primitive value changes.**\n * ```tsx\n * const [count, setCount] = useState(0);\n *\n * useOnChange(count, (current, prev) => {\n * console.log(\"Count changed:\", prev, \"➔\", current);\n * });\n * ```\n *\n * @example\n * **2. Detect object changes with custom comparator.**\n * ```tsx\n * type User = { id: number; name: string };\n *\n * useOnChange(\n * user,\n * (current, prev) => {\n * console.log(\"User updated\", prev, current);\n * },\n * (prev, current) => prev.id !== current.id\n * );\n * ```\n *\n * @example\n * **3. Sync external state without `useEffect`.**\n * ```tsx\n * useOnChange(value, (current) => {\n * localStorage.setItem(\"value\", JSON.stringify(current));\n * });\n * ```\n */\nexport function useOnChange<T>(\n value: T,\n onChange: (current: T, previous: T) => void,\n isUpdated: (prev: T, current: T) => boolean = isDifferent\n): void {\n const [prev, setPrev] = useState<T>(value);\n\n if (isUpdated(prev, value)) {\n onChange(value, prev);\n setPrev(value);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAS,YAAY,GAAY,GAAqB;CACpD,IAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GACrC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,EAAE,EAAE,CAAC;CAGvE,OAAO,MAAM;AACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,YACd,OACA,UACA,YAA8C,aACxC;CACN,MAAM,CAAC,MAAM,WAAW,SAAY,KAAK;CAEzC,IAAI,UAAU,MAAM,KAAK,GAAG;EAC1B,SAAS,OAAO,IAAI;EACpB,QAAQ,KAAK;CACf;AACF"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"merge-props.cjs","names":[],"sources":["../../src/utils/merge-props.ts"],"sourcesContent":["/* eslint-disable quotes */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I\n) => void\n ? I\n : never;\n\nfunction pushProp(\n target: { [key: string]: any },\n key: string,\n value: unknown[]\n): void {\n if (key === \"className\") {\n target.className = [target.className, value].join(\" \").trim();\n } else if (key === \"style\") {\n target.style = { ...target.style, ...value };\n } else if (typeof value === \"function\") {\n const oldFn = target[key] as Function | undefined;\n target[key] = oldFn\n ? (...args: unknown[]) => {\n oldFn(...args);\n (value as Function)(...args);\n }\n : value;\n } else if (\n // skip merging undefined values\n value === undefined ||\n // skip if both value are the same primitive value\n (typeof value !== \"object\" && value === target[key])\n ) {\n return;\n } else if (!(key in target)) {\n target[key] = value;\n } else {\n throw new Error(\n `Didn’t know how to merge prop '${key}'. ` +\n `Only 'className', 'style', and event handlers are supported`\n );\n }\n}\n\ntype MergedProps<T extends object[]> = {\n [K in keyof UnionToIntersection<T[number]>]: K extends \"className\"\n ? string\n : K extends \"style\"\n ? UnionToIntersection<T[number]>[K]\n : Exclude<Extract<T[number], { [Q in K]: unknown }>[K], undefined>;\n};\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple props objects into a single props object with\n * predictable and React-friendly merging behavior.***\n * --------------------------------------------------------------------\n *\n * This utility is designed to safely merge component props where certain\n * keys require special handling instead of simple overwrites.\n *\n * - **Behavior:**\n * - Concatenates duplicate `className` values with a single space\n * - Shallow-merges duplicate `style` objects (later props take precedence)\n * - Chains duplicate function values (commonly event handlers),\n * executing them from left to right\n * - Skips merging `undefined` values\n * - Preserves identical primitive values without reassigning\n * - Throws an error for unsupported duplicate keys\n *\n * Later props in the argument list always have higher precedence\n * when conflicts occur.\n *\n * This makes the function especially suitable for **React / JSX props\n * composition**, such as combining props from hooks, components,\n * and user overrides.\n *\n * @typeParam T - A tuple of props object types to be merged.\n * @param props - One or more props objects. Later objects override\n * earlier ones when applicable.\n *\n * @returns A single merged props object with correctly inferred types,\n * including special handling for `className` and `style`.\n *\n * @throws {Error} If duplicate keys other than `className`, `style`,\n * or function values are encountered.\n *\n * @example\n * ```ts\n * mergeProps(\n * { className: \"btn\", onClick: () => console.log(\"a\") },\n * { className: \"btn-primary\", onClick: () => console.log(\"b\") }\n * );\n * // => {\n * // className: \"btn btn-primary\",\n * // onClick: () => { a(); b(); }\n * // }\n * ```\n *\n * @example\n * ```ts\n * mergeProps(\n * { style: { color: \"red\", fontSize: 12 } },\n * { style: { fontSize: 14 } }\n * );\n * // => { style: { color: \"red\", fontSize: 14 } }\n * ```\n */\nexport function mergeProps<T extends object[]>(...props: T): MergedProps<T> {\n if (props.length === 1) {\n return props[0] as MergedProps<T>;\n }\n\n return props.reduce((merged, ps: { [key: string]: any }) => {\n for (const key in ps) {\n pushProp(merged, key, ps[key]);\n }\n return merged;\n }, {}) as MergedProps<T>;\n}\n"],"mappings":";;;;;;;;;;;;;AASA,SAAS,SACP,QACA,KACA,OACM;CACN,IAAI,QAAQ,aACV,OAAO,YAAY,CAAC,OAAO,WAAW,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM;MACxD,IAAI,QAAQ,SACjB,OAAO,QAAQ;EAAE,GAAG,OAAO;EAAO,GAAG;EAAO;MACvC,IAAI,OAAO,UAAU,YAAY;EACtC,MAAM,QAAQ,OAAO;EACrB,OAAO,OAAO,SACT,GAAG,SAAoB;GACtB,MAAM,GAAG,KAAK;GACd,AAAC,MAAmB,GAAG,KAAK;MAE9B;QACC,IAEL,UAAU,UAET,OAAO,UAAU,YAAY,UAAU,OAAO,MAE/C;MACK,IAAI,EAAE,OAAO,SAClB,OAAO,OAAO;MAEd,MAAM,IAAI,MACR,kCAAkC,IAAI,gEAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEL,SAAgB,WAA+B,GAAG,OAA0B;CAC1E,IAAI,MAAM,WAAW,GACnB,OAAO,MAAM;CAGf,OAAO,MAAM,QAAQ,QAAQ,OAA+B;EAC1D,KAAK,MAAM,OAAO,IAChB,SAAS,QAAQ,KAAK,GAAG,KAAK;EAEhC,OAAO;IACN,EAAE,CAAC"} | ||
| {"version":3,"file":"merge-props.cjs","names":[],"sources":["../../src/utils/merge-props.ts"],"sourcesContent":["/* eslint-disable quotes */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I\n) => void\n ? I\n : never;\n\nfunction pushProp(\n target: { [key: string]: any },\n key: string,\n value: unknown[]\n): void {\n if (key === \"className\") {\n target.className = [target.className, value].join(\" \").trim();\n } else if (key === \"style\") {\n target.style = { ...target.style, ...value };\n } else if (typeof value === \"function\") {\n const oldFn = target[key] as Function | undefined;\n target[key] = oldFn\n ? (...args: unknown[]) => {\n oldFn(...args);\n (value as Function)(...args);\n }\n : value;\n } else if (\n // skip merging undefined values\n value === undefined ||\n // skip if both value are the same primitive value\n (typeof value !== \"object\" && value === target[key])\n ) {\n return;\n } else if (!(key in target)) {\n target[key] = value;\n } else {\n throw new Error(\n `Didn’t know how to merge prop '${key}'. ` +\n `Only 'className', 'style', and event handlers are supported`\n );\n }\n}\n\ntype MergedProps<T extends object[]> = {\n [K in keyof UnionToIntersection<T[number]>]: K extends \"className\"\n ? string\n : K extends \"style\"\n ? UnionToIntersection<T[number]>[K]\n : Exclude<Extract<T[number], { [Q in K]: unknown }>[K], undefined>;\n};\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple props objects into a single props object with\n * predictable and React-friendly merging behavior.***\n * --------------------------------------------------------------------\n *\n * This utility is designed to safely merge component props where certain\n * keys require special handling instead of simple overwrites.\n *\n * - **Behavior:**\n * - Concatenates duplicate `className` values with a single space\n * - Shallow-merges duplicate `style` objects (later props take precedence)\n * - Chains duplicate function values (commonly event handlers),\n * executing them from left to right\n * - Skips merging `undefined` values\n * - Preserves identical primitive values without reassigning\n * - Throws an error for unsupported duplicate keys\n *\n * Later props in the argument list always have higher precedence\n * when conflicts occur.\n *\n * This makes the function especially suitable for **React / JSX props\n * composition**, such as combining props from hooks, components,\n * and user overrides.\n *\n * @typeParam T - A tuple of props object types to be merged.\n * @param props - One or more props objects. Later objects override\n * earlier ones when applicable.\n *\n * @returns A single merged props object with correctly inferred types,\n * including special handling for `className` and `style`.\n *\n * @throws {Error} If duplicate keys other than `className`, `style`,\n * or function values are encountered.\n *\n * @example\n * ```ts\n * mergeProps(\n * { className: \"btn\", onClick: () => console.log(\"a\") },\n * { className: \"btn-primary\", onClick: () => console.log(\"b\") }\n * );\n * // => {\n * // className: \"btn btn-primary\",\n * // onClick: () => { a(); b(); }\n * // }\n * ```\n *\n * @example\n * ```ts\n * mergeProps(\n * { style: { color: \"red\", fontSize: 12 } },\n * { style: { fontSize: 14 } }\n * );\n * // => { style: { color: \"red\", fontSize: 14 } }\n * ```\n */\nexport function mergeProps<T extends object[]>(...props: T): MergedProps<T> {\n if (props.length === 1) {\n return props[0] as MergedProps<T>;\n }\n\n return props.reduce((merged, ps: { [key: string]: any }) => {\n for (const key in ps) {\n pushProp(merged, key, ps[key]);\n }\n return merged;\n }, {}) as MergedProps<T>;\n}\n"],"mappings":";;;;;;;;;;;;;AASA,SAAS,SACP,QACA,KACA,OACM;CACN,IAAI,QAAQ,aACV,OAAO,YAAY,CAAC,OAAO,WAAW,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK;MACvD,IAAI,QAAQ,SACjB,OAAO,QAAQ;EAAE,GAAG,OAAO;EAAO,GAAG;CAAM;MACtC,IAAI,OAAO,UAAU,YAAY;EACtC,MAAM,QAAQ,OAAO;EACrB,OAAO,OAAO,SACT,GAAG,SAAoB;GACtB,MAAM,GAAG,IAAI;GACb,AAAC,MAAmB,GAAG,IAAI;EAC7B,IACA;CACN,OAAO,IAEL,UAAU,UAET,OAAO,UAAU,YAAY,UAAU,OAAO,MAE/C;MACK,IAAI,EAAE,OAAO,SAClB,OAAO,OAAO;MAEd,MAAM,IAAI,MACR,kCAAkC,IAAI,+DAExC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,WAA+B,GAAG,OAA0B;CAC1E,IAAI,MAAM,WAAW,GACnB,OAAO,MAAM;CAGf,OAAO,MAAM,QAAQ,QAAQ,OAA+B;EAC1D,KAAK,MAAM,OAAO,IAChB,SAAS,QAAQ,KAAK,GAAG,IAAI;EAE/B,OAAO;CACT,GAAG,CAAC,CAAC;AACP"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"merge-props.js","names":[],"sources":["../../src/utils/merge-props.ts"],"sourcesContent":["/* eslint-disable quotes */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I\n) => void\n ? I\n : never;\n\nfunction pushProp(\n target: { [key: string]: any },\n key: string,\n value: unknown[]\n): void {\n if (key === \"className\") {\n target.className = [target.className, value].join(\" \").trim();\n } else if (key === \"style\") {\n target.style = { ...target.style, ...value };\n } else if (typeof value === \"function\") {\n const oldFn = target[key] as Function | undefined;\n target[key] = oldFn\n ? (...args: unknown[]) => {\n oldFn(...args);\n (value as Function)(...args);\n }\n : value;\n } else if (\n // skip merging undefined values\n value === undefined ||\n // skip if both value are the same primitive value\n (typeof value !== \"object\" && value === target[key])\n ) {\n return;\n } else if (!(key in target)) {\n target[key] = value;\n } else {\n throw new Error(\n `Didn’t know how to merge prop '${key}'. ` +\n `Only 'className', 'style', and event handlers are supported`\n );\n }\n}\n\ntype MergedProps<T extends object[]> = {\n [K in keyof UnionToIntersection<T[number]>]: K extends \"className\"\n ? string\n : K extends \"style\"\n ? UnionToIntersection<T[number]>[K]\n : Exclude<Extract<T[number], { [Q in K]: unknown }>[K], undefined>;\n};\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple props objects into a single props object with\n * predictable and React-friendly merging behavior.***\n * --------------------------------------------------------------------\n *\n * This utility is designed to safely merge component props where certain\n * keys require special handling instead of simple overwrites.\n *\n * - **Behavior:**\n * - Concatenates duplicate `className` values with a single space\n * - Shallow-merges duplicate `style` objects (later props take precedence)\n * - Chains duplicate function values (commonly event handlers),\n * executing them from left to right\n * - Skips merging `undefined` values\n * - Preserves identical primitive values without reassigning\n * - Throws an error for unsupported duplicate keys\n *\n * Later props in the argument list always have higher precedence\n * when conflicts occur.\n *\n * This makes the function especially suitable for **React / JSX props\n * composition**, such as combining props from hooks, components,\n * and user overrides.\n *\n * @typeParam T - A tuple of props object types to be merged.\n * @param props - One or more props objects. Later objects override\n * earlier ones when applicable.\n *\n * @returns A single merged props object with correctly inferred types,\n * including special handling for `className` and `style`.\n *\n * @throws {Error} If duplicate keys other than `className`, `style`,\n * or function values are encountered.\n *\n * @example\n * ```ts\n * mergeProps(\n * { className: \"btn\", onClick: () => console.log(\"a\") },\n * { className: \"btn-primary\", onClick: () => console.log(\"b\") }\n * );\n * // => {\n * // className: \"btn btn-primary\",\n * // onClick: () => { a(); b(); }\n * // }\n * ```\n *\n * @example\n * ```ts\n * mergeProps(\n * { style: { color: \"red\", fontSize: 12 } },\n * { style: { fontSize: 14 } }\n * );\n * // => { style: { color: \"red\", fontSize: 14 } }\n * ```\n */\nexport function mergeProps<T extends object[]>(...props: T): MergedProps<T> {\n if (props.length === 1) {\n return props[0] as MergedProps<T>;\n }\n\n return props.reduce((merged, ps: { [key: string]: any }) => {\n for (const key in ps) {\n pushProp(merged, key, ps[key]);\n }\n return merged;\n }, {}) as MergedProps<T>;\n}\n"],"mappings":";;;;;;;;;;;AASA,SAAS,SACP,QACA,KACA,OACM;CACN,IAAI,QAAQ,aACV,OAAO,YAAY,CAAC,OAAO,WAAW,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM;MACxD,IAAI,QAAQ,SACjB,OAAO,QAAQ;EAAE,GAAG,OAAO;EAAO,GAAG;EAAO;MACvC,IAAI,OAAO,UAAU,YAAY;EACtC,MAAM,QAAQ,OAAO;EACrB,OAAO,OAAO,SACT,GAAG,SAAoB;GACtB,MAAM,GAAG,KAAK;GACd,AAAC,MAAmB,GAAG,KAAK;MAE9B;QACC,IAEL,UAAU,UAET,OAAO,UAAU,YAAY,UAAU,OAAO,MAE/C;MACK,IAAI,EAAE,OAAO,SAClB,OAAO,OAAO;MAEd,MAAM,IAAI,MACR,kCAAkC,IAAI,gEAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEL,SAAgB,WAA+B,GAAG,OAA0B;CAC1E,IAAI,MAAM,WAAW,GACnB,OAAO,MAAM;CAGf,OAAO,MAAM,QAAQ,QAAQ,OAA+B;EAC1D,KAAK,MAAM,OAAO,IAChB,SAAS,QAAQ,KAAK,GAAG,KAAK;EAEhC,OAAO;IACN,EAAE,CAAC"} | ||
| {"version":3,"file":"merge-props.js","names":[],"sources":["../../src/utils/merge-props.ts"],"sourcesContent":["/* eslint-disable quotes */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-function-type */\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I\n) => void\n ? I\n : never;\n\nfunction pushProp(\n target: { [key: string]: any },\n key: string,\n value: unknown[]\n): void {\n if (key === \"className\") {\n target.className = [target.className, value].join(\" \").trim();\n } else if (key === \"style\") {\n target.style = { ...target.style, ...value };\n } else if (typeof value === \"function\") {\n const oldFn = target[key] as Function | undefined;\n target[key] = oldFn\n ? (...args: unknown[]) => {\n oldFn(...args);\n (value as Function)(...args);\n }\n : value;\n } else if (\n // skip merging undefined values\n value === undefined ||\n // skip if both value are the same primitive value\n (typeof value !== \"object\" && value === target[key])\n ) {\n return;\n } else if (!(key in target)) {\n target[key] = value;\n } else {\n throw new Error(\n `Didn’t know how to merge prop '${key}'. ` +\n `Only 'className', 'style', and event handlers are supported`\n );\n }\n}\n\ntype MergedProps<T extends object[]> = {\n [K in keyof UnionToIntersection<T[number]>]: K extends \"className\"\n ? string\n : K extends \"style\"\n ? UnionToIntersection<T[number]>[K]\n : Exclude<Extract<T[number], { [Q in K]: unknown }>[K], undefined>;\n};\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple props objects into a single props object with\n * predictable and React-friendly merging behavior.***\n * --------------------------------------------------------------------\n *\n * This utility is designed to safely merge component props where certain\n * keys require special handling instead of simple overwrites.\n *\n * - **Behavior:**\n * - Concatenates duplicate `className` values with a single space\n * - Shallow-merges duplicate `style` objects (later props take precedence)\n * - Chains duplicate function values (commonly event handlers),\n * executing them from left to right\n * - Skips merging `undefined` values\n * - Preserves identical primitive values without reassigning\n * - Throws an error for unsupported duplicate keys\n *\n * Later props in the argument list always have higher precedence\n * when conflicts occur.\n *\n * This makes the function especially suitable for **React / JSX props\n * composition**, such as combining props from hooks, components,\n * and user overrides.\n *\n * @typeParam T - A tuple of props object types to be merged.\n * @param props - One or more props objects. Later objects override\n * earlier ones when applicable.\n *\n * @returns A single merged props object with correctly inferred types,\n * including special handling for `className` and `style`.\n *\n * @throws {Error} If duplicate keys other than `className`, `style`,\n * or function values are encountered.\n *\n * @example\n * ```ts\n * mergeProps(\n * { className: \"btn\", onClick: () => console.log(\"a\") },\n * { className: \"btn-primary\", onClick: () => console.log(\"b\") }\n * );\n * // => {\n * // className: \"btn btn-primary\",\n * // onClick: () => { a(); b(); }\n * // }\n * ```\n *\n * @example\n * ```ts\n * mergeProps(\n * { style: { color: \"red\", fontSize: 12 } },\n * { style: { fontSize: 14 } }\n * );\n * // => { style: { color: \"red\", fontSize: 14 } }\n * ```\n */\nexport function mergeProps<T extends object[]>(...props: T): MergedProps<T> {\n if (props.length === 1) {\n return props[0] as MergedProps<T>;\n }\n\n return props.reduce((merged, ps: { [key: string]: any }) => {\n for (const key in ps) {\n pushProp(merged, key, ps[key]);\n }\n return merged;\n }, {}) as MergedProps<T>;\n}\n"],"mappings":";;;;;;;;;;;AASA,SAAS,SACP,QACA,KACA,OACM;CACN,IAAI,QAAQ,aACV,OAAO,YAAY,CAAC,OAAO,WAAW,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK;MACvD,IAAI,QAAQ,SACjB,OAAO,QAAQ;EAAE,GAAG,OAAO;EAAO,GAAG;CAAM;MACtC,IAAI,OAAO,UAAU,YAAY;EACtC,MAAM,QAAQ,OAAO;EACrB,OAAO,OAAO,SACT,GAAG,SAAoB;GACtB,MAAM,GAAG,IAAI;GACb,AAAC,MAAmB,GAAG,IAAI;EAC7B,IACA;CACN,OAAO,IAEL,UAAU,UAET,OAAO,UAAU,YAAY,UAAU,OAAO,MAE/C;MACK,IAAI,EAAE,OAAO,SAClB,OAAO,OAAO;MAEd,MAAM,IAAI,MACR,kCAAkC,IAAI,+DAExC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,WAA+B,GAAG,OAA0B;CAC1E,IAAI,MAAM,WAAW,GACnB,OAAO,MAAM;CAGf,OAAO,MAAM,QAAQ,QAAQ,OAA+B;EAC1D,KAAK,MAAM,OAAO,IAChB,SAAS,QAAQ,KAAK,GAAG,IAAI;EAE/B,OAAO;CACT,GAAG,CAAC,CAAC;AACP"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -13,3 +13,2 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_chunk = require('../chunk-DZH3KJL-.cjs'); | ||
| let _rzl_zone_utils_js_predicates = require("@rzl-zone/utils-js/predicates"); | ||
@@ -16,0 +15,0 @@ let react = require("react"); |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"merge-refs.cjs","names":[],"sources":["../../src/utils/merge-refs.ts"],"sourcesContent":["import { type Ref, type RefCallback } from \"react\";\nimport { isFunction } from \"@rzl-zone/utils-js/predicates\";\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple React refs into a single ref callback,\n * allowing them to be assigned simultaneously.***\n * --------------------------------------------------------------------\n *\n * This utility enables safe composition of refs when multiple components,\n * hooks, or consumers need access to the same underlying DOM element\n * or component instance.\n *\n * It supports both:\n * - **Callback refs**\n * - **Mutable object refs** (`RefObject`)\n *\n * - **Behavior:**\n * - Invokes all function refs with the provided value\n * - Assigns the value to `.current` for object refs\n * - Safely ignores `undefined` refs\n * - Preserves invocation order from left to right\n *\n * This is especially useful in **React** when combining forwarded refs\n * with internal refs.\n *\n * @typeParam T - The type of the ref value (e.g. `HTMLDivElement`).\n * @param refs - A list of refs to merge. Each ref may be a callback,\n * a ref object, or `undefined`.\n *\n * @returns A single `RefCallback` that updates all provided refs.\n *\n * @example\n * ```tsx\n * const localRef = useRef<HTMLDivElement>(null);\n *\n * function Component(props: { ref?: Ref<HTMLDivElement> }) {\n * return (\n * <div ref={mergeRefs(localRef, props.ref)} />\n * );\n * }\n * ```\n */\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> {\n return (value) => {\n refs.forEach((ref) => {\n if (isFunction(ref)) {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n });\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,UAAa,GAAG,MAA8C;CAC5E,QAAQ,UAAU;EAChB,KAAK,SAAS,QAAQ;GACpB,kDAAe,IAAI,EACjB,IAAI,MAAM;QACL,IAAI,KACT,IAAI,UAAU;IAEhB"} | ||
| {"version":3,"file":"merge-refs.cjs","names":[],"sources":["../../src/utils/merge-refs.ts"],"sourcesContent":["import { type Ref, type RefCallback } from \"react\";\nimport { isFunction } from \"@rzl-zone/utils-js/predicates\";\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple React refs into a single ref callback,\n * allowing them to be assigned simultaneously.***\n * --------------------------------------------------------------------\n *\n * This utility enables safe composition of refs when multiple components,\n * hooks, or consumers need access to the same underlying DOM element\n * or component instance.\n *\n * It supports both:\n * - **Callback refs**\n * - **Mutable object refs** (`RefObject`)\n *\n * - **Behavior:**\n * - Invokes all function refs with the provided value\n * - Assigns the value to `.current` for object refs\n * - Safely ignores `undefined` refs\n * - Preserves invocation order from left to right\n *\n * This is especially useful in **React** when combining forwarded refs\n * with internal refs.\n *\n * @typeParam T - The type of the ref value (e.g. `HTMLDivElement`).\n * @param refs - A list of refs to merge. Each ref may be a callback,\n * a ref object, or `undefined`.\n *\n * @returns A single `RefCallback` that updates all provided refs.\n *\n * @example\n * ```tsx\n * const localRef = useRef<HTMLDivElement>(null);\n *\n * function Component(props: { ref?: Ref<HTMLDivElement> }) {\n * return (\n * <div ref={mergeRefs(localRef, props.ref)} />\n * );\n * }\n * ```\n */\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> {\n return (value) => {\n refs.forEach((ref) => {\n if (isFunction(ref)) {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n });\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,UAAa,GAAG,MAA8C;CAC5E,QAAQ,UAAU;EAChB,KAAK,SAAS,QAAQ;GACpB,kDAAe,GAAG,GAChB,IAAI,KAAK;QACJ,IAAI,KACT,IAAI,UAAU;EAElB,CAAC;CACH;AACF"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"merge-refs.js","names":[],"sources":["../../src/utils/merge-refs.ts"],"sourcesContent":["import { type Ref, type RefCallback } from \"react\";\nimport { isFunction } from \"@rzl-zone/utils-js/predicates\";\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple React refs into a single ref callback,\n * allowing them to be assigned simultaneously.***\n * --------------------------------------------------------------------\n *\n * This utility enables safe composition of refs when multiple components,\n * hooks, or consumers need access to the same underlying DOM element\n * or component instance.\n *\n * It supports both:\n * - **Callback refs**\n * - **Mutable object refs** (`RefObject`)\n *\n * - **Behavior:**\n * - Invokes all function refs with the provided value\n * - Assigns the value to `.current` for object refs\n * - Safely ignores `undefined` refs\n * - Preserves invocation order from left to right\n *\n * This is especially useful in **React** when combining forwarded refs\n * with internal refs.\n *\n * @typeParam T - The type of the ref value (e.g. `HTMLDivElement`).\n * @param refs - A list of refs to merge. Each ref may be a callback,\n * a ref object, or `undefined`.\n *\n * @returns A single `RefCallback` that updates all provided refs.\n *\n * @example\n * ```tsx\n * const localRef = useRef<HTMLDivElement>(null);\n *\n * function Component(props: { ref?: Ref<HTMLDivElement> }) {\n * return (\n * <div ref={mergeRefs(localRef, props.ref)} />\n * );\n * }\n * ```\n */\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> {\n return (value) => {\n refs.forEach((ref) => {\n if (isFunction(ref)) {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n });\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,UAAa,GAAG,MAA8C;CAC5E,QAAQ,UAAU;EAChB,KAAK,SAAS,QAAQ;GACpB,IAAI,WAAW,IAAI,EACjB,IAAI,MAAM;QACL,IAAI,KACT,IAAI,UAAU;IAEhB"} | ||
| {"version":3,"file":"merge-refs.js","names":[],"sources":["../../src/utils/merge-refs.ts"],"sourcesContent":["import { type Ref, type RefCallback } from \"react\";\nimport { isFunction } from \"@rzl-zone/utils-js/predicates\";\n\n/** -------------------------------------------------------------------\n * * ***Merges multiple React refs into a single ref callback,\n * allowing them to be assigned simultaneously.***\n * --------------------------------------------------------------------\n *\n * This utility enables safe composition of refs when multiple components,\n * hooks, or consumers need access to the same underlying DOM element\n * or component instance.\n *\n * It supports both:\n * - **Callback refs**\n * - **Mutable object refs** (`RefObject`)\n *\n * - **Behavior:**\n * - Invokes all function refs with the provided value\n * - Assigns the value to `.current` for object refs\n * - Safely ignores `undefined` refs\n * - Preserves invocation order from left to right\n *\n * This is especially useful in **React** when combining forwarded refs\n * with internal refs.\n *\n * @typeParam T - The type of the ref value (e.g. `HTMLDivElement`).\n * @param refs - A list of refs to merge. Each ref may be a callback,\n * a ref object, or `undefined`.\n *\n * @returns A single `RefCallback` that updates all provided refs.\n *\n * @example\n * ```tsx\n * const localRef = useRef<HTMLDivElement>(null);\n *\n * function Component(props: { ref?: Ref<HTMLDivElement> }) {\n * return (\n * <div ref={mergeRefs(localRef, props.ref)} />\n * );\n * }\n * ```\n */\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> {\n return (value) => {\n refs.forEach((ref) => {\n if (isFunction(ref)) {\n ref(value);\n } else if (ref) {\n ref.current = value;\n }\n });\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,UAAa,GAAG,MAA8C;CAC5E,QAAQ,UAAU;EAChB,KAAK,SAAS,QAAQ;GACpB,IAAI,WAAW,GAAG,GAChB,IAAI,KAAK;QACJ,IAAI,KACT,IAAI,UAAU;EAElB,CAAC;CACH;AACF"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -13,3 +13,2 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| const require_chunk = require('../chunk-DZH3KJL-.cjs'); | ||
| let react = require("react"); | ||
@@ -16,0 +15,0 @@ const PORTAL_KEY = "$$typeof"; |
@@ -1,1 +0,1 @@ | ||
| {"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,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DpD,SAAgB,YAAY,OAAoC;CAC9D,OAAO,gBAAgB,uBAAO,IAAI,SAAS,CAAC;;;AAI9C,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;;CAIJ,8BAAmB,MAAM,EAAE,OAAO;CAElC,MAAM,MAAM;CAGZ,IAAI,MAAM,IAAI,IAAI,EAAE,OAAO;CAC3B,MAAM,IAAI,IAAI;CAGd,IAAI,MAAM,gBAAgB,mBAAmB,OAAO;CAGpD,IACE,iBAAiB,QACjB,iBAAiB,UACjB,iBAAiB,WACjB,iBAAiB,OACjB,iBAAiB,WACjB,iBAAiB,SAEjB,OAAO;CAIT,IAAI,MAAM,QAAQ,MAAM,EAAE;EACxB,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,gBAAgB,MAAM,MAAM,EAAE,OAAO;EAE5C,OAAO;;CAOT,IAAI,OAHc,QAChB,OAAO,cAEe,YACtB,IAAI;EACF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,gBAAgB,MAAM,MAAM,EAAE,OAAO;EAE5C,OAAO;SACD;EACN,OAAO;;CAIX,OAAO"} | ||
| {"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"} |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -5,3 +5,3 @@ /*! | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Version: `0.0.11-beta.0` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
@@ -8,0 +8,0 @@ * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"react-node.js","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,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DpD,SAAgB,YAAY,OAAoC;CAC9D,OAAO,gBAAgB,uBAAO,IAAI,SAAS,CAAC;;;AAI9C,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;;CAIJ,IAAI,eAAe,MAAM,EAAE,OAAO;CAElC,MAAM,MAAM;CAGZ,IAAI,MAAM,IAAI,IAAI,EAAE,OAAO;CAC3B,MAAM,IAAI,IAAI;CAGd,IAAI,MAAM,gBAAgB,mBAAmB,OAAO;CAGpD,IACE,iBAAiB,QACjB,iBAAiB,UACjB,iBAAiB,WACjB,iBAAiB,OACjB,iBAAiB,WACjB,iBAAiB,SAEjB,OAAO;CAIT,IAAI,MAAM,QAAQ,MAAM,EAAE;EACxB,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,gBAAgB,MAAM,MAAM,EAAE,OAAO;EAE5C,OAAO;;CAOT,IAAI,OAHc,QAChB,OAAO,cAEe,YACtB,IAAI;EACF,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,gBAAgB,MAAM,MAAM,EAAE,OAAO;EAE5C,OAAO;SACD;EACN,OAAO;;CAIX,OAAO"} | ||
| {"version":3,"file":"react-node.js","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,IAAI,eAAe,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"} |
+3
-3
| { | ||
| "name": "@rzl-zone/core-react", | ||
| "version": "0.0.10", | ||
| "version": "0.0.11-beta.0", | ||
| "description": "Modern React core utilities and primitives.", | ||
@@ -98,5 +98,5 @@ "license": "MIT", | ||
| "dependencies": { | ||
| "@rzl-zone/core": "0.0.10", | ||
| "@rzl-zone/core": "0.0.11-beta.0", | ||
| "@rzl-zone/node-only": "0.0.10", | ||
| "@rzl-zone/utils-js": "3.13.0" | ||
| "@rzl-zone/utils-js": "3.13.1-beta.0" | ||
| }, | ||
@@ -103,0 +103,0 @@ "devDependencies": { |
| /*! | ||
| * ======================================================================== | ||
| * @rzl-zone/core-react | ||
| * ------------------------------------------------------------------------ | ||
| * Version: `0.0.10` | ||
| * Author: `Rizalvin Dwiky <rizalvindwiky1998@gmail.com>` | ||
| * Repository: `https://github.com/rzl-zone/rzl-zone/tree/main/packages/core-react` | ||
| * ======================================================================== | ||
| */ | ||
| "use strict"; | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { | ||
| key = keys[i]; | ||
| if (!__hasOwnProp.call(to, key) && key !== except) { | ||
| __defProp(to, key, { | ||
| get: ((k) => from[k]).bind(null, key), | ||
| enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { | ||
| value: mod, | ||
| enumerable: true | ||
| }) : target, mod)); | ||
| Object.defineProperty(exports, '__toESM', { | ||
| enumerable: true, | ||
| get: function () { | ||
| return __toESM; | ||
| } | ||
| }); |
180798
0.21%1535
-0.26%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated