diff --git a/web/blueprint/src/lib/components/datasetView/SpanHover.ts b/web/blueprint/src/lib/components/datasetView/SpanHover.ts index 298cd5ba5..31bba8fa1 100644 --- a/web/blueprint/src/lib/components/datasetView/SpanHover.ts +++ b/web/blueprint/src/lib/components/datasetView/SpanHover.ts @@ -4,7 +4,7 @@ import SpanHoverTooltip, {type SpanHoverNamedValue} from './SpanHoverTooltip.sve export interface SpanHoverInfo { namedValues: SpanHoverNamedValue[]; - spansHovered: string[]; + spansHovered: Set; isHovered: boolean; itemScrollContainer: HTMLDivElement | null; } @@ -12,19 +12,15 @@ export function spanHover(element: HTMLSpanElement, spanHoverInfo: SpanHoverInfo let tooltipComponent: SvelteComponent | undefined; let curSpanHoverInfo = spanHoverInfo; const itemScrollListener = () => destroyHoverElement(); - showSpan(); + if (curSpanHoverInfo.isHovered) { + showSpan(); + } function showSpan() { - if (!curSpanHoverInfo.isHovered) { - return; - } - curSpanHoverInfo.namedValues = spanHoverInfo.namedValues.filter(namedValue => - curSpanHoverInfo.spansHovered.some(path => + const namedValues = curSpanHoverInfo.namedValues.filter(namedValue => + Array.from(curSpanHoverInfo.spansHovered).some(path => pathIsMatching(deserializePath(namedValue.spanPath), deserializePath(path)) ) ); - if (curSpanHoverInfo.namedValues.length === 0) { - return; - } if (curSpanHoverInfo.itemScrollContainer != null) { curSpanHoverInfo.itemScrollContainer.addEventListener('scroll', itemScrollListener); } @@ -39,7 +35,7 @@ export function spanHover(element: HTMLSpanElement, spanHoverInfo: SpanHoverInfo tooltipComponent = new SpanHoverTooltip({ props: { - namedValues: curSpanHoverInfo.namedValues, + namedValues, x, y: boundingRect.top }, @@ -59,12 +55,11 @@ export function spanHover(element: HTMLSpanElement, spanHoverInfo: SpanHoverInfo update(spanHoverInfo: SpanHoverInfo) { curSpanHoverInfo = spanHoverInfo; - if (!spanHoverInfo.isHovered) { + if (!curSpanHoverInfo.isHovered) { destroyHoverElement(); } else { showSpan(); } - tooltipComponent?.$set({namedValues: curSpanHoverInfo.namedValues}); }, destroy() { destroyHoverElement(); diff --git a/web/blueprint/src/lib/components/datasetView/StringSpanHighlight.svelte b/web/blueprint/src/lib/components/datasetView/StringSpanHighlight.svelte index 4b0e99c8a..a6b31d3e3 100644 --- a/web/blueprint/src/lib/components/datasetView/StringSpanHighlight.svelte +++ b/web/blueprint/src/lib/components/datasetView/StringSpanHighlight.svelte @@ -429,7 +429,7 @@ use:spanHover={{ namedValues: renderSpan.hoverInfo, isHovered: renderSpan.isFirstHover, - spansHovered: Array.from(pathsHovered), + spansHovered: pathsHovered, itemScrollContainer: $itemScrollContainer }} use:spanClick={{ diff --git a/web/blueprint/src/lib/view_utils.ts b/web/blueprint/src/lib/view_utils.ts index 97d3e0dad..8813a9e5a 100644 --- a/web/blueprint/src/lib/view_utils.ts +++ b/web/blueprint/src/lib/view_utils.ts @@ -218,11 +218,11 @@ export interface MergedSpan { } // Split a merged span up into smaller chunks to help with snippeting. -function splitMergedSpan(mergedSpan: MergedSpan): MergedSpan[] { +function chunkText(text: string): MergedSpan[] { const splitBy = '\n'; - const splits = mergedSpan.text.split(splitBy); + const splits = text.split(splitBy); const splitSpans: MergedSpan[] = []; - let lastEnd = mergedSpan.span?.start || 0; + let lastEnd = 0; for (let i = 0; i < splits.length; i++) { const text = splits[i] + (i < splits.length - 1 ? splitBy : ''); const end = lastEnd + text.length; @@ -230,8 +230,8 @@ function splitMergedSpan(mergedSpan: MergedSpan): MergedSpan[] { splitSpans.push({ text, span, - originalSpans: mergedSpan.originalSpans, - paths: mergedSpan.paths + originalSpans: {}, + paths: [] }); lastEnd = end; } @@ -260,6 +260,9 @@ export function mergeSpans( inputSpanSets: {[spanSet: string]: LilacValueNodeCasted<'string_span'>[]} ): MergedSpan[] { const spanSetKeys = Object.keys(inputSpanSets); + if (spanSetKeys.length === 0) { + return chunkText(text); + } const textLength = text.length; // Maps a span set to the index of the spans we're currently processing for each span set. @@ -329,14 +332,12 @@ export function mergeSpans( .map(span => L.path(span as LilacValueNode)) .map(path => serializePath(path!)); - mergedSpans.push( - ...splitMergedSpan({ - text: text.slice(curStartIdx, curEndIndex), - span: {start: curStartIdx, end: curEndIndex}, - originalSpans: spansInRange, - paths - }) - ); + mergedSpans.push({ + text: text.slice(curStartIdx, curEndIndex), + span: {start: curStartIdx, end: curEndIndex}, + originalSpans: spansInRange, + paths + }); // Advance the spans that have the span end index. for (const spanSet of Object.keys(spanSetIndices)) { @@ -364,14 +365,12 @@ export function mergeSpans( // If the text has more characters than spans, emit a final empty span. if (curStartIdx < text.length) { - mergedSpans.push( - ...splitMergedSpan({ - text: text.slice(curStartIdx, text.length), - span: {start: curStartIdx, end: text.length}, - originalSpans: {}, - paths: [] - }) - ); + mergedSpans.push({ + text: text.slice(curStartIdx, text.length), + span: {start: curStartIdx, end: text.length}, + originalSpans: {}, + paths: [] + }); } return mergedSpans;