your personal website on atproto - mirror blento.app

Merge pull request #99 from flo-bit/button

Button

authored by

Florian and committed by
GitHub
15ff5f50 78d08bfc

+125 -1
+2 -1
.claude/settings.local.json
··· 22 22 "Bash(pnpm config:*)", 23 23 "Bash(lsof:*)", 24 24 "Bash(pnpm dev)", 25 - "Bash(pnpm exec svelte-kit:*)" 25 + "Bash(pnpm exec svelte-kit:*)", 26 + "Bash(pnpm build:*)" 26 27 ] 27 28 } 28 29 }
+41
src/lib/cards/ButtonCard/ButtonCard.svelte
··· 1 + <script lang="ts"> 2 + import { goto } from '$app/navigation'; 3 + import { user } from '$lib/atproto'; 4 + import { getHandleOrDid } from '$lib/atproto/methods'; 5 + import { loginModalState } from '$lib/atproto/UI/LoginModal.svelte'; 6 + import type { ContentComponentProps } from '../types'; 7 + 8 + let { item }: ContentComponentProps = $props(); 9 + </script> 10 + 11 + {#snippet content()} 12 + <span 13 + class="text-base-950 dark:text-base-50 line-clamp-1 inline-flex items-center justify-center px-4 text-2xl font-semibold" 14 + > 15 + {item.cardData.text || 'Click me'} 16 + </span> 17 + {/snippet} 18 + 19 + {#if item.cardData.href === '#login'} 20 + <button 21 + onclick={() => { 22 + if (user.isLoggedIn && user.profile) { 23 + goto('/' + getHandleOrDid(user.profile) + '/edit', {}); 24 + } else { 25 + loginModalState.show(); 26 + } 27 + }} 28 + class="hover:bg-accent-100/20 flex h-full w-full cursor-pointer flex-col items-center justify-center transition-colors duration-100" 29 + > 30 + {@render content()} 31 + </button> 32 + {:else} 33 + <a 34 + href={item.cardData.href || '#'} 35 + target="_blank" 36 + rel="noopener noreferrer" 37 + class="hover:bg-accent-100/20 flex h-full w-full flex-col items-center justify-center transition-colors duration-100" 38 + > 39 + {@render content()} 40 + </a> 41 + {/if}
+34
src/lib/cards/ButtonCard/ButtonCardSettings.svelte
··· 1 + <script lang="ts"> 2 + import type { Item } from '$lib/types'; 3 + import type { SettingsComponentProps } from '../types'; 4 + import { Input, Label } from '@foxui/core'; 5 + 6 + let { item = $bindable<Item>(), onclose }: SettingsComponentProps = $props(); 7 + 8 + function confirmUrl() { 9 + let href = item.cardData.href?.trim() || ''; 10 + if (href && !/^https?:\/\//i.test(href) && !href.startsWith('#')) { 11 + href = 'https://' + href; 12 + } 13 + item.cardData.href = href; 14 + onclose(); 15 + } 16 + </script> 17 + 18 + <div class="flex flex-col gap-3"> 19 + <div class="flex flex-col gap-1"> 20 + <Label for="button-href" class="text-sm">Link</Label> 21 + <Input 22 + id="button-href" 23 + bind:value={item.cardData.href} 24 + placeholder="youtube.com" 25 + class="text-sm mt-2" 26 + onkeydown={(event) => { 27 + if (event.code === 'Enter') { 28 + event.preventDefault(); 29 + confirmUrl(); 30 + } 31 + }} 32 + /> 33 + </div> 34 + </div>
+15
src/lib/cards/ButtonCard/EditingButtonCard.svelte
··· 1 + <script lang="ts"> 2 + import type { ContentComponentProps } from '../types'; 3 + import PlainTextEditor from '$lib/components/PlainTextEditor.svelte'; 4 + 5 + let { item = $bindable() }: ContentComponentProps = $props(); 6 + </script> 7 + 8 + <div class="text-base-950 dark:text-base-50 flex h-full w-full flex-col items-center justify-center gap-2 px-4"> 9 + <PlainTextEditor 10 + key="text" 11 + bind:contentDict={item.cardData} 12 + placeholder="Button text" 13 + class="line-clamp-1 text-center text-2xl font-bold" 14 + /> 15 + </div>
+31
src/lib/cards/ButtonCard/index.ts
··· 1 + import type { CardDefinition } from '../types'; 2 + import ButtonCard from './ButtonCard.svelte'; 3 + import EditingButtonCard from './EditingButtonCard.svelte'; 4 + import ButtonCardSettings from './ButtonCardSettings.svelte'; 5 + 6 + export const ButtonCardDefinition: CardDefinition = { 7 + type: 'button', 8 + contentComponent: ButtonCard, 9 + editingContentComponent: EditingButtonCard, 10 + settingsComponent: ButtonCardSettings, 11 + sidebarButtonText: 'Button', 12 + 13 + createNew: (card) => { 14 + card.cardData = { 15 + text: 'Click me' 16 + }; 17 + card.w = 2; 18 + card.h = 1; 19 + card.mobileW = 4; 20 + card.mobileH = 2; 21 + }, 22 + 23 + defaultColor: 'transparent', 24 + allowSetColor: true, 25 + canHaveLabel: false, 26 + 27 + minW: 2, 28 + minH: 1, 29 + maxW: 8, 30 + maxH: 4 31 + };
+2
src/lib/cards/index.ts
··· 31 31 import { DrawCardDefinition } from './DrawCard'; 32 32 import { TimerCardDefinition } from './TimerCard'; 33 33 import { SpotifyCardDefinition } from './SpotifyCard'; 34 + import { ButtonCardDefinition } from './ButtonCard'; 34 35 // import { Model3DCardDefinition } from './Model3DCard'; 35 36 36 37 export const AllCardDefinitions = [ 38 + ButtonCardDefinition, 37 39 ImageCardDefinition, 38 40 VideoCardDefinition, 39 41 TextCardDefinition,