<commit_before>import { Fragment, ReactNode, useCallback, createElement } from 'react'
import { Container, useDimensions, SvgWrapper } from '@nivo/core'
import { useTooltip } from '@nivo/tooltip'
import { svgDefaultProps } from './defaults'
import { useNetwork } from './hooks'
import { NetworkNodes } from './NetworkNodes'
import { NetworkLinks } from './NetworkLinks'
import { NetworkInputNode, NetworkLayerId, NetworkSvgProps } from './types'

type InnerNetworkProps<N extends NetworkInputNode> = Omit<
    NetworkSvgProps<N>,
    'animate' | 'motionConfig' | 'renderWrapper' | 'theme'
>

const InnerNetwork = <N extends NetworkInputNode>({
    width,
    height,
    margin: partialMargin,

    data: { nodes: rawNodes, links: rawLinks },

    linkDistance = svgDefaultProps.linkDistance,
    repulsivity = svgDefaultProps.repulsivity,
    distanceMin = svgDefaultProps.distanceMin,
    distanceMax = svgDefaultProps.distanceMax,
    iterations = svgDefaultProps.iterations,

    layers = svgDefaultProps.layers,

    nodeComponent = svgDefaultProps.nodeComponent,
    nodeColor = svgDefaultProps.nodeColor,
    nodeBorderWidth = svgDefaultProps.nodeBorderWidth,
    nodeBorderColor = svgDefaultProps.nodeBorderColor,

    linkComponent = svgDefaultProps.linkComponent,
    linkThickness = svgDefaultProps.linkThickness,
    linkColor = svgDefaultProps.linkColor,

    isInteractive = svgDefaultProps.isInteractive,
    nodeTooltip = svgDefaultProps.nodeTooltip,
    onClick,

    role = svgDefaultProps.role,
}: InnerNetworkProps<N>) => {
    const { margin, innerWidth, innerHeight, outerWidth, outerHeight } = useDimensions(
        width,
        height,
        partialMargin
    )

    const [nodes, links] = useNetwork<N>({
        center: [innerWidth / 2, innerHeight / 2],
        nodes: rawNodes,
        links: rawLinks,
        linkDistance,
        repulsivity,
        distanceMin,
        distanceMax,
        iterations,
        nodeColor,
        nodeBorderWidth,
        nodeBorderColor,
        linkThickness,
        linkColor,
    })

    const { showTooltipFromEvent, hideTooltip } = useTooltip()

    const handleNodeHover = useCallback(
        (node, event) => {
            showTooltipFromEvent(createElement(nodeTooltip, { node }), event)
        },
        [showTooltipFromEvent, nodeTooltip]
    )

    const handleNodeLeave = useCallback(() => {
        hideTooltip()
    }, [hideTooltip])

    const layerById: Record<NetworkLayerId, ReactNode> = {
        links: null,
        nodes: null,
    }

    if (layers.includes('links') && links !== null) {
        layerById.links = (
            <NetworkLinks<N> key="links" links={links} linkComponent={linkComponent} />
        )
    }

    if (layers.includes('nodes') && nodes !== null) {
        layerById.nodes = (
            <NetworkNodes<N>
                key="nodes"
                nodes={nodes}
                nodeComponent={nodeComponent}
                onClick={isInteractive ? onClick : undefined}
                onMouseEnter={isInteractive ? handleNodeHover : undefined}
                onMouseMove={isInteractive ? handleNodeHover : undefined}
                onMouseLeave={isInteractive ? handleNodeLeave : undefined}
            />
        )
    }

    return (
        <SvgWrapper width={outerWidth} height={outerHeight} margin={margin} role={role}>
            {layers.map((layer, i) => {
                if (typeof layer === 'function') {
                    return (
                        <Fragment key={i}><commit_msg>feat(network): forward aria props to SvgWrapper<commit_after>import { Fragment, ReactNode, useCallback, createElement } from 'react'
import { Container, useDimensions, SvgWrapper } from '@nivo/core'
import { useTooltip } from '@nivo/tooltip'
import { svgDefaultProps } from './defaults'
import { useNetwork } from './hooks'
import { NetworkNodes } from './NetworkNodes'
import { NetworkLinks } from './NetworkLinks'
import { NetworkInputNode, NetworkLayerId, NetworkSvgProps } from './types'

type InnerNetworkProps<N extends NetworkInputNode> = Omit<
    NetworkSvgProps<N>,
    'animate' | 'motionConfig' | 'renderWrapper' | 'theme'
>

const InnerNetwork = <N extends NetworkInputNode>({
    width,
    height,
    margin: partialMargin,

    data: { nodes: rawNodes, links: rawLinks },

    linkDistance = svgDefaultProps.linkDistance,
    repulsivity = svgDefaultProps.repulsivity,
    distanceMin = svgDefaultProps.distanceMin,
    distanceMax = svgDefaultProps.distanceMax,
    iterations = svgDefaultProps.iterations,

    layers = svgDefaultProps.layers,

    nodeComponent = svgDefaultProps.nodeComponent,
    nodeColor = svgDefaultProps.nodeColor,
    nodeBorderWidth = svgDefaultProps.nodeBorderWidth,
    nodeBorderColor = svgDefaultProps.nodeBorderColor,

    linkComponent = svgDefaultProps.linkComponent,
    linkThickness = svgDefaultProps.linkThickness,
    linkColor = svgDefaultProps.linkColor,

    isInteractive = svgDefaultProps.isInteractive,
    nodeTooltip = svgDefaultProps.nodeTooltip,
    onClick,

    role = svgDefaultProps.role,
    ariaLabel,
    ariaLabelledBy,
    ariaDescribedBy,
}: InnerNetworkProps<N>) => {
    const { margin, innerWidth, innerHeight, outerWidth, outerHeight } = useDimensions(
        width,
        height,
        partialMargin
    )

    const [nodes, links] = useNetwork<N>({
        center: [innerWidth / 2, innerHeight / 2],
        nodes: rawNodes,
        links: rawLinks,
        linkDistance,
        repulsivity,
        distanceMin,
        distanceMax,
        iterations,
        nodeColor,
        nodeBorderWidth,
        nodeBorderColor,
        linkThickness,
        linkColor,
    })

    const { showTooltipFromEvent, hideTooltip } = useTooltip()

    const handleNodeHover = useCallback(
        (node, event) => {
            showTooltipFromEvent(createElement(nodeTooltip, { node }), event)
        },
        [showTooltipFromEvent, nodeTooltip]
    )

    const handleNodeLeave = useCallback(() => {
        hideTooltip()
    }, [hideTooltip])

    const layerById: Record<NetworkLayerId, ReactNode> = {
        links: null,
        nodes: null,
    }

    if (layers.includes('links') && links !== null) {
        layerById.links = (
            <NetworkLinks<N> key="links" links={links} linkComponent={linkComponent} />
        )
    }

    if (layers.includes('nodes') && nodes !== null) {
        layerById.nodes = (
            <NetworkNodes<N>
                key="nodes"
                nodes={nodes}
                nodeComponent={nodeComponent}
                onClick={isInteractive ? onClick : undefined}
                onMouseEnter={isInteractive ? handleNodeHover : undefined}
                onMouseMove={isInteractive ? handleNodeHover : undefined}
                onMouseLeave={isInteractive ? handleNodeLeave : undefined}
            />
        )
    }

    return (
        <SvgWrapper
            width={outerWidth}
            height={outerHeight}
            margin={margin}
            role={role}
            ariaLabel={ariaLabel}
            ariaLabelledBy={ariaLabelledBy}
            ariaDescribedBy={ariaDescribedBy}
        >
            {layers.map((layer, i) => {
                if (typeof layer === 'function') {
                    return (
                        <Fragment key={i}>
{'fraction_non_alphanumeric': 0.10165097557647701, 'fraction_numerical': 0.0005457770500750444, 'mean_word_length': 2.6090595765632694, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4018577', 'n_tokens_mistral': 2040, 'n_tokens_neox': 2000, 'n_words': 414}