{ if (isTyping()) return; const text = event.clipboardData?.getData('text/plain'); const link = validateLink(text, false); if (!link) return; addLink(link); }} /> {#if !dev}
Editing on mobile is not supported yet. Please use a desktop browser.
{/if} {#if showingMobileView}
{/if} {#if newItem.modal && newItem.item} { saveNewItem(); }} bind:item={newItem.item} oncancel={() => { newItem = {}; }} /> {/if}
{#if !getHideProfileSection(data)} {/if}
{ e.preventDefault(); const result = getDragXY(e); if (!result) return; activeDragElement.x = result.x; activeDragElement.y = result.y; if (activeDragElement.item) { // Get dragged card's original position for swapping const draggedOrigPos = activeDragElement.originalPositions.get( activeDragElement.item.id ); // Reset all items to original positions first for (const it of items) { const origPos = activeDragElement.originalPositions.get(it.id); if (origPos && it !== activeDragElement.item) { if (isMobile) { it.mobileX = origPos.mobileX; it.mobileY = origPos.mobileY; } else { it.x = origPos.x; it.y = origPos.y; } } } // Update dragged item position if (isMobile) { activeDragElement.item.mobileX = result.x; activeDragElement.item.mobileY = result.y; } else { activeDragElement.item.x = result.x; activeDragElement.item.y = result.y; } // Handle horizontal swap if (result.swapWithId && draggedOrigPos) { const swapTarget = items.find((it) => it.id === result.swapWithId); if (swapTarget) { // Move swap target to dragged card's original position if (isMobile) { swapTarget.mobileX = draggedOrigPos.mobileX; swapTarget.mobileY = draggedOrigPos.mobileY; } else { swapTarget.x = draggedOrigPos.x; swapTarget.y = draggedOrigPos.y; } } } // Now fix collisions (with compacting) fixCollisions(items, activeDragElement.item, isMobile); } // Auto-scroll when dragging near top or bottom of viewport const scrollZone = 100; const scrollSpeed = 10; const viewportHeight = window.innerHeight; if (e.clientY < scrollZone) { // Near top - scroll up const intensity = 1 - e.clientY / scrollZone; window.scrollBy(0, -scrollSpeed * intensity); } else if (e.clientY > viewportHeight - scrollZone) { // Near bottom - scroll down const intensity = 1 - (viewportHeight - e.clientY) / scrollZone; window.scrollBy(0, scrollSpeed * intensity); } }} ondragend={async (e) => { e.preventDefault(); const cell = getDragXY(e); if (!cell) return; if (activeDragElement.item) { if (isMobile) { activeDragElement.item.mobileX = cell.x; activeDragElement.item.mobileY = cell.y; } else { activeDragElement.item.x = cell.x; activeDragElement.item.y = cell.y; } // Fix collisions and compact items after drag ends fixCollisions(items, activeDragElement.item, isMobile); } activeDragElement.x = -1; activeDragElement.y = -1; activeDragElement.element = null; activeDragElement.item = null; activeDragElement.lastTargetId = null; activeDragElement.lastPlacement = null; return true; }} class={[ '@container/grid relative col-span-3 rounded-4xl px-2 py-8 @5xl/wrapper:px-8', imageDragOver && 'outline-accent-500 outline-3 -outline-offset-10 outline-dashed' ]} > {#each items as item, i (item.id)} { items = items.filter((it) => it !== item); compactItems(items, isMobile); }} onsetsize={(newW: number, newH: number) => { if (isMobile) { item.mobileW = newW; item.mobileH = newH; } else { item.w = newW; item.h = newH; } fixCollisions(items, item, isMobile); }} ondragstart={(e: DragEvent) => { const target = e.currentTarget as HTMLDivElement; activeDragElement.element = target; activeDragElement.w = item.w; activeDragElement.h = item.h; activeDragElement.item = item; // Store original positions of all items activeDragElement.originalPositions = new Map(); for (const it of items) { activeDragElement.originalPositions.set(it.id, { x: it.x, y: it.y, mobileX: it.mobileX, mobileY: it.mobileY }); } const rect = target.getBoundingClientRect(); activeDragElement.mouseDeltaX = rect.left - e.clientX; activeDragElement.mouseDeltaY = rect.top - e.clientY; }} > {/each}
{#each sidebarItems as cardDef (cardDef.type)} {/each}