@gradio/draggable 0.4.0 → 0.5.0
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 +35 -0
- package/Draggable.test.ts +434 -0
- package/Index.svelte +2 -1
- package/WithChildren.svelte +10 -0
- package/WithFormChildren.svelte +12 -0
- package/dist/Index.svelte +2 -1
- package/dist/Index.svelte.d.ts +2 -19
- package/dist/WithChildren.svelte +10 -0
- package/dist/WithChildren.svelte.d.ts +3 -0
- package/dist/WithFormChildren.svelte +12 -0
- package/dist/WithFormChildren.svelte.d.ts +3 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @gradio/draggable
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- [`96a79b1`](https://github.com/gradio-app/gradio/commit/96a79b19c8b4a0634c9ab4a969460c0ad55ddf77) - Refactor the remaining component unit tests and remove components.test.ts. Thanks @abidlabs!
|
|
8
|
+
|
|
9
|
+
### Dependency updates
|
|
10
|
+
|
|
11
|
+
- @gradio/statustracker@0.15.4
|
|
12
|
+
|
|
13
|
+
## 0.4.0
|
|
14
|
+
|
|
15
|
+
### Dependency updates
|
|
16
|
+
|
|
17
|
+
- @gradio/utils@0.14.2
|
|
18
|
+
|
|
19
|
+
## 0.4.0
|
|
20
|
+
|
|
21
|
+
### Dependency updates
|
|
22
|
+
|
|
23
|
+
- @gradio/utils@0.14.1
|
|
24
|
+
|
|
25
|
+
## 0.4.0
|
|
26
|
+
|
|
27
|
+
### Dependency updates
|
|
28
|
+
|
|
29
|
+
- @gradio/utils@0.14.0
|
|
30
|
+
- @gradio/statustracker@0.15.2
|
|
31
|
+
|
|
32
|
+
## 0.4.0
|
|
33
|
+
|
|
34
|
+
### Dependency updates
|
|
35
|
+
|
|
36
|
+
- @gradio/statustracker@0.15.1
|
|
37
|
+
|
|
3
38
|
## 0.4.0
|
|
4
39
|
|
|
5
40
|
### Features
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { test, describe, afterEach, expect } from "vitest";
|
|
2
|
+
import { cleanup, render, fireEvent, waitFor } from "@self/tootils/render";
|
|
3
|
+
|
|
4
|
+
import Draggable from "./Index.svelte";
|
|
5
|
+
import DraggableWithChildren from "./WithChildren.svelte";
|
|
6
|
+
import DraggableWithFormChildren from "./WithFormChildren.svelte";
|
|
7
|
+
|
|
8
|
+
const default_props = {
|
|
9
|
+
orientation: "column" as const,
|
|
10
|
+
show_progress: false,
|
|
11
|
+
visible: true,
|
|
12
|
+
elem_classes: [] as string[]
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function item_order(container: HTMLElement): (string | null)[] {
|
|
16
|
+
return Array.from(container.querySelectorAll("[data-testid^='item-']")).map(
|
|
17
|
+
(el) => el.textContent?.replace("⋮⋮", "").trim() ?? null
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function drag(from: HTMLElement, to: HTMLElement): Promise<void> {
|
|
22
|
+
const handle = from.querySelector("[data-testid='drag-handle']")!;
|
|
23
|
+
await fireEvent.dragStart(handle, { dataTransfer: new DataTransfer() });
|
|
24
|
+
await fireEvent.dragEnter(to, { dataTransfer: new DataTransfer() });
|
|
25
|
+
await fireEvent.drop(to, { dataTransfer: new DataTransfer() });
|
|
26
|
+
await fireEvent.dragEnd(handle, { dataTransfer: new DataTransfer() });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("Draggable", () => {
|
|
30
|
+
afterEach(() => cleanup());
|
|
31
|
+
|
|
32
|
+
test("renders a labelled region for the draggable items", async () => {
|
|
33
|
+
const { getByRole } = await render(Draggable, default_props);
|
|
34
|
+
|
|
35
|
+
expect(
|
|
36
|
+
getByRole("region", { name: "Draggable items container" })
|
|
37
|
+
).toBeVisible();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("renders its children", async () => {
|
|
41
|
+
const { getByTestId } = await render(DraggableWithChildren, default_props);
|
|
42
|
+
|
|
43
|
+
expect(getByTestId("item-a")).toBeVisible();
|
|
44
|
+
expect(getByTestId("item-b")).toBeVisible();
|
|
45
|
+
expect(getByTestId("item-c")).toBeVisible();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("gives every child a drag handle", async () => {
|
|
49
|
+
const { getAllByTestId } = await render(
|
|
50
|
+
DraggableWithChildren,
|
|
51
|
+
default_props
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
await waitFor(() => {
|
|
55
|
+
expect(getAllByTestId("drag-handle")).toHaveLength(3);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("drag handles are draggable and start un-grabbed", async () => {
|
|
60
|
+
const { getAllByTestId } = await render(
|
|
61
|
+
DraggableWithChildren,
|
|
62
|
+
default_props
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
66
|
+
|
|
67
|
+
for (const handle of getAllByTestId("drag-handle")) {
|
|
68
|
+
expect(handle).toHaveAttribute("draggable", "true");
|
|
69
|
+
expect(handle).toHaveAttribute("aria-grabbed", "false");
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("handles are numbered in the order the children appear", async () => {
|
|
74
|
+
const { getAllByTestId } = await render(
|
|
75
|
+
DraggableWithChildren,
|
|
76
|
+
default_props
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
80
|
+
|
|
81
|
+
expect(
|
|
82
|
+
getAllByTestId("drag-handle").map((h) => h.getAttribute("data-index"))
|
|
83
|
+
).toEqual(["0", "1", "2"]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("adds no drag handles when it has no children", async () => {
|
|
87
|
+
const { queryAllByTestId } = await render(Draggable, default_props);
|
|
88
|
+
|
|
89
|
+
expect(queryAllByTestId("drag-handle")).toHaveLength(0);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe("Props: visible", () => {
|
|
94
|
+
afterEach(() => cleanup());
|
|
95
|
+
|
|
96
|
+
test("visible: true shows the container and its children", async () => {
|
|
97
|
+
const { getByRole, getByTestId } = await render(DraggableWithChildren, {
|
|
98
|
+
...default_props,
|
|
99
|
+
visible: true
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
expect(getByRole("region")).toBeVisible();
|
|
103
|
+
expect(getByTestId("item-a")).toBeVisible();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("visible: false hides the container and its children", async () => {
|
|
107
|
+
const { getByRole, getByTestId } = await render(DraggableWithChildren, {
|
|
108
|
+
...default_props,
|
|
109
|
+
visible: false
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
expect(getByRole("region", { hidden: true })).not.toBeVisible();
|
|
113
|
+
expect(getByTestId("item-a")).not.toBeVisible();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("visible: 'hidden' does NOT hide the container (Draggable uses !visible — 'hidden' is truthy)", async () => {
|
|
117
|
+
// Draggable's template uses class:hide={!gradio.shared.visible}. "hidden" is
|
|
118
|
+
// a non-empty string and therefore truthy, so !("hidden") === false and
|
|
119
|
+
// .hide is never applied. This matches Row and the other bare layouts, and
|
|
120
|
+
// differs from components that check === "hidden" explicitly.
|
|
121
|
+
const { getByRole } = await render(DraggableWithChildren, {
|
|
122
|
+
...default_props,
|
|
123
|
+
visible: "hidden"
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
expect(getByRole("region")).toBeVisible();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("Props: elem_id / elem_classes", () => {
|
|
131
|
+
afterEach(() => cleanup());
|
|
132
|
+
|
|
133
|
+
test("elem_id is applied to the container", async () => {
|
|
134
|
+
const { container } = await render(Draggable, {
|
|
135
|
+
...default_props,
|
|
136
|
+
elem_id: "my-draggable"
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
expect(container.querySelector("#my-draggable")).not.toBeNull();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("elem_classes are applied to the container", async () => {
|
|
143
|
+
const { getByRole } = await render(Draggable, {
|
|
144
|
+
...default_props,
|
|
145
|
+
elem_classes: ["my-draggable-class"]
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(getByRole("region")).toHaveClass("my-draggable-class");
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("missing elem_classes still renders the container", async () => {
|
|
152
|
+
const { getByRole } = await render(Draggable, {
|
|
153
|
+
orientation: "column",
|
|
154
|
+
visible: true
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
expect(getByRole("region")).toBeVisible();
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("Props: show_progress", () => {
|
|
162
|
+
afterEach(() => cleanup());
|
|
163
|
+
|
|
164
|
+
test("never renders a status tracker, whatever show_progress is set to", async () => {
|
|
165
|
+
// The template guards the StatusTracker on gradio.props.show_progress, but
|
|
166
|
+
// show_progress is in allowed_shared_props, so it always lands on
|
|
167
|
+
// gradio.shared and gradio.props.show_progress is always undefined. Python's
|
|
168
|
+
// gr.Draggable exposes no show_progress parameter either, so the branch is
|
|
169
|
+
// unreachable in the app as well as here.
|
|
170
|
+
for (const show_progress of [true, false]) {
|
|
171
|
+
const { queryByTestId, unmount } = await render(Draggable, {
|
|
172
|
+
...default_props,
|
|
173
|
+
show_progress
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
expect(queryByTestId("status-tracker")).not.toBeInTheDocument();
|
|
177
|
+
unmount();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe("Drag interactions", () => {
|
|
183
|
+
afterEach(() => cleanup());
|
|
184
|
+
|
|
185
|
+
test("starting a drag marks the handle as grabbed", async () => {
|
|
186
|
+
const { getAllByTestId } = await render(
|
|
187
|
+
DraggableWithChildren,
|
|
188
|
+
default_props
|
|
189
|
+
);
|
|
190
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
191
|
+
|
|
192
|
+
const handle = getAllByTestId("drag-handle")[0];
|
|
193
|
+
await fireEvent.dragStart(handle, { dataTransfer: new DataTransfer() });
|
|
194
|
+
|
|
195
|
+
expect(handle).toHaveAttribute("aria-grabbed", "true");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("ending a drag releases the handle again", async () => {
|
|
199
|
+
const { getAllByTestId } = await render(
|
|
200
|
+
DraggableWithChildren,
|
|
201
|
+
default_props
|
|
202
|
+
);
|
|
203
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
204
|
+
|
|
205
|
+
const handle = getAllByTestId("drag-handle")[0];
|
|
206
|
+
await fireEvent.dragStart(handle, { dataTransfer: new DataTransfer() });
|
|
207
|
+
await fireEvent.dragEnd(handle, { dataTransfer: new DataTransfer() });
|
|
208
|
+
|
|
209
|
+
expect(handle).toHaveAttribute("aria-grabbed", "false");
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("dragging over an item allows the drop", async () => {
|
|
213
|
+
const { getByTestId } = await render(DraggableWithChildren, default_props);
|
|
214
|
+
|
|
215
|
+
const allowed = await fireEvent.dragOver(getByTestId("item-b"), {
|
|
216
|
+
dataTransfer: new DataTransfer()
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// fireEvent resolves false when a handler called preventDefault, which is
|
|
220
|
+
// how the drop target opts in to receiving the drop.
|
|
221
|
+
expect(allowed).toBe(false);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("dropping one item onto another swaps their positions", async () => {
|
|
225
|
+
const { container, getByTestId } = await render(
|
|
226
|
+
DraggableWithChildren,
|
|
227
|
+
default_props
|
|
228
|
+
);
|
|
229
|
+
await waitFor(() =>
|
|
230
|
+
expect(item_order(container)).toEqual(["Item A", "Item B", "Item C"])
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
await drag(getByTestId("item-a"), getByTestId("item-c"));
|
|
234
|
+
|
|
235
|
+
expect(item_order(container)).toEqual(["Item C", "Item B", "Item A"]);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test("swapping adjacent items reorders them", async () => {
|
|
239
|
+
const { container, getByTestId } = await render(
|
|
240
|
+
DraggableWithChildren,
|
|
241
|
+
default_props
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
await drag(getByTestId("item-a"), getByTestId("item-b"));
|
|
245
|
+
|
|
246
|
+
expect(item_order(container)).toEqual(["Item B", "Item A", "Item C"]);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
test("dropping an item onto itself leaves the order unchanged", async () => {
|
|
250
|
+
const { container, getByTestId } = await render(
|
|
251
|
+
DraggableWithChildren,
|
|
252
|
+
default_props
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
await drag(getByTestId("item-b"), getByTestId("item-b"));
|
|
256
|
+
|
|
257
|
+
expect(item_order(container)).toEqual(["Item A", "Item B", "Item C"]);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
test("a drop with no drag in progress leaves the order unchanged", async () => {
|
|
261
|
+
const { container, getByTestId } = await render(
|
|
262
|
+
DraggableWithChildren,
|
|
263
|
+
default_props
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
await fireEvent.drop(getByTestId("item-c"), {
|
|
267
|
+
dataTransfer: new DataTransfer()
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
expect(item_order(container)).toEqual(["Item A", "Item B", "Item C"]);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("handles are renumbered after a swap", async () => {
|
|
274
|
+
const { getByTestId, getAllByTestId } = await render(
|
|
275
|
+
DraggableWithChildren,
|
|
276
|
+
default_props
|
|
277
|
+
);
|
|
278
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
279
|
+
|
|
280
|
+
await drag(getByTestId("item-a"), getByTestId("item-c"));
|
|
281
|
+
|
|
282
|
+
await waitFor(() => {
|
|
283
|
+
expect(
|
|
284
|
+
getAllByTestId("drag-handle").map((h) => h.getAttribute("data-index"))
|
|
285
|
+
).toEqual(["0", "1", "2"]);
|
|
286
|
+
});
|
|
287
|
+
expect(
|
|
288
|
+
getByTestId("item-c").querySelector("[data-testid='drag-handle']")
|
|
289
|
+
).toHaveAttribute("data-index", "0");
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("every item keeps exactly one handle after a swap", async () => {
|
|
293
|
+
const { getByTestId, getAllByTestId } = await render(
|
|
294
|
+
DraggableWithChildren,
|
|
295
|
+
default_props
|
|
296
|
+
);
|
|
297
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
298
|
+
|
|
299
|
+
await drag(getByTestId("item-a"), getByTestId("item-c"));
|
|
300
|
+
|
|
301
|
+
await waitFor(() => {
|
|
302
|
+
expect(getAllByTestId("drag-handle")).toHaveLength(3);
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test("the dropped item is released when the drag completes", async () => {
|
|
307
|
+
const { getByTestId } = await render(DraggableWithChildren, default_props);
|
|
308
|
+
|
|
309
|
+
await drag(getByTestId("item-a"), getByTestId("item-c"));
|
|
310
|
+
|
|
311
|
+
await waitFor(() => {
|
|
312
|
+
expect(
|
|
313
|
+
getByTestId("item-a").querySelector("[data-testid='drag-handle']")
|
|
314
|
+
).toHaveAttribute("aria-grabbed", "false");
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
describe("Children in a form wrapper", () => {
|
|
320
|
+
afterEach(() => cleanup());
|
|
321
|
+
|
|
322
|
+
test("children inside a form each get their own handle", async () => {
|
|
323
|
+
const { getAllByTestId } = await render(
|
|
324
|
+
DraggableWithFormChildren,
|
|
325
|
+
default_props
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
await waitFor(() => {
|
|
329
|
+
expect(getAllByTestId("drag-handle")).toHaveLength(3);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
test("form children share one index sequence with direct children", async () => {
|
|
334
|
+
const { getByTestId } = await render(
|
|
335
|
+
DraggableWithFormChildren,
|
|
336
|
+
default_props
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
await waitFor(() => {
|
|
340
|
+
expect(
|
|
341
|
+
getByTestId("item-c").querySelector("[data-testid='drag-handle']")
|
|
342
|
+
).toHaveAttribute("data-index", "2");
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
test("two children inside the same form can be swapped", async () => {
|
|
347
|
+
const { container, getByTestId } = await render(
|
|
348
|
+
DraggableWithFormChildren,
|
|
349
|
+
default_props
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
await drag(getByTestId("item-a"), getByTestId("item-b"));
|
|
353
|
+
|
|
354
|
+
expect(item_order(container)).toEqual(["Item B", "Item A", "Item C"]);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
test("a form child can be swapped with a direct child", async () => {
|
|
358
|
+
const { container, getByTestId } = await render(
|
|
359
|
+
DraggableWithFormChildren,
|
|
360
|
+
default_props
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
await drag(getByTestId("item-a"), getByTestId("item-c"));
|
|
364
|
+
|
|
365
|
+
expect(item_order(container)).toEqual(["Item C", "Item B", "Item A"]);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
describe("Edge cases", () => {
|
|
370
|
+
afterEach(() => cleanup());
|
|
371
|
+
|
|
372
|
+
test("a child added after mount is made draggable", async () => {
|
|
373
|
+
const { getAllByTestId, getByRole } = await render(
|
|
374
|
+
DraggableWithChildren,
|
|
375
|
+
default_props
|
|
376
|
+
);
|
|
377
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
378
|
+
|
|
379
|
+
const late_child = document.createElement("div");
|
|
380
|
+
late_child.dataset.testid = "item-d";
|
|
381
|
+
late_child.textContent = "Item D";
|
|
382
|
+
getByRole("region").appendChild(late_child);
|
|
383
|
+
|
|
384
|
+
await waitFor(() => {
|
|
385
|
+
expect(getAllByTestId("drag-handle")).toHaveLength(4);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
test("a child removed after mount takes its handle with it", async () => {
|
|
390
|
+
const { getAllByTestId, getByTestId } = await render(
|
|
391
|
+
DraggableWithChildren,
|
|
392
|
+
default_props
|
|
393
|
+
);
|
|
394
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
395
|
+
|
|
396
|
+
getByTestId("item-c").remove();
|
|
397
|
+
|
|
398
|
+
await waitFor(() => {
|
|
399
|
+
expect(getAllByTestId("drag-handle")).toHaveLength(2);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test("a late child joins the existing index sequence", async () => {
|
|
404
|
+
const { getAllByTestId, getByRole } = await render(
|
|
405
|
+
DraggableWithChildren,
|
|
406
|
+
default_props
|
|
407
|
+
);
|
|
408
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
409
|
+
|
|
410
|
+
const late_child = document.createElement("div");
|
|
411
|
+
late_child.dataset.testid = "item-d";
|
|
412
|
+
late_child.textContent = "Item D";
|
|
413
|
+
getByRole("region").appendChild(late_child);
|
|
414
|
+
|
|
415
|
+
await waitFor(() => {
|
|
416
|
+
expect(
|
|
417
|
+
getAllByTestId("drag-handle").map((h) => h.getAttribute("data-index"))
|
|
418
|
+
).toEqual(["0", "1", "2", "3"]);
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
test("setting up twice does not leave a child with two handles", async () => {
|
|
423
|
+
const { getByTestId, getAllByTestId } = await render(
|
|
424
|
+
DraggableWithChildren,
|
|
425
|
+
default_props
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
await waitFor(() => expect(getAllByTestId("drag-handle")).toHaveLength(3));
|
|
429
|
+
|
|
430
|
+
expect(
|
|
431
|
+
getByTestId("item-a").querySelectorAll("[data-testid='drag-handle']")
|
|
432
|
+
).toHaveLength(1);
|
|
433
|
+
});
|
|
434
|
+
});
|
package/Index.svelte
CHANGED
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
handle.setAttribute("draggable", "true");
|
|
59
59
|
handle.setAttribute("aria-grabbed", "false");
|
|
60
60
|
handle.setAttribute("data-index", index.toString());
|
|
61
|
+
handle.setAttribute("data-testid", "drag-handle");
|
|
61
62
|
handle.innerHTML = "⋮⋮";
|
|
62
63
|
|
|
63
64
|
element.appendChild(handle);
|
|
@@ -282,7 +283,7 @@
|
|
|
282
283
|
: null}
|
|
283
284
|
/>
|
|
284
285
|
{/if}
|
|
285
|
-
|
|
286
|
+
{@render props.children?.()}
|
|
286
287
|
</div>
|
|
287
288
|
|
|
288
289
|
<style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Draggable from "./Index.svelte";
|
|
3
|
+
let props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<Draggable {...props}>
|
|
7
|
+
<div data-testid="item-a">Item A</div>
|
|
8
|
+
<div data-testid="item-b">Item B</div>
|
|
9
|
+
<div data-testid="item-c">Item C</div>
|
|
10
|
+
</Draggable>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Draggable from "./Index.svelte";
|
|
3
|
+
let props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<Draggable {...props}>
|
|
7
|
+
<div class="form">
|
|
8
|
+
<div data-testid="item-a">Item A</div>
|
|
9
|
+
<div data-testid="item-b">Item B</div>
|
|
10
|
+
</div>
|
|
11
|
+
<div data-testid="item-c">Item C</div>
|
|
12
|
+
</Draggable>
|
package/dist/Index.svelte
CHANGED
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
handle.setAttribute("draggable", "true");
|
|
59
59
|
handle.setAttribute("aria-grabbed", "false");
|
|
60
60
|
handle.setAttribute("data-index", index.toString());
|
|
61
|
+
handle.setAttribute("data-testid", "drag-handle");
|
|
61
62
|
handle.innerHTML = "⋮⋮";
|
|
62
63
|
|
|
63
64
|
element.appendChild(handle);
|
|
@@ -282,7 +283,7 @@
|
|
|
282
283
|
: null}
|
|
283
284
|
/>
|
|
284
285
|
{/if}
|
|
285
|
-
|
|
286
|
+
{@render props.children?.()}
|
|
286
287
|
</div>
|
|
287
288
|
|
|
288
289
|
<style>
|
package/dist/Index.svelte.d.ts
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: Props & {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const Index: $$__sveltets_2_IsomorphicComponent<any, {
|
|
15
|
-
[evt: string]: CustomEvent<any>;
|
|
16
|
-
}, {
|
|
17
|
-
default: {};
|
|
18
|
-
}, {}, "">;
|
|
19
|
-
type Index = InstanceType<typeof Index>;
|
|
1
|
+
declare const Index: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
2
|
+
type Index = ReturnType<typeof Index>;
|
|
20
3
|
export default Index;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Draggable from "./Index.svelte";
|
|
3
|
+
let props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<Draggable {...props}>
|
|
7
|
+
<div data-testid="item-a">Item A</div>
|
|
8
|
+
<div data-testid="item-b">Item B</div>
|
|
9
|
+
<div data-testid="item-c">Item C</div>
|
|
10
|
+
</Draggable>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Draggable from "./Index.svelte";
|
|
3
|
+
let props = $props();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<Draggable {...props}>
|
|
7
|
+
<div class="form">
|
|
8
|
+
<div data-testid="item-a">Item A</div>
|
|
9
|
+
<div data-testid="item-b">Item B</div>
|
|
10
|
+
</div>
|
|
11
|
+
<div data-testid="item-c">Item C</div>
|
|
12
|
+
</Draggable>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gradio/draggable",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Gradio Draggable layout component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"./package.json": "./package.json"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@gradio/preview": "^0.
|
|
20
|
-
"@gradio/utils": "^0.
|
|
21
|
-
"@gradio/statustracker": "^0.15.
|
|
19
|
+
"@gradio/preview": "^0.17.1",
|
|
20
|
+
"@gradio/utils": "^0.14.2",
|
|
21
|
+
"@gradio/statustracker": "^0.15.4"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
24
|
"svelte": "^5.48.0"
|