{ 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 (cardDef.type === 'image') { const input = document.getElementById('image-input') as HTMLInputElement; if (input) { input.click(); return; } } else { newCard(cardDef.type); } }} /> {#if showingMobileView}
{/if} {#if newItem.modal && newItem.item} { saveNewItem(); }} bind:item={newItem.item} oncancel={() => { newItem = {}; }} /> {/if}
{#if !getHideProfileSection(data)} {/if}
{ // Deselect when tapping empty grid space if (e.target === e.currentTarget || !(e.target as HTMLElement)?.closest?.('.card')) { selectedCardId = null; } }} ontouchstart={touchStart} ontouchend={touchEnd} ondragover={(e) => { 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); onLayoutChanged(); } activeDragElement.x = -1; activeDragElement.y = -1; activeDragElement.element = null; activeDragElement.item = null; activeDragElement.lastTargetId = null; activeDragElement.lastPlacement = null; return true; }} class={[ '@container/grid pointer-events-auto 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, false); compactItems(items, true); onLayoutChanged(); }} onsetsize={(newW: number, newH: number) => { if (isMobile) { item.mobileW = newW; item.mobileH = newH; } else { item.w = newW; item.h = newH; } fixCollisions(items, item, isMobile); onLayoutChanged(); }} 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}
{ showCardCommand = true; }} {selectedCard} {isMobile} {isCoarse} ondeselect={() => { selectedCardId = null; }} ondelete={() => { if (selectedCard) { items = items.filter((it) => it.id !== selectedCardId); compactItems(items, false); compactItems(items, true); onLayoutChanged(); selectedCardId = null; } }} onsetsize={(w: number, h: number) => { if (selectedCard) { if (isMobile) { selectedCard.mobileW = w; selectedCard.mobileH = h; } else { selectedCard.w = w; selectedCard.h = h; } fixCollisions(items, selectedCard, isMobile); onLayoutChanged(); } }} /> {#if dev}
editedOn: {editedOn}
{/if}