gradio/js/highlightedtext/interactive/LabelInput.svelte
Hannah d112e2611b
Allow interactive input in gr.HighlightedText (#5400)
* add preprocess param to highlighted_text.py

* add params

* static tweaks

* add interactive highlight container

* highlight selection logic

* allow editing label value and move shared funcs

* add changeset

* remove py code

* wait for input render

* remove redundant event listeners

* accessibility enhancements and remove label logic

* add keyboard navigation and interaction

* merge adjacent empty elements and split input element

* add interactive support for scores mode

* remove merge adjacent logic and move to frontend

* tweak

* add changeset

* format backend

* tweaks

* backend test tweaks

* set the interactive default to None

* BE tweak

* unit tests and stories

* be formatting

* fix label errors

* tweak

* fix tests

* fix tests

* fix test

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
2023-09-12 18:47:16 -07:00

121 lines
2.8 KiB
Svelte

<script lang="ts">
type HighlightedTextType = [string, string | number | null, symbol?];
export let value: HighlightedTextType[];
export let category: string | number | null;
export let active: string;
export let labelToEdit: number;
export let indexOfLabel: number;
export let text: string;
export let handleValueChange: () => void;
export let isScoresMode = false;
export let _color_map: Record<string, { primary: string; secondary: string }>;
let _input_value = category;
function handleInput(e: Event): void {
let target = e.target as HTMLInputElement;
if (target) {
_input_value = target.value;
}
}
function updateLabelValue(
e: Event,
elementIndex: number,
text: string
): void {
let target = e.target as HTMLInputElement;
value = [
...value.slice(0, elementIndex),
[
text,
target.value === ""
? null
: isScoresMode
? Number(target.value)
: target.value,
],
...value.slice(elementIndex + 1),
];
handleValueChange();
}
function clearPlaceHolderOnFocus(e: FocusEvent): void {
let target = e.target as HTMLInputElement;
if (target && target.placeholder) target.placeholder = "";
}
</script>
<!-- svelte-ignore a11y-autofocus -->
<!-- autofocus should not be disorienting for a screen reader users
as input is only rendered once a new label is created -->
{#if !isScoresMode}
<input
class="label-input"
autofocus
id={`label-input-${indexOfLabel}`}
type="text"
placeholder="label"
value={category}
style:background-color={category === null || (active && active !== category)
? ""
: _color_map[category].primary}
style:width={_input_value
? _input_value.toString()?.length + 4 + "ch"
: "8ch"}
on:input={handleInput}
on:blur={(e) => updateLabelValue(e, indexOfLabel, text)}
on:keydown={(e) => {
if (e.key === "Enter") {
updateLabelValue(e, indexOfLabel, text);
labelToEdit = -1;
}
}}
on:focus={clearPlaceHolderOnFocus}
/>
{:else}
<input
class="label-input"
autofocus
type="number"
step="0.1"
style={"background-color: rgba(" +
(typeof category === "number" && category < 0
? "128, 90, 213," + -category
: "239, 68, 60," + category) +
")"}
value={category}
style:width="7ch"
on:input={handleInput}
on:blur={(e) => updateLabelValue(e, indexOfLabel, text)}
on:keydown={(e) => {
if (e.key === "Enter") {
updateLabelValue(e, indexOfLabel, text);
labelToEdit = -1;
}
}}
/>
{/if}
<style>
.label-input {
transition: 150ms;
margin-top: 1px;
margin-right: calc(var(--size-1));
border-radius: var(--radius-xs);
padding: 1px 5px;
color: black;
font-weight: var(--weight-bold);
font-size: var(--text-sm);
text-transform: uppercase;
line-height: 1;
color: white;
}
.label-input::placeholder {
color: rgba(1, 1, 1, 0.5);
}
</style>