UNPKG

@simspace/nivo-circle-packing

Version:

[![version](https://img.shields.io/npm/v/@nivo/circle-packing.svg?style=flat-square)](https://www.npmjs.com/package/@nivo/circle-packing)

1,245 lines (1,167 loc) 45.9 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@simspace/nivo-core'), require('d3-hierarchy'), require('lodash/cloneDeep'), require('lodash/sortBy'), require('@simspace/nivo-colors'), require('@simspace/nivo-tooltip'), require('react/jsx-runtime'), require('@react-spring/web')) : typeof define === 'function' && define.amd ? define(['exports', 'react', '@simspace/nivo-core', 'd3-hierarchy', 'lodash/cloneDeep', 'lodash/sortBy', '@simspace/nivo-colors', '@simspace/nivo-tooltip', 'react/jsx-runtime', '@react-spring/web'], factory) : (global = global || self, factory(global.nivo = global.nivo || {}, global.React, global['@simspace/nivo-core'], global.d3, global['lodash/cloneDeep'], global['lodash/sortBy'], global['@simspace/nivo-colors'], global['@simspace/nivo-tooltip'], global['react/jsx-runtime'], global['@react-spring/web'])); }(this, (function (exports, React, nivoCore, d3Hierarchy, cloneDeep, sortBy, nivoColors, nivoTooltip, jsxRuntime, web) { 'use strict'; cloneDeep = cloneDeep && Object.prototype.hasOwnProperty.call(cloneDeep, 'default') ? cloneDeep['default'] : cloneDeep; sortBy = sortBy && Object.prototype.hasOwnProperty.call(sortBy, 'default') ? sortBy['default'] : sortBy; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } var useCirclePacking = function useCirclePacking(_ref) { var _hierarchy$value; var data = _ref.data, id = _ref.id, value = _ref.value, valueFormat = _ref.valueFormat, width = _ref.width, height = _ref.height, padding = _ref.padding, leavesOnly = _ref.leavesOnly, colors = _ref.colors, colorBy = _ref.colorBy, inheritColorFromParent = _ref.inheritColorFromParent, childColor = _ref.childColor; var getId = nivoCore.usePropertyAccessor(id); var getValue = nivoCore.usePropertyAccessor(value); var formatValue = nivoCore.useValueFormatter(valueFormat); var getColor = nivoColors.useOrdinalColorScale(colors, colorBy); var theme = nivoCore.useTheme(); var getChildColor = nivoColors.useInheritedColor(childColor, theme); var clonedData = cloneDeep(data); var hierarchy = d3Hierarchy.hierarchy(clonedData).sum(getValue); var pack = d3Hierarchy.pack().size([width, height]).padding(padding); var packedData = pack(hierarchy); var nodes = leavesOnly ? packedData.leaves() : packedData.descendants(); var sortedNodes = sortBy(nodes, 'depth'); var total = (_hierarchy$value = hierarchy.value) !== null && _hierarchy$value !== void 0 ? _hierarchy$value : 0; var computedNodes = sortedNodes.reduce(function (acc, descendant) { var id = getId(descendant.data); var value = descendant.value; var percentage = 100 * value / total; var path = descendant.ancestors().map(function (ancestor) { return getId(ancestor.data); }); var parent; if (descendant.parent) { parent = acc.find(function (node) { return node.id === getId(descendant.parent.data); }); } var normalizedNode = { id: id, path: path, value: value, percentage: percentage, formattedValue: valueFormat ? formatValue(value) : "".concat(percentage.toFixed(2), "%"), x: descendant.x, y: descendant.y, radius: descendant.r, color: '', data: descendant.data, depth: descendant.depth, height: descendant.height }; if (inheritColorFromParent && parent && normalizedNode.depth > 1) { normalizedNode.color = getChildColor(parent); } else { normalizedNode.color = getColor(normalizedNode); } return [].concat(_toConsumableArray(acc), [normalizedNode]); }, []); return computedNodes; }; var useCirclePackingZoom = function useCirclePackingZoom(nodes, zoomedId, width, height) { return React.useMemo(function () { if (!zoomedId) return nodes; var zoomedNode = nodes.find(function (_ref2) { var id = _ref2.id; return id === zoomedId; }); if (!zoomedNode) return nodes; var ratio = Math.min(width, height) / (zoomedNode.radius * 2); var offsetX = width / 2 - zoomedNode.x * ratio; var offsetY = height / 2 - zoomedNode.y * ratio; return nodes.map(function (node) { return _objectSpread2(_objectSpread2({}, node), {}, { x: node.x * ratio + offsetX, y: node.y * ratio + offsetY, radius: node.radius * ratio }); }); }, [nodes, zoomedId, width, height]); }; var useCirclePackingLabels = function useCirclePackingLabels(_ref3) { var nodes = _ref3.nodes, label = _ref3.label, filter = _ref3.filter, skipRadius = _ref3.skipRadius, textColor = _ref3.textColor; var getLabel = nivoCore.usePropertyAccessor(label); var theme = nivoCore.useTheme(); var getTextColor = nivoColors.useInheritedColor(textColor, theme); var labels = React.useMemo(function () { return nodes.filter(function (node) { return node.radius >= skipRadius; }).map(function (node) { return { label: getLabel(node), textColor: getTextColor(node), node: node }; }); }, [nodes, skipRadius, getLabel, getTextColor]); return React.useMemo(function () { if (!filter) return labels; return labels.filter(filter); }, [labels, filter]); }; var useNodeMouseHandlers = function useNodeMouseHandlers(node, _ref4) { var onMouseEnter = _ref4.onMouseEnter, onMouseMove = _ref4.onMouseMove, onMouseLeave = _ref4.onMouseLeave, onClick = _ref4.onClick; return React.useMemo(function () { return { onMouseEnter: onMouseEnter ? function (event) { onMouseEnter(node, event); } : undefined, onMouseMove: onMouseMove ? function (event) { onMouseMove(node, event); } : undefined, onMouseLeave: onMouseLeave ? function (event) { onMouseLeave(node, event); } : undefined, onClick: onClick ? function (event) { onClick(node, event); } : undefined }; }, [node, onMouseEnter, onMouseMove, onMouseLeave, onClick]); }; var useMouseCircleDetection = function useMouseCircleDetection(_ref5) { var nodes = _ref5.nodes, canvasEl = _ref5.canvasEl, margin = _ref5.margin; var sortedNodes = React.useMemo(function () { return sortBy(nodes, 'height'); }, [nodes]); return React.useCallback(function (event) { if (!canvasEl.current) return null; var _getRelativeCursor = nivoCore.getRelativeCursor(canvasEl.current, event), _getRelativeCursor2 = _slicedToArray(_getRelativeCursor, 2), x = _getRelativeCursor2[0], y = _getRelativeCursor2[1]; return sortedNodes.find(function (node) { var distanceFromNode = nivoCore.getDistance(node.x, node.y, x - margin.left, y - margin.top); return distanceFromNode <= node.radius; }); }, [canvasEl, margin, sortedNodes]); }; var useCirclePackingLayerContext = function useCirclePackingLayerContext(_ref6) { var nodes = _ref6.nodes; return React.useMemo(function () { return { nodes: nodes }; }, [nodes]); }; var CirclePackingTooltip = function CirclePackingTooltip(_ref) { var id = _ref.id, formattedValue = _ref.formattedValue, color = _ref.color; return jsxRuntime.jsx(nivoTooltip.BasicTooltip, { id: id, value: formattedValue, enableChip: true, color: color }); }; var _window$devicePixelRa; var defaultProps = { id: 'id', value: 'value', padding: 0, leavesOnly: false, layers: ['circles', 'labels'], colors: { scheme: 'nivo' }, colorBy: 'depth', inheritColorFromParent: false, childColor: { from: 'color', modifiers: [['darker', 0.3]] }, borderWidth: 0, borderColor: { from: 'color', modifiers: [['darker', 0.3]] }, defs: [], fill: [], enableLabels: false, label: 'id', labelTextColor: { from: 'color', modifiers: [['darker', 1.6]] }, labelsSkipRadius: 8, isInteractive: true, tooltip: CirclePackingTooltip, animate: true, motionConfig: 'gentle', role: 'img', pixelRatio: typeof window !== 'undefined' ? (_window$devicePixelRa = window.devicePixelRatio) !== null && _window$devicePixelRa !== void 0 ? _window$devicePixelRa : 1 : 1 }; var interpolateRadius = function interpolateRadius(radiusValue) { return web.to([radiusValue], function (radius) { return Math.max(0, radius); }); }; var getTransitionPhases = function getTransitionPhases(getBorderColor) { return { enter: function enter(node) { return { x: node.x, y: node.y, radius: 0, color: node.color, borderColor: getBorderColor(node), opacity: 0 }; }, update: function update(node) { return { x: node.x, y: node.y, radius: node.radius, color: node.color, borderColor: getBorderColor(node), opacity: 1 }; }, leave: function leave(node) { return { x: node.x, y: node.y, radius: 0, color: node.color, borderColor: getBorderColor(node), opacity: 0 }; } }; }; var Circles = function Circles(_ref) { var nodes = _ref.nodes, borderWidth = _ref.borderWidth, borderColor = _ref.borderColor, component = _ref.component, isInteractive = _ref.isInteractive, onMouseEnter = _ref.onMouseEnter, onMouseMove = _ref.onMouseMove, onMouseLeave = _ref.onMouseLeave, onClick = _ref.onClick, tooltip = _ref.tooltip; var _useTooltip = nivoTooltip.useTooltip(), showTooltipFromEvent = _useTooltip.showTooltipFromEvent, hideTooltip = _useTooltip.hideTooltip; var handleMouseEnter = React.useMemo(function () { if (!isInteractive) return undefined; return function (node, event) { showTooltipFromEvent(React.createElement(tooltip, node), event); onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(node, event); }; }, [isInteractive, showTooltipFromEvent, tooltip, onMouseEnter]); var handleMouseMove = React.useMemo(function () { if (!isInteractive) return undefined; return function (node, event) { showTooltipFromEvent(React.createElement(tooltip, node), event); onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(node, event); }; }, [isInteractive, showTooltipFromEvent, tooltip, onMouseMove]); var handleMouseLeave = React.useMemo(function () { if (!isInteractive) return undefined; return function (node, event) { hideTooltip(); onMouseLeave === null || onMouseLeave === void 0 ? void 0 : onMouseLeave(node, event); }; }, [isInteractive, hideTooltip, onMouseLeave]); var handleClick = React.useMemo(function () { if (!isInteractive) return undefined; return function (node, event) { onClick === null || onClick === void 0 ? void 0 : onClick(node, event); }; }, [isInteractive, onClick]); var _useMotionConfig = nivoCore.useMotionConfig(), animate = _useMotionConfig.animate, springConfig = _useMotionConfig.config; var theme = nivoCore.useTheme(); var getBorderColor = nivoColors.useInheritedColor(borderColor, theme); var transitionPhases = React.useMemo(function () { return getTransitionPhases(getBorderColor); }, [getBorderColor]); var transition = web.useTransition(nodes, { keys: function keys(node) { return node.id; }, initial: transitionPhases.update, from: transitionPhases.enter, enter: transitionPhases.update, update: transitionPhases.update, leave: transitionPhases.leave, config: springConfig, immediate: !animate }); return jsxRuntime.jsx(jsxRuntime.Fragment, { children: transition(function (transitionProps, node) { return React.createElement(component, { key: node.id, node: node, style: _objectSpread2(_objectSpread2({}, transitionProps), {}, { radius: interpolateRadius(transitionProps.radius), borderWidth: borderWidth }), onMouseEnter: handleMouseEnter, onMouseMove: handleMouseMove, onMouseLeave: handleMouseLeave, onClick: handleClick }); }) }); }; var CircleSvg = function CircleSvg(_ref) { var node = _ref.node, style = _ref.style, onMouseEnter = _ref.onMouseEnter, onMouseMove = _ref.onMouseMove, onMouseLeave = _ref.onMouseLeave, onClick = _ref.onClick; var handlers = useNodeMouseHandlers(node, { onMouseEnter: onMouseEnter, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, onClick: onClick }); return jsxRuntime.jsx(web.animated.circle, { cx: style.x, cy: style.y, r: style.radius, fill: node.fill || style.color, stroke: style.borderColor, strokeWidth: style.borderWidth, opacity: style.opacity, onMouseEnter: handlers.onMouseEnter, onMouseMove: handlers.onMouseMove, onMouseLeave: handlers.onMouseLeave, onClick: handlers.onClick }, node.id); }; var getTransitionPhases$1 = function getTransitionPhases() { return { enter: function enter(label) { return { x: label.node.x, y: label.node.y, radius: label.node.radius, textColor: label.textColor, opacity: 0 }; }, update: function update(label) { return { x: label.node.x, y: label.node.y, radius: label.node.radius, textColor: label.textColor, opacity: 1 }; }, leave: function leave(label) { return { x: label.node.x, y: label.node.y, radius: label.node.radius, textColor: label.textColor, opacity: 0 }; } }; }; var Labels = function Labels(_ref) { var nodes = _ref.nodes, label = _ref.label, filter = _ref.filter, skipRadius = _ref.skipRadius, textColor = _ref.textColor, component = _ref.component; var _useMotionConfig = nivoCore.useMotionConfig(), animate = _useMotionConfig.animate, springConfig = _useMotionConfig.config; var labels = useCirclePackingLabels({ nodes: nodes, label: label, filter: filter, skipRadius: skipRadius, textColor: textColor }); var transitionPhases = React.useMemo(function () { return getTransitionPhases$1(); }, []); var transition = web.useTransition(labels, { keys: function keys(label) { return label.node.id; }, initial: transitionPhases.update, from: transitionPhases.enter, enter: transitionPhases.update, update: transitionPhases.update, leave: transitionPhases.leave, config: springConfig, immediate: !animate }); return jsxRuntime.jsx(jsxRuntime.Fragment, { children: transition(function (transitionProps, label) { return React.createElement(component, { key: label.node.id, label: label.label, style: _objectSpread2(_objectSpread2({}, transitionProps), {}, { radius: interpolateRadius(transitionProps.radius) }), node: label.node }); }) }); }; var LabelSvg = function LabelSvg(_ref) { var node = _ref.node, label = _ref.label, style = _ref.style; var theme = nivoCore.useTheme(); return jsxRuntime.jsx(web.animated.text, { x: style.x, y: style.y, textAnchor: "middle", dominantBaseline: "central", style: _objectSpread2(_objectSpread2({}, theme.labels.text), {}, { fill: style.textColor, opacity: style.opacity, pointerEvents: 'none' }), children: label }, node.id); }; var InnerCirclePacking = function InnerCirclePacking(_ref) { var data = _ref.data, _ref$id = _ref.id, id = _ref$id === void 0 ? defaultProps.id : _ref$id, _ref$value = _ref.value, value = _ref$value === void 0 ? defaultProps.value : _ref$value, valueFormat = _ref.valueFormat, width = _ref.width, height = _ref.height, partialMargin = _ref.margin, _ref$padding = _ref.padding, padding = _ref$padding === void 0 ? defaultProps.padding : _ref$padding, _ref$leavesOnly = _ref.leavesOnly, leavesOnly = _ref$leavesOnly === void 0 ? defaultProps.leavesOnly : _ref$leavesOnly, _ref$colors = _ref.colors, colors = _ref$colors === void 0 ? defaultProps.colors : _ref$colors, _ref$colorBy = _ref.colorBy, colorBy = _ref$colorBy === void 0 ? defaultProps.colorBy : _ref$colorBy, _ref$inheritColorFrom = _ref.inheritColorFromParent, inheritColorFromParent = _ref$inheritColorFrom === void 0 ? defaultProps.inheritColorFromParent : _ref$inheritColorFrom, _ref$childColor = _ref.childColor, childColor = _ref$childColor === void 0 ? defaultProps.childColor : _ref$childColor, _ref$borderWidth = _ref.borderWidth, borderWidth = _ref$borderWidth === void 0 ? defaultProps.borderWidth : _ref$borderWidth, _ref$borderColor = _ref.borderColor, borderColor = _ref$borderColor === void 0 ? defaultProps.borderColor : _ref$borderColor, _ref$circleComponent = _ref.circleComponent, circleComponent = _ref$circleComponent === void 0 ? CircleSvg : _ref$circleComponent, _ref$defs = _ref.defs, defs = _ref$defs === void 0 ? defaultProps.defs : _ref$defs, _ref$fill = _ref.fill, fill = _ref$fill === void 0 ? defaultProps.fill : _ref$fill, _ref$enableLabels = _ref.enableLabels, enableLabels = _ref$enableLabels === void 0 ? defaultProps.enableLabels : _ref$enableLabels, _ref$label = _ref.label, label = _ref$label === void 0 ? defaultProps.label : _ref$label, labelsFilter = _ref.labelsFilter, _ref$labelsSkipRadius = _ref.labelsSkipRadius, labelsSkipRadius = _ref$labelsSkipRadius === void 0 ? defaultProps.labelsSkipRadius : _ref$labelsSkipRadius, _ref$labelTextColor = _ref.labelTextColor, labelTextColor = _ref$labelTextColor === void 0 ? defaultProps.labelTextColor : _ref$labelTextColor, _ref$labelComponent = _ref.labelComponent, labelComponent = _ref$labelComponent === void 0 ? LabelSvg : _ref$labelComponent, _ref$layers = _ref.layers, layers = _ref$layers === void 0 ? defaultProps.layers : _ref$layers, isInteractive = _ref.isInteractive, onMouseEnter = _ref.onMouseEnter, onMouseMove = _ref.onMouseMove, onMouseLeave = _ref.onMouseLeave, onClick = _ref.onClick, _ref$tooltip = _ref.tooltip, tooltip = _ref$tooltip === void 0 ? defaultProps.tooltip : _ref$tooltip, zoomedId = _ref.zoomedId, _ref$role = _ref.role, role = _ref$role === void 0 ? defaultProps.role : _ref$role; var _useDimensions = nivoCore.useDimensions(width, height, partialMargin), outerWidth = _useDimensions.outerWidth, outerHeight = _useDimensions.outerHeight, margin = _useDimensions.margin, innerWidth = _useDimensions.innerWidth, innerHeight = _useDimensions.innerHeight; var nodes = useCirclePacking({ data: data, id: id, value: value, valueFormat: valueFormat, width: innerWidth, height: innerHeight, padding: padding, leavesOnly: leavesOnly, colors: colors, colorBy: colorBy, inheritColorFromParent: inheritColorFromParent, childColor: childColor }); var zoomedNodes = useCirclePackingZoom(nodes, zoomedId, innerWidth, innerHeight); var boundDefs = React.useMemo(function () { return nivoCore.bindDefs(defs, zoomedNodes, fill, { targetKey: 'fill' }); }, [defs, zoomedNodes, fill]); var layerById = { circles: null, labels: null }; if (layers.includes('circles')) { layerById.circles = jsxRuntime.jsx(Circles, { nodes: zoomedNodes, borderWidth: borderWidth, borderColor: borderColor, isInteractive: isInteractive, onMouseEnter: onMouseEnter, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, onClick: onClick, component: circleComponent, tooltip: tooltip }, "circles"); } if (enableLabels && layers.includes('labels')) { layerById.labels = jsxRuntime.jsx(Labels, { nodes: zoomedNodes, label: label, filter: labelsFilter, skipRadius: labelsSkipRadius, textColor: labelTextColor, component: labelComponent }, "labels"); } var layerContext = useCirclePackingLayerContext({ nodes: nodes }); return jsxRuntime.jsx(nivoCore.SvgWrapper, { width: outerWidth, height: outerHeight, margin: margin, defs: boundDefs, role: role, children: layers.map(function (layer, i) { if (layerById[layer] !== undefined) { return layerById[layer]; } if (typeof layer === 'function') { return jsxRuntime.jsx(React.Fragment, { children: React.createElement(layer, layerContext) }, i); } return null; }) }); }; var CirclePacking = function CirclePacking(_ref2) { var theme = _ref2.theme, _ref2$isInteractive = _ref2.isInteractive, isInteractive = _ref2$isInteractive === void 0 ? defaultProps.isInteractive : _ref2$isInteractive, _ref2$animate = _ref2.animate, animate = _ref2$animate === void 0 ? defaultProps.animate : _ref2$animate, _ref2$motionConfig = _ref2.motionConfig, motionConfig = _ref2$motionConfig === void 0 ? defaultProps.motionConfig : _ref2$motionConfig, otherProps = _objectWithoutProperties(_ref2, ["theme", "isInteractive", "animate", "motionConfig"]); return jsxRuntime.jsx(nivoCore.Container, { isInteractive: isInteractive, animate: animate, motionConfig: motionConfig, theme: theme, children: jsxRuntime.jsx(InnerCirclePacking, _objectSpread2({ isInteractive: isInteractive }, otherProps)) }); }; var ResponsiveCirclePacking = function ResponsiveCirclePacking(props) { return jsxRuntime.jsx(nivoCore.ResponsiveWrapper, { children: function children(_ref) { var width = _ref.width, height = _ref.height; return jsxRuntime.jsx(CirclePacking, _objectSpread2({ width: width, height: height }, props)); } }); }; var interpolatePosition = function interpolatePosition(positionValue, radiusValue) { return web.to([positionValue, radiusValue], function (position, radius) { return position - radius; }); }; var interpolateSize = function interpolateSize(radiusValue) { return web.to([radiusValue], function (radius) { return radius * 2; }); }; var interpolateBorderWidth = function interpolateBorderWidth(borderWidth, radiusValue) { return web.to([radiusValue], function (radius) { return Math.min(borderWidth, radius); }); }; var CircleHtml = function CircleHtml(_ref) { var node = _ref.node, style = _ref.style, onMouseEnter = _ref.onMouseEnter, onMouseMove = _ref.onMouseMove, onMouseLeave = _ref.onMouseLeave, onClick = _ref.onClick; var size = interpolateSize(style.radius); var handlers = useNodeMouseHandlers(node, { onMouseEnter: onMouseEnter, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, onClick: onClick }); return jsxRuntime.jsx(web.animated.div, { style: { position: 'absolute', top: interpolatePosition(style.y, style.radius), left: interpolatePosition(style.x, style.radius), height: size, width: size, borderRadius: style.radius, backgroundColor: style.color, borderWidth: interpolateBorderWidth(style.borderWidth, style.radius), borderStyle: 'solid', borderColor: style.borderColor, boxSizing: 'border-box' }, onMouseEnter: handlers.onMouseEnter, onMouseMove: handlers.onMouseMove, onMouseLeave: handlers.onMouseLeave, onClick: handlers.onClick }); }; var LabelHtml = function LabelHtml(_ref) { var node = _ref.node, label = _ref.label, style = _ref.style; var theme = nivoCore.useTheme(); var size = interpolateSize(style.radius); return jsxRuntime.jsx(web.animated.div, { style: _objectSpread2(_objectSpread2({}, theme.labels.text), {}, { position: 'absolute', display: 'flex', justifyContent: 'center', alignItems: 'center', top: interpolatePosition(style.y, style.radius), left: interpolatePosition(style.x, style.radius), width: size, height: size, color: style.textColor, opacity: style.opacity, pointerEvents: 'none' }), children: label }, node.id); }; var InnerCirclePackingHtml = function InnerCirclePackingHtml(_ref) { var data = _ref.data, _ref$id = _ref.id, id = _ref$id === void 0 ? defaultProps.id : _ref$id, _ref$value = _ref.value, value = _ref$value === void 0 ? defaultProps.value : _ref$value, valueFormat = _ref.valueFormat, width = _ref.width, height = _ref.height, partialMargin = _ref.margin, _ref$padding = _ref.padding, padding = _ref$padding === void 0 ? defaultProps.padding : _ref$padding, _ref$leavesOnly = _ref.leavesOnly, leavesOnly = _ref$leavesOnly === void 0 ? defaultProps.leavesOnly : _ref$leavesOnly, _ref$colors = _ref.colors, colors = _ref$colors === void 0 ? defaultProps.colors : _ref$colors, _ref$colorBy = _ref.colorBy, colorBy = _ref$colorBy === void 0 ? defaultProps.colorBy : _ref$colorBy, _ref$inheritColorFrom = _ref.inheritColorFromParent, inheritColorFromParent = _ref$inheritColorFrom === void 0 ? defaultProps.inheritColorFromParent : _ref$inheritColorFrom, _ref$childColor = _ref.childColor, childColor = _ref$childColor === void 0 ? defaultProps.childColor : _ref$childColor, _ref$borderWidth = _ref.borderWidth, borderWidth = _ref$borderWidth === void 0 ? defaultProps.borderWidth : _ref$borderWidth, _ref$borderColor = _ref.borderColor, borderColor = _ref$borderColor === void 0 ? defaultProps.borderColor : _ref$borderColor, _ref$circleComponent = _ref.circleComponent, circleComponent = _ref$circleComponent === void 0 ? CircleHtml : _ref$circleComponent, _ref$enableLabels = _ref.enableLabels, enableLabels = _ref$enableLabels === void 0 ? defaultProps.enableLabels : _ref$enableLabels, _ref$label = _ref.label, label = _ref$label === void 0 ? defaultProps.label : _ref$label, labelsFilter = _ref.labelsFilter, _ref$labelsSkipRadius = _ref.labelsSkipRadius, labelsSkipRadius = _ref$labelsSkipRadius === void 0 ? defaultProps.labelsSkipRadius : _ref$labelsSkipRadius, _ref$labelTextColor = _ref.labelTextColor, labelTextColor = _ref$labelTextColor === void 0 ? defaultProps.labelTextColor : _ref$labelTextColor, _ref$labelComponent = _ref.labelComponent, labelComponent = _ref$labelComponent === void 0 ? LabelHtml : _ref$labelComponent, _ref$layers = _ref.layers, layers = _ref$layers === void 0 ? defaultProps.layers : _ref$layers, isInteractive = _ref.isInteractive, onMouseEnter = _ref.onMouseEnter, onMouseMove = _ref.onMouseMove, onMouseLeave = _ref.onMouseLeave, onClick = _ref.onClick, _ref$tooltip = _ref.tooltip, tooltip = _ref$tooltip === void 0 ? defaultProps.tooltip : _ref$tooltip, zoomedId = _ref.zoomedId, _ref$role = _ref.role, role = _ref$role === void 0 ? defaultProps.role : _ref$role; var _useDimensions = nivoCore.useDimensions(width, height, partialMargin), outerWidth = _useDimensions.outerWidth, outerHeight = _useDimensions.outerHeight, margin = _useDimensions.margin, innerWidth = _useDimensions.innerWidth, innerHeight = _useDimensions.innerHeight; var nodes = useCirclePacking({ data: data, id: id, value: value, valueFormat: valueFormat, width: innerWidth, height: innerHeight, padding: padding, leavesOnly: leavesOnly, colors: colors, colorBy: colorBy, inheritColorFromParent: inheritColorFromParent, childColor: childColor }); var zoomedNodes = useCirclePackingZoom(nodes, zoomedId, innerWidth, innerHeight); var layerById = { circles: null, labels: null }; if (layers.includes('circles')) { layerById.circles = jsxRuntime.jsx(Circles, { nodes: zoomedNodes, borderWidth: borderWidth, borderColor: borderColor, isInteractive: isInteractive, onMouseEnter: onMouseEnter, onMouseMove: onMouseMove, onMouseLeave: onMouseLeave, onClick: onClick, component: circleComponent, tooltip: tooltip }, "circles"); } if (enableLabels && layers.includes('labels')) { layerById.labels = jsxRuntime.jsx(Labels, { nodes: zoomedNodes, label: label, filter: labelsFilter, skipRadius: labelsSkipRadius, textColor: labelTextColor, component: labelComponent }, "labels"); } var layerContext = useCirclePackingLayerContext({ nodes: nodes }); return jsxRuntime.jsx("div", { role: role, style: { position: 'relative', overflow: 'hidden', width: outerWidth, height: outerHeight }, children: jsxRuntime.jsx("div", { style: { position: 'absolute', top: margin.top, left: margin.left }, children: layers.map(function (layer, i) { if (layerById[layer] !== undefined) { return layerById[layer]; } if (typeof layer === 'function') { return jsxRuntime.jsx(React.Fragment, { children: React.createElement(layer, layerContext) }, i); } return null; }) }) }); }; var CirclePackingHtml = function CirclePackingHtml(_ref2) { var theme = _ref2.theme, _ref2$isInteractive = _ref2.isInteractive, isInteractive = _ref2$isInteractive === void 0 ? defaultProps.isInteractive : _ref2$isInteractive, _ref2$animate = _ref2.animate, animate = _ref2$animate === void 0 ? defaultProps.animate : _ref2$animate, _ref2$motionConfig = _ref2.motionConfig, motionConfig = _ref2$motionConfig === void 0 ? defaultProps.motionConfig : _ref2$motionConfig, otherProps = _objectWithoutProperties(_ref2, ["theme", "isInteractive", "animate", "motionConfig"]); return jsxRuntime.jsx(nivoCore.Container, { isInteractive: isInteractive, animate: animate, motionConfig: motionConfig, theme: theme, children: jsxRuntime.jsx(InnerCirclePackingHtml, _objectSpread2({ isInteractive: isInteractive }, otherProps)) }); }; var ResponsiveCirclePackingHtml = function ResponsiveCirclePackingHtml(props) { return jsxRuntime.jsx(nivoCore.ResponsiveWrapper, { children: function children(_ref) { var width = _ref.width, height = _ref.height; return jsxRuntime.jsx(CirclePackingHtml, _objectSpread2({ width: width, height: height }, props)); } }); }; var InnerCirclePackingCanvas = function InnerCirclePackingCanvas(_ref) { var data = _ref.data, _ref$id = _ref.id, id = _ref$id === void 0 ? defaultProps.id : _ref$id, _ref$value = _ref.value, value = _ref$value === void 0 ? defaultProps.value : _ref$value, valueFormat = _ref.valueFormat, width = _ref.width, height = _ref.height, partialMargin = _ref.margin, _ref$padding = _ref.padding, padding = _ref$padding === void 0 ? defaultProps.padding : _ref$padding, _ref$leavesOnly = _ref.leavesOnly, leavesOnly = _ref$leavesOnly === void 0 ? defaultProps.leavesOnly : _ref$leavesOnly, _ref$colors = _ref.colors, colors = _ref$colors === void 0 ? defaultProps.colors : _ref$colors, _ref$colorBy = _ref.colorBy, colorBy = _ref$colorBy === void 0 ? defaultProps.colorBy : _ref$colorBy, _ref$inheritColorFrom = _ref.inheritColorFromParent, inheritColorFromParent = _ref$inheritColorFrom === void 0 ? defaultProps.inheritColorFromParent : _ref$inheritColorFrom, _ref$childColor = _ref.childColor, childColor = _ref$childColor === void 0 ? defaultProps.childColor : _ref$childColor, _ref$borderWidth = _ref.borderWidth, borderWidth = _ref$borderWidth === void 0 ? defaultProps.borderWidth : _ref$borderWidth, _ref$borderColor = _ref.borderColor, borderColor = _ref$borderColor === void 0 ? defaultProps.borderColor : _ref$borderColor, _ref$enableLabels = _ref.enableLabels, enableLabels = _ref$enableLabels === void 0 ? defaultProps.enableLabels : _ref$enableLabels, _ref$label = _ref.label, label = _ref$label === void 0 ? defaultProps.label : _ref$label, labelsFilter = _ref.labelsFilter, _ref$labelsSkipRadius = _ref.labelsSkipRadius, labelsSkipRadius = _ref$labelsSkipRadius === void 0 ? defaultProps.labelsSkipRadius : _ref$labelsSkipRadius, _ref$labelTextColor = _ref.labelTextColor, labelTextColor = _ref$labelTextColor === void 0 ? defaultProps.labelTextColor : _ref$labelTextColor, isInteractive = _ref.isInteractive, onMouseMove = _ref.onMouseMove, onClick = _ref.onClick, _ref$tooltip = _ref.tooltip, tooltip = _ref$tooltip === void 0 ? defaultProps.tooltip : _ref$tooltip, zoomedId = _ref.zoomedId, _ref$role = _ref.role, role = _ref$role === void 0 ? defaultProps.role : _ref$role, _ref$pixelRatio = _ref.pixelRatio, pixelRatio = _ref$pixelRatio === void 0 ? defaultProps.pixelRatio : _ref$pixelRatio; var canvasEl = React.useRef(null); var theme = nivoCore.useTheme(); var _useDimensions = nivoCore.useDimensions(width, height, partialMargin), margin = _useDimensions.margin, innerWidth = _useDimensions.innerWidth, innerHeight = _useDimensions.innerHeight, outerWidth = _useDimensions.outerWidth, outerHeight = _useDimensions.outerHeight; var nodes = useCirclePacking({ data: data, id: id, value: value, valueFormat: valueFormat, width: innerWidth, height: innerHeight, padding: padding, leavesOnly: leavesOnly, colors: colors, colorBy: colorBy, inheritColorFromParent: inheritColorFromParent, childColor: childColor }); var zoomedNodes = useCirclePackingZoom(nodes, zoomedId, innerWidth, innerHeight); var labels = useCirclePackingLabels({ nodes: zoomedNodes, label: label, filter: labelsFilter, skipRadius: labelsSkipRadius, textColor: labelTextColor }); var getBorderColor = nivoColors.useInheritedColor(borderColor, theme); React.useEffect(function () { if (!canvasEl.current) return; canvasEl.current.width = outerWidth * pixelRatio; canvasEl.current.height = outerHeight * pixelRatio; var ctx = canvasEl.current.getContext('2d'); ctx.scale(pixelRatio, pixelRatio); ctx.fillStyle = theme.background; ctx.fillRect(0, 0, outerWidth, outerHeight); ctx.save(); ctx.translate(margin.left, margin.top); zoomedNodes.forEach(function (node) { if (borderWidth > 0) { ctx.strokeStyle = getBorderColor(node); ctx.lineWidth = borderWidth; } ctx.beginPath(); ctx.arc(node.x, node.y, node.radius, 0, 2 * Math.PI); ctx.fillStyle = node.color; ctx.fill(); if (borderWidth > 0) { ctx.stroke(); } }); if (enableLabels) { ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.font = "".concat(theme.labels.text.fontSize, "px ").concat(theme.labels.text.fontFamily); labels.forEach(function (label) { ctx.fillStyle = label.textColor; ctx.fillText("".concat(label.label), label.node.x, label.node.y); }); } }, [canvasEl, innerWidth, innerHeight, outerWidth, outerHeight, margin.top, margin.left, theme, pixelRatio, zoomedNodes, enableLabels, labels, borderWidth, getBorderColor]); var getNodeFromMouseEvent = useMouseCircleDetection({ nodes: zoomedNodes, canvasEl: canvasEl, margin: margin }); var _useTooltip = nivoTooltip.useTooltip(), showTooltipFromEvent = _useTooltip.showTooltipFromEvent, hideTooltip = _useTooltip.hideTooltip; var handleMouseHover = React.useCallback(function (event) { var node = getNodeFromMouseEvent(event); if (node) { onMouseMove === null || onMouseMove === void 0 ? void 0 : onMouseMove(node, event); showTooltipFromEvent(React.createElement(tooltip, node), event); } else { hideTooltip(); } }, [getNodeFromMouseEvent, showTooltipFromEvent, tooltip, hideTooltip]); var handleMouseLeave = React.useCallback(function () { hideTooltip(); }, [hideTooltip]); var handleClick = React.useCallback(function (event) { if (!onClick) return; var node = getNodeFromMouseEvent(event); if (node) { onClick(node, event); } }, [getNodeFromMouseEvent, onClick]); return jsxRuntime.jsx("canvas", { ref: canvasEl, width: outerWidth * pixelRatio, height: outerHeight * pixelRatio, style: { width: outerWidth, height: outerHeight, cursor: isInteractive ? 'auto' : 'normal' }, role: role, onMouseEnter: isInteractive ? handleMouseHover : undefined, onMouseMove: isInteractive ? handleMouseHover : undefined, onMouseLeave: isInteractive ? handleMouseLeave : undefined, onClick: isInteractive ? handleClick : undefined }); }; var CirclePackingCanvas = function CirclePackingCanvas(_ref2) { var _ref2$isInteractive = _ref2.isInteractive, isInteractive = _ref2$isInteractive === void 0 ? defaultProps.isInteractive : _ref2$isInteractive, theme = _ref2.theme, otherProps = _objectWithoutProperties(_ref2, ["isInteractive", "theme"]); return jsxRuntime.jsx(nivoCore.Container, { isInteractive: isInteractive, theme: theme, children: jsxRuntime.jsx(InnerCirclePackingCanvas, _objectSpread2({ isInteractive: isInteractive }, otherProps)) }); }; var ResponsiveCirclePackingCanvas = function ResponsiveCirclePackingCanvas(props) { return jsxRuntime.jsx(nivoCore.ResponsiveWrapper, { children: function children(_ref) { var width = _ref.width, height = _ref.height; return jsxRuntime.jsx(CirclePackingCanvas, _objectSpread2({ width: width, height: height }, props)); } }); }; exports.CirclePacking = CirclePacking; exports.CirclePackingCanvas = CirclePackingCanvas; exports.CirclePackingHtml = CirclePackingHtml; exports.InnerCirclePackingHtml = InnerCirclePackingHtml; exports.ResponsiveCirclePacking = ResponsiveCirclePacking; exports.ResponsiveCirclePackingCanvas = ResponsiveCirclePackingCanvas; exports.ResponsiveCirclePackingHtml = ResponsiveCirclePackingHtml; exports.defaultProps = defaultProps; exports.useCirclePacking = useCirclePacking; exports.useCirclePackingLabels = useCirclePackingLabels; exports.useCirclePackingLayerContext = useCirclePackingLayerContext; exports.useCirclePackingZoom = useCirclePackingZoom; exports.useMouseCircleDetection = useMouseCircleDetection; exports.useNodeMouseHandlers = useNodeMouseHandlers; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=nivo-circle-packing.umd.js.map