import React, { useEffect, useMemo, useState } from 'react'; import type { ComponentType } from 'react'; import Icon from '../Icon'; import { EditorEvents, ToolbarEvents } from './constants'; import { StyledSeparator, StyledToolbar, StyledToolbarButton, } from './StyledToolbar'; import type { ToolbarButtonName } from './types'; import type { IconProps } from '../Icon'; import useRichTextEditorEvents from './hooks/useRichTextEditorEvents'; type ToolbarButtonProps = { icon: IconProps['icon']; onPress: () => void; testID?: string; selected: boolean; }; const ToolbarButton: ComponentType = ({ icon, onPress, testID, selected, }: ToolbarButtonProps) => ( ); interface ButtonConfig { icon: IconProps['icon']; eventName: ToolbarEvents; standalone?: boolean; } const buttonConfigs: Partial> = { bold: { icon: 'format-bold', eventName: ToolbarEvents.Bold, }, italic: { icon: 'format-italic', eventName: ToolbarEvents.Italic, }, underline: { icon: 'format-underlined', eventName: ToolbarEvents.Underline, }, bulletedList: { icon: 'format-list-bulleted', eventName: ToolbarEvents.BulletedList, standalone: true, }, numberedList: { icon: 'format-list-numbered', eventName: ToolbarEvents.NumberedList, standalone: true, }, headingOne: { icon: 'format-heading1', eventName: ToolbarEvents.HeadingOne, standalone: true, }, headingTwo: { icon: 'format-heading2', eventName: ToolbarEvents.HeadingTwo, standalone: true, }, }; const defaultButtons: ToolbarButtonName[] = [ 'bold', 'italic', 'underline', '|', 'bulletedList', 'numberedList', '|', 'headingOne', 'headingTwo', ]; export interface EditorToolbarProps { /** * List of buttons to display in toolbar */ buttons?: ToolbarButtonName[]; /** * Unique name used to communicate with webview, should be the same with the RichTextEditor component it used with */ name: string; /** * Testing ID of the component */ testID?: string; } const EditorToolbar = ({ name, buttons = defaultButtons, testID, }: EditorToolbarProps) => { const [show, setShow] = useState(false); const { emitEvent, subscribeToEvents } = useRichTextEditorEvents(name); const [toolbarButtonState, setToolbarButtonState] = useState< Record >({}); useEffect(() => { const removeFocusListener = subscribeToEvents( EditorEvents.EditorFocus, () => setShow(true) ); const removeBlurListener = subscribeToEvents(EditorEvents.EditorBlur, () => setShow(false) ); const removeEditorChangeListener = subscribeToEvents( EditorEvents.EditorChange, ({ toolbarState = {} }) => { setToolbarButtonState(toolbarState); } ); return () => { removeFocusListener(); removeBlurListener(); removeEditorChangeListener(); }; }, []); const toolbarButtons = useMemo( () => buttons.map((button, index) => { if (button === '|') { return ; } const config = buttonConfigs[button]; if (config) { return ( { emitEvent({ type: config.eventName, data: null, }); }} selected={toolbarButtonState[config.eventName]} /> ); } return null; }), [toolbarButtonState, buttons] ); if (show) { return {toolbarButtons}; } return null; }; export default EditorToolbar;