Something went wrong. Try again.
your personal website on atproto - mirror blento.app
Something went wrong. Try again.
2.1 kB · 84 lines
Svelte
at moar-cards
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485<script lang="ts"> import { getHexCSSVar } from '$lib/cards/helper'; import { onMount } from 'svelte';
let { url, icon, iconColor, class: className = '' }: { url: string; icon?: string; iconColor?: string; class?: string; } = $props();
let container: HTMLDivElement | undefined = $state();
// Convert SVG string to data URI for use as QR center image function svgToDataUri(svg: string, color: string): string { // Add fill color to SVG - insert fill attribute on the svg tag let coloredSvg = svg; if (!svg.includes('fill=')) { // No fill attribute, add it to the svg tag coloredSvg = svg.replace('<svg', `<svg fill="${color}"`); } else { // Replace existing fill attributes coloredSvg = svg.replace(/fill="[^"]*"/g, `fill="${color}"`); } const encoded = encodeURIComponent(coloredSvg); return `data:image/svg+xml,${encoded}`; }
onMount(async () => { if (!container) return;
// Use iconColor or accent color, ensure # prefix const rawColor = iconColor || getHexCSSVar('--color-accent-600'); const dotColor = rawColor.startsWith('#') ? rawColor : `#${rawColor}`;
const module = await import('qr-code-styling'); const QRCodeStyling = module.default;
// Get container size for responsive QR const rect = container.getBoundingClientRect(); const size = Math.min(rect.width, rect.height) || 280;
const options: ConstructorParameters<typeof QRCodeStyling>[0] = { width: size, height: size, data: url, dotsOptions: { color: dotColor, type: 'rounded' }, backgroundOptions: { color: '#FFF' }, cornersSquareOptions: { type: 'extra-rounded', color: dotColor }, cornersDotOptions: { type: 'dot', color: dotColor }, margin: 10 };
// Add icon as center image if provided (as SVG string) if (icon) { options.image = svgToDataUri(icon, dotColor); options.imageOptions = { margin: 10, imageSize: 0.5 }; }
const qrCode = new QRCodeStyling(options); qrCode.append(container); });</script>
<div bind:this={container} class="flex items-center justify-center {className}"></div>