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
: therenderItem
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