f/basic-mdx-components #9

Merged
Skydust merged 7 commits from f/basic-mdx-components into dev 2023-09-09 23:01:32 +00:00
12 changed files with 259 additions and 240 deletions
Showing only changes of commit bfeeb71312 - Show all commits

View File

@@ -2,11 +2,11 @@ import React from "react";
import { Container } from "../util/container"; import { Container } from "../util/container";
import { Section } from "../util/section"; import { Section } from "../util/section";
import { TinaMarkdown } from "tinacms/dist/rich-text"; import { TinaMarkdown } from "tinacms/dist/rich-text";
import type { Template, TinaTemplate } from "tinacms"; import type { Template } from "tinacms";
import { PageBlocksCarousel, PageBlocksContent } from "../../tina/__generated__/types"; import { PageBlocksContent } from "../../tina/__generated__/types";
import { tinaField } from "tinacms/dist/react"; import { tinaField } from "tinacms/dist/react";
import { PageBlockFunction } from "../blocks-renderer"; import { PageBlockFunction } from "../blocks-renderer";
import { components } from "../posts/post"; import inlineComponents, { richTextTemplates } from "../inline/inline-definitions";
export const Content: PageBlockFunction<PageBlocksContent> = ({ data }) => { export const Content: PageBlockFunction<PageBlocksContent> = ({ data }) => {
return ( return (
@@ -19,7 +19,7 @@ export const Content: PageBlockFunction<PageBlocksContent> = ({ data }) => {
size="large" size="large"
width="medium" width="medium"
> >
<TinaMarkdown components={ components } content={ data.body } /> <TinaMarkdown components={ inlineComponents } content={ data.body } />
</Container> </Container>
</Section> </Section>
); );
@@ -40,69 +40,7 @@ export const contentBlockSchema: Template = {
type: "rich-text", type: "rich-text",
label: "Body", label: "Body",
name: "body", name: "body",
templates: [ templates: richTextTemplates,
{
name: "DateTime",
label: "Date & Time",
inline: true,
fields: [
{
name: "format",
label: "Format",
type: "string",
options: ["utc", "iso", "local"]
}
]
},
{
name: "BlockQuote",
label: "Block Quote",
fields: [
{
name: "children",
label: "Quote",
type: "rich-text"
},
{
name: "authorName",
label: "Author",
type: "string"
}
]
},
{
name: "NewsletterSignup",
label: "Newsletter Sign Up",
fields: [
{
name: "children",
label: "CTA",
type: "rich-text"
},
{
name: "placeholder",
label: "Placeholder",
type: "string"
},
{
name: "buttonText",
label: "Button Text",
type: "string"
},
{
name: "disclaimer",
label: "Disclaimer",
type: "rich-text"
}
],
ui: {
defaultItem: {
placeholder: "Enter your email",
buttonText: "Notify Me"
}
}
}
],
isBody: true isBody: true
}, },
{ {

View File

@@ -9,17 +9,6 @@ import { tinaField } from "tinacms/dist/react";
import { PageBlockFunction } from "../blocks-renderer"; import { PageBlockFunction } from "../blocks-renderer";
export const Hero: PageBlockFunction<PageBlocksHero> = ({ data }) => { export const Hero: PageBlockFunction<PageBlocksHero> = ({ data }) => {
const headlineColorClasses = {
blue: "from-blue-400 to-blue-600",
teal: "from-teal-400 to-teal-600",
green: "from-green-400 to-green-600",
red: "from-red-400 to-red-600",
pink: "from-pink-400 to-pink-600",
purple: "from-purple-400 to-purple-600",
orange: "from-orange-300 to-orange-600",
yellow: "from-yellow-400 to-yellow-600"
};
return ( return (
<Section color={ data.color }> <Section color={ data.color }>
<Container <Container

View File

@@ -0,0 +1,34 @@
import { TinaMarkdown, TinaMarkdownContent } from "tinacms/dist/rich-text";
import { RichTextTemplate } from "@tinacms/schema-tools";
export interface BlockQuoteProps {
children: TinaMarkdownContent;
authorName: string;
}
const BlockQuote = (props: BlockQuoteProps) => (
<div>
<blockquote>
<TinaMarkdown content={ props.children } />
{ props.authorName }
</blockquote>
</div>);
export const blockQuoteSchema: RichTextTemplate = {
name: "BlockQuote",
label: "Block Quote",
fields: [
{
name: "children",
label: "Quote",
type: "rich-text"
},
{
name: "authorName",
label: "Author",
type: "string"
}
]
};
export default BlockQuote;

View File

@@ -0,0 +1,40 @@
import React from "react";
import format from "date-fns/format";
import { Template } from "tinacms";
import { RichTextTemplate } from "@tinacms/schema-tools";
export interface DateTimeProps {
format?: string;
}
const DateTime = (props: DateTimeProps) => {
const dt = React.useMemo(() => {
return new Date();
}, []);
switch (props.format) {
case "iso":
return <span>{ format(dt, "yyyy-MM-dd") }</span>;
case "utc":
return <span>{ format(dt, "eee, dd MMM yyyy HH:mm:ss OOOO") }</span>;
case "local":
return <span>{ format(dt, "P") }</span>;
default:
return <span>{ format(dt, "P") }</span>;
}
};
export const dateTimeSchema: RichTextTemplate = {
name: "DateTime",
label: "Date & Time",
inline: true,
fields: [
{
name: "format",
label: "Format",
type: "string",
options: ["utc", "iso", "local"]
}
] };
export default DateTime;

View File

@@ -0,0 +1,48 @@
import { TinaMarkdown, TinaMarkdownContent } from "tinacms/dist/rich-text";
import { Template } from "tinacms";
import { anchoringSchema } from "../util/anchoring";
import { RichTextTemplate } from "@tinacms/schema-tools";
export interface ImageProps {
children: TinaMarkdownContent;
size: "small" | "medium" | "large";
imageUrl: string,
decorations: string,
position: "left" | "middle" | "right"
}
const Image = (props: ImageProps) => (
<div>
<img src={ props.imageUrl }/>
</div>);
export const imageSchema: RichTextTemplate = {
name: "image",
label: "Image",
inline: true,
fields: [
{
name: "size",
label: "Size",
type: "string",
options: ["small", "medium", "large"]
},
{
name: "position",
label: "Position",
type: "string",
options: ["left", "middle", "right"]
},
{
name: "imageUrl",
label: "Image",
type: "image"
},
{
name: "decorations",
label: "Decorations",
type: "string"
}
] };
export default Image;

View File

@@ -0,0 +1,35 @@
import { Components } from "tinacms/dist/rich-text";
import BlockQuote, { BlockQuoteProps, blockQuoteSchema } from "./block-quote";
import DateTime, { DateTimeProps, dateTimeSchema } from "./date-time";
import NewsletterSignup, { NewsletterSignupProps, newsletterSignupSchema } from "./newsletter-signup";
import { Prism } from "tinacms/dist/rich-text/prism";
import React from "react";
import Image, { ImageProps, imageSchema } from "./image";
import { RichTextTemplate } from "@tinacms/schema-tools";
const inlineComponents: Components<{
BlockQuote: BlockQuoteProps;
DateTime: DateTimeProps;
NewsletterSignup: NewsletterSignupProps;
Image: ImageProps;
}> = {
code_block: (props) => <Prism { ...props } />,
BlockQuote,
DateTime,
NewsletterSignup,
img: (props) => (
<span className="flex items-center justify-center">
<img src={ props.url } alt={ props.alt } />
</span>
),
Image
};
export const richTextTemplates: RichTextTemplate[] = [
dateTimeSchema,
blockQuoteSchema,
newsletterSignupSchema,
imageSchema
];
export default inlineComponents;

View File

@@ -0,0 +1,83 @@
import { TinaMarkdown, TinaMarkdownContent } from "tinacms/dist/rich-text";
import React from "react";
import format from "date-fns/format";
import { RichTextTemplate } from "@tinacms/schema-tools";
export interface NewsletterSignupProps {
placeholder: string;
buttonText: string;
children: TinaMarkdownContent;
disclaimer?: TinaMarkdownContent;
}
const NewsletterSignup = (props: NewsletterSignupProps) => (
<div className="bg-white">
<div className="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
<div className="">
<TinaMarkdown content={ props.children } />
</div>
<div className="mt-8 ">
<form className="sm:flex">
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
id="email-address"
name="email-address"
type="email"
autoComplete="email"
required
className="w-full px-5 py-3 border border-gray-300 shadow-sm placeholder-gray-400 focus:ring-1 focus:ring-teal-500 focus:border-teal-500 sm:max-w-xs rounded-md"
placeholder={ props.placeholder }
/>
<div className="mt-3 rounded-md shadow sm:mt-0 sm:ml-3 sm:flex-shrink-0">
<button
type="submit"
className="w-full flex items-center justify-center py-3 px-5 border border-transparent text-base font-medium rounded-md text-white bg-teal-600 hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-teal-500"
>
{ props.buttonText }
</button>
</div>
</form>
<div className="mt-3 text-sm text-gray-500">
{ props.disclaimer && <TinaMarkdown content={ props.disclaimer } /> }
</div>
</div>
</div>
</div>
);
export const newsletterSignupSchema: RichTextTemplate = {
name: "NewsletterSignup",
label: "Newsletter Sign Up",
fields: [
{
name: "children",
label: "CTA",
type: "rich-text"
},
{
name: "placeholder",
label: "Placeholder",
type: "string"
},
{
name: "buttonText",
label: "Button Text",
type: "string"
},
{
name: "disclaimer",
label: "Disclaimer",
type: "rich-text"
}
],
ui: {
defaultItem: {
placeholder: "Enter your email",
buttonText: "Notify Me"
}
}
};
export default NewsletterSignup;

View File

@@ -16,100 +16,9 @@ import { Container } from "../util/container";
import { Section } from "../util/section"; import { Section } from "../util/section";
import format from "date-fns/format"; import format from "date-fns/format";
import { TinaMarkdown } from "tinacms/dist/rich-text"; import { TinaMarkdown } from "tinacms/dist/rich-text";
import { Prism } from "tinacms/dist/rich-text/prism";
import type { TinaMarkdownContent, Components } from "tinacms/dist/rich-text";
import { PostType } from "../../pages/posts/[filename]"; import { PostType } from "../../pages/posts/[filename]";
import { tinaField } from "tinacms/dist/react"; import { tinaField } from "tinacms/dist/react";
import inlineComponents from "../inline/inline-definitions";
export const components: Components<{
BlockQuote: {
children: TinaMarkdownContent;
authorName: string;
};
DateTime: {
format?: string;
};
NewsletterSignup: {
placeholder: string;
buttonText: string;
children: TinaMarkdownContent;
disclaimer?: TinaMarkdownContent;
};
}> = {
code_block: (props) => <Prism { ...props } />,
BlockQuote: (props: {
children: TinaMarkdownContent;
authorName: string;
}) => {
return (
<div>
<blockquote>
<TinaMarkdown content={ props.children } />
{ props.authorName }
</blockquote>
</div>
);
},
DateTime: (props) => {
const dt = React.useMemo(() => {
return new Date();
}, []);
switch (props.format) {
case "iso":
return <span>{ format(dt, "yyyy-MM-dd") }</span>;
case "utc":
return <span>{ format(dt, "eee, dd MMM yyyy HH:mm:ss OOOO") }</span>;
case "local":
return <span>{ format(dt, "P") }</span>;
default:
return <span>{ format(dt, "P") }</span>;
}
},
NewsletterSignup: (props) => {
return (
<div className="bg-white">
<div className="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
<div className="">
<TinaMarkdown content={ props.children } />
</div>
<div className="mt-8 ">
<form className="sm:flex">
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
id="email-address"
name="email-address"
type="email"
autoComplete="email"
required
className="w-full px-5 py-3 border border-gray-300 shadow-sm placeholder-gray-400 focus:ring-1 focus:ring-teal-500 focus:border-teal-500 sm:max-w-xs rounded-md"
placeholder={ props.placeholder }
/>
<div className="mt-3 rounded-md shadow sm:mt-0 sm:ml-3 sm:flex-shrink-0">
<button
type="submit"
className="w-full flex items-center justify-center py-3 px-5 border border-transparent text-base font-medium rounded-md text-white bg-teal-600 hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-teal-500"
>
{ props.buttonText }
</button>
</div>
</form>
<div className="mt-3 text-sm text-gray-500">
{ props.disclaimer && <TinaMarkdown content={ props.disclaimer } /> }
</div>
</div>
</div>
</div>
);
},
img: (props) => (
<span className="flex items-center justify-center">
<img src={ props.url } alt={ props.alt } />
</span>
)
};
export const Post = (props: PostType) => { export const Post = (props: PostType) => {
const date = new Date(props.date); const date = new Date(props.date);
@@ -188,7 +97,7 @@ export const Post = (props: PostType) => {
data-tina-field={ tinaField(props, "_body") } data-tina-field={ tinaField(props, "_body") }
className="prose dark:prose-dark w-full max-w-none" className="prose dark:prose-dark w-full max-w-none"
> >
<TinaMarkdown components={ components } content={ props._body } /> <TinaMarkdown components={ inlineComponents } content={ props._body } />
</div> </div>
</Container> </Container>
</Section> </Section>

View File

@@ -82,6 +82,10 @@ blocks:
via les réseaux sociaux** ! via les réseaux sociaux** !
color: default color: default
_template: content _template: content
url: aboutt
--- ---

View File

@@ -66,6 +66,7 @@ blocks:
author: Phil Karlton author: Phil Karlton
color: primary color: primary
_template: testimonial _template: testimonial
url: home
--- ---
@@ -86,5 +87,6 @@ blocks:

View File

@@ -6,6 +6,7 @@ import { testimonialBlockSchema } from "../components/blocks/testimonial";
import { carouselBlockSchema } from "../components/blocks/carousel"; import { carouselBlockSchema } from "../components/blocks/carousel";
import { headerSchema } from "../components/layout/header"; import { headerSchema } from "../components/layout/header";
import { footerSchema } from "../components/layout/footer/footer"; import { footerSchema } from "../components/layout/footer/footer";
import { richTextTemplates } from "../components/inline/inline-definitions";
const config = defineConfig({ const config = defineConfig({
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID!, clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID!,
@@ -79,69 +80,7 @@ const config = defineConfig({
type: "rich-text", type: "rich-text",
label: "Body", label: "Body",
name: "_body", name: "_body",
templates: [ templates: richTextTemplates,
{
name: "DateTime",
label: "Date & Time",
inline: true,
fields: [
{
name: "format",
label: "Format",
type: "string",
options: ["utc", "iso", "local"]
}
]
},
{
name: "BlockQuote",
label: "Block Quote",
fields: [
{
name: "children",
label: "Quote",
type: "rich-text"
},
{
name: "authorName",
label: "Author",
type: "string"
}
]
},
{
name: "NewsletterSignup",
label: "Newsletter Sign Up",
fields: [
{
name: "children",
label: "CTA",
type: "rich-text"
},
{
name: "placeholder",
label: "Placeholder",
type: "string"
},
{
name: "buttonText",
label: "Button Text",
type: "string"
},
{
name: "disclaimer",
label: "Disclaimer",
type: "rich-text"
}
],
ui: {
defaultItem: {
placeholder: "Enter your email",
buttonText: "Notify Me"
}
}
}
],
isBody: true isBody: true
} }
] ]
@@ -185,14 +124,12 @@ const config = defineConfig({
path: "content/pages", path: "content/pages",
format: "mdx", format: "mdx",
ui: { ui: {
router: ({ document }) => { router: ({ document, collection }) => {
if (document._sys.filename === "home") { if (document._sys.filename === "home") {
return "/"; return "/";
} }
if (document._sys.filename === "about") {
return "/about"; return `/${ document._sys.filename }`;
}
return undefined;
} }
}, },
fields: [ fields: [

File diff suppressed because one or more lines are too long