@portabletext/plugin-one-line
Version:
🤏 Restricts the Portable Text Editor to a single line
1 lines • 5.71 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/plugin.one-line.tsx"],"sourcesContent":["import {useEditor} from '@portabletext/editor'\nimport {defineBehavior, execute, raise} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport * as utils from '@portabletext/editor/utils'\nimport {useEffect} from 'react'\n\nconst oneLineBehaviors = [\n /**\n * Hitting Enter on an expanded selection should just delete that selection\n * without causing a line break.\n */\n defineBehavior({\n on: 'insert.break',\n guard: ({snapshot}) =>\n snapshot.context.selection && selectors.isSelectionExpanded(snapshot)\n ? {selection: snapshot.context.selection}\n : false,\n actions: [(_, {selection}) => [execute({type: 'delete', at: selection})]],\n }),\n /**\n * All other cases of `insert.break` should be aborted.\n */\n defineBehavior({\n on: 'insert.break',\n actions: [],\n }),\n /**\n * `insert.block` `before` or `after` is not allowed in a one-line editor.\n */\n defineBehavior({\n on: 'insert.block',\n guard: ({event}) =>\n event.placement === 'before' || event.placement === 'after',\n actions: [],\n }),\n /**\n * An ordinary `insert.block` is acceptable if it's a text block. In that\n * case it will get merged into the existing text block.\n */\n defineBehavior({\n on: 'insert.block',\n guard: ({snapshot, event}) => {\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n\n if (\n !focusTextBlock ||\n !utils.isTextBlock(snapshot.context, event.block)\n ) {\n return false\n }\n\n return true\n },\n actions: [\n ({event}) => [\n execute({\n type: 'insert.block',\n block: event.block,\n placement: 'auto',\n select: 'end',\n }),\n ],\n ],\n }),\n /**\n * Fallback Behavior to avoid `insert.block` in case the Behaviors above all\n * end up with a falsy guard.\n */\n defineBehavior({\n on: 'insert.block',\n actions: [],\n }),\n /**\n * If multiple blocks are inserted, then the non-text blocks are filtered out\n * and the text blocks are merged into one block\n */\n defineBehavior({\n on: 'insert.blocks',\n guard: ({snapshot, event}) => {\n const textBlocks = event.blocks.filter((block) =>\n utils.isTextBlock(snapshot.context, block),\n )\n\n if (textBlocks.length === 0) {\n return false\n }\n\n return textBlocks.reduce((targetBlock, incomingBlock) => {\n return utils.mergeTextBlocks({\n context: snapshot.context,\n targetBlock,\n incomingBlock,\n })\n })\n },\n actions: [\n // `insert.block` is raised so the Behavior above can handle the\n // insertion\n (_, block) => [raise({type: 'insert.block', block, placement: 'auto'})],\n ],\n }),\n /**\n * Fallback Behavior to avoid `insert.blocks` in case the Behavior above\n * ends up with a falsy guard.\n */\n defineBehavior({\n on: 'insert.blocks',\n actions: [],\n }),\n]\n\n/**\n * @beta\n * Restrict the editor to one line. The plugin takes care of blocking\n * `insert.break` events and smart handling of other `insert.*` events.\n *\n * Place it with as high priority as possible to make sure other plugins don't\n * overwrite `insert.*` events before this plugin gets a chance to do so.\n */\nexport function OneLinePlugin() {\n const editor = useEditor()\n\n useEffect(() => {\n const unregisterBehaviors = oneLineBehaviors.map((behavior) =>\n editor.registerBehavior({behavior}),\n )\n\n return () => {\n for (const unregisterBehavior of unregisterBehaviors) {\n unregisterBehavior()\n }\n }\n }, [editor])\n\n return null\n}\n"],"names":["defineBehavior","selectors","execute","utils","raise","editor","useEditor","useEffect"],"mappings":";;;;;;;;;;;;;;;;;;;AAMA,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKvBA,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,OAAO,CAAC,EAAC,SAAQ,MACf,SAAS,QAAQ,aAAaC,qBAAU,oBAAoB,QAAQ,IAChE,EAAC,WAAW,SAAS,QAAQ,cAC7B;AAAA,IACN,SAAS,CAAC,CAAC,GAAG,EAAC,gBAAe,CAACC,kBAAQ,EAAC,MAAM,UAAU,IAAI,UAAU,CAAA,CAAC,CAAC;AAAA,EAAA,CACzE;AAAA;AAAA;AAAA;AAAA,EAIDF,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,SAAS,CAAA;AAAA,EAAC,CACX;AAAA;AAAA;AAAA;AAAA,EAIDA,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,OAAO,CAAC,EAAC,YACP,MAAM,cAAc,YAAY,MAAM,cAAc;AAAA,IACtD,SAAS,CAAA;AAAA,EAAC,CACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAKDA,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,OAAO,CAAC,EAAC,UAAU,MAAA,MAIf,EAHqB,CAAAC,qBAAU,kBAAkB,QAAQ,KAIzD,CAACE,iBAAM,YAAY,SAAS,SAAS,MAAM,KAAK;AAAA,IAOpD,SAAS;AAAA,MACP,CAAC,EAAC,MAAA,MAAW;AAAA,QACXD,kBAAQ;AAAA,UACN,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,WAAW;AAAA,UACX,QAAQ;AAAA,QACT,CAAA;AAAA,MAAA;AAAA,IACH;AAAA,EACF,CACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAKDF,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,SAAS,CAAA;AAAA,EAAC,CACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAKDA,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,OAAO,CAAC,EAAC,UAAU,YAAW;AACtB,YAAA,aAAa,MAAM,OAAO;AAAA,QAAO,CAAC,UACtCG,iBAAM,YAAY,SAAS,SAAS,KAAK;AAAA,MAC3C;AAEI,aAAA,WAAW,WAAW,IACjB,KAGF,WAAW,OAAO,CAAC,aAAa,kBAC9BA,iBAAM,gBAAgB;AAAA,QAC3B,SAAS,SAAS;AAAA,QAClB;AAAA,QACA;AAAA,MAAA,CACD,CACF;AAAA,IACH;AAAA,IACA,SAAS;AAAA;AAAA;AAAA,MAGP,CAAC,GAAG,UAAU,CAACC,gBAAM,EAAC,MAAM,gBAAgB,OAAO,WAAW,QAAO,CAAC;AAAA,IAAA;AAAA,EACxE,CACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAKDJ,yBAAe;AAAA,IACb,IAAI;AAAA,IACJ,SAAS,CAAA;AAAA,EACV,CAAA;AACH;AAUO,SAAS,gBAAgB;AAC9B,QAAMK,WAASC,OAAAA,UAAU;AAEzB,SAAAC,MAAA,UAAU,MAAM;AACd,UAAM,sBAAsB,iBAAiB;AAAA,MAAI,CAAC,aAChDF,SAAO,iBAAiB,EAAC,SAAS,CAAA;AAAA,IACpC;AAEA,WAAO,MAAM;AACX,iBAAW,sBAAsB;AACZ,2BAAA;AAAA,IAEvB;AAAA,EAAA,GACC,CAACA,QAAM,CAAC,GAEJ;AACT;;"}