@rzl-zone/utils-js 3.12.1-beta.1 → 3.13.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -32
- package/dist/.references/index.d.cts +1 -3
- package/dist/.references/index.d.ts +1 -3
- package/dist/{assertIsArray-bTA3XLjq.js → assertIsArray-C2rkhR9M.js} +3 -3
- package/dist/{assertIsArray-bTA3XLjq.js.map → assertIsArray-C2rkhR9M.js.map} +1 -1
- package/dist/{assertIsArray-DJXkjHZs.cjs → assertIsArray-DWsgvahU.cjs} +3 -3
- package/dist/{assertIsArray-DJXkjHZs.cjs.map → assertIsArray-DWsgvahU.cjs.map} +1 -1
- package/dist/{assertIsBoolean-C8WEXVr2.cjs → assertIsBoolean-BKcvET7Z.cjs} +2 -2
- package/dist/{assertIsBoolean-C8WEXVr2.cjs.map → assertIsBoolean-BKcvET7Z.cjs.map} +1 -1
- package/dist/{assertIsBoolean-DR1SaXPD.js → assertIsBoolean-Clc7Vw4v.js} +2 -2
- package/dist/{assertIsBoolean-DR1SaXPD.js.map → assertIsBoolean-Clc7Vw4v.js.map} +1 -1
- package/dist/{assertIsString-CEB07_83.js → assertIsString-Ddz4y81W.js} +3 -3
- package/dist/{assertIsString-CEB07_83.js.map → assertIsString-Ddz4y81W.js.map} +1 -1
- package/dist/{assertIsString-BiHQSrB2.cjs → assertIsString-DxIqUfF1.cjs} +3 -3
- package/dist/{assertIsString-BiHQSrB2.cjs.map → assertIsString-DxIqUfF1.cjs.map} +1 -1
- package/dist/assertions/index.cjs +5 -5
- package/dist/assertions/index.d.cts +2 -2
- package/dist/assertions/index.d.ts +2 -2
- package/dist/assertions/index.js +5 -5
- package/dist/conversions/index.cjs +6 -6
- package/dist/conversions/index.d.cts +2 -2
- package/dist/conversions/index.d.ts +2 -2
- package/dist/conversions/index.js +6 -6
- package/dist/{conversions-D_Kh0a_C.cjs → conversions-Bu5c_RZ9.cjs} +12 -12
- package/dist/{conversions-D_Kh0a_C.cjs.map → conversions-Bu5c_RZ9.cjs.map} +1 -1
- package/dist/{conversions-BNIh_tCH.js → conversions-DjfhrQE9.js} +12 -12
- package/dist/{conversions-BNIh_tCH.js.map → conversions-DjfhrQE9.js.map} +1 -1
- package/dist/events/index.cjs +4 -4
- package/dist/events/index.d.cts +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +4 -4
- package/dist/formatters/index.cjs +2 -2
- package/dist/formatters/index.d.cts +2 -2
- package/dist/formatters/index.d.ts +2 -2
- package/dist/formatters/index.js +2 -2
- package/dist/{formatters--1m_vpE8.js → formatters-CidRTj87.js} +10 -10
- package/dist/{formatters--1m_vpE8.js.map → formatters-CidRTj87.js.map} +1 -1
- package/dist/{formatters-Cbij0XLU.cjs → formatters-DF4887ia.cjs} +10 -10
- package/dist/{formatters-Cbij0XLU.cjs.map → formatters-DF4887ia.cjs.map} +1 -1
- package/dist/generators/index.cjs +5 -5
- package/dist/generators/index.d.cts +2 -2
- package/dist/generators/index.d.ts +2 -2
- package/dist/generators/index.js +5 -5
- package/dist/{index-UPp94Agr.d.ts → index-BK86Fnvd.d.ts} +2 -2
- package/dist/{index-B6tawc8L.d.cts → index-BZMwAuLf.d.ts} +1 -1
- package/dist/{index-CeBC2Vvl.d.cts → index-BbCX319b.d.cts} +2 -2
- package/dist/{index-CgRDTI6f.d.ts → index-C02XatNH.d.ts} +2 -2
- package/dist/{index-59zbLcPr.d.ts → index-CHwf6vUh.d.ts} +1 -1
- package/dist/{index-gBA_8SuF.d.cts → index-CIBhF2hQ.d.cts} +1 -1
- package/dist/{index-jyDqzicx.d.cts → index-CWgiyaU3.d.cts} +2 -2
- package/dist/{index-D4fcasfZ.d.cts → index-CX8gCrW8.d.ts} +241 -14
- package/dist/{index-Hg1qJkjl.d.ts → index-CyZz4BHD.d.cts} +1 -1
- package/dist/{index-CoiUBVmr.d.ts → index-Cyu3Mh3N.d.cts} +241 -14
- package/dist/{index-DDrSQKIc.d.ts → index-DC7eXTo_.d.cts} +1 -1
- package/dist/{index-DsGxO31H.d.cts → index-DPBypj6v.d.ts} +1 -1
- package/dist/{index-C267akkJ.d.ts → index-Dq5vUFfH.d.ts} +1 -1
- package/dist/{index-Qm3iFwd0.d.cts → index-YeyLvCAr.d.cts} +1 -1
- package/dist/{isBigInt-C4krUeAw.cjs → isBigInt-BePsmNsm.cjs} +2 -2
- package/dist/{isBigInt-C4krUeAw.cjs.map → isBigInt-BePsmNsm.cjs.map} +1 -1
- package/dist/{isBigInt-DKe0M6hp.js → isBigInt-Cx4j_cju.js} +2 -2
- package/dist/{isBigInt-DKe0M6hp.js.map → isBigInt-Cx4j_cju.js.map} +1 -1
- package/dist/{isEmptyObject-ZkSwRC_D.cjs → isEmptyObject-DYypq92-.cjs} +3 -3
- package/dist/{isEmptyObject-ZkSwRC_D.cjs.map → isEmptyObject-DYypq92-.cjs.map} +1 -1
- package/dist/{isEmptyObject-DCipFwxJ.js → isEmptyObject-Dp4pCGTa.js} +3 -3
- package/dist/{isEmptyObject-DCipFwxJ.js.map → isEmptyObject-Dp4pCGTa.js.map} +1 -1
- package/dist/{isEmptyString-BXzKAC2j.js → isEmptyString-BXgKFQxw.js} +3 -3
- package/dist/{isEmptyString-BXzKAC2j.js.map → isEmptyString-BXgKFQxw.js.map} +1 -1
- package/dist/{isEmptyString-UiiUsSQj.cjs → isEmptyString-CzY-9G-x.cjs} +3 -3
- package/dist/{isEmptyString-UiiUsSQj.cjs.map → isEmptyString-CzY-9G-x.cjs.map} +1 -1
- package/dist/{isEmptyValue-jqOr7OHD.js → isEmptyValue-B7Zd9DI3.js} +5 -5
- package/dist/{isEmptyValue-jqOr7OHD.js.map → isEmptyValue-B7Zd9DI3.js.map} +1 -1
- package/dist/{isEmptyValue-BQzcjVaL.cjs → isEmptyValue-Ci3kVU4E.cjs} +5 -5
- package/dist/{isEmptyValue-BQzcjVaL.cjs.map → isEmptyValue-Ci3kVU4E.cjs.map} +1 -1
- package/dist/{isEqual-BvumA3RA.cjs → isEqual-Bd7mClU4.cjs} +4 -4
- package/dist/{isEqual-BvumA3RA.cjs.map → isEqual-Bd7mClU4.cjs.map} +1 -1
- package/dist/{isEqual-BX49cF9m.js → isEqual-CylDBGUr.js} +4 -4
- package/dist/{isEqual-BX49cF9m.js.map → isEqual-CylDBGUr.js.map} +1 -1
- package/dist/{isFinite-BCnaDpod.js → isFinite-CZ-Aiy4T.js} +3 -3
- package/dist/{isFinite-BCnaDpod.js.map → isFinite-CZ-Aiy4T.js.map} +1 -1
- package/dist/{isFinite-D24ZaE6c.cjs → isFinite-D8jhlqPf.cjs} +3 -3
- package/dist/{isFinite-D24ZaE6c.cjs.map → isFinite-D8jhlqPf.cjs.map} +1 -1
- package/dist/{isInteger-Caeuz0rB.cjs → isInteger-CCJhQ1Mx.cjs} +2 -2
- package/dist/{isInteger-Caeuz0rB.cjs.map → isInteger-CCJhQ1Mx.cjs.map} +1 -1
- package/dist/{isInteger-naMbJsxJ.js → isInteger-DK_0nvNU.js} +2 -2
- package/dist/{isInteger-naMbJsxJ.js.map → isInteger-DK_0nvNU.js.map} +1 -1
- package/dist/{isPlainObject-BF-2-phb.d.cts → isPlainObject-BGg8uHeL.d.cts} +1 -1
- package/dist/{isPlainObject-DxNDL8XU.d.ts → isPlainObject-DtduwtUp.d.ts} +1 -1
- package/dist/{isServer-Da3o3XSs.js → isServer-C2YtJlD1.js} +2 -2
- package/dist/{isServer-Da3o3XSs.js.map → isServer-C2YtJlD1.js.map} +1 -1
- package/dist/{isServer-BJHVnixd.cjs → isServer-CT9EkFKG.cjs} +2 -2
- package/dist/{isServer-BJHVnixd.cjs.map → isServer-CT9EkFKG.cjs.map} +1 -1
- package/dist/{isTypedArray-TJptiw2b.cjs → isTypedArray-BT7YP1S9.cjs} +3 -3
- package/dist/{isTypedArray-TJptiw2b.cjs.map → isTypedArray-BT7YP1S9.cjs.map} +1 -1
- package/dist/{isTypedArray-DuNA8tK6.js → isTypedArray-hcngU0pK.js} +3 -3
- package/dist/{isTypedArray-DuNA8tK6.js.map → isTypedArray-hcngU0pK.js.map} +1 -1
- package/dist/{isValidDomain-DoE98yhJ.js → isValidDomain-BCN5-tj9.js} +9 -6
- package/dist/isValidDomain-BCN5-tj9.js.map +1 -0
- package/dist/{isValidDomain-BB9IGhJs.cjs → isValidDomain-CXWNcRo6.cjs} +14 -5
- package/dist/isValidDomain-CXWNcRo6.cjs.map +1 -0
- package/dist/{noop-ubqAIbHD.js → noop-BDfC9Zq4.js} +2 -2
- package/dist/{noop-ubqAIbHD.js.map → noop-BDfC9Zq4.js.map} +1 -1
- package/dist/{noop-B13_ii35.cjs → noop-D4tT7tWN.cjs} +2 -2
- package/dist/{noop-B13_ii35.cjs.map → noop-D4tT7tWN.cjs.map} +1 -1
- package/dist/{normalizeSpaces-Bg2IZW7W.js → normalizeSpaces-B289eKyK.js} +3 -3
- package/dist/{normalizeSpaces-Bg2IZW7W.js.map → normalizeSpaces-B289eKyK.js.map} +1 -1
- package/dist/{normalizeSpaces-ZXnR4Qzp.cjs → normalizeSpaces-BTXDP8vZ.cjs} +3 -3
- package/dist/{normalizeSpaces-ZXnR4Qzp.cjs.map → normalizeSpaces-BTXDP8vZ.cjs.map} +1 -1
- package/dist/operations/index.cjs +7 -7
- package/dist/operations/index.d.cts +1 -1
- package/dist/operations/index.d.ts +1 -1
- package/dist/operations/index.js +7 -7
- package/dist/parsers/index.cjs +2 -2
- package/dist/parsers/index.d.cts +1 -1
- package/dist/parsers/index.d.ts +1 -1
- package/dist/parsers/index.js +2 -2
- package/dist/{parsers-OqDeffqc.cjs → parsers-5G1Lface.cjs} +4 -4
- package/dist/{parsers-OqDeffqc.cjs.map → parsers-5G1Lface.cjs.map} +1 -1
- package/dist/{parsers-BSBPgvsq.js → parsers-CNag9LsX.js} +4 -4
- package/dist/{parsers-BSBPgvsq.js.map → parsers-CNag9LsX.js.map} +1 -1
- package/dist/{parsing-DOGSCH6N.cjs → parsing-B6vxp2h8.cjs} +3 -3
- package/dist/{parsing-DOGSCH6N.cjs.map → parsing-B6vxp2h8.cjs.map} +1 -1
- package/dist/{parsing-Cao8b358.js → parsing-CobzHooQ.js} +3 -3
- package/dist/{parsing-Cao8b358.js.map → parsing-CobzHooQ.js.map} +1 -1
- package/dist/predicates/index.cjs +15 -16
- package/dist/predicates/index.d.cts +3 -3
- package/dist/predicates/index.d.ts +3 -3
- package/dist/predicates/index.js +14 -15
- package/dist/{predicates-D0ubqgqy.cjs → predicates-DlID4Pks.cjs} +13 -13
- package/dist/{predicates-D0ubqgqy.cjs.map → predicates-DlID4Pks.cjs.map} +1 -1
- package/dist/{predicates-Bj6meyXV.js → predicates-DvLryz_b.js} +11 -11
- package/dist/{predicates-Bj6meyXV.js.map → predicates-DvLryz_b.js.map} +1 -1
- package/dist/promises/index.cjs +4 -4
- package/dist/promises/index.d.cts +1 -1
- package/dist/promises/index.d.ts +1 -1
- package/dist/promises/index.js +4 -4
- package/dist/{punyCode-D-Qu6nj6.cjs → punyCode-DaBFrfga.cjs} +4 -4
- package/dist/{punyCode-D-Qu6nj6.cjs.map → punyCode-DaBFrfga.cjs.map} +1 -1
- package/dist/{punyCode-8SrbMWfM.js → punyCode-GakZYPCT.js} +4 -4
- package/dist/{punyCode-8SrbMWfM.js.map → punyCode-GakZYPCT.js.map} +1 -1
- package/dist/{removeSpaces-Bmc5DX4F.js → removeSpaces-BJ-zNnJq.js} +7 -4
- package/dist/removeSpaces-BJ-zNnJq.js.map +1 -0
- package/dist/{removeSpaces-CWIvhZHg.cjs → removeSpaces-DhJ1haaH.cjs} +12 -3
- package/dist/removeSpaces-DhJ1haaH.cjs.map +1 -0
- package/dist/rzl-utils.global.js +1 -1
- package/dist/{safeJsonParse-Sms2CJf4.cjs → safeJsonParse-DiWBPfaE.cjs} +6 -6
- package/dist/{safeJsonParse-Sms2CJf4.cjs.map → safeJsonParse-DiWBPfaE.cjs.map} +1 -1
- package/dist/{safeJsonParse-BP38mwlj.js → safeJsonParse-bcBYPjeb.js} +6 -6
- package/dist/{safeJsonParse-BP38mwlj.js.map → safeJsonParse-bcBYPjeb.js.map} +1 -1
- package/dist/{safeStableStringify-CXOZ9Ub8.js → safeStableStringify-C1SA52w7.js} +4 -4
- package/dist/{safeStableStringify-CXOZ9Ub8.js.map → safeStableStringify-C1SA52w7.js.map} +1 -1
- package/dist/{safeStableStringify-CJtP89qn.cjs → safeStableStringify-DSwcrPll.cjs} +4 -4
- package/dist/{safeStableStringify-CJtP89qn.cjs.map → safeStableStringify-DSwcrPll.cjs.map} +1 -1
- package/dist/strings/index.cjs +6 -7
- package/dist/strings/index.cjs.map +1 -1
- package/dist/strings/index.d.cts +2 -2
- package/dist/strings/index.d.ts +2 -2
- package/dist/strings/index.js +5 -6
- package/dist/strings/index.js.map +1 -1
- package/dist/tailwind/index.cjs +6 -2
- package/dist/tailwind/index.d.cts +3 -3
- package/dist/tailwind/index.d.ts +3 -3
- package/dist/tailwind/index.js +3 -3
- package/dist/{tailwind-B2ssevxq.js → tailwind-D62asDBR.js} +18 -8
- package/dist/tailwind-D62asDBR.js.map +1 -0
- package/dist/{tailwind-CHIx9uxu.cjs → tailwind-DMPTwJ0X.cjs} +39 -5
- package/dist/tailwind-DMPTwJ0X.cjs.map +1 -0
- package/dist/{toStringArrayUnRecursive-DJGtPsFb.js → toStringArrayUnRecursive-DBicbWv8.js} +6 -6
- package/dist/{toStringArrayUnRecursive-DJGtPsFb.js.map → toStringArrayUnRecursive-DBicbWv8.js.map} +1 -1
- package/dist/{toStringArrayUnRecursive-C4zYCja7.cjs → toStringArrayUnRecursive-DJ8JBO3N.cjs} +6 -6
- package/dist/{toStringArrayUnRecursive-C4zYCja7.cjs.map → toStringArrayUnRecursive-DJ8JBO3N.cjs.map} +1 -1
- package/dist/urls/index.cjs +9 -120
- package/dist/urls/index.d.cts +1 -1
- package/dist/urls/index.d.ts +1 -1
- package/dist/urls/index.js +3 -114
- package/dist/urls-DCjjZNTH.cjs +299 -0
- package/dist/urls-DCjjZNTH.cjs.map +1 -0
- package/dist/urls-DTndjYDD.js +263 -0
- package/dist/urls-DTndjYDD.js.map +1 -0
- package/package.json +3 -24
- package/dist/formatEnvPort-B3OLxQk9.cjs +0 -171
- package/dist/formatEnvPort-B3OLxQk9.cjs.map +0 -1
- package/dist/formatEnvPort-ByFVLjSV.js +0 -159
- package/dist/formatEnvPort-ByFVLjSV.js.map +0 -1
- package/dist/isURL-C-kSk6KJ.js +0 -14
- package/dist/isURL-C-kSk6KJ.js.map +0 -1
- package/dist/isURL-DeUPO_oR.cjs +0 -20
- package/dist/isURL-DeUPO_oR.cjs.map +0 -1
- package/dist/isValidDomain-BB9IGhJs.cjs.map +0 -1
- package/dist/isValidDomain-DoE98yhJ.js.map +0 -1
- package/dist/next/index.cjs +0 -129
- package/dist/next/index.cjs.map +0 -1
- package/dist/next/index.d.cts +0 -220
- package/dist/next/index.d.ts +0 -220
- package/dist/next/index.js +0 -124
- package/dist/next/index.js.map +0 -1
- package/dist/next/server/index.cjs +0 -28
- package/dist/next/server/index.cjs.map +0 -1
- package/dist/next/server/index.d.cts +0 -39
- package/dist/next/server/index.d.ts +0 -39
- package/dist/next/server/index.js +0 -26
- package/dist/next/server/index.js.map +0 -1
- package/dist/normalizeString-BDdkaXui.js +0 -15
- package/dist/normalizeString-BDdkaXui.js.map +0 -1
- package/dist/normalizeString-BE6ELqEb.cjs +0 -21
- package/dist/normalizeString-BE6ELqEb.cjs.map +0 -1
- package/dist/removeSpaces-Bmc5DX4F.js.map +0 -1
- package/dist/removeSpaces-CWIvhZHg.cjs.map +0 -1
- package/dist/tailwind-B2ssevxq.js.map +0 -1
- package/dist/tailwind-CHIx9uxu.cjs.map +0 -1
- package/dist/urls/index.cjs.map +0 -1
- package/dist/urls/index.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tailwind-CHIx9uxu.cjs","names":["isNonEmptyString","isNumber","isObjectOrArray","isStringObject","isNumberObject","isBooleanObject","isArray","isPlainObject","isNumber","isNonEmptyString","isFunction","hasOwnProp","isNonEmptyArray","defaultConfig","isPlainObject","isPlainObject","isFunction","getPreciseType","isString","getPreciseType","isEmptyString","isNonEmptyArray"],"sources":["../src/tailwind/class-names/cx.ts","../src/tailwind/tw-merge/_private/validate-props.ts","../src/tailwind/tw-merge/v3/twMergeDefault.ts","../src/tailwind/tw-merge/v4/twMergeDefault.ts","../src/tailwind/class-names/customCn.ts","../src/tailwind/class-names/cn.ts","../src/tailwind/tw-macro/shouldForwardProp.ts"],"sourcesContent":["import { isArray } from \"@/predicates/is/isArray\";\nimport { isNumber } from \"@/predicates/is/isNumber\";\nimport { isStringObject } from \"@/predicates/is/isStringObject\";\nimport { isNumberObject } from \"@/predicates/is/isNumberObject\";\nimport { isBooleanObject } from \"@/predicates/is/isBooleanObject\";\nimport { isObjectOrArray } from \"@/predicates/is/isObjectOrArray\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** ----------------------------------------------------------\n * * ***Type-Utility: `ClassValue`.***\n * ----------------------------------------------------------\n * **Represents a single valid value that can be converted to a CSS class string.**\n * @description\n * - Supports the following types:\n * - `string` → literal class names (non-empty only)\n * - `number | bigint` → numeric class names\n * - `boolean` → only `true` is considered in objects/arrays\n * - `null | undefined` → ignored\n * - `ClassObject` → objects where **keys with truthy values** are included\n * - `ClassValues` → arrays recursively flattened\n * - Used internally by ***`cx` utility function*** to process mixed input values.\n * @example\n * ```ts\n * const val1: ClassValue = \"button\"; // ➔ string\n * const val2: ClassValue = 0; // ➔ number\n * const val3: ClassValue = [\"a\", { b: true }]; // ➔ array with object\n * const val4: ClassValue = { d: true, e: false }; // ➔ object\n * const val5: ClassValue = new String(\"foo\"); // ➔ boxed string\n * const val6: ClassValue = new Number(\"123\"); // ➔ boxed number\n * const val7: ClassValue = new Boolean(\"true\"); // ➔ boxed boolean\n * ```\n */\nexport type ClassValue =\n | ClassValues\n | ClassObject\n | string\n | number\n | bigint\n | null\n | boolean\n | undefined;\n\n/** ----------------------------------------------------------\n * * ***Type-Utility: `ClassObject`.***\n * ----------------------------------------------------------\n * **Represents an object whose keys with truthy values are included in the final class string.**\n * @example\n * ```ts\n * const obj: ClassObject = { \"text-red\": true, \"hidden\": false };\n * // ➔ \"text-red\" when processed by cx\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ClassObject = Record<string, any>;\n\n/** ----------------------------------------------------------\n * * ***Type-Utility: `ClassValues`.***\n * ----------------------------------------------------------\n * **Represents an array of {@link ClassValue | `ClassValue's`}, potentially nested.**\n * @example\n * ```ts\n * const arr: ClassValues = [\n * \"a\",\n * 1,\n * [\"b\", { c: true, d: false }],\n * { e: 2 }\n * ];\n * ```\n */\nexport type ClassValues = ClassValue[];\n\n/** ----------------------------------------------------------\n * * ***Utility: `toStringValue`.***\n * ----------------------------------------------------------\n * **Converts a `ClassValue` into a single space-separated string suitable for CSS class usage.**\n * @param {ClassValue} value The mixed value to process.\n * @returns {string} A string containing all valid class names.\n * @description\n * - Arrays are recursively flattened.\n * - Objects include only keys with truthy values.\n * - Skips `null`, `undefined`, and empty strings.\n * - Numbers, strings, and bigint are included as-is.\n * - Boolean `false` is ignored in objects/arrays.\n * - Boxed primitives (`new String()`, `new Number()`, `new Boolean()`) are supported.\n * - Preserves inherited object keys.\n * @example\n * ```ts\n * toStringValue(\"btn\"); // ➔ \"btn\"\n * toStringValue([\"a\", 0, \"b\"]); // ➔ \"a b\"\n * toStringValue({ a: true, b: false, c: 1 }); // ➔ \"a c\"\n * toStringValue([\"a\", [\"b\", { c: true, d: false }]]); // ➔ \"a b c\"\n * toStringValue(new String(\"foo\")); // ➔ \"foo\"\n * toStringValue(new Number(42)); // ➔ \"42\"\n * toStringValue(new Boolean(true)); // ➔ \"true\"\n * toStringValue(new Boolean(false));// ➔ \"\"\n * ```\n */\nfunction toStringValue(value: ClassValue): string {\n let str = \"\";\n\n if (isNonEmptyString(value) || isNumber(value)) {\n str += value;\n } else if (isObjectOrArray(value)) {\n if (\n isStringObject(value) ||\n isNumberObject(value) ||\n isBooleanObject(value)\n ) {\n const val = value.valueOf();\n if (val) str += val; // skip falsy\n } else if (isArray(value)) {\n for (const item of value) {\n if (!item) continue; // skip falsy\n const y = toStringValue(item);\n if (!y) continue;\n if (str) str += \" \";\n str += y;\n }\n } else {\n for (const key in value) {\n if (!value[key]) continue; // skip falsy\n if (str) str += \" \";\n str += key;\n }\n }\n }\n\n return str;\n}\n\n/** ----------------------------------------------------------\n * * ***Utility: `cx`.***\n * ----------------------------------------------------------\n * **Merge multiple class values into a single, space-separated string suitable for CSS usage.**\n * @description\n * - Supports **nested combinations** of arrays and objects, recursively.\n * - **Falsy values** are skipped:\n * - `false`, `null`, `undefined`, empty strings `\"\"` are ignored anywhere.\n * - Numbers `0` are ignored inside nested arrays/objects.\n * - **Boxed primitives** are correctly unwrapped to their primitive value.\n * - **Inherited object keys** are included in the final class string.\n * - Optimized for **CSS class merging** where conditional inclusion is common.\n * @param {ClassValues} values\n * A list of mixed class values, which can include:\n * - **Strings** → literal class names.\n * - **Numbers** → numeric class names.\n * - **BigInt** → numeric class names larger than JS safe integer limit.\n * - **Arrays** → recursively flattened, can contain nested arrays or objects.\n * - **Objects** → include keys whose values are truthy. Inherited keys are also included.\n * - **Boxed primitives** (`new String()`, `new Number()`, `new Boolean()`) → automatically unwrapped.\n * - **Falsy values** (`false`, `null`, `undefined`, `\"\"`, `0`) are ignored according to original behavior.\n * @returns {string}\n * A single space-separated string containing all valid class names.\n * @example\n * ```ts\n * // Basic string merge\n * cx(\"btn\", \"btn-primary\");\n * // ➔ \"btn btn-primary\"\n *\n * // Mixed arrays and objects\n * cx(\"a\", [\"b\", { c: true, d: false }], { e: 1, f: 0 }, null, 2);\n * // ➔ \"a b c e 2\"\n *\n * // Empty and falsy values are ignored\n * cx(\"\", null, undefined, false, 0);\n * // ➔ \"\"\n *\n * // Nested arrays with objects\n * cx([\"a\", [\"b\", { c: true, d: false }]]);\n * // ➔ \"a b c\"\n *\n * // Boxed primitives are unwrapped\n * cx(new String(\"foo\"), new Number(42), new Boolean(true), new Number(0), new Boolean(false));\n * // ➔ \"foo 42 true\"\n *\n * // Inherited keys from objects are included\n * const proto = { inherited: true };\n * const obj = Object.create(proto);\n * obj.own = true;\n * cx(obj);\n * // ➔ \"own inherited\"\n * ```\n */\nexport function cx(...values: ClassValues): string {\n let str = \"\";\n\n for (const value of values) {\n if (!value) continue; // skip falsy arguments\n const x = toStringValue(value);\n if (!x) continue;\n if (str) str += \" \";\n str += x;\n }\n\n return str;\n}\n","import type { Config as TwConfig } from \"tailwindcss\";\nimport type { ConfigExtension } from \"tailwind-merge-v4\";\n\nimport type { OptionsMergeTwClsV4 } from \"../v4/_private/types\";\n\nimport { hasOwnProp } from \"@/predicates/has/hasOwnProp\";\n\nimport { isNumber } from \"@/predicates/is/isNumber\";\nimport { isFunction } from \"@/predicates/is/isFunction\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { isNonEmptyArray } from \"@/predicates/is/isNonEmptyArray\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nexport type TailwindConfig = TwConfig;\n\n/**\n * @internal\n */\ntype TwMergeConfigExt = ConfigExtension<string, string>;\n\n/**\n * @internal\n */\ntype ValidatorTwMergeReturn = {\n config: TwConfig;\n override: TwMergeConfigExt[\"override\"];\n cacheSize: TwMergeConfigExt[\"cacheSize\"];\n prefix: TwMergeConfigExt[\"prefix\"];\n experimentalParseClassName?: TwMergeConfigExt[\"experimentalParseClassName\"];\n theme: NonNullable<NonNullable<TwMergeConfigExt[\"extend\"]>[\"theme\"]>;\n classGroups: NonNullable<\n NonNullable<TwMergeConfigExt[\"extend\"]>[\"classGroups\"]\n >;\n conflictingClassGroupModifiers: NonNullable<\n NonNullable<TwMergeConfigExt[\"extend\"]>[\"conflictingClassGroupModifiers\"]\n >;\n conflictingClassGroups: NonNullable<\n NonNullable<TwMergeConfigExt[\"extend\"]>[\"conflictingClassGroups\"]\n >;\n orderSensitiveModifiers: NonNullable<\n NonNullable<TwMergeConfigExt[\"extend\"]>[\"orderSensitiveModifiers\"]\n >;\n};\n\n/**\n * @internal\n */\nexport const validatorPropsTwMerge = (\n options: OptionsMergeTwClsV4\n): ValidatorTwMergeReturn => {\n if (!isPlainObject(options)) options = {};\n let {\n config,\n prefix,\n extend,\n override,\n cacheSize,\n experimentalParseClassName\n } = options;\n\n if (!isPlainObject(config)) config = {};\n if (!isPlainObject(extend)) extend = {};\n if (!isPlainObject(override)) override = {};\n if (!isNumber(cacheSize)) cacheSize = undefined;\n if (!isNonEmptyString(prefix)) prefix = undefined;\n if (!isFunction(experimentalParseClassName))\n experimentalParseClassName = undefined;\n\n const theme = hasOwnProp(extend, \"theme\") ? extend.theme : {};\n const classGroups = hasOwnProp(extend, \"classGroups\")\n ? extend.classGroups\n : {};\n const conflictingClassGroupModifiers = hasOwnProp(\n extend,\n \"conflictingClassGroupModifiers\"\n )\n ? extend.conflictingClassGroupModifiers\n : {};\n\n const conflictingClassGroups = hasOwnProp(extend, \"conflictingClassGroups\")\n ? extend.conflictingClassGroups\n : {};\n const orderSensitiveModifiers =\n hasOwnProp(extend, \"orderSensitiveModifiers\") &&\n isNonEmptyArray(extend.orderSensitiveModifiers)\n ? extend.orderSensitiveModifiers\n : [];\n\n return {\n config,\n override,\n cacheSize,\n prefix,\n experimentalParseClassName,\n theme,\n classGroups,\n conflictingClassGroupModifiers,\n conflictingClassGroups,\n orderSensitiveModifiers\n };\n};\n","import type { OptionsMergeTwClsV3, TwMergeDefaultFnV3 } from \"./_private/types\";\n\nimport { extendTailwindMerge, getDefaultConfig } from \"tailwind-merge-v3\";\n\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { validatorPropsTwMerge } from \"../_private/validate-props\";\n\n// Get default Tailwind merge configuration\nconst defaultConfig = getDefaultConfig();\n\n/** -------------------------------------------------------------\n * * ***Customized Tailwind class merger Version 3 with extended rules.***\n * -------------------------------------------------------------\n * **Wraps ***`extendTailwindMerge` from tailwind-merge-v3*** with Tailwind’s default\n * config (_*`getDefaultConfig()` from tailwind-merge-v3*_) to create a **project-ready `twMerge`**.**\n * - 🔑 **When to use it?**\n * - Your project uses **Tailwind v3**.\n * - Extend **class groups** (e.g. add `text-shadow`).\n * - Respect your own **`tailwind.config.ts`** (colors, spacing, fontSize, etc).\n * - Override or fine-tune **merge behavior**.\n * - Create a **project-wide `cn` helper** that replaces raw `twMerge`.\n * @param {OptionsMergeTwClsV3} [options={}]\n * ***Merge options:***\n * - `config` – Your Tailwind config (from `tailwind.config.ts`).\n * - `prefix` - Utility prefix (e.g. `tw-` or `tw`).\n * - `extend` – Extra merge rules (classGroups, theme, etc).\n * - `override` – Fully replace rules.\n * - `cacheSize` – Parsed class cache size.\n * - `experimentalParseClassName` – Custom classname parser.\n * @returns {TwMergeDefaultFnV3}\n * Customized Tailwind class merge function version 3 (same signature as `twMerge`).\n * @example\n * #### Example 1: ***Default behavior (same as tailwind-merge).***\n * ```ts\n * import { twMergeDefaultV3 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const twMerge = twMergeDefaultV3();\n * twMerge(\"p-2 p-4\");\n * // ➔ \"p-4\"\n * ```\n * #### Example 2: ***Extend class groups.***\n * ```ts\n * import { twMergeDefaultV3 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const twMerge2 = twMergeDefaultV3({\n * extend: {\n * classGroups: {\n * shadow: [\"shadow-soft\", \"shadow-hard\"],\n * },\n * },\n * });\n * twMerge2(\"shadow-soft shadow-hard\");\n * // ➔ \"shadow-hard\"\n * ```\n * #### Example 3: ***Respect your Tailwind config.***\n * ```ts\n * import config from \"../tailwind.config\";\n * import { twMergeDefaultV3 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const twMerge3 = twMergeDefaultV3({ config });\n * twMerge3(\"text-base text-xxs\");\n * // ➔ \"text-xxs\" (resolved from config)\n * ```\n * #### Example 4: ***Project-wide helper (recommended).***\n * ```ts\n * import configTwCss from \"../tailwind.config\";\n * import { customCnV3, twMergeDefaultV3, type ClassValues } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const customTwMerge = twMergeDefaultV3({\n * config: configTwCss,\n * extend: {\n * classGroups: { shadow: [\"shadow-soft\", \"shadow-hard\"] },\n * },\n * });\n *\n * export const cnApp = (...classes: ClassValues) => {\n * return customCnV3(customTwMerge, ...classes);\n * };\n *\n * // ✅ Usage\n * cnApp(\"p-2 p-4\"); // ➔ \"p-4\"\n * cnApp(\"shadow-soft shadow-hard\"); // ➔ \"shadow-hard\"\n * cnApp(\"text-base text-xxs\"); // ➔ \"text-xxs\" (uses config)\n *\n * // ⚡ Difference with package-level `cn`\n * import { cnV3, cnV4 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * cnV3(\"text-base text-xxs\");\n * // or\n * cnV4(\"text-base text-xxs\");\n * // ➔ \"text-base\" (❌ doesn't know about your config)\n *\n * cnApp(\"text-base text-xxs\");\n * // ➔ \"text-xxs\" (✅ respects config)\n * ```\n */\nexport const twMergeDefaultV3 = (\n options: OptionsMergeTwClsV3 = {}\n): TwMergeDefaultFnV3 => {\n if (!isPlainObject(options)) options = {};\n const {\n cacheSize,\n classGroups,\n config,\n conflictingClassGroupModifiers,\n conflictingClassGroups,\n override,\n prefix,\n theme,\n experimentalParseClassName\n } = validatorPropsTwMerge(options);\n\n return extendTailwindMerge<string, string>({\n prefix: prefix ?? config.prefix,\n cacheSize: cacheSize || defaultConfig.cacheSize,\n experimentalParseClassName,\n override,\n extend: {\n conflictingClassGroupModifiers: {\n ...defaultConfig.conflictingClassGroupModifiers,\n ...conflictingClassGroupModifiers\n },\n theme: { ...defaultConfig.theme, ...theme },\n conflictingClassGroups: {\n ...defaultConfig.conflictingClassGroups,\n ...conflictingClassGroups\n },\n classGroups: {\n ...defaultConfig.classGroups,\n ...classGroups,\n\n \"text-shadow\": [\n \"\",\n \"-sm\",\n \"-md\",\n \"-lg\",\n \"-xl\",\n \"-xxl\",\n \"-none\",\n \"-default\"\n ].map((size) => `text-shadow${size}`),\n \"font-size\": Object.keys({\n ...(config.theme?.fontSize || {}),\n ...(config.theme?.extend?.fontSize || {})\n }).map((size) => `text-${size}`)\n }\n }\n });\n};\n","import type { OptionsMergeTwClsV4, TwMergeDefaultFnV4 } from \"./_private/types\";\n\nimport { extendTailwindMerge, getDefaultConfig } from \"tailwind-merge-v4\";\n\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { validatorPropsTwMerge } from \"../_private/validate-props\";\n\n// Get default Tailwind merge configuration\nconst defaultConfig = getDefaultConfig();\n\n/** -------------------------------------------------------------\n * * ***Customized Tailwind class merger Version 4 with extended rules.***\n * -------------------------------------------------------------\n * **Wraps ***`extendTailwindMerge` from tailwind-merge-v4*** with Tailwind’s default\n * config (_*`getDefaultConfig()` from tailwind-merge-v4*_) to create a **project-ready `twMerge`**.**\n * - 🔑 **When to use it?**\n * - Your project uses **Tailwind v4**.\n * - Extend **class groups** (e.g. add `text-shadow`).\n * - Respect your own **`tailwind.config.ts`** (colors, spacing, fontSize, etc).\n * - Override or fine-tune **merge behavior**.\n * - Create a **project-wide `cn` helper** that replaces raw `twMerge`.\n * @param {OptionsMergeTwClsV4} [options={}]\n * ***Merge options:***\n * - `config` – Your Tailwind config (from `tailwind.config.ts`).\n * - `prefix` - Utility prefix (e.g. `tw-` or `tw`).\n * - `extend` – Extra merge rules (classGroups, theme, etc).\n * - `override` – Fully replace rules.\n * - `cacheSize` – Parsed class cache size.\n * - `experimentalParseClassName` – Custom classname parser.\n * @returns {TwMergeDefaultFnV4}\n * Customized Tailwind class merge function version 4 (same signature as `twMerge`).\n * @example\n * #### Example 1: ***Default behavior (same as tailwind-merge).***\n * ```ts\n * import { twMergeDefaultV4 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const twMerge = twMergeDefaultV4();\n * twMerge(\"p-2 p-4\");\n * // ➔ \"p-4\"\n * ```\n * #### Example 2: ***Extend class groups.***\n * ```ts\n * import { twMergeDefaultV4 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const twMerge2 = twMergeDefaultV4({\n * extend: {\n * classGroups: {\n * shadow: [\"shadow-soft\", \"shadow-hard\"],\n * },\n * },\n * });\n * twMerge2(\"shadow-soft shadow-hard\");\n * // ➔ \"shadow-hard\"\n * ```\n * #### Example 3: ***Respect your Tailwind config.***\n * ```ts\n * import config from \"../tailwind.config\";\n * import { twMergeDefaultV4 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const twMerge3 = twMergeDefaultV4({ config });\n * twMerge3(\"text-base text-xxs\");\n * // ➔ \"text-xxs\" (resolved from config)\n * ```\n * #### Example 4: ***Project-wide helper (recommended).***\n * ```ts\n * import configTwCss from \"../tailwind.config\";\n * import { customCnV4, twMergeDefaultV4, type ClassValues } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const customTwMerge = twMergeDefaultV4({\n * config: configTwCss,\n * extend: {\n * classGroups: { shadow: [\"shadow-soft\", \"shadow-hard\"] },\n * },\n * });\n *\n * export const cnApp = (...classes: ClassValues) => {\n * return customCnV4(customTwMerge, ...classes);\n * };\n *\n * // ✅ Usage\n * cnApp(\"p-2 p-4\"); // ➔ \"p-4\"\n * cnApp(\"shadow-soft shadow-hard\"); // ➔ \"shadow-hard\"\n * cnApp(\"text-base text-xxs\"); // ➔ \"text-xxs\" (uses config)\n *\n * // ⚡ Difference with package-level `cn`\n * import { cnV3, cnV4 } from \"@rzl-zone/utils-js/tailwind\";\n *\n * cnV3(\"text-base text-xxs\");\n * // or\n * cnV4(\"text-base text-xxs\");\n * // ➔ \"text-base\" (❌ doesn't know about your config)\n *\n * cnApp(\"text-base text-xxs\");\n * // ➔ \"text-xxs\" (✅ respects config)\n * ```\n */\nexport const twMergeDefaultV4 = (\n options: OptionsMergeTwClsV4 = {}\n): TwMergeDefaultFnV4 => {\n if (!isPlainObject(options)) options = {};\n const {\n cacheSize,\n classGroups,\n config,\n conflictingClassGroupModifiers,\n conflictingClassGroups,\n orderSensitiveModifiers,\n override,\n prefix,\n theme,\n experimentalParseClassName\n } = validatorPropsTwMerge(options);\n\n return extendTailwindMerge<string, string>({\n prefix: prefix || config.prefix,\n cacheSize: cacheSize || defaultConfig.cacheSize,\n experimentalParseClassName,\n override,\n extend: {\n conflictingClassGroupModifiers: {\n ...defaultConfig.conflictingClassGroupModifiers,\n ...conflictingClassGroupModifiers\n },\n theme: { ...defaultConfig.theme, ...theme },\n conflictingClassGroups: {\n ...defaultConfig.conflictingClassGroups,\n ...conflictingClassGroups\n },\n orderSensitiveModifiers: [\n ...defaultConfig.orderSensitiveModifiers,\n ...orderSensitiveModifiers\n ],\n classGroups: {\n ...defaultConfig.classGroups,\n ...classGroups,\n\n \"text-shadow\": [\n \"\",\n \"-sm\",\n \"-md\",\n \"-lg\",\n \"-xl\",\n \"-xxl\",\n \"-none\",\n \"-default\"\n ].map((size) => `text-shadow${size}`),\n \"font-size\": Object.keys({\n ...(config.theme?.fontSize || {}),\n ...(config.theme?.extend?.fontSize || {})\n }).map((size) => `text-${size}`)\n }\n }\n });\n};\n","import type { TwMergeDefaultFnV3 } from \"../tw-merge/v3/_private/types\";\nimport type { TwMergeDefaultFnV4 } from \"../tw-merge/v4/_private/types\";\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { twMergeDefaultV3 } from \"../tw-merge/v3/twMergeDefault\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { twMergeDefaultV4 } from \"../tw-merge/v4/twMergeDefault\";\n\nimport { isFunction } from \"@/predicates/is/isFunction\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { cx, type ClassValues } from \"./cx\";\n\nexport type { ClassValues };\n\n/** -------------------------------------------------------------\n * * ***Factory utility for building a custom `cn` helper (Tailwind `v3`).***\n * -------------------------------------------------------------\n * **Wraps internally function to combines class-name values and applies the provided\n * Tailwind merge function (from {@link twMergeDefaultV3 | `twMergeDefaultV3`}).**\n * - 🔑 **When to use it?**\n * - Your project uses **Tailwind v3**.\n * - You extend Tailwind merge rules (`classGroups`, `tailwind.config`).\n * - You need multiple `cn*` variants across apps/packages.\n * @param {TwMergeDefaultFnV3} customTwMergeV3 - Merge function created via {@link twMergeDefaultV3 | `twMergeDefaultV3`}.\n * @param {ClassValues} classes - Class values (`string`, `array`, `object`, `etc`).\n * @returns {string} Merged Tailwind class string.\n * @example\n * ```ts\n * import tailwindConfig from \"../tailwind.config\";\n * import { twMergeDefaultV3, customCnV3, type ClassValues } from \"@rzl-zone/utils-js/tailwind\";\n *\n * // 1. Create a custom merge function\n * const myCustomTwMerge = twMergeDefaultV3({\n * config: tailwindConfig,\n * extend: {\n * classGroups: {\n * \"text-shadow\": [\"text-shadow\", \"text-shadow-sm\", \"text-shadow-md\"],\n * },\n * },\n * });\n *\n * // 2. Build your helper using `customCnV3`\n * export const cnApp = (...classes: ClassValues) => {\n * return customCnV3(myCustomTwMerge, ...classes);\n * };\n * // ✅ Usage\n * cnApp(\"p-2\", \"p-4\"); // ➔ \"p-4\"\n * cnApp(\"shadow-sm shadow-md\"); // ➔ \"shadow-md\"\n * cnApp(\"text-base text-xxs\"); // ➔ \"text-xxs\" (resolved from config)\n * ```\n */\nexport const customCnV3 = (\n customTwMergeV3: TwMergeDefaultFnV3,\n ...classes: ClassValues\n): string => {\n if (!isFunction(customTwMergeV3)) {\n throw new TypeError(\n `first Parameter (\\`customTwMergeV3\\`) must be of type \\`function\\`, but received: \\`${getPreciseType(\n customTwMergeV3\n )}\\`.`\n );\n }\n\n return customTwMergeV3(cx(...classes));\n};\n\n/** -------------------------------------------------------------\n * * ***Factory utility for building a custom `cn` helper (Tailwind `v4`).***\n * -------------------------------------------------------------\n * **Wraps internally function to combines class-name values and applies the provided\n * Tailwind merge function (from {@link twMergeDefaultV4 | `twMergeDefaultV4`}).**\n * - 🔑 **When to use it?**\n * - Your project uses **Tailwind v4**.\n * - You extend Tailwind merge rules (`classGroups`, `tailwind.config`).\n * - You need multiple `cn*` variants across apps/packages.\n * @param {TwMergeDefaultFnV4} customTwMergeV4 - Merge function created via {@link twMergeDefaultV4 | `twMergeDefaultV4`}.\n * @param {ClassValues} classes - Class values (`string`, `array`, `object`, `etc`).\n * @returns {string} Merged Tailwind class string.\n * @example\n * ```ts\n * import tailwindConfig from \"../tailwind.config\";\n * import { twMergeDefaultV4, customCnV4, type ClassValues } from \"@rzl-zone/utils-js/tailwind\";\n *\n * // 1. Create a custom merge function\n * const myCustomTwMerge = twMergeDefaultV4({\n * config: tailwindConfig,\n * extend: {\n * classGroups: {\n * \"text-shadow\": [\"text-shadow\", \"text-shadow-sm\", \"text-shadow-md\"],\n * },\n * },\n * });\n *\n * // 2. Build your helper using `customCnV4`\n * export const cnApp = (...classes: ClassValues) => {\n * return customCnV4(myCustomTwMerge, ...classes);\n * };\n *\n * // ✅ Usage\n * cnApp(\"p-2\", \"p-4\"); // ➔ \"p-4\"\n * cnApp(\"shadow-sm shadow-md\"); // ➔ \"shadow-md\"\n * cnApp(\"text-base text-xxs\"); // ➔ \"text-xxs\" (resolved from config)\n * ```\n */\nexport const customCnV4 = (\n customTwMergeV4: TwMergeDefaultFnV4,\n ...classes: ClassValues\n): string => {\n if (!isFunction(customTwMergeV4)) {\n throw new TypeError(\n `first Parameter (\\`customTwMergeV4\\`) must be of type \\`function\\`, but received: \\`${getPreciseType(\n customTwMergeV4\n )}\\`.`\n );\n }\n\n return customTwMergeV4(cx(...classes));\n};\n","import type { ClassValues } from \"./cx\";\n\nimport { cx } from \"./cx\";\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { customCnV3, customCnV4 } from \"./customCn\";\nimport { twMergeDefaultV3 } from \"../tw-merge/v3/twMergeDefault\";\nimport { twMergeDefaultV4 } from \"../tw-merge/v4/twMergeDefault\";\n\nconst defaultTwMergeV3 = twMergeDefaultV3();\nconst defaultTwMergeV4 = twMergeDefaultV4();\n\n/** -------------------------------------------------------------\n * * ***Default `cnV3` utility (Tailwind v3).***\n * -------------------------------------------------------------\n * **Combines class-name values and then deduplicates/resolves\n * conflicts using {@link twMergeDefaultV3 | `twMergeDefaultV3`}\n * with **Tailwind v3 default config only**.**\n * - ✅ **Use this when:**\n * - Your project uses **Tailwind v3**.\n * - You need a simple `cn` that works out of the box without a custom config.\n * - ⚡ **Need custom rules?**\n * - Create a project-wide helper using\n * {@link twMergeDefaultV3 | `twMergeDefaultV3`} +\n * {@link customCnV3 | `customCnV3`} (see Example 2).\n * @param {ClassValues} classes - Class values (`string`, `array`, `object`, `etc`).\n * @returns {string} Merged Tailwind class string.\n * @example\n * #### Example 1: ✅ Default usage (Tailwind v3).\n * ```ts\n * cnV3(\"p-2\", \"p-4\");\n * // ➔ \"p-4\"\n *\n * cnV3(\"text-red-500\", { \"text-blue-500\": true });\n * // ➔ \"text-blue-500\"\n *\n * cnV3([\"m-2\", [\"m-4\"]], \"m-8\");\n * // ➔ \"m-8\"\n * ```\n * #### Example 2: ⚡ Custom project-wide usage with Tailwind config.\n * ```ts\n * import tailwindConfig from \"../tailwind.config\";\n * import { twMergeDefaultV3, customCnV3, type ClassValues } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const cnApp = (...classes: ClassValues) => {\n * return customCnV3(\n * twMergeDefaultV3({\n * config: tailwindConfig,\n * extend: {\n * classGroups: {\n * \"text-shadow\": [\n * \"text-shadow\",\n * \"text-shadow-sm\",\n * \"text-shadow-md\",\n * ],\n * },\n * },\n * }),\n * // ...other options classes,\n * );\n * };\n *\n * cnApp(\"p-2 p-4\"); // ➔ \"p-4\"\n * cnApp(\"shadow-sm shadow-md\"); // ➔ \"shadow-md\"\n * cnApp(\"text-base text-xxs\"); // ➔ \"text-xxs\" (resolved from config)\n * ```\n */\nexport const cnV3 = (...classes: ClassValues): string => {\n return defaultTwMergeV3(cx(...classes));\n};\n\n/** -------------------------------------------------------------\n * * ***Default `cnV4` utility (Tailwind v4).***\n * -------------------------------------------------------------\n * **Combines class-name values and then deduplicates/resolves\n * conflicts using {@link twMergeDefaultV4 | `twMergeDefaultV4`}\n * with **Tailwind v4 default config only**.**\n * - ✅ **Use this when:**\n * - Your project uses **Tailwind v4**.\n * - You need a simple `cn` that works out of the box without a custom config.\n * - ⚡ **Need custom rules?**\n * - Create a project-wide helper using\n * {@link twMergeDefaultV4 | `twMergeDefaultV4`} +\n * {@link customCnV4 | `customCnV4`} (see Example 2).\n * @param {ClassValues} classes - Class values (`string`, `array`, `object`, `etc`).\n * @returns {string} Merged Tailwind class string.\n * @example\n * #### Example 1: ✅ Default usage (Tailwind v4).\n * ```ts\n * cnV4(\"p-2\", \"p-4\");\n * // ➔ \"p-4\"\n *\n * cnV4(\"text-red-500\", { \"text-blue-500\": true });\n * // ➔ \"text-blue-500\"\n *\n * cnV4([\"m-2\", [\"m-4\"]], \"m-8\");\n * // ➔ \"m-8\"\n * ```\n * #### Example 2: ⚡ Custom project-wide usage with Tailwind config.\n * ```ts\n * import tailwindConfig from \"../tailwind.config\";\n * import { twMergeDefaultV4, customCnV4, type ClassValues } from \"@rzl-zone/utils-js/tailwind\";\n *\n * const cnApp = (...classes: ClassValues) => {\n * return customCnV4(\n * twMergeDefaultV4({\n * config: tailwindConfig,\n * extend: {\n * classGroups: {\n * \"text-shadow\": [\n * \"text-shadow\",\n * \"text-shadow-sm\",\n * \"text-shadow-md\",\n * ],\n * },\n * },\n * }),\n * // ...other options classes,\n * );\n * };\n *\n * cnApp(\"p-2 p-4\"); // ➔ \"p-4\"\n * cnApp(\"shadow-sm shadow-md\"); // ➔ \"shadow-md\"\n * cnApp(\"text-base text-xxs\"); // ➔ \"text-xxs\" (resolved from config)\n * ```\n */\nexport const cnV4 = (...classes: ClassValues): string => {\n return defaultTwMergeV4(cx(...classes));\n};\n","import type { Stringify } from \"@rzl-zone/ts-types-plus\";\n\nimport { isString } from \"@/predicates/is/isString\";\nimport { isEmptyString } from \"@/predicates/is/isEmptyString\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyArray } from \"@/predicates/is/isNonEmptyArray\";\nimport { assertIsArray } from \"@/assertions/objects/assertIsArray\";\n\n/** ----------------------------------------------------------\n * * ***Utility: `shouldForwardProp`.***\n * ----------------------------------------------------------\n * **Creates a helper for styled-components `shouldForwardProp`.**\n *\n * @description\n * 1. Returns a **predicate function** that determines whether a given prop\n * should be forwarded to the DOM.\n * 2. Useful for filtering out internal props (e.g., `$size`, `$active`)\n * so they don't become invalid HTML attributes.\n *\n * - **Behavior:**\n * - Accepts a strict tuple of **string keys** to exclude from forwarding.\n * - Every key is validated as a **non-empty string** at runtime.\n * - Throws a `TypeError` if:\n * - `props` is not an array, or\n * - any item is not a non-empty string.\n * - Automatically coerces the tested prop name to string for matching.\n *\n * @template CustomProps\n * The component props type to validate against.\n *\n * @param {readonly Stringify<keyof CustomProps>[]}\n * props\n * The list of prop names (keys of `CustomProps`) to exclude from forwarding.\n *\n * @returns {(propName: keyof CustomProps | ({} & string)) => boolean}\n * A function that receives a prop name and returns:\n * - `true` ➔ the prop **will** be forwarded to the DOM.\n * - `false` ➔ the prop **will not** be forwarded.\n *\n * @throws **{@link TypeError | `TypeError`}**\n * when:\n * - `props` is not an array, or\n * - any item is not a non-empty string.\n *\n * @example\n * // Basic usage\n * type Props = { $size: string; color: string; visible: boolean };\n * const filter = shouldForwardProp<Props>([\"$size\"]);\n *\n * filter(\"$size\"); // ➔ false (blocked).\n * filter(\"color\"); // ➔ true (forwarded).\n * filter(\"visible\"); // ➔ true (forwarded).\n *\n * @example\n * // With styled-components\n * type CustomProps = { $internal: boolean; public: string; another: boolean };\n *\n * styled.div.withConfig({\n * shouldForwardProp: shouldForwardProp<CustomProps>([\"$internal\"])\n * });\n */\nexport const shouldForwardProp = <CustomProps extends Record<string, unknown>>(\n props: readonly Stringify<keyof CustomProps>[]\n // props: Partial<UnionToTupleStrict<keyof CustomProps>>\n): ((propName: keyof CustomProps | ({} & string)) => boolean) => {\n assertIsArray(props, {\n message: ({ currentType, validType }) =>\n `First parameter (\\`props\\`) must be of type \\`${validType}\\`, but received: \\`${currentType}\\`.`\n });\n\n const invalidItems: { index: number; reason: string }[] = [];\n\n props.forEach((p, idx) => {\n if (!isString(p)) {\n invalidItems.push({\n index: idx,\n reason: `Expected a non-empty string, but received ${getPreciseType(p, {\n formatCase: \"toPascalCaseSpace\"\n })}.`\n });\n } else if (isEmptyString(p)) {\n invalidItems.push({\n index: idx,\n reason: \"Expected a non-empty string, but received EmptyString.\"\n });\n }\n });\n\n if (isNonEmptyArray(invalidItems)) {\n const maxWidth = Math.max(\n ...invalidItems.map((item) => String(item.index).length)\n );\n\n const details = invalidItems\n .map(\n (item) =>\n `• [Index ${String(item.index).padStart(maxWidth, \"0\")}] ${item.reason}`\n )\n .join(\"\\n\");\n\n throw new TypeError(\n `First parameter (\\`props\\`) contains invalid entries:\\n${details}`\n );\n }\n\n return (propName): boolean => {\n return !props.map(String).includes(String(propName));\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGA,SAAS,cAAc,OAA2B;CAChD,IAAI,MAAM;CAEV,IAAIA,yCAAiB,MAAM,IAAIC,iCAAS,MAAM,EAC5C,OAAO;MACF,IAAIC,wCAAgB,MAAM,EAC/B,IACEC,uCAAe,MAAM,IACrBC,uCAAe,MAAM,IACrBC,wCAAgB,MAAM,EACtB;EACA,MAAM,MAAM,MAAM,SAAS;EAC3B,IAAI,KAAK,OAAO;QACX,IAAIC,gCAAQ,MAAM,EACvB,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,CAAC,MAAM;EACX,MAAM,IAAI,cAAc,KAAK;EAC7B,IAAI,CAAC,GAAG;EACR,IAAI,KAAK,OAAO;EAChB,OAAO;;MAGT,KAAK,MAAM,OAAO,OAAO;EACvB,IAAI,CAAC,MAAM,MAAM;EACjB,IAAI,KAAK,OAAO;EAChB,OAAO;;CAKb,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDT,SAAgB,GAAG,GAAG,QAA6B;CACjD,IAAI,MAAM;CAEV,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,CAAC,OAAO;EACZ,MAAM,IAAI,cAAc,MAAM;EAC9B,IAAI,CAAC,GAAG;EACR,IAAI,KAAK,OAAO;EAChB,OAAO;;CAGT,OAAO;;;;;;;;ACnJT,MAAa,yBACX,YAC2B;CAC3B,IAAI,CAACC,sCAAc,QAAQ,EAAE,UAAU,EAAE;CACzC,IAAI,EACF,QACA,QACA,QACA,UACA,WACA,+BACE;CAEJ,IAAI,CAACA,sCAAc,OAAO,EAAE,SAAS,EAAE;CACvC,IAAI,CAACA,sCAAc,OAAO,EAAE,SAAS,EAAE;CACvC,IAAI,CAACA,sCAAc,SAAS,EAAE,WAAW,EAAE;CAC3C,IAAI,CAACC,iCAAS,UAAU,EAAE,YAAY;CACtC,IAAI,CAACC,yCAAiB,OAAO,EAAE,SAAS;CACxC,IAAI,CAACC,mCAAW,2BAA2B,EACzC,6BAA6B;CAE/B,MAAM,QAAQC,mCAAW,QAAQ,QAAQ,GAAG,OAAO,QAAQ,EAAE;CAC7D,MAAM,cAAcA,mCAAW,QAAQ,cAAc,GACjD,OAAO,cACP,EAAE;CACN,MAAM,iCAAiCA,mCACrC,QACA,iCACD,GACG,OAAO,iCACP,EAAE;CAEN,MAAM,yBAAyBA,mCAAW,QAAQ,yBAAyB,GACvE,OAAO,yBACP,EAAE;CACN,MAAM,0BACJA,mCAAW,QAAQ,0BAA0B,IAC7CC,wCAAgB,OAAO,wBAAwB,GAC3C,OAAO,0BACP,EAAE;CAER,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;;;;;AC3FH,MAAMC,2DAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwFxC,MAAa,oBACX,UAA+B,EAAE,KACV;CACvB,IAAI,CAACC,sCAAc,QAAQ,EAAE,UAAU,EAAE;CACzC,MAAM,EACJ,WACA,aACA,QACA,gCACA,wBACA,UACA,QACA,OACA,+BACE,sBAAsB,QAAQ;CAElC,kDAA2C;EACzC,QAAQ,UAAU,OAAO;EACzB,WAAW,aAAaD,gBAAc;EACtC;EACA;EACA,QAAQ;GACN,gCAAgC;IAC9B,GAAGA,gBAAc;IACjB,GAAG;IACJ;GACD,OAAO;IAAE,GAAGA,gBAAc;IAAO,GAAG;IAAO;GAC3C,wBAAwB;IACtB,GAAGA,gBAAc;IACjB,GAAG;IACJ;GACD,aAAa;IACX,GAAGA,gBAAc;IACjB,GAAG;IAEH,eAAe;KACb;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD,CAAC,KAAK,SAAS,cAAc,OAAO;IACrC,aAAa,OAAO,KAAK;KACvB,GAAI,OAAO,OAAO,YAAY,EAAE;KAChC,GAAI,OAAO,OAAO,QAAQ,YAAY,EAAE;KACzC,CAAC,CAAC,KAAK,SAAS,QAAQ,OAAO;IACjC;GACF;EACF,CAAC;;;;;AC3IJ,MAAM,yDAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwFxC,MAAa,oBACX,UAA+B,EAAE,KACV;CACvB,IAAI,CAACE,sCAAc,QAAQ,EAAE,UAAU,EAAE;CACzC,MAAM,EACJ,WACA,aACA,QACA,gCACA,wBACA,yBACA,UACA,QACA,OACA,+BACE,sBAAsB,QAAQ;CAElC,kDAA2C;EACzC,QAAQ,UAAU,OAAO;EACzB,WAAW,aAAa,cAAc;EACtC;EACA;EACA,QAAQ;GACN,gCAAgC;IAC9B,GAAG,cAAc;IACjB,GAAG;IACJ;GACD,OAAO;IAAE,GAAG,cAAc;IAAO,GAAG;IAAO;GAC3C,wBAAwB;IACtB,GAAG,cAAc;IACjB,GAAG;IACJ;GACD,yBAAyB,CACvB,GAAG,cAAc,yBACjB,GAAG,wBACJ;GACD,aAAa;IACX,GAAG,cAAc;IACjB,GAAG;IAEH,eAAe;KACb;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD,CAAC,KAAK,SAAS,cAAc,OAAO;IACrC,aAAa,OAAO,KAAK;KACvB,GAAI,OAAO,OAAO,YAAY,EAAE;KAChC,GAAI,OAAO,OAAO,QAAQ,YAAY,EAAE;KACzC,CAAC,CAAC,KAAK,SAAS,QAAQ,OAAO;IACjC;GACF;EACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrGJ,MAAa,cACX,iBACA,GAAG,YACQ;CACX,IAAI,CAACC,mCAAW,gBAAgB,EAC9B,MAAM,IAAI,UACR,uFAAuFC,uCACrF,gBACD,CAAC,KACH;CAGH,OAAO,gBAAgB,GAAG,GAAG,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCxC,MAAa,cACX,iBACA,GAAG,YACQ;CACX,IAAI,CAACD,mCAAW,gBAAgB,EAC9B,MAAM,IAAI,UACR,uFAAuFC,uCACrF,gBACD,CAAC,KACH;CAGH,OAAO,gBAAgB,GAAG,GAAG,QAAQ,CAAC;;;;;AC5GxC,MAAM,mBAAmB,kBAAkB;AAC3C,MAAM,mBAAmB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyD3C,MAAa,QAAQ,GAAG,YAAiC;CACvD,OAAO,iBAAiB,GAAG,GAAG,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DzC,MAAa,QAAQ,GAAG,YAAiC;CACvD,OAAO,iBAAiB,GAAG,GAAG,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjEzC,MAAa,qBACX,UAE+D;CAC/D,oCAAc,OAAO,EACnB,UAAU,EAAE,aAAa,gBACvB,iDAAiD,UAAU,sBAAsB,YAAY,MAChG,CAAC;CAEF,MAAM,eAAoD,EAAE;CAE5D,MAAM,SAAS,GAAG,QAAQ;EACxB,IAAI,CAACC,iCAAS,EAAE,EACd,aAAa,KAAK;GAChB,OAAO;GACP,QAAQ,6CAA6CC,uCAAe,GAAG,EACrE,YAAY,qBACb,CAAC,CAAC;GACJ,CAAC;OACG,IAAIC,oCAAc,EAAE,EACzB,aAAa,KAAK;GAChB,OAAO;GACP,QAAQ;GACT,CAAC;GAEJ;CAEF,IAAIC,wCAAgB,aAAa,EAAE;EACjC,MAAM,WAAW,KAAK,IACpB,GAAG,aAAa,KAAK,SAAS,OAAO,KAAK,MAAM,CAAC,OAAO,CACzD;EAED,MAAM,UAAU,aACb,KACE,SACC,YAAY,OAAO,KAAK,MAAM,CAAC,SAAS,UAAU,IAAI,CAAC,IAAI,KAAK,SACnE,CACA,KAAK,KAAK;EAEb,MAAM,IAAI,UACR,0DAA0D,UAC3D;;CAGH,QAAQ,aAAsB;EAC5B,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,SAAS,OAAO,SAAS,CAAC"}
|
package/dist/urls/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["isString","isEmptyString","normalizeString","isURL","getPreciseType","safeStableStringify","isUndefined","isNonEmptyString","isFunction","isEmptyValue","isNumber","isError","isNonEmptyString","isNonEmptyString","getPreciseType","safeStableStringify","isArray","isString","normalizePathname","isNil","isString","isArray","getPreciseType","isNull","isPlainObject","isInteger","safeStableStringify","isBoolean","isNonEmptyArray","joinLines","EOL","normalizePathname","isNonEmptyString"],"sources":["../../src/urls/builders/constructURL.ts","../../src/urls/extractors/extractURLs.ts","../../src/urls/pathname/getFirstPrefixPathname.ts","../../src/urls/pathname/getPrefixPathname.ts"],"sourcesContent":["import { isURL } from \"@/predicates/is/isURL\";\nimport { isError } from \"@/predicates/is/isError\";\nimport { isNumber } from \"@/predicates/is/isNumber\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isFunction } from \"@/predicates/is/isFunction\";\nimport { isUndefined } from \"@/predicates/is/isUndefined\";\nimport { isEmptyValue } from \"@/predicates/is/isEmptyValue\";\nimport { isEmptyString } from \"@/predicates/is/isEmptyString\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { normalizeString } from \"@/strings/sanitizations/normalizeString\";\n\nimport { assertIsArray } from \"@/assertions/objects/assertIsArray\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\nimport { toStringArrayUnRecursive } from \"@/conversions/arrays/casts/toStringArrayUnRecursive\";\n\n/** ----------------------------------------------------------\n * * ***Type-Utility: `QueryParamPairs`.***\n * ----------------------------------------------------------\n * **Represents a non-empty array of key–value pairs.**\n * @description\n * Type for `queryParams` parameter, the second parameter of ***`constructURL` utility function***.\n * - **Behavior:**\n * - Each inner tuple strictly follows the `[string, string | number]` shape.\n * - Ensures the outer array contains **at least one pair** (non-empty).\n * - Commonly used for URL construction parameters,\n * query string segments, or other key–value structured data.\n * @example\n * // ✅ valid usage\n * const params: QueryParamPairs = [\n * [\"foo\", 1],\n * [\"bar\", \"baz\"]\n * ];\n * constructURL(\"https://example.com\", params);\n *\n * // ❌ invalid: must contain at least one item\n * const empty: QueryParamPairs = [];\n *\n * // ❌ invalid: key without value pairs.\n * const empty2: QueryParamPairs = [[\"key\"]];\n */\nexport type QueryParamPairs = [\n [string, string | number],\n ...[string, string | number][]\n];\n\n/** ---------------------------------\n * * ***Utility: `constructURL`.***\n * ---------------------------------\n * **Constructs a valid URL with optional query parameters and allows selective removal of duplicate parameters.**\n * @param {string | URL} baseUrl The base URL to build upon. Must include protocol (e.g., `\"https://\"`), `domain`, and may include port and existing query parameters.\n * @param {Iterable<[string, string]> | URLSearchParamsIterator<[string, string]> | QueryParamPairs} [queryParams]\n * Additional query parameters to append or overwrite on the URL.\n * - Accepts any iterable of key-value pairs (like `new URLSearchParams().entries()` and `[[string, string | number]...]`).\n * @param {string[]} [removeParams]\n * A list of query parameter keys to remove from the final URL, whether they were in the base URL or provided queryParams.\n * @returns {URL} A new URL object representing the constructed URL with merged and cleaned query parameters.\n * @throws **{@link TypeError | `TypeError`}** if `baseUrl` is not a valid non-empty string or URL object, or if `queryParams` is not iterable, or if `removeParams` is not an array of strings.\n * @example\n * 1. #### Basic Usage:\n * ```ts\n * constructURL(\n * \"https://example.com/path\",\n * new URLSearchParams({ a: \"1\", b: \"2\" }).entries()\n * );\n * // ➔ URL { href: \"https://example.com/path?a=1&b=2\", ... }\n * ```\n * 2. #### Remove parameters from Base and Added:\n * ```ts\n * // with new URLSearchParams({ ... }).entries();\n * constructURL(\n * \"https://example.com/path?foo=1&bar=2\",\n * new URLSearchParams({ bar: \"ignored\", baz: \"3\" }).entries(),\n * [\"bar\"]\n * );\n * // ➔ URL { href: \"https://example.com/path?foo=1&baz=3\", ... }\n *\n * // with [[string, string | number]...]\n * constructURL(\n * \"https://example.com/path?foo=1&bar=2\",\n * [[\"bar\", \"ignored\"],[\"baz\", 3]],\n * [\"bar\"]\n * );\n * // ➔ URL { href: \"https://example.com/path?foo=1&baz=3\", ... }\n *\n * const params: QueryParamPairs = [\n * [\"foo\", 1],\n * [\"bar\", 2],\n * [\"baz\", 3]\n * ];\n *\n * constructURL(\"https://example.com\", params, [\"bar\"]);\n * // ➔ URL { href: \"https://example.com/?foo=1&baz=3\", ... }\n * ```\n */\nexport const constructURL = (\n baseUrl: string | URL,\n queryParams?:\n | URLSearchParamsIterator<[string, string | number]>\n | QueryParamPairs,\n removeParams?: string[]\n): URL => {\n if (isString(baseUrl)) {\n if (isEmptyString(baseUrl)) {\n throw new TypeError(\n \"First parameter (`baseUrl`) cannot be an empty-string.\"\n );\n }\n baseUrl = normalizeString(baseUrl);\n } else if (!isURL(baseUrl)) {\n throw new TypeError(\n `First parameter (\\`baseUrl\\`) must be of type an URL instance or a \\`string\\` and a non empty-string, but received: \\`${getPreciseType(\n baseUrl\n )}\\`, with current value: \\`${safeStableStringify(baseUrl, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n // Check removeParams\n if (!isUndefined(removeParams)) {\n assertIsArray(removeParams, {\n message: ({ currentType, validType }) =>\n `Third parameter (\\`removeParams\\`) must be of type \\`${validType} of strings\\`, but received: \\`${currentType}\\`.`\n });\n\n if (!removeParams.every((param) => isNonEmptyString(param))) {\n throw new TypeError(\n \"Third parameter (`removeParams`) must be of type `array` and contains `string` only and non empty-string.\"\n );\n }\n }\n\n try {\n // Check queryParams\n if (\n !isUndefined(queryParams) &&\n !isFunction(queryParams[Symbol.iterator])\n ) {\n throw new TypeError(\n `Second parameter (\\`queryParams\\`) must be iterable (like URLSearchParams.entries() or an array of [[string, string | number]...]), but received: \\`${getPreciseType(\n queryParams\n )}\\`, with value: \\`${safeStableStringify(queryParams, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n const urlInstance = new URL(baseUrl);\n\n // Add query parameters if provided\n if (!isUndefined(queryParams)) {\n const paramObject = Object.fromEntries(queryParams);\n\n if (!isEmptyValue(paramObject)) {\n // existing params\n const mergedParams = new URLSearchParams(urlInstance.search);\n\n // add / overwrite from queryParams\n for (const [key, value] of Object.entries(paramObject)) {\n if (\n !isNonEmptyString(value) &&\n !isNumber(value, { includeNaN: true })\n ) {\n throw new TypeError(\n `Second parameter (\\`queryParams\\`) must be iterable (like URLSearchParams.entries() or an array of [[string, string | number]...]), but received: \\`${getPreciseType(\n queryParams\n )}\\`, with value: \\`${safeStableStringify(queryParams, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n mergedParams.set(key, String(value));\n }\n\n // Remove specific query parameters if needed\n if (removeParams?.length) {\n toStringArrayUnRecursive(removeParams).map((paramKey) => {\n mergedParams.delete(paramKey);\n });\n }\n\n urlInstance.search = mergedParams.toString();\n }\n }\n\n // Remove query parameters directly from URL if needed\n removeParams?.forEach((param) => urlInstance.searchParams.delete(param));\n\n return urlInstance;\n } catch (error) {\n if (isError(error)) throw error;\n\n throw new Error(\n \"Failed to construct a valid URL in `constructURL()`, Error:\" + error,\n { cause: error }\n );\n }\n};\n","import { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** ---------------------------------\n * * ***Utility: `extractURLs`.***\n * ---------------------------------\n * **Extracts all valid URLs from a given string.**\n * @description\n * This function scans the input url and returns an array of URLs\n * that match a valid `http` or `https` format.\n * - **Supports:**\n * - Internationalized domain names (IDN), e.g. `https://münich.de`\n * - Unicode & emoji paths, e.g. `https://example.com/🎉/page`\n * - Long URLs with multiple queries & fragments, e.g. `https://example.com/path?foo=1#hash`\n * - **Ignores:**\n * - Non-string inputs\n * - Empty or whitespace-only strings\n * - Non-HTTP(S) protocols (ftp, mailto, etc)\n * @param {string | null | undefined} url - The input string containing potential URLs.\n * @returns {string[] | null} An array of extracted URLs or `null` if no URLs are found.\n * @example\n * extractURLs(\"Visit https://example.com and https://例子.公司\");\n * // ➔ [\"https://example.com\", \"https://例子.公司\"]\n * extractURLs(\"Here: https://example.com/🎉/page\");\n * // ➔ [\"https://example.com/🎉/page\"]\n * extractURLs(\"ftp://example.com http://example.com\");\n * // ➔ [\"http://example.com\"]\n */\nexport const extractURLs = (\n url: string | null | undefined\n): string[] | null => {\n if (!isNonEmptyString(url)) return null;\n\n let decoded;\n try {\n decoded = decodeURIComponent(url);\n } catch {\n return null;\n }\n\n // Core regex with lookahead\n const urlPattern = /https?:\\/\\/.*?(?=https?:\\/\\/|\\s|$)/g;\n const matches = decoded.match(urlPattern);\n if (!matches) return null;\n\n // Cleanup trailing punctuation and validation protocol\n const cleaned = matches\n .map((url) => url.replace(/[.,;:!?)]*$/, \"\"))\n .filter((url) => {\n try {\n const u = new URL(url);\n return u.protocol === \"http:\" || u.protocol === \"https:\";\n } catch {\n return false;\n }\n });\n\n return cleaned.length ? cleaned : null;\n};\n","import { isNil } from \"@/predicates/is/isNil\";\nimport { isArray } from \"@/predicates/is/isArray\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\nimport { normalizePathname } from \"./normalizePathname\";\n\n/** --------------------------------------------------------\n * * ***Utility: `getFirstPrefixPathname`.***\n * --------------------------------------------------------\n * **Extract First Valid Prefix from Path Array or String.**\n * - **Main Purpose:**\n * - This function helps extract the first valid URL prefix from various possible inputs.\n * - It is especially useful in routing systems, middleware, or frontend apps that need to\n * decide layout, active navigation, or permissions based on the first segment (or prefix) of a pathname.\n * - **Typical uses include:**\n * - Determining which layout to render (e.g., `/admin` vs `/dashboard` vs `/`).\n * - Highlighting the active menu item in a sidebar based on the current URL.\n * - Enforcing route guards or access controls depending on the URL prefix.\n * - Parsing multi-level route prefixes and selecting the most relevant one.\n * - **Behavior:**\n * - It works as follows:\n * - If `result` is an array of strings, it normalizes each element and returns\n * the first non-root path (i.e., not just `\"/\"`).\n * - If all items normalize to `\"/\"`,\n * it returns the `defaultValue` (normalized).\n * - If `result` is a single string, it normalizes it and returns it if valid,\n * otherwise falls back to the normalized `defaultValue`.\n * - If `result` is `null` or `undefined`, it returns the normalized `defaultValue`.\n * - **Validation & Errors:**\n * - Throws a `TypeError` if:\n * - `defaultValue` is not a string or empty-string.\n * - `result` is an array that contains non-string elements.\n * - `result` is a value that is neither `string`, `string[]`, nor `null`.\n * @example\n * 1. #### For React (*Determining layout*):\n * ```ts\n * const prefix = getFirstPrefixPathname(\n * getPrefixPathname(\n * \"/admin/settings\",\n * [\"/admin\", \"/dashboard\"]\n * )\n * );\n *\n * if (prefix === \"/admin\") {\n * renderAdminLayout();\n * }\n * ```\n *\n * 2. #### Setting active menu state:\n * ```ts\n * const activeSection = getFirstPrefixPathname([\"\", \"/dashboard\", \"/profile\"]);\n * // ➔ \"/dashboard\"\n * ```\n *\n * 3. #### Providing graceful fallback:\n * ```ts\n * const section = getFirstPrefixPathname([], \"/home\");\n * // ➔ \"/home\"\n * ```\n * 4. #### ✅ Using with an Array of Pathnames:\n * ```ts\n * const result = getPrefixPathname([\" \", \"/dashboard\", \"/settings\"]);\n * console.log(getFirstPrefixPathname(result));\n * // ➔ \"/dashboard\"\n * ```\n *\n * 5. #### ✅ Using with Single String:\n * ```ts\n * console.log(getFirstPrefixPathname(\"/profile/settings\"));\n * // ➔ \"/profile/settings\"\n * console.log(getFirstPrefixPathname(\" \"));\n * // ➔ \"/\"\n * ```\n *\n * 6. #### ✅ Fallback to Custom Default:\n * ```ts\n * console.log(getFirstPrefixPathname([\" \", \"\"], \"/home\"));\n * // ➔ \"/home\"\n * console.log(getFirstPrefixPathname(null, \"/dashboard\"));\n * // ➔ \"/dashboard\"\n * ```\n *\n * 7. #### ✅ Throws on Invalid Input:\n * ```ts\n * getFirstPrefixPathname([1, 2] as any); // ➔ ❌ throws TypeError\n * getFirstPrefixPathname({} as any); // ➔ ❌ throws TypeError\n * getFirstPrefixPathname(null, \" \"); // ➔ ❌ throws TypeError\n * ```\n * @param {string | string[] | null | undefined} result\n * ***The pathname(s) to process, can be:***\n * - A string path (e.g. `\"/profile\"`),\n * - An array of string paths (e.g. `[\" \", \"/dashboard\"]`),\n * - Or `null`.\n * @param {string} [defaultValue=\"/\"]\n * ***A custom default path to use if `result` is null or no valid prefix is found, behavior:***\n * - Must be a string and non-empty string.\n * - Defaults to `\"/\"`.\n * @returns {string}\n * ***The first valid normalized pathname, or the normalized default.***\n * @throws **{@link TypeError | `TypeError`}** ***if `result` is not a valid type, or `defaultValue` is not a string or empty-string.***\n */\nexport const getFirstPrefixPathname = (\n result: string | string[] | null | undefined,\n defaultValue: string = \"/\"\n): string => {\n if (!isNonEmptyString(defaultValue)) {\n throw new TypeError(\n `Second parameter (\\`defaultValue\\`) must be of type \\`string\\` and not an \\`empty-string\\`, but received: \\`${getPreciseType(\n defaultValue\n )}\\`, with value: \\`${safeStableStringify(defaultValue, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n if (isArray(result)) {\n if (!result.every((item) => isString(item))) {\n throw new TypeError(\n `First parameter (\\`result\\`) must be of type \\`string\\` or \\`array of string\\`, but received: \\`${getPreciseType(\n result\n )}\\`, with value: \\`${safeStableStringify(result, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n for (const item of result) {\n const normalized = normalizePathname(item);\n if (normalized !== \"/\") {\n return normalized;\n }\n }\n return normalizePathname(defaultValue);\n }\n\n if (isString(result)) {\n const normalized = normalizePathname(result);\n return normalized !== \"/\" ? normalized : normalizePathname(defaultValue);\n }\n\n if (!isNil(result)) {\n throw new TypeError(\n `First parameter (\\`result\\`) must be of type \\`string\\`, \\`array-string\\`, \\`null\\` or \\`undefined\\`, but received: \\`${getPreciseType(\n result\n )}\\`.`\n );\n }\n\n return normalizePathname(defaultValue);\n};\n","import { joinLines, EOL } from \"@rzl-zone/build-tools/utils\";\n\nimport { isNull } from \"@/predicates/is/isNull\";\nimport { isArray } from \"@/predicates/is/isArray\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isInteger } from \"@/predicates/is/isInteger\";\nimport { isBoolean } from \"@/predicates/is/isBoolean\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyArray } from \"@/predicates/is/isNonEmptyArray\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { normalizePathname } from \"./normalizePathname\";\n\ntype GetPrefixPathnameOptions = {\n /** The number of levels to include in the prefix (default is `1`).\n *\n * - For example, with `levels = 2`, the function will return the first two parts of the URL.\n *\n * @default 1\n */\n levels?: number;\n /** Whether to remove duplicates from the result if multiple URLs are passed (default is `true`).\n *\n * @default true\n */\n removeDuplicates?: boolean;\n};\n\n/** --------------------------------------------------------\n * * ***Utility: `getPrefixPathname`.***\n * --------------------------------------------------------\n * **Get Prefix from URL with Optional Base or Auto-detection (Supports String or Array of URLs).**\n * - **This function extracts the prefix from one or more URLs. It can either:**\n * - Use a provided `base` string or an array of strings to check and return the matching prefix.\n * - Automatically detect the prefix if no `base` is provided by analyzing the first part of the URL.\n * - **The function is flexible and can handle both scenarios:**\n * 1. **When the base is provided as a single string or an array of strings**:\n * - The function will check if the URL starts with one of the provided base(s) and return the matching base.\n * 2. **When the base is not provided**:\n * - The function will automatically detect the prefix by splitting the URL or using a regex.\n * - **Important Notes**:\n * - If a base (or an array of bases) is provided, the URL must start with one of the given base(s).\n * - If no base is provided, the function will attempt to detect the prefix automatically.\n * - The `url` parameter can be either a string or an array of strings.\n * - Supports deduplication of results (enabled by default).\n * - Automatically returns a single string if only one unique result exists after processing.\n * @param {string|string[]} url\n * ***The full URL(s) from which the prefix should be extracted, can be a `string` or an `array of strings`.***\n * @param {string|string[]|null} [base=null]\n * ***The base URL(s) (e.g., `\"/settings\"`), behavior:***\n * - It can be a `string`, an `array of strings`, or `null`.\n * - If `provided`, it will be used to check the URL(s).\n * - If `not provided`, the prefix will be auto-detected.\n * @param {GetPrefixPathnameOptions} [options]\n * ***Additional options object:***\n * - `levels` (default `1`): The number of segments to include when auto-detecting the prefix (e.g. `/foo/bar` for `levels: 2`).\n * - `removeDuplicates` (default `true`): Whether to remove duplicate prefixes from the final array result.\n * @returns {string|string[]|null}\n * ***Returns one of:***\n * - A single string if only one unique prefix/base is found.\n * - An array of strings if multiple different prefixes/bases are found.\n * - `null` if no matching base is found when using `base`.\n * @throws **{@link TypeError | `TypeError`}**\n * ***if:***\n * - `url` is `not a string` or `not an array of strings`.\n * - `base` is `not a string`, `array of strings`, or `null`.\n * - `options` is `not an object`.\n * - `levels` is `not a number`.\n * - `removeDuplicates` is `not a boolean`.\n * @example\n * - #### ✅ **Correct Usage (With an Array of URLs and Base):**\n * ```ts\n * const routes = [\n * \"/settings/profile\",\n * \"/settings/password\",\n * \"/settings/other-path\",\n * \"/other-path/xyz\",\n * ];\n *\n * // With base provided as a string\n * routes.forEach(route => {\n * console.log(getPrefixPathname(route, '/settings'));\n * // ➔ \"/settings\"\n * });\n *\n * // With base provided as an array\n * routes.forEach(route => {\n * console.log(getPrefixPathname(route, ['/settings', '/admin']));\n * // ➔ \"/settings\" or \"/admin\" depending on the current URL.\n * });\n * ```\n * - #### ✅ **Correct Usage (With Single URL and Single Base):**\n * ```ts\n * const result = getPrefixPathname(\"/settings/profile\", \"/settings\");\n * console.log(result); // ➔ \"/settings\"\n * ```\n * - #### ✅ **Correct Usage (With Multiple URLs and Single Base):**\n * ```ts\n * const result = getPrefixPathname(\n * [\"/settings/profile\", \"/settings/password\"],\n * \"/settings\"\n * );\n * console.log(result); // ➔ \"/settings\"\n *\n * const result2 = getPrefixPathname(\n * [\"/settings/profile\", \"/other/password\"],\n * \"/other\"\n * );\n * console.log(result2); // ➔ \"/other\"\n * ```\n * - #### ✅ **Correct Usage (With Multiple URLs and Multiple Bases)**\n * ```ts\n * const result = getPrefixPathname(\n * [\"/settings/profile\", \"/admin/password\"],\n * [\"/settings\", \"/admin\"]\n * );\n * console.log(result); // ➔ [\"/settings\", \"/admin\"]\n * ```\n * - #### ✅ **Auto-detection of Prefix**\n * ```ts\n * const result = getPrefixPathname(\"/settings/profile\");\n * console.log(result); // ➔ \"/settings\"\n *\n * const result2 = getPrefixPathname(\n * \"/settings/profile/info\",\n * null,\n * { levels: 2 }\n * );\n * console.log(result2); // ➔ \"/settings/profile\"\n * ```\n * - #### ✅ **Multiple URLs with Auto-detection**\n * ```ts\n * const result = getPrefixPathname([\"/admin/profile\", \"/settings/password\"]);\n * console.log(result); // ➔ [\"/admin\", \"/settings\"]\n * ```\n * - #### ✅ **Handling Duplicates**\n * ```ts\n * const result = getPrefixPathname(\n * [\"/settings/profile\", \"/settings/password\"],\n * \"/settings\"\n * );\n * console.log(result); // ➔ \"/settings\" (deduped to single string)\n *\n * const result2 = getPrefixPathname(\n * [\"/settings/profile\", \"/settings/profile\"],\n * \"/settings\",\n * { removeDuplicates: false }\n * );\n * console.log(result2); // ➔ [\"/settings\", \"/settings\"]\n * ```\n * - #### ❌ **Incorrect Usage (URL Does Not Match Base)**\n * ```ts\n * const result = getPrefixPathname(\"/other-path/profile\", \"/settings\");\n * console.log(result); // ➔ null\n * ```\n */\nexport const getPrefixPathname = (\n url: string | string[],\n base: string | string[] | null = null,\n options: GetPrefixPathnameOptions = {}\n): string | string[] | null => {\n const errors: string[] = [];\n\n if (!isString(url) && !isArray(url)) {\n errors.push(\n `First parameter (\\`url\\`) must be of type \\`string\\` or \\`array-string\\`, but received: \\`${getPreciseType(\n url\n )}\\`.`\n );\n }\n if (!isString(base) && !isArray(base) && !isNull(base)) {\n errors.push(\n `Second parameter (\\`base\\`) must be of type \\`string\\`, \\`array-string\\` or \\`null\\`, but received: \\`${getPreciseType(\n base\n )}\\`.`\n );\n }\n if (!isPlainObject(options)) {\n errors.push(\n `Second parameter (\\`options\\`) must be of type \\`plain-object\\`, but received: \\`${getPreciseType(\n options\n )}\\`.`\n );\n }\n\n const { levels = 1, removeDuplicates = true } = options;\n\n if (!isInteger(levels) || (isInteger(levels) && levels < 0)) {\n errors.push(\n `Parameter \\`levels\\` property of the \\`options\\` (second parameter) must be of type \\`integer-number\\` and minimum is \\`0\\`, but received: \\`${getPreciseType(\n levels\n )}\\`, with value: \\`${safeStableStringify(levels, {\n keepUndefined: true\n })}\\`.`\n );\n }\n if (!isBoolean(removeDuplicates)) {\n errors.push(\n `Parameter \\`removeDuplicates\\` property of the \\`options\\` (second parameter) must be of type \\`boolean\\`, but received: \\`${getPreciseType(\n removeDuplicates\n )}\\`.`\n );\n }\n if (isNonEmptyArray(errors)) {\n throw new TypeError(\n joinLines(\n \"Invalid parameter(s) in `getPrefixPathname` function:\",\n `- ${errors.join(`${EOL}- `)}`\n )\n );\n }\n\n // Helper function to process a single URL\n function getLevel(singleUrl: string) {\n // If no base is provided, detect the base automatically\n const parts = normalizePathname(singleUrl).split(\"/\").filter(Boolean); // Split URL into parts\n\n // Return the first `levels` parts as the prefix\n return `/${parts.slice(0, levels).join(\"/\")}`;\n }\n\n // Helper function to process a single URL\n function processUrl(singleUrl: string): string | null {\n // If a base is provided, check if URL starts with one of the bases\n if (base) {\n singleUrl = normalizePathname(singleUrl);\n\n if (isArray(base)) {\n // Check if the URL starts with any of the base values in the array\n for (const b of base) {\n if (singleUrl.startsWith(normalizePathname(b))) {\n // return normalizePathname(b); // Return the matching base if URL starts with it\n return getLevel(singleUrl);\n }\n }\n } else if (\n isNonEmptyString(base) &&\n singleUrl.startsWith(normalizePathname(base))\n ) {\n // If base is a single string, check if URL starts with it\n // return normalizePathname(base); // Return the base if URL starts with it\n return getLevel(singleUrl);\n }\n return null; // Return null if the URL does not match any base\n }\n\n return getLevel(singleUrl);\n }\n\n // If url is an array, process each URL and return an array of results\n if (isArray(url)) {\n const result = url.map(processUrl).filter((r): r is string => !isNull(r));\n\n // Remove duplicates if required\n const uniqueResult = removeDuplicates ? [...new Set(result)] : result;\n\n // If all results are the same, return just the first one\n if (uniqueResult.length === 1) {\n return uniqueResult[0] ?? null;\n }\n\n return uniqueResult;\n }\n\n // If url is a single string, process it and return the result\n return processUrl(url);\n};\n"],"mappings":"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"}
|
package/dist/urls/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/urls/builders/constructURL.ts","../../src/urls/extractors/extractURLs.ts","../../src/urls/pathname/getFirstPrefixPathname.ts","../../src/urls/pathname/getPrefixPathname.ts"],"sourcesContent":["import { isURL } from \"@/predicates/is/isURL\";\nimport { isError } from \"@/predicates/is/isError\";\nimport { isNumber } from \"@/predicates/is/isNumber\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isFunction } from \"@/predicates/is/isFunction\";\nimport { isUndefined } from \"@/predicates/is/isUndefined\";\nimport { isEmptyValue } from \"@/predicates/is/isEmptyValue\";\nimport { isEmptyString } from \"@/predicates/is/isEmptyString\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { normalizeString } from \"@/strings/sanitizations/normalizeString\";\n\nimport { assertIsArray } from \"@/assertions/objects/assertIsArray\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\nimport { toStringArrayUnRecursive } from \"@/conversions/arrays/casts/toStringArrayUnRecursive\";\n\n/** ----------------------------------------------------------\n * * ***Type-Utility: `QueryParamPairs`.***\n * ----------------------------------------------------------\n * **Represents a non-empty array of key–value pairs.**\n * @description\n * Type for `queryParams` parameter, the second parameter of ***`constructURL` utility function***.\n * - **Behavior:**\n * - Each inner tuple strictly follows the `[string, string | number]` shape.\n * - Ensures the outer array contains **at least one pair** (non-empty).\n * - Commonly used for URL construction parameters,\n * query string segments, or other key–value structured data.\n * @example\n * // ✅ valid usage\n * const params: QueryParamPairs = [\n * [\"foo\", 1],\n * [\"bar\", \"baz\"]\n * ];\n * constructURL(\"https://example.com\", params);\n *\n * // ❌ invalid: must contain at least one item\n * const empty: QueryParamPairs = [];\n *\n * // ❌ invalid: key without value pairs.\n * const empty2: QueryParamPairs = [[\"key\"]];\n */\nexport type QueryParamPairs = [\n [string, string | number],\n ...[string, string | number][]\n];\n\n/** ---------------------------------\n * * ***Utility: `constructURL`.***\n * ---------------------------------\n * **Constructs a valid URL with optional query parameters and allows selective removal of duplicate parameters.**\n * @param {string | URL} baseUrl The base URL to build upon. Must include protocol (e.g., `\"https://\"`), `domain`, and may include port and existing query parameters.\n * @param {Iterable<[string, string]> | URLSearchParamsIterator<[string, string]> | QueryParamPairs} [queryParams]\n * Additional query parameters to append or overwrite on the URL.\n * - Accepts any iterable of key-value pairs (like `new URLSearchParams().entries()` and `[[string, string | number]...]`).\n * @param {string[]} [removeParams]\n * A list of query parameter keys to remove from the final URL, whether they were in the base URL or provided queryParams.\n * @returns {URL} A new URL object representing the constructed URL with merged and cleaned query parameters.\n * @throws **{@link TypeError | `TypeError`}** if `baseUrl` is not a valid non-empty string or URL object, or if `queryParams` is not iterable, or if `removeParams` is not an array of strings.\n * @example\n * 1. #### Basic Usage:\n * ```ts\n * constructURL(\n * \"https://example.com/path\",\n * new URLSearchParams({ a: \"1\", b: \"2\" }).entries()\n * );\n * // ➔ URL { href: \"https://example.com/path?a=1&b=2\", ... }\n * ```\n * 2. #### Remove parameters from Base and Added:\n * ```ts\n * // with new URLSearchParams({ ... }).entries();\n * constructURL(\n * \"https://example.com/path?foo=1&bar=2\",\n * new URLSearchParams({ bar: \"ignored\", baz: \"3\" }).entries(),\n * [\"bar\"]\n * );\n * // ➔ URL { href: \"https://example.com/path?foo=1&baz=3\", ... }\n *\n * // with [[string, string | number]...]\n * constructURL(\n * \"https://example.com/path?foo=1&bar=2\",\n * [[\"bar\", \"ignored\"],[\"baz\", 3]],\n * [\"bar\"]\n * );\n * // ➔ URL { href: \"https://example.com/path?foo=1&baz=3\", ... }\n *\n * const params: QueryParamPairs = [\n * [\"foo\", 1],\n * [\"bar\", 2],\n * [\"baz\", 3]\n * ];\n *\n * constructURL(\"https://example.com\", params, [\"bar\"]);\n * // ➔ URL { href: \"https://example.com/?foo=1&baz=3\", ... }\n * ```\n */\nexport const constructURL = (\n baseUrl: string | URL,\n queryParams?:\n | URLSearchParamsIterator<[string, string | number]>\n | QueryParamPairs,\n removeParams?: string[]\n): URL => {\n if (isString(baseUrl)) {\n if (isEmptyString(baseUrl)) {\n throw new TypeError(\n \"First parameter (`baseUrl`) cannot be an empty-string.\"\n );\n }\n baseUrl = normalizeString(baseUrl);\n } else if (!isURL(baseUrl)) {\n throw new TypeError(\n `First parameter (\\`baseUrl\\`) must be of type an URL instance or a \\`string\\` and a non empty-string, but received: \\`${getPreciseType(\n baseUrl\n )}\\`, with current value: \\`${safeStableStringify(baseUrl, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n // Check removeParams\n if (!isUndefined(removeParams)) {\n assertIsArray(removeParams, {\n message: ({ currentType, validType }) =>\n `Third parameter (\\`removeParams\\`) must be of type \\`${validType} of strings\\`, but received: \\`${currentType}\\`.`\n });\n\n if (!removeParams.every((param) => isNonEmptyString(param))) {\n throw new TypeError(\n \"Third parameter (`removeParams`) must be of type `array` and contains `string` only and non empty-string.\"\n );\n }\n }\n\n try {\n // Check queryParams\n if (\n !isUndefined(queryParams) &&\n !isFunction(queryParams[Symbol.iterator])\n ) {\n throw new TypeError(\n `Second parameter (\\`queryParams\\`) must be iterable (like URLSearchParams.entries() or an array of [[string, string | number]...]), but received: \\`${getPreciseType(\n queryParams\n )}\\`, with value: \\`${safeStableStringify(queryParams, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n const urlInstance = new URL(baseUrl);\n\n // Add query parameters if provided\n if (!isUndefined(queryParams)) {\n const paramObject = Object.fromEntries(queryParams);\n\n if (!isEmptyValue(paramObject)) {\n // existing params\n const mergedParams = new URLSearchParams(urlInstance.search);\n\n // add / overwrite from queryParams\n for (const [key, value] of Object.entries(paramObject)) {\n if (\n !isNonEmptyString(value) &&\n !isNumber(value, { includeNaN: true })\n ) {\n throw new TypeError(\n `Second parameter (\\`queryParams\\`) must be iterable (like URLSearchParams.entries() or an array of [[string, string | number]...]), but received: \\`${getPreciseType(\n queryParams\n )}\\`, with value: \\`${safeStableStringify(queryParams, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n mergedParams.set(key, String(value));\n }\n\n // Remove specific query parameters if needed\n if (removeParams?.length) {\n toStringArrayUnRecursive(removeParams).map((paramKey) => {\n mergedParams.delete(paramKey);\n });\n }\n\n urlInstance.search = mergedParams.toString();\n }\n }\n\n // Remove query parameters directly from URL if needed\n removeParams?.forEach((param) => urlInstance.searchParams.delete(param));\n\n return urlInstance;\n } catch (error) {\n if (isError(error)) throw error;\n\n throw new Error(\n \"Failed to construct a valid URL in `constructURL()`, Error:\" + error,\n { cause: error }\n );\n }\n};\n","import { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** ---------------------------------\n * * ***Utility: `extractURLs`.***\n * ---------------------------------\n * **Extracts all valid URLs from a given string.**\n * @description\n * This function scans the input url and returns an array of URLs\n * that match a valid `http` or `https` format.\n * - **Supports:**\n * - Internationalized domain names (IDN), e.g. `https://münich.de`\n * - Unicode & emoji paths, e.g. `https://example.com/🎉/page`\n * - Long URLs with multiple queries & fragments, e.g. `https://example.com/path?foo=1#hash`\n * - **Ignores:**\n * - Non-string inputs\n * - Empty or whitespace-only strings\n * - Non-HTTP(S) protocols (ftp, mailto, etc)\n * @param {string | null | undefined} url - The input string containing potential URLs.\n * @returns {string[] | null} An array of extracted URLs or `null` if no URLs are found.\n * @example\n * extractURLs(\"Visit https://example.com and https://例子.公司\");\n * // ➔ [\"https://example.com\", \"https://例子.公司\"]\n * extractURLs(\"Here: https://example.com/🎉/page\");\n * // ➔ [\"https://example.com/🎉/page\"]\n * extractURLs(\"ftp://example.com http://example.com\");\n * // ➔ [\"http://example.com\"]\n */\nexport const extractURLs = (\n url: string | null | undefined\n): string[] | null => {\n if (!isNonEmptyString(url)) return null;\n\n let decoded;\n try {\n decoded = decodeURIComponent(url);\n } catch {\n return null;\n }\n\n // Core regex with lookahead\n const urlPattern = /https?:\\/\\/.*?(?=https?:\\/\\/|\\s|$)/g;\n const matches = decoded.match(urlPattern);\n if (!matches) return null;\n\n // Cleanup trailing punctuation and validation protocol\n const cleaned = matches\n .map((url) => url.replace(/[.,;:!?)]*$/, \"\"))\n .filter((url) => {\n try {\n const u = new URL(url);\n return u.protocol === \"http:\" || u.protocol === \"https:\";\n } catch {\n return false;\n }\n });\n\n return cleaned.length ? cleaned : null;\n};\n","import { isNil } from \"@/predicates/is/isNil\";\nimport { isArray } from \"@/predicates/is/isArray\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\nimport { normalizePathname } from \"./normalizePathname\";\n\n/** --------------------------------------------------------\n * * ***Utility: `getFirstPrefixPathname`.***\n * --------------------------------------------------------\n * **Extract First Valid Prefix from Path Array or String.**\n * - **Main Purpose:**\n * - This function helps extract the first valid URL prefix from various possible inputs.\n * - It is especially useful in routing systems, middleware, or frontend apps that need to\n * decide layout, active navigation, or permissions based on the first segment (or prefix) of a pathname.\n * - **Typical uses include:**\n * - Determining which layout to render (e.g., `/admin` vs `/dashboard` vs `/`).\n * - Highlighting the active menu item in a sidebar based on the current URL.\n * - Enforcing route guards or access controls depending on the URL prefix.\n * - Parsing multi-level route prefixes and selecting the most relevant one.\n * - **Behavior:**\n * - It works as follows:\n * - If `result` is an array of strings, it normalizes each element and returns\n * the first non-root path (i.e., not just `\"/\"`).\n * - If all items normalize to `\"/\"`,\n * it returns the `defaultValue` (normalized).\n * - If `result` is a single string, it normalizes it and returns it if valid,\n * otherwise falls back to the normalized `defaultValue`.\n * - If `result` is `null` or `undefined`, it returns the normalized `defaultValue`.\n * - **Validation & Errors:**\n * - Throws a `TypeError` if:\n * - `defaultValue` is not a string or empty-string.\n * - `result` is an array that contains non-string elements.\n * - `result` is a value that is neither `string`, `string[]`, nor `null`.\n * @example\n * 1. #### For React (*Determining layout*):\n * ```ts\n * const prefix = getFirstPrefixPathname(\n * getPrefixPathname(\n * \"/admin/settings\",\n * [\"/admin\", \"/dashboard\"]\n * )\n * );\n *\n * if (prefix === \"/admin\") {\n * renderAdminLayout();\n * }\n * ```\n *\n * 2. #### Setting active menu state:\n * ```ts\n * const activeSection = getFirstPrefixPathname([\"\", \"/dashboard\", \"/profile\"]);\n * // ➔ \"/dashboard\"\n * ```\n *\n * 3. #### Providing graceful fallback:\n * ```ts\n * const section = getFirstPrefixPathname([], \"/home\");\n * // ➔ \"/home\"\n * ```\n * 4. #### ✅ Using with an Array of Pathnames:\n * ```ts\n * const result = getPrefixPathname([\" \", \"/dashboard\", \"/settings\"]);\n * console.log(getFirstPrefixPathname(result));\n * // ➔ \"/dashboard\"\n * ```\n *\n * 5. #### ✅ Using with Single String:\n * ```ts\n * console.log(getFirstPrefixPathname(\"/profile/settings\"));\n * // ➔ \"/profile/settings\"\n * console.log(getFirstPrefixPathname(\" \"));\n * // ➔ \"/\"\n * ```\n *\n * 6. #### ✅ Fallback to Custom Default:\n * ```ts\n * console.log(getFirstPrefixPathname([\" \", \"\"], \"/home\"));\n * // ➔ \"/home\"\n * console.log(getFirstPrefixPathname(null, \"/dashboard\"));\n * // ➔ \"/dashboard\"\n * ```\n *\n * 7. #### ✅ Throws on Invalid Input:\n * ```ts\n * getFirstPrefixPathname([1, 2] as any); // ➔ ❌ throws TypeError\n * getFirstPrefixPathname({} as any); // ➔ ❌ throws TypeError\n * getFirstPrefixPathname(null, \" \"); // ➔ ❌ throws TypeError\n * ```\n * @param {string | string[] | null | undefined} result\n * ***The pathname(s) to process, can be:***\n * - A string path (e.g. `\"/profile\"`),\n * - An array of string paths (e.g. `[\" \", \"/dashboard\"]`),\n * - Or `null`.\n * @param {string} [defaultValue=\"/\"]\n * ***A custom default path to use if `result` is null or no valid prefix is found, behavior:***\n * - Must be a string and non-empty string.\n * - Defaults to `\"/\"`.\n * @returns {string}\n * ***The first valid normalized pathname, or the normalized default.***\n * @throws **{@link TypeError | `TypeError`}** ***if `result` is not a valid type, or `defaultValue` is not a string or empty-string.***\n */\nexport const getFirstPrefixPathname = (\n result: string | string[] | null | undefined,\n defaultValue: string = \"/\"\n): string => {\n if (!isNonEmptyString(defaultValue)) {\n throw new TypeError(\n `Second parameter (\\`defaultValue\\`) must be of type \\`string\\` and not an \\`empty-string\\`, but received: \\`${getPreciseType(\n defaultValue\n )}\\`, with value: \\`${safeStableStringify(defaultValue, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n if (isArray(result)) {\n if (!result.every((item) => isString(item))) {\n throw new TypeError(\n `First parameter (\\`result\\`) must be of type \\`string\\` or \\`array of string\\`, but received: \\`${getPreciseType(\n result\n )}\\`, with value: \\`${safeStableStringify(result, {\n keepUndefined: true\n })}\\`.`\n );\n }\n\n for (const item of result) {\n const normalized = normalizePathname(item);\n if (normalized !== \"/\") {\n return normalized;\n }\n }\n return normalizePathname(defaultValue);\n }\n\n if (isString(result)) {\n const normalized = normalizePathname(result);\n return normalized !== \"/\" ? normalized : normalizePathname(defaultValue);\n }\n\n if (!isNil(result)) {\n throw new TypeError(\n `First parameter (\\`result\\`) must be of type \\`string\\`, \\`array-string\\`, \\`null\\` or \\`undefined\\`, but received: \\`${getPreciseType(\n result\n )}\\`.`\n );\n }\n\n return normalizePathname(defaultValue);\n};\n","import { joinLines, EOL } from \"@rzl-zone/build-tools/utils\";\n\nimport { isNull } from \"@/predicates/is/isNull\";\nimport { isArray } from \"@/predicates/is/isArray\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isInteger } from \"@/predicates/is/isInteger\";\nimport { isBoolean } from \"@/predicates/is/isBoolean\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyArray } from \"@/predicates/is/isNonEmptyArray\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { normalizePathname } from \"./normalizePathname\";\n\ntype GetPrefixPathnameOptions = {\n /** The number of levels to include in the prefix (default is `1`).\n *\n * - For example, with `levels = 2`, the function will return the first two parts of the URL.\n *\n * @default 1\n */\n levels?: number;\n /** Whether to remove duplicates from the result if multiple URLs are passed (default is `true`).\n *\n * @default true\n */\n removeDuplicates?: boolean;\n};\n\n/** --------------------------------------------------------\n * * ***Utility: `getPrefixPathname`.***\n * --------------------------------------------------------\n * **Get Prefix from URL with Optional Base or Auto-detection (Supports String or Array of URLs).**\n * - **This function extracts the prefix from one or more URLs. It can either:**\n * - Use a provided `base` string or an array of strings to check and return the matching prefix.\n * - Automatically detect the prefix if no `base` is provided by analyzing the first part of the URL.\n * - **The function is flexible and can handle both scenarios:**\n * 1. **When the base is provided as a single string or an array of strings**:\n * - The function will check if the URL starts with one of the provided base(s) and return the matching base.\n * 2. **When the base is not provided**:\n * - The function will automatically detect the prefix by splitting the URL or using a regex.\n * - **Important Notes**:\n * - If a base (or an array of bases) is provided, the URL must start with one of the given base(s).\n * - If no base is provided, the function will attempt to detect the prefix automatically.\n * - The `url` parameter can be either a string or an array of strings.\n * - Supports deduplication of results (enabled by default).\n * - Automatically returns a single string if only one unique result exists after processing.\n * @param {string|string[]} url\n * ***The full URL(s) from which the prefix should be extracted, can be a `string` or an `array of strings`.***\n * @param {string|string[]|null} [base=null]\n * ***The base URL(s) (e.g., `\"/settings\"`), behavior:***\n * - It can be a `string`, an `array of strings`, or `null`.\n * - If `provided`, it will be used to check the URL(s).\n * - If `not provided`, the prefix will be auto-detected.\n * @param {GetPrefixPathnameOptions} [options]\n * ***Additional options object:***\n * - `levels` (default `1`): The number of segments to include when auto-detecting the prefix (e.g. `/foo/bar` for `levels: 2`).\n * - `removeDuplicates` (default `true`): Whether to remove duplicate prefixes from the final array result.\n * @returns {string|string[]|null}\n * ***Returns one of:***\n * - A single string if only one unique prefix/base is found.\n * - An array of strings if multiple different prefixes/bases are found.\n * - `null` if no matching base is found when using `base`.\n * @throws **{@link TypeError | `TypeError`}**\n * ***if:***\n * - `url` is `not a string` or `not an array of strings`.\n * - `base` is `not a string`, `array of strings`, or `null`.\n * - `options` is `not an object`.\n * - `levels` is `not a number`.\n * - `removeDuplicates` is `not a boolean`.\n * @example\n * - #### ✅ **Correct Usage (With an Array of URLs and Base):**\n * ```ts\n * const routes = [\n * \"/settings/profile\",\n * \"/settings/password\",\n * \"/settings/other-path\",\n * \"/other-path/xyz\",\n * ];\n *\n * // With base provided as a string\n * routes.forEach(route => {\n * console.log(getPrefixPathname(route, '/settings'));\n * // ➔ \"/settings\"\n * });\n *\n * // With base provided as an array\n * routes.forEach(route => {\n * console.log(getPrefixPathname(route, ['/settings', '/admin']));\n * // ➔ \"/settings\" or \"/admin\" depending on the current URL.\n * });\n * ```\n * - #### ✅ **Correct Usage (With Single URL and Single Base):**\n * ```ts\n * const result = getPrefixPathname(\"/settings/profile\", \"/settings\");\n * console.log(result); // ➔ \"/settings\"\n * ```\n * - #### ✅ **Correct Usage (With Multiple URLs and Single Base):**\n * ```ts\n * const result = getPrefixPathname(\n * [\"/settings/profile\", \"/settings/password\"],\n * \"/settings\"\n * );\n * console.log(result); // ➔ \"/settings\"\n *\n * const result2 = getPrefixPathname(\n * [\"/settings/profile\", \"/other/password\"],\n * \"/other\"\n * );\n * console.log(result2); // ➔ \"/other\"\n * ```\n * - #### ✅ **Correct Usage (With Multiple URLs and Multiple Bases)**\n * ```ts\n * const result = getPrefixPathname(\n * [\"/settings/profile\", \"/admin/password\"],\n * [\"/settings\", \"/admin\"]\n * );\n * console.log(result); // ➔ [\"/settings\", \"/admin\"]\n * ```\n * - #### ✅ **Auto-detection of Prefix**\n * ```ts\n * const result = getPrefixPathname(\"/settings/profile\");\n * console.log(result); // ➔ \"/settings\"\n *\n * const result2 = getPrefixPathname(\n * \"/settings/profile/info\",\n * null,\n * { levels: 2 }\n * );\n * console.log(result2); // ➔ \"/settings/profile\"\n * ```\n * - #### ✅ **Multiple URLs with Auto-detection**\n * ```ts\n * const result = getPrefixPathname([\"/admin/profile\", \"/settings/password\"]);\n * console.log(result); // ➔ [\"/admin\", \"/settings\"]\n * ```\n * - #### ✅ **Handling Duplicates**\n * ```ts\n * const result = getPrefixPathname(\n * [\"/settings/profile\", \"/settings/password\"],\n * \"/settings\"\n * );\n * console.log(result); // ➔ \"/settings\" (deduped to single string)\n *\n * const result2 = getPrefixPathname(\n * [\"/settings/profile\", \"/settings/profile\"],\n * \"/settings\",\n * { removeDuplicates: false }\n * );\n * console.log(result2); // ➔ [\"/settings\", \"/settings\"]\n * ```\n * - #### ❌ **Incorrect Usage (URL Does Not Match Base)**\n * ```ts\n * const result = getPrefixPathname(\"/other-path/profile\", \"/settings\");\n * console.log(result); // ➔ null\n * ```\n */\nexport const getPrefixPathname = (\n url: string | string[],\n base: string | string[] | null = null,\n options: GetPrefixPathnameOptions = {}\n): string | string[] | null => {\n const errors: string[] = [];\n\n if (!isString(url) && !isArray(url)) {\n errors.push(\n `First parameter (\\`url\\`) must be of type \\`string\\` or \\`array-string\\`, but received: \\`${getPreciseType(\n url\n )}\\`.`\n );\n }\n if (!isString(base) && !isArray(base) && !isNull(base)) {\n errors.push(\n `Second parameter (\\`base\\`) must be of type \\`string\\`, \\`array-string\\` or \\`null\\`, but received: \\`${getPreciseType(\n base\n )}\\`.`\n );\n }\n if (!isPlainObject(options)) {\n errors.push(\n `Second parameter (\\`options\\`) must be of type \\`plain-object\\`, but received: \\`${getPreciseType(\n options\n )}\\`.`\n );\n }\n\n const { levels = 1, removeDuplicates = true } = options;\n\n if (!isInteger(levels) || (isInteger(levels) && levels < 0)) {\n errors.push(\n `Parameter \\`levels\\` property of the \\`options\\` (second parameter) must be of type \\`integer-number\\` and minimum is \\`0\\`, but received: \\`${getPreciseType(\n levels\n )}\\`, with value: \\`${safeStableStringify(levels, {\n keepUndefined: true\n })}\\`.`\n );\n }\n if (!isBoolean(removeDuplicates)) {\n errors.push(\n `Parameter \\`removeDuplicates\\` property of the \\`options\\` (second parameter) must be of type \\`boolean\\`, but received: \\`${getPreciseType(\n removeDuplicates\n )}\\`.`\n );\n }\n if (isNonEmptyArray(errors)) {\n throw new TypeError(\n joinLines(\n \"Invalid parameter(s) in `getPrefixPathname` function:\",\n `- ${errors.join(`${EOL}- `)}`\n )\n );\n }\n\n // Helper function to process a single URL\n function getLevel(singleUrl: string) {\n // If no base is provided, detect the base automatically\n const parts = normalizePathname(singleUrl).split(\"/\").filter(Boolean); // Split URL into parts\n\n // Return the first `levels` parts as the prefix\n return `/${parts.slice(0, levels).join(\"/\")}`;\n }\n\n // Helper function to process a single URL\n function processUrl(singleUrl: string): string | null {\n // If a base is provided, check if URL starts with one of the bases\n if (base) {\n singleUrl = normalizePathname(singleUrl);\n\n if (isArray(base)) {\n // Check if the URL starts with any of the base values in the array\n for (const b of base) {\n if (singleUrl.startsWith(normalizePathname(b))) {\n // return normalizePathname(b); // Return the matching base if URL starts with it\n return getLevel(singleUrl);\n }\n }\n } else if (\n isNonEmptyString(base) &&\n singleUrl.startsWith(normalizePathname(base))\n ) {\n // If base is a single string, check if URL starts with it\n // return normalizePathname(base); // Return the base if URL starts with it\n return getLevel(singleUrl);\n }\n return null; // Return null if the URL does not match any base\n }\n\n return getLevel(singleUrl);\n }\n\n // If url is an array, process each URL and return an array of results\n if (isArray(url)) {\n const result = url.map(processUrl).filter((r): r is string => !isNull(r));\n\n // Remove duplicates if required\n const uniqueResult = removeDuplicates ? [...new Set(result)] : result;\n\n // If all results are the same, return just the first one\n if (uniqueResult.length === 1) {\n return uniqueResult[0] ?? null;\n }\n\n return uniqueResult;\n }\n\n // If url is a single string, process it and return the result\n return processUrl(url);\n};\n"],"mappings":"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"}
|