@gradio/dataframe 0.23.0 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,13 +21,15 @@
21
21
  i18n,
22
22
  is_dragging = false,
23
23
  wrap_text = false,
24
+ expanded = false,
24
25
  show_selection_buttons = false,
25
26
  coords,
26
27
  on_select_column = null,
27
28
  on_select_row = null,
28
29
  el = $bindable(null),
29
30
  onblur,
30
- onkeydown
31
+ onkeydown,
32
+ pad_left = false
31
33
  }: {
32
34
  edit: boolean;
33
35
  value?: CellValue;
@@ -55,6 +57,7 @@
55
57
  i18n: I18nFormatter;
56
58
  is_dragging?: boolean;
57
59
  wrap_text?: boolean;
60
+ expanded?: boolean;
58
61
  show_selection_buttons?: boolean;
59
62
  coords: [number, number];
60
63
  on_select_column?: ((col: number) => void) | null;
@@ -65,6 +68,7 @@
65
68
  coords: [number, number];
66
69
  }) => void;
67
70
  onkeydown?: (event: KeyboardEvent) => void;
71
+ pad_left: boolean;
68
72
  } = $props();
69
73
 
70
74
  function truncate_text(
@@ -79,7 +83,9 @@
79
83
  return str.slice(0, max_length) + "...";
80
84
  }
81
85
 
82
- let should_truncate = $derived(!edit && max_chars !== null && max_chars > 0);
86
+ let should_truncate = $derived(
87
+ !edit && !expanded && max_chars !== null && max_chars > 0
88
+ );
83
89
 
84
90
  let display_content = $derived(
85
91
  editable ? value : display_value !== null ? display_value : value
@@ -99,6 +105,22 @@
99
105
  return {};
100
106
  }
101
107
 
