Allow new lines in HighlightedText with /n and preserve whitespace (#5046)

* allow new lines in highlighted text with /n

* add changeset

* preserve white spaces in text

* add changeset

* add changeset

* add highlighted text stories

* add changeset

* fix broken story

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Hannah 2023-07-31 16:54:29 +02:00 committed by GitHub
parent 620e464527
commit 5244c5873c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 53 deletions

View File

@ -0,0 +1,7 @@
---
"@gradio/app": minor
"@gradio/highlighted-text": minor
"gradio": minor
---
feat:Allow new lines in `HighlightedText` with `/n` and preserve whitespace

View File

@ -0,0 +1,31 @@
<script>
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
import HighlightedText from "./HighlightedText.svelte";
</script>
<Meta title="Components/HighlightedText" component={HighlightedText} />
<Template let:args>
<HighlightedText
value={[
["zebras", "+"],
["dogs", "-"],
["elephants", "+"],
]}
{...args}
/>
</Template>
<Story name="Highlighted Text" />
<Story name="Highlighted Text with legend" args={{ show_legend: true }} />
<Story name="Highlighted Text with label" args={{ label: "animals" }} />
<Story
name="Highlighted Text with new lines"
args={{
value: [["zebras", "+"], ["\n"], ["dogs", "-"], ["\n"], ["elephants", "+"]],
}}
/>
<Story
name="Highlighted Text with color map"
args={{ color_map: { "+": "green", "-": "red" } }}
/>

View File

@ -6,18 +6,18 @@
import StatusTracker from "../StatusTracker/StatusTracker.svelte";
import type { LoadingStatus } from "../StatusTracker/types";
export let elem_id: string = "";
export let elem_classes: Array<string> = [];
export let visible: boolean = true;
export let value: Array<[string, string | number]>;
let old_value: Array<[string, string | number]>;
export let elem_id = "";
export let elem_classes: string[] = [];
export let visible = true;
export let value: [string, string | number][];
let old_value: [string, string | number][];
export let show_legend: boolean;
export let color_map: Record<string, string> = {};
export let label: string = "Highlighted Text";
export let container: boolean = true;
export let label = "Highlighted Text";
export let container = true;
export let scale: number | null = null;
export let min_width: number | undefined = undefined;
export let selectable: boolean = false;
export let selectable = false;
$: if (!color_map && Object.keys(color_map).length) {
color_map = color_map;

View File

@ -5,17 +5,37 @@
import type { SelectData } from "@gradio/utils";
import { createEventDispatcher } from "svelte";
export let value: Array<[string, string | number]> = [];
export let show_legend: boolean = false;
export let value: [string, string | number][] = [];
export let show_legend = false;
export let color_map: Record<string, string> = {};
export let selectable: boolean = false;
export let selectable = false;
let ctx: CanvasRenderingContext2D;
let _color_map: Record<string, { primary: string; secondary: string }> = {};
let active = "";
function name_to_rgba(name: string, a: number) {
function splitTextByNewline(text: string): string[] {
return text.split("\n");
}
function correct_color_map(): void {
for (const col in color_map) {
const _c = color_map[col].trim();
if (_c in colors) {
_color_map[col] = colors[_c as keyof typeof colors];
} else {
_color_map[col] = {
primary: browser ? name_to_rgba(color_map[col], 1) : color_map[col],
secondary: browser
? name_to_rgba(color_map[col], 0.5)
: color_map[col],
};
}
}
}
function name_to_rgba(name: string, a: number): string {
if (!ctx) {
var canvas = document.createElement("canvas");
ctx = canvas.getContext("2d")!;
@ -52,29 +72,14 @@
}
}
}
function correct_color_map() {
for (const col in color_map) {
const _c = color_map[col].trim();
if (_c in colors) {
_color_map[col] = colors[_c as keyof typeof colors];
} else {
_color_map[col] = {
primary: browser ? name_to_rgba(color_map[col], 1) : color_map[col],
secondary: browser
? name_to_rgba(color_map[col], 0.5)
: color_map[col]
};
}
}
}
correct_color_map();
}
function handle_mouseover(label: string) {
function handle_mouseover(label: string): void {
active = label;
}
function handle_mouseout() {
function handle_mouseout(): void {
active = "";
}
</script>
@ -114,37 +119,46 @@
{/if}
<div class="textfield">
{#each value as [text, category], i}
<span
class="textspan"
style:background-color={category === null ||
(active && active !== category)
? ""
: _color_map[category].secondary}
class:no-cat={category === null || (active && active !== category)}
class:hl={category !== null}
class:selectable
on:click={() => {
dispatch("select", {
index: i,
value: [text, category]
});
}}
>
<span class:no-label={!_color_map[category]} class="text">{text}</span
>
{#if !show_legend && category !== null}
&nbsp;
{#each splitTextByNewline(text) as line, j}
{#if line.trim() !== ""}
<span
class="label"
class="textspan"
style:background-color={category === null ||
(active && active !== category)
? ""
: _color_map[category].primary}
: _color_map[category].secondary}
class:no-cat={category === null ||
(active && active !== category)}
class:hl={category !== null}
class:selectable
on:click={() => {
dispatch("select", {
index: i,
value: [text, category],
});
}}
>
{category}
<span class:no-label={!_color_map[category]} class="text"
>{line}</span
>
{#if !show_legend && category !== null}
&nbsp;
<span
class="label"
style:background-color={category === null ||
(active && active !== category)
? ""
: _color_map[category].primary}
>
{category}
</span>
{/if}
</span>
{/if}
</span>
{#if j < splitTextByNewline(text).length - 1}
<br />
{/if}
{/each}
{/each}
</div>
{:else}
@ -250,6 +264,7 @@
.text {
color: black;
white-space: pre-wrap;
}
.score-text .text {