UNPKG

@portabletext/plugin-one-line

Version:

🤏 Restricts the Portable Text Editor to a single line

104 lines (103 loc) 3.15 kB
import { useEditor } from "@portabletext/editor"; import { defineBehavior, execute, raise } from "@portabletext/editor/behaviors"; import * as selectors from "@portabletext/editor/selectors"; import * as utils from "@portabletext/editor/utils"; import { useEffect } from "react"; const oneLineBehaviors = [ /** * Hitting Enter on an expanded selection should just delete that selection * without causing a line break. */ defineBehavior({ on: "insert.break", guard: ({ snapshot }) => snapshot.context.selection && selectors.isSelectionExpanded(snapshot) ? { selection: snapshot.context.selection } : !1, actions: [(_, { selection }) => [execute({ type: "delete", at: selection })]] }), /** * All other cases of `insert.break` should be aborted. */ defineBehavior({ on: "insert.break", actions: [] }), /** * `insert.block` `before` or `after` is not allowed in a one-line editor. */ defineBehavior({ on: "insert.block", guard: ({ event }) => event.placement === "before" || event.placement === "after", actions: [] }), /** * An ordinary `insert.block` is acceptable if it's a text block. In that * case it will get merged into the existing text block. */ defineBehavior({ on: "insert.block", guard: ({ snapshot, event }) => !(!selectors.getFocusTextBlock(snapshot) || !utils.isTextBlock(snapshot.context, event.block)), actions: [ ({ event }) => [ execute({ type: "insert.block", block: event.block, placement: "auto", select: "end" }) ] ] }), /** * Fallback Behavior to avoid `insert.block` in case the Behaviors above all * end up with a falsy guard. */ defineBehavior({ on: "insert.block", actions: [] }), /** * If multiple blocks are inserted, then the non-text blocks are filtered out * and the text blocks are merged into one block */ defineBehavior({ on: "insert.blocks", guard: ({ snapshot, event }) => { const textBlocks = event.blocks.filter( (block) => utils.isTextBlock(snapshot.context, block) ); return textBlocks.length === 0 ? !1 : textBlocks.reduce((targetBlock, incomingBlock) => utils.mergeTextBlocks({ context: snapshot.context, targetBlock, incomingBlock })); }, actions: [ // `insert.block` is raised so the Behavior above can handle the // insertion (_, block) => [raise({ type: "insert.block", block, placement: "auto" })] ] }), /** * Fallback Behavior to avoid `insert.blocks` in case the Behavior above * ends up with a falsy guard. */ defineBehavior({ on: "insert.blocks", actions: [] }) ]; function OneLinePlugin() { const editor = useEditor(); return useEffect(() => { const unregisterBehaviors = oneLineBehaviors.map( (behavior) => editor.registerBehavior({ behavior }) ); return () => { for (const unregisterBehavior of unregisterBehaviors) unregisterBehavior(); }; }, [editor]), null; } export { OneLinePlugin }; //# sourceMappingURL=index.js.map