108
+ // grow the edit-mode textarea to fit its content so the overlay
109
+ // expands the same way the display span does.
110
+ function use_autosize(node: HTMLTextAreaElement): any {
111
+ function resize(): void {
112
+ node.style.height = "auto";
113
+ node.style.height = `${node.scrollHeight}px`;
114
+ }
115
+ node.addEventListener("input", resize);
116
+ requestAnimationFrame(resize);
117
+ return {
118
+ destroy() {
119
+ node.removeEventListener("input", resize);
120
+ }
121
+ };
122
+ }
123
+
102
124
  function handle_blur(event: FocusEvent): void {
103
125
  onblur?.({
104
126
  blur_event: event,
@@ -114,10 +136,12 @@
114
136
  handle_blur({ target: { value } } as unknown as FocusEvent);
115
137
  }
116
138
 
139
+ // returning cleanup from the effect fires the blur only when leaving edit mode, not on every render
117
140
  $effect(() => {
118
- if (!edit) {
119
- // Shim blur on removal for Safari and Firefox
120
- handle_blur({ target: { value } } as unknown as FocusEvent);
141
+ if (edit) {
142
+ return () => {
143
+ handle_blur({ target: { value } } as unknown as FocusEvent);
144
+ };
121
145
  }
122
146
  });
123
147
  </script>
@@ -135,7 +159,9 @@
135
159
  onmousedown={(e: MouseEvent) => e.stopPropagation()}
136
160
  onclick={(e: MouseEvent) => e.stopPropagation()}
137
161
  use:use_focus
162
+ use:use_autosize
138
163
  onkeydown={handle_keydown}
164
+ class:pad_left
139
165
  />
140
166
  {/if}
141
167
 
@@ -149,7 +175,7 @@
149
175
  role="button"
150
176
  class:edit
151
177
  class:expanded={edit}
152
- class:multiline={header}
178
+ class:header
153
179
  onfocus={(e) => e.preventDefault()}
154
180
  style={styling}
155
181
  data-editable={editable}
@@ -205,7 +231,7 @@
205
231
  textarea {
206
232
  position: absolute;
207
233
  flex: 1 1 0%;
208
- transform: translateX(-0.1px);
234
+ transform: translate(0.2px, -0.5px);
209
235
  outline: none;
210
236
  border: none;
211
237
  background: transparent;
@@ -217,24 +243,33 @@
217
243
  font-size: inherit;
218
244
  font-weight: inherit;
219
245
  line-height: var(--line-lg);
246
+ left: var(--size-2);
247
+ user-select: text;
220
248
  }
221
249
 
222
250
  textarea:focus {
223
251
  outline: none;
224
252
  }
225
253
 
254
+ textarea.pad_left {
255
+ margin-left: var(--size-7);
256
+ }
257
+
226
258
  span {
227
259
  flex: 1 1 0%;
228
260
  position: relative;
229
261
  display: block;
230
262
  outline: none;
231
- -webkit-user-select: text;
232
- -moz-user-select: text;
233
- -ms-user-select: text;
234
- user-select: text;
235
263
  cursor: text;
236
264
  width: 100%;
237
- overflow-wrap: break-word;
265
+ min-width: 0;
266
+ white-space: nowrap;
267
+ overflow: hidden;
268
+ text-overflow: ellipsis;
269
+ }
270
+
271
+ .header {
272
+ font-weight: var(--weight-bold);
238
273
  }
239
274
 
240
275
  span.text.expanded {
@@ -245,21 +280,6 @@
245
280
  overflow: visible;
246
281
  }
247
282
 
248
- .multiline {
249
- white-space: pre;
250
- overflow: hidden;
251
- text-overflow: ellipsis;
252
- }
253
-
254
- .header {
255
- transform: translateX(0);
256
- font-weight: var(--weight-bold);
257
- white-space: nowrap;
258
- overflow: hidden;
259
- text-overflow: ellipsis;
260
- margin-left: var(--size-1);
261
- }
262
-
263
283
  .edit {
264
284
  opacity: 0;
265
285
  pointer-events: none;
@@ -267,6 +287,8 @@
267
287
 
268
288
  span :global(img) {
269
289
  max-height: 100px;
290
+ max-width: 100%;
291
+ height: auto;
270
292
  width: auto;
271
293
  object-fit: contain;
272
294
  }
@@ -278,8 +300,9 @@
278
300
  .wrap,
279
301
  .wrap.expanded {
280
302
  white-space: normal;
281
- word-wrap: break-word;
303
+ overflow: visible;
304
+ text-overflow: clip;
282
305
  overflow-wrap: break-word;
283
- word-wrap: break-word;
306
+ word-break: break-word;
284
307
  }
285
308
  </style>
@@ -20,6 +20,7 @@ type $$ComponentProps = {
20
20
  i18n: I18nFormatter;
21
21
  is_dragging?: boolean;
22
22
  wrap_text?: boolean;
23
+ expanded?: boolean;
23
24
  show_selection_buttons?: boolean;
24
25
  coords: [number, number];
25
26
  on_select_column?: ((col: number) => void) | null;
@@ -30,6 +31,7 @@ type $$ComponentProps = {
30
31
  coords: [number, number];
31
32
  }) => void;
32
33
  onkeydown?: (event: KeyboardEvent) => void;
34
+ pad_left: boolean;
33
35
  };
34
36
  declare const EditableCell: import("svelte").Component<$$ComponentProps, {}, "value" | "el">;
35
37
  type EditableCell = ReturnType<typeof EditableCell>;
@@ -5,6 +5,7 @@
5
5
  import FilterIcon from "./icons/FilterIcon.svelte";
6
6
  import SortButtonUp from "./icons/SortButtonUp.svelte";
7
7
  import SortButtonDown from "./icons/SortButtonDown.svelte";
8
+ import { BaseCheckbox } from "@gradio/checkbox";
8
9
  import type { I18nFormatter } from "js/core/src/gradio_helper";
9
10
  import type { SortDirection } from "./types";
10
11
 
@@ -14,6 +15,8 @@
14
15
  is_editing = false,
15
16
  is_selected = false,
16
17
  is_static = false,
18
+ is_bool = false,
19
+ select_all_state = "unchecked",
17
20
  sort_direction = null,
18
21
  sort_priority = null,
19
22
  multi_sort = false,
@@ -25,15 +28,19 @@
25
28
  editable = true,
26
29
  max_chars = undefined,
27
30
  i18n,
31
+ wrap_text = false,
28
32
  onclick,
29
33
  on_menu_click,
30
- on_end_edit
34
+ on_end_edit,
35
+ on_select_all
31
36
  }: {
32
37
  value: string;
33
38
  col_idx: number;
34
39
  is_editing?: boolean;
35
40
  is_selected?: boolean;
36
41
  is_static?: boolean;
42
+ is_bool?: boolean;
43
+ select_all_state?: "checked" | "unchecked" | "indeterminate";
37
44
  sort_direction?: SortDirection | null;
38
45
  sort_priority?: number | null;
39
46
  multi_sort?: boolean;
@@ -45,10 +52,16 @@
45
52
  editable?: boolean;
46
53
  max_chars?: number | undefined;
47
54
  i18n: I18nFormatter;
55
+ wrap_text?: boolean;
48
56
  onclick: (event: MouseEvent, col: number) => void;
49
57
  on_menu_click: (event: MouseEvent, col: number) => void;
50
58
  on_end_edit: (key: string) => void;
59
+ on_select_all?: (col: number, checked: boolean) => void;
51
60
  } = $props();
61
+
62
+ let show_select_all = $derived(
63
+ is_bool && editable && !is_static && !!on_select_all
64
+ );
52
65
  </script>
53
66
 
54
67
  <th
@@ -57,6 +70,7 @@
57
70
  class:sorted={sort_direction !== null}
58
71
  class:filtered={is_filtered}
59
72
  class:first-column={is_first_column}
73
+ data-heading={col_idx}
60
74
  onclick={(e) => onclick(e, col_idx)}
61
75
  onmousedown={(e) => {
62
76
  e.preventDefault();
@@ -66,6 +80,25 @@
66
80
  >
67
81
  <div class="cell-wrap">
68
82
  <div class="header-content">
83
+ {#if show_select_all}
84
+ <div
85
+ class="select-all-checkbox"
86
+ role="button"
87
+ tabindex="-1"
88
+ onclick={(e) => e.stopPropagation()}
89
+ onmousedown={(e) => e.stopPropagation()}
90
+ onkeydown={(e) => e.stopPropagation()}
91
+ >
92
+ <BaseCheckbox
93
+ value={select_all_state === "checked"}
94
+ indeterminate={select_all_state === "indeterminate"}
95
+ label={`Toggle all: ${value}`}
96
+ interactive={true}
97
+ on_select={() =>
98
+ on_select_all?.(col_idx, select_all_state !== "checked")}
99
+ />
100
+ </div>
101
+ {/if}
69
102
  <EditableCell
70
103
  {value}
71
104
  {latex_delimiters}
@@ -81,7 +114,9 @@
81
114
  {is_static}
82
115
  {i18n}
83
116
  {max_chars}
117
+ {wrap_text}
84
118
  coords={[col_idx, 0]}
119
+ pad_left={show_select_all ? true : false}
85
120
  />
86
121
  </div>
87
122
  {#if sort_direction || is_filtered || is_static}
@@ -129,6 +164,13 @@
129
164
  padding: 0;
130
165
  background: var(--table-even-background-fill) !important;
131
166
  font-weight: var(--weight-bold, 700);
167
+ outline: none;
168
+ box-shadow:
169
+ inset 1px 0 0 var(--border-color-primary),
170
+ inset 0 0 0 1px var(--ring-color);
171
+ padding: 0;
172
+ overflow: visible;
173
+ box-sizing: border-box;
132
174
  }
133
175
 
134
176
  .header-cell.first-column {
@@ -142,10 +184,14 @@
142
184
 
143
185
  .header-cell.focus {
144
186
  --ring-color: var(--color-accent);
187
+ --sel-top: inset 0 2px 0 0 var(--ring-color);
188
+ --sel-bottom: inset 0 -2px 0 0 var(--ring-color);
189
+ --sel-left: inset 2px 0 0 0 var(--ring-color);
190
+ --sel-right: inset -2px 0 0 0 var(--ring-color);
145
191
  box-shadow:
146
- inset 1px 0 0 var(--border-color-primary),
147
- inset 0 0 0 2px var(--ring-color);
148
- z-index: 4;
192
+ var(--sel-top), var(--sel-bottom), var(--sel-left), var(--sel-right);
193
+ z-index: 2;
194
+ position: relative;
149
195
  }
150
196
 
151
197
  .header-cell.focus.first-column {
@@ -155,7 +201,7 @@
155
201
  .header-content {
156
202
  display: flex;
157
203
  align-items: center;
158
- gap: var(--size-1);
204
+ gap: var(--size-3);
159
205
  overflow: hidden;
160
206
  min-width: 0;
161
207
  }
@@ -215,4 +261,20 @@
215
261
  overflow: visible;
216
262
  min-width: 0;
217
263
  }
264
+
265
+ .select-all-checkbox {
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ flex-shrink: 0;
270
+ width: var(--size-4);
271
+ }
272
+
273
+ .select-all-checkbox :global(label) {
274
+ margin: 0;
275
+ }
276
+
277
+ .select-all-checkbox :global(span) {
278
+ display: none;
279
+ }
218
280
  </style>
@@ -6,6 +6,8 @@ type $$ComponentProps = {
6
6
  is_editing?: boolean;
7
7
  is_selected?: boolean;
8
8
  is_static?: boolean;
9
+ is_bool?: boolean;
10
+ select_all_state?: "checked" | "unchecked" | "indeterminate";
9
11
  sort_direction?: SortDirection | null;
10
12
  sort_priority?: number | null;
11
13
  multi_sort?: boolean;
@@ -21,9 +23,11 @@ type $$ComponentProps = {
21
23
  editable?: boolean;
22
24
  max_chars?: number | undefined;
23
25
  i18n: I18nFormatter;
26
+ wrap_text?: boolean;
24
27
  onclick: (event: MouseEvent, col: number) => void;
25
28
  on_menu_click: (event: MouseEvent, col: number) => void;
26
29
  on_end_edit: (key: string) => void;
30
+ on_select_all?: (col: number, checked: boolean) => void;
27
31
  };
28
32
  declare const HeaderCell: import("svelte").Component<$$ComponentProps, {}, "">;
29
33
  type HeaderCell = ReturnType<typeof HeaderCell>;