_includes/resourcecard/ResourceCard.11ty.tsx (157 lines of code) (raw):

import ConsistentHash from "consistent-hash"; import { Resource } from "../../src/ResourceModels"; import { Topic } from "../resources/topic/TopicModels"; import TopicTag from "../resources/topic/TopicTag.11ty"; import { AuthorIcon, doesExist } from "./Utilities.11ty"; const glowColorHashRing = new ConsistentHash({ range: 100003, weight: 85, distribution: "uniform", }); glowColorHashRing.add("has-glow-magenta"); glowColorHashRing.add("has-glow-pink"); glowColorHashRing.add("has-glow-fresh-green"); glowColorHashRing.add("has-glow-cold-green"); glowColorHashRing.add("has-glow-orange"); glowColorHashRing.add("has-glow-red"); glowColorHashRing.add("has-glow-purple"); export type ResourceCardProps = { resource: Resource; columnClassName?: string; hasShadow?: boolean; includeCardFooter?: boolean; compactMode?: boolean; includeContentType?: boolean; hideTitle?: boolean; }; export type GetGlowInfoProps = { displayDate: string; title: string; }; export function getGlowInfo({ displayDate, title }: GetGlowInfoProps): any { // Thumbnail const thumbnailFigureCss = "is-16by9 is-contained"; // Glow const glowCssClass = glowColorHashRing.get(title + displayDate); return { thumbnailFigureCss, glowCssClass, }; } const ResourceCard = ({ resource: { url, title, displayDate, subtitle, references }, resource, columnClassName, hasShadow = false, includeCardFooter = true, compactMode = false, includeContentType = true, hideTitle = false, }: ResourceCardProps): JSX.Element => { doesExist(references); const { author, topics } = references; let thumbnail = resource.getThumbnail(); // Data needed for glow info const { thumbnailFigureCss, glowCssClass } = getGlowInfo({ displayDate, title, }); // Custom CSS classes const columnCssClass = columnClassName ? columnClassName : "is-half-tablet is-one-quarter-desktop"; const cardCssClass = hasShadow ? "" : "is-shadowless"; // Content type const contentType = resource.describeContentType(); return ( <div class={`column ${columnCssClass}`}> <div class={`card is-equal-height has-box-outline has-box-hover ${cardCssClass}`} > <div class="card-image"> <a href={url} data-template-href="url" aria-hidden={true} tabindex={-1} > <figure data-template-class="thumbnailCss" class={`image ${thumbnailFigureCss} ${glowCssClass}`} > <img data-template-src="thumbnail" data-template-title="title" src={thumbnail} alt={title} /> </figure> </a> </div> {!hideTitle && ( <div class="card-content has-position-relative"> {contentType && includeContentType && !compactMode && ( <p class="subtitle is-size-7 is-uppercase" // TODO Paul remember this might be "Medium" etc. for Link data-template="contentType" // TODO Paul this should be replaced in explore as well > {contentType} </p> )} <a class="title is-size-5 is-stretched-link clamp clamp-2 mb-1" aria-label={title} data-template="title" data-template-href="url" href={url} > {title} </a> {subtitle && !compactMode && ( <div class="content clamp clamp-5" data-template="subtitle"> {subtitle} </div> )} </div> )} {includeCardFooter && !compactMode && ( <footer class="card-footer"> <div class="container p-4"> <div class="tags mb-2 clamp clamp-1"> {topics.map((topic: Topic) => ( <TopicTag topic={topic} /> ))} </div> <div class="media author"> <div class="p-2 media-left"> <a href={author.url} data-template-href="authorURL"> <figure class="image m-0 is-24x24"> <AuthorIcon {...author} /> </figure> </a> </div> <div class="media-content"> <div class="content is-size-7"> <p class="m-0"> <a href={author.url} data-template-href="authorURL" data-template="author" > {author.title}{" "} {(author as any).isGuest && "(Community)"} </a> </p> <time class="m-0 has-text-grey-dark" datetime={displayDate} data-template="datetime" > {displayDate} </time> </div> </div> </div> </div> </footer> )} </div> </div> ); }; export default ResourceCard;