1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-05 07:24:56 +01:00
metamask-extension/ui/components/app/metamask-template-renderer/metamask-template-renderer.js
Filip Sekulic 43f7a44c25
Adding popular custom network integration (#14557)
* Initial push

* Refactored the code

* Additional code

* Removed the unused message

* Added a tooltip

* Fixed tests

* Lint fix

* Added style to a tooltip

* Fix e2e test failure

* Lint fix and code revert

* Fix e2e test

* Fixed paddings

* Fixed paddings

* CSS fix

* Minified svg files

* Applied requested changes

* Fixed theme issue

* Code revert

* Added back overridden code

* Icon problem fixed

* Lint fix

* Replaced H3 with H4

* Added unit test

* Added breadcrumbs

* Added const props for networks

* Lint fix

* Lint fix

* Added toggle button for showing the custom network list and resolved few issues

* Fixed routes

* Refactored a piece of code

* Enabled searching for the newly created option

* Fixed unit test

* Updated theme
2022-06-30 13:49:07 -02:30

106 lines
3.2 KiB
JavaScript

import React, { memo } from 'react';
import PropTypes from 'prop-types';
import { isEqual } from 'lodash';
import { safeComponentList } from './safe-component-list';
function getElement(section) {
const { element } = section;
const Element = safeComponentList[element];
if (!Element) {
throw new Error(
`${element} is not in the safe component list for MetaMask template renderer`,
);
}
return Element;
}
const MetaMaskTemplateRenderer = ({ sections }) => {
if (!sections) {
// If sections is null eject early by returning null
return null;
} else if (typeof sections === 'string') {
// React can render strings directly, so return the string
return sections;
} else if (
sections &&
typeof sections === 'object' &&
!Array.isArray(sections)
) {
// If dealing with a single entry, then render a single object without key
const Element = getElement(sections);
return (
<Element {...sections.props}>
{typeof sections.children === 'object' ? (
<MetaMaskTemplateRenderer sections={sections.children} />
) : (
sections?.children
)}
</Element>
);
}
// The last case is dealing with an array of objects
return (
<>
{sections.reduce((allChildren, child) => {
if (child?.hide === true) {
return allChildren;
}
if (typeof child === 'string') {
// React can render strings directly, so push them into the accumulator
allChildren.push(child);
} else {
// If the entry in array is not a string, then it must be a Section.
// Sections are handled by the main function, but must
// be provided a key when a part of an array.
if (!child.key) {
throw new Error(
'When using array syntax in MetaMask Template Language, you must specify a key for each child of the array',
);
}
if (typeof child?.children === 'object') {
// If this child has its own children, check if children is an
// object, and in that case use recursion to render.
allChildren.push(
<MetaMaskTemplateRenderer sections={child} key={child.key} />,
);
} else {
// Otherwise render the element.
const Element = getElement(child);
allChildren.push(
<Element key={child.key} {...child.props}>
{child?.children}
</Element>,
);
}
}
return allChildren;
}, [])}
</>
);
};
export const SectionShape = {
props: PropTypes.object,
element: PropTypes.oneOf(Object.keys(safeComponentList)).isRequired,
key: PropTypes.string,
};
const ValidChildren = PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape(SectionShape),
PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.shape(SectionShape), PropTypes.string]),
),
]);
SectionShape.children = ValidChildren;
MetaMaskTemplateRenderer.propTypes = {
sections: ValidChildren,
};
export default memo(MetaMaskTemplateRenderer, (prevProps, nextProps) => {
return isEqual(prevProps.sections, nextProps.sections);
});