Submit
Path:
~
/
/
usr
/
share
/
grafana
/
public
/
app
/
plugins
/
panel
/
canvas
/
components
/
connections
/
File Content:
ConnectionAnchors.tsx
import { css } from '@emotion/css'; import React, { useRef } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; import { ConnectionCoordinates } from 'app/features/canvas'; type Props = { setRef: (anchorElement: HTMLDivElement) => void; handleMouseLeave: ( event: React.MouseEvent<Element, MouseEvent> | React.FocusEvent<HTMLDivElement, Element> ) => boolean; }; export const CONNECTION_ANCHOR_DIV_ID = 'connectionControl'; export const CONNECTION_ANCHOR_ALT = 'connection anchor'; export const CONNECTION_ANCHOR_HIGHLIGHT_OFFSET = 8; const ANCHOR_PADDING = 3; export const ConnectionAnchors = ({ setRef, handleMouseLeave }: Props) => { const highlightEllipseRef = useRef<HTMLDivElement>(null); const styles = useStyles2(getStyles); const halfSize = 2.5; const halfSizeHighlightEllipse = 5.5; const anchorImage = 'data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSI1cHgiIGhlaWdodD0iNXB4IiB2ZXJzaW9uPSIxLjEiPjxwYXRoIGQ9Im0gMCAwIEwgNSA1IE0gMCA1IEwgNSAwIiBzdHJva2Utd2lkdGg9IjIiIHN0eWxlPSJzdHJva2Utb3BhY2l0eTowLjQiIHN0cm9rZT0iI2ZmZmZmZiIvPjxwYXRoIGQ9Im0gMCAwIEwgNSA1IE0gMCA1IEwgNSAwIiBzdHJva2U9IiMyOWI2ZjIiLz48L3N2Zz4='; const onMouseEnterAnchor = (event: React.MouseEvent) => { if (!(event.target instanceof HTMLImageElement)) { return; } if (highlightEllipseRef.current && event.target.style) { highlightEllipseRef.current.style.display = 'block'; highlightEllipseRef.current.style.top = `calc(${event.target.style.top} - ${halfSizeHighlightEllipse}px + ${ANCHOR_PADDING}px)`; highlightEllipseRef.current.style.left = `calc(${event.target.style.left} - ${halfSizeHighlightEllipse}px + ${ANCHOR_PADDING}px)`; } }; const onMouseLeaveHighlightElement = () => { if (highlightEllipseRef.current) { highlightEllipseRef.current.style.display = 'none'; } }; const handleMouseLeaveAnchors = ( event: React.MouseEvent<Element, MouseEvent> | React.FocusEvent<HTMLDivElement, Element> ) => { const didHideAnchors = handleMouseLeave(event); if (didHideAnchors) { onMouseLeaveHighlightElement(); } }; // Unit is percentage from the middle of the element // 0, 0 middle; -1, -1 bottom left; 1, 1 top right const ANCHORS = [ { x: -1, y: 1 }, { x: -0.5, y: 1 }, { x: 0, y: 1 }, { x: 0.5, y: 1 }, { x: 1, y: 1 }, { x: 1, y: 0.5 }, { x: 1, y: 0 }, { x: 1, y: -0.5 }, { x: 1, y: -1 }, { x: 0.5, y: -1 }, { x: 0, y: -1 }, { x: -0.5, y: -1 }, { x: -1, y: -1 }, { x: -1, y: -0.5 }, { x: -1, y: 0 }, { x: -1, y: 0.5 }, ]; const generateAnchors = (anchors: ConnectionCoordinates[] = ANCHORS) => { return anchors.map((anchor) => { const id = `${anchor.x},${anchor.y}`; // Convert anchor coords to relative percentage const style = { top: `calc(${-anchor.y * 50 + 50}% - ${halfSize}px - ${ANCHOR_PADDING}px)`, left: `calc(${anchor.x * 50 + 50}% - ${halfSize}px - ${ANCHOR_PADDING}px)`, }; return ( <img id={id} ref={(element) => { if (element) { // After React 15+, inline styles no longer support !important element.style.setProperty('pointer-events', 'auto', 'important'); } }} key={id} alt={CONNECTION_ANCHOR_ALT} className={styles.anchor} style={style} src={anchorImage} onMouseEnter={onMouseEnterAnchor} /> ); }); }; return ( <div className={styles.root} ref={setRef}> <div className={styles.mouseoutDiv} onMouseOut={handleMouseLeaveAnchors} onBlur={handleMouseLeaveAnchors} /> <div id={CONNECTION_ANCHOR_DIV_ID} ref={highlightEllipseRef} className={styles.highlightElement} onMouseLeave={onMouseLeaveHighlightElement} /> {generateAnchors()} </div> ); }; const getStyles = (theme: GrafanaTheme2) => ({ root: css({ position: 'absolute', display: 'none', }), mouseoutDiv: css({ position: 'absolute', margin: '-30px', width: 'calc(100% + 60px)', height: 'calc(100% + 60px)', }), anchor: css({ padding: `${ANCHOR_PADDING}px`, position: 'absolute', cursor: 'cursor', width: `calc(5px + 2 * ${ANCHOR_PADDING}px)`, height: `calc(5px + 2 * ${ANCHOR_PADDING}px)`, zIndex: 100, }), highlightElement: css({ backgroundColor: '#00ff00', opacity: 0.3, position: 'absolute', cursor: 'cursor', pointerEvents: 'auto', width: '16px', height: '16px', borderRadius: theme.shape.radius.circle, display: 'none', zIndex: 110, }), });
Submit
FILE
FOLDER
INFO
Name
Size
Permission
Action
ConnectionAnchors.tsx
4961 bytes
0644
ConnectionSVG.tsx
6820 bytes
0644
Connections.tsx
10890 bytes
0644
N4ST4R_ID | Naxtarrr