UNPKG

@wordpress/block-editor

Version:
70 lines (63 loc) 1.7 kB
/** * Converts a path to an array of its fragments. * Supports strings, numbers and arrays: * * 'foo' => [ 'foo' ] * 2 => [ '2' ] * [ 'foo', 'bar' ] => [ 'foo', 'bar' ] * * @param {string|number|Array} path Path * @return {Array} Normalized path. */ function normalizePath( path ) { if ( Array.isArray( path ) ) { return path; } else if ( typeof path === 'number' ) { return [ path.toString() ]; } return [ path ]; } /** * Clones an object. * Non-object values are returned unchanged. * * @param {*} object Object to clone. * @return {*} Cloned object, or original literal non-object value. */ function cloneObject( object ) { if ( object && typeof object === 'object' ) { return { ...Object.fromEntries( Object.entries( object ).map( ( [ key, value ] ) => [ key, cloneObject( value ), ] ) ), }; } return object; } /** * Immutably sets a value inside an object. Like `lodash#set`, but returning a * new object. Treats nullish initial values as empty objects. Clones any * nested objects. * * @param {Object} object Object to set a value in. * @param {number|string|Array} path Path in the object to modify. * @param {*} value New value to set. * @return {Object} Cloned object with the new value set. */ export function setImmutably( object, path, value ) { const normalizedPath = normalizePath( path ); const newObject = object ? cloneObject( object ) : {}; normalizedPath.reduce( ( acc, key, i ) => { if ( acc[ key ] === undefined ) { acc[ key ] = {}; } if ( i === normalizedPath.length - 1 ) { acc[ key ] = value; } return acc[ key ]; }, newObject ); return newObject; }