Skip to content

Latest commit

 

History

History

pt-react

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

@portabletext-typed/react

NPM Downloads GitHub commit activity (branch) GitHub Repo stars GitHub contributors GitHub issues by-label Minified Size License

GitHub Sponsors

@portabletext/react with typed arguments

Page Contents

Install

npm install @portabletext/react @portabletext-typed/react

Usage

After using @sanity-typed/types and @sanity-typed/client and you have typed blocks, use PortableText from this library as you would from @portabletext/react to get fully typed arguments!

post.ts:

// import { defineArrayMember, defineField, defineType } from "sanity";
import {
  defineArrayMember,
  defineField,
  defineType,
} from "@sanity-typed/types";

/** No changes using defineType, defineField, and defineArrayMember */
export const post = defineType({
  name: "post",
  type: "document",
  title: "Post",
  fields: [
    defineField({
      name: "content",
      type: "array",
      title: "Content",
      validation: (Rule) => Rule.required(),
      of: [
        defineArrayMember({ type: "image" }),
        defineArrayMember({
          type: "block",
          of: [defineArrayMember({ type: "file" })],
          styles: [
            { title: "Normal", value: "normal" as const },
            { title: "Foo", value: "foo" as const },
          ],
          lists: [
            { title: "Bullet", value: "bullet" as const },
            { title: "Bar", value: "bar" as const },
          ],
          marks: {
            decorators: [
              { title: "Strong", value: "strong" as const },
              { title: "Baz", value: "baz" as const },
            ],
            annotations: [
              defineArrayMember({
                name: "link",
                type: "object",
                title: "Link",
                fields: [
                  defineField({
                    name: "href",
                    type: "string",
                    validation: (Rule) => Rule.required(),
                  }),
                ],
              }),
              defineArrayMember({
                name: "qux",
                type: "object",
                title: "Qux",
                fields: [
                  defineField({
                    name: "value",
                    type: "string",
                    validation: (Rule) => Rule.required(),
                  }),
                ],
              }),
            ],
          },
        }),
      ],
    }),
  ],
});

with-portabletext-react.tsx:

import type { InferGetStaticPropsType } from "next";
import { Fragment } from "react";

// import { PortableText } from "@portabletext/react";
import { PortableText } from "@portabletext-typed/react";

import { client } from "../sanity/client";

export const getStaticProps = async () => ({
  props: {
    posts: await client.fetch('*[_type=="post"]'),
  },
});

const Index = ({ posts }: InferGetStaticPropsType<typeof getStaticProps>) => (
  <>
    <h1>Posts</h1>
    {posts.map(({ _id, content }) => (
      <Fragment key={_id}>
        <h2>Post</h2>
        <PortableText
          value={content}
          components={{
            types: {
              // From Siblings
              image: ({ isInline, value }) => (
                <div>
                  typeof {isInline} === false,
                  <br />
                  typeof {JSON.stringify(value)} === ImageValue,
                </div>
              ),
              // From Children
              file: ({ isInline, value }) => (
                <span>
                  typeof {isInline} === true,
                  <span />
                  typeof {JSON.stringify(value)} === FileValue,
                </span>
              ),
            },
            block: {
              // Non-Default Styles
              foo: ({ children, value }) => (
                <div>
                  typeof {JSON.stringify(value)} === PortableTextBlock{"<"} ...
                  {">"} & {"{"} style: &quot;foo&quot; {"}"},
                  <span />
                  {children}
                </div>
              ),
            },
            list: {
              // Non-Default Lists
              bar: ({ children, value }) => (
                <ul>
                  <li>
                    typeof {JSON.stringify(value)} === ToolkitPortableTextList &
                    {"{"} listItem: &quot;bar&quot; {"}"},
                  </li>
                  {children}
                </ul>
              ),
            },
            listItem: {
              // Non-Default Lists
              bar: ({ children, value }) => (
                <li>
                  typeof {JSON.stringify(value)} === PortableTextBlock{"<"} ...
                  {">"} & {"{"} listItem: &quot;bar&quot; {"}"},
                  <span />
                  {children}
                </li>
              ),
            },
            marks: {
              // Non-Default Decorators
              baz: ({ children, markKey, markType, value }) => (
                <span>
                  typeof {value} === undefined,
                  <span />
                  typeof {markKey} === &quot;baz&quot;,
                  <span />
                  typeof {markType} === &quot;baz&quot;,
                  <span />
                  {children}
                </span>
              ),
              // Non-Default Annotations
              qux: ({ children, markKey, markType, value }) => (
                <span>
                  typeof {JSON.stringify(value)} === {"{"}
                  _key: string,
                  <span />
                  _type: &quot;qux&quot;,
                  <span />
                  value: typeof {value.value} === string,
                  {"}"},
                  <span />
                  typeof {markKey} === string,
                  <span />
                  typeof {markType} === &quot;qux&quot;,
                  <span />
                  {children}
                </span>
              ),
            },
          }}
        />
      </Fragment>
    ))}
  </>
);

export default Index;

Breaking Changes

1 to 2

Typescript version from 5.4.2 <= x <= 5.6.3

The supported Typescript version is now 5.4.2 <= x <= 5.6.3. Older versions are no longer supported and newer versions will be added as we validate it.