your personal website on atproto - mirror
blento.app
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('&', '&');
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>