this repo has no description
at main 98 lines 3.4 kB view raw
1import { getContext, setContext } from 'svelte'; 2 3import type { TodayPage } from '@jet-app/app-store/api/models'; 4import { 5 type TodayCardShelf, 6 isTodayCardShelf, 7} from '~/components/jet/shelf/TodayCardShelf.svelte'; 8 9/** 10 * Describes the configuration of the card layout within a {@linkcode TodayCardShelf} 11 */ 12interface LayoutConfiguration { 13 wrap: { 14 shouldStretchFirstCard: boolean; 15 }; 16 nowrap: { 17 shouldStretchFirstCard: boolean; 18 }; 19} 20 21const LAYOUT_CONFIGURATION_FALLBACK: LayoutConfiguration = Object.freeze({ 22 wrap: { 23 shouldStretchFirstCard: true, 24 }, 25 nowrap: { 26 shouldStretchFirstCard: true, 27 }, 28}); 29 30type TodayCardLayoutStore = WeakMap<TodayCardShelf, LayoutConfiguration>; 31type TodayCardLayoutStoreContext = TodayCardLayoutStore | undefined; 32 33const TODAY_CARD_LAYOUT_CONTEXT_ID = 'today-card-layout-context'; 34 35/** 36 * Store the {@linkcode LayoutConfiguration} for each {@linkcode TodayCardShelf} in a 37 * {@linkcode TodayPage} in "context", so it can be retrieved at the shelf-component level 38 * 39 * This is necessary because the layout of the cards within each shelf of a {@linkcode TodayPage} 40 * is only knowable given information about the shelves that were rendered before it 41 * 42 * The information about the shelf layout is persisted through the "context" API so that the 43 * rendering of a {@linkcode TodayPage} can defer to the "default" page component, which requires 44 * that we pass no additional arguments into each shelf component 45 * 46 * {@linkcode getTodayCardLayoutConfiguration} can be used to look up the {@linkcode LayoutConfiguration} 47 * stored for a given {@linkcode TodayCardShelf} 48 */ 49export function setTodayCardLayoutContext(page: Pick<TodayPage, 'shelves'>) { 50 const store: TodayCardLayoutStore = new WeakMap(); 51 52 let shouldStretchFirstCardMultiline = false; 53 let shouldStretchFirstCardInline = false; 54 55 for (const shelf of page.shelves) { 56 // Skip any non-`TodayCard` shelves 57 if (!isTodayCardShelf(shelf)) { 58 continue; 59 } 60 61 store.set(shelf, { 62 wrap: { 63 shouldStretchFirstCard: shouldStretchFirstCardMultiline, 64 }, 65 nowrap: { 66 shouldStretchFirstCard: shouldStretchFirstCardInline, 67 }, 68 }); 69 70 // In the multi-line card configuration, shelves with two or three cards in them will 71 // require that the next shelf swaps to stretching the cards at the opposite end 72 if (shelf.items.length === 2 || shelf.items.length === 3) { 73 shouldStretchFirstCardMultiline = !shouldStretchFirstCardMultiline; 74 } 75 76 // In the "inline" card configuration, each shelf should always alternate which end the 77 // card is stretched on 78 shouldStretchFirstCardInline = !shouldStretchFirstCardInline; 79 } 80 81 setContext<TodayCardLayoutStoreContext>( 82 TODAY_CARD_LAYOUT_CONTEXT_ID, 83 store, 84 ); 85} 86 87/** 88 * Retrieve the {@linkcode LayoutConfiguration} for a given {@linkcode TodayCardShelf} 89 */ 90export function getTodayCardLayoutConfiguration( 91 shelf: TodayCardShelf, 92): LayoutConfiguration { 93 const todayCardLayout = getContext<TodayCardLayoutStoreContext>( 94 TODAY_CARD_LAYOUT_CONTEXT_ID, 95 ); 96 97 return todayCardLayout?.get(shelf) ?? LAYOUT_CONFIGURATION_FALLBACK; 98}