<commit_before>import { ExternalLink, Highlight, nodeHref } from "../../common";
import React, { memo, useCallback, useMemo } from "react";
import { OpenInBrowser as LinkIcon } from "@mui/icons-material";
import { Chip } from "@mui/material";
import { TruncateWrapper } from "../utils";
import { GridRenderCellParams } from "@mui/x-data-grid";

const icon = <LinkIcon />;

export const NodesCell = ({ filterText, ...props }: GridRenderCellParams & { filterText: string }): JSX.Element => {
    const {
        value,
        row: { id },
    } = props;
    const filterSegments = useMemo(() => filterText?.toString().trim().split(/\s/) || [], [filterText]);

    const countMatches = useCallback(
        (node: string) => filterSegments.filter((segment) => node.toString().includes(segment)).length,
        [filterSegments],
    );

    const sorted = useMemo(() => value.map((node) => [countMatches(node), node]).sort(([a], [b]) => b - a), [countMatches, value]);

    const elements = sorted.map(([match, node]) => (
        <NodeChip key={node} icon={icon} node={node} filterText={filterText} rowId={id} matched={filterText ? match : -1} />
    ));
    return <TruncateWrapper {...props}>{elements}</TruncateWrapper>;
};

const NodeChip = memo(function NodeChip({
    rowId,
    node,
    filterText,
    matched,
    icon,
}: {
    rowId: string;
    node: string;
    filterText: string;
    matched: number;
    icon: React.ReactElement;
}) {
    return (
        <Chip
            size="small"
            component={ExternalLink}
            href={nodeHref(rowId, node)}
            target="_blank"
            rel="noopener"
            tabIndex={0}
            label={matched > 0 ? <Highlight value={node} filterText={filterText} /> : node}<commit_msg>Open usage link in same window (#3020)<commit_after>import { ExternalLink, Highlight, nodeHref } from "../../common";
import React, { memo, useCallback, useMemo } from "react";
import { OpenInBrowser as LinkIcon } from "@mui/icons-material";
import { Chip } from "@mui/material";
import { TruncateWrapper } from "../utils";
import { GridRenderCellParams } from "@mui/x-data-grid";

const icon = <LinkIcon />;

export const NodesCell = ({ filterText, ...props }: GridRenderCellParams & { filterText: string }): JSX.Element => {
    const {
        value,
        row: { id },
    } = props;
    const filterSegments = useMemo(() => filterText?.toString().trim().split(/\s/) || [], [filterText]);

    const countMatches = useCallback(
        (node: string) => filterSegments.filter((segment) => node.toString().includes(segment)).length,
        [filterSegments],
    );

    const sorted = useMemo(() => value.map((node) => [countMatches(node), node]).sort(([a], [b]) => b - a), [countMatches, value]);

    const elements = sorted.map(([match, node]) => (
        <NodeChip key={node} icon={icon} node={node} filterText={filterText} rowId={id} matched={filterText ? match : -1} />
    ));
    return <TruncateWrapper {...props}>{elements}</TruncateWrapper>;
};

const NodeChip = memo(function NodeChip({
    rowId,
    node,
    filterText,
    matched,
    icon,
}: {
    rowId: string;
    node: string;
    filterText: string;
    matched: number;
    icon: React.ReactElement;
}) {
    return (
        <Chip
            size="small"
            component={ExternalLink}
            href={nodeHref(rowId, node)}
            tabIndex={0}
            label={matched > 0 ? <Highlight value={node} filterText={filterText} /> : node}
{'fraction_non_alphanumeric': 0.16952544311034878, 'fraction_numerical': 0.002858776443682104, 'mean_word_length': 3.0733410942956927, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 31, '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': '6890353', 'n_tokens_mistral': 1073, 'n_tokens_neox': 1048, 'n_words': 247}