@gradio/gallery 0.17.6 → 0.17.8

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @gradio/gallery
2
2
 
3
+ ## 0.17.8
4
+
5
+ ### Fixes
6
+
7
+ - [#13335](https://github.com/gradio-app/gradio/pull/13335) [`953efe0`](https://github.com/gradio-app/gradio/commit/953efe06fa6d0742a9dd899b846d45fbc6ea3ccf) - Prevent Gallery Select Event From Triggering When Value Updated Programmatically. Thanks @freddyaboulton!
8
+
9
+ ## 0.17.7
10
+
11
+ ### Dependency updates
12
+
13
+ - @gradio/atoms@0.24.0
14
+ - @gradio/statustracker@0.14.1
15
+ - @gradio/upload@0.17.9
16
+ - @gradio/file@0.14.8
17
+ - @gradio/image@0.26.3
18
+ - @gradio/video@0.20.8
19
+
3
20
  ## 0.17.6
4
21
 
5
22
  ### Features
package/Gallery.test.ts CHANGED
@@ -627,7 +627,7 @@ describe("Events: select", () => {
627
627
  expect(select).toHaveBeenCalledWith(expect.objectContaining({ index: 1 }));
628
628
  });
629
629
 
630
- test("select: fired when selected_index changes via set_data", async () => {
630
+ test("select: not fired when selected_index changes via set_data", async () => {
631
631
  const { listen, set_data } = await render(Gallery, {
632
632
  ...default_props,
633
633
  preview: true,
@@ -639,8 +639,25 @@ describe("Events: select", () => {
639
639
 
640
640
  await set_data({ selected_index: 2 });
641
641
 
642
- expect(select).toHaveBeenCalled();
643
- expect(select).toHaveBeenCalledWith(expect.objectContaining({ index: 2 }));
642
+ expect(select).not.toHaveBeenCalled();
643
+ });
644
+
645
+ test("select: not fired when value and selected_index update together via set_data", async () => {
646
+ const { listen, set_data } = await render(Gallery, {
647
+ ...default_props,
648
+ preview: true,
649
+ selected_index: 0,
650
+ value: [img("a"), img("b")]
651
+ });
652
+
653
+ const select = listen("select");
654
+
655
+ await set_data({
656
+ value: [img("a"), img("b"), img("c")],
657
+ selected_index: 2
658
+ });
659
+
660
+ expect(select).not.toHaveBeenCalled();
644
661
  });
645
662
  });
646
663
 
@@ -976,7 +993,7 @@ describe("Regression: #13170 — selected_index points to newly appended image",
976
993
  expect(preview_img.src).toBe("https://example.com/img3.png");
977
994
  });
978
995
 
979
- test("selected_index pointing to newly appended item dispatches select with correct data", async () => {
996
+ test("selected_index pointing to newly appended item does not dispatch select", async () => {
980
997
  const initial_value = [img("a"), img("b")];
981
998
 
982
999
  const { set_data, listen } = await render(Gallery, {
@@ -993,9 +1010,7 @@ describe("Regression: #13170 — selected_index points to newly appended image",
993
1010
  selected_index: 2
994
1011
  });
995
1012
 
996
- expect(select).toHaveBeenCalled();
997
- const last_call = select.mock.calls[select.mock.calls.length - 1][0];
998
- expect(last_call.index).toBe(2);
1013
+ expect(select).not.toHaveBeenCalled();
999
1014
  });
1000
1015
 
1001
1016
  test("rapidly appending images with selected_index tracking last always shows the latest", async () => {
@@ -160,7 +160,6 @@
160
160
  if (selected_index == null && preview && value?.length) {
161
161
  selected_index = 0;
162
162
  }
163
- let old_selected_index: number | null = $state(selected_index);
164
163
 
165
164
  $effect(() => {
166
165
  if (!dequal(prev_value, value)) {
@@ -195,6 +194,15 @@
195
194
  () => ((selected_index ?? 0) + 1) % (resolved_value?.length ?? 0)
196
195
  );
197
196
 
197
+ function dispatch_select(index: number): void {
198
+ if (resolved_value !== null) {
199
+ onselect({
200
+ index,
201
+ value: resolved_value?.[index]
202
+ });
203
+ }
204
+ }
205
+
198
206
  function handle_preview_click(event: MouseEvent): void {
199
207
  const element = event.target as HTMLElement;
200
208
  const x = event.offsetX;
@@ -206,6 +214,7 @@
206
214
  } else {
207
215
  selected_index = next;
208
216
  }
217
+ dispatch_select(selected_index);
209
218
  }
210
219
 
211
220
  function on_keydown(e: KeyboardEvent): void {
@@ -218,32 +227,18 @@
218
227
  case "ArrowLeft":
219
228
  e.preventDefault();
220
229
  selected_index = previous;
230
+ dispatch_select(selected_index);
221
231
  break;
222
232
  case "ArrowRight":
223
233
  e.preventDefault();
224
234
  selected_index = next;
235
+ dispatch_select(selected_index);
225
236
  break;
226
237
  default:
227
238
  break;
228
239
  }
229
240
  }
230
241
 
231
- $effect(() => {
232
- // Only trigger the effect if the selected_index has actually changed
233
- if (selected_index !== old_selected_index) {
234
- old_selected_index = selected_index;
235
-
236
- // Ensure we have a valid selection and data to work with
237
- if (selected_index !== null && resolved_value !== null) {
238
- // Notify the parent component or listener about the updated selection
239
- onselect({
240
- index: selected_index,
241
- value: resolved_value?.[selected_index]
242
- });
243
- }
244
- }
245
- });
246
-
247
242
  $effect(() => {
248
243
  if (allow_preview && container_element) {
249
244
  scroll_to_img(selected_index);
@@ -495,7 +490,10 @@
495
490
  {#each resolved_value as media, i}
496
491
  <button
497
492
  bind:this={el[i]}
498
- on:click={() => (selected_index = i)}
493
+ on:click={() => {
494
+ selected_index = i;
495
+ dispatch_select(i);
496
+ }}
499
497
  class="thumbnail-item thumbnail-small"
500
498
  class:selected={selected_index === i && mode !== "minimal"}
501
499
  aria-label={"Thumbnail " +
@@ -616,6 +614,7 @@
616
614
  onpreview_open();
617
615
  }
618
616
  selected_index = i;
617
+ dispatch_select(i);
619
618
  }}
620
619
  aria-label={"Thumbnail " +
621
620
  (i + 1) +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradio/gallery",
3
- "version": "0.17.6",
3
+ "version": "0.17.8",
4
4
  "description": "Gradio UI packages",
5
5
  "type": "module",
6
6
  "author": "",
@@ -8,15 +8,15 @@
8
8
  "private": false,
9
9
  "dependencies": {
10
10
  "dequal": "^2.0.3",
11
- "@gradio/atoms": "^0.23.1",
12
- "@gradio/file": "^0.14.7",
13
- "@gradio/icons": "^0.15.1",
11
+ "@gradio/atoms": "^0.24.0",
12
+ "@gradio/file": "^0.14.8",
14
13
  "@gradio/client": "^2.2.0",
15
- "@gradio/upload": "^0.17.8",
14
+ "@gradio/icons": "^0.15.1",
15
+ "@gradio/image": "^0.26.3",
16
+ "@gradio/statustracker": "^0.14.1",
16
17
  "@gradio/utils": "^0.12.2",
17
- "@gradio/video": "^0.20.7",
18
- "@gradio/statustracker": "^0.14.0",
19
- "@gradio/image": "^0.26.2"
18
+ "@gradio/upload": "^0.17.9",
19
+ "@gradio/video": "^0.20.8"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@gradio/preview": "^0.16.2"
@@ -160,7 +160,6 @@
160
160
  if (selected_index == null && preview && value?.length) {
161
161
  selected_index = 0;
162
162
  }
163
- let old_selected_index: number | null = $state(selected_index);
164
163
 
165
164
  $effect(() => {
166
165
  if (!dequal(prev_value, value)) {
@@ -195,6 +194,15 @@
195
194
  () => ((selected_index ?? 0) + 1) % (resolved_value?.length ?? 0)
196
195
  );
197
196
 
197
+ function dispatch_select(index: number): void {
198
+ if (resolved_value !== null) {
199
+ onselect({
200
+ index,
201
+ value: resolved_value?.[index]
202
+ });
203
+ }
204
+ }
205
+
198
206
  function handle_preview_click(event: MouseEvent): void {
199
207
  const element = event.target as HTMLElement;
200
208
  const x = event.offsetX;
@@ -206,6 +214,7 @@
206
214
  } else {
207
215
  selected_index = next;
208
216
  }
217
+ dispatch_select(selected_index);
209
218
  }
210
219
 
211
220
  function on_keydown(e: KeyboardEvent): void {
@@ -218,32 +227,18 @@
218
227
  case "ArrowLeft":
219
228
  e.preventDefault();
220
229
  selected_index = previous;
230
+ dispatch_select(selected_index);
221
231
  break;
222
232
  case "ArrowRight":
223
233
  e.preventDefault();
224
234
  selected_index = next;
235
+ dispatch_select(selected_index);
225
236
  break;
226
237
  default:
227
238
  break;
228
239
  }
229
240
  }
230
241
 
231
- $effect(() => {
232
- // Only trigger the effect if the selected_index has actually changed
233
- if (selected_index !== old_selected_index) {
234
- old_selected_index = selected_index;
235
-
236
- // Ensure we have a valid selection and data to work with
237
- if (selected_index !== null && resolved_value !== null) {
238
- // Notify the parent component or listener about the updated selection
239
- onselect({
240
- index: selected_index,
241
- value: resolved_value?.[selected_index]
242
- });
243
- }
244
- }
245
- });
246
-
247
242
  $effect(() => {
248
243
  if (allow_preview && container_element) {
249
244
  scroll_to_img(selected_index);
@@ -495,7 +490,10 @@
495
490
  {#each resolved_value as media, i}
496
491
  <button
497
492
  bind:this={el[i]}
498
- on:click={() => (selected_index = i)}
493
+ on:click={() => {
494
+ selected_index = i;
495
+ dispatch_select(i);
496
+ }}
499
497
  class="thumbnail-item thumbnail-small"
500
498
  class:selected={selected_index === i && mode !== "minimal"}
501
499
  aria-label={"Thumbnail " +
@@ -616,6 +614,7 @@
616
614
  onpreview_open();
617
615
  }
618
616
  selected_index = i;
617
+ dispatch_select(i);
619
618
  }}
620
619
  aria-label={"Thumbnail " +
621
620
  (i + 1) +