@invopop/popui 0.1.4-beta.45 → 0.1.4-beta.47

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.
@@ -3,8 +3,8 @@
3
3
  import { createFloatingActions } from 'svelte-floating-ui'
4
4
  import { clickOutside } from './clickOutside.js'
5
5
  import { portal } from 'svelte-portal'
6
- import { slide } from 'svelte/transition'
7
6
  import type { BaseDropdownProps } from './types.js'
7
+ import type { TransitionConfig } from 'svelte/transition'
8
8
 
9
9
  let {
10
10
  isOpen = $bindable(false),
@@ -46,6 +46,33 @@
46
46
  middleware
47
47
  })
48
48
 
49
+ // Custom transition that mimics shadcn style
50
+ function dropdownTransition(
51
+ node: HTMLElement,
52
+ { duration = 150 }: { duration?: number } = {}
53
+ ): TransitionConfig {
54
+ const side = placement.split('-')[0]
55
+
56
+ // Calculate slide direction
57
+ let slideY = 0
58
+ let slideX = 0
59
+ if (side === 'bottom') slideY = -8
60
+ if (side === 'top') slideY = 8
61
+ if (side === 'left') slideX = 8
62
+ if (side === 'right') slideX = -8
63
+
64
+ return {
65
+ duration,
66
+ css: (t) => {
67
+ const eased = t * (2 - t) // ease-out
68
+ return `
69
+ opacity: ${eased};
70
+ transform: scale(${0.95 + eased * 0.05}) translate(${slideX * (1 - eased)}px, ${slideY * (1 - eased)}px);
71
+ `
72
+ }
73
+ }
74
+ }
75
+
49
76
  export const toggle = () => {
50
77
  isOpen = !isOpen
51
78
  }
@@ -83,7 +110,7 @@
83
110
  }, 100)
84
111
  isOpen = false
85
112
  }}
86
- transition:slide={{ duration: 100 }}
113
+ transition:dropdownTransition={{ duration: 150 }}
87
114
  >
88
115
  {@render children?.()}
89
116
  </div>
@@ -8,8 +8,26 @@
8
8
  import { ChevronRight } from '@steeze-ui/heroicons'
9
9
  import { slide } from 'svelte/transition'
10
10
  import { flip } from 'svelte/animate'
11
- import { dndzone } from 'svelte-dnd-action'
12
- import { onMount } from 'svelte'
11
+ import {
12
+ draggable as makeDraggable,
13
+ dropTargetForElements
14
+ } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'
15
+ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine'
16
+ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element'
17
+ import { reorder } from '@atlaskit/pragmatic-drag-and-drop/reorder'
18
+ import {
19
+ attachClosestEdge,
20
+ extractClosestEdge,
21
+ type Edge
22
+ } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge'
23
+ import { onMount, onDestroy, untrack } from 'svelte'
24
+ import {
25
+ shouldShowDropIndicator,
26
+ reorderItems,
27
+ moveItemBetweenGroups,
28
+ type DropIndicatorState,
29
+ type DndItem as DndItemType
30
+ } from './drawer-dnd-helpers'
13
31
 
14
32
  const flipDurationMs = 150
15
33
 
@@ -59,6 +77,9 @@
59
77
  let itemsCache = $state<DrawerOption[]>([])
60
78
  let isDragging = $state(false)
61
79
  let emitTimeout: number | undefined
80
+ let draggedOverGroup = $state<string | null>(null)
81
+ let dropIndicator = $state<DropIndicatorState>(null)
82
+ let cleanupFunctions: (() => void)[] = []
62
83
 
63
84
  // Build internal DND items from external items
64
85
  function buildListIn() {
@@ -140,14 +161,18 @@
140
161
  itemsCache = JSON.parse(JSON.stringify(items))
141
162
  buildListIn()
142
163
  mounted = true
164
+
165
+ // Set up auto-scroll
166
+ const autoScrollCleanup = autoScrollForElements({
167
+ element: document.documentElement
168
+ })
169
+ cleanupFunctions.push(autoScrollCleanup)
143
170
  })
144
171
 
145
- function transformDraggedElement(draggedEl: HTMLElement | undefined) {
146
- if (draggedEl) {
147
- draggedEl.style.border = 'none'
148
- draggedEl.style.outline = 'none'
149
- }
150
- }
172
+ onDestroy(() => {
173
+ cleanupFunctions.forEach((cleanup) => cleanup())
174
+ cleanupFunctions = []
175
+ })
151
176
 
152
177
  function emitGroupDistribution() {
153
178
  if (ondropitem && hasGroups) {
@@ -168,40 +193,199 @@
168
193
  }
169
194
  }
170
195
 
171
- function handleDndConsider(groupSlug: string, e: CustomEvent<any>) {
172
- if (!isDragging) {
173
- isDragging = true
196
+ // Setup draggable item (Svelte action)
197
+ function setupDraggableItem(element: HTMLElement, params: [DndItem, string]) {
198
+ const [dndItem, groupSlug] = params
199
+ if (!element || dndItem.locked) return
200
+
201
+ const cleanup = makeDraggable({
202
+ element,
203
+ getInitialData: () => ({ id: dndItem.id, groupSlug, type: 'drawer-item' }),
204
+ onDragStart: () => {
205
+ isDragging = true
206
+ dropIndicator = null
207
+ },
208
+ onDrop: () => {
209
+ isDragging = false
210
+ dropIndicator = null
211
+ }
212
+ })
213
+
214
+ return {
215
+ destroy() {
216
+ cleanup()
217
+ }
174
218
  }
175
- groupDndItems[groupSlug] = e.detail.items
176
219
  }
177
220
 
178
- function handleDndFinalize(groupSlug: string, e: CustomEvent<any>) {
179
- isDragging = false
180
- groupDndItems[groupSlug] = e.detail.items
221
+ // Setup drop zone for a container (group or ungrouped) (Svelte action)
222
+ function setupDropZone(element: HTMLElement, groupSlug: string) {
223
+ if (!element) return
224
+
225
+ const cleanup = dropTargetForElements({
226
+ element,
227
+ getData: () => {
228
+ const items =
229
+ groupSlug === 'ungrouped' ? ungroupedDndItems : groupDndItems[groupSlug] || []
230
+ return { groupSlug, items: items.map((i) => i.id) }
231
+ },
232
+ canDrop: ({ source }) => source.data.type === 'drawer-item',
233
+ onDragEnter: () => {
234
+ draggedOverGroup = groupSlug
235
+ },
236
+ onDragLeave: () => {
237
+ if (draggedOverGroup === groupSlug) {
238
+ draggedOverGroup = null
239
+ }
240
+ },
241
+ onDrop: ({ source, location }) => {
242
+ draggedOverGroup = null
243
+ dropIndicator = null
244
+ const sourceId = source.data.id as string
245
+ const sourceGroup = source.data.groupSlug as string
246
+ const targetGroup = groupSlug
247
+
248
+ // Get source and target arrays
249
+ const sourceItems =
250
+ sourceGroup === 'ungrouped' ? ungroupedDndItems : groupDndItems[sourceGroup] || []
251
+ const targetItems =
252
+ targetGroup === 'ungrouped' ? ungroupedDndItems : groupDndItems[targetGroup] || []
253
+
254
+ // Find the dragged item
255
+ const sourceIndex = sourceItems.findIndex((item) => item.id === sourceId)
256
+ if (sourceIndex === -1) return
257
+
258
+ const draggedItem = sourceItems[sourceIndex]
259
+
260
+ // If moving within the same group, we need to handle reordering
261
+ if (sourceGroup === targetGroup) {
262
+ // Check if we're dropping on another item
263
+ const dropTargets = location.current.dropTargets
264
+ const itemDropTarget = dropTargets.find((target) => target.data.itemId)
265
+
266
+ if (itemDropTarget) {
267
+ const targetItemId = itemDropTarget.data.itemId as string
268
+ const edge = extractClosestEdge(itemDropTarget.data)
269
+
270
+ if (edge) {
271
+ const newItems = reorderItems(targetItems, sourceId, targetItemId, edge)
272
+
273
+ if (targetGroup === 'ungrouped') {
274
+ ungroupedDndItems = newItems
275
+ } else {
276
+ groupDndItems[targetGroup] = newItems
277
+ }
278
+ }
279
+ }
280
+ } else {
281
+ // Moving between groups
282
+ const dropTargets = location.current.dropTargets
283
+ const itemDropTarget = dropTargets.find((target) => target.data.itemId)
181
284
 
182
- const newItems = buildListOut()
183
- items = newItems
184
- itemsCache = JSON.parse(JSON.stringify(items))
185
- onreorder?.(newItems)
186
- emitGroupDistribution()
187
- }
285
+ let targetItemId: string | undefined
286
+ let edge: Edge | undefined
287
+
288
+ if (itemDropTarget) {
289
+ targetItemId = itemDropTarget.data.itemId as string
290
+ edge = extractClosestEdge(itemDropTarget.data) || undefined
291
+ }
292
+
293
+ const { newSourceItems, newTargetItems } = moveItemBetweenGroups(
294
+ sourceItems,
295
+ targetItems,
296
+ sourceId,
297
+ targetItemId,
298
+ edge
299
+ )
300
+
301
+ if (sourceGroup === 'ungrouped') {
302
+ ungroupedDndItems = newSourceItems
303
+ } else {
304
+ groupDndItems[sourceGroup] = newSourceItems
305
+ }
188
306
 
189
- function handleUngroupedDndConsider(e: CustomEvent<any>) {
190
- if (!isDragging) {
191
- isDragging = true
307
+ if (targetGroup === 'ungrouped') {
308
+ ungroupedDndItems = newTargetItems
309
+ } else {
310
+ groupDndItems[targetGroup] = newTargetItems
311
+ }
312
+ }
313
+
314
+ // Update items and notify
315
+ const newItems = buildListOut()
316
+ items = newItems
317
+ itemsCache = JSON.parse(JSON.stringify(items))
318
+ onreorder?.(newItems)
319
+ emitGroupDistribution()
320
+ }
321
+ })
322
+
323
+ return {
324
+ destroy() {
325
+ cleanup()
326
+ }
192
327
  }
193
- ungroupedDndItems = e.detail.items
194
328
  }
195
329
 
196
- function handleUngroupedDndFinalize(e: CustomEvent<any>) {
197
- isDragging = false
198
- ungroupedDndItems = e.detail.items
330
+ // Setup drop zone for individual items (for reordering within same group) (Svelte action)
331
+ function setupItemDropZone(element: HTMLElement, params: [DndItem, string]) {
332
+ const [dndItem, groupSlug] = params
333
+ if (!element) return
334
+
335
+ const cleanup = dropTargetForElements({
336
+ element,
337
+ getData: ({ input }) => {
338
+ const data = { itemId: dndItem.id, groupSlug }
339
+ return attachClosestEdge(data, {
340
+ element,
341
+ input,
342
+ allowedEdges: ['top', 'bottom']
343
+ })
344
+ },
345
+ canDrop: ({ source }) => {
346
+ return source.data.type === 'drawer-item' && source.data.id !== dndItem.id
347
+ },
348
+ onDragEnter: ({ self, source }) => {
349
+ const edge = extractClosestEdge(self.data)
350
+ if (!edge) return
351
+
352
+ const sourceId = source.data.id as string
353
+ const sourceGroup = source.data.groupSlug as string
354
+ const items = groupSlug === 'ungrouped' ? ungroupedDndItems : groupDndItems[groupSlug] || []
355
+
356
+ if (shouldShowDropIndicator(sourceId, dndItem.id, sourceGroup, groupSlug, edge, items)) {
357
+ dropIndicator = { itemId: dndItem.id, edge }
358
+ }
359
+ },
360
+ onDrag: ({ self, source }) => {
361
+ const edge = extractClosestEdge(self.data)
362
+ if (!edge) return
363
+
364
+ const sourceId = source.data.id as string
365
+ const sourceGroup = source.data.groupSlug as string
366
+ const items = groupSlug === 'ungrouped' ? ungroupedDndItems : groupDndItems[groupSlug] || []
367
+
368
+ if (shouldShowDropIndicator(sourceId, dndItem.id, sourceGroup, groupSlug, edge, items)) {
369
+ dropIndicator = { itemId: dndItem.id, edge }
370
+ } else {
371
+ dropIndicator = null
372
+ }
373
+ },
374
+ onDragLeave: () => {
375
+ if (dropIndicator?.itemId === dndItem.id) {
376
+ dropIndicator = null
377
+ }
378
+ },
379
+ onDrop: () => {
380
+ dropIndicator = null
381
+ }
382
+ })
199
383
 
200
- const newItems = buildListOut()
201
- items = newItems
202
- itemsCache = JSON.parse(JSON.stringify(items))
203
- onreorder?.(newItems)
204
- emitGroupDistribution()
384
+ return {
385
+ destroy() {
386
+ cleanup()
387
+ }
388
+ }
205
389
  }
206
390
 
207
391
  function updateItem(item: DrawerOption) {
@@ -231,7 +415,7 @@
231
415
  >
232
416
  {@render children?.()}
233
417
 
234
- {#if hasGroups}
418
+ {#if hasGroups && groups}
235
419
  {#each groups as group, index}
236
420
  {@const groupItems = groupedItems.get(group.slug) || []}
237
421
  {@const isLastGroup = index === groups!.length - 1}
@@ -281,15 +465,8 @@
281
465
  >
282
466
  {#if draggable}
283
467
  <div
284
- use:dndzone={{
285
- items: groupDndItems[group.slug] || [],
286
- flipDurationMs,
287
- dropTargetStyle: {},
288
- type: 'drawer-item',
289
- transformDraggedElement
290
- }}
291
- onconsider={(e) => handleDndConsider(group.slug, e)}
292
- onfinalize={(e) => handleDndFinalize(group.slug, e)}
468
+ use:setupDropZone={group.slug}
469
+ class="min-h-[40px]"
293
470
  >
294
471
  {#if !groupItems.length}
295
472
  <div class="px-1 pt-1 pb-5">
@@ -301,7 +478,19 @@
301
478
  </div>
302
479
  {:else}
303
480
  {#each groupDndItems[group.slug] || [] as dndItem (dndItem.id)}
304
- <div animate:flip={{ duration: isDragging ? flipDurationMs : 0 }}>
481
+ {@const showTopIndicator =
482
+ dropIndicator?.itemId === dndItem.id && dropIndicator?.edge === 'top'}
483
+ {@const showBottomIndicator =
484
+ dropIndicator?.itemId === dndItem.id && dropIndicator?.edge === 'bottom'}
485
+ <div
486
+ animate:flip={{ duration: isDragging ? flipDurationMs : 0 }}
487
+ use:setupDraggableItem={[dndItem, group.slug]}
488
+ use:setupItemDropZone={[dndItem, group.slug]}
489
+ class:border-t-2={showTopIndicator}
490
+ class:border-t-border-selected={showTopIndicator}
491
+ class:border-b-2={showBottomIndicator}
492
+ class:border-b-border-selected={showBottomIndicator}
493
+ >
305
494
  {@render drawerItem(dndItem)}
306
495
  </div>
307
496
  {/each}
@@ -332,19 +521,23 @@
332
521
  {#if ungroupedItems.length}
333
522
  {#if draggable}
334
523
  <div
335
- class="flex-shrink-0 overflow-y-auto max-h-[564px]"
336
- use:dndzone={{
337
- items: ungroupedDndItems,
338
- flipDurationMs,
339
- dropTargetStyle: {},
340
- type: 'drawer-item',
341
- transformDraggedElement
342
- }}
343
- onconsider={handleUngroupedDndConsider}
344
- onfinalize={handleUngroupedDndFinalize}
524
+ class="flex-shrink-0 overflow-y-auto max-h-[564px] min-h-[40px]"
525
+ use:setupDropZone={'ungrouped'}
345
526
  >
346
527
  {#each ungroupedDndItems as dndItem (dndItem.id)}
347
- <div animate:flip={{ duration: isDragging ? flipDurationMs : 0 }}>
528
+ {@const showTopIndicator =
529
+ dropIndicator?.itemId === dndItem.id && dropIndicator?.edge === 'top'}
530
+ {@const showBottomIndicator =
531
+ dropIndicator?.itemId === dndItem.id && dropIndicator?.edge === 'bottom'}
532
+ <div
533
+ animate:flip={{ duration: isDragging ? flipDurationMs : 0 }}
534
+ use:setupDraggableItem={[dndItem, 'ungrouped']}
535
+ use:setupItemDropZone={[dndItem, 'ungrouped']}
536
+ class:border-t-2={showTopIndicator}
537
+ class:border-t-border-selected={showTopIndicator}
538
+ class:border-b-2={showBottomIndicator}
539
+ class:border-b-border-selected={showBottomIndicator}
540
+ >
348
541
  {@render drawerItem(dndItem)}
349
542
  </div>
350
543
  {/each}
@@ -78,6 +78,7 @@ export interface DataTableProps<TData> {
78
78
  initialSortDirection?: TableSortBy;
79
79
  initialFrozenColumns?: string[];
80
80
  initialColumnOrder?: string[];
81
+ initialColumnVisibility?: Record<string, boolean>;
81
82
  pageSizeOptions?: number[];
82
83
  emptyState?: Omit<EmptyStateProps, 'children' | 'check'>;
83
84
  onRowClick?: (row: TData) => void;
@@ -96,6 +97,7 @@ export interface DataTableProps<TData> {
96
97
  onFreezeChange?: (columnId: string) => void;
97
98
  onColumnResize?: (columnSizes: Record<string, number>) => void;
98
99
  onColumnOrderChange?: (columnOrder: string[]) => void;
100
+ onColumnVisibilityChange?: (visibility: Record<string, boolean>) => void;
99
101
  getRowClassName?: (row: TData) => string;
100
102
  getRowState?: (row: TData) => {
101
103
  isSuccess?: boolean;
@@ -45,6 +45,7 @@
45
45
  initialSortDirection,
46
46
  initialFrozenColumns = [],
47
47
  initialColumnOrder = [],
48
+ initialColumnVisibility = {},
48
49
  emptyState = {
49
50
  iconSource: Search,
50
51
  title: 'No results',
@@ -65,6 +66,7 @@
65
66
  onFreezeChange,
66
67
  onColumnResize,
67
68
  onColumnOrderChange,
69
+ onColumnVisibilityChange,
68
70
  getRowClassName,
69
71
  getRowState,
70
72
  children
@@ -74,7 +76,7 @@
74
76
  const enablePagination = !disablePagination
75
77
 
76
78
  let rowSelection = $state<RowSelectionState>({})
77
- let columnVisibility = $state<VisibilityState>({})
79
+ let columnVisibility = $state<VisibilityState>(initialColumnVisibility)
78
80
  let sorting = $state<SortingState>(
79
81
  initialSortColumn && initialSortDirection
80
82
  ? [{ id: initialSortColumn, desc: initialSortDirection === 'desc' }]
@@ -151,6 +153,13 @@
151
153
  }
152
154
  })
153
155
 
156
+ // Track column visibility changes
157
+ $effect(() => {
158
+ if (onColumnVisibilityChange && Object.keys(columnVisibility).length > 0) {
159
+ onColumnVisibilityChange(columnVisibility)
160
+ }
161
+ })
162
+
154
163
  const table = setupTable({
155
164
  getData: () => data,
156
165
  getColumns: () => columns,
@@ -263,8 +272,9 @@
263
272
  if (header.id === columnId) {
264
273
  break
265
274
  }
266
- // Add width of previous frozen columns (or select column)
267
- if (frozenColumns.has(header.id) || header.id === 'select') {
275
+ // Only add width of previous frozen columns that are visible (or select column)
276
+ const isVisible = header.column?.getIsVisible?.() ?? true
277
+ if (isVisible && (frozenColumns.has(header.id) || header.id === 'select')) {
268
278
  offset += header.getSize()
269
279
  }
270
280
  }
@@ -0,0 +1,30 @@
1
+ import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
2
+ export type DndItem = {
3
+ id: string;
4
+ locked?: boolean;
5
+ [key: string]: any;
6
+ };
7
+ export type DropIndicatorState = {
8
+ itemId: string;
9
+ edge: Edge;
10
+ } | null;
11
+ /**
12
+ * Checks if dropping an item would result in no position change
13
+ * (i.e., dropping right next to its current position)
14
+ */
15
+ export declare function shouldShowDropIndicator(sourceId: string, targetId: string, sourceGroup: string, targetGroup: string, edge: Edge, items: DndItem[]): boolean;
16
+ /**
17
+ * Calculates the new index where a dragged item should be inserted
18
+ */
19
+ export declare function calculateInsertIndex(sourceIndex: number, targetIndex: number, edge: Edge): number;
20
+ /**
21
+ * Reorders items within the same group
22
+ */
23
+ export declare function reorderItems<T extends DndItem>(items: T[], sourceId: string, targetId: string, edge: Edge): T[];
24
+ /**
25
+ * Moves an item from one group to another
26
+ */
27
+ export declare function moveItemBetweenGroups<T extends DndItem>(sourceItems: T[], targetItems: T[], sourceId: string, targetId?: string, edge?: Edge): {
28
+ newSourceItems: T[];
29
+ newTargetItems: T[];
30
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Checks if dropping an item would result in no position change
3
+ * (i.e., dropping right next to its current position)
4
+ */
5
+ export function shouldShowDropIndicator(sourceId, targetId, sourceGroup, targetGroup, edge, items) {
6
+ // Always show for cross-group drops
7
+ if (sourceGroup !== targetGroup) {
8
+ return true;
9
+ }
10
+ // Check if dropping would result in no position change
11
+ const sourceIndex = items.findIndex((item) => item.id === sourceId);
12
+ const targetIndex = items.findIndex((item) => item.id === targetId);
13
+ // Don't show indicator if dropping adjacent to current position
14
+ const isAdjacentTop = edge === 'top' && targetIndex === sourceIndex + 1;
15
+ const isAdjacentBottom = edge === 'bottom' && targetIndex === sourceIndex - 1;
16
+ return !isAdjacentTop && !isAdjacentBottom;
17
+ }
18
+ /**
19
+ * Calculates the new index where a dragged item should be inserted
20
+ */
21
+ export function calculateInsertIndex(sourceIndex, targetIndex, edge) {
22
+ let insertIndex = targetIndex;
23
+ // Adjust target index if source was before target (array shifts after removal)
24
+ if (sourceIndex < targetIndex) {
25
+ insertIndex = targetIndex - 1;
26
+ }
27
+ // If dropping on bottom edge, insert after
28
+ if (edge === 'bottom') {
29
+ insertIndex = insertIndex + 1;
30
+ }
31
+ return insertIndex;
32
+ }
33
+ /**
34
+ * Reorders items within the same group
35
+ */
36
+ export function reorderItems(items, sourceId, targetId, edge) {
37
+ const sourceIndex = items.findIndex((item) => item.id === sourceId);
38
+ const targetIndex = items.findIndex((item) => item.id === targetId);
39
+ if (sourceIndex === -1 || targetIndex === -1) {
40
+ return items;
41
+ }
42
+ const newItems = [...items];
43
+ const [draggedItem] = newItems.splice(sourceIndex, 1);
44
+ const insertIndex = calculateInsertIndex(sourceIndex, targetIndex, edge);
45
+ newItems.splice(insertIndex, 0, draggedItem);
46
+ return newItems;
47
+ }
48
+ /**
49
+ * Moves an item from one group to another
50
+ */
51
+ export function moveItemBetweenGroups(sourceItems, targetItems, sourceId, targetId, edge) {
52
+ const draggedItem = sourceItems.find((item) => item.id === sourceId);
53
+ if (!draggedItem) {
54
+ return { newSourceItems: sourceItems, newTargetItems: targetItems };
55
+ }
56
+ const newSourceItems = sourceItems.filter((item) => item.id !== sourceId);
57
+ // If no target specified, append to end
58
+ if (!targetId || !edge) {
59
+ const newTargetItems = [...targetItems, draggedItem];
60
+ return { newSourceItems, newTargetItems };
61
+ }
62
+ // Insert at specific position based on target and edge
63
+ const targetIndex = targetItems.findIndex((item) => item.id === targetId);
64
+ if (targetIndex === -1) {
65
+ const newTargetItems = [...targetItems, draggedItem];
66
+ return { newSourceItems, newTargetItems };
67
+ }
68
+ const newTargetItems = [...targetItems];
69
+ const insertIndex = edge === 'bottom' ? targetIndex + 1 : targetIndex;
70
+ newTargetItems.splice(insertIndex, 0, draggedItem);
71
+ return { newSourceItems, newTargetItems };
72
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@invopop/popui",
3
3
  "license": "MIT",
4
- "version": "0.1.4-beta.45",
4
+ "version": "0.1.4-beta.47",
5
5
  "repository": {
6
6
  "url": "https://github.com/invopop/popui"
7
7
  },
@@ -81,6 +81,9 @@
81
81
  "types": "./dist/index.d.ts",
82
82
  "type": "module",
83
83
  "dependencies": {
84
+ "@atlaskit/pragmatic-drag-and-drop": "^1.7.7",
85
+ "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.5",
86
+ "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
84
87
  "@floating-ui/core": "^1.5.1",
85
88
  "@invopop/ui-icons": "^0.0.78",
86
89
  "@steeze-ui/heroicons": "^2.2.3",
@@ -97,7 +100,6 @@
97
100
  "inter-ui": "^3.19.3",
98
101
  "lodash-es": "^4.17.21",
99
102
  "mode-watcher": "^1.1.0",
100
- "svelte-dnd-action": "^0.9.69",
101
103
  "svelte-floating-ui": "^1.5.8",
102
104
  "svelte-headlessui": "^0.0.46",
103
105
  "svelte-intersection-observer-action": "^0.0.4",
@@ -106,6 +108,7 @@
106
108
  "svelte-transition": "^0.0.17",
107
109
  "svelte-viewport-info": "^1.0.2",
108
110
  "tailwind-variants": "^1.0.0",
111
+ "tailwindcss-animate": "^1.0.7",
109
112
  "zod": "^4.3.5"
110
113
  }
111
114
  }