storybook-addon-deep-controls
Version:
A Storybook addon that extends @storybook/addon-controls and provides an alternative to interacting with object arguments
71 lines (70 loc) • 2.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setProperty = setProperty;
exports.getProperty = getProperty;
exports.isPojo = isPojo;
exports.isReactElement = isReactElement;
function setProperty(object, path, value) {
if (!isAnyObject(object)) {
return object; // should be an object but handle if it isn't
}
const remainingPathSegments = path.split(".");
const currentTargetSegment = remainingPathSegments.shift();
if (!currentTargetSegment) {
return object; // invalid path ignore
}
if (!remainingPathSegments.length) {
// we have reached the last segment so set the value
object[currentTargetSegment] = value;
return object;
}
// we have more segments to go so recurse if possible
let nextTargetObj = object[currentTargetSegment];
if (nextTargetObj === undefined) {
// next target doesn't exist so create one in our path
object[currentTargetSegment] = {};
nextTargetObj = object[currentTargetSegment];
// check if we can go further
}
else if (!nextTargetObj || typeof nextTargetObj !== "object") {
return object; // cant go further, invalid path ignore the rest
}
// recurse
setProperty(nextTargetObj, remainingPathSegments.join("."), value);
// need to return the original object, only the top level caller will get this
return object;
}
function getProperty(value, path) {
for (const pathSegment of path.split(".")) {
if (!isAnyObject(value)) {
return; // cant go further, invalid path ignore
}
if (pathSegment in value) {
value = value[pathSegment];
}
else {
return; // invalid path ignore
}
}
return value; // value at the end of the path
}
const POJO_PROTOTYPES = [Object.prototype, null];
/**
* Is the value a simple object, ie a Plain Old Javascript Object,
* not a class instance, function, array etc which are also objects
*
* @internal
*/
function isPojo(val) {
return Boolean(typeof val === "object" &&
val &&
POJO_PROTOTYPES.includes(Object.getPrototypeOf(val)) &&
!isReactElement(val));
}
function isAnyObject(val) {
return typeof val === "object" && val !== null;
}
// NOTE: React has `#isValidElement` utility to check this, however we dont use it here so React isn't a dependency
function isReactElement(val) {
return typeof val.$$typeof === "symbol";
}