import * as React from "react"; import ConfigurationMapSection from "./ConfigurationMapSection"; import ConfigurationMapHeading, { HeadingLevel } from "./ConfigurationMapHeading"; import ConfigurationMapRow from "./ConfigurationMapRow"; import ConfigurationMapLabel from "./ConfigurationMapLabel"; import ConfigurationMapValue from "./ConfigurationMapValue"; type Hash = { [key: string]: React.ReactNode | Hash; }; interface HashMapProps { /** * Content to render if no value is available */ defaultValue?: string; /** * The data to render. Keys are rendered as labels, values are rendered as the value */ hash: Hash; /** * Priority of the heading that the `headline` prop renders in. Numbers map to

through

*/ headingLevel?: HeadingLevel; /** * The heading that labels the data */ headline?: React.ReactNode; /** * Optional object with keys consisting of keys in the `hash` prop to be replaced, and with corresponding values of the replacement to be rendered. */ renderKeys?: { [key: string]: string }; } function isHashMap(value) { // Check whether we are trying to render an object that is not a // React component return ( typeof value === "object" && !Array.isArray(value) && value !== null && !React.isValidElement(value) ); } function formatValue(value, defaultValue) { if (typeof value === "boolean") { value = value.toString(); } if (Array.isArray(value)) { value = value.join(", "); } if (!value && defaultValue) { value = defaultValue; } return value; } const HashMap = ({ hash, headline, headingLevel = 1, renderKeys, defaultValue = "-" }: HashMapProps) => { if (!hash || Object.keys(hash).length === 0) { return null; } return ( {headline && ( {headline} )} {Object.entries(hash).map(([key, value]) => { if (value && isHashMap(value)) { return ( ); } // I think this is verifying that it is an object if ( renderKeys && Object.prototype.hasOwnProperty.call(renderKeys, key) ) { key = renderKeys[key]; } return ( {key} {formatValue(value, defaultValue)} ); })} ); }; export default React.memo(HashMap);