svelte-portabletext
svelte-portabletext copied to clipboard
Passing non-Sanity props to custom components
In the react docs, it seems possible to render custom components with external props, as seen here in the docs :
const components = {
types: {
code: props => (
<pre data-language={props.node.language}>
<code>{props.node.code}</code>
</pre>
)
}
}
However, in the svelte implementation, the docs suggest that we just pass the name of the Svelte component in the serializer:
<script>
let page={
interviewName: "Ryan"
}
</script>
<PortableText
value={value}
components={{
types: {
image: ImageBlock,
doubleImage: DoubleImage,
story: Story,
interview: <InterviewItem name={page.interviewName} />, // What I'd like to do.
},
marks: {
link: Link,
},
block:{
normal: ArticleText,
}
}}
/>
I'd like to be able to pass external props (in this case from the field's parent document) into a PortableText block. So far, I'm able to get by with Svelte stores, but it feels more like a workaround.
Running into the exact same "problem"! +1
Actually @rscheuer , I just found out this is possible by first looking through the source code, and then the documentation.
See this reference: https://github.com/portabletext/svelte-portabletext/blob/35511cf7043aeb529bad8d2080c7e26b4241bca8/README.md#customizing-rendering
Here's my code:
<script lang="ts">
import { PortableText } from '@portabletext/svelte';
import type { InputValue } from '@portabletext/svelte/ptTypes';
import Block from './Blocks/Block.svelte';
import BlockImage from './Blocks/BlockImage.svelte';
import BlockHeadings from './Blocks/BlockHeadings.svelte';
import AnnotationLinkExternal from './Annotations/AnnotationLinkExternal.svelte';
import AnnotationLinkInternal from './Annotations/AnnotationLinkInternal.svelte';
import AnnotationLinkEmail from './Annotations/AnnotationLinkEmail.svelte';
import NormalListItem from './ListItem/NormalListItem.svelte';
export let blocks: InputValue;
export let isBlog = false;
</script>
<div {...$$restProps}>
<PortableText
context={{ isBlog }}
components={{
types: {
blockImage: BlockImage,
},
marks: {
annotationLinkExternal: AnnotationLinkExternal,
annotationLinkInternal: AnnotationLinkInternal,
annotationLinkEmail: AnnotationLinkEmail,
},
listItem: {
normal: NormalListItem,
},
block: {
normal: Block,
h2: BlockHeadings,
h3: BlockHeadings,
h4: BlockHeadings,
},
}}
value={blocks}
/>
</div>
Then in the Block.svelte, you can access portableText.
<script lang="ts">
import type { BlockComponentProps } from '@portabletext/svelte';
export let portableText: BlockComponentProps<{ _key: string; style: string }>;
$: console.log(portableText,global.context.isBlog);
</script>
<p class="relative mb-3 text-lg font-normal leading-7"><slot /></p>