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);