your personal website on atproto - mirror blento.app
at kickstarter-card 89 lines 2.3 kB view raw
1<script lang="ts"> 2 import { Alert, Button, Modal, Subheading } from '@foxui/core'; 3 import type { CreationModalComponentProps } from '../types'; 4 5 let { item = $bindable(), oncreate, oncancel }: CreationModalComponentProps = $props(); 6 7 let embedCode = $state(''); 8 let errorMessage = $state(''); 9 10 function parseInput(code: string): { 11 src: string | null; 12 widgetType: 'card' | 'video'; 13 } { 14 const normalized = code.trim().replaceAll('&amp;', '&'); 15 16 // Try iframe embed code first 17 const srcMatch = normalized.match(/src="(https:\/\/www\.kickstarter\.com\/[^"]+)"/); 18 if (srcMatch) { 19 const src = srcMatch[1]; 20 const widgetType = src.includes('/widget/video') ? 'video' : 'card'; 21 return { src, widgetType }; 22 } 23 24 // Try plain project URL 25 const urlMatch = normalized.match(/kickstarter\.com\/projects\/([^/]+\/[^/?#\s]+)/i); 26 if (urlMatch) { 27 return { 28 src: `https://www.kickstarter.com/projects/${urlMatch[1]}/widget/card.html?v=2`, 29 widgetType: 'card' 30 }; 31 } 32 33 return { src: null, widgetType: 'card' }; 34 } 35 36 function validate(): boolean { 37 errorMessage = ''; 38 39 const { src, widgetType } = parseInput(embedCode); 40 41 if (!src) { 42 errorMessage = 'Could not find a Kickstarter URL in the input'; 43 return false; 44 } 45 46 item.cardData.src = src; 47 item.cardData.widgetType = widgetType; 48 49 if (widgetType === 'video') { 50 item.w = 4; 51 item.h = 2; 52 item.mobileW = 8; 53 item.mobileH = 4; 54 } else { 55 item.w = 4; 56 item.h = 4; 57 item.mobileW = 8; 58 item.mobileH = 8; 59 } 60 61 return true; 62 } 63</script> 64 65<Modal open={true} closeButton={false}> 66 <Subheading>Paste Kickstarter URL or Embed Code</Subheading> 67 68 <textarea 69 bind:value={embedCode} 70 placeholder="https://www.kickstarter.com/projects/..." 71 rows={5} 72 class="bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 text-base-900 dark:text-base-100 w-full rounded-xl border px-3 py-2 font-mono text-sm" 73 ></textarea> 74 75 {#if errorMessage} 76 <Alert type="error" title="Invalid embed code"><span>{errorMessage}</span></Alert> 77 {/if} 78 79 <div class="mt-4 flex justify-end gap-2"> 80 <Button onclick={oncancel} variant="ghost">Cancel</Button> 81 <Button 82 onclick={() => { 83 if (validate()) oncreate(); 84 }} 85 > 86 Create 87 </Button> 88 </div> 89</Modal>