THIS IS A PROOF OF CONCEPT, CONSIDER IT WORK IN PROGRESS.
Sanity Iframe Preview component.
- Use IFramePreview component in studio structure view.
- Configure with render-app preview-url
- Use sanity-iframe-api or sanity-iframe-api-react in the render-app.
- Configure with groq-query (or just use document directly from Sanity Studio as is)
- Enjoy live-updated preview in Studio, with queries executed by the Studio on behalf of the render app.
Implements an iframe.postMessage protocol that allows the target iframe to specify a GROQ-query for the studio to execute. The result of the query will be sent to the iframe whenever the query revision matches the studio revision.
- Generic type param for document
- Tests
- Better error messages & error handling
- jsdocs
- Better docs
Install as a dependency in your Sanity Studio:
npm install @snorreeb/sanity-plugin-iframe-preview
Use in your structure code:
import { IFramePreview } from '@snorreeb/sanity-plugin-iframe-preview'
S.view
.component(IFramePreview)
.options({
url: (doc: SanityDocument) => 'iframe-url', // (doc) => (string | Promise<string>)
mapDocument: (doc: SanityDocument) => ({ _id: doc._id }),
desktopMinWidth: 900,
})
.icon(EyeIcon)
.id("preview")
.title("Preview")
Read IFramePreviewBasicProps jsdocs for config details.
To enable iframe preview directly in schema definition, you can do something along the lines of this:
// someSchema.tsx
export const someSchema = {
type: 'document',
title: 'Some doc',
previewComponent: IFramePreview,
fields: [/** omitted */]
}
// given sanity.json with structure implemented like so
{
"name": "part:@sanity/desk-tool/structure",
"path": "./structure.ts"
}
// structure.ts
export function editAndPreviewViews<T>(previewComponent: IPreviewComponent<T>) {
return [
S.view.form().title("Edit").icon(EditIcon),
S.view
.component(previewComponent)
.icon(EyeIcon)
.id("preview")
.title("Preview"),
];
}
// https://www.sanity.io/docs/structure-builder-reference#97e44ce262c9
export const getDefaultDocumentNode = ({ schemaType }: any) => {
const matchingTypes = S.documentTypeListItems()
.filter((listItem: any) => listItem.spec.schemaType.name === schemaType)
.map((listItem: any) => {
const previewComponent = listItem.spec.schemaType.previewComponent;
if (previewComponent) {
return S.document().views(editAndPreviewViews(previewComponent));
}
return S.document();
});
return matchingTypes.length ? matchingTypes[0] : S.document();
};
export default () => S.list().items(/* your structure */)
Caveat: uses access to protected listItem.spec
feield; this might break in future Sanity releases.
sanipack
seems to be kinda particular about not building types.
Therefore, type are build separately and placed in /lib/types
.
npm run build
cd /path/to/my-studio
npm link sanity-plugin-iframe-preview-alpha