UNPKG

@frontity/mars-theme

Version:

A starter theme for Frontity

248 lines (216 loc) 5.57 kB
import { useEffect } from "react"; import { connect, styled } from "frontity"; import Link from "./link"; import List from "./list"; import FeaturedMedia from "./featured-media"; /** * The Post component that Mars uses to render any kind of "post type", like * posts, pages, attachments, etc. * * It doesn't receive any prop but the Frontity store, which it receives from * {@link connect}. The current Frontity state is used to know which post type * should be rendered. * * @param props - The Frontity store (state, actions, and libraries). * * @example * ```js * <Switch> * <Post when={data.isPostType} /> * </Switch> * ``` * * @returns The {@link Post} element rendered. */ const Post = ({ state, actions, libraries }) => { // Get information about the current URL. const data = state.source.get(state.router.link); // Get the data of the post. const post = state.source[data.type][data.id]; // Get the data of the author. const author = state.source.author[post.author]; // Get a human readable date. const date = new Date(post.date); // Get the html2react component. const Html2React = libraries.html2react.Component; /** * Once the post has loaded in the DOM, prefetch both the * home posts and the list component so if the user visits * the home page, everything is ready and it loads instantly. */ useEffect(() => { actions.source.fetch("/"); List.preload(); }, [actions.source]); // Load the post, but only if the data is ready. return data.isReady ? ( <Container> <div> <Title dangerouslySetInnerHTML={{ __html: post.title.rendered }} /> {/* Hide author and date on pages */} {!data.isPage && ( <div> {author && ( <StyledLink link={author.link}> <Author> By <b>{author.name}</b> </Author> </StyledLink> )} <DateWrapper> {" "} on <b>{date.toDateString()}</b> </DateWrapper> </div> )} </div> {/* Look at the settings to see if we should include the featured image */} {state.theme.featured.showOnPost && ( <FeaturedMedia id={post.featured_media} /> )} {data.isAttachment ? ( // If the post is an attachment, just render the description property, // which already contains the thumbnail. <div dangerouslySetInnerHTML={{ __html: post.description.rendered }} /> ) : ( // Render the content using the Html2React component so the HTML is // processed by the processors we included in the // libraries.html2react.processors array. <Content> <Html2React html={post.content.rendered} /> </Content> )} </Container> ) : null; }; export default connect(Post); const Container = styled.div` width: 800px; margin: 0; padding: 24px; `; const Title = styled.h1` margin: 0; margin-top: 24px; margin-bottom: 8px; color: rgba(12, 17, 43); `; const StyledLink = styled(Link)` padding: 15px 0; `; const Author = styled.p` color: rgba(12, 17, 43, 0.9); font-size: 0.9em; display: inline; `; const DateWrapper = styled.p` color: rgba(12, 17, 43, 0.9); font-size: 0.9em; display: inline; `; /** * This component is the parent of the `content.rendered` HTML. We can use nested * selectors to style that HTML. */ const Content = styled.div` color: rgba(12, 17, 43, 0.8); word-break: break-word; * { max-width: 100%; } p { line-height: 1.6em; } img { width: 100%; object-fit: cover; object-position: center; } figure { margin: 24px auto; width: 100%; figcaption { font-size: 0.7em; } } iframe { display: block; margin: auto; } blockquote { margin: 16px 0; background-color: rgba(0, 0, 0, 0.1); border-left: 4px solid rgba(12, 17, 43); padding: 4px 16px; } a { color: rgb(31, 56, 197); text-decoration: underline; } /* Input fields styles */ input[type="text"], input[type="email"], input[type="url"], input[type="tel"], input[type="number"], input[type="date"], textarea, select { display: block; padding: 6px 12px; font-size: 16px; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; border-radius: 4px; outline-color: transparent; transition: outline-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; margin: 8px 0 4px 0; &:focus { outline-color: #1f38c5; } } input[type="submit"] { display: inline-block; margin-bottom: 0; font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle; -ms-touch-action: manipulation; touch-action: manipulation; cursor: pointer; background-image: none; border: 1px solid #1f38c5; padding: 12px 36px; font-size: 14px; line-height: 1.42857143; border-radius: 4px; color: #fff; background-color: #1f38c5; } /* WordPress Core Align Classes */ @media (min-width: 420px) { img.aligncenter, img.alignleft, img.alignright { width: auto; } .aligncenter { display: block; margin-left: auto; margin-right: auto; } .alignright { float: right; margin-left: 24px; } .alignleft { float: left; margin-right: 24px; } } `;