your personal website on atproto - mirror blento.app
at next 87 lines 2.6 kB view raw
1<script lang="ts"> 2 import NumberFlow, { NumberFlowGroup } from '@number-flow/svelte'; 3 import type { ContentComponentProps } from '../types'; 4 import type { ClockCardData } from './index'; 5 import { onMount } from 'svelte'; 6 7 let { item }: ContentComponentProps = $props(); 8 9 let cardData = $derived(item.cardData as ClockCardData); 10 11 let now = $state(new Date()); 12 13 onMount(() => { 14 const interval = setInterval(() => { 15 now = new Date(); 16 }, 1000); 17 return () => clearInterval(interval); 18 }); 19 20 let clockParts = $derived.by(() => { 21 try { 22 return new Intl.DateTimeFormat('en-US', { 23 timeZone: cardData.timezone || 'UTC', 24 hour: '2-digit', 25 minute: '2-digit', 26 second: '2-digit', 27 hour12: false 28 }).formatToParts(now); 29 } catch { 30 return null; 31 } 32 }); 33 34 let clockHours = $derived( 35 clockParts ? parseInt(clockParts.find((p) => p.type === 'hour')?.value || '0') : 0 36 ); 37 let clockMinutes = $derived( 38 clockParts ? parseInt(clockParts.find((p) => p.type === 'minute')?.value || '0') : 0 39 ); 40 let clockSeconds = $derived( 41 clockParts ? parseInt(clockParts.find((p) => p.type === 'second')?.value || '0') : 0 42 ); 43 44 let timezoneDisplay = $derived.by(() => { 45 if (!cardData.timezone) return ''; 46 try { 47 const formatter = new Intl.DateTimeFormat('en-US', { 48 timeZone: cardData.timezone, 49 timeZoneName: 'short' 50 }); 51 const parts = formatter.formatToParts(now); 52 return parts.find((p) => p.type === 'timeZoneName')?.value || cardData.timezone; 53 } catch { 54 return cardData.timezone; 55 } 56 }); 57</script> 58 59<div class="@container flex h-full w-full flex-col items-center justify-center p-4"> 60 <NumberFlowGroup> 61 <div 62 class="text-base-900 dark:text-base-100 accent:text-base-900 flex items-center text-3xl font-bold @xs:text-4xl @sm:text-5xl @md:text-6xl @lg:text-7xl" 63 style="font-variant-numeric: tabular-nums;" 64 > 65 <NumberFlow value={clockHours} format={{ minimumIntegerDigits: 2 }} /> 66 <span class="text-base-400 dark:text-base-500 accent:text-accent-950 mx-0.5">:</span> 67 <NumberFlow 68 value={clockMinutes} 69 format={{ minimumIntegerDigits: 2 }} 70 digits={{ 1: { max: 5 } }} 71 trend={1} 72 /> 73 <span class="text-base-400 dark:text-base-500 accent:text-accent-950 mx-0.5">:</span> 74 <NumberFlow 75 value={clockSeconds} 76 format={{ minimumIntegerDigits: 2 }} 77 digits={{ 1: { max: 5 } }} 78 trend={1} 79 /> 80 </div> 81 </NumberFlowGroup> 82 {#if timezoneDisplay} 83 <div class="text-base-500 dark:text-base-400 accent:text-base-600 mt-1 text-xs @sm:text-sm"> 84 {timezoneDisplay} 85 </div> 86 {/if} 87</div>