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