your personal website on atproto - mirror blento.app

first test

jycouet 0e4a4935 4feffd02

+68 -15
+33 -13
src/lib/cards/GitHubContributorsCard/GitHubContributorsCard.svelte
··· 13 13 let owner: string = $derived(item.cardData.owner ?? ''); 14 14 let repo: string = $derived(item.cardData.repo ?? ''); 15 15 let repoKey: string = $derived(owner && repo ? `${owner}/${repo}` : ''); 16 + let layout: 'hex' | 'grid' = $derived(item.cardData.layout ?? 'hex'); 16 17 17 18 let serverContributors: GitHubContributor[] = $derived.by(() => { 18 19 if (!repoKey) return []; ··· 66 67 const colsNarrow = Math.max(1, colsWide - 1); 67 68 const maxRows = Math.floor((availH + GAP) / (size + GAP)); 68 69 let capacity = 0; 70 + // Pattern: narrow, wide, narrow, wide... (row 0 is narrow) 69 71 for (let r = 0; r < maxRows; r++) { 70 - capacity += r % 2 === 0 ? colsWide : colsNarrow; 72 + capacity += r % 2 === 0 ? colsNarrow : colsWide; 71 73 } 72 74 return capacity; 73 75 } 74 76 77 + function gridCapacity(size: number, availW: number, availH: number): number { 78 + const cols = Math.floor((availW + GAP) / (size + GAP)); 79 + const rows = Math.floor((availH + GAP) / (size + GAP)); 80 + return cols * rows; 81 + } 82 + 75 83 let computedSize = $derived.by(() => { 76 84 if (!containerWidth || !containerHeight || totalItems === 0) return 40; 77 85 78 86 let lo = MIN_SIZE; 79 87 let hi = MAX_SIZE; 88 + const capacityFn = layout === 'hex' ? hexCapacity : gridCapacity; 80 89 81 90 while (lo <= hi) { 82 91 const mid = Math.floor((lo + hi) / 2); 83 - const availW = containerWidth - mid; 84 - const availH = containerHeight - mid; 92 + const availW = containerWidth - (layout === 'hex' ? mid : 0); 93 + const availH = containerHeight - (layout === 'hex' ? mid : 0); 85 94 if (availW <= 0 || availH <= 0) { 86 95 hi = mid - 1; 87 96 continue; 88 97 } 89 - if (hexCapacity(mid, availW, availH) >= totalItems) { 98 + if (capacityFn(mid, availW, availH) >= totalItems) { 90 99 lo = mid + 1; 91 100 } else { 92 101 hi = mid - 1; ··· 96 105 return Math.max(MIN_SIZE, hi); 97 106 }); 98 107 99 - let padding = $derived(computedSize / 2); 108 + let padding = $derived(layout === 'hex' ? computedSize / 2 : 0); 100 109 101 110 let rows = $derived.by(() => { 102 - const availW = containerWidth - computedSize; 111 + const availW = containerWidth - (layout === 'hex' ? computedSize : 0); 103 112 if (availW <= 0) return [] as GitHubContributor[][]; 113 + 104 114 const colsWide = Math.floor((availW + GAP) / (computedSize + GAP)); 105 - const colsNarrow = Math.max(1, colsWide - 1); 115 + const colsNarrow = layout === 'hex' ? Math.max(1, colsWide - 1) : colsWide; 106 116 117 + // Calculate row sizes from bottom up, then reverse for incomplete row at top 118 + const rowSizes: number[] = []; 119 + let remaining = namedContributors.length; 120 + let rowNum = 0; 121 + while (remaining > 0) { 122 + const cols = layout === 'hex' && rowNum % 2 === 0 ? colsNarrow : colsWide; 123 + rowSizes.push(Math.min(cols, remaining)); 124 + remaining -= cols; 125 + rowNum++; 126 + } 127 + rowSizes.reverse(); 128 + 129 + // Fill rows with contributors in order 107 130 const result: GitHubContributor[][] = []; 108 131 let idx = 0; 109 - let rowNum = 0; 110 - while (idx < namedContributors.length) { 111 - const cols = rowNum % 2 === 0 ? colsWide : colsNarrow; 112 - result.push(namedContributors.slice(idx, idx + cols)); 113 - idx += cols; 114 - rowNum++; 132 + for (const size of rowSizes) { 133 + result.push(namedContributors.slice(idx, idx + size)); 134 + idx += size; 115 135 } 116 136 return result; 117 137 });
+32
src/lib/cards/GitHubContributorsCard/GitHubContributorsCardSettings.svelte
··· 1 + <script lang="ts"> 2 + import type { SettingsComponentProps } from '../types'; 3 + import { Label } from '@foxui/core'; 4 + 5 + let { item = $bindable() }: SettingsComponentProps = $props(); 6 + 7 + const layoutOptions = [ 8 + { value: 'hex', label: 'Hexagon' }, 9 + { value: 'grid', label: 'Grid' } 10 + ]; 11 + 12 + let layout = $derived(item.cardData.layout ?? 'hex'); 13 + </script> 14 + 15 + <div class="flex flex-col gap-2"> 16 + <Label>Layout</Label> 17 + <div class="flex gap-2"> 18 + {#each layoutOptions as opt (opt.value)} 19 + <button 20 + class={[ 21 + 'flex-1 rounded-xl border px-3 py-2 text-sm transition-colors', 22 + layout === opt.value 23 + ? 'bg-accent-500 border-accent-500 text-white' 24 + : 'bg-base-100 dark:bg-base-800 border-base-300 dark:border-base-700 text-base-900 dark:text-base-100 hover:border-accent-400' 25 + ]} 26 + onclick={() => (item.cardData.layout = opt.value)} 27 + > 28 + {opt.label} 29 + </button> 30 + {/each} 31 + </div> 32 + </div>
+2
src/lib/cards/GitHubContributorsCard/index.ts
··· 1 1 import type { CardDefinition } from '../types'; 2 2 import GitHubContributorsCard from './GitHubContributorsCard.svelte'; 3 3 import CreateGitHubContributorsCardModal from './CreateGitHubContributorsCardModal.svelte'; 4 + import GitHubContributorsCardSettings from './GitHubContributorsCardSettings.svelte'; 4 5 5 6 export type GitHubContributor = { 6 7 username: string; ··· 15 16 type: 'githubContributors', 16 17 contentComponent: GitHubContributorsCard, 17 18 creationModalComponent: CreateGitHubContributorsCardModal, 19 + settingsComponent: GitHubContributorsCardSettings, 18 20 createNew: (card) => { 19 21 card.w = 4; 20 22 card.h = 2;
+1 -2
src/routes/(auth)/oauth/callback/+page.svelte
··· 12 12 goto('/' + getHandleOrDid(user.profile) + '/edit', {}); 13 13 } 14 14 15 - if(!user.isInitializing && !startedErrorTimer) { 15 + if (!user.isInitializing && !startedErrorTimer) { 16 16 startedErrorTimer = true; 17 17 18 18 setTimeout(() => { ··· 30 30 >There was an error signing you in, please go back to the 31 31 <a class="text-accent-600 dark:text-accent-400" href="/">homepage</a> 32 32 and try again. 33 - 34 33 </span> 35 34 </div> 36 35 {/if}