2022-12-09 13:05:31 +01:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { isComponent } from '@metamask/snaps-ui';
|
2023-04-03 18:04:30 +02:00
|
|
|
import { useSelector } from 'react-redux';
|
2022-12-09 13:05:31 +01:00
|
|
|
import MetaMaskTemplateRenderer from '../../metamask-template-renderer/metamask-template-renderer';
|
|
|
|
import {
|
|
|
|
DISPLAY,
|
|
|
|
FLEX_DIRECTION,
|
2023-06-06 12:15:20 +02:00
|
|
|
TypographyVariant,
|
|
|
|
OverflowWrap,
|
|
|
|
FontWeight,
|
2023-04-03 18:04:30 +02:00
|
|
|
TextVariant,
|
2022-12-09 13:05:31 +01:00
|
|
|
} from '../../../../helpers/constants/design-system';
|
|
|
|
import { SnapDelineator } from '../snap-delineator';
|
|
|
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
2022-12-20 11:44:49 +01:00
|
|
|
import Box from '../../../ui/box';
|
2023-04-03 18:04:30 +02:00
|
|
|
import { getSnapName } from '../../../../helpers/utils/util';
|
|
|
|
import { getTargetSubjectMetadata } from '../../../../selectors';
|
|
|
|
import { Text } from '../../../component-library';
|
|
|
|
import { Copyable } from '../copyable';
|
2023-05-03 10:53:58 +02:00
|
|
|
import { DelineatorType } from '../../../../helpers/constants/snaps';
|
2022-12-09 13:05:31 +01:00
|
|
|
|
|
|
|
export const UI_MAPPING = {
|
2023-04-24 12:56:44 +02:00
|
|
|
panel: (props, elementKey) => ({
|
2022-12-09 13:05:31 +01:00
|
|
|
element: 'Box',
|
2023-04-24 12:56:44 +02:00
|
|
|
children: props.children.map((element) =>
|
|
|
|
// eslint-disable-next-line no-use-before-define
|
|
|
|
mapToTemplate(element, elementKey),
|
|
|
|
),
|
2022-12-09 13:05:31 +01:00
|
|
|
props: {
|
|
|
|
display: DISPLAY.FLEX,
|
|
|
|
flexDirection: FLEX_DIRECTION.COLUMN,
|
|
|
|
className: 'snap-ui-renderer__panel',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
heading: (props) => ({
|
|
|
|
element: 'Typography',
|
|
|
|
children: props.value,
|
|
|
|
props: {
|
2023-06-06 12:15:20 +02:00
|
|
|
variant: TypographyVariant.H4,
|
|
|
|
fontWeight: FontWeight.Bold,
|
|
|
|
overflowWrap: OverflowWrap.BreakWord,
|
2022-12-09 13:05:31 +01:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
text: (props) => ({
|
2022-12-13 15:37:20 +01:00
|
|
|
element: 'SnapUIMarkdown',
|
2022-12-09 13:05:31 +01:00
|
|
|
children: props.value,
|
|
|
|
}),
|
|
|
|
spinner: () => ({
|
|
|
|
element: 'Spinner',
|
|
|
|
props: {
|
|
|
|
className: 'snap-ui-renderer__spinner',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
divider: () => ({
|
|
|
|
element: 'hr',
|
|
|
|
props: {
|
|
|
|
className: 'snap-ui-renderer__divider',
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
copyable: (props) => ({
|
|
|
|
element: 'Copyable',
|
|
|
|
props: {
|
|
|
|
text: props.value,
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
|
2022-12-20 11:44:22 +01:00
|
|
|
// TODO: Stop exporting this when we remove the mapToTemplate hack in confirmation templates.
|
2023-04-24 12:56:44 +02:00
|
|
|
export const mapToTemplate = (data, elementKeyIndex) => {
|
2022-12-09 13:05:31 +01:00
|
|
|
const { type } = data;
|
2023-04-24 12:56:44 +02:00
|
|
|
elementKeyIndex.value += 1;
|
|
|
|
const indexKey = `snap_ui_element_${type}__${elementKeyIndex.value}`;
|
|
|
|
const mapped = UI_MAPPING[type](data, elementKeyIndex);
|
|
|
|
return { ...mapped, key: indexKey };
|
2022-12-09 13:05:31 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Component that maps Snaps UI JSON format to MetaMask Template Renderer format
|
2023-04-03 18:04:30 +02:00
|
|
|
export const SnapUIRenderer = ({
|
|
|
|
snapId,
|
|
|
|
delineatorType = DelineatorType.Content,
|
|
|
|
data,
|
|
|
|
}) => {
|
2022-12-09 13:05:31 +01:00
|
|
|
const t = useI18nContext();
|
2023-04-03 18:04:30 +02:00
|
|
|
const targetSubjectMetadata = useSelector((state) =>
|
|
|
|
getTargetSubjectMetadata(state, snapId),
|
|
|
|
);
|
2022-12-09 13:05:31 +01:00
|
|
|
|
2023-04-03 18:04:30 +02:00
|
|
|
const snapName = getSnapName(snapId, targetSubjectMetadata);
|
2022-12-09 13:05:31 +01:00
|
|
|
|
|
|
|
if (!isComponent(data)) {
|
|
|
|
return (
|
2023-04-03 18:04:30 +02:00
|
|
|
<SnapDelineator snapName={snapName} type={DelineatorType.Error}>
|
|
|
|
<Text variant={TextVariant.bodySm} marginBottom={4}>
|
|
|
|
{t('snapsUIError', [<b key="0">{snapName}</b>])}
|
|
|
|
</Text>
|
|
|
|
<Copyable text={t('snapsInvalidUIError')} />
|
2022-12-09 13:05:31 +01:00
|
|
|
</SnapDelineator>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-04-24 12:56:44 +02:00
|
|
|
const elementKeyIndex = { value: 0 };
|
|
|
|
const sections = mapToTemplate(data, elementKeyIndex);
|
2022-12-09 13:05:31 +01:00
|
|
|
|
|
|
|
return (
|
2023-04-03 18:04:30 +02:00
|
|
|
<SnapDelineator snapName={snapName} type={delineatorType}>
|
2022-12-20 11:44:49 +01:00
|
|
|
<Box className="snap-ui-renderer__content">
|
|
|
|
<MetaMaskTemplateRenderer sections={sections} />
|
|
|
|
</Box>
|
2022-12-09 13:05:31 +01:00
|
|
|
</SnapDelineator>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
SnapUIRenderer.propTypes = {
|
|
|
|
snapId: PropTypes.string,
|
2023-04-03 18:04:30 +02:00
|
|
|
delineatorType: PropTypes.string,
|
2022-12-09 13:05:31 +01:00
|
|
|
data: PropTypes.object,
|
|
|
|
};
|