@gradio/dataframe 0.17.3 → 0.17.5

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/Dataframe.stories.svelte +29 -0
  3. package/dist/shared/CellMenu.svelte.d.ts +1 -1
  4. package/dist/shared/EditableCell.svelte +8 -17
  5. package/dist/shared/EditableCell.svelte.d.ts +5 -3
  6. package/dist/shared/Table.svelte +111 -138
  7. package/dist/shared/TableCell.svelte +4 -6
  8. package/dist/shared/TableCell.svelte.d.ts +5 -1
  9. package/dist/shared/TableHeader.svelte +4 -3
  10. package/dist/shared/TableHeader.svelte.d.ts +1 -2
  11. package/dist/shared/context/dataframe_context.d.ts +147 -0
  12. package/dist/shared/context/dataframe_context.js +335 -0
  13. package/dist/shared/selection_utils.d.ts +1 -2
  14. package/dist/shared/selection_utils.js +0 -13
  15. package/dist/shared/utils/drag_utils.js +1 -0
  16. package/dist/shared/utils/keyboard_utils.d.ts +3 -2
  17. package/dist/shared/utils/keyboard_utils.js +107 -68
  18. package/package.json +7 -7
  19. package/shared/CellMenu.svelte +1 -1
  20. package/shared/EditableCell.svelte +9 -20
  21. package/shared/Table.svelte +147 -165
  22. package/shared/TableCell.svelte +9 -6
  23. package/shared/TableHeader.svelte +5 -8
  24. package/shared/context/dataframe_context.ts +576 -0
  25. package/shared/selection_utils.ts +1 -23
  26. package/shared/utils/drag_utils.ts +1 -0
  27. package/shared/utils/keyboard_utils.ts +142 -80
  28. package/{shared/utils → test}/sort_utils.test.ts +5 -1
  29. package/{shared/utils → test}/table_utils.test.ts +2 -2
  30. package/dist/shared/context/keyboard_context.d.ts +0 -37
  31. package/dist/shared/context/keyboard_context.js +0 -12
  32. package/dist/shared/context/selection_context.d.ts +0 -32
  33. package/dist/shared/context/selection_context.js +0 -107
  34. package/dist/shared/context/table_context.d.ts +0 -141
  35. package/dist/shared/context/table_context.js +0 -375
  36. package/shared/context/keyboard_context.ts +0 -65
  37. package/shared/context/selection_context.ts +0 -168
  38. package/shared/context/table_context.ts +0 -625
@@ -1,141 +0,0 @@
1
- import type { Writable } from "svelte/store";
2
- import type { DataframeValue } from "../utils";
3
- export declare const DATAFRAME_KEY: unique symbol;
4
- export type SortDirection = "asc" | "desc";
5
- export type DataFrameState = {
6
- config: {
7
- show_fullscreen_button: boolean;
8
- show_copy_button: boolean;
9
- show_search: "none" | "search" | "filter";
10
- show_row_numbers: boolean;
11
- editable: boolean;
12
- pinned_columns: number;
13
- show_label: boolean;
14
- line_breaks: boolean;
15
- wrap: boolean;
16
- max_height: number;
17
- column_widths: string[];
18
- max_chars: number | undefined;
19
- };
20
- current_search_query: string | null;
21
- sort_state: {
22
- sort_columns: {
23
- col: number;
24
- direction: SortDirection;
25
- }[];
26
- row_order: number[];
27
- };
28
- ui_state: {
29
- active_cell_menu: {
30
- row: number;
31
- col: number;
32
- x: number;
33
- y: number;
34
- } | null;
35
- active_header_menu: {
36
- col: number;
37
- x: number;
38
- y: number;
39
- } | null;
40
- selected_cells: [number, number][];
41
- selected: [number, number] | false;
42
- editing: [number, number] | false;
43
- header_edit: number | false;
44
- selected_header: number | false;
45
- active_button: {
46
- type: "header" | "cell";
47
- row?: number;
48
- col: number;
49
- } | null;
50
- };
51
- };
52
- export interface DataFrameContext {
53
- state: Writable<DataFrameState>;
54
- actions: {
55
- handle_search: (search_query: string | null) => void;
56
- handle_sort: (col: number, direction: SortDirection) => void;
57
- get_sort_status: (name: string, headers: string[]) => "none" | "asc" | "desc";
58
- sort_data: (data: any[][], display_value: string[][] | null, styling: string[][] | null) => void;
59
- update_row_order: (data: any[][]) => void;
60
- filter_data: (data: any[][]) => any[][];
61
- add_row: (data: any[][], make_id: () => string, index?: number) => any[][];
62
- add_col: (data: any[][], headers: string[], make_id: () => string, index?: number) => {
63
- data: any[][];
64
- headers: string[];
65
- };
66
- add_row_at: (data: any[][], index: number, position: "above" | "below", make_id: () => string) => any[][];
67
- add_col_at: (data: any[][], headers: string[], index: number, position: "left" | "right", make_id: () => string) => {
68
- data: any[][];
69
- headers: string[];
70
- };
71
- delete_row: (data: any[][], index: number) => any[][];
72
- delete_col: (data: any[][], headers: string[], index: number) => {
73
- data: any[][];
74
- headers: string[];
75
- };
76
- delete_row_at: (data: any[][], index: number) => any[][];
77
- delete_col_at: (data: any[][], headers: string[], index: number) => {
78
- data: any[][];
79
- headers: string[];
80
- };
81
- set_active_cell_menu: (menu: {
82
- row: number;
83
- col: number;
84
- x: number;
85
- y: number;
86
- } | null) => void;
87
- set_active_header_menu: (menu: {
88
- col: number;
89
- x: number;
90
- y: number;
91
- } | null) => void;
92
- set_selected_cells: (cells: [number, number][]) => void;
93
- set_selected: (selected: [number, number] | false) => void;
94
- set_editing: (editing: [number, number] | false) => void;
95
- clear_ui_state: () => void;
96
- set_header_edit: (header_index: number | false) => void;
97
- set_selected_header: (header_index: number | false) => void;
98
- handle_header_click: (col: number, editable: boolean) => void;
99
- end_header_edit: (key: string) => void;
100
- trigger_change: (data: any[][], headers: any[], previous_data: string[][], previous_headers: string[], value_is_output: boolean, dispatch: {
101
- (e: "change", detail: DataframeValue): void;
102
- (e: "input", detail?: undefined): void;
103
- (e: "select", detail: any): void;
104
- (e: "search", detail: string | null): void;
105
- }) => Promise<void>;
106
- get_selected_cells: () => [number, number][];
107
- get_active_cell_menu: () => {
108
- row: number;
109
- col: number;
110
- x: number;
111
- y: number;
112
- } | null;
113
- get_active_button: () => {
114
- type: "header" | "cell";
115
- row?: number;
116
- col: number;
117
- } | null;
118
- set_active_button: (button: {
119
- type: "header" | "cell";
120
- row?: number;
121
- col: number;
122
- } | null) => void;
123
- reset_sort_state: () => void;
124
- };
125
- }
126
- export declare function create_actions(state: Writable<DataFrameState>): DataFrameContext["actions"];
127
- export declare function create_dataframe_context(config: {
128
- show_fullscreen_button: boolean;
129
- show_copy_button: boolean;
130
- show_search: "none" | "search" | "filter";
131
- show_row_numbers: boolean;
132
- editable: boolean;
133
- pinned_columns: number;
134
- show_label: boolean;
135
- line_breaks: boolean;
136
- wrap: boolean;
137
- max_height: number;
138
- column_widths: string[];
139
- max_chars: number | undefined;
140
- }): DataFrameContext;
141
- export declare function get_dataframe_context(): DataFrameContext;
@@ -1,375 +0,0 @@
1
- import { getContext, setContext } from "svelte";
2
- import { writable, get } from "svelte/store";
3
- import { sort_table_data } from "../utils/table_utils";
4
- import { dequal } from "dequal/lite";
5
- export const DATAFRAME_KEY = Symbol("dataframe");
6
- export function create_actions(state) {
7
- const add_row = (data, make_id, index) => {
8
- if (!data || data.length === 0) {
9
- return [[{ value: "", id: make_id() }]];
10
- }
11
- const new_row = Array(data[0].length)
12
- .fill(null)
13
- .map(() => ({
14
- value: "",
15
- id: make_id()
16
- }));
17
- const new_data = [...data];
18
- if (typeof index === "number" && index >= 0 && index <= data.length) {
19
- new_data.splice(index, 0, new_row);
20
- }
21
- else {
22
- new_data.push(new_row);
23
- }
24
- return new_data;
25
- };
26
- const add_col = (data, headers, make_id, index) => {
27
- if (!data || data.length === 0) {
28
- return {
29
- data: [[{ value: "", id: make_id() }]],
30
- headers: ["Header 1"]
31
- };
32
- }
33
- const new_headers = [...headers];
34
- const new_data = data.map((row) => [...row]);
35
- if (typeof index === "number" &&
36
- index >= 0 &&
37
- index <= (data[0]?.length || 0)) {
38
- new_headers.splice(index, 0, `Header ${headers.length + 1}`);
39
- new_data.forEach((row) => {
40
- const id = make_id();
41
- row.splice(index, 0, { value: "", id });
42
- });
43
- }
44
- else {
45
- new_headers.push(`Header ${headers.length + 1}`);
46
- new_data.forEach((row) => {
47
- const id = make_id();
48
- row.push({ value: "", id });
49
- });
50
- }
51
- return { data: new_data, headers: new_headers };
52
- };
53
- const reset_sort_state = () => {
54
- state.update((s) => ({
55
- ...s,
56
- sort_state: {
57
- sort_columns: [],
58
- row_order: []
59
- }
60
- }));
61
- };
62
- return {
63
- handle_search: (search_query) => {
64
- state.update((s) => ({ ...s, current_search_query: search_query }));
65
- },
66
- handle_sort: (col, direction) => {
67
- state.update((s) => {
68
- const sort_columns = [...s.sort_state.sort_columns];
69
- const existing_index = sort_columns.findIndex((item) => item.col === col);
70
- if (existing_index !== -1) {
71
- const existing_item = sort_columns[existing_index];
72
- if (existing_item.direction === direction) {
73
- sort_columns.splice(existing_index, 1);
74
- }
75
- else {
76
- sort_columns[existing_index] = { col, direction };
77
- }
78
- }
79
- else {
80
- if (sort_columns.length >= 3) {
81
- sort_columns.shift();
82
- }
83
- sort_columns.push({ col, direction });
84
- }
85
- return {
86
- ...s,
87
- sort_state: {
88
- ...s.sort_state,
89
- sort_columns
90
- }
91
- };
92
- });
93
- },
94
- get_sort_status: (name, headers) => {
95
- const current_state = get(state);
96
- const sort_item = current_state.sort_state.sort_columns.find((item) => headers[item.col] === name);
97
- if (!sort_item)
98
- return "none";
99
- return sort_item.direction;
100
- },
101
- sort_data: (data, display_value, styling) => {
102
- const current_state = get(state);
103
- if (current_state.sort_state.sort_columns.length > 0) {
104
- sort_table_data(data, display_value, styling, current_state.sort_state.sort_columns);
105
- }
106
- },
107
- update_row_order: (data) => {
108
- state.update((s) => {
109
- const current_sort_state = { ...s.sort_state };
110
- if (current_sort_state.sort_columns.length > 0 && data[0]) {
111
- const indices = [...Array(data.length)].map((_, i) => i);
112
- indices.sort((a, b) => {
113
- const row_a = data[a];
114
- const row_b = data[b];
115
- for (const { col: sort_index, direction } of current_sort_state.sort_columns) {
116
- if (!row_a ||
117
- !row_b ||
118
- sort_index < 0 ||
119
- sort_index >= row_a.length ||
120
- sort_index >= row_b.length) {
121
- continue;
122
- }
123
- const val_a = row_a[sort_index].value;
124
- const val_b = row_b[sort_index].value;
125
- const comp = val_a < val_b ? -1 : val_a > val_b ? 1 : 0;
126
- if (comp !== 0) {
127
- return direction === "asc" ? comp : -comp;
128
- }
129
- }
130
- return 0;
131
- });
132
- current_sort_state.row_order = indices;
133
- }
134
- else {
135
- current_sort_state.row_order = [...Array(data.length)].map((_, i) => i);
136
- }
137
- return { ...s, sort_state: current_sort_state };
138
- });
139
- },
140
- filter_data: (data) => {
141
- const current_state = get(state);
142
- if (!current_state.current_search_query) {
143
- return data;
144
- }
145
- const search_query = current_state.current_search_query.toLowerCase();
146
- const filtered = data.filter((row) => {
147
- return row.some((cell) => {
148
- if (!cell) {
149
- return false;
150
- }
151
- const cell_value = cell.value;
152
- if (cell_value === null || cell_value === undefined) {
153
- return false;
154
- }
155
- const string_value = String(cell_value).toLowerCase();
156
- return string_value.includes(search_query);
157
- });
158
- });
159
- return filtered;
160
- },
161
- add_row,
162
- add_col,
163
- add_row_at: (data, index, position, make_id) => {
164
- const row_index = position === "above" ? index : index + 1;
165
- return add_row(data, make_id, row_index);
166
- },
167
- add_col_at: (data, headers, index, position, make_id) => {
168
- const col_index = position === "left" ? index : index + 1;
169
- return add_col(data, headers, make_id, col_index);
170
- },
171
- delete_row: (data, index) => {
172
- if (data.length <= 1) {
173
- return data;
174
- }
175
- const new_data = [...data];
176
- new_data.splice(index, 1);
177
- return new_data;
178
- },
179
- delete_col: (data, headers, index) => {
180
- if (headers.length <= 1) {
181
- return { data, headers };
182
- }
183
- const new_headers = [...headers];
184
- new_headers.splice(index, 1);
185
- const new_data = data.map((row) => {
186
- const new_row = [...row];
187
- new_row.splice(index, 1);
188
- return new_row;
189
- });
190
- return { data: new_data, headers: new_headers };
191
- },
192
- delete_row_at: (data, index) => {
193
- if (data.length <= 1)
194
- return data;
195
- data.splice(index, 1);
196
- return data;
197
- },
198
- delete_col_at: (data, headers, index) => {
199
- if (headers.length <= 1) {
200
- return { data, headers };
201
- }
202
- const new_headers = [...headers];
203
- new_headers.splice(index, 1);
204
- const new_data = data.map((row) => {
205
- const new_row = [...row];
206
- new_row.splice(index, 1);
207
- return new_row;
208
- });
209
- return { data: new_data, headers: new_headers };
210
- },
211
- set_active_cell_menu: (menu) => {
212
- state.update((s) => ({
213
- ...s,
214
- ui_state: { ...s.ui_state, active_cell_menu: menu }
215
- }));
216
- },
217
- set_active_header_menu: (menu) => {
218
- state.update((s) => ({
219
- ...s,
220
- ui_state: { ...s.ui_state, active_header_menu: menu }
221
- }));
222
- },
223
- set_selected_cells: (cells) => {
224
- state.update((s) => ({
225
- ...s,
226
- ui_state: { ...s.ui_state, selected_cells: cells }
227
- }));
228
- },
229
- set_selected: (selected) => {
230
- state.update((s) => ({
231
- ...s,
232
- ui_state: { ...s.ui_state, selected: selected }
233
- }));
234
- },
235
- set_editing: (editing) => {
236
- state.update((s) => ({
237
- ...s,
238
- ui_state: { ...s.ui_state, editing: editing }
239
- }));
240
- },
241
- clear_ui_state: () => {
242
- state.update((s) => ({
243
- ...s,
244
- ui_state: {
245
- active_cell_menu: null,
246
- active_header_menu: null,
247
- selected_cells: [],
248
- selected: false,
249
- editing: false,
250
- header_edit: false,
251
- selected_header: false,
252
- active_button: null
253
- }
254
- }));
255
- },
256
- set_header_edit: (header_index) => {
257
- state.update((s) => ({
258
- ...s,
259
- ui_state: {
260
- ...s.ui_state,
261
- selected_cells: [],
262
- selected_header: header_index,
263
- header_edit: header_index
264
- }
265
- }));
266
- },
267
- set_selected_header: (header_index) => {
268
- state.update((s) => ({
269
- ...s,
270
- ui_state: {
271
- ...s.ui_state,
272
- selected_header: header_index,
273
- selected: false,
274
- selected_cells: []
275
- }
276
- }));
277
- },
278
- handle_header_click: (col, editable) => {
279
- state.update((s) => ({
280
- ...s,
281
- ui_state: {
282
- ...s.ui_state,
283
- active_cell_menu: null,
284
- active_header_menu: null,
285
- selected: false,
286
- selected_cells: [],
287
- selected_header: col,
288
- header_edit: editable ? col : false
289
- }
290
- }));
291
- },
292
- end_header_edit: (key) => {
293
- if (key === "Escape" || key === "Enter" || key === "Tab") {
294
- state.update((s) => ({
295
- ...s,
296
- ui_state: {
297
- ...s.ui_state,
298
- selected: false,
299
- header_edit: false
300
- }
301
- }));
302
- }
303
- },
304
- trigger_change: async (data, headers, previous_data, previous_headers, value_is_output, dispatch) => {
305
- const current_state = get(state);
306
- if (current_state.current_search_query)
307
- return;
308
- const current_headers = headers.map((h) => h.value);
309
- const current_data = data.map((row) => row.map((cell) => String(cell.value)));
310
- if (!dequal(current_data, previous_data) ||
311
- !dequal(current_headers, previous_headers)) {
312
- if (!dequal(current_headers, previous_headers)) {
313
- reset_sort_state();
314
- }
315
- dispatch("change", {
316
- data: data.map((row) => row.map((cell) => cell.value)),
317
- headers: headers.map((h) => h.value),
318
- metadata: null
319
- });
320
- if (!value_is_output) {
321
- dispatch("input");
322
- }
323
- }
324
- },
325
- get_selected_cells: () => {
326
- const current_state = get(state);
327
- return current_state.ui_state.selected_cells;
328
- },
329
- get_active_cell_menu: () => {
330
- const current_state = get(state);
331
- return current_state.ui_state.active_cell_menu;
332
- },
333
- get_active_button: () => {
334
- const current_state = get(state);
335
- return current_state.ui_state.active_button;
336
- },
337
- set_active_button: (button) => {
338
- state.update((s) => ({
339
- ...s,
340
- ui_state: { ...s.ui_state, active_button: button }
341
- }));
342
- },
343
- reset_sort_state
344
- };
345
- }
346
- export function create_dataframe_context(config) {
347
- const instance_id = Symbol(`dataframe_${Math.random().toString(36).substring(2)}`);
348
- const state = writable({
349
- config,
350
- current_search_query: null,
351
- sort_state: {
352
- sort_columns: [],
353
- row_order: []
354
- },
355
- ui_state: {
356
- active_cell_menu: null,
357
- active_header_menu: null,
358
- selected_cells: [],
359
- selected: false,
360
- editing: false,
361
- header_edit: false,
362
- selected_header: false,
363
- active_button: null
364
- }
365
- });
366
- const actions = create_actions(state);
367
- const context = { state, actions };
368
- setContext(instance_id, context);
369
- setContext(DATAFRAME_KEY, { instance_id, context });
370
- return context;
371
- }
372
- export function get_dataframe_context() {
373
- const ctx = getContext(DATAFRAME_KEY);
374
- return ctx ? ctx.context : getContext(DATAFRAME_KEY);
375
- }
@@ -1,65 +0,0 @@
1
- import { getContext, setContext } from "svelte";
2
- import type { DataFrameContext } from "./table_context";
3
- import type { CellData } from "../selection_utils";
4
- import type { DataframeValue } from "../utils";
5
- import type { CellCoordinate } from "../types";
6
-
7
- const KEYBOARD_KEY = Symbol("keyboard");
8
-
9
- export type KeyboardContext = {
10
- selected_header: number | false;
11
- header_edit: number | false;
12
- editing: [number, number] | false;
13
- selected: [number, number] | false;
14
- selected_cells: [number, number][];
15
- editable: boolean;
16
- data: CellData[][];
17
- headers: { id: string; value: string }[];
18
- els: Record<
19
- string,
20
- { cell: null | HTMLTableCellElement; input: null | HTMLInputElement }
21
- >;
22
- df_actions: DataFrameContext["actions"];
23
- dispatch: {
24
- (e: "change", detail: DataframeValue): void;
25
- (e: "input", detail?: undefined): void;
26
- (e: "select", detail: any): void;
27
- (e: "search", detail: string | null): void;
28
- };
29
- add_row: (index?: number) => Promise<void>;
30
- get_next_cell_coordinates: (
31
- current: CellCoordinate,
32
- data: CellData[][],
33
- shift_key: boolean
34
- ) => false | CellCoordinate;
35
- get_range_selection: (
36
- start: CellCoordinate,
37
- end: CellCoordinate
38
- ) => CellCoordinate[];
39
- move_cursor: (
40
- event: KeyboardEvent,
41
- current_coords: CellCoordinate,
42
- data: CellData[][]
43
- ) => false | CellCoordinate;
44
- copy_flash: boolean;
45
- set_copy_flash: (value: boolean) => void;
46
- parent_element?: HTMLDivElement;
47
- };
48
-
49
- export function create_keyboard_context(
50
- context: KeyboardContext
51
- ): KeyboardContext {
52
- const instance_id = Symbol(
53
- `keyboard_${Math.random().toString(36).substring(2)}`
54
- );
55
- setContext(instance_id, context);
56
- setContext(KEYBOARD_KEY, { instance_id, context });
57
- return context;
58
- }
59
-
60
- export function get_keyboard_context(): KeyboardContext | undefined {
61
- const ctx = getContext<{ instance_id: symbol; context: KeyboardContext }>(
62
- KEYBOARD_KEY
63
- );
64
- return ctx ? ctx.context : getContext<KeyboardContext>(KEYBOARD_KEY);
65
- }