@fluixi/utils 1.0.0-alpha.100
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/LICENSE +21 -0
- package/README.md +68 -0
- package/dist/index.cjs +2858 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +2838 -0
- package/dist/lib/array/advanced.cjs +2227 -0
- package/dist/lib/array/advanced.d.ts +1116 -0
- package/dist/lib/array/advanced.d.ts.map +1 -0
- package/dist/lib/array/advanced.js +2429 -0
- package/dist/lib/array/advanced.mjs +2204 -0
- package/dist/lib/array/array.cjs +57 -0
- package/dist/lib/array/array.d.ts +6 -0
- package/dist/lib/array/array.d.ts.map +1 -0
- package/dist/lib/array/array.js +31 -0
- package/dist/lib/array/array.mjs +36 -0
- package/dist/lib/array/index.cjs +2344 -0
- package/dist/lib/array/index.d.ts +4 -0
- package/dist/lib/array/index.d.ts.map +1 -0
- package/dist/lib/array/index.js +3 -0
- package/dist/lib/array/index.mjs +2322 -0
- package/dist/lib/array/utils.cjs +103 -0
- package/dist/lib/array/utils.d.ts +100 -0
- package/dist/lib/array/utils.d.ts.map +1 -0
- package/dist/lib/array/utils.js +165 -0
- package/dist/lib/array/utils.mjs +82 -0
- package/dist/lib/color/color.cjs +2190 -0
- package/dist/lib/color/color.d.ts +366 -0
- package/dist/lib/color/color.d.ts.map +1 -0
- package/dist/lib/color/color.js +722 -0
- package/dist/lib/color/color.mjs +2167 -0
- package/dist/lib/color/constants.cjs +380 -0
- package/dist/lib/color/constants.d.ts +361 -0
- package/dist/lib/color/constants.d.ts.map +1 -0
- package/dist/lib/color/constants.js +358 -0
- package/dist/lib/color/constants.mjs +359 -0
- package/dist/lib/color/conversions.cjs +629 -0
- package/dist/lib/color/conversions.d.ts +166 -0
- package/dist/lib/color/conversions.d.ts.map +1 -0
- package/dist/lib/color/conversions.js +766 -0
- package/dist/lib/color/conversions.mjs +608 -0
- package/dist/lib/color/helpers.cjs +2534 -0
- package/dist/lib/color/helpers.d.ts +75 -0
- package/dist/lib/color/helpers.d.ts.map +1 -0
- package/dist/lib/color/helpers.js +419 -0
- package/dist/lib/color/helpers.mjs +2511 -0
- package/dist/lib/color/index.cjs +2641 -0
- package/dist/lib/color/index.d.ts +12 -0
- package/dist/lib/color/index.d.ts.map +1 -0
- package/dist/lib/color/index.js +15 -0
- package/dist/lib/color/index.mjs +2619 -0
- package/dist/lib/color/types.cjs +18 -0
- package/dist/lib/color/types.d.ts +179 -0
- package/dist/lib/color/types.d.ts.map +1 -0
- package/dist/lib/color/types.js +1 -0
- package/dist/lib/color/types.mjs +0 -0
- package/dist/lib/color/utils.cjs +962 -0
- package/dist/lib/color/utils.d.ts +199 -0
- package/dist/lib/color/utils.d.ts.map +1 -0
- package/dist/lib/color/utils.js +858 -0
- package/dist/lib/color/utils.mjs +939 -0
- package/dist/lib/compare/comparators.cjs +171 -0
- package/dist/lib/compare/comparators.d.ts +65 -0
- package/dist/lib/compare/comparators.d.ts.map +1 -0
- package/dist/lib/compare/comparators.js +210 -0
- package/dist/lib/compare/comparators.mjs +150 -0
- package/dist/lib/compare/index.cjs +172 -0
- package/dist/lib/compare/index.d.ts +2 -0
- package/dist/lib/compare/index.d.ts.map +1 -0
- package/dist/lib/compare/index.js +1 -0
- package/dist/lib/compare/index.mjs +152 -0
- package/dist/lib/cookie/codec.cjs +72 -0
- package/dist/lib/cookie/codec.d.ts +22 -0
- package/dist/lib/cookie/codec.d.ts.map +1 -0
- package/dist/lib/cookie/codec.js +67 -0
- package/dist/lib/cookie/codec.mjs +51 -0
- package/dist/lib/cookie/index.cjs +75 -0
- package/dist/lib/cookie/index.d.ts +2 -0
- package/dist/lib/cookie/index.d.ts.map +1 -0
- package/dist/lib/cookie/index.js +1 -0
- package/dist/lib/cookie/index.mjs +53 -0
- package/dist/lib/crypto/hash.cjs +83 -0
- package/dist/lib/crypto/hash.d.ts +6 -0
- package/dist/lib/crypto/hash.d.ts.map +1 -0
- package/dist/lib/crypto/hash.js +53 -0
- package/dist/lib/crypto/hash.mjs +62 -0
- package/dist/lib/crypto/index.cjs +85 -0
- package/dist/lib/crypto/index.d.ts +2 -0
- package/dist/lib/crypto/index.d.ts.map +1 -0
- package/dist/lib/crypto/index.js +1 -0
- package/dist/lib/crypto/index.mjs +62 -0
- package/dist/lib/dom/events.cjs +40 -0
- package/dist/lib/dom/events.d.ts +159 -0
- package/dist/lib/dom/events.d.ts.map +1 -0
- package/dist/lib/dom/events.js +50 -0
- package/dist/lib/dom/events.mjs +19 -0
- package/dist/lib/dom/index.cjs +78 -0
- package/dist/lib/dom/index.d.ts +3 -0
- package/dist/lib/dom/index.d.ts.map +1 -0
- package/dist/lib/dom/index.js +2 -0
- package/dist/lib/dom/index.mjs +56 -0
- package/dist/lib/dom/utils.cjs +57 -0
- package/dist/lib/dom/utils.d.ts +6 -0
- package/dist/lib/dom/utils.d.ts.map +1 -0
- package/dist/lib/dom/utils.js +37 -0
- package/dist/lib/dom/utils.mjs +36 -0
- package/dist/lib/functions/functions.cjs +366 -0
- package/dist/lib/functions/functions.d.ts +329 -0
- package/dist/lib/functions/functions.d.ts.map +1 -0
- package/dist/lib/functions/functions.js +585 -0
- package/dist/lib/functions/functions.mjs +345 -0
- package/dist/lib/functions/index.cjs +369 -0
- package/dist/lib/functions/index.d.ts +3 -0
- package/dist/lib/functions/index.d.ts.map +1 -0
- package/dist/lib/functions/index.js +1 -0
- package/dist/lib/functions/index.mjs +347 -0
- package/dist/lib/functions/types.cjs +18 -0
- package/dist/lib/functions/types.d.ts +2 -0
- package/dist/lib/functions/types.d.ts.map +1 -0
- package/dist/lib/functions/types.js +1 -0
- package/dist/lib/functions/types.mjs +0 -0
- package/dist/lib/helpers.cjs +78 -0
- package/dist/lib/helpers.d.ts +13 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +66 -0
- package/dist/lib/helpers.mjs +59 -0
- package/dist/lib/index.cjs +2857 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +2836 -0
- package/dist/lib/maths/constants.cjs +70 -0
- package/dist/lib/maths/constants.d.ts +84 -0
- package/dist/lib/maths/constants.d.ts.map +1 -0
- package/dist/lib/maths/constants.js +79 -0
- package/dist/lib/maths/constants.mjs +50 -0
- package/dist/lib/maths/fn/advanced.cjs +231 -0
- package/dist/lib/maths/fn/advanced.d.ts +149 -0
- package/dist/lib/maths/fn/advanced.d.ts.map +1 -0
- package/dist/lib/maths/fn/advanced.js +264 -0
- package/dist/lib/maths/fn/advanced.mjs +208 -0
- package/dist/lib/maths/fn/basic.cjs +212 -0
- package/dist/lib/maths/fn/basic.d.ts +182 -0
- package/dist/lib/maths/fn/basic.d.ts.map +1 -0
- package/dist/lib/maths/fn/basic.js +343 -0
- package/dist/lib/maths/fn/basic.mjs +191 -0
- package/dist/lib/maths/fn/complex.cjs +268 -0
- package/dist/lib/maths/fn/complex.d.ts +153 -0
- package/dist/lib/maths/fn/complex.d.ts.map +1 -0
- package/dist/lib/maths/fn/complex.js +383 -0
- package/dist/lib/maths/fn/complex.mjs +247 -0
- package/dist/lib/maths/fn/index.cjs +877 -0
- package/dist/lib/maths/fn/index.d.ts +10 -0
- package/dist/lib/maths/fn/index.d.ts.map +1 -0
- package/dist/lib/maths/fn/index.js +9 -0
- package/dist/lib/maths/fn/index.mjs +855 -0
- package/dist/lib/maths/fn/trigo.cjs +179 -0
- package/dist/lib/maths/fn/trigo.d.ts +147 -0
- package/dist/lib/maths/fn/trigo.d.ts.map +1 -0
- package/dist/lib/maths/fn/trigo.js +227 -0
- package/dist/lib/maths/fn/trigo.mjs +156 -0
- package/dist/lib/maths/fn/vector.cjs +728 -0
- package/dist/lib/maths/fn/vector.d.ts +512 -0
- package/dist/lib/maths/fn/vector.d.ts.map +1 -0
- package/dist/lib/maths/fn/vector.js +1136 -0
- package/dist/lib/maths/fn/vector.mjs +707 -0
- package/dist/lib/maths/formatter.cjs +61 -0
- package/dist/lib/maths/formatter.d.ts +35 -0
- package/dist/lib/maths/formatter.d.ts.map +1 -0
- package/dist/lib/maths/formatter.js +56 -0
- package/dist/lib/maths/formatter.mjs +40 -0
- package/dist/lib/maths/guards.cjs +164 -0
- package/dist/lib/maths/guards.d.ts +166 -0
- package/dist/lib/maths/guards.d.ts.map +1 -0
- package/dist/lib/maths/guards.js +315 -0
- package/dist/lib/maths/guards.mjs +144 -0
- package/dist/lib/maths/index.cjs +1152 -0
- package/dist/lib/maths/index.d.ts +24 -0
- package/dist/lib/maths/index.d.ts.map +1 -0
- package/dist/lib/maths/index.js +29 -0
- package/dist/lib/maths/index.mjs +1130 -0
- package/dist/lib/maths/parser.cjs +75 -0
- package/dist/lib/maths/parser.d.ts +20 -0
- package/dist/lib/maths/parser.d.ts.map +1 -0
- package/dist/lib/maths/parser.js +78 -0
- package/dist/lib/maths/parser.mjs +54 -0
- package/dist/lib/maths/random.cjs +49 -0
- package/dist/lib/maths/random.d.ts +27 -0
- package/dist/lib/maths/random.d.ts.map +1 -0
- package/dist/lib/maths/random.js +49 -0
- package/dist/lib/maths/random.mjs +28 -0
- package/dist/lib/maths/types/advanced.cjs +18 -0
- package/dist/lib/maths/types/advanced.d.ts +357 -0
- package/dist/lib/maths/types/advanced.d.ts.map +1 -0
- package/dist/lib/maths/types/advanced.js +5 -0
- package/dist/lib/maths/types/advanced.mjs +0 -0
- package/dist/lib/maths/types/basic.cjs +18 -0
- package/dist/lib/maths/types/basic.d.ts +95 -0
- package/dist/lib/maths/types/basic.d.ts.map +1 -0
- package/dist/lib/maths/types/basic.js +5 -0
- package/dist/lib/maths/types/basic.mjs +0 -0
- package/dist/lib/maths/types/index.cjs +19 -0
- package/dist/lib/maths/types/index.d.ts +4 -0
- package/dist/lib/maths/types/index.d.ts.map +1 -0
- package/dist/lib/maths/types/index.js +3 -0
- package/dist/lib/maths/types/index.mjs +1 -0
- package/dist/lib/maths/types/negative.cjs +18 -0
- package/dist/lib/maths/types/negative.d.ts +51 -0
- package/dist/lib/maths/types/negative.d.ts.map +1 -0
- package/dist/lib/maths/types/negative.js +5 -0
- package/dist/lib/maths/types/negative.mjs +0 -0
- package/dist/lib/maths/types/operations.cjs +18 -0
- package/dist/lib/maths/types/operations.d.ts +188 -0
- package/dist/lib/maths/types/operations.d.ts.map +1 -0
- package/dist/lib/maths/types/operations.js +6 -0
- package/dist/lib/maths/types/operations.mjs +0 -0
- package/dist/lib/object/clone.cjs +88 -0
- package/dist/lib/object/clone.d.ts +46 -0
- package/dist/lib/object/clone.d.ts.map +1 -0
- package/dist/lib/object/clone.js +104 -0
- package/dist/lib/object/clone.mjs +65 -0
- package/dist/lib/object/diff.cjs +573 -0
- package/dist/lib/object/diff.d.ts +203 -0
- package/dist/lib/object/diff.d.ts.map +1 -0
- package/dist/lib/object/diff.js +805 -0
- package/dist/lib/object/diff.mjs +550 -0
- package/dist/lib/object/getter-setter.cjs +2351 -0
- package/dist/lib/object/getter-setter.d.ts +361 -0
- package/dist/lib/object/getter-setter.d.ts.map +1 -0
- package/dist/lib/object/getter-setter.js +1771 -0
- package/dist/lib/object/getter-setter.mjs +2330 -0
- package/dist/lib/object/index.cjs +3956 -0
- package/dist/lib/object/index.d.ts +13 -0
- package/dist/lib/object/index.d.ts.map +1 -0
- package/dist/lib/object/index.js +12 -0
- package/dist/lib/object/index.mjs +3936 -0
- package/dist/lib/object/merge.cjs +1029 -0
- package/dist/lib/object/merge.d.ts +93 -0
- package/dist/lib/object/merge.d.ts.map +1 -0
- package/dist/lib/object/merge.js +474 -0
- package/dist/lib/object/merge.mjs +1006 -0
- package/dist/lib/object/object.cjs +280 -0
- package/dist/lib/object/object.d.ts +128 -0
- package/dist/lib/object/object.d.ts.map +1 -0
- package/dist/lib/object/object.js +432 -0
- package/dist/lib/object/object.mjs +257 -0
- package/dist/lib/object/omit.cjs +2022 -0
- package/dist/lib/object/omit.d.ts +351 -0
- package/dist/lib/object/omit.d.ts.map +1 -0
- package/dist/lib/object/omit.js +656 -0
- package/dist/lib/object/omit.mjs +1999 -0
- package/dist/lib/object/reconcile.cjs +126 -0
- package/dist/lib/object/reconcile.d.ts +7 -0
- package/dist/lib/object/reconcile.d.ts.map +1 -0
- package/dist/lib/object/reconcile.js +122 -0
- package/dist/lib/object/reconcile.mjs +105 -0
- package/dist/lib/object/selector.cjs +303 -0
- package/dist/lib/object/selector.d.ts +50 -0
- package/dist/lib/object/selector.d.ts.map +1 -0
- package/dist/lib/object/selector.js +371 -0
- package/dist/lib/object/selector.mjs +282 -0
- package/dist/lib/object/sort.cjs +209 -0
- package/dist/lib/object/sort.d.ts +149 -0
- package/dist/lib/object/sort.d.ts.map +1 -0
- package/dist/lib/object/sort.js +298 -0
- package/dist/lib/object/sort.mjs +186 -0
- package/dist/lib/object/transform.cjs +2211 -0
- package/dist/lib/object/transform.d.ts +620 -0
- package/dist/lib/object/transform.d.ts.map +1 -0
- package/dist/lib/object/transform.js +1058 -0
- package/dist/lib/object/transform.mjs +2190 -0
- package/dist/lib/object/types.cjs +18 -0
- package/dist/lib/object/types.d.ts +250 -0
- package/dist/lib/object/types.d.ts.map +1 -0
- package/dist/lib/object/types.js +1 -0
- package/dist/lib/object/types.mjs +0 -0
- package/dist/lib/object/utils.cjs +326 -0
- package/dist/lib/object/utils.d.ts +165 -0
- package/dist/lib/object/utils.d.ts.map +1 -0
- package/dist/lib/object/utils.js +444 -0
- package/dist/lib/object/utils.mjs +305 -0
- package/dist/lib/primitive/boolean/boolean.cjs +407 -0
- package/dist/lib/primitive/boolean/boolean.d.ts +276 -0
- package/dist/lib/primitive/boolean/boolean.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/boolean.js +615 -0
- package/dist/lib/primitive/boolean/boolean.mjs +386 -0
- package/dist/lib/primitive/boolean/index.cjs +382 -0
- package/dist/lib/primitive/boolean/index.d.ts +3 -0
- package/dist/lib/primitive/boolean/index.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/index.js +2 -0
- package/dist/lib/primitive/boolean/index.mjs +359 -0
- package/dist/lib/primitive/boolean/types.cjs +18 -0
- package/dist/lib/primitive/boolean/types.d.ts +14 -0
- package/dist/lib/primitive/boolean/types.d.ts.map +1 -0
- package/dist/lib/primitive/boolean/types.js +1 -0
- package/dist/lib/primitive/boolean/types.mjs +0 -0
- package/dist/lib/primitive/date/date.cjs +1126 -0
- package/dist/lib/primitive/date/date.d.ts +641 -0
- package/dist/lib/primitive/date/date.d.ts.map +1 -0
- package/dist/lib/primitive/date/date.js +1998 -0
- package/dist/lib/primitive/date/date.mjs +1105 -0
- package/dist/lib/primitive/date/index.cjs +1128 -0
- package/dist/lib/primitive/date/index.d.ts +3 -0
- package/dist/lib/primitive/date/index.d.ts.map +1 -0
- package/dist/lib/primitive/date/index.js +2 -0
- package/dist/lib/primitive/date/index.mjs +1105 -0
- package/dist/lib/primitive/date/types.cjs +18 -0
- package/dist/lib/primitive/date/types.d.ts +205 -0
- package/dist/lib/primitive/date/types.d.ts.map +1 -0
- package/dist/lib/primitive/date/types.js +7 -0
- package/dist/lib/primitive/date/types.mjs +0 -0
- package/dist/lib/primitive/index.cjs +2338 -0
- package/dist/lib/primitive/index.d.ts +5 -0
- package/dist/lib/primitive/index.d.ts.map +1 -0
- package/dist/lib/primitive/index.js +4 -0
- package/dist/lib/primitive/index.mjs +2316 -0
- package/dist/lib/primitive/string/index.cjs +875 -0
- package/dist/lib/primitive/string/index.d.ts +3 -0
- package/dist/lib/primitive/string/index.d.ts.map +1 -0
- package/dist/lib/primitive/string/index.js +2 -0
- package/dist/lib/primitive/string/index.mjs +852 -0
- package/dist/lib/primitive/string/parser-2.cjs +543 -0
- package/dist/lib/primitive/string/parser-2.d.ts +17 -0
- package/dist/lib/primitive/string/parser-2.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser-2.js +656 -0
- package/dist/lib/primitive/string/parser-2.mjs +522 -0
- package/dist/lib/primitive/string/parser.cjs +236 -0
- package/dist/lib/primitive/string/parser.d.ts +9 -0
- package/dist/lib/primitive/string/parser.d.ts.map +1 -0
- package/dist/lib/primitive/string/parser.js +775 -0
- package/dist/lib/primitive/string/parser.mjs +215 -0
- package/dist/lib/primitive/string/string.cjs +926 -0
- package/dist/lib/primitive/string/string.d.ts +535 -0
- package/dist/lib/primitive/string/string.d.ts.map +1 -0
- package/dist/lib/primitive/string/string.js +1301 -0
- package/dist/lib/primitive/string/string.mjs +903 -0
- package/dist/lib/primitive/string/types.cjs +18 -0
- package/dist/lib/primitive/string/types.d.ts +318 -0
- package/dist/lib/primitive/string/types.d.ts.map +1 -0
- package/dist/lib/primitive/string/types.js +5 -0
- package/dist/lib/primitive/string/types.mjs +0 -0
- package/dist/lib/primitive/types.cjs +18 -0
- package/dist/lib/primitive/types.d.ts +27 -0
- package/dist/lib/primitive/types.d.ts.map +1 -0
- package/dist/lib/primitive/types.js +1 -0
- package/dist/lib/primitive/types.mjs +0 -0
- package/dist/lib/url/index.cjs +327 -0
- package/dist/lib/url/index.d.ts +3 -0
- package/dist/lib/url/index.d.ts.map +1 -0
- package/dist/lib/url/index.js +2 -0
- package/dist/lib/url/index.mjs +304 -0
- package/dist/lib/url/parser.cjs +325 -0
- package/dist/lib/url/parser.d.ts +216 -0
- package/dist/lib/url/parser.d.ts.map +1 -0
- package/dist/lib/url/parser.js +488 -0
- package/dist/lib/url/parser.mjs +304 -0
- package/dist/lib/url/types.cjs +18 -0
- package/dist/lib/url/types.d.ts +18 -0
- package/dist/lib/url/types.d.ts.map +1 -0
- package/dist/lib/url/types.js +1 -0
- package/dist/lib/url/types.mjs +0 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +127 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { isPlainObject } from './utils.js';
|
|
2
|
+
// ─── Internal helpers ─────────────────────────────────────────────────────────
|
|
3
|
+
/** Read a value via dot-notation path, e.g. `'address.city'`. */
|
|
4
|
+
function getAtPath(obj, path) {
|
|
5
|
+
if (obj == null)
|
|
6
|
+
return undefined;
|
|
7
|
+
let cur = obj;
|
|
8
|
+
for (const segment of path.split('.')) {
|
|
9
|
+
if (cur == null)
|
|
10
|
+
return undefined;
|
|
11
|
+
cur = cur[segment];
|
|
12
|
+
}
|
|
13
|
+
return cur;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Natural, type-aware comparison.
|
|
17
|
+
* Returns negative / zero / positive like `Array.prototype.sort` expects.
|
|
18
|
+
* Handles: null/undefined (always pushed last), NaN, Date, boolean, number, string.
|
|
19
|
+
* Falls back to locale-aware string coercion for mixed / unknown types.
|
|
20
|
+
*/
|
|
21
|
+
function compareValues(a, b, locale, localeOptions) {
|
|
22
|
+
// null / undefined: treated as "greater than anything" so they sink to the end
|
|
23
|
+
const aN = a == null;
|
|
24
|
+
const bN = b == null;
|
|
25
|
+
if (aN && bN)
|
|
26
|
+
return 0;
|
|
27
|
+
if (aN)
|
|
28
|
+
return 1;
|
|
29
|
+
if (bN)
|
|
30
|
+
return -1;
|
|
31
|
+
// NaN: sink below null
|
|
32
|
+
const aNaN = typeof a === 'number' && Number.isNaN(a);
|
|
33
|
+
const bNaN = typeof b === 'number' && Number.isNaN(b);
|
|
34
|
+
if (aNaN && bNaN)
|
|
35
|
+
return 0;
|
|
36
|
+
if (aNaN)
|
|
37
|
+
return 1;
|
|
38
|
+
if (bNaN)
|
|
39
|
+
return -1;
|
|
40
|
+
// Date
|
|
41
|
+
if (a instanceof Date && b instanceof Date) {
|
|
42
|
+
return a.getTime() - b.getTime();
|
|
43
|
+
}
|
|
44
|
+
// Boolean (false < true)
|
|
45
|
+
if (typeof a === 'boolean' && typeof b === 'boolean') {
|
|
46
|
+
return (a === b ? 0 : a ? 1 : -1);
|
|
47
|
+
}
|
|
48
|
+
// Number (covers BigInt with coercion below)
|
|
49
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
50
|
+
return a - b;
|
|
51
|
+
}
|
|
52
|
+
// String: locale-aware
|
|
53
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
54
|
+
return a.localeCompare(b, locale, localeOptions);
|
|
55
|
+
}
|
|
56
|
+
// Fallback: coerce both to string
|
|
57
|
+
return String(a).localeCompare(String(b), locale, localeOptions);
|
|
58
|
+
}
|
|
59
|
+
/** Build a single numeric direction multiplier for the i-th sort key. */
|
|
60
|
+
function dirFor(order, i) {
|
|
61
|
+
const o = Array.isArray(order) ? (order[i] ?? 'asc') : (order ?? 'asc');
|
|
62
|
+
return o === 'desc' ? -1 : 1;
|
|
63
|
+
}
|
|
64
|
+
// ─── Core sort functions ──────────────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* Sort a flat array of primitives, Dates, or mixed values using natural
|
|
67
|
+
* comparison. Respects `order`, `locale`, `localeOptions`, and `nullsLast`.
|
|
68
|
+
*/
|
|
69
|
+
function sortPrimitiveArray(arr, options) {
|
|
70
|
+
const { order, locale, localeOptions, nullsLast = true } = options;
|
|
71
|
+
const dir = dirFor(order, 0);
|
|
72
|
+
return arr.slice().sort((a, b) => {
|
|
73
|
+
const aN = a == null;
|
|
74
|
+
const bN = b == null;
|
|
75
|
+
if (aN && bN)
|
|
76
|
+
return 0;
|
|
77
|
+
if (aN)
|
|
78
|
+
return nullsLast ? 1 : -1;
|
|
79
|
+
if (bN)
|
|
80
|
+
return nullsLast ? -1 : 1;
|
|
81
|
+
return compareValues(a, b, locale, localeOptions) * dir;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Sort an array of objects by one or more key paths.
|
|
86
|
+
* Keys are compared left-to-right; the next key is only consulted when all
|
|
87
|
+
* previous keys produced a tie.
|
|
88
|
+
*/
|
|
89
|
+
function sortObjectArray(arr, keys, options) {
|
|
90
|
+
const { order, locale, localeOptions, nullsLast = true, comparator } = options;
|
|
91
|
+
if (comparator) {
|
|
92
|
+
return arr.slice().sort(comparator);
|
|
93
|
+
}
|
|
94
|
+
return arr.slice().sort((a, b) => {
|
|
95
|
+
for (let i = 0; i < keys.length; i++) {
|
|
96
|
+
const aVal = getAtPath(a, keys[i]);
|
|
97
|
+
const bVal = getAtPath(b, keys[i]);
|
|
98
|
+
const aN = aVal == null;
|
|
99
|
+
const bN = bVal == null;
|
|
100
|
+
if (aN && bN)
|
|
101
|
+
continue;
|
|
102
|
+
if (aN)
|
|
103
|
+
return nullsLast ? 1 : -1;
|
|
104
|
+
if (bN)
|
|
105
|
+
return nullsLast ? -1 : 1;
|
|
106
|
+
const cmp = compareValues(aVal, bVal, locale, localeOptions);
|
|
107
|
+
if (cmp !== 0)
|
|
108
|
+
return cmp * dirFor(order, i);
|
|
109
|
+
}
|
|
110
|
+
return 0;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Return a new plain object whose own keys are sorted alphabetically, with
|
|
115
|
+
* `priorityKeys` pinned to the front. Values are left untouched unless
|
|
116
|
+
* `deep` is set.
|
|
117
|
+
*/
|
|
118
|
+
function sortRecord(record, options) {
|
|
119
|
+
const { order, priorityKeys = [], locale, localeOptions, deep } = options;
|
|
120
|
+
const dir = dirFor(order, 0);
|
|
121
|
+
const prioritySet = new Set(priorityKeys);
|
|
122
|
+
const rest = Object.keys(record).filter((k) => !prioritySet.has(k));
|
|
123
|
+
rest.sort((a, b) => a.localeCompare(b, locale, localeOptions) * dir);
|
|
124
|
+
const ordered = [...priorityKeys.filter((k) => k in record), ...rest];
|
|
125
|
+
const result = {};
|
|
126
|
+
for (const key of ordered) {
|
|
127
|
+
result[key] = deep ? sortDeep(record[key], options) : record[key];
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Recursively sort a value: sorts arrays in place (returning new array) and
|
|
133
|
+
* sorts record-object keys. Primitives and non-plain objects are returned
|
|
134
|
+
* unchanged.
|
|
135
|
+
*/
|
|
136
|
+
function sortDeep(value, options) {
|
|
137
|
+
if (Array.isArray(value)) {
|
|
138
|
+
// Deep-sort elements first, then sort the array itself
|
|
139
|
+
const deepSorted = value.map((item) => sortDeep(item, options));
|
|
140
|
+
return sortArrayValue(deepSorted, options);
|
|
141
|
+
}
|
|
142
|
+
if (isPlainObject(value)) {
|
|
143
|
+
return sortRecord(value, options);
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Apply an explicit index permutation to an array.
|
|
149
|
+
*
|
|
150
|
+
* `indices[i]` names the source index that appears at position `i` in the
|
|
151
|
+
* output. Input elements not named by any index are appended at the end in
|
|
152
|
+
* their original relative order. Out-of-range indices are ignored.
|
|
153
|
+
*/
|
|
154
|
+
function applyIndices(arr, indices) {
|
|
155
|
+
const len = arr.length;
|
|
156
|
+
const used = new Set();
|
|
157
|
+
const result = [];
|
|
158
|
+
for (const idx of indices) {
|
|
159
|
+
if (idx >= 0 && idx < len && !used.has(idx)) {
|
|
160
|
+
result.push(arr[idx]);
|
|
161
|
+
used.add(idx);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Append any elements not covered by the permutation
|
|
165
|
+
for (let i = 0; i < len; i++) {
|
|
166
|
+
if (!used.has(i))
|
|
167
|
+
result.push(arr[i]);
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Dispatch array sorting to the appropriate strategy based on the options
|
|
173
|
+
* present: explicit index permutation → value-based sort → direction-only.
|
|
174
|
+
*/
|
|
175
|
+
function sortArrayValue(arr, options) {
|
|
176
|
+
const { by, comparator, indices, order } = options;
|
|
177
|
+
// ── Explicit index permutation ───────────────────────────────────────────
|
|
178
|
+
if (indices) {
|
|
179
|
+
const permuted = applyIndices(arr, indices);
|
|
180
|
+
// order: 'desc' reverses the permuted result
|
|
181
|
+
return dirFor(order, 0) === -1 ? permuted.reverse() : permuted;
|
|
182
|
+
}
|
|
183
|
+
// ── Custom comparator ────────────────────────────────────────────────────
|
|
184
|
+
if (comparator) {
|
|
185
|
+
return arr.slice().sort(comparator);
|
|
186
|
+
}
|
|
187
|
+
// ── Key-based sort ───────────────────────────────────────────────────────
|
|
188
|
+
if (by) {
|
|
189
|
+
const keys = Array.isArray(by) ? by : [by];
|
|
190
|
+
return sortObjectArray(arr, keys, options);
|
|
191
|
+
}
|
|
192
|
+
// ── No key: object arrays are ordered by index position ──────────────────
|
|
193
|
+
// asc = natural order (unchanged)
|
|
194
|
+
// desc = reverse the array
|
|
195
|
+
const firstReal = arr.find((x) => x != null);
|
|
196
|
+
if (firstReal != null && isPlainObject(firstReal)) {
|
|
197
|
+
return dirFor(order, 0) === -1 ? arr.slice().reverse() : arr.slice();
|
|
198
|
+
}
|
|
199
|
+
// ── Primitive array ──────────────────────────────────────────────────────
|
|
200
|
+
return sortPrimitiveArray(arr, options);
|
|
201
|
+
}
|
|
202
|
+
export function sort(input, options = {}) {
|
|
203
|
+
const { deep } = options;
|
|
204
|
+
if (Array.isArray(input)) {
|
|
205
|
+
const items = deep
|
|
206
|
+
? input.map((item) => sortDeep(item, options))
|
|
207
|
+
: input;
|
|
208
|
+
return sortArrayValue(items, options);
|
|
209
|
+
}
|
|
210
|
+
if (isPlainObject(input)) {
|
|
211
|
+
return sortRecord(input, options);
|
|
212
|
+
}
|
|
213
|
+
return input;
|
|
214
|
+
}
|
|
215
|
+
// ─── Convenience helpers ──────────────────────────────────────────────────────
|
|
216
|
+
/**
|
|
217
|
+
* Sort an array of objects by one or more key paths, returning a new array.
|
|
218
|
+
* Shorthand for `sort(arr, { by: key, order })`.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* sortBy(users, 'name')
|
|
222
|
+
* sortBy(users, ['lastName', 'firstName'], 'asc')
|
|
223
|
+
* sortBy(products, 'price', 'desc')
|
|
224
|
+
*/
|
|
225
|
+
export function sortBy(arr, by, order = 'asc', options = {}) {
|
|
226
|
+
return sort(arr, { ...options, by, order });
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Sort the keys of a record object, returning a new object.
|
|
230
|
+
* Shorthand for `sort(record, { order, priorityKeys, deep })`.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* sortKeys({ z: 1, a: 2 }) // { a: 2, z: 1 }
|
|
234
|
+
* sortKeys(obj, { priorityKeys: ['id', 'type'] })
|
|
235
|
+
* sortKeys(tree, { deep: true })
|
|
236
|
+
*/
|
|
237
|
+
export function sortKeys(record, options = {}) {
|
|
238
|
+
return sort(record, options);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Move an element from one index to another, shifting the elements in between.
|
|
242
|
+
* Returns a new array; the original is not mutated.
|
|
243
|
+
*
|
|
244
|
+
* - Clamps `from` and `to` to valid array bounds.
|
|
245
|
+
* - When `from === to` the original array is returned as-is (same reference).
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* move(['a','b','c','d'], 0, 2) // ['b','c','a','d'] (first → third)
|
|
249
|
+
* move(['a','b','c','d'], 3, 1) // ['a','d','b','c'] (last → second)
|
|
250
|
+
* move(users, fromIndex, toIndex)
|
|
251
|
+
*/
|
|
252
|
+
export function move(arr, from, to) {
|
|
253
|
+
const len = arr.length;
|
|
254
|
+
if (len === 0)
|
|
255
|
+
return arr.slice();
|
|
256
|
+
const f = Math.max(0, Math.min(len - 1, from));
|
|
257
|
+
const t = Math.max(0, Math.min(len - 1, to));
|
|
258
|
+
if (f === t)
|
|
259
|
+
return arr.slice();
|
|
260
|
+
const result = arr.slice();
|
|
261
|
+
const [item] = result.splice(f, 1);
|
|
262
|
+
result.splice(t, 0, item);
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Swap two elements by index, returning a new array.
|
|
267
|
+
* The original array is not mutated.
|
|
268
|
+
* Out-of-range indices throw a `RangeError`.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* swap(['a','b','c'], 0, 2) // ['c','b','a']
|
|
272
|
+
* swap(users, 1, 3)
|
|
273
|
+
*/
|
|
274
|
+
export function swap(arr, i, j) {
|
|
275
|
+
const len = arr.length;
|
|
276
|
+
if (i < 0 || i >= len)
|
|
277
|
+
throw new RangeError(`swap: index ${i} out of range`);
|
|
278
|
+
if (j < 0 || j >= len)
|
|
279
|
+
throw new RangeError(`swap: index ${j} out of range`);
|
|
280
|
+
if (i === j)
|
|
281
|
+
return arr.slice();
|
|
282
|
+
const result = arr.slice();
|
|
283
|
+
result[i] = arr[j];
|
|
284
|
+
result[j] = arr[i];
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Reorder an array by providing the full desired sequence of source indices.
|
|
289
|
+
* Shorthand for `sort(arr, { indices })`.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* reorder(['a','b','c'], [2, 0, 1]) // ['c','a','b']
|
|
293
|
+
* reorder(tabs, newIndexOrder) // apply UI drag-and-drop result
|
|
294
|
+
* reorder(rows, [3,1,0,2], 'desc') // permute then reverse
|
|
295
|
+
*/
|
|
296
|
+
export function reorder(arr, indices, order = 'asc') {
|
|
297
|
+
return sort(arr, { indices, order });
|
|
298
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// src/lib/object/utils.ts
|
|
2
|
+
function isPlainObject(v) {
|
|
3
|
+
if (typeof v !== "object" || v === null) return false;
|
|
4
|
+
const proto = Object.getPrototypeOf(v);
|
|
5
|
+
return proto === Object.prototype || proto === null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/lib/object/sort.ts
|
|
9
|
+
function getAtPath(obj, path) {
|
|
10
|
+
if (obj == null) return void 0;
|
|
11
|
+
let cur = obj;
|
|
12
|
+
for (const segment of path.split(".")) {
|
|
13
|
+
if (cur == null) return void 0;
|
|
14
|
+
cur = cur[segment];
|
|
15
|
+
}
|
|
16
|
+
return cur;
|
|
17
|
+
}
|
|
18
|
+
function compareValues(a, b, locale, localeOptions) {
|
|
19
|
+
const aN = a == null;
|
|
20
|
+
const bN = b == null;
|
|
21
|
+
if (aN && bN) return 0;
|
|
22
|
+
if (aN) return 1;
|
|
23
|
+
if (bN) return -1;
|
|
24
|
+
const aNaN = typeof a === "number" && Number.isNaN(a);
|
|
25
|
+
const bNaN = typeof b === "number" && Number.isNaN(b);
|
|
26
|
+
if (aNaN && bNaN) return 0;
|
|
27
|
+
if (aNaN) return 1;
|
|
28
|
+
if (bNaN) return -1;
|
|
29
|
+
if (a instanceof Date && b instanceof Date) {
|
|
30
|
+
return a.getTime() - b.getTime();
|
|
31
|
+
}
|
|
32
|
+
if (typeof a === "boolean" && typeof b === "boolean") {
|
|
33
|
+
return a === b ? 0 : a ? 1 : -1;
|
|
34
|
+
}
|
|
35
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
36
|
+
return a - b;
|
|
37
|
+
}
|
|
38
|
+
if (typeof a === "string" && typeof b === "string") {
|
|
39
|
+
return a.localeCompare(b, locale, localeOptions);
|
|
40
|
+
}
|
|
41
|
+
return String(a).localeCompare(String(b), locale, localeOptions);
|
|
42
|
+
}
|
|
43
|
+
function dirFor(order, i) {
|
|
44
|
+
const o = Array.isArray(order) ? order[i] ?? "asc" : order ?? "asc";
|
|
45
|
+
return o === "desc" ? -1 : 1;
|
|
46
|
+
}
|
|
47
|
+
function sortPrimitiveArray(arr, options) {
|
|
48
|
+
const { order, locale, localeOptions, nullsLast = true } = options;
|
|
49
|
+
const dir = dirFor(order, 0);
|
|
50
|
+
return arr.slice().sort((a, b) => {
|
|
51
|
+
const aN = a == null;
|
|
52
|
+
const bN = b == null;
|
|
53
|
+
if (aN && bN) return 0;
|
|
54
|
+
if (aN) return nullsLast ? 1 : -1;
|
|
55
|
+
if (bN) return nullsLast ? -1 : 1;
|
|
56
|
+
return compareValues(a, b, locale, localeOptions) * dir;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
function sortObjectArray(arr, keys, options) {
|
|
60
|
+
const { order, locale, localeOptions, nullsLast = true, comparator } = options;
|
|
61
|
+
if (comparator) {
|
|
62
|
+
return arr.slice().sort(comparator);
|
|
63
|
+
}
|
|
64
|
+
return arr.slice().sort((a, b) => {
|
|
65
|
+
for (let i = 0; i < keys.length; i++) {
|
|
66
|
+
const aVal = getAtPath(a, keys[i]);
|
|
67
|
+
const bVal = getAtPath(b, keys[i]);
|
|
68
|
+
const aN = aVal == null;
|
|
69
|
+
const bN = bVal == null;
|
|
70
|
+
if (aN && bN) continue;
|
|
71
|
+
if (aN) return nullsLast ? 1 : -1;
|
|
72
|
+
if (bN) return nullsLast ? -1 : 1;
|
|
73
|
+
const cmp = compareValues(aVal, bVal, locale, localeOptions);
|
|
74
|
+
if (cmp !== 0) return cmp * dirFor(order, i);
|
|
75
|
+
}
|
|
76
|
+
return 0;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function sortRecord(record, options) {
|
|
80
|
+
const { order, priorityKeys = [], locale, localeOptions, deep } = options;
|
|
81
|
+
const dir = dirFor(order, 0);
|
|
82
|
+
const prioritySet = new Set(priorityKeys);
|
|
83
|
+
const rest = Object.keys(record).filter((k) => !prioritySet.has(k));
|
|
84
|
+
rest.sort(
|
|
85
|
+
(a, b) => a.localeCompare(b, locale, localeOptions) * dir
|
|
86
|
+
);
|
|
87
|
+
const ordered = [...priorityKeys.filter((k) => k in record), ...rest];
|
|
88
|
+
const result = {};
|
|
89
|
+
for (const key of ordered) {
|
|
90
|
+
result[key] = deep ? sortDeep(record[key], options) : record[key];
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
function sortDeep(value, options) {
|
|
95
|
+
if (Array.isArray(value)) {
|
|
96
|
+
const deepSorted = value.map((item) => sortDeep(item, options));
|
|
97
|
+
return sortArrayValue(deepSorted, options);
|
|
98
|
+
}
|
|
99
|
+
if (isPlainObject(value)) {
|
|
100
|
+
return sortRecord(value, options);
|
|
101
|
+
}
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
function applyIndices(arr, indices) {
|
|
105
|
+
const len = arr.length;
|
|
106
|
+
const used = /* @__PURE__ */ new Set();
|
|
107
|
+
const result = [];
|
|
108
|
+
for (const idx of indices) {
|
|
109
|
+
if (idx >= 0 && idx < len && !used.has(idx)) {
|
|
110
|
+
result.push(arr[idx]);
|
|
111
|
+
used.add(idx);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (let i = 0; i < len; i++) {
|
|
115
|
+
if (!used.has(i)) result.push(arr[i]);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
function sortArrayValue(arr, options) {
|
|
120
|
+
const { by, comparator, indices, order } = options;
|
|
121
|
+
if (indices) {
|
|
122
|
+
const permuted = applyIndices(arr, indices);
|
|
123
|
+
return dirFor(order, 0) === -1 ? permuted.reverse() : permuted;
|
|
124
|
+
}
|
|
125
|
+
if (comparator) {
|
|
126
|
+
return arr.slice().sort(comparator);
|
|
127
|
+
}
|
|
128
|
+
if (by) {
|
|
129
|
+
const keys = Array.isArray(by) ? by : [by];
|
|
130
|
+
return sortObjectArray(arr, keys, options);
|
|
131
|
+
}
|
|
132
|
+
const firstReal = arr.find((x) => x != null);
|
|
133
|
+
if (firstReal != null && isPlainObject(firstReal)) {
|
|
134
|
+
return dirFor(order, 0) === -1 ? arr.slice().reverse() : arr.slice();
|
|
135
|
+
}
|
|
136
|
+
return sortPrimitiveArray(arr, options);
|
|
137
|
+
}
|
|
138
|
+
function sort(input, options = {}) {
|
|
139
|
+
const { deep } = options;
|
|
140
|
+
if (Array.isArray(input)) {
|
|
141
|
+
const items = deep ? input.map((item) => sortDeep(item, options)) : input;
|
|
142
|
+
return sortArrayValue(items, options);
|
|
143
|
+
}
|
|
144
|
+
if (isPlainObject(input)) {
|
|
145
|
+
return sortRecord(input, options);
|
|
146
|
+
}
|
|
147
|
+
return input;
|
|
148
|
+
}
|
|
149
|
+
function sortBy(arr, by, order = "asc", options = {}) {
|
|
150
|
+
return sort(arr, { ...options, by, order });
|
|
151
|
+
}
|
|
152
|
+
function sortKeys(record, options = {}) {
|
|
153
|
+
return sort(record, options);
|
|
154
|
+
}
|
|
155
|
+
function move(arr, from, to) {
|
|
156
|
+
const len = arr.length;
|
|
157
|
+
if (len === 0) return arr.slice();
|
|
158
|
+
const f = Math.max(0, Math.min(len - 1, from));
|
|
159
|
+
const t = Math.max(0, Math.min(len - 1, to));
|
|
160
|
+
if (f === t) return arr.slice();
|
|
161
|
+
const result = arr.slice();
|
|
162
|
+
const [item] = result.splice(f, 1);
|
|
163
|
+
result.splice(t, 0, item);
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
function swap(arr, i, j) {
|
|
167
|
+
const len = arr.length;
|
|
168
|
+
if (i < 0 || i >= len) throw new RangeError(`swap: index ${i} out of range`);
|
|
169
|
+
if (j < 0 || j >= len) throw new RangeError(`swap: index ${j} out of range`);
|
|
170
|
+
if (i === j) return arr.slice();
|
|
171
|
+
const result = arr.slice();
|
|
172
|
+
result[i] = arr[j];
|
|
173
|
+
result[j] = arr[i];
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
function reorder(arr, indices, order = "asc") {
|
|
177
|
+
return sort(arr, { indices, order });
|
|
178
|
+
}
|
|
179
|
+
export {
|
|
180
|
+
move,
|
|
181
|
+
reorder,
|
|
182
|
+
sort,
|
|
183
|
+
sortBy,
|
|
184
|
+
sortKeys,
|
|
185
|
+
swap
|
|
186
|
+
};
|