UNPKG

@nivo/funnel

Version:
1 lines 61.3 kB
{"version":3,"file":"nivo-funnel.mjs","sources":["../src/props.tsx","../src/PartTooltip.tsx","../src/hooks.ts","../src/Part.tsx","../src/Parts.tsx","../src/PartLabel.tsx","../src/PartLabels.tsx","../src/Separator.tsx","../src/Separators.tsx","../src/FunnelAnnotations.tsx","../src/Funnel.tsx","../src/ResponsiveFunnel.tsx"],"sourcesContent":["import { motionDefaultProps } from '@nivo/core'\nimport { FunnelLayerId } from './types'\n\nexport const svgDefaultProps = {\n layers: ['separators', 'parts', 'labels', 'annotations'] as FunnelLayerId[],\n\n direction: 'vertical' as const,\n interpolation: 'smooth' as const,\n spacing: 0,\n shapeBlending: 0.66,\n\n colors: { scheme: 'nivo' as const },\n size: undefined,\n fillOpacity: 1,\n\n borderWidth: 6,\n borderColor: { from: 'color' },\n borderOpacity: 0.66,\n\n enableLabel: true,\n labelColor: { theme: 'background' },\n\n enableBeforeSeparators: true,\n beforeSeparatorLength: 0,\n beforeSeparatorOffset: 0,\n enableAfterSeparators: true,\n afterSeparatorLength: 0,\n afterSeparatorOffset: 0,\n\n annotations: [],\n\n isInteractive: true,\n currentPartSizeExtension: 0,\n\n role: 'img',\n\n animate: motionDefaultProps.animate,\n motionConfig: motionDefaultProps.config,\n}\n","import { BasicTooltip } from '@nivo/tooltip'\nimport { FunnelDatum, FunnelPartWithHandlers } from './types'\n\nexport interface PartTooltipProps<D extends FunnelDatum> {\n part: FunnelPartWithHandlers<D>\n}\n\nexport const PartTooltip = <D extends FunnelDatum>({ part }: PartTooltipProps<D>) => (\n <BasicTooltip\n id={part.data.label}\n value={part.formattedValue}\n color={part.color}\n enableChip={true}\n />\n)\n","import { createElement, useMemo, useState, MouseEvent } from 'react'\nimport { line, area, curveBasis, curveLinear } from 'd3-shape'\nimport { ScaleLinear, scaleLinear, scaleOrdinal } from 'd3-scale'\nimport { useInheritedColor, useOrdinalColorScale } from '@nivo/colors'\nimport { useValueFormatter } from '@nivo/core'\nimport { useTheme } from '@nivo/theming'\nimport { useAnnotations } from '@nivo/annotations'\nimport { useTooltip, TooltipActionsContextData } from '@nivo/tooltip'\nimport { svgDefaultProps as defaults } from './props'\nimport { PartTooltip, PartTooltipProps } from './PartTooltip'\nimport isPlainObject from 'lodash/isPlainObject.js'\nimport get from 'lodash/get.js'\nimport {\n FunnelDatum,\n FunnelCommonProps,\n FunnelDataProps,\n FunnelPart,\n SeparatorProps,\n FunnelCustomLayerProps,\n FunnelAreaGenerator,\n FunnelAreaPoint,\n FunnelBorderGenerator,\n Position,\n SizeSpec,\n SizeSpecDatumProperty,\n} from './types'\n\nexport const computeShapeGenerators = <D extends FunnelDatum>(\n interpolation: FunnelCommonProps<D>['interpolation'],\n direction: FunnelCommonProps<D>['direction']\n): [FunnelAreaGenerator, FunnelBorderGenerator] => {\n // area generator which is used to draw funnel chart parts\n const areaGenerator: FunnelAreaGenerator = area<FunnelAreaPoint>()\n if (direction === 'vertical') {\n areaGenerator\n .curve(interpolation === 'smooth' ? curveBasis : curveLinear)\n .x0(d => d.x0)\n .x1(d => d.x1)\n .y(d => d.y)\n } else {\n areaGenerator\n .curve(interpolation === 'smooth' ? curveBasis : curveLinear)\n .y0(d => d.y0)\n .y1(d => d.y1)\n .x(d => d.x)\n }\n\n return [\n areaGenerator,\n // we're using a different line generator to draw borders, this way\n // we we don't have borders joining each side of the parts.\n // it's important to have an empty point when defining the points\n // to be used along with this, otherwise we'll get a line between both sides.\n line<Position | null>()\n .defined(d => d !== null)\n .x(d => d!.x)\n .y(d => d!.y)\n .curve(interpolation === 'smooth' ? curveBasis : curveLinear),\n ]\n}\n\ninterface CustomBandScale {\n (index: number): number\n bandwidth: number\n}\n\nexport const computeScales = <D extends FunnelDatum>({\n data,\n direction,\n width,\n height,\n spacing,\n}: {\n data: FunnelDataProps<D>['data']\n direction: FunnelCommonProps<D>['direction']\n width: number\n height: number\n spacing: number\n}): [CustomBandScale, ScaleLinear<number, number>] => {\n let bandScaleSize\n let linearScaleSize\n if (direction === 'vertical') {\n bandScaleSize = height\n linearScaleSize = width\n } else {\n bandScaleSize = width\n linearScaleSize = height\n }\n\n const bandwidth = (bandScaleSize - spacing * (data.length - 1)) / data.length\n\n // we're not using d3 band scale here to be able to get\n // the actual paddingInner value in pixels, required to\n // create centered separator lines between parts\n const bandScale = (index: number) => spacing * index + bandwidth * index\n bandScale.bandwidth = bandwidth\n\n const allValues = data.map(d => d.value)\n\n const linearScale = scaleLinear()\n .domain([0, Math.max(...allValues)])\n .range([0, linearScaleSize])\n\n return [bandScale, linearScale]\n}\n\nexport const computeSeparators = <D extends FunnelDatum>({\n parts,\n direction,\n width,\n height,\n spacing,\n enableBeforeSeparators,\n beforeSeparatorOffset,\n enableAfterSeparators,\n afterSeparatorOffset,\n}: {\n parts: FunnelPart<D>[]\n direction: FunnelCommonProps<D>['direction']\n width: number\n height: number\n spacing: number\n enableBeforeSeparators: boolean\n beforeSeparatorOffset: number\n enableAfterSeparators: boolean\n afterSeparatorOffset: number\n}) => {\n const beforeSeparators: SeparatorProps[] = []\n const afterSeparators: SeparatorProps[] = []\n const lastPart = parts[parts.length - 1]\n\n if (direction === 'vertical') {\n parts.forEach(part => {\n const y = part.y0 - spacing / 2\n\n if (enableBeforeSeparators) {\n beforeSeparators.push({\n partId: part.data.id,\n x0: 0,\n x1: part.x0 - beforeSeparatorOffset,\n y0: y,\n y1: y,\n })\n }\n if (enableAfterSeparators) {\n afterSeparators.push({\n partId: part.data.id,\n x0: part.x1 + afterSeparatorOffset,\n x1: width,\n y0: y,\n y1: y,\n })\n }\n })\n\n const y = lastPart.y1\n if (enableBeforeSeparators) {\n beforeSeparators.push({\n ...beforeSeparators[beforeSeparators.length - 1],\n partId: 'none',\n y0: y,\n y1: y,\n })\n }\n if (enableAfterSeparators) {\n afterSeparators.push({\n ...afterSeparators[afterSeparators.length - 1],\n partId: 'none',\n y0: y,\n y1: y,\n })\n }\n } else if (direction === 'horizontal') {\n parts.forEach(part => {\n const x = part.x0 - spacing / 2\n\n beforeSeparators.push({\n partId: part.data.id,\n x0: x,\n x1: x,\n y0: 0,\n y1: part.y0 - beforeSeparatorOffset,\n })\n afterSeparators.push({\n partId: part.data.id,\n x0: x,\n x1: x,\n y0: part.y1 + afterSeparatorOffset,\n y1: height,\n })\n })\n\n const x = lastPart.x1\n beforeSeparators.push({\n ...beforeSeparators[beforeSeparators.length - 1],\n partId: 'none',\n x0: x,\n x1: x,\n })\n afterSeparators.push({\n ...afterSeparators[afterSeparators.length - 1],\n partId: 'none',\n x0: x,\n x1: x,\n })\n }\n\n return [beforeSeparators, afterSeparators]\n}\n\nexport const computePartsHandlers = <D extends FunnelDatum>({\n parts,\n setCurrentPartId,\n isInteractive,\n onMouseEnter,\n onMouseLeave,\n onMouseMove,\n onClick,\n showTooltipFromEvent,\n hideTooltip,\n tooltip = PartTooltip,\n}: {\n parts: FunnelPart<D>[]\n setCurrentPartId: (id: string | number | null) => void\n isInteractive: FunnelCommonProps<D>['isInteractive']\n onMouseEnter?: FunnelCommonProps<D>['onMouseEnter']\n onMouseLeave?: FunnelCommonProps<D>['onMouseLeave']\n onMouseMove?: FunnelCommonProps<D>['onMouseMove']\n onClick?: FunnelCommonProps<D>['onClick']\n showTooltipFromEvent: TooltipActionsContextData['showTooltipFromEvent']\n hideTooltip: () => void\n tooltip?: (props: PartTooltipProps<D>) => JSX.Element\n}) => {\n if (!isInteractive) return parts\n\n return parts.map(part => {\n const boundOnMouseEnter = (event: MouseEvent) => {\n setCurrentPartId(part.data.id)\n showTooltipFromEvent(createElement(tooltip, { part }), event)\n onMouseEnter?.(part, event)\n }\n\n const boundOnMouseLeave = (event: MouseEvent) => {\n setCurrentPartId(null)\n hideTooltip()\n onMouseLeave?.(part, event)\n }\n\n const boundOnMouseMove = (event: MouseEvent) => {\n showTooltipFromEvent(createElement(tooltip, { part }), event)\n onMouseMove?.(part, event)\n }\n\n const boundOnClick =\n onClick !== undefined\n ? (event: MouseEvent) => {\n onClick(part, event)\n }\n : undefined\n\n return {\n ...part,\n onMouseEnter: boundOnMouseEnter,\n onMouseLeave: boundOnMouseLeave,\n onMouseMove: boundOnMouseMove,\n onClick: boundOnClick,\n }\n })\n}\n\nconst isSizeSpecDatumProperty = <Datum>(\n config: SizeSpec<Datum> | undefined\n): config is SizeSpecDatumProperty => {\n return (config as SizeSpecDatumProperty).datum !== undefined\n}\n\n// Get size based on configuration\nexport const getSizeGenerator = <Datum extends FunnelDatum>(\n config: SizeSpec<Datum> | undefined,\n linearScale: ScaleLinear<number, number>\n): ((datum: Datum) => number) => {\n //User defined function\n if (typeof config === 'function') {\n return config\n }\n\n // User defined sizes array\n if (Array.isArray(config)) {\n const scale = scaleOrdinal(config)\n const generator = (datum: Datum) => {\n // Ensure we're using the id property from the datum to map to the appropriate size\n return Number(scale(String(datum.id)))\n }\n\n return generator\n }\n\n if (isPlainObject(config)) {\n // Use size from current datum\n if (isSizeSpecDatumProperty(config)) {\n return (datum: Datum) => {\n const value = get(datum, config.datum)\n return typeof value === 'number' ? value : 0\n }\n }\n\n throw new Error(`Invalid size, when using an object, you should specify a 'datum' property`)\n }\n\n // Default behavior: use linearScale with datum.value\n return (datum: Datum) => linearScale(datum.value)\n}\n\n// Use size scale hook\nexport const useSize = <Datum extends FunnelDatum>(\n config: SizeSpec<Datum> | undefined,\n linearScale: ScaleLinear<number, number>\n): ((datum: Datum) => number) =>\n useMemo(() => getSizeGenerator<Datum>(config, linearScale), [config, linearScale])\n\n/**\n * Creates required layout to generate a funnel chart,\n * it uses almost the same parameters as the Funnel component.\n *\n * For purpose/constrains on the parameters, please have a look\n * at the component's props.\n */\nexport const useFunnel = <D extends FunnelDatum>({\n data,\n width,\n height,\n direction = defaults.direction,\n interpolation = defaults.interpolation,\n spacing = defaults.spacing,\n shapeBlending: rawShapeBlending = defaults.shapeBlending,\n valueFormat,\n colors = defaults.colors,\n size = defaults.size,\n fillOpacity = defaults.fillOpacity,\n borderWidth = defaults.borderWidth,\n borderColor = defaults.borderColor,\n borderOpacity = defaults.borderOpacity,\n labelColor = defaults.labelColor,\n enableBeforeSeparators = defaults.enableBeforeSeparators,\n beforeSeparatorLength = defaults.beforeSeparatorLength,\n beforeSeparatorOffset = defaults.beforeSeparatorOffset,\n enableAfterSeparators = defaults.enableAfterSeparators,\n afterSeparatorLength = defaults.afterSeparatorLength,\n afterSeparatorOffset = defaults.afterSeparatorOffset,\n isInteractive = defaults.isInteractive,\n currentPartSizeExtension = defaults.currentPartSizeExtension,\n currentBorderWidth,\n onMouseEnter,\n onMouseMove,\n onMouseLeave,\n onClick,\n tooltip,\n}: {\n data: FunnelDataProps<D>['data']\n width: number\n height: number\n direction?: FunnelCommonProps<D>['direction']\n interpolation?: FunnelCommonProps<D>['interpolation']\n spacing?: FunnelCommonProps<D>['spacing']\n shapeBlending?: FunnelCommonProps<D>['shapeBlending']\n valueFormat?: FunnelCommonProps<D>['valueFormat']\n colors?: FunnelCommonProps<D>['colors']\n size?: FunnelCommonProps<D>['size']\n fillOpacity?: FunnelCommonProps<D>['fillOpacity']\n borderWidth?: FunnelCommonProps<D>['borderWidth']\n borderColor?: FunnelCommonProps<D>['borderColor']\n borderOpacity?: FunnelCommonProps<D>['borderOpacity']\n labelColor?: FunnelCommonProps<D>['labelColor']\n enableBeforeSeparators?: FunnelCommonProps<D>['enableBeforeSeparators']\n beforeSeparatorLength?: FunnelCommonProps<D>['beforeSeparatorLength']\n beforeSeparatorOffset?: FunnelCommonProps<D>['beforeSeparatorOffset']\n enableAfterSeparators?: FunnelCommonProps<D>['enableAfterSeparators']\n afterSeparatorLength?: FunnelCommonProps<D>['afterSeparatorLength']\n afterSeparatorOffset?: FunnelCommonProps<D>['afterSeparatorOffset']\n isInteractive?: FunnelCommonProps<D>['isInteractive']\n currentPartSizeExtension?: FunnelCommonProps<D>['currentPartSizeExtension']\n currentBorderWidth?: FunnelCommonProps<D>['currentBorderWidth']\n onMouseEnter?: FunnelCommonProps<D>['onMouseEnter']\n onMouseMove?: FunnelCommonProps<D>['onMouseMove']\n onMouseLeave?: FunnelCommonProps<D>['onMouseLeave']\n onClick?: FunnelCommonProps<D>['onClick']\n tooltip?: (props: PartTooltipProps<D>) => JSX.Element\n}) => {\n const theme = useTheme()\n const getColor = useOrdinalColorScale<D>(colors, 'id')\n const getBorderColor = useInheritedColor(borderColor, theme)\n const getLabelColor = useInheritedColor(labelColor, theme)\n\n const formatValue = useValueFormatter<number>(valueFormat)\n\n const [areaGenerator, borderGenerator] = useMemo(\n () => computeShapeGenerators<D>(interpolation, direction),\n [interpolation, direction]\n )\n\n let innerWidth: number\n let innerHeight: number\n const paddingBefore = enableBeforeSeparators ? beforeSeparatorLength + beforeSeparatorOffset : 0\n const paddingAfter = enableAfterSeparators ? afterSeparatorLength + afterSeparatorOffset : 0\n if (direction === 'vertical') {\n innerWidth = width - paddingBefore - paddingAfter\n innerHeight = height\n } else {\n innerWidth = width\n innerHeight = height - paddingBefore - paddingAfter\n }\n\n const [bandScale, linearScale] = useMemo(\n () =>\n computeScales<D>({\n data,\n direction,\n width: innerWidth,\n height: innerHeight,\n spacing,\n }),\n [data, direction, innerWidth, innerHeight, spacing]\n )\n\n const getSize = useSize<D>(size, linearScale)\n\n const [currentPartId, setCurrentPartId] = useState<string | number | null>(null)\n\n const parts: FunnelPart<D>[] = useMemo(() => {\n const enhancedParts = data.map((datum, index) => {\n const isCurrent = datum.id === currentPartId\n const sizeValue = getSize(datum)\n\n let partWidth\n let partHeight\n let y0, x0\n\n if (direction === 'vertical') {\n partWidth = sizeValue\n partHeight = bandScale.bandwidth\n x0 = paddingBefore + (innerWidth - partWidth) * 0.5\n y0 = bandScale(index)\n } else {\n partWidth = bandScale.bandwidth\n partHeight = sizeValue\n x0 = bandScale(index)\n y0 = paddingBefore + (innerHeight - partHeight) * 0.5\n }\n\n const x1 = x0 + partWidth\n const x = x0 + partWidth * 0.5\n const y1 = y0 + partHeight\n const y = y0 + partHeight * 0.5\n\n const part: FunnelPart<D> = {\n data: datum,\n width: partWidth,\n height: partHeight,\n color: getColor(datum),\n fillOpacity,\n borderWidth:\n isCurrent && currentBorderWidth !== undefined\n ? currentBorderWidth\n : borderWidth,\n borderOpacity,\n formattedValue: formatValue(datum.value),\n isCurrent,\n x,\n x0,\n x1,\n y,\n y0,\n y1,\n borderColor: '',\n labelColor: '',\n points: [],\n areaPoints: [],\n borderPoints: [],\n }\n\n part.borderColor = getBorderColor(part)\n part.labelColor = getLabelColor(part)\n\n return part\n })\n\n const shapeBlending = rawShapeBlending / 2\n\n enhancedParts.forEach((part, index) => {\n const nextPart = enhancedParts[index + 1]\n\n if (direction === 'vertical') {\n part.points.push({ x: part.x0, y: part.y0 })\n part.points.push({ x: part.x1, y: part.y0 })\n if (nextPart) {\n part.points.push({ x: nextPart.x1, y: part.y1 })\n part.points.push({ x: nextPart.x0, y: part.y1 })\n } else {\n part.points.push({ x: part.points[1].x, y: part.y1 })\n part.points.push({ x: part.points[0].x, y: part.y1 })\n }\n if (part.isCurrent) {\n part.points[0].x -= currentPartSizeExtension\n part.points[1].x += currentPartSizeExtension\n part.points[2].x += currentPartSizeExtension\n part.points[3].x -= currentPartSizeExtension\n }\n\n part.areaPoints = [\n {\n x: 0,\n x0: part.points[0].x,\n x1: part.points[1].x,\n y: part.y0,\n y0: 0,\n y1: 0,\n },\n ]\n part.areaPoints.push({\n ...part.areaPoints[0],\n y: part.y0 + part.height * shapeBlending,\n })\n const lastAreaPoint = {\n x: 0,\n x0: part.points[3].x,\n x1: part.points[2].x,\n y: part.y1,\n y0: 0,\n y1: 0,\n }\n part.areaPoints.push({\n ...lastAreaPoint,\n y: part.y1 - part.height * shapeBlending,\n })\n part.areaPoints.push(lastAreaPoint)\n ;[0, 1, 2, 3].map(index => {\n part.borderPoints.push({\n x: part.areaPoints[index].x0,\n y: part.areaPoints[index].y,\n })\n })\n part.borderPoints.push(null)\n ;[3, 2, 1, 0].map(index => {\n part.borderPoints.push({\n x: part.areaPoints[index].x1,\n y: part.areaPoints[index].y,\n })\n })\n } else {\n part.points.push({ x: part.x0, y: part.y0 })\n if (nextPart) {\n part.points.push({ x: part.x1, y: nextPart.y0 })\n part.points.push({ x: part.x1, y: nextPart.y1 })\n } else {\n part.points.push({ x: part.x1, y: part.y0 })\n part.points.push({ x: part.x1, y: part.y1 })\n }\n part.points.push({ x: part.x0, y: part.y1 })\n if (part.isCurrent) {\n part.points[0].y -= currentPartSizeExtension\n part.points[1].y -= currentPartSizeExtension\n part.points[2].y += currentPartSizeExtension\n part.points[3].y += currentPartSizeExtension\n }\n\n part.areaPoints = [\n {\n x: part.x0,\n x0: 0,\n x1: 0,\n y: 0,\n y0: part.points[0].y,\n y1: part.points[3].y,\n },\n ]\n part.areaPoints.push({\n ...part.areaPoints[0],\n x: part.x0 + part.width * shapeBlending,\n })\n const lastAreaPoint = {\n x: part.x1,\n x0: 0,\n x1: 0,\n y: 0,\n y0: part.points[1].y,\n y1: part.points[2].y,\n }\n part.areaPoints.push({\n ...lastAreaPoint,\n x: part.x1 - part.width * shapeBlending,\n })\n part.areaPoints.push(lastAreaPoint)\n ;[0, 1, 2, 3].map(index => {\n part.borderPoints.push({\n x: part.areaPoints[index].x,\n y: part.areaPoints[index].y0,\n })\n })\n part.borderPoints.push(null)\n ;[3, 2, 1, 0].map(index => {\n part.borderPoints.push({\n x: part.areaPoints[index].x,\n y: part.areaPoints[index].y1,\n })\n })\n }\n })\n\n return enhancedParts\n }, [\n data,\n direction,\n bandScale,\n innerWidth,\n innerHeight,\n paddingBefore,\n rawShapeBlending,\n getColor,\n formatValue,\n getBorderColor,\n getLabelColor,\n currentPartId,\n borderOpacity,\n borderWidth,\n currentBorderWidth,\n currentPartSizeExtension,\n fillOpacity,\n getSize,\n ])\n\n const { showTooltipFromEvent, hideTooltip } = useTooltip()\n const partsWithHandlers = useMemo(\n () =>\n computePartsHandlers<D>({\n parts,\n setCurrentPartId,\n isInteractive,\n onMouseEnter,\n onMouseLeave,\n onMouseMove,\n onClick,\n showTooltipFromEvent,\n hideTooltip,\n tooltip,\n }),\n [\n parts,\n setCurrentPartId,\n isInteractive,\n onMouseEnter,\n onMouseLeave,\n onMouseMove,\n onClick,\n showTooltipFromEvent,\n hideTooltip,\n tooltip,\n ]\n )\n\n const [beforeSeparators, afterSeparators] = useMemo(\n () =>\n computeSeparators({\n parts,\n direction,\n width,\n height,\n spacing,\n enableBeforeSeparators,\n beforeSeparatorOffset,\n enableAfterSeparators,\n afterSeparatorOffset,\n }),\n [\n parts,\n direction,\n width,\n height,\n spacing,\n enableBeforeSeparators,\n beforeSeparatorOffset,\n enableAfterSeparators,\n afterSeparatorOffset,\n ]\n )\n\n const customLayerProps: FunnelCustomLayerProps<D> = useMemo(\n () => ({\n width,\n height,\n parts: partsWithHandlers,\n areaGenerator,\n borderGenerator,\n beforeSeparators,\n afterSeparators,\n setCurrentPartId,\n }),\n [\n width,\n height,\n partsWithHandlers,\n areaGenerator,\n borderGenerator,\n beforeSeparators,\n afterSeparators,\n setCurrentPartId,\n ]\n )\n\n return {\n parts: partsWithHandlers,\n areaGenerator,\n borderGenerator,\n beforeSeparators,\n afterSeparators,\n setCurrentPartId,\n currentPartId,\n customLayerProps,\n }\n}\n\nexport const useFunnelAnnotations = <D extends FunnelDatum>(\n parts: FunnelPart<D>[],\n annotations: FunnelCommonProps<D>['annotations']\n) =>\n useAnnotations<FunnelPart<D>>({\n data: parts,\n annotations,\n getPosition: (part: FunnelPart<D>) => ({\n x: part.x,\n y: part.y,\n }),\n getDimensions: (part: FunnelPart<D>) => {\n const width = part.width\n const height = part.height\n\n return { size: Math.max(width, height), width, height }\n },\n })\n","import { useSpring, animated } from '@react-spring/web'\nimport { useAnimatedPath, useMotionConfig } from '@nivo/core'\nimport {\n FunnelDatum,\n FunnelPartWithHandlers,\n FunnelAreaGenerator,\n FunnelBorderGenerator,\n} from './types'\n\nexport interface PartProps<D extends FunnelDatum> {\n part: FunnelPartWithHandlers<D>\n areaGenerator: FunnelAreaGenerator\n borderGenerator: FunnelBorderGenerator\n}\n\nexport const Part = <D extends FunnelDatum>({\n part,\n areaGenerator,\n borderGenerator,\n}: PartProps<D>) => {\n const { animate, config: motionConfig } = useMotionConfig()\n\n const animatedAreaPath = useAnimatedPath(areaGenerator(part.areaPoints) as string)\n const animatedBorderPath = useAnimatedPath(borderGenerator(part.borderPoints) as string)\n const animatedProps = useSpring({\n areaColor: part.color,\n borderWidth: part.borderWidth,\n borderColor: part.borderColor,\n config: motionConfig,\n immediate: !animate,\n })\n\n return (\n <>\n {part.borderWidth > 0 && (\n <animated.path\n d={animatedBorderPath}\n stroke={animatedProps.borderColor}\n strokeWidth={animatedProps.borderWidth}\n strokeOpacity={part.borderOpacity}\n fill=\"none\"\n />\n )}\n <animated.path\n d={animatedAreaPath}\n fill={animatedProps.areaColor}\n fillOpacity={part.fillOpacity}\n onMouseEnter={part.onMouseEnter}\n onMouseLeave={part.onMouseLeave}\n onMouseMove={part.onMouseMove}\n onClick={part.onClick}\n />\n </>\n )\n}\n","import { Part } from './Part'\nimport {\n FunnelPartWithHandlers,\n FunnelAreaGenerator,\n FunnelBorderGenerator,\n FunnelDatum,\n} from './types'\n\ninterface PartsProps<D extends FunnelDatum> {\n parts: FunnelPartWithHandlers<D>[]\n areaGenerator: FunnelAreaGenerator\n borderGenerator: FunnelBorderGenerator\n}\n\nexport const Parts = <D extends FunnelDatum>({\n parts,\n areaGenerator,\n borderGenerator,\n}: PartsProps<D>) => (\n <>\n {parts.map(part => (\n <Part<D>\n key={part.data.id}\n part={part}\n areaGenerator={areaGenerator}\n borderGenerator={borderGenerator}\n />\n ))}\n </>\n)\n","import { useSpring, animated } from '@react-spring/web'\nimport { useMotionConfig } from '@nivo/core'\nimport { useTheme } from '@nivo/theming'\nimport { Text } from '@nivo/text'\nimport { FunnelDatum, FunnelPart } from './types'\n\ninterface PartLabelProps<D extends FunnelDatum> {\n part: FunnelPart<D>\n}\n\nexport const PartLabel = <D extends FunnelDatum>({ part }: PartLabelProps<D>) => {\n const theme = useTheme()\n const { animate, config: motionConfig } = useMotionConfig()\n\n const animatedProps = useSpring({\n transform: `translate(${part.x}, ${part.y})`,\n color: part.labelColor,\n config: motionConfig,\n immediate: !animate,\n })\n\n return (\n <animated.g transform={animatedProps.transform}>\n <Text\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n style={{\n ...theme.labels.text,\n fill: animatedProps.color,\n pointerEvents: 'none',\n }}\n >\n {part.formattedValue}\n </Text>\n </animated.g>\n )\n}\n","import { PartLabel } from './PartLabel'\nimport { FunnelDatum, FunnelPart } from './types'\n\ninterface PartLabelsProps<D extends FunnelDatum> {\n parts: FunnelPart<D>[]\n}\n\nexport const PartLabels = <D extends FunnelDatum>({ parts }: PartLabelsProps<D>) => (\n <>\n {parts.map(part => (\n <PartLabel key={part.data.id} part={part} />\n ))}\n </>\n)\n","import { useSpring, animated } from '@react-spring/web'\nimport { useMotionConfig } from '@nivo/core'\nimport { useTheme } from '@nivo/theming'\nimport { SeparatorProps as SeparatorType } from './types'\n\ninterface SeparatorProps {\n separator: SeparatorType\n}\n\nexport const Separator = ({ separator }: SeparatorProps) => {\n const theme = useTheme()\n const { animate, config: motionConfig } = useMotionConfig()\n\n const animatedProps = useSpring({\n x1: separator.x0,\n x2: separator.x1,\n y1: separator.y0,\n y2: separator.y1,\n config: motionConfig,\n immediate: !animate,\n })\n\n return (\n <animated.line\n x1={animatedProps.x1}\n x2={animatedProps.x2}\n y1={animatedProps.y1}\n y2={animatedProps.y2}\n fill=\"none\"\n {...(theme.grid.line as any)}\n />\n )\n}\n","import { Separator } from './Separator'\nimport { SeparatorProps as SeparatorType } from './types'\n\ninterface SeparatorsProps {\n beforeSeparators: SeparatorType[]\n afterSeparators: SeparatorType[]\n}\n\nexport const Separators = ({ beforeSeparators, afterSeparators }: SeparatorsProps) => (\n <>\n {beforeSeparators.map(separator => (\n <Separator key={separator.partId} separator={separator} />\n ))}\n {afterSeparators.map(separator => (\n <Separator key={separator.partId} separator={separator} />\n ))}\n </>\n)\n","import { Annotation } from '@nivo/annotations'\nimport { useFunnelAnnotations } from './hooks'\nimport { FunnelDatum, FunnelPart } from './types'\n\ninterface FunnelAnnotationsProps<D extends FunnelDatum> {\n parts: FunnelPart<D>[]\n annotations: any[]\n}\n\nexport const FunnelAnnotations = <D extends FunnelDatum>({\n parts,\n annotations,\n}: FunnelAnnotationsProps<D>) => {\n const boundAnnotations = useFunnelAnnotations<D>(parts, annotations)\n\n return (\n <>\n {boundAnnotations.map((annotation, i) => (\n <Annotation key={i} {...annotation} />\n ))}\n </>\n )\n}\n","import { createElement, Fragment, ReactNode, forwardRef, Ref, ReactElement } from 'react'\nimport { SvgWrapper, Container, useDimensions, WithChartRef } from '@nivo/core'\nimport { svgDefaultProps } from './props'\nimport { useFunnel } from './hooks'\nimport { Parts } from './Parts'\nimport { PartLabels } from './PartLabels'\nimport { Separators } from './Separators'\nimport { FunnelAnnotations } from './FunnelAnnotations'\nimport { FunnelDatum, FunnelLayerId, FunnelSvgProps } from './types'\n\ntype InnerFunnelProps<D extends FunnelDatum> = Omit<\n FunnelSvgProps<D>,\n 'animate' | 'motionConfig' | 'renderWrapper' | 'theme'\n> & {\n forwardedRef: Ref<SVGSVGElement>\n}\n\nconst InnerFunnel = <D extends FunnelDatum>({\n data,\n width,\n height,\n margin: partialMargin,\n direction = svgDefaultProps.direction,\n interpolation = svgDefaultProps.interpolation,\n spacing = svgDefaultProps.spacing,\n shapeBlending = svgDefaultProps.shapeBlending,\n valueFormat,\n colors = svgDefaultProps.colors,\n size = svgDefaultProps.size,\n fillOpacity = svgDefaultProps.fillOpacity,\n borderWidth = svgDefaultProps.borderWidth,\n borderColor = svgDefaultProps.borderColor,\n borderOpacity = svgDefaultProps.borderOpacity,\n enableLabel = svgDefaultProps.enableLabel,\n labelColor = svgDefaultProps.labelColor,\n enableBeforeSeparators = svgDefaultProps.enableBeforeSeparators,\n beforeSeparatorLength = svgDefaultProps.beforeSeparatorLength,\n beforeSeparatorOffset = svgDefaultProps.beforeSeparatorOffset,\n enableAfterSeparators = svgDefaultProps.enableAfterSeparators,\n afterSeparatorLength = svgDefaultProps.afterSeparatorLength,\n afterSeparatorOffset = svgDefaultProps.afterSeparatorOffset,\n layers = svgDefaultProps.layers,\n annotations = svgDefaultProps.annotations,\n isInteractive = svgDefaultProps.isInteractive,\n currentPartSizeExtension = svgDefaultProps.currentPartSizeExtension,\n currentBorderWidth,\n onMouseEnter,\n onMouseMove,\n onMouseLeave,\n onClick,\n tooltip,\n role = svgDefaultProps.role,\n ariaLabel,\n ariaLabelledBy,\n ariaDescribedBy,\n forwardedRef,\n}: InnerFunnelProps<D>) => {\n const { margin, innerWidth, innerHeight, outerWidth, outerHeight } = useDimensions(\n width,\n height,\n partialMargin\n )\n\n const {\n areaGenerator,\n borderGenerator,\n parts,\n beforeSeparators,\n afterSeparators,\n customLayerProps,\n } = useFunnel<D>({\n data,\n width: innerWidth,\n height: innerHeight,\n direction,\n interpolation,\n spacing,\n shapeBlending,\n valueFormat,\n colors,\n size,\n fillOpacity,\n borderWidth,\n borderColor,\n borderOpacity,\n labelColor,\n enableBeforeSeparators,\n beforeSeparatorLength,\n beforeSeparatorOffset,\n enableAfterSeparators,\n afterSeparatorLength,\n afterSeparatorOffset,\n isInteractive,\n currentPartSizeExtension,\n currentBorderWidth,\n onMouseEnter,\n onMouseMove,\n onMouseLeave,\n onClick,\n tooltip,\n })\n\n const layerById: Record<FunnelLayerId, ReactNode> = {\n separators: null,\n parts: null,\n annotations: null,\n labels: null,\n }\n\n if (layers.includes('separators')) {\n layerById.separators = (\n <Separators\n key=\"separators\"\n beforeSeparators={beforeSeparators}\n afterSeparators={afterSeparators}\n />\n )\n }\n\n if (layers.includes('parts')) {\n layerById.parts = (\n <Parts<D>\n key=\"parts\"\n parts={parts}\n areaGenerator={areaGenerator}\n borderGenerator={borderGenerator}\n />\n )\n }\n\n if (layers?.includes('annotations')) {\n layerById.annotations = (\n <FunnelAnnotations<D> key=\"annotations\" parts={parts} annotations={annotations} />\n )\n }\n\n if (layers.includes('labels') && enableLabel) {\n layerById.labels = <PartLabels<D> key=\"labels\" parts={parts} />\n }\n\n return (\n <SvgWrapper\n width={outerWidth}\n height={outerHeight}\n margin={margin}\n role={role}\n ariaLabel={ariaLabel}\n ariaLabelledBy={ariaLabelledBy}\n ariaDescribedBy={ariaDescribedBy}\n ref={forwardedRef}\n >\n {layers.map((layer, i) => {\n if (typeof layer === 'function') {\n return <Fragment key={i}>{createElement(layer, customLayerProps)}</Fragment>\n }\n\n return layerById?.[layer] ?? null\n })}\n </SvgWrapper>\n )\n}\n\nexport const Funnel = forwardRef(\n <D extends FunnelDatum = FunnelDatum>(\n {\n isInteractive = svgDefaultProps.isInteractive,\n animate = svgDefaultProps.animate,\n motionConfig = svgDefaultProps.motionConfig,\n theme,\n renderWrapper,\n ...otherProps\n }: FunnelSvgProps<D>,\n ref: Ref<SVGSVGElement>\n ) => (\n <Container\n {...{\n animate,\n isInteractive,\n motionConfig,\n renderWrapper,\n theme,\n }}\n >\n <InnerFunnel<D> isInteractive={isInteractive} {...otherProps} forwardedRef={ref} />\n </Container>\n )\n) as <D extends FunnelDatum = FunnelDatum>(\n props: WithChartRef<FunnelSvgProps<D>, SVGSVGElement>\n) => ReactElement\n","import { forwardRef, Ref, ReactElement } from 'react'\nimport { ResponsiveProps, ResponsiveWrapper, WithChartRef } from '@nivo/core'\nimport { FunnelDatum, FunnelSvgProps } from './types'\nimport { Funnel } from './Funnel'\n\nexport const ResponsiveFunnel = forwardRef(\n <D extends FunnelDatum = FunnelDatum>(\n {\n defaultWidth,\n defaultHeight,\n onResize,\n debounceResize,\n ...props\n }: ResponsiveProps<FunnelSvgProps<D>>,\n ref: Ref<SVGSVGElement>\n ) => (\n <ResponsiveWrapper\n defaultWidth={defaultWidth}\n defaultHeight={defaultHeight}\n onResize={onResize}\n debounceResize={debounceResize}\n >\n {({ width, height }) => (\n <Funnel<D> width={width} height={height} {...props} ref={ref} />\n )}\n </ResponsiveWrapper>\n )\n) as <D extends FunnelDatum = FunnelDatum>(\n props: WithChartRef<ResponsiveProps<FunnelSvgProps<D>>, SVGSVGElement>\n) => ReactElement\n"],"names":["svgDefaultProps","layers","direction","interpolation","spacing","shapeBlending","colors","scheme","size","undefined","fillOpacity","borderWidth","borderColor","from","borderOpacity","enableLabel","labelColor","theme","enableBeforeSeparators","beforeSeparatorLength","beforeSeparatorOffset","enableAfterSeparators","afterSeparatorLength","afterSeparatorOffset","annotations","isInteractive","currentPartSizeExtension","role","animate","motionDefaultProps","motionConfig","config","PartTooltip","_ref","part","_jsx","BasicTooltip","id","data","label","value","formattedValue","color","enableChip","computeShapeGenerators","areaGenerator","area","curve","curveBasis","curveLinear","x0","d","x1","y","y0","y1","x","line","defined","computeScales","bandScaleSize","linearScaleSize","width","height","bandwidth","length","bandScale","index","allValues","map","scaleLinear","domain","Math","max","apply","range","computeSeparators","_ref2","parts","beforeSeparators","afterSeparators","lastPart","forEach","push","partId","_extends","computePartsHandlers","_ref3","setCurrentPartId","onMouseEnter","onMouseLeave","onMouseMove","onClick","showTooltipFromEvent","hideTooltip","_ref3$tooltip","tooltip","event","createElement","getSizeGenerator","linearScale","Array","isArray","scale","scaleOrdinal","datum","Number","String","isPlainObject","isSizeSpecDatumProperty","get","Error","useSize","useMemo","useFunnel","_ref4","innerWidth","innerHeight","_ref4$direction","defaults","_ref4$interpolation","_ref4$spacing","_ref4$shapeBlending","rawShapeBlending","valueFormat","_ref4$colors","_ref4$size","_ref4$fillOpacity","_ref4$borderWidth","_ref4$borderColor","_ref4$borderOpacity","_ref4$labelColor","_ref4$enableBeforeSep","_ref4$beforeSeparator","_ref4$beforeSeparator2","_ref4$enableAfterSepa","_ref4$afterSeparatorL","_ref4$afterSeparatorO","_ref4$isInteractive","_ref4$currentPartSize","currentBorderWidth","useTheme","getColor","useOrdinalColorScale","getBorderColor","useInheritedColor","getLabelColor","formatValue","useValueFormatter","_useMemo","borderGenerator","paddingBefore","paddingAfter","_useMemo2","getSize","_useState","useState","currentPartId","enhancedParts","partWidth","partHeight","isCurrent","sizeValue","points","areaPoints","borderPoints","nextPart","lastAreaPoint","_useTooltip","useTooltip","partsWithHandlers","_useMemo3","customLayerProps","useFunnelAnnotations","useAnnotations","getPosition","getDimensions","Part","_useMotionConfig","useMotionConfig","animatedAreaPath","useAnimatedPath","animatedBorderPath","animatedProps","useSpring","areaColor","immediate","_jsxs","_Fragment","children","animated","path","stroke","strokeWidth","strokeOpacity","fill","Parts","PartLabel","transform","g","Text","textAnchor","dominantBaseline","style","labels","text","pointerEvents","PartLabels","Separator","separator","x2","y2","grid","Separators","FunnelAnnotations","boundAnnotations","annotation","i","Annotation","InnerFunnel","partialMargin","margin","_ref$direction","_ref$interpolation","_ref$spacing","_ref$shapeBlending","_ref$colors","_ref$size","_ref$fillOpacity","_ref$borderWidth","_ref$borderColor","_ref$borderOpacity","_ref$enableLabel","_ref$labelColor","_ref$enableBeforeSepa","_ref$beforeSeparatorL","_ref$beforeSeparatorO","_ref$enableAfterSepar","_ref$afterSeparatorLe","_ref$afterSeparatorOf","_ref$layers","_ref$annotations","_ref$isInteractive","_ref$currentPartSizeE","_ref$role","ariaLabel","ariaLabelledBy","ariaDescribedBy","forwardedRef","_useDimensions","useDimensions","outerWidth","outerHeight","_useFunnel","layerById","separators","includes","SvgWrapper","ref","layer","_layerById$layer","Fragment","Funnel","forwardRef","_ref2$isInteractive","_ref2$animate","_ref2$motionConfig","renderWrapper","otherProps","_objectWithoutPropertiesLoose","_excluded","Container","ResponsiveFunnel","defaultWidth","defaultHeight","onResize","debounceResize","props","ResponsiveWrapper"],"mappings":"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