{"version":3,"file":"index.cjs","names":["Extension","Plugin","PluginKey","DecorationSet","Decoration"],"sources":["../../src/focus/focus.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nexport interface FocusOptions {\n  /**\n   * The class name that should be added to the focused node.\n   * @default 'has-focus'\n   * @example 'is-focused'\n   */\n  className: string\n\n  /**\n   * The mode by which the focused node is determined.\n   * - All: All nodes are marked as focused.\n   * - Deepest: Only the deepest node is marked as focused.\n   * - Shallowest: Only the shallowest node is marked as focused.\n   *\n   * @default 'all'\n   * @example 'deepest'\n   * @example 'shallowest'\n   */\n  mode: 'all' | 'deepest' | 'shallowest'\n}\n\n/**\n * This extension allows you to add a class to the focused node.\n * @see https://www.tiptap.dev/api/extensions/focus\n */\nexport const Focus = Extension.create<FocusOptions>({\n  name: 'focus',\n\n  addOptions() {\n    return {\n      className: 'has-focus',\n      mode: 'all',\n    }\n  },\n\n  addProseMirrorPlugins() {\n    return [\n      new Plugin({\n        key: new PluginKey('focus'),\n        props: {\n          decorations: ({ doc, selection }) => {\n            const { isEditable, isFocused } = this.editor\n            const { anchor } = selection\n            const decorations: Decoration[] = []\n\n            if (!isEditable || !isFocused) {\n              return DecorationSet.create(doc, [])\n            }\n\n            // Maximum Levels\n            let maxLevels = 0\n\n            if (this.options.mode === 'deepest') {\n              doc.descendants((node, pos) => {\n                if (node.isText) {\n                  return\n                }\n\n                const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1\n\n                if (!isCurrent) {\n                  return false\n                }\n\n                maxLevels += 1\n              })\n            }\n\n            // Loop through current\n            let currentLevel = 0\n\n            doc.descendants((node, pos) => {\n              if (node.isText) {\n                return false\n              }\n\n              const isCurrent = anchor >= pos && anchor <= pos + node.nodeSize - 1\n\n              if (!isCurrent) {\n                return false\n              }\n\n              currentLevel += 1\n\n              const outOfScope =\n                (this.options.mode === 'deepest' && maxLevels - currentLevel > 0) ||\n                (this.options.mode === 'shallowest' && currentLevel > 1)\n\n              if (outOfScope) {\n                return this.options.mode === 'deepest'\n              }\n\n              decorations.push(\n                Decoration.node(pos, pos + node.nodeSize, {\n                  class: this.options.className,\n                }),\n              )\n            })\n\n            return DecorationSet.create(doc, decorations)\n          },\n        },\n      }),\n    ]\n  },\n})\n"],"mappings":";;;;;;;;;AA6BA,MAAa,QAAQA,aAAAA,UAAU,OAAqB;CAClD,MAAM;CAEN,aAAa;EACX,OAAO;GACL,WAAW;GACX,MAAM;EACR;CACF;CAEA,wBAAwB;EACtB,OAAO,CACL,IAAIC,iBAAAA,OAAO;GACT,KAAK,IAAIC,iBAAAA,UAAU,OAAO;GAC1B,OAAO,EACL,cAAc,EAAE,KAAK,gBAAgB;IACnC,MAAM,EAAE,YAAY,cAAc,KAAK;IACvC,MAAM,EAAE,WAAW;IACnB,MAAM,cAA4B,CAAC;IAEnC,IAAI,CAAC,cAAc,CAAC,WAClB,OAAOC,gBAAAA,cAAc,OAAO,KAAK,CAAC,CAAC;IAIrC,IAAI,YAAY;IAEhB,IAAI,KAAK,QAAQ,SAAS,WACxB,IAAI,aAAa,MAAM,QAAQ;KAC7B,IAAI,KAAK,QACP;KAKF,IAAI,EAFc,UAAU,OAAO,UAAU,MAAM,KAAK,WAAW,IAGjE,OAAO;KAGT,aAAa;IACf,CAAC;IAIH,IAAI,eAAe;IAEnB,IAAI,aAAa,MAAM,QAAQ;KAC7B,IAAI,KAAK,QACP,OAAO;KAKT,IAAI,EAFc,UAAU,OAAO,UAAU,MAAM,KAAK,WAAW,IAGjE,OAAO;KAGT,gBAAgB;KAMhB,IAHG,KAAK,QAAQ,SAAS,aAAa,YAAY,eAAe,KAC9D,KAAK,QAAQ,SAAS,gBAAgB,eAAe,GAGtD,OAAO,KAAK,QAAQ,SAAS;KAG/B,YAAY,KACVC,gBAAAA,WAAW,KAAK,KAAK,MAAM,KAAK,UAAU,EACxC,OAAO,KAAK,QAAQ,UACtB,CAAC,CACH;IACF,CAAC;IAED,OAAOD,gBAAAA,cAAc,OAAO,KAAK,WAAW;GAC9C,EACF;EACF,CAAC,CACH;CACF;AACF,CAAC"}