gradio/frontend
1442k
1<script lang="ts">2 import EditableCell from "./EditableCell.svelte";3 import CellMenuButton from "./CellMenuButton.svelte";4 import type { I18nFormatter } from "js/core/src/gradio_helper";5 import type { Datatype } from "./utils/utils";6 import type { CellValue } from "./types";7 import { is_cell_in_selection } from "./utils/selection_utils";8 9 export let value: CellValue;10 export let index: number;11 export let j: number;12 export let actual_pinned_columns: number;13 export let get_cell_width: (index: number) => string;14 export let handle_cell_click: (15 event: MouseEvent,16 row: number,17 col: number18 ) => void;19 export let handle_blur: (20 event: CustomEvent<{21 blur_event: FocusEvent;22 coords: [number, number];23 }>24 ) => void;25 export let toggle_cell_menu: (26 event: MouseEvent,27 row: number,28 col: number29 ) => void;30 export let is_cell_selected: (31 coords: [number, number],32 selected_cells: [number, number][]33 ) => string;34 export let should_show_cell_menu: (35 coords: [number, number],36 selected_cells: [number, number][],37 editable: boolean38 ) => boolean;39 export let selected_cells: [number, number][];40 export let copy_flash: boolean;41 export let active_cell_menu: {42 row: number;43 col: number;44 x: number;45 y: number;46 } | null;47 export let styling: string | undefined;48 export let latex_delimiters: {49 left: string;50 right: string;51 display: boolean;52 }[];53 export let line_breaks: boolean;54 export let datatype: Datatype;55 export let editing: [number, number] | false;56 export let max_chars: number | undefined;57 export let editable: boolean;58 export let is_static = false;59 export let i18n: I18nFormatter;60 export let components: Record<string, any> = {};61 export let el: {62 cell: HTMLTableCellElement | null;63 input: HTMLTextAreaElement | null;64 };65 export let handle_select_column: (col: number) => void;66 export let handle_select_row: (row: number) => void;67 export let is_dragging: boolean;68 export let display_value: string | undefined;69 export let wrap = false;70 71 function get_cell_position(col_index: number): string {72 if (col_index >= actual_pinned_columns) {73 return "auto";74 }75 76 if (col_index === 0) {77 return "0";78 }79 80 const previous_widths = Array(col_index)81 .fill(0)82 .map((_, idx) => {83 return get_cell_width(idx);84 })85 .join(" + ");86 87 return `calc(${previous_widths})`;88 }89 90 $: cell_classes = is_cell_selected([index, j], selected_cells || []);91 $: is_in_selection = is_cell_in_selection([index, j], selected_cells);92 $: has_no_top = cell_classes.includes("no-top");93 $: has_no_bottom = cell_classes.includes("no-bottom");94 $: has_no_left = cell_classes.includes("no-left");95 $: has_no_right = cell_classes.includes("no-right");96</script>97 98<td99 class:pinned-column={j < actual_pinned_columns}100 class:last-pinned={j === actual_pinned_columns - 1}101 tabindex={j < actual_pinned_columns ? -1 : 0}102 bind:this={el.cell}103 data-row={index}104 data-col={j}105 data-testid={`cell-${index}-${j}`}106 on:mousedown={(e) => handle_cell_click(e, index, j)}107 on:contextmenu|preventDefault={(e) => toggle_cell_menu(e, index, j)}108 style="width: {get_cell_width(j)}; left: {get_cell_position(j)}; {styling ||109 ''}"110 class:flash={copy_flash && is_in_selection}111 class:cell-selected={is_in_selection}112 class:no-top={has_no_top}113 class:no-bottom={has_no_bottom}114 class:no-left={has_no_left}115 class:no-right={has_no_right}116 class:menu-active={active_cell_menu &&117 active_cell_menu.row === index &&118 active_cell_menu.col === j}119 class:dragging={is_dragging}120>121 <div class="cell-wrap">122 <EditableCell123 bind:value124 bind:el={el.input}125 display_value={display_value !== undefined126 ? display_value127 : String(value)}128 {latex_delimiters}129 {line_breaks}130 {editable}131 {is_static}132 edit={editing && editing[0] === index && editing[1] === j}133 {datatype}134 on:focus={() => {135 const row = index;136 const col = j;137 if (!selected_cells.some(([r, c]) => r === row && c === col)) {138 selected_cells = [[row, col]];139 }140 }}141 on:blur={handle_blur}142 {max_chars}143 {i18n}144 {components}145 show_selection_buttons={selected_cells.length === 1 &&146 selected_cells[0][0] === index &&147 selected_cells[0][1] === j}148 coords={[index, j]}149 on_select_column={handle_select_column}150 on_select_row={handle_select_row}151 {is_dragging}152 wrap_text={wrap}153 />154 {#if editable && should_show_cell_menu([index, j], selected_cells, editable)}155 <CellMenuButton on_click={(event) => toggle_cell_menu(event, index, j)} />156 {/if}157 </div>158</td>159 160<style>161 td {162 --ring-color: transparent;163 position: relative;164 outline: none;165 box-shadow: inset 0 0 0 1px var(--ring-color);166 padding: 0;167 border-right-width: 0px;168 border-left-width: 1px;169 border-style: solid;170 border-color: var(--border-color-primary);171 }172 173 .cell-wrap {174 display: flex;175 align-items: center;176 justify-content: flex-start;177 outline: none;178 min-height: var(--size-9);179 position: relative;180 height: 100%;181 padding: var(--size-2);182 box-sizing: border-box;183 margin: 0;184 gap: var(--size-1);185 overflow: visible;186 min-width: 0;187 border-radius: var(--table-radius);188 }189 190 .cell-selected {191 --ring-color: var(--color-accent);192 box-shadow: inset 0 0 0 2px var(--ring-color);193 z-index: 2;194 position: relative;195 }196 197 .cell-selected :global(.cell-menu-button) {198 display: flex;199 }200 201 .flash.cell-selected {202 animation: flash-color 700ms ease-out;203 }204 205 @keyframes flash-color {206 0%,207 30% {208 background: var(--color-accent-copied);209 }210 211 100% {212 background: transparent;213 }214 }215 216 .pinned-column {217 position: sticky;218 z-index: 3;219 border-right: none;220 }221 222 .pinned-column:nth-child(odd) {223 background: var(--table-odd-background-fill);224 }225 226 .pinned-column:nth-child(even) {227 background: var(--table-even-background-fill);228 }229 230 td:first-child {231 border-left-width: 0px;232 }233 234 :global(tr:last-child) td:first-child {235 border-bottom-left-radius: var(--table-radius);236 }237 238 :global(tr:last-child) td:last-child {239 border-bottom-right-radius: var(--table-radius);240 }241 242 .dragging {243 cursor: crosshair;244 }245 246 /* Add back the cell selection border styles */247 .cell-selected.no-top {248 box-shadow:249 inset 2px 0 0 var(--ring-color),250 inset -2px 0 0 var(--ring-color),251 inset 0 -2px 0 var(--ring-color);252 }253 254 .cell-selected.no-bottom {255 box-shadow:256 inset 2px 0 0 var(--ring-color),257 inset -2px 0 0 var(--ring-color),258 inset 0 2px 0 var(--ring-color);259 }260 261 .cell-selected.no-left {262 box-shadow:263 inset 0 2px 0 var(--ring-color),264 inset -2px 0 0 var(--ring-color),265 inset 0 -2px 0 var(--ring-color);266 }267 268 .cell-selected.no-right {269 box-shadow:270 inset 0 2px 0 var(--ring-color),271 inset 2px 0 0 var(--ring-color),272 inset 0 -2px 0 var(--ring-color);273 }274 275 .cell-selected.no-top.no-left {276 box-shadow:277 inset -2px 0 0 var(--ring-color),278 inset 0 -2px 0 var(--ring-color);279 }280 281 .cell-selected.no-top.no-right {282 box-shadow:283 inset 2px 0 0 var(--ring-color),284 inset 0 -2px 0 var(--ring-color);285 }286 287 .cell-selected.no-bottom.no-left {288 box-shadow:289 inset -2px 0 0 var(--ring-color),290 inset 0 2px 0 var(--ring-color);291 }292 293 .cell-selected.no-bottom.no-right {294 box-shadow:295 inset 2px 0 0 var(--ring-color),296 inset 0 2px 0 var(--ring-color);297 }298 299 .cell-selected.no-top.no-bottom {300 box-shadow:301 inset 2px 0 0 var(--ring-color),302 inset -2px 0 0 var(--ring-color);303 }304 305 .cell-selected.no-left.no-right {306 box-shadow:307 inset 0 2px 0 var(--ring-color),308 inset 0 -2px 0 var(--ring-color);309 }310 311 .cell-selected.no-top.no-left.no-right {312 box-shadow: inset 0 -2px 0 var(--ring-color);313 }314 315 .cell-selected.no-bottom.no-left.no-right {316 box-shadow: inset 0 2px 0 var(--ring-color);317 }318 319 .cell-selected.no-left.no-top.no-bottom {320 box-shadow: inset -2px 0 0 var(--ring-color);321 }322 323 .cell-selected.no-right.no-top.no-bottom {324 box-shadow: inset 2px 0 0 var(--ring-color);325 }326 327 .cell-selected.no-top.no-bottom.no-left.no-right {328 box-shadow: none;329 }330</style>331 