feat(xod-client): new patch board look with bound values

This commit is contained in:
Kirill Shumilov
2019-02-13 13:32:38 +03:00
parent af2f7d3e19
commit 3cf820cf70
25 changed files with 287 additions and 153 deletions

View File

@@ -91,7 +91,7 @@ describe('creating blink patch', () => {
await clockNode.drag(150, 10);
const { x, y } = await clockNode.getBoundingClientRect();
assert.deepEqual({ x, y }, { x: 389, y: 114 });
assert.deepEqual({ x, y }, { x: 399.5, y: 128.5 });
});
it('adds rest of the nodes needed for blink patch', async () => {

View File

@@ -19,7 +19,7 @@ $light-grey: #777;
$light-grey-bright: #999;
$chalk: #ccc;
$chalk-light: #aaa;
$chalk-light: #ddd;
$chalk-bright: #eee;
// Colored

View File

@@ -14,7 +14,7 @@ $color-success: #579205;
$color-canvas-background: $dark-deep;
$color-canvas-background-gridlines: $dark-light;
$color-canvas-face: #646464;
$color-canvas-face-light: #A7A7A7;
$color-canvas-face-light: $chalk-light;
$color-canvas-face-text: #a7a7a7;
$color-canvas-selected: #4ed5ed;
$color-highlight: #eeeeee;
@@ -30,7 +30,7 @@ $color-datatype-custom: $terracotta;
$color-datatype-dead: $error;
$color-node-fill: #222222;
$color-node-outline: #bbbbbb;
$color-node-outline: $light-grey-bright;
$color-pin-fill: #262626;
$color-watch-node-text: $color-canvas-face-text;
@@ -44,7 +44,7 @@ $color-watch-node-highlight-outline: #bce88e;
$color-comment-text: #d0ccc0;
$color-comment-handle: #605f5b;
$color-pinlabel: $color-canvas-face-text; //#8b8b8b;
$color-pinlabel: $grey-bright;
$color-toolbar-background: #b3b3b3;
$color-toolbar-foreground: #000;

View File

@@ -10,7 +10,7 @@
.outline {
fill: transparent;
stroke-width: 2px;
stroke-width: 1px;
}
.container {

View File

@@ -199,7 +199,7 @@
.PinIcon {
pointer-events: none;
float: left;
margin-top: 4px;
margin-top: 7px;
}
label {

View File

@@ -15,7 +15,7 @@
.outline {
fill: transparent;
stroke: $color-node-outline;
stroke-width: 2px;
stroke-width: 1px;
// For terminals:
&.string { stroke: $color-datatype-string; }
@@ -76,6 +76,12 @@
}
}
.terminal-node, .bus-node {
.outline {
stroke-width: 2px;
}
}
.jumper-line {
stroke: $color-node-outline;
stroke-width: 2px;
@@ -117,7 +123,7 @@
// move from under pins
// leave 1px margin on the sides to avoid "gluing" of two nearest labels
margin: 12px 1px;
margin: 11px 1px;
height: calc(100% - 24px);
}
@@ -125,9 +131,10 @@
display: block;
text-align: center;
padding: 0;
font-size: 12px;
font-family: $font-family-condensed;
color: $color-canvas-face-text;
font-size: 13px;
font-family: $font-family-normal;
font-weight: 400;
color: $color-canvas-face-light;
white-space: pre;
overflow: hidden;
text-overflow: ellipsis;
@@ -144,11 +151,11 @@
}
.nodeLabel {
color: $color-highlight;
color: $color-canvas-face-light;
}
.VariadicHandle--grip {
stroke: $color-highlight;
fill: $color-highlight;
}
.NodeResizeHandle {
@@ -173,7 +180,7 @@
}
.VariadicHandle--grip {
stroke: $color-canvas-selected !important;
fill: $color-canvas-selected !important;
}
.NodeResizeHandle {
@@ -185,9 +192,12 @@
pointer-events: none;
opacity: 0.3;
.outline, .VariadicHandle--grip {
.outline {
stroke: $color-node-outline !important;
}
.VariadicHandle--grip {
fill: $color-node-outline !important;
}
.nodeLabel {
visibility: hidden;
}
@@ -201,7 +211,7 @@
color: $color-highlight;
}
.VariadicHandle--grip {
stroke: $color-highlight;
fill: $color-highlight;
}
}
@@ -223,8 +233,7 @@
}
&--grip {
pointer-events: none;
stroke-width: 5px;
stroke-linecap: round;
stroke: $color-node-outline;
fill: $color-node-outline;
stroke-width: 0;
}
}

View File

@@ -87,7 +87,7 @@ $PinInfo-padding-bottom: 10px;
min-height: $node-height;
&--no-inputs {
min-height: 75px;
min-height: 77px;
overflow: hidden;
box-sizing: border-box;
}

View File

@@ -22,7 +22,7 @@
.symbol {
fill: $color-pin-fill;
stroke: $color-datatype-custom;
stroke-width: 2px;
stroke-width: 1.5px;
&.t1, &.t2, &.t3 {
@include symbol-coloring($color-datatype-generic);
@@ -71,9 +71,12 @@
}
.generic-pin-marker {
fill: none;
stroke: $color-datatype-generic;
stroke-width: 2px;
fill: $color-datatype-generic;
stroke-width: 0;
}
.hotspotHelper {
fill: transparent;
}
.linkingHighlight {
@@ -100,7 +103,7 @@
}
.PinOverlay {
.symbol {
.linkingHighlight {
fill: white;
stroke: white;
stroke-width: 2px;
@@ -108,14 +111,13 @@
}
&:hover {
.symbol {
.linkingHighlight {
opacity: 0.5;
}
}
.linkingHighlight {
display: none;
opacity: 0; // just acts as a hotspot
.hotspot {
fill: transparent;
}
&.is-accepting-links, &.is-selected {

View File

@@ -1,14 +1,14 @@
.PinLabel {
font-family: $font-family-condensed;
font-weight: 500;
font-size: 10px;
dominant-baseline: central;
fill: $color-pinlabel;
font-size: 11px;
color: $color-pinlabel;
user-select: none;
&.outline {
stroke: #262626;
stroke-linejoin: round;
stroke-width: 5;
}
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1;
}

View File

@@ -0,0 +1,24 @@
.PinValue {
font-family: $font-family-condensed;
font-weight: 400;
font-size: 11px;
color: $color-datatype-generic;
user-select: none;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1;
// For terminals:
&.string { color: $color-datatype-string; }
&.number { color: $color-datatype-number; }
&.boolean { color: $color-datatype-boolean; }
&.pulse { color: $color-datatype-pulse; }
&.byte { color: $color-datatype-byte; }
&.port { color: $color-datatype-port; }
&.dead, &.conflicting { color: $color-datatype-dead; }
&.self, &.custom { color: $color-datatype-custom; }
}

View File

@@ -7,7 +7,7 @@
margin: 7px 0;
.propertyLabel {
color: $color-canvas-face-light;
color: $color-canvas-face-text;
}
}

View File

@@ -45,6 +45,7 @@
'components/PatchWrapper',
'components/Pin',
'components/PinLabel',
'components/PinValue',
'components/PopupPublishProject',
'components/ProjectBrowser',
'components/Sidebar',

View File

@@ -12,11 +12,11 @@ import { SLOT_SIZE } from '../../project/nodeLayout';
const NODE_POSITION_IN_PREVIEW = {
x: 3,
y: 20, // compensate for labels outside the node
y: 10, // compensate for bound values outside the node
};
const MAX_NODE_WIDTH = 245 - NODE_POSITION_IN_PREVIEW.x * 2;
const NODE_PREVIEW_HEIGHT = 93;
const NODE_PREVIEW_HEIGHT = 85;
const formatPinType = R.when(XP.isGenericType, type => `generic ${type}`);
const getPinTypeClassName = R.when(XP.isGenericType, R.always('generic'));
@@ -152,13 +152,6 @@ const PatchDocs = ({ patch, minimal }) => {
const distanceBetweenPins = minimal ? 0 : scaleFactor * SLOT_SIZE.WIDTH - 1;
// because we never draw labels for terminal nodes
const position = R.when(
() => XP.isTerminalPatchPath(nodeType),
R.assoc('y', XP.isInputTerminalPath(nodeType) ? 32 : 8),
NODE_POSITION_IN_PREVIEW
);
const deprecatedReason = XP.getDeprecationReason(patch);
const cls = cn('PatchDocs', {
@@ -200,10 +193,16 @@ const PatchDocs = ({ patch, minimal }) => {
width={scaledNodeWidth}
height={scaledNodePreviewHeight}
>
<rect className="bg" width="100%" height="100%" />
<g transform={`scale(${scaleFactor})`}>
<Node {...nodeProps} position={position} noEvents />
</g>
<svg x="0.5" y="0.5">
<rect className="bg" width="100%" height="100%" />
<g transform={`scale(${scaleFactor})`}>
<Node
{...nodeProps}
position={NODE_POSITION_IN_PREVIEW}
noEvents
/>
</g>
</svg>
</svg>
)}
</div>

View File

@@ -6,6 +6,7 @@ import * as XP from 'xod-project';
import Pin from './Pin';
import PinLabel from './PinLabel';
import PinValue from './PinValue';
import { noop } from '../../utils/ramda';
import { isPinSelected } from '../../editor/utils';
@@ -207,12 +208,11 @@ class Node extends React.Component {
<g className={pinsCls} id={`nodePins_${id}`}>
{pinsArr.map(pin => (
<g key={pin.key}>
{pin.isConnected || XP.isOutputPin(pin) ? null : (
<PinValue {...pin} key={`pinValue_${pin.key}`} />
)}
{isTerminalNode ? null : (
<PinLabel
{...pin}
keyName={pin.key}
key={`pinlabel_${pin.key}`}
/>
<PinLabel {...pin} key={`pinlabel_${pin.key}`} />
)}
<Pin
{...pin}

View File

@@ -26,10 +26,13 @@ const PatchSVG = ({
ref={svgRef}
{...restProps}
>
<defs>
<DraggedNodeShadowFilter />
</defs>
{children}
{/* Nested svg to compensate bluring of strokes */}
<svg xmlns="http://www.w3.org/2000/svg" x="0.5" y="0.5">
<defs>
<DraggedNodeShadowFilter />
</defs>
{children}
</svg>
</svg>
);

View File

@@ -12,35 +12,6 @@ import {
PIN_HIGHLIGHT_RADIUS,
} from '../nodeLayout';
/**
* An outline of half of the circle, that indicated that Pin is generic
* even it has a deduced type.
*/
// :: Number -> Number -> Boolean -> ReactElement
const genericPinMarker = (pinCircleCenter, output) => {
// To avoid using complex paths we draw just a circle
// but draw only half of the outline by CSS.
// To do it with CSS we have to:
// 1. Calculate the length of the circle (circumference).
const circumference = Math.PI * PIN_RADIUS * 2;
// 2. Calculate distance beetween dashes
const dasharray = 0.5 * circumference;
// 3. And then set `dasharray` to draw a half of outline
// 4. And set `dashoffset` to draw another half (for output Pin)
return (
<circle
className="generic-pin-marker"
{...pinCircleCenter}
r={PIN_RADIUS}
style={{
strokeDashoffset: output ? dasharray : 0,
strokeDasharray: dasharray,
}}
/>
);
};
const Pin = props => {
const isOutput = props.direction === PIN_DIRECTION.OUTPUT;
@@ -104,9 +75,9 @@ const Pin = props => {
r={PIN_INNER_RADIUS}
/>
) : null}
{isGenericType(props.type)
? genericPinMarker(pinCircleCenter, isOutput)
: null}
{isGenericType(props.type) ? (
<circle className="generic-pin-marker" {...pinCircleCenter} r={1} />
) : null}
{variadicDots}
</g>
);

View File

@@ -1,36 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import { PIN_DIRECTION } from 'xod-project';
import { PIN_RADIUS, TEXT_OFFSET_FROM_PIN_BORDER } from '../nodeLayout';
import { PINLABEL_WIDTH, getPinLabelProps } from '../nodeLayout';
const Pin = ({ keyName, label, direction, position }) => {
const textVerticalOffset = PIN_RADIUS + TEXT_OFFSET_FROM_PIN_BORDER;
const isInput = direction === PIN_DIRECTION.INPUT;
const textProps = {
x: position.x,
y: position.y + textVerticalOffset * (isInput ? -1 : 1),
textAnchor: 'middle',
};
const PinLabel = ({ label, direction, position }) => {
const textProps = getPinLabelProps(direction, position);
return label ? (
<g key={`pinText_${keyName}`}>
<text className="PinLabel outline" {...textProps}>
<foreignObject {...textProps}>
<div
className="PinLabel"
xmlns="http://www.w3.org/1999/xhtml"
style={{ width: PINLABEL_WIDTH }}
>
{label}
</text>
<text className="PinLabel" {...textProps}>
{label}
</text>
</g>
</div>
</foreignObject>
) : null;
};
Pin.propTypes = {
keyName: PropTypes.string.isRequired,
PinLabel.propTypes = {
label: PropTypes.string,
direction: PropTypes.string.isRequired,
position: PropTypes.object.isRequired,
};
export default Pin;
export default PinLabel;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { PIN_RADIUS, PIN_HIGHLIGHT_RADIUS } from '../nodeLayout';
import { PIN_HOTSPOT_RADIUS, PIN_HOVER_HIGHLIGHT_RADIUS } from '../nodeLayout';
import deepSCU from '../../utils/deepSCU';
@@ -45,9 +45,13 @@ export default class PinOverlay extends React.Component {
<circle
className="linkingHighlight"
{...pinCircleCenter}
r={PIN_HIGHLIGHT_RADIUS}
r={PIN_HOVER_HIGHLIGHT_RADIUS}
/>
<circle
className="hotspot"
{...pinCircleCenter}
r={PIN_HOTSPOT_RADIUS}
/>
<circle className="symbol" {...pinCircleCenter} r={PIN_RADIUS} />
</g>
);
}

View File

@@ -0,0 +1,60 @@
import React from 'react';
import PropTypes from 'prop-types';
import cls from 'classnames';
import { PIN_TYPE, INPUT_PULSE_PIN_BINDING_OPTIONS } from 'xod-project';
import { unquote } from 'xod-func-tools';
import { PINVALUE_WIDTH, getPinValueProps } from '../nodeLayout';
import { getRenderablePinType } from '../utils';
const formatPulsePinValue = value => {
switch (value) {
case INPUT_PULSE_PIN_BINDING_OPTIONS.CONTINUOUSLY:
return 'Loop';
case INPUT_PULSE_PIN_BINDING_OPTIONS.ON_BOOT:
return 'Boot';
default:
case INPUT_PULSE_PIN_BINDING_OPTIONS.NEVER:
return '';
}
};
const formatPinValue = (type, value) => {
switch (type) {
case PIN_TYPE.STRING:
return unquote(value);
case PIN_TYPE.PULSE:
return formatPulsePinValue(value);
default:
return value;
}
};
const PinValue = ({ value, type, deducedType, direction, position }) => {
const textProps = getPinValueProps(direction, position);
const pinType = getRenderablePinType({ type, deducedType });
const className = cls('PinValue', pinType);
return value ? (
<foreignObject {...textProps}>
<div
className={className}
xmlns="http://www.w3.org/1999/xhtml"
style={{ width: PINVALUE_WIDTH }}
>
{formatPinValue(pinType, value)}
</div>
</foreignObject>
) : null;
};
PinValue.propTypes = {
value: PropTypes.string,
type: PropTypes.string,
deducedType: PropTypes.object,
direction: PropTypes.string.isRequired,
position: PropTypes.object.isRequired,
};
export default PinValue;

View File

@@ -4,19 +4,32 @@ import { noop } from 'xod-func-tools';
import { SLOT_SIZE, NODE_HEIGHT } from '../../nodeLayout';
// Add 0.5 to compensate blurring of pattern
const COMPENSATE_BLUR = 0.5;
const NodeSlotPattern = ({ offset }) => (
<pattern
id="patch_bg_pattern"
x={Math.round(offset.x)}
y={Math.round(offset.y)}
x={Math.round(offset.x) - COMPENSATE_BLUR}
y={Math.round(offset.y) - COMPENSATE_BLUR}
width={SLOT_SIZE.WIDTH}
height={SLOT_SIZE.HEIGHT}
patternUnits="userSpaceOnUse"
>
<g stroke="none" fill="none">
<line x1={1} y1={1} x2={1} y2={NODE_HEIGHT} />
<line x1={0} y1={1} x2={SLOT_SIZE.WIDTH} y2={1} />
<line x1={0} y1={NODE_HEIGHT} x2={SLOT_SIZE.WIDTH} y2={NODE_HEIGHT} />
<line x1={COMPENSATE_BLUR} y1={1} x2={COMPENSATE_BLUR} y2={NODE_HEIGHT} />
<line
x1={0}
y1={COMPENSATE_BLUR}
x2={SLOT_SIZE.WIDTH}
y2={COMPENSATE_BLUR}
/>
<line
x1={0}
y1={NODE_HEIGHT + COMPENSATE_BLUR}
x2={SLOT_SIZE.WIDTH}
y2={NODE_HEIGHT + COMPENSATE_BLUR}
/>
</g>
</pattern>
);

View File

@@ -38,7 +38,7 @@ const BusNodeBody = ({ type, size, pins, label }) => {
)(pins);
return (
<g>
<g className="bus-node">
<polygon className="body" {...polygonProps} />
<NodeLabel
text={label}

View File

@@ -2,27 +2,19 @@ import R from 'ramda';
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { foldEither, foldMaybe, maybePath } from 'xod-func-tools';
import { NODE_CORNER_RADIUS } from '../../nodeLayout';
import { getRenderablePinType } from '../../utils';
const INPUT_PINKEY = '__in__';
const OUTPUT_PINKEY = '__out__';
const getDeducedTypeOfPin = R.curry((pinkey, pins) =>
R.compose(
foldMaybe('generic', R.identity),
R.map(foldEither('error', R.identity)),
maybePath([INPUT_PINKEY, 'deducedType'])
)(pins)
);
const JumperNodeBody = ({ pins }) => {
const inConnected = R.path([INPUT_PINKEY, 'isConnected'], pins);
const outConnected = R.path([OUTPUT_PINKEY, 'isConnected'], pins);
const type = R.cond([
[() => inConnected, getDeducedTypeOfPin(INPUT_PINKEY)],
[() => outConnected, getDeducedTypeOfPin(OUTPUT_PINKEY)],
[() => inConnected, R.pipe(R.prop(INPUT_PINKEY), getRenderablePinType)],
[() => outConnected, R.pipe(R.prop(OUTPUT_PINKEY), getRenderablePinType)],
[R.T, R.always('generic')],
])(pins);
@@ -30,7 +22,7 @@ const JumperNodeBody = ({ pins }) => {
inConnected || outConnected ? 'is-connected' : 'not-connected';
return (
<g>
<g className="jumper-node">
<rect
className="clickable-area"
width="100%"

View File

@@ -21,7 +21,7 @@ const TerminalNodeBody = props => {
);
return (
<g>
<g className="terminal-node">
<circle className="body" {...circleProps} />
<NodeLabel
text={terminalLabel}

View File

@@ -1,7 +1,40 @@
import * as R from 'ramda';
import React from 'react';
import PropTypes from 'prop-types';
import { NODE_CORNER_RADIUS } from '../../nodeLayout';
import {
NODE_CORNER_RADIUS,
VARIADIC_HANDLE_WIDTH,
VARIADIC_HANDLE_HEIGHT,
} from '../../nodeLayout';
const COMPENSATE_BLURING = 0.5;
/**
* Outputs a string with coordinates for four points of variadic handle:
* 0○
* 3○
*
* 2○
* 1○
*
* :: { width, height } -> String
*/
const getVariadicPoints = size => {
const xRight = size.width - COMPENSATE_BLURING;
const xLeft = size.width - VARIADIC_HANDLE_WIDTH - COMPENSATE_BLURING;
const yTop = (size.height - VARIADIC_HANDLE_HEIGHT) / 2;
const yBottom = yTop + VARIADIC_HANDLE_HEIGHT;
const points = [
[xRight, yTop], // 0
[xRight, yBottom], // 1
[xLeft, yBottom - VARIADIC_HANDLE_WIDTH], // 2
[xLeft, yTop + VARIADIC_HANDLE_WIDTH], // 3
];
return R.compose(R.join(' '), R.unnest)(points);
};
const VariadicHandle = props => (
<g className="VariadicHandle">
@@ -9,19 +42,16 @@ const VariadicHandle = props => (
className="VariadicHandle--clickArea"
rx={NODE_CORNER_RADIUS}
ry={NODE_CORNER_RADIUS}
x={props.size.width - 8}
x={props.size.width - VARIADIC_HANDLE_WIDTH * 2}
y={-1}
width={10}
height={props.size.height + 2}
width={VARIADIC_HANDLE_WIDTH * 2 + 2}
height={props.size.height + 1}
fill="rgba(255,0,0,.5)"
onMouseDown={props.onMouseDown}
/>
<line
<polygon
className="VariadicHandle--grip"
x1={props.size.width - 1.5}
x2={props.size.width - 1.5}
y1={props.size.height / 2 - 5}
y2={props.size.height / 2 + 5}
points={getVariadicPoints(props.size)}
/>
</g>
);

View File

@@ -3,14 +3,20 @@ import { Maybe } from 'ramda-fantasy';
import * as XP from 'xod-project';
import { foldMaybe } from 'xod-func-tools';
const BASE_SIZE_UNIT = 17;
const BASE_SIZE_UNIT = 5;
export const NODE_HEIGHT = BASE_SIZE_UNIT * 13;
export const SLOT_SIZE = {
WIDTH: BASE_SIZE_UNIT * 2,
HEIGHT: BASE_SIZE_UNIT * 6,
WIDTH: BASE_SIZE_UNIT * 8 + 4,
HEIGHT: NODE_HEIGHT + BASE_SIZE_UNIT * 8,
};
export const NODE_HEIGHT = BASE_SIZE_UNIT * 3;
const PINVALUE_GAP = 4;
export const PINVALUE_WIDTH = SLOT_SIZE.WIDTH - PINVALUE_GAP / 2;
const PINLABEL_GAP = 8;
export const PINLABEL_WIDTH = SLOT_SIZE.WIDTH - PINLABEL_GAP / 2;
export const DEFAULT_PANNING_OFFSET = {
x: NODE_HEIGHT,
@@ -21,18 +27,22 @@ export const LINK_HOTSPOT_SIZE = {
WIDTH: 8,
};
export const NODE_CORNER_RADIUS = 5;
export const NODE_CORNER_RADIUS = 3;
export const RESIZE_HANDLE_SIZE = 12;
export const VARIADIC_HANDLE_WIDTH = 4;
export const VARIADIC_HANDLE_HEIGHT = BASE_SIZE_UNIT * 5;
export const PIN_RADIUS = 6;
export const PIN_RADIUS = 4;
export const PIN_INNER_RADIUS = PIN_RADIUS - 2;
export const PIN_RADIUS_WITH_OUTER_STROKE = PIN_RADIUS + 3;
export const PIN_RADIUS_WITH_SHADOW = PIN_RADIUS + 4; // TODO: rename
export const PIN_HIGHLIGHT_RADIUS = 15;
export const PIN_OFFSET_FROM_NODE_EDGE = 3;
export const PIN_HOVER_HIGHLIGHT_RADIUS = PIN_RADIUS;
export const PIN_HOTSPOT_RADIUS = PIN_HIGHLIGHT_RADIUS;
export const PIN_OFFSET_FROM_NODE_EDGE = 0;
export const TEXT_OFFSET_FROM_PIN_BORDER = 10;
export const TEXT_OFFSET_FROM_PIN_BORDER = 3;
// :: { input: Number, output: Number } -> Size
const nodeSizeInSlots = pinCountByDirection => ({
@@ -221,3 +231,27 @@ export const getBusNodePositionForPin = (node, pin) => {
SLOT_SIZE.HEIGHT * (pinDirection === XP.PIN_DIRECTION.INPUT ? -1 : 1),
};
};
// :: Number -> Boolean -> PIN_DIRECTION -> { x: Number, y: Number } -> { x, y, width, height }
const getPinTextProps = (width, isLabel, direction, position) => {
const FONT_HEIGHT = 11;
const isAboveNodeBorder = direction === XP.PIN_DIRECTION.OUTPUT || !isLabel;
const compensateFontHeight = isAboveNodeBorder ? FONT_HEIGHT : 0;
const offsetFromNodeBorder =
(PIN_RADIUS + TEXT_OFFSET_FROM_PIN_BORDER) * (isAboveNodeBorder ? -1 : 1);
return {
x: position.x - width / 2,
y: position.y - compensateFontHeight + offsetFromNodeBorder,
width,
height: FONT_HEIGHT,
};
};
// :: PIN_DIRECTION -> { x: Number, y: Number } -> { x, y, width, height }
export const getPinValueProps = (pinDirection, position) =>
getPinTextProps(PINVALUE_WIDTH, false, pinDirection, position);
// :: PIN_DIRECTION -> { x: Number, y: Number } -> { x, y, width, height }
export const getPinLabelProps = (pinDirection, position) =>
getPinTextProps(PINLABEL_WIDTH, true, pinDirection, position);