Skip to content

Commit

Permalink
docs: add examples
Browse files Browse the repository at this point in the history
  • Loading branch information
angeloashmore committed Jul 30, 2021
1 parent 0ba98f0 commit 4984832
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 0 deletions.
Empty file removed examples/.gitkeep
Empty file.
3 changes: 3 additions & 0 deletions examples/custom-slicezone-props/README.md
@@ -0,0 +1,3 @@
# Custom `SliceZone` Props

This example shows how to pass custom props to Slice Zone components. This is helpful when your Slice components require data not contained with a Slice. It can also be helpful if your Slice component was not written specifically to accept a Slice as a prop.
91 changes: 91 additions & 0 deletions examples/custom-slicezone-props/index.tsx
@@ -0,0 +1,91 @@
/* eslint-disable react/prop-types */
/* eslint-disable react/display-name */

import * as React from "react";
import {
SliceZone,
SliceComponentProps,
SliceZoneComponents,
} from "@prismicio/react";

import { Slices, HeroSlice, ExampleSliceZone } from "./types";

// This is the contents of a Slice Zone field.
// Normally, this would be accessed at `document.data.body`, where `document`
// is a Prismic document and `body` is a Slice Zone.
const slices: ExampleSliceZone = [
{
slice_type: "hero",
slice_label: null,
primary: {
heading: "Lorem ipsum",
buttonText: "Lorem ipsum",
},
items: [],
},
{
slice_type: "call_to_action",
slice_label: null,
primary: {
text: "Lorem ipsum dolor sit amet",
},
items: [],
},
];

// This React component is rendered for Hero Slices.
// It accepts a Slice object as a prop.
const HeroSlice = ({ slice }: SliceComponentProps<HeroSlice>) => {
return (
<section>
<h1>{slice.primary.heading}</h1>
<button>{slice.primary.buttonText}</button>
</section>
);
};

// This React component is rendered for Call To Action Slices.
//
// It does **not** accept a Slice object as a prop.
//
// The SliceZome component will need to extract the content from within the
// Slice object before rendering.
const CallToActionSlice = ({
text,
disclaimer,
}: {
text: string;
disclaimer: string;
}) => {
return (
<section>
<p>{text}</p>
<small>{disclaimer}</small>
</section>
);
};

// This object contains a component for each type of Slice that can be rendered
// by `<SliceZone>`.
//
// It is important to define this object *outside* the React component that
// uses `<SliceZone>`. This ensures the React app will not re-render
// unnecessarily.
const components: SliceZoneComponents<Slices> = {
// Since HeroSlice accepts a `slice` prop, we can pass the component directly.
hero: HeroSlice,

// Since CallToActionSLice does not accept a `slice` prop, we must pass the
// props it expects using content from within the Slice object.
//
// We can also pass arbitrary data as well, such as the `disclaimer` prop.
call_to_action: ({ slice }) => (
<CallToActionSlice text={slice.primary.text} disclaimer="foo" />
),
};

// We render the Slice Zone using the `<SliceZone>` component by passing the
// list of Slices and component map.
export const App = (): JSX.Element => {
return <SliceZone slices={slices} components={components} />;
};
9 changes: 9 additions & 0 deletions examples/custom-slicezone-props/package.json
@@ -0,0 +1,9 @@
{
"type": "module",
"dependencies": {
"@prismicio/react": "alpha"
},
"devDependencies": {
"@prismicio/types": "^0.1.4"
}
}
20 changes: 20 additions & 0 deletions examples/custom-slicezone-props/types.ts
@@ -0,0 +1,20 @@
import * as prismicT from "@prismicio/types";

export type HeroSlice = prismicT.Slice<
"hero",
{
heading: prismicT.KeyTextField;
buttonText: prismicT.KeyTextField;
}
>;

export type CallToActionSlice = prismicT.Slice<
"call_to_action",
{
text: prismicT.KeyTextField;
}
>;

export type Slices = HeroSlice | CallToActionSlice;

export type ExampleSliceZone = prismicT.SliceZone<Slices>;
3 changes: 3 additions & 0 deletions examples/router-link/README.md
@@ -0,0 +1,3 @@
# Router Link

This example shows how to use a router-specific Link component with `<PrismicLink>`. This is helpful when links within your app need to use a special component for internal Links. `react-router-dom`, for example, requires using its `<Link>` component.
26 changes: 26 additions & 0 deletions examples/router-link/index.tsx
@@ -0,0 +1,26 @@
import * as React from "react";
import * as prismicT from "@prismicio/types";
import { PrismicLink, LinkProps } from "@prismicio/react";
import { Link } from "react-router-dom";

// This is an example Link field value. It contains a URL internal to the app.
const field: prismicT.LinkField = {
link_type: prismicT.LinkType.Web,
url: "/internal-url",
};

// This React component acts as a "shim" to convert the `href` prop provided by
// `<PrismicLink>` to the `to` prop required by react-router-dom's `<Link>`.
const LinkShim = ({ href, ...props }: LinkProps) => {
return <Link to={href} {...props} />;
};

// We render the Link field using `<PrismicLink>`. Since the field contains an
// internal URL, react-router-dom's `<Link>` component will render.
export const App = (): JSX.Element => {
return (
<main>
<PrismicLink field={field} internalComponent={LinkShim} />
</main>
);
};
11 changes: 11 additions & 0 deletions examples/router-link/package.json
@@ -0,0 +1,11 @@
{
"type": "module",
"dependencies": {
"@prismicio/react": "alpha",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"@prismicio/types": "^0.1.4",
"@types/react-router-dom": "^5.1.8"
}
}
20 changes: 20 additions & 0 deletions examples/router-link/types.ts
@@ -0,0 +1,20 @@
import * as prismicT from "@prismicio/types";

export type HeroSlice = prismicT.Slice<
"hero",
{
heading: prismicT.KeyTextField;
buttonText: prismicT.KeyTextField;
}
>;

export type CallToActionSlice = prismicT.Slice<
"call_to_action",
{
text: prismicT.KeyTextField;
}
>;

export type Slices = HeroSlice | CallToActionSlice;

export type ExampleSliceZone = prismicT.SliceZone<Slices>;
3 changes: 3 additions & 0 deletions examples/with-provider/README.md
@@ -0,0 +1,3 @@
# Custom `SliceZone` Props

This example shows how to pass custom props to Slice Zone components. This is helpful when your Slice components require data not contained with a Slice. It can also be helpful if your Slice component was not written specifically to accept a Slice as a prop.
77 changes: 77 additions & 0 deletions examples/with-provider/index.tsx
@@ -0,0 +1,77 @@
/* eslint-disable react/prop-types */
/* eslint-disable react/display-name */

import * as React from "react";
import * as prismicT from "@prismicio/types";
import {
PrismicProvider,
PrismicLink,
LinkProps,
JSXMapSerializer,
PrismicRichText,
} from "@prismicio/react";
import { Link } from "react-router-dom";

// This is an example Link field value. It contains a URL internal to the app.
const linkField: prismicT.LinkField = {
link_type: prismicT.LinkType.Web,
url: "/internal-url",
};

// This is an example Rich Text field value. It contains a "Heading 1" block.
const richTextField: prismicT.RichTextField = [
{
type: prismicT.RichTextNodeType.heading1,
text: "Lorem ipsum",
spans: [],
},
];

// This React component acts as a "shim" to convert the `href` prop provided by
// `<PrismicLink>` to the `to` prop required by react-router-dom's `<Link>`.
const LinkShim = ({ href, ...props }: LinkProps) => {
return <Link to={href} {...props} />;
};

// This React componetn is used for headings. We will use it when rendering
// "Heading 1" blocks in Rich Text fields.
const Heading = ({ children }: { children: React.ReactNode }) => {
return <h1 className="heading">{children}</h1>;
};

// This object contains components used to render a Rich Text field.
//
// Here we configure PrismicRichText to render the `<Heading>` component for
// "Heading 1" blocks.
const richTextComponents: JSXMapSerializer = {
heading1: ({ children }) => <Heading>{children}</Heading>,
};

// This component acts as the main part of the example app. We use
// `<PrismicRichText>` and `<PrismicLink>` with example fields.
//
// Note that we do not need to pass configuration since it is provided to
// `<PrismicProvider>` higher in the tree (see the "App" component below).
const MyComponent = () => {
return (
<main>
<PrismicRichText field={richTextField} />
<PrismicLink field={linkField} />
</main>
);
};

// This React component acts as the app, including the top-level
// `<PrismicProvider>`. We pass global Prismic configuration to the provider at
// this level. By doing so, it becomes available automatically to all Prismic
// components lower in the tree.
export const App = (): JSX.Element => {
return (
<PrismicProvider
internalLinkComponent={LinkShim}
richTextComponents={richTextComponents}
>
<MyComponent />
</PrismicProvider>
);
};
11 changes: 11 additions & 0 deletions examples/with-provider/package.json
@@ -0,0 +1,11 @@
{
"type": "module",
"dependencies": {
"@prismicio/react": "alpha",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"@prismicio/types": "^0.1.4",
"@types/react-router-dom": "^5.1.8"
}
}
20 changes: 20 additions & 0 deletions examples/with-provider/types.ts
@@ -0,0 +1,20 @@
import * as prismicT from "@prismicio/types";

export type HeroSlice = prismicT.Slice<
"hero",
{
heading: prismicT.KeyTextField;
buttonText: prismicT.KeyTextField;
}
>;

export type CallToActionSlice = prismicT.Slice<
"call_to_action",
{
text: prismicT.KeyTextField;
}
>;

export type Slices = HeroSlice | CallToActionSlice;

export type ExampleSliceZone = prismicT.SliceZone<Slices>;
2 changes: 2 additions & 0 deletions src/index.ts
Expand Up @@ -40,3 +40,5 @@ export {
usePrismicDocumentsByType,
useSinglePrismicDocument,
} from "./hooks";

export type { JSXMapSerializer, JSXFunctionSerializer } from "./types";

0 comments on commit 4984832

Please sign in to comment.