your personal website on atproto - mirror blento.app
at fix-formatting 84 lines 2.1 kB view raw
1<script lang="ts"> 2 import { getHexCSSVar } from '$lib/cards/helper'; 3 import { onMount } from 'svelte'; 4 5 let { 6 url, 7 icon, 8 iconColor, 9 class: className = '' 10 }: { 11 url: string; 12 icon?: string; 13 iconColor?: string; 14 class?: string; 15 } = $props(); 16 17 let container: HTMLDivElement | undefined = $state(); 18 19 // Convert SVG string to data URI for use as QR center image 20 function svgToDataUri(svg: string, color: string): string { 21 // Add fill color to SVG - insert fill attribute on the svg tag 22 let coloredSvg = svg; 23 if (!svg.includes('fill=')) { 24 // No fill attribute, add it to the svg tag 25 coloredSvg = svg.replace('<svg', `<svg fill="${color}"`); 26 } else { 27 // Replace existing fill attributes 28 coloredSvg = svg.replace(/fill="[^"]*"/g, `fill="${color}"`); 29 } 30 const encoded = encodeURIComponent(coloredSvg); 31 return `data:image/svg+xml,${encoded}`; 32 } 33 34 onMount(async () => { 35 if (!container) return; 36 37 // Use iconColor or accent color, ensure # prefix 38 const rawColor = iconColor || getHexCSSVar('--color-accent-600'); 39 const dotColor = rawColor.startsWith('#') ? rawColor : `#${rawColor}`; 40 41 const module = await import('qr-code-styling'); 42 const QRCodeStyling = module.default; 43 44 // Get container size for responsive QR 45 const rect = container.getBoundingClientRect(); 46 const size = Math.min(rect.width, rect.height) || 280; 47 48 const options: ConstructorParameters<typeof QRCodeStyling>[0] = { 49 width: size, 50 height: size, 51 data: url, 52 dotsOptions: { 53 color: dotColor, 54 type: 'rounded' 55 }, 56 backgroundOptions: { 57 color: '#FFF' 58 }, 59 cornersSquareOptions: { 60 type: 'extra-rounded', 61 color: dotColor 62 }, 63 cornersDotOptions: { 64 type: 'dot', 65 color: dotColor 66 }, 67 margin: 10 68 }; 69 70 // Add icon as center image if provided (as SVG string) 71 if (icon) { 72 options.image = svgToDataUri(icon, dotColor); 73 options.imageOptions = { 74 margin: 10, 75 imageSize: 0.5 76 }; 77 } 78 79 const qrCode = new QRCodeStyling(options); 80 qrCode.append(container); 81 }); 82</script> 83 84<div bind:this={container} class="flex items-center justify-center {className}"></div>