feat: Refactor layouts in www

This commit is contained in:
deytenit committed 2026-03-07 20:59:03 +03:00
1 parent 6aa3a03319
commit f3a3a52aa8
66 files changed
+1805 -352

No files matched your search

+1
View File
@@ -1,4 +1,5 @@
export * from './types/index.js';
export * from './functions/index.js';
export * from './object/index.js';
export * from './window/localStorage.js';
export * from './react/index.js';
+6
View File
@@ -0,0 +1,6 @@
/**
* Object utilities for common operations on objects.
*/
export { merge } from './merge/merge';
export type { MergeOptions } from './merge/merge';
@@ -0,0 +1,108 @@
import { merge } from './merge';
/**
* Test suite for the merge utility function.
*/
describe('shared/helpers/object/merge', () => {
it('deeply merges two objects, preserving source values by default', () => {
const source = { a: 1, b: { c: 2 } };
const target = { a: 3, b: { c: 4, d: 5 }, e: 6 };
const result = merge(source, target);
expect(result).toEqual({
a: 1, // force is false, so 1 is preserved
b: {
c: 2, // force is false, so 2 is preserved
d: 5, // added because it was not in source
},
e: 6, // added because it was not in source
});
});
it('deeply merges two objects and overrides values when force is true', () => {
const source = { a: 1, b: { c: 2 } };
const target = { a: 3, b: { c: 4, d: 5 }, e: 6 };
const result = merge(source, target, { force: true });
expect(result).toEqual({
a: 3,
b: {
c: 4,
d: 5,
},
e: 6,
});
});
it('concatenates arrays when both are present at the same key', () => {
const source = { a: [1, 2] };
const target = { a: [3, 4] };
const result = merge(source, target);
expect(result).toEqual({ a: [1, 2, 3, 4] });
});
it('handles primitive values at the root', () => {
expect(merge(1, 2)).toBe(1);
expect(merge(1, 2, { force: true })).toBe(2);
});
it('handles mixed types between source and target', () => {
const source = { a: { b: 1 } };
const target = { a: [1, 2] };
// Source wins because force is false
expect(merge(source, target)).toEqual({ a: { b: 1 } });
// Target wins because force is true
expect(merge(source, target, { force: true })).toEqual({ a: [1, 2] });
});
it('handles deep recursion with arrays and objects', () => {
const source = {
users: [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
],
config: {
retries: 3,
enabled: true,
},
};
const target = {
users: [{ id: 3, name: 'Doe' }],
config: {
retries: 5,
timeout: 1000,
},
};
const result = merge(source, target);
expect(result).toEqual({
users: [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 3, name: 'Doe' },
],
config: {
retries: 3,
enabled: true,
timeout: 1000,
},
});
});
it('preserves the source when target has undefined values', () => {
const source = { a: 1 };
const target = { a: undefined };
expect(merge(source, target)).toEqual({ a: 1 });
});
it('replaces undefined source with target', () => {
const source = { a: undefined };
const target = { a: 1 };
expect(merge(source, target)).toEqual({ a: 1 });
});
});
@@ -0,0 +1,76 @@
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unnecessary-type-assertion */
/**
* Options for the merge utility.
*/
export interface MergeOptions {
/**
* Whether to override existing primitive values in the source with values from the target.
* If false, existing primitive values are preserved.
* @default false
*/
force?: boolean;
}
/**
* Deeply merges two values (objects, arrays, or primitives).
*
* Behavior:
* - If both values are arrays, they are concatenated.
* - If both values are objects, they are merged recursively.
* - If encounter a primitive value, it is overridden only if `force` is set to true.
* - If a key exists in target but not in source, it is added to the result.
*
* @param source - The source value to merge from
* @param target - The target value to merge with
* @param options - Merge configuration options
* @returns The merged result
*
* @example
* ```typescript
* merge({ a: 1 }, { a: 2 }) // { a: 1 }
* merge({ a: 1 }, { a: 2 }, { force: true }) // { a: 2 }
* merge({ a: [1] }, { a: [2] }) // { a: [1, 2] }
* merge({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: 1, c: 2 } }
* ```
*/
export function merge<T = any>(source: any, target: any, options: MergeOptions = {}): T {
const { force = false } = options;
// If target is undefined, source wins
if (target === undefined) {
return source;
}
// If source is undefined, target wins
if (source === undefined) {
return target;
}
const sourceIsArray = Array.isArray(source);
const targetIsArray = Array.isArray(target);
// If both are arrays, concatenate
if (sourceIsArray && targetIsArray) {
return [...source, ...target] as any;
}
const sourceIsObject = source !== null && typeof source === 'object' && !sourceIsArray;
const targetIsObject = target !== null && typeof target === 'object' && !targetIsArray;
// If both are objects, deep merge
if (sourceIsObject && targetIsObject) {
const result = { ...source };
for (const key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
if (key in source) {
result[key] = merge(source[key], target[key], options);
} else {
result[key] = target[key];
}
}
}
return result as any;
}
// If we encounter primitive values or mixed types, override only if force is true
return force ? target : source;
}