UNPKG

@gechiui/block-editor

Version:
109 lines (92 loc) 2.66 kB
/** * GeChiUI dependencies */ import { useRef } from '@gechiui/element'; import { useRefEffect } from '@gechiui/compose'; import { slice, toHTMLString } from '@gechiui/rich-text'; import { getBlockTransforms, findTransform } from '@gechiui/blocks'; import { useDispatch } from '@gechiui/data'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../store'; export function useInputRules( props ) { const { __unstableMarkLastChangeAsPersistent, __unstableMarkAutomaticChange, } = useDispatch( blockEditorStore ); const propsRef = useRef( props ); propsRef.current = props; return useRefEffect( ( element ) => { function inputRule() { const { value, onReplace } = propsRef.current; if ( ! onReplace ) { return; } const { start, text } = value; const characterBefore = text.slice( start - 1, start ); // The character right before the caret must be a plain space. if ( characterBefore !== ' ' ) { return; } const trimmedTextBefore = text.slice( 0, start ).trim(); const prefixTransforms = getBlockTransforms( 'from' ).filter( ( { type } ) => type === 'prefix' ); const transformation = findTransform( prefixTransforms, ( { prefix } ) => { return trimmedTextBefore === prefix; } ); if ( ! transformation ) { return; } const content = toHTMLString( { value: slice( value, start, text.length ), } ); const block = transformation.transform( content ); onReplace( [ block ] ); __unstableMarkAutomaticChange(); } function onInput( event ) { const { inputType, type } = event; const { value, onChange, __unstableAllowPrefixTransformations, formatTypes, } = propsRef.current; // Only run input rules when inserting text. if ( inputType !== 'insertText' && type !== 'compositionend' ) { return; } if ( __unstableAllowPrefixTransformations && inputRule ) { inputRule(); } const transformed = formatTypes.reduce( ( accumlator, { __unstableInputRule } ) => { if ( __unstableInputRule ) { accumlator = __unstableInputRule( accumlator ); } return accumlator; }, value ); if ( transformed !== value ) { __unstableMarkLastChangeAsPersistent(); onChange( { ...transformed, activeFormats: value.activeFormats, } ); __unstableMarkAutomaticChange(); } } element.addEventListener( 'input', onInput ); element.addEventListener( 'compositionend', onInput ); return () => { element.removeEventListener( 'input', onInput ); element.removeEventListener( 'compositionend', onInput ); }; }, [] ); }