your personal website on atproto - mirror blento.app

small fixes

Florian 613d2ebd bae16167

+99 -48
+2 -21
src/lib/EditableWebsite.svelte
··· 299 } 300 301 // Auto-scroll when dragging near top or bottom of viewport 302 - const scrollZone = 150; 303 - const scrollSpeed = 15; 304 const viewportHeight = window.innerHeight; 305 306 if (e.clientY < scrollZone) { ··· 373 </BaseEditingCard> 374 <!-- {/if} --> 375 {/each} 376 - 377 - {#if activeDragElement.element && activeDragElement.x >= 0 && activeDragElement.item} 378 - {@const finalPos = simulateFinalPosition( 379 - items, 380 - activeDragElement.item, 381 - activeDragElement.x, 382 - activeDragElement.y, 383 - isMobile 384 - )} 385 - <div 386 - class={[ 387 - 'bg-base-500/10 absolute aspect-square rounded-2xl transition-transform duration-100' 388 - ]} 389 - style={`translate: calc(${(finalPos.x / COLUMNS) * 100}cqw + ${margin}px) calc(${(finalPos.y / COLUMNS) * 100}cqw + ${margin}px); 390 - 391 - width: calc(${(getW(activeDragElement.item) / COLUMNS) * 100}cqw - ${margin * 2}px); 392 - height: calc(${(getH(activeDragElement.item) / COLUMNS) * 100}cqw - ${margin * 2}px);`} 393 - ></div> 394 - {/if} 395 396 <div style="height: {((maxHeight + 2) / 8) * 100}cqw;"></div> 397 </div>
··· 299 } 300 301 // Auto-scroll when dragging near top or bottom of viewport 302 + const scrollZone = 100; 303 + const scrollSpeed = 10; 304 const viewportHeight = window.innerHeight; 305 306 if (e.clientY < scrollZone) { ··· 373 </BaseEditingCard> 374 <!-- {/if} --> 375 {/each} 376 377 <div style="height: {((maxHeight + 2) / 8) * 100}cqw;"></div> 378 </div>
+4 -4
src/lib/cards/BaseCard/BaseCard.svelte
··· 7 import { getColor } from '..'; 8 9 const colors = { 10 - base: 'border-base-300 shadow-lg dark:shadow-none inset-shadow-sm inset-shadow-base-500/10 shadow-base-900/5 bg-base-50 dark:border-base-700 dark:bg-base-900 border', 11 accent: 12 - 'border-accent-300 shadow-lg inset-shadow-sm inset-shadow-accent-500/10 shadow-accent-900/10 bg-accent-50 dark:border-accent-900 dark:bg-accent-950/20 border', 13 transparent: '' 14 } as Record<string, string>; 15 ··· 39 bind:this={ref} 40 draggable={isEditing} 41 class={[ 42 - 'card group focus-within:outline-accent-500 @container/card absolute z-0 rounded-2xl outline-offset-2 transition-all duration-200 focus-within:outline-2', 43 color ? (colors[color] ?? colors.accent) : colors.base, 44 color !== 'accent' && item.color !== 'base' && item.color !== 'transparent' ? color : '', 45 showOutline ? 'outline-2' : '' ··· 60 --columns: ${COLUMNS}`} 61 {...rest} 62 > 63 - <div class="relative h-full w-full overflow-hidden rounded-[15px] isolate"> 64 {@render children?.()} 65 </div> 66 {@render controls?.()}
··· 7 import { getColor } from '..'; 8 9 const colors = { 10 + base: 'border-base-300 shadow-lg dark:shadow-none inset-shadow-sm inset-shadow-base-500/10 shadow-base-900/5 bg-base-50 dark:border-base-700 dark:bg-base-900/30 border', 11 accent: 12 + 'border-accent-300 shadow-lg inset-shadow-sm inset-shadow-accent-500/10 shadow-accent-900/10 bg-accent-50 dark:border-accent-900 dark:bg-accent-900/10 border dark:inset-shadow-accent-500/20', 13 transparent: '' 14 } as Record<string, string>; 15 ··· 39 bind:this={ref} 40 draggable={isEditing} 41 class={[ 42 + 'card group focus-within:outline-accent-500 @container/card absolute z-0 rounded-3xl outline-offset-2 transition-all duration-200 focus-within:outline-2 isolate', 43 color ? (colors[color] ?? colors.accent) : colors.base, 44 color !== 'accent' && item.color !== 'base' && item.color !== 'transparent' ? color : '', 45 showOutline ? 'outline-2' : '' ··· 60 --columns: ${COLUMNS}`} 61 {...rest} 62 > 63 + <div class="relative h-full w-full overflow-hidden rounded-[23px] isolate"> 64 {@render children?.()} 65 </div> 66 {@render controls?.()}
+77 -16
src/lib/cards/BaseCard/BaseEditingCard.svelte
··· 62 const minH = $derived(cardDef.minH ?? (isMobile() ? 2 : 2)); 63 64 const maxW = $derived(cardDef.maxW ?? COLUMNS); 65 - const maxH = $derived(cardDef.maxH ?? 6); 66 67 // Resize handle state 68 let isResizing = $state(false); ··· 99 const deltaX = e.clientX - resizeStartX; 100 const deltaY = e.clientY - resizeStartY; 101 102 - const refRect = ref.getBoundingClientRect(); 103 - 104 - console.log(Math.round(deltaX / cellSize)); 105 // Convert pixel delta to grid units (2 grid units = 1 visual cell) 106 const gridDeltaW = Math.round(deltaX / cellSize); 107 const gridDeltaH = Math.round(deltaY / cellSize); ··· 135 document.removeEventListener('pointermove', handleResizeMove); 136 document.removeEventListener('pointerup', handleResizeEnd); 137 } 138 </script> 139 140 <BaseCard {item} {...rest} isEditing={true} bind:ref showOutline={isResizing}> ··· 170 171 <div 172 class={[ 173 - 'absolute -bottom-7 z-50 w-full items-center justify-center text-xs group-focus-within:inline-flex group-hover:inline-flex', 174 colorPopoverOpen ? 'inline-flex' : 'hidden' 175 ]} 176 > 177 <div 178 - class="bg-base-100 border-base-200 dark:bg-base-800 dark:border-base-700 inline-flex items-center gap-0.5 rounded-2xl border p-1 px-2 shadow-lg" 179 > 180 <Popover bind:open={colorPopoverOpen}> 181 {#snippet child({ props })} ··· 216 /> 217 </Popover> 218 219 {#if onshowsettings} 220 <button 221 onclick={() => { ··· 252 {#if cardDef.canResize !== false} 253 <!-- Resize handle at bottom right corner --> 254 <!-- svelte-ignore a11y_no_static_element_interactions --> 255 - <div 256 - class={[ 257 - 'absolute pointer-events-none inset-0 z-50 items-end justify-end overflow-hidden rounded-2xl group-focus-within:flex group-hover:flex', 258 - isResizing ? 'flex' : 'hidden' 259 - ]} 260 - onpointerdown={handleResizeStart} 261 - > 262 - <div onpointerdown={handleResizeStart} class="pointer-events-auto cursor-se-resize"> 263 <svg 264 xmlns="http://www.w3.org/2000/svg" 265 viewBox="0 0 24 24" ··· 268 stroke-width="2" 269 stroke-linecap="round" 270 stroke-linejoin="round" 271 - class="text-base-500 size-4" 272 > 273 <circle cx="12" cy="5" r="1" /><circle cx="19" cy="5" r="1" /><circle 274 cx="5" ··· 288 </svg> 289 <span class="sr-only">Resize card</span> 290 </div> 291 - </div> 292 {/if} 293 {/if} 294 {/snippet}
··· 62 const minH = $derived(cardDef.minH ?? (isMobile() ? 2 : 2)); 63 64 const maxW = $derived(cardDef.maxW ?? COLUMNS); 65 + const maxH = $derived(cardDef.maxH ?? (isMobile() ? 12 : 6)); 66 67 // Resize handle state 68 let isResizing = $state(false); ··· 99 const deltaX = e.clientX - resizeStartX; 100 const deltaY = e.clientY - resizeStartY; 101 102 // Convert pixel delta to grid units (2 grid units = 1 visual cell) 103 const gridDeltaW = Math.round(deltaX / cellSize); 104 const gridDeltaH = Math.round(deltaY / cellSize); ··· 132 document.removeEventListener('pointermove', handleResizeMove); 133 document.removeEventListener('pointerup', handleResizeEnd); 134 } 135 + 136 + 137 + function canSetSize(w: number, h: number) { 138 + if (!cardDef) return false; 139 + 140 + if(isMobile()) { 141 + w *= 2; 142 + h *= 2; 143 + } 144 + 145 + return w >= minW && w <= maxW && h >= minH && h <= maxH; 146 + } 147 + 148 + function setSize(w: number, h: number) { 149 + 150 + if(isMobile()) { 151 + w *= 2; 152 + h *= 2; 153 + } 154 + onsetsize?.(w, h); 155 + } 156 </script> 157 158 <BaseCard {item} {...rest} isEditing={true} bind:ref showOutline={isResizing}> ··· 188 189 <div 190 class={[ 191 + 'absolute -bottom-7 w-full items-center justify-center text-xs group-focus-within:inline-flex group-hover:inline-flex', 192 colorPopoverOpen ? 'inline-flex' : 'hidden' 193 ]} 194 > 195 <div 196 + class="bg-base-100 z-[100] border-base-200 dark:bg-base-800 dark:border-base-700 inline-flex items-center gap-0.5 rounded-2xl border p-1 px-2 shadow-lg" 197 > 198 <Popover bind:open={colorPopoverOpen}> 199 {#snippet child({ props })} ··· 234 /> 235 </Popover> 236 237 + 238 + {#if canSetSize(2, 2)} 239 + <button 240 + onclick={() => { 241 + setSize(2, 2); 242 + }} 243 + class="hover:bg-accent-500/10 cursor-pointer rounded-xl p-2" 244 + > 245 + <div class="border-base-900 dark:border-base-50 size-3 rounded-sm border-2"></div> 246 + 247 + <span class="sr-only">set size to 1x1</span> 248 + </button> 249 + {/if} 250 + 251 + {#if canSetSize(4, 2)} 252 + <button 253 + onclick={() => { 254 + setSize(4, 2); 255 + }} 256 + class="hover:bg-accent-500/10 cursor-pointer rounded-xl p-2" 257 + > 258 + <div class="border-base-900 dark:border-base-50 h-3 w-5 rounded-sm border-2"></div> 259 + <span class="sr-only">set size to 2x1</span> 260 + </button> 261 + {/if} 262 + {#if canSetSize(2, 4)} 263 + <button 264 + onclick={() => { 265 + setSize(2, 4); 266 + }} 267 + class="hover:bg-accent-500/10 cursor-pointer rounded-xl p-2" 268 + > 269 + <div class="border-base-900 dark:border-base-50 h-5 w-3 rounded-sm border-2"></div> 270 + 271 + <span class="sr-only">set size to 1x2</span> 272 + </button> 273 + {/if} 274 + {#if canSetSize(4, 4)} 275 + <button 276 + onclick={() => { 277 + setSize(4, 4); 278 + }} 279 + class="hover:bg-accent-500/10 cursor-pointer rounded-xl p-2" 280 + > 281 + <div class="border-base-900 dark:border-base-50 h-5 w-5 rounded-sm border-2"></div> 282 + 283 + <span class="sr-only">set size to 2x2</span> 284 + </button> 285 + {/if} 286 + 287 {#if onshowsettings} 288 <button 289 onclick={() => { ··· 320 {#if cardDef.canResize !== false} 321 <!-- Resize handle at bottom right corner --> 322 <!-- svelte-ignore a11y_no_static_element_interactions --> 323 + 324 + <div onpointerdown={handleResizeStart} class="absolute hidden group-hover:block right-0.5 bottom-0.5 pointer-events-auto cursor-se-resize bg-base-300/70 p-1 dark:bg-base-900/70 rounded-md rounded-br-3xl"> 325 <svg 326 xmlns="http://www.w3.org/2000/svg" 327 viewBox="0 0 24 24" ··· 330 stroke-width="2" 331 stroke-linecap="round" 332 stroke-linejoin="round" 333 + class=" dark:text-base-400 text-base-600 size-4" 334 > 335 <circle cx="12" cy="5" r="1" /><circle cx="19" cy="5" r="1" /><circle 336 cx="5" ··· 350 </svg> 351 <span class="sr-only">Resize card</span> 352 </div> 353 {/if} 354 {/if} 355 {/snippet}
+1
src/lib/cards/BlueskyMediaCard/Video.svelte
··· 32 muted 33 loop 34 autoplay 35 class="absolute inset-0 h-full w-full object-cover" 36 aria-label={video.alt} 37 ></video>
··· 32 muted 33 loop 34 autoplay 35 + playsinline 36 class="absolute inset-0 h-full w-full object-cover" 37 aria-label={video.alt} 38 ></video>
+5 -2
src/lib/cards/utils/MarkdownTextEditor.svelte
··· 85 onUpdate: () => { 86 update(); 87 }, 88 - 89 content: json, 90 91 editorProps: { 92 attributes: { 93 class: 'outline-none' 94 - } 95 } 96 }); 97
··· 85 onUpdate: () => { 86 update(); 87 }, 88 + onDrop: () => { 89 + return false; 90 + }, 91 content: json, 92 93 editorProps: { 94 attributes: { 95 class: 'outline-none' 96 + }, 97 + handleDOMEvents: { drop: () => true } 98 } 99 }); 100
+10 -5
src/routes/[handle]/og.png/+server.ts
··· 22 23 <p class="mt-8 text-4xl text-neutral-300">Check out my blento</p> 24 25 - <div class="w-20 h-20 rounded-xl bg-rose-700 text-transparent absolute top-70 right-20">h</div> 26 - <div class="w-20 h-40 rounded-xl bg-rose-400 text-transparent absolute top-94 right-20">h</div> 27 - <div class="w-40 h-40 rounded-xl bg-rose-300 text-transparent absolute top-70 right-44">h</div> 28 - <div class="w-20 h-40 rounded-xl bg-rose-600 text-transparent absolute top-70 right-88">h</div> 29 - <div class="w-40 h-20 rounded-xl bg-rose-500 text-transparent absolute top-114 right-68">h</div> 30 </div> 31 `; 32
··· 22 23 <p class="mt-8 text-4xl text-neutral-300">Check out my blento</p> 24 25 + <svg class="absolute w-130 h-130 top-50 right-0" viewBox="0 0 900 900" fill="none" xmlns="http://www.w3.org/2000/svg"> 26 + <rect x="100" y="100" width="160" height="340" rx="23" fill="#EF4444"/> 27 + <rect x="640" y="280" width="160" height="340" rx="23" fill="#22C55E"/> 28 + <rect x="280" y="100" width="340" height="340" rx="23" fill="#F59E0B"/> 29 + <rect x="100" y="460" width="340" height="160" rx="23" fill="#0EA5E9"/> 30 + <rect x="640" y="100" width="160" height="160" rx="23" fill="#EAB308"/> 31 + <rect x="100" y="640" width="160" height="160" rx="23" fill="#6366F1"/> 32 + <rect x="460" y="460" width="160" height="160" rx="23" fill="#14B8A6"/> 33 + <rect x="280" y="640" width="520" height="160" rx="23" fill="#A855F7"/> 34 + </svg> 35 </div> 36 `; 37