Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass currentBlock to CustomBlockComponent #53

Merged
merged 4 commits into from
Feb 19, 2021

Conversation

pyk
Copy link
Contributor

@pyk pyk commented Feb 16, 2021

Previously, I can't create a custom block component for image because I can't access the parent block of the image.

<NotionRenderer
    blockMap={notionBlocks ?? {}}
    customBlockComponents={{
        image: ({ blockValue }) => {
            // Image cannot be loaded because it need the parent and file id
            const src = defaultMapImageUrl(
                blockValue.properties.source[0][0]
            );
            const caption = blockValue.properties.caption?.[0][0];
            return (
                <figure>
                    <div>
                        <img src={src} alt={caption} />
                    </div>
                </figure>
            );
        },
    }}
/>

With this changes, now I can do the following:

<NotionRenderer
    blockMap={notionBlocks ?? {}}
    customBlockComponents={{
        // NOTE: currentBlock now passed to this custom component
        image: ({ block, blockValue }) => {
            const src = defaultMapImageUrl(
                blockValue.properties.source[0][0],
                block
            );
            const caption = blockValue.properties.caption?.[0][0];
            return (
                <figure>
                    <div>
                        <img src={src} alt={caption} />
                    </div>
                </figure>
            );
        },
    }}
/>

Now the image can be loaded correctly in CustomBlockComponent.

@pyk
Copy link
Contributor Author

pyk commented Feb 17, 2021

Update:

turns out I can pass block using blockValue:

/**
 * React Component to render Notion's image block
 */
export const NotionImage: FunctionComponent<
    CustomBlockComponentProps<"image">
> = ({ blockValue }) => { 
    // NOTE: like the following
    const block: BlockType = {
        // @ts-ignore
        value: {
            type: "image",
            ...blockValue,
        },
    };
    const notionImageUrl = defaultMapImageUrl(
        blockValue.properties.source[0][0],
        block
    );
   ...
};

So instead of passing block to CustomComponent, I changes the PR to pass blockMap instead.

It is useful for implementing custom numbered_list component.

For example:

/**
 * React Component to render Notion's numbered list block
 */
export const NotionNumberedList: FunctionComponent<
    CustomBlockComponentProps<"numbered_list">
> = ({ blockMap, blockValue, children }) => {
    // Get total number of elements in order to create custom classes for the latest
    // <ol> element
    const totalListElements = getTotalListMember(blockValue.id, blockMap);

    const wrapList = (content: React.ReactNode, start?: number) => {
        return (
            // Increase the margin for last element
            <ol
                start={start}
                className={`list-decimal text-fg-200 text-xl tracking-wide leading-normal list-outside pl-8 ${
                    start == totalListElements ? "mb-8" : "mb-4"
                }`}
            >
                {content}
            </ol>
        );
    };

    let output: JSX.Element | null = null;

    if (blockValue.content) {
        output = (
            <>
                {blockValue.properties && (
                    <li className={styles.listMarker}>
                        {notionRenderChildText()(blockValue.properties.title)}
                    </li>
                )}
                {wrapList(children)}
            </>
        );
    } else {
        output = blockValue.properties ? (
            <li className={styles.listMarker}>
                {notionRenderChildText()(blockValue.properties.title)}
            </li>
        ) : null;
    }

    const parentBlockType = blockMap[blockValue.parent_id].value.type;
    const isTopLevel = parentBlockType == "numbered_list" ? false : true;
    const start = getListNumber(blockValue.id, blockMap);

    return isTopLevel ? wrapList(output, start) : output;
};

@tobiaslins tobiaslins merged commit df95638 into splitbee:master Feb 19, 2021
@tobiaslins
Copy link
Member

Good addition, thanks!! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants