Skip to content

blockWithModalPluginConstructor

As we saw, the RichTextExt can be extended using a plugin system.

The blockPluginConstructor helper is meant to create an advanced plugin, which needs parameters configured through a modal interface.

It accepts a BlockWithModalPlugin object:

type BlockPluginConstructor = (
blockPlugin: BlockWithModalPlugin
) => RichTextPlugin
interface BlockWithModalPlugin {
name: string
isInline?: boolean
itemName?: string
label?: string
hotKey?: string
render: (props: RenderElementProps) => JSX.Element
renderItem?: (props: RenderElementProps) => JSX.Element
icon: React.ReactElement
// highlight-next-line
pluginCustomFields: Array<types.ISideEditPropPage | types.ISideGroup>
// highlight-next-line
getDefaultProps?: () => Props
// highlight-next-line
renderAdmin?: (props: RenderElementProps) => JSX.Element
// highlight-next-line
renderItemAdmin?: (props: RenderElementProps) => JSX.Element
}

As you can see, it’s like a BlockPlugin, but for the highlighted props:

  • pluginCustomFields: the array of custom fields the plugin needs. The interface is the same used for sidebar controls of a brick. See SideEditProps.
  • getDefaultProps: function that returns the default values for the custom fields.
  • renderAdmin: what should be rendered on the Admin interface (sometimes it may be useful to render something different from the frontend in the Admin interface)
  • renderItemAdmin: the renderItem function to render an item on the Admin interface.

Usage example

Here’s the code for a custom “stock quote” plugin, created using the blockPluginConstructor:

import React from 'react'
import { MdLooksOne } from 'react-icons/md'
import { blockPluginConstructor } from 'react-bricks/frontend' // or 'react-bricks/rsc
const plugin = blockWithModalPluginConstructor({
name: 'stockQuote',
label: 'Stock quote',
isInline: true,
hotKey: 'mod+k',
icon: <FaChartLine />,
render: (props) => (
<span>
{props.children} {renderStockData(props.element?.data)}
// renderStockData renders the stock value, not relevant here
</span>
),
renderAdmin: (props) => (
<strong className="border-b border-dashed border-blue-500">
{props.children || 'STOCK'} {renderStockData(props.element?.data)}
</strong>
),
getDefaultProps: () => {
return {
stockCode: {},
type: 'c',
}
},
pluginCustomFields: [
{
name: 'stockCode',
label: 'Stock code',
type: types.SideEditPropType.Autocomplete,
autocompleteOptions: {
getOptions: async (input) => {
if (!input) {
return []
}
return fetch(
`https://finnhub.io/api/v1/search?q=${input}&token=cmpac5hr01qg7bbo20r0cmpac5hr01qg7bbo20rg`,
{
next: {
revalidate: 10,
},
}
)
.then((res) => res.json())
.then((data) => data.result)
},
getKey: (option) => option?.symbol,
getLabel: (option) =>
option?.displaySymbol
? `${option?.description} (${option?.displaySymbol})`
: '',
getNoOptionsMessage: (input) => `No stocks for "${input}"`,
debounceTime: 200,
},
},
{
name: 'type',
label: 'Data Type',
type: types.SideEditPropType.Select,
selectOptions: {
display: types.OptionsDisplay.Select,
options: [
{ label: 'Value', value: 'c' },
{ label: 'Daily change', value: 'd' },
{ label: 'Daily change %', value: 'dp' },
],
},
},
],
})
export default plugin