[READ-ONLY] Mirror of https://github.com/flo-bit/room. tiny 3d rooms saved locally or in your bluesky account, svelte/threlte flo-bit.dev/room/
0

Configure Feed

Select the types of activity you want to include in your feed.

room / src / lib / components / extra / following-pointer / FollowingPointer.svelte
2.4 kB 104 lines
1<script lang="ts"> 2 import { cn } from '$lib/utils'; 3 import { Portal } from 'bits-ui'; 4 import { onMount, type Snippet } from 'svelte'; 5 6 let { 7 class: className, 8 children, 9 container, 10 title, 11 titleClasses, 12 hideCursor = true 13 }: { 14 class?: string; 15 children?: Snippet; 16 container?: HTMLElement | string; 17 title?: string; 18 titleClasses?: string; 19 hideCursor?: boolean; 20 } = $props(); 21 22 let x = $state(-1000); 23 let y = $state(-1000); 24 let isInside: boolean = $state(false); 25 26 onMount(() => { 27 if (typeof container === 'string') { 28 let containerElement = document.querySelector(container); 29 30 if (containerElement) { 31 container = containerElement as HTMLElement; 32 } else { 33 console.error(`Container ${container} not found, using body`); 34 } 35 } 36 37 if (!container) { 38 container = document.body; 39 } 40 41 if (container instanceof HTMLElement) { 42 container.addEventListener('mousemove', handleMouseMove); 43 container.addEventListener('mouseleave', handleMouseLeave); 44 container.addEventListener('mouseenter', handleMouseEnter); 45 window.addEventListener('resize', handleResize); 46 rect = container.getBoundingClientRect(); 47 48 if (hideCursor) { 49 // important: 50 // container.style.cursor = 'none !important;'; 51 } 52 } 53 }); 54 55 let rect: DOMRect | null = null; 56 57 const handleResize = () => { 58 if (container instanceof HTMLElement) { 59 rect = container.getBoundingClientRect(); 60 } 61 }; 62 63 const handleMouseMove = (e: MouseEvent) => { 64 const scrollX = window.scrollX; 65 const scrollY = window.scrollY; 66 67 x = e.clientX - (rect?.left ?? 0) + scrollX; 68 y = e.clientY - (rect?.top ?? 0) + scrollY; 69 }; 70 const handleMouseLeave = () => { 71 console.log('mouse leave'); 72 isInside = false; 73 }; 74 75 const handleMouseEnter = () => { 76 console.log('mouse enter'); 77 isInside = true; 78 }; 79</script> 80 81<Portal to={container}> 82 {#if isInside} 83 <div 84 class={cn( 85 'animate-in fade-in-0 pointer-events-none absolute z-50', 86 className 87 )} 88 style={`top: ${y}px; left: ${x}px`} 89 > 90 {#if title} 91 <div 92 class={cn( 93 'bg-accent-500/10 dark:bg-accent-500/10 text-accent-600 dark:text-accent-400 border-accent-500/20 dark:border-accent-500/10 m-3 w-fit rounded-2xl border px-2 py-1 text-sm backdrop-blur-sm', 94 titleClasses 95 )} 96 > 97 {title} 98 </div> 99 {/if} 100 101 {@render children?.()} 102 </div> 103 {/if} 104</Portal>