CoolFace
Datasetpublic

gradio/frontend

sourceHugging Faceupdated 4h agoView on Hugging Face
1likes413kdownloads
EditableCell.svelte262 linesDownload Raw Back to shared
1<script lang="ts">2	import { createEventDispatcher } from "svelte";3	import { MarkdownCode } from "@gradio/markdown-code";4	import type { I18nFormatter } from "@gradio/utils";5	import type { CellValue } from "./types";6	import SelectionButtons from "./icons/SelectionButtons.svelte";7	import BooleanCell from "./BooleanCell.svelte";8 9	export let edit: boolean;10	export let value: CellValue = "";11	export let display_value: string | null = null;12	export let styling = "";13	export let header = false;14	export let datatype:15		| "str"16		| "markdown"17		| "html"18		| "number"19		| "bool"20		| "date"21		| "image" = "str";22	export let latex_delimiters: {23		left: string;24		right: string;25		display: boolean;26	}[];27	export let line_breaks = true;28	export let editable = true;29	export let is_static = false;30	export let max_chars: number | null = null;31	export let components: Record<string, any> = {};32	export let i18n: I18nFormatter;33	export let is_dragging = false;34	export let wrap_text = false;35 36	export let show_selection_buttons = false;37	export let coords: [number, number];38	export let on_select_column: ((col: number) => void) | null = null;39	export let on_select_row: ((row: number) => void) | null = null;40	export let el: HTMLTextAreaElement | null;41 42	const dispatch = createEventDispatcher<{43		blur: { blur_event: FocusEvent; coords: [number, number] };44		keydown: KeyboardEvent;45	}>();46 47	function truncate_text(48		text: CellValue,49		max_length: number | null = null,50		is_image = false51	): string {52		if (is_image) return String(text);53		const str = String(text);54		if (!max_length || max_length <= 0) return str;55		if (str.length <= max_length) return str;56		return str.slice(0, max_length) + "...";57	}58 59	$: should_truncate = !edit && max_chars !== null && max_chars > 0;60 61	$: display_content = editable62		? value63		: display_value !== null64			? display_value65			: value;66 67	$: display_text = should_truncate68		? truncate_text(display_content, max_chars, datatype === "image")69		: display_content;70 71	function use_focus(node: HTMLTextAreaElement): any {72		requestAnimationFrame(() => {73			node.focus();74		});75 76		return {};77	}78 79	function handle_blur(event: FocusEvent): void {80		dispatch("blur", {81			blur_event: event,82			coords: coords83		});84	}85 86	function handle_keydown(event: KeyboardEvent): void {87		dispatch("keydown", event);88	}89 90	function commit_change(checked: boolean): void {91		handle_blur({ target: { value } } as unknown as FocusEvent);92	}93 94	$: if (!edit) {95		// Shim blur on removal for Safari and Firefox96		handle_blur({ target: { value } } as unknown as FocusEvent);97	}98</script>99 100{#if edit && datatype !== "bool"}101	<textarea102		readonly={is_static}103		aria-readonly={is_static}104		aria-label={is_static ? "Cell is read-only" : "Edit cell"}105		bind:this={el}106		bind:value107		class:header108		tabindex="-1"109		on:blur={handle_blur}110		on:mousedown|stopPropagation111		on:click|stopPropagation112		use:use_focus113		on:keydown={handle_keydown}114	/>115{/if}116 117{#if datatype === "bool" && typeof value === "boolean"}118	<BooleanCell bind:value {editable} on_change={commit_change} />119{:else}120	<span121		class:dragging={is_dragging}122		on:keydown={handle_keydown}123		tabindex="0"124		role="button"125		class:edit126		class:expanded={edit}127		class:multiline={header}128		on:focus|preventDefault129		style={styling}130		data-editable={editable}131		data-max-chars={max_chars}132		data-expanded={edit}133		placeholder=" "134		class:text={datatype === "str"}135		class:wrap={wrap_text}136	>137		{#if datatype === "image" && components.image}138			<svelte:component139				this={components.image}140				value={{ url: display_text }}141				show_label={false}142				label="cell-image"143				show_download_button={false}144				{i18n}145				gradio={{ dispatch: () => {} }}146			/>147		{:else if datatype === "html"}148			{@html display_text}149		{:else if datatype === "markdown"}150			<MarkdownCode151				message={display_text.toLocaleString()}152				{latex_delimiters}153				{line_breaks}154				chatbot={false}155			/>156		{:else}157			{display_text}158		{/if}159	</span>160{/if}161 162{#if show_selection_buttons && coords && on_select_column && on_select_row}163	<SelectionButtons164		position="column"165		{coords}166		on_click={() => on_select_column(coords[1])}167	/>168	<SelectionButtons169		position="row"170		{coords}171		on_click={() => on_select_row(coords[0])}172	/>173{/if}174 175<style>176	.dragging {177		cursor: crosshair !important;178	}179 180	textarea {181		position: absolute;182		flex: 1 1 0%;183		transform: translateX(-0.1px);184		outline: none;185		border: none;186		background: transparent;187		cursor: text;188		width: calc(100% - var(--size-2));189		resize: none;190		height: 100%;191		padding-left: 0;192		font-size: inherit;193		font-weight: inherit;194		line-height: var(--line-lg);195	}196 197	textarea:focus {198		outline: none;199	}200 201	span {202		flex: 1 1 0%;203		position: relative;204		display: inline-block;205		outline: none;206		-webkit-user-select: text;207		-moz-user-select: text;208		-ms-user-select: text;209		user-select: text;210		cursor: text;211		width: 100%;212		height: 100%;213		overflow: hidden;214	}215 216	span.text.expanded {217		height: auto;218		min-height: 100%;219		white-space: pre-wrap;220		word-break: break-word;221		overflow: visible;222	}223 224	.multiline {225		white-space: pre;226		overflow: hidden;227		text-overflow: ellipsis;228	}229 230	.header {231		transform: translateX(0);232		font-weight: var(--weight-bold);233		white-space: nowrap;234		overflow: hidden;235		text-overflow: ellipsis;236		margin-left: var(--size-1);237	}238 239	.edit {240		opacity: 0;241		pointer-events: none;242	}243 244	span :global(img) {245		max-height: 100px;246		width: auto;247		object-fit: contain;248	}249 250	textarea:read-only {251		cursor: not-allowed;252	}253 254	.wrap,255	.wrap.expanded {256		white-space: normal;257		word-wrap: break-word;258		overflow-wrap: break-word;259		word-wrap: break-word;260	}261</style>262 
gradio/frontend · CoolFace