UNPKG

@zendesk/react-measure-timing-hooks

Version:

react hooks for measuring time to interactive and time to render of components

161 lines (156 loc) 7.19 kB
"use strict"; /* eslint-disable no-magic-numbers */ /* eslint-disable import/no-extraneous-dependencies */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importDefault(require("react")); const styled_components_1 = __importStar(require("styled-components")); const annotation_1 = require("@visx/annotation"); const event_1 = require("@visx/event"); const shape_1 = require("@visx/shape"); const text_1 = require("@visx/text"); const react_theming_1 = require("@zendeskgarden/react-theming"); const constants_1 = require("../constants"); const interactiveStyles = ` cursor: pointer; transition: all 0.2s ease-in-out; &:hover { filter: brightness(1.2); } `; const MIN_SPAN_WIDTH = 10; // minimum width in pixels for any span bar const StyledLine = (0, styled_components_1.default)(shape_1.Line) ` ${interactiveStyles} &:hover { stroke-opacity: 0.8; stroke-width: 3.5px; } `; const StyledBar = (0, styled_components_1.default)(shape_1.Bar) ` ${interactiveStyles} &:hover { opacity: 0.7 !important; stroke: #fff; stroke-width: 2px; } ${(props) => props.$isTiny && ` stroke: ${props.$fill}; stroke-width: 2px; rx: 4px; &:hover { stroke-width: 3px; filter: brightness(1.3); } `} `; const InteractiveSpan = (props) => { const { xScale, yScale, yMax, data, showTooltip, hideTooltip, onClick, scrollContainerRef, titleColor: color, title, annotateAt, ...restProps } = props; let tooltipTimeout; const theme = (0, styled_components_1.useTheme)(); const handleMouseLeave = () => { // prevent tooltip flickering tooltipTimeout = window.setTimeout(() => { hideTooltip(); }, 300); }; const handleMouseMove = (event) => { if (tooltipTimeout) clearTimeout(tooltipTimeout); if (!('ownerSVGElement' in event.target)) return; const coords = (0, event_1.localPoint)(event.target.ownerSVGElement, event); if (coords && scrollContainerRef.current) { const { scrollTop } = scrollContainerRef.current; showTooltip({ tooltipLeft: coords.x + 20, tooltipTop: coords.y + 10 - scrollTop, tooltipData: data, }); } }; const handleClick = (event) => { event.stopPropagation(); // Prevent click from bubbling to container onClick(); }; let element; if (restProps.type === 'line') { element = (react_1.default.createElement(StyledLine, { ...restProps, from: { x: xScale(data.annotation.operationRelativeEndTime), y: 0, }, to: { x: xScale(data.annotation.operationRelativeEndTime), y: yMax, }, stroke: constants_1.BAR_FILL_COLOR[data.type], strokeOpacity: 0.3, strokeWidth: 2.5, strokeDasharray: "8,4", strokeLinecap: "round", onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, onClick: handleClick })); } else { /* Calculate if span is tiny based on scaled width */ const scaledWidth = xScale(data.annotation.operationRelativeEndTime) - xScale(data.annotation.operationRelativeStartTime); const isTiny = scaledWidth < MIN_SPAN_WIDTH; const width = isTiny ? MIN_SPAN_WIDTH : scaledWidth; const fill = data.span.status === 'error' ? (0, react_theming_1.getColor)({ theme, variable: 'background.dangerEmphasis' }) : constants_1.BAR_FILL_COLOR[data.type]; const height = isTiny ? yScale.bandwidth() / 2 : yScale.bandwidth(); const y = (yScale(data.groupName) ?? 0) + (isTiny ? yScale.bandwidth() / 4 : 0); element = (react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement(StyledBar, { ...restProps, "data-status": data.span.status, x: xScale(data.annotation.operationRelativeStartTime), y: y, width: width, height: height, fill: fill, rx: 2, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, onClick: handleClick }), data.span.status === 'error' && (react_1.default.createElement(text_1.Text, { x: (xScale(data.annotation.operationRelativeStartTime) + xScale(data.annotation.operationRelativeEndTime)) / 2, y: yScale(data.groupName) + yScale.bandwidth() / 2, dy: ".33em", fontSize: 12, textAnchor: "middle", fill: (0, react_theming_1.getColor)({ theme, variable: 'background.danger' }), style: { pointerEvents: 'none' } }, "\u274C")))); } const xCoordinate = xScale(data.annotation.operationRelativeEndTime); return (react_1.default.createElement(react_1.default.Fragment, null, element, annotateAt === 'top' && (react_1.default.createElement(annotation_1.Annotation, { x: xCoordinate + 15, y: -2, dx: 0, dy: 0 }, react_1.default.createElement(annotation_1.Label, { fontColor: color, title: title, titleFontSize: 13, subtitle: `${data.annotation.operationRelativeEndTime.toFixed(2)} ms`, showAnchorLine: false, backgroundFill: (0, react_theming_1.getColor)({ theme, variable: 'background.success', }), titleProps: { width: 200, color: (0, react_theming_1.getColor)({ theme, variable: 'foreground.primary' }), }, backgroundProps: { opacity: 1, rx: 5, width: 160, } }))))); }; // eslint-disable-next-line import/no-default-export exports.default = InteractiveSpan; //# sourceMappingURL=InteractiveSpan.js.map