diff --git a/src/rendering/Box/index.js b/src/rendering/Box/index.js new file mode 100644 index 0000000..9fc4498 --- /dev/null +++ b/src/rendering/Box/index.js @@ -0,0 +1,85 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { getBBox } from 'layout'; + +import * as style from './style'; + +const Box = ({ + theme, + radius, + label, + width, + height, + rectTransform, + labelTransform, + contentTransform, + children +}) => { + const rectProps = { + style: style[theme], + width, + height, + rx: radius, + ry: radius, + transform: rectTransform + }; + const textProps = { + transform: labelTransform, + style: style.infoText + }; + + return <> + + { label && { label } } + + { children } + + ; +}; + +Box.defaultProps = { + padding: 5, + radius: 3 +}; + +Box.propTypes = { + theme: PropTypes.string, + radius: PropTypes.number, + padding: PropTypes.number, + label: PropTypes.string, + width: PropTypes.number, + height: PropTypes.number, + rectTransform: PropTypes.string, + labelTransform: PropTypes.string, + contentTransform: PropTypes.string, + children: PropTypes.node +}; + +const layout = data => { + const { label, padding } = { + ...Box.defaultProps, + ...data.props + }; + const childBox = data.children[0].box; + const labelBox = label ? + getBBox({ label }) : + { width: 0, height: 0 }; + + data.box = { + width: Math.max(childBox.width + 2 * padding, labelBox.width), + height: childBox.height + 2 * padding + labelBox.height + }; + data.props = { + ...data.props, + width: data.box.width, + height: childBox.height + 2 * padding, + rectTransform: `translate(0 ${ labelBox.height })`, + labelTransform: `translate(0 ${ labelBox.height })`, + contentTransform: `translate(${ padding } ${ padding + labelBox.height })` + }; + return data; +}; + +export default Box; +export { layout }; diff --git a/src/rendering/Box/style.js b/src/rendering/Box/style.js new file mode 100644 index 0000000..ada161b --- /dev/null +++ b/src/rendering/Box/style.js @@ -0,0 +1,38 @@ +import { + green, + brown, + tan, + grey, + blue, + fontFamily, + fontSizeSmall, + strokeBase +} from 'rendering/style'; + +export const literal = { + fill: blue, + strokeWidth: '1px', + stroke: brown +}; +export const escape = { + fill: green, + strokeWidth: '1px', + stroke: brown +}; +export const charClass = { + fill: tan +}; +export const capture = { + fillOpacity: 0, + ...strokeBase, + stroke: grey, + strokeDasharray: '6,2' +}; +export const anchor = { + fill: brown +}; +export const infoText = { + fontSize: fontSizeSmall, + fontFamily: fontFamily, + dominantBaseline: 'text-after-edge' +}; diff --git a/src/rendering/types.js b/src/rendering/types.js index 88beaeb..da7e963 100644 --- a/src/rendering/types.js +++ b/src/rendering/types.js @@ -1,7 +1,9 @@ import * as SVG from 'rendering/SVG'; import * as Text from 'rendering/Text'; +import * as Box from 'rendering/Box'; export default { SVG, - Text + Text, + Box }; diff --git a/src/syntax/js.js b/src/syntax/js.js index a3c68bd..02e0478 100644 --- a/src/syntax/js.js +++ b/src/syntax/js.js @@ -6,12 +6,20 @@ const parse = expr => { type: 'SVG', children: [ { - type: 'Text', + type: 'Box', props: { - quoted: true + theme: 'literal' }, children: [ - `JS => ${ expr }` + { + type: 'Text', + props: { + quoted: true + }, + children: [ + `JS => ${ expr }` + ] + } ] } ] diff --git a/src/syntax/pcre.js b/src/syntax/pcre.js index 997046a..12b2fa4 100644 --- a/src/syntax/pcre.js +++ b/src/syntax/pcre.js @@ -6,12 +6,20 @@ const parse = expr => { type: 'SVG', children: [ { - type: 'Text', + type: 'Box', props: { - quoted: true + theme: 'literal' }, children: [ - `PCRE => ${ expr }` + { + type: 'Text', + props: { + quoted: true + }, + children: [ + `PCRE => ${ expr }` + ] + } ] } ]