payload-richtext-tiptap 0.0.47 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/fields/TiptapEditor/extensions/AICommand/AICommand.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/AICommand/AICommand.js +2 -0
- package/dist/src/fields/TiptapEditor/extensions/AICommand/AICommand.js.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.js +21 -9
- package/dist/src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.js.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/Video/Video.d.ts +52 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/Video.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/Video.js +81 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/Video.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/index.d.ts +2 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/index.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/index.js +3 -0
- package/dist/src/fields/TiptapEditor/extensions/Video/index.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/VideoBlock.d.ts +21 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/VideoBlock.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/VideoBlock.js +97 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/VideoBlock.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockMenu.d.ts +5 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockMenu.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockMenu.js +133 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockMenu.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockView.d.ts +16 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockView.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockView.js +39 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockView.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockWidth.d.ts +7 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockWidth.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockWidth.js +39 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockWidth.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/index.d.ts +2 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/index.d.ts.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/index.js +3 -0
- package/dist/src/fields/TiptapEditor/extensions/VideoBlock/index.js.map +1 -0
- package/dist/src/fields/TiptapEditor/extensions/extension-kit.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/extension-kit.js +4 -3
- package/dist/src/fields/TiptapEditor/extensions/extension-kit.js.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/index.d.ts +1 -0
- package/dist/src/fields/TiptapEditor/extensions/index.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/extensions/index.js +1 -0
- package/dist/src/fields/TiptapEditor/extensions/index.js.map +1 -1
- package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.d.ts +2 -1
- package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.js +3 -2
- package/dist/src/fields/TiptapEditor/features/BlockEditor/BlockEditor.js.map +1 -1
- package/dist/src/fields/TiptapEditor/features/panels/AICommandPanel/AICommandPanel.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/features/panels/AICommandPanel/AICommandPanel.js +2 -2
- package/dist/src/fields/TiptapEditor/features/panels/AICommandPanel/AICommandPanel.js.map +1 -1
- package/dist/src/fields/TiptapEditor/hooks/useBlockEditor.d.ts +2 -1
- package/dist/src/fields/TiptapEditor/hooks/useBlockEditor.d.ts.map +1 -1
- package/dist/src/fields/TiptapEditor/hooks/useBlockEditor.js +8 -2
- package/dist/src/fields/TiptapEditor/hooks/useBlockEditor.js.map +1 -1
- package/dist/src/fields/TiptapEditor/lib/extract.js +0 -1
- package/dist/src/fields/TiptapEditor/lib/extract.js.map +1 -1
- package/dist/src/fields/TiptapEditor/types.d.js.map +1 -1
- package/dist/src/styles.css +2 -28
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AICommand.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/AICommand/AICommand.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,SAAS,EAAE,MAAM,cAAc,CAAC;AAiBjD,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"AICommand.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/AICommand/AICommand.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,SAAS,EAAE,MAAM,cAAc,CAAC;AAiBjD,eAAO,MAAM,SAAS,qBA2SpB,CAAC;AAEH,eAAe,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/AICommand/AICommand.ts"],"sourcesContent":["\"use client\";\nimport { Editor, Extension } from \"@tiptap/core\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion, {\n SuggestionKeyDownProps,\n SuggestionProps,\n} from \"@tiptap/suggestion\";\nimport tippy from \"tippy.js\";\n\nimport { GROUPS } from \"./groups.js\";\nimport AIMenuList from \"./AIMenuList.js\";\n// import { AICommandPanel } from \"../../features/panels/AICommandPanel/AICommandPanel.js\";\n\nconst extensionName = \"aiCommand\";\n\nlet popup: any;\n\nexport const AICommand = Extension.create({\n name: extensionName,\n\n priority: 200,\n\n onCreate() {\n const t = tippy as any;\n popup = t(\"body\", {\n interactive: true,\n trigger: \"manual\",\n placement: \"bottom-start\",\n theme: \"slash-command\",\n // maxWidth: \"16rem\",\n offset: [0, -16],\n popperOptions: {\n strategy: \"fixed\",\n modifiers: [\n {\n name: \"flip\",\n enabled: false,\n },\n ],\n },\n onHidden: (instance) => {\n const selection = this?.editor?.state?.selection;\n\n this.editor\n ?.chain()\n ?.focus()\n ?.insertContentAt(\n selection.to - 1,\n this?.editor?.storage?.aiCommand?.completion ?? \"\"\n )\n ?.insertContentAt(selection.to, \" \")\n ?.run();\n },\n });\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: \" \",\n allowSpaces: true,\n startOfLine: true,\n pluginKey: new PluginKey(extensionName),\n allow: ({ state, range }) => {\n const $from = state.doc.resolve(range.from);\n const isRootDepth = $from.depth === 1;\n const isParagraph = $from.parent.type.name === \"paragraph\";\n const isStartOfNode = $from.parent.textContent?.charAt(0) === \" \";\n // TODO\n const isInColumn = this.editor.isActive(\"column\");\n\n const afterContent = $from.parent.textContent?.substring(\n $from.parent.textContent?.indexOf(\" \")\n );\n const isValidAfterContent = !afterContent?.endsWith(\" \");\n\n return (\n ((isRootDepth && isParagraph && isStartOfNode) ||\n (isInColumn && isParagraph && isStartOfNode)) &&\n isValidAfterContent\n );\n },\n command: ({ editor, props }: { editor: Editor; props: any }) => {\n // const { view, state } = editor;\n // const { $head, $from } = view.state.selection;\n\n // const end = $from.pos;\n // const from = $head?.nodeBefore\n // ? end -\n // ($head.nodeBefore.text?.substring(\n // $head.nodeBefore.text?.indexOf(\" \")\n // ).length ?? 0)\n // : $from.start();\n\n // const tr = state.tr.deleteRange(from, end);\n // view.dispatch(tr);\n\n props.action(editor);\n // view.focus();\n },\n items: ({ query }: { query: string }) => {\n const withFilteredCommands = GROUPS.map((group) => ({\n ...group,\n commands: group.commands\n .filter((item) => {\n const labelNormalized = item.label.toLowerCase().trim();\n const queryNormalized = query.toLowerCase().trim();\n\n if (item.aliases) {\n const aliases = item.aliases.map((alias) =>\n alias.toLowerCase().trim()\n );\n\n return (\n labelNormalized.includes(queryNormalized) ||\n aliases.includes(queryNormalized)\n );\n }\n\n return labelNormalized.includes(queryNormalized);\n })\n .filter((command) =>\n command.shouldBeHidden\n ? !command.shouldBeHidden(this.editor)\n : true\n ),\n }));\n\n const withoutEmptyGroups = withFilteredCommands.filter((group) => {\n if (group.commands.length > 0) {\n return true;\n }\n\n return false;\n });\n\n const withEnabledSettings = withoutEmptyGroups.map((group) => ({\n ...group,\n commands: group.commands.map((command) => ({\n ...command,\n isEnabled: true,\n })),\n }));\n\n return withEnabledSettings;\n },\n render: () => {\n let component: any;\n\n let scrollHandler: (() => void) | null = null;\n\n return {\n onStart: (props: SuggestionProps) => {\n component = new ReactRenderer(AIMenuList, {\n props,\n editor: props.editor,\n });\n props.editor.storage.aiCommand.active = true;\n const { view } = props.editor;\n\n const editorNode = view.dom as HTMLElement;\n\n const getReferenceClientRect = () => {\n if (!props.clientRect) {\n return props.editor.storage[extensionName].rect;\n }\n\n const rect = props.clientRect();\n\n if (!rect) {\n return props.editor.storage[extensionName].rect;\n }\n\n let yPos = rect.y;\n\n if (\n rect.top + component.element.offsetHeight + 40 >\n window.innerHeight\n ) {\n const diff =\n rect.top +\n component.element.offsetHeight -\n window.innerHeight +\n 40;\n yPos = rect.y - diff;\n }\n\n // Account for when the editor is bound inside a container that doesn't go all the way to the edge of the screen\n const editorXOffset = editorNode.getBoundingClientRect().x;\n const boundigClient = editorNode.getBoundingClientRect();\n\n return new DOMRect(\n rect.x,\n yPos,\n boundigClient.width,\n rect.height\n );\n };\n\n scrollHandler = () => {\n popup?.[0].setProps({\n getReferenceClientRect,\n });\n };\n\n view.dom.parentElement?.addEventListener(\"scroll\", scrollHandler);\n\n popup?.[0].setProps({\n getReferenceClientRect,\n appendTo: () => document.body,\n content: component.element,\n });\n\n popup?.[0].show();\n },\n\n onUpdate(props: SuggestionProps) {\n component.updateProps(props);\n\n const { view } = props.editor;\n\n const editorNode = view.dom as HTMLElement;\n\n const getReferenceClientRect = () => {\n if (!props.clientRect) {\n return props.editor.storage[extensionName].rect;\n }\n\n const rect = props.clientRect();\n\n if (!rect) {\n return props.editor.storage[extensionName].rect;\n }\n\n // Account for when the editor is bound inside a container that doesn't go all the way to the edge of the screen\n return new DOMRect(rect.x, rect.y, rect.width, rect.height);\n };\n\n let scrollHandler = () => {\n popup?.[0].setProps({\n getReferenceClientRect,\n });\n };\n\n view.dom.parentElement?.addEventListener(\"scroll\", scrollHandler);\n\n // eslint-disable-next-line no-param-reassign\n props.editor.storage[extensionName].rect = props.clientRect\n ? getReferenceClientRect()\n : {\n width: 0,\n height: 0,\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n };\n popup?.[0].setProps({\n getReferenceClientRect,\n });\n },\n\n onKeyDown(props: SuggestionKeyDownProps) {\n if (props.event.key === \"Escape\") {\n popup?.[0].hide();\n\n return true;\n }\n\n if (!popup?.[0].state.isShown) {\n popup?.[0].show();\n }\n\n return component.ref?.onKeyDown(props);\n },\n\n onExit(props) {\n popup?.[0].hide();\n if (scrollHandler) {\n const { view } = props.editor;\n view.dom.parentElement?.removeEventListener(\n \"scroll\",\n scrollHandler\n );\n }\n\n props.editor.storage.aiCommand.active = false;\n props.editor.storage.aiCommand.userPrompt = \"\";\n props.editor.storage.aiCommand.completion = \"\";\n\n component.destroy();\n },\n };\n },\n }),\n ];\n },\n\n addStorage() {\n return {\n rect: {\n width: 0,\n height: 0,\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n },\n userPrompt: \"\",\n completion: \"\",\n active: false,\n };\n },\n});\n\nexport default AICommand;\n"],"names":["Extension","PluginKey","ReactRenderer","Suggestion","tippy","GROUPS","AIMenuList","extensionName","popup","AICommand","create","name","priority","onCreate","t","interactive","trigger","placement","theme","offset","popperOptions","strategy","modifiers","enabled","onHidden","instance","selection","editor","state","chain","focus","insertContentAt","to","storage","aiCommand","completion","run","addProseMirrorPlugins","char","allowSpaces","startOfLine","pluginKey","allow","range","$from","doc","resolve","from","isRootDepth","depth","isParagraph","parent","type","isStartOfNode","textContent","charAt","isInColumn","isActive","afterContent","substring","indexOf","isValidAfterContent","endsWith","command","props","action","items","query","withFilteredCommands","map","group","commands","filter","item","labelNormalized","label","toLowerCase","trim","queryNormalized","aliases","alias","includes","shouldBeHidden","withoutEmptyGroups","length","withEnabledSettings","isEnabled","render","component","scrollHandler","onStart","active","view","editorNode","dom","getReferenceClientRect","clientRect","rect","yPos","y","top","element","offsetHeight","window","innerHeight","diff","editorXOffset","getBoundingClientRect","x","boundigClient","DOMRect","width","height","setProps","parentElement","addEventListener","appendTo","document","body","content","show","onUpdate","updateProps","left","right","bottom","onKeyDown","event","key","hide","isShown","ref","onExit","removeEventListener","userPrompt","destroy","addStorage"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/AICommand/AICommand.ts"],"sourcesContent":["\"use client\";\nimport { Editor, Extension } from \"@tiptap/core\";\nimport { PluginKey } from \"@tiptap/pm/state\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport Suggestion, {\n SuggestionKeyDownProps,\n SuggestionProps,\n} from \"@tiptap/suggestion\";\nimport tippy from \"tippy.js\";\n\nimport { GROUPS } from \"./groups.js\";\nimport AIMenuList from \"./AIMenuList.js\";\n// import { AICommandPanel } from \"../../features/panels/AICommandPanel/AICommandPanel.js\";\n\nconst extensionName = \"aiCommand\";\n\nlet popup: any;\n\nexport const AICommand = Extension.create({\n name: extensionName,\n\n priority: 200,\n\n onCreate() {\n const t = tippy as any;\n popup = t(\"body\", {\n interactive: true,\n trigger: \"manual\",\n placement: \"bottom-start\",\n theme: \"slash-command\",\n // maxWidth: \"16rem\",\n offset: [0, -16],\n popperOptions: {\n strategy: \"fixed\",\n modifiers: [\n {\n name: \"flip\",\n enabled: false,\n },\n ],\n },\n onHidden: (instance) => {\n const selection = this?.editor?.state?.selection;\n\n this.editor\n ?.chain()\n ?.focus()\n ?.insertContentAt(\n selection.to - 1,\n this?.editor?.storage?.aiCommand?.completion ?? \"\"\n )\n ?.insertContentAt(selection.to, \" \")\n ?.run();\n },\n });\n },\n\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n char: \" \",\n allowSpaces: true,\n startOfLine: true,\n pluginKey: new PluginKey(extensionName),\n allow: ({ state, range }) => {\n const $from = state.doc.resolve(range.from);\n const isRootDepth = $from.depth === 1;\n const isParagraph = $from.parent.type.name === \"paragraph\";\n const isStartOfNode = $from.parent.textContent?.charAt(0) === \" \";\n // TODO\n const isInColumn = this.editor.isActive(\"column\");\n\n const afterContent = $from.parent.textContent?.substring(\n $from.parent.textContent?.indexOf(\" \")\n );\n const isValidAfterContent = !afterContent?.endsWith(\" \");\n\n return (\n ((isRootDepth && isParagraph && isStartOfNode) ||\n (isInColumn && isParagraph && isStartOfNode)) &&\n isValidAfterContent\n );\n },\n command: ({ editor, props }: { editor: Editor; props: any }) => {\n // const { view, state } = editor;\n // const { $head, $from } = view.state.selection;\n\n // const end = $from.pos;\n // const from = $head?.nodeBefore\n // ? end -\n // ($head.nodeBefore.text?.substring(\n // $head.nodeBefore.text?.indexOf(\" \")\n // ).length ?? 0)\n // : $from.start();\n\n // const tr = state.tr.deleteRange(from, end);\n // view.dispatch(tr);\n\n props.action(editor);\n // view.focus();\n },\n items: ({ query }: { query: string }) => {\n const withFilteredCommands = GROUPS.map((group) => ({\n ...group,\n commands: group.commands\n .filter((item) => {\n const labelNormalized = item.label.toLowerCase().trim();\n const queryNormalized = query.toLowerCase().trim();\n\n if (item.aliases) {\n const aliases = item.aliases.map((alias) =>\n alias.toLowerCase().trim()\n );\n\n return (\n labelNormalized.includes(queryNormalized) ||\n aliases.includes(queryNormalized)\n );\n }\n\n return labelNormalized.includes(queryNormalized);\n })\n .filter((command) =>\n command.shouldBeHidden\n ? !command.shouldBeHidden(this.editor)\n : true\n ),\n }));\n\n const withoutEmptyGroups = withFilteredCommands.filter((group) => {\n if (group.commands.length > 0) {\n return true;\n }\n\n return false;\n });\n\n const withEnabledSettings = withoutEmptyGroups.map((group) => ({\n ...group,\n commands: group.commands.map((command) => ({\n ...command,\n isEnabled: true,\n })),\n }));\n\n return withEnabledSettings;\n },\n render: () => {\n let component: any;\n\n let scrollHandler: (() => void) | null = null;\n\n return {\n onStart: (props: SuggestionProps) => {\n component = new ReactRenderer(AIMenuList, {\n props,\n editor: props.editor,\n });\n props.editor.storage.aiCommand.active = true;\n const { view } = props.editor;\n\n const editorNode = view.dom as HTMLElement;\n\n const getReferenceClientRect = () => {\n if (!props.clientRect) {\n return props.editor.storage[extensionName].rect;\n }\n\n const rect = props.clientRect();\n\n if (!rect) {\n return props.editor.storage[extensionName].rect;\n }\n\n let yPos = rect.y;\n\n if (\n rect.top + component.element.offsetHeight + 40 >\n window.innerHeight\n ) {\n const diff =\n rect.top +\n component.element.offsetHeight -\n window.innerHeight +\n 40;\n yPos = rect.y - diff;\n }\n\n // Account for when the editor is bound inside a container that doesn't go all the way to the edge of the screen\n const editorXOffset = editorNode.getBoundingClientRect().x;\n const boundigClient = editorNode.getBoundingClientRect();\n\n return new DOMRect(\n rect.x,\n yPos,\n boundigClient.width,\n rect.height\n );\n };\n\n scrollHandler = () => {\n popup?.[0].setProps({\n getReferenceClientRect,\n });\n };\n\n view.dom.parentElement?.addEventListener(\"scroll\", scrollHandler);\n\n popup?.[0].setProps({\n getReferenceClientRect,\n appendTo: () => document.body,\n content: component.element,\n });\n\n popup?.[0].show();\n },\n\n onUpdate(props: SuggestionProps) {\n component.updateProps(props);\n\n const { view } = props.editor;\n\n const editorNode = view.dom as HTMLElement;\n\n const getReferenceClientRect = () => {\n if (!props.clientRect) {\n return props.editor.storage[extensionName].rect;\n }\n\n const rect = props.clientRect();\n\n if (!rect) {\n return props.editor.storage[extensionName].rect;\n }\n\n // Account for when the editor is bound inside a container that doesn't go all the way to the edge of the screen\n return new DOMRect(rect.x, rect.y, rect.width, rect.height);\n };\n\n let scrollHandler = () => {\n popup?.[0].setProps({\n getReferenceClientRect,\n });\n };\n\n view.dom.parentElement?.addEventListener(\"scroll\", scrollHandler);\n\n // eslint-disable-next-line no-param-reassign\n props.editor.storage[extensionName].rect = props.clientRect\n ? getReferenceClientRect()\n : {\n width: 0,\n height: 0,\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n };\n popup?.[0].setProps({\n getReferenceClientRect,\n });\n },\n\n onKeyDown(props: SuggestionKeyDownProps) {\n if (props.event.key === \"Escape\") {\n popup?.[0].hide();\n\n return true;\n }\n\n if (!popup?.[0].state.isShown) {\n popup?.[0].show();\n }\n\n return component.ref?.onKeyDown(props);\n },\n\n onExit(props) {\n popup?.[0].hide();\n if (scrollHandler) {\n const { view } = props.editor;\n view.dom.parentElement?.removeEventListener(\n \"scroll\",\n scrollHandler\n );\n }\n\n props.editor.storage.aiCommand.active = false;\n props.editor.storage.aiCommand.userPrompt = \"\";\n props.editor.storage.aiCommand.completion = \"\";\n\n component.destroy();\n },\n };\n },\n }),\n ];\n },\n\n addStorage() {\n return {\n rect: {\n width: 0,\n height: 0,\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n },\n userPrompt: \"\",\n completion: \"\",\n language: \"en\",\n title: \"\",\n active: false,\n };\n },\n});\n\nexport default AICommand;\n"],"names":["Extension","PluginKey","ReactRenderer","Suggestion","tippy","GROUPS","AIMenuList","extensionName","popup","AICommand","create","name","priority","onCreate","t","interactive","trigger","placement","theme","offset","popperOptions","strategy","modifiers","enabled","onHidden","instance","selection","editor","state","chain","focus","insertContentAt","to","storage","aiCommand","completion","run","addProseMirrorPlugins","char","allowSpaces","startOfLine","pluginKey","allow","range","$from","doc","resolve","from","isRootDepth","depth","isParagraph","parent","type","isStartOfNode","textContent","charAt","isInColumn","isActive","afterContent","substring","indexOf","isValidAfterContent","endsWith","command","props","action","items","query","withFilteredCommands","map","group","commands","filter","item","labelNormalized","label","toLowerCase","trim","queryNormalized","aliases","alias","includes","shouldBeHidden","withoutEmptyGroups","length","withEnabledSettings","isEnabled","render","component","scrollHandler","onStart","active","view","editorNode","dom","getReferenceClientRect","clientRect","rect","yPos","y","top","element","offsetHeight","window","innerHeight","diff","editorXOffset","getBoundingClientRect","x","boundigClient","DOMRect","width","height","setProps","parentElement","addEventListener","appendTo","document","body","content","show","onUpdate","updateProps","left","right","bottom","onKeyDown","event","key","hide","isShown","ref","onExit","removeEventListener","userPrompt","destroy","addStorage","language","title"],"mappings":"AAAA;AACA,SAAiBA,SAAS,QAAQ,eAAe;AACjD,SAASC,SAAS,QAAQ,mBAAmB;AAC7C,SAASC,aAAa,QAAQ,gBAAgB;AAC9C,OAAOC,gBAGA,qBAAqB;AAC5B,OAAOC,WAAW,WAAW;AAE7B,SAASC,MAAM,QAAQ,cAAc;AACrC,OAAOC,gBAAgB,kBAAkB;AACzC,2FAA2F;AAE3F,MAAMC,gBAAgB;AAEtB,IAAIC;AAEJ,OAAO,MAAMC,YAAYT,UAAUU,MAAM,CAAC;IACxCC,MAAMJ;IAENK,UAAU;IAEVC;QACE,MAAMC,IAAIV;QACVI,QAAQM,EAAE,QAAQ;YAChBC,aAAa;YACbC,SAAS;YACTC,WAAW;YACXC,OAAO;YACP,qBAAqB;YACrBC,QAAQ;gBAAC;gBAAG,CAAC;aAAG;YAChBC,eAAe;gBACbC,UAAU;gBACVC,WAAW;oBACT;wBACEX,MAAM;wBACNY,SAAS;oBACX;iBACD;YACH;YACAC,UAAU,CAACC;gBACT,MAAMC,YAAY,IAAI,EAAEC,QAAQC,OAAOF;gBAEvC,IAAI,CAACC,MAAM,EACPE,SACAC,SACAC,gBACAL,UAAUM,EAAE,GAAG,GACf,IAAI,EAAEL,QAAQM,SAASC,WAAWC,cAAc,KAEhDJ,gBAAgBL,UAAUM,EAAE,EAAE,MAC9BI;YACN;QACF;IACF;IAEAC;QACE,OAAO;YACLlC,WAAW;gBACTwB,QAAQ,IAAI,CAACA,MAAM;gBACnBW,MAAM;gBACNC,aAAa;gBACbC,aAAa;gBACbC,WAAW,IAAIxC,UAAUM;gBACzBmC,OAAO,CAAC,EAAEd,KAAK,EAAEe,KAAK,EAAE;oBACtB,MAAMC,QAAQhB,MAAMiB,GAAG,CAACC,OAAO,CAACH,MAAMI,IAAI;oBAC1C,MAAMC,cAAcJ,MAAMK,KAAK,KAAK;oBACpC,MAAMC,cAAcN,MAAMO,MAAM,CAACC,IAAI,CAACzC,IAAI,KAAK;oBAC/C,MAAM0C,gBAAgBT,MAAMO,MAAM,CAACG,WAAW,EAAEC,OAAO,OAAO;oBAC9D,OAAO;oBACP,MAAMC,aAAa,IAAI,CAAC7B,MAAM,CAAC8B,QAAQ,CAAC;oBAExC,MAAMC,eAAed,MAAMO,MAAM,CAACG,WAAW,EAAEK,UAC7Cf,MAAMO,MAAM,CAACG,WAAW,EAAEM,QAAQ;oBAEpC,MAAMC,sBAAsB,CAACH,cAAcI,SAAS;oBAEpD,OACE,AAAC,CAAA,AAACd,eAAeE,eAAeG,iBAC7BG,cAAcN,eAAeG,aAAa,KAC7CQ;gBAEJ;gBACAE,SAAS,CAAC,EAAEpC,MAAM,EAAEqC,KAAK,EAAkC;oBACzD,kCAAkC;oBAClC,iDAAiD;oBAEjD,yBAAyB;oBACzB,iCAAiC;oBACjC,YAAY;oBACZ,yCAAyC;oBACzC,4CAA4C;oBAC5C,qBAAqB;oBACrB,qBAAqB;oBAErB,8CAA8C;oBAC9C,qBAAqB;oBAErBA,MAAMC,MAAM,CAACtC;gBACb,gBAAgB;gBAClB;gBACAuC,OAAO,CAAC,EAAEC,KAAK,EAAqB;oBAClC,MAAMC,uBAAuB/D,OAAOgE,GAAG,CAAC,CAACC,QAAW,CAAA;4BAClD,GAAGA,KAAK;4BACRC,UAAUD,MAAMC,QAAQ,CACrBC,MAAM,CAAC,CAACC;gCACP,MAAMC,kBAAkBD,KAAKE,KAAK,CAACC,WAAW,GAAGC,IAAI;gCACrD,MAAMC,kBAAkBX,MAAMS,WAAW,GAAGC,IAAI;gCAEhD,IAAIJ,KAAKM,OAAO,EAAE;oCAChB,MAAMA,UAAUN,KAAKM,OAAO,CAACV,GAAG,CAAC,CAACW,QAChCA,MAAMJ,WAAW,GAAGC,IAAI;oCAG1B,OACEH,gBAAgBO,QAAQ,CAACH,oBACzBC,QAAQE,QAAQ,CAACH;gCAErB;gCAEA,OAAOJ,gBAAgBO,QAAQ,CAACH;4BAClC,GACCN,MAAM,CAAC,CAACT,UACPA,QAAQmB,cAAc,GAClB,CAACnB,QAAQmB,cAAc,CAAC,IAAI,CAACvD,MAAM,IACnC;wBAEV,CAAA;oBAEA,MAAMwD,qBAAqBf,qBAAqBI,MAAM,CAAC,CAACF;wBACtD,IAAIA,MAAMC,QAAQ,CAACa,MAAM,GAAG,GAAG;4BAC7B,OAAO;wBACT;wBAEA,OAAO;oBACT;oBAEA,MAAMC,sBAAsBF,mBAAmBd,GAAG,CAAC,CAACC,QAAW,CAAA;4BAC7D,GAAGA,KAAK;4BACRC,UAAUD,MAAMC,QAAQ,CAACF,GAAG,CAAC,CAACN,UAAa,CAAA;oCACzC,GAAGA,OAAO;oCACVuB,WAAW;gCACb,CAAA;wBACF,CAAA;oBAEA,OAAOD;gBACT;gBACAE,QAAQ;oBACN,IAAIC;oBAEJ,IAAIC,gBAAqC;oBAEzC,OAAO;wBACLC,SAAS,CAAC1B;4BACRwB,YAAY,IAAItF,cAAcI,YAAY;gCACxC0D;gCACArC,QAAQqC,MAAMrC,MAAM;4BACtB;4BACAqC,MAAMrC,MAAM,CAACM,OAAO,CAACC,SAAS,CAACyD,MAAM,GAAG;4BACxC,MAAM,EAAEC,IAAI,EAAE,GAAG5B,MAAMrC,MAAM;4BAE7B,MAAMkE,aAAaD,KAAKE,GAAG;4BAE3B,MAAMC,yBAAyB;gCAC7B,IAAI,CAAC/B,MAAMgC,UAAU,EAAE;oCACrB,OAAOhC,MAAMrC,MAAM,CAACM,OAAO,CAAC1B,cAAc,CAAC0F,IAAI;gCACjD;gCAEA,MAAMA,OAAOjC,MAAMgC,UAAU;gCAE7B,IAAI,CAACC,MAAM;oCACT,OAAOjC,MAAMrC,MAAM,CAACM,OAAO,CAAC1B,cAAc,CAAC0F,IAAI;gCACjD;gCAEA,IAAIC,OAAOD,KAAKE,CAAC;gCAEjB,IACEF,KAAKG,GAAG,GAAGZ,UAAUa,OAAO,CAACC,YAAY,GAAG,KAC5CC,OAAOC,WAAW,EAClB;oCACA,MAAMC,OACJR,KAAKG,GAAG,GACRZ,UAAUa,OAAO,CAACC,YAAY,GAC9BC,OAAOC,WAAW,GAClB;oCACFN,OAAOD,KAAKE,CAAC,GAAGM;gCAClB;gCAEA,gHAAgH;gCAChH,MAAMC,gBAAgBb,WAAWc,qBAAqB,GAAGC,CAAC;gCAC1D,MAAMC,gBAAgBhB,WAAWc,qBAAqB;gCAEtD,OAAO,IAAIG,QACTb,KAAKW,CAAC,EACNV,MACAW,cAAcE,KAAK,EACnBd,KAAKe,MAAM;4BAEf;4BAEAvB,gBAAgB;gCACdjF,OAAO,CAAC,EAAE,CAACyG,SAAS;oCAClBlB;gCACF;4BACF;4BAEAH,KAAKE,GAAG,CAACoB,aAAa,EAAEC,iBAAiB,UAAU1B;4BAEnDjF,OAAO,CAAC,EAAE,CAACyG,SAAS;gCAClBlB;gCACAqB,UAAU,IAAMC,SAASC,IAAI;gCAC7BC,SAAS/B,UAAUa,OAAO;4BAC5B;4BAEA7F,OAAO,CAAC,EAAE,CAACgH;wBACb;wBAEAC,UAASzD,KAAsB;4BAC7BwB,UAAUkC,WAAW,CAAC1D;4BAEtB,MAAM,EAAE4B,IAAI,EAAE,GAAG5B,MAAMrC,MAAM;4BAE7B,MAAMkE,aAAaD,KAAKE,GAAG;4BAE3B,MAAMC,yBAAyB;gCAC7B,IAAI,CAAC/B,MAAMgC,UAAU,EAAE;oCACrB,OAAOhC,MAAMrC,MAAM,CAACM,OAAO,CAAC1B,cAAc,CAAC0F,IAAI;gCACjD;gCAEA,MAAMA,OAAOjC,MAAMgC,UAAU;gCAE7B,IAAI,CAACC,MAAM;oCACT,OAAOjC,MAAMrC,MAAM,CAACM,OAAO,CAAC1B,cAAc,CAAC0F,IAAI;gCACjD;gCAEA,gHAAgH;gCAChH,OAAO,IAAIa,QAAQb,KAAKW,CAAC,EAAEX,KAAKE,CAAC,EAAEF,KAAKc,KAAK,EAAEd,KAAKe,MAAM;4BAC5D;4BAEA,IAAIvB,gBAAgB;gCAClBjF,OAAO,CAAC,EAAE,CAACyG,SAAS;oCAClBlB;gCACF;4BACF;4BAEAH,KAAKE,GAAG,CAACoB,aAAa,EAAEC,iBAAiB,UAAU1B;4BAEnD,6CAA6C;4BAC7CzB,MAAMrC,MAAM,CAACM,OAAO,CAAC1B,cAAc,CAAC0F,IAAI,GAAGjC,MAAMgC,UAAU,GACvDD,2BACA;gCACEgB,OAAO;gCACPC,QAAQ;gCACRW,MAAM;gCACNvB,KAAK;gCACLwB,OAAO;gCACPC,QAAQ;4BACV;4BACJrH,OAAO,CAAC,EAAE,CAACyG,SAAS;gCAClBlB;4BACF;wBACF;wBAEA+B,WAAU9D,KAA6B;4BACrC,IAAIA,MAAM+D,KAAK,CAACC,GAAG,KAAK,UAAU;gCAChCxH,OAAO,CAAC,EAAE,CAACyH;gCAEX,OAAO;4BACT;4BAEA,IAAI,CAACzH,OAAO,CAAC,EAAE,CAACoB,MAAMsG,SAAS;gCAC7B1H,OAAO,CAAC,EAAE,CAACgH;4BACb;4BAEA,OAAOhC,UAAU2C,GAAG,EAAEL,UAAU9D;wBAClC;wBAEAoE,QAAOpE,KAAK;4BACVxD,OAAO,CAAC,EAAE,CAACyH;4BACX,IAAIxC,eAAe;gCACjB,MAAM,EAAEG,IAAI,EAAE,GAAG5B,MAAMrC,MAAM;gCAC7BiE,KAAKE,GAAG,CAACoB,aAAa,EAAEmB,oBACtB,UACA5C;4BAEJ;4BAEAzB,MAAMrC,MAAM,CAACM,OAAO,CAACC,SAAS,CAACyD,MAAM,GAAG;4BACxC3B,MAAMrC,MAAM,CAACM,OAAO,CAACC,SAAS,CAACoG,UAAU,GAAG;4BAC5CtE,MAAMrC,MAAM,CAACM,OAAO,CAACC,SAAS,CAACC,UAAU,GAAG;4BAE5CqD,UAAU+C,OAAO;wBACnB;oBACF;gBACF;YACF;SACD;IACH;IAEAC;QACE,OAAO;YACLvC,MAAM;gBACJc,OAAO;gBACPC,QAAQ;gBACRW,MAAM;gBACNvB,KAAK;gBACLwB,OAAO;gBACPC,QAAQ;YACV;YACAS,YAAY;YACZnG,YAAY;YACZsG,UAAU;YACVC,OAAO;YACP/C,QAAQ;QACV;IACF;AACF,GAAG;AAEH,eAAelF,UAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmB,MAAM,eAAe,CAAC;AAExD,OAAO,
|
|
1
|
+
{"version":3,"file":"ImageUpload.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmB,MAAM,eAAe,CAAC;AAExD,OAAO,EAEL,eAAe,EAChB,MAAM,kCAAkC,CAAC;AAC1C,eAAO,MAAM,kBAAkB,uBAAwB,eAAe,2BAIjE;IACD,MAAM,EAAE,MAAM,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB,gCA4EF,CAAC"}
|
|
@@ -3,14 +3,26 @@ import { NodeViewWrapper } from "@tiptap/react";
|
|
|
3
3
|
import { useCallback } from "react";
|
|
4
4
|
export const ImageUploadBuilder = (openAssetHQHandler)=>{
|
|
5
5
|
const ImageUpload = ({ getPos, editor })=>{
|
|
6
|
-
const onUpload = useCallback((
|
|
7
|
-
if (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
const onUpload = useCallback((asset)=>{
|
|
7
|
+
if (asset) {
|
|
8
|
+
console.log("asset in ImageUpload itself:", asset);
|
|
9
|
+
if (asset.type === "IMAGE") {
|
|
10
|
+
editor.chain().focus().setImageBlock({
|
|
11
|
+
src: asset.fullUrl
|
|
12
|
+
}) //TODO: should also set other fields to data-media-id ... it'd be easier to later find which media id is this.
|
|
13
|
+
.deleteRange({
|
|
14
|
+
from: getPos(),
|
|
15
|
+
to: getPos()
|
|
16
|
+
}).focus().run();
|
|
17
|
+
} else {
|
|
18
|
+
editor.chain().focus().setVideoBlock({
|
|
19
|
+
src: asset.videoUrl,
|
|
20
|
+
poster: asset.fullUrl
|
|
21
|
+
}).deleteRange({
|
|
22
|
+
from: getPos(),
|
|
23
|
+
to: getPos()
|
|
24
|
+
}).focus().run();
|
|
25
|
+
}
|
|
14
26
|
}
|
|
15
27
|
}, [
|
|
16
28
|
getPos,
|
|
@@ -33,7 +45,7 @@ export const ImageUploadBuilder = (openAssetHQHandler)=>{
|
|
|
33
45
|
e.preventDefault();
|
|
34
46
|
openAssetHQHandler(onUpload);
|
|
35
47
|
},
|
|
36
|
-
children: "
|
|
48
|
+
children: "Select an asset"
|
|
37
49
|
})
|
|
38
50
|
})
|
|
39
51
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.tsx"],"sourcesContent":["import { Editor, NodeViewWrapper } from \"@tiptap/react\";\nimport { useCallback } from \"react\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../../../src/fields/TiptapEditor/extensions/ImageUpload/view/ImageUpload.tsx"],"sourcesContent":["import { Editor, NodeViewWrapper } from \"@tiptap/react\";\nimport { useCallback } from \"react\";\nimport {\n AssetReturnType,\n openAssetHQType,\n} from \"src/fields/TiptapEditor/types.js\";\nexport const ImageUploadBuilder = (openAssetHQHandler: openAssetHQType) => {\n const ImageUpload = ({\n getPos,\n editor,\n }: {\n getPos: () => number;\n editor: Editor;\n }) => {\n const onUpload = useCallback(\n (asset: AssetReturnType) => {\n if (asset) {\n console.log(\"asset in ImageUpload itself:\", asset);\n if (asset.type === \"IMAGE\") {\n editor\n .chain()\n .focus()\n .setImageBlock({ src: asset.fullUrl }) //TODO: should also set other fields to data-media-id ... it'd be easier to later find which media id is this.\n .deleteRange({ from: getPos(), to: getPos() })\n .focus()\n .run();\n } else {\n editor\n .chain()\n .focus()\n .setVideoBlock({ src: asset.videoUrl, poster: asset.fullUrl })\n .deleteRange({ from: getPos(), to: getPos() })\n .focus()\n .run();\n }\n }\n },\n [getPos, editor]\n );\n\n return (\n <NodeViewWrapper>\n <div className=\"p-0 m-0\" data-drag-handle>\n {/* <RenderFields\n fieldMap={[\n {\n name: \"media\",\n type: \"upload\",\n cellComponentProps: {\n name: \"media\",\n schemaPath: \"media\",\n },\n fieldComponentProps: {},\n fieldIsPresentational: true,\n isFieldAffectingData: false,\n localized: false,\n },\n ]}\n path=\"media\"\n readOnly={false}\n schemaPath=\"\"\n // fieldTypes={fieldTypes}\n // fields={sidebarFields}\n // permissions={permissions.fields}\n // readOnly={!hasSavePermission}\n /> */}\n <a\n href=\"#\"\n style={{\n padding: 5,\n borderRadius: 5,\n backgroundColor: \"blue\",\n color: \"white\",\n cursor: \"pointer\",\n }}\n onClick={(e) => {\n e.preventDefault();\n openAssetHQHandler(onUpload);\n }}\n >\n Select an asset\n </a>\n {/* <ImageUploader onUpload={onUpload} /> */}\n </div>\n </NodeViewWrapper>\n );\n };\n\n return ImageUpload;\n};\n"],"names":["NodeViewWrapper","useCallback","ImageUploadBuilder","openAssetHQHandler","ImageUpload","getPos","editor","onUpload","asset","console","log","type","chain","focus","setImageBlock","src","fullUrl","deleteRange","from","to","run","setVideoBlock","videoUrl","poster","div","className","data-drag-handle","a","href","style","padding","borderRadius","backgroundColor","color","cursor","onClick","e","preventDefault"],"mappings":";AAAA,SAAiBA,eAAe,QAAQ,gBAAgB;AACxD,SAASC,WAAW,QAAQ,QAAQ;AAKpC,OAAO,MAAMC,qBAAqB,CAACC;IACjC,MAAMC,cAAc,CAAC,EACnBC,MAAM,EACNC,MAAM,EAIP;QACC,MAAMC,WAAWN,YACf,CAACO;YACC,IAAIA,OAAO;gBACTC,QAAQC,GAAG,CAAC,gCAAgCF;gBAC5C,IAAIA,MAAMG,IAAI,KAAK,SAAS;oBAC1BL,OACGM,KAAK,GACLC,KAAK,GACLC,aAAa,CAAC;wBAAEC,KAAKP,MAAMQ,OAAO;oBAAC,GAAG,8GAA8G;qBACpJC,WAAW,CAAC;wBAAEC,MAAMb;wBAAUc,IAAId;oBAAS,GAC3CQ,KAAK,GACLO,GAAG;gBACR,OAAO;oBACLd,OACGM,KAAK,GACLC,KAAK,GACLQ,aAAa,CAAC;wBAAEN,KAAKP,MAAMc,QAAQ;wBAAEC,QAAQf,MAAMQ,OAAO;oBAAC,GAC3DC,WAAW,CAAC;wBAAEC,MAAMb;wBAAUc,IAAId;oBAAS,GAC3CQ,KAAK,GACLO,GAAG;gBACR;YACF;QACF,GACA;YAACf;YAAQC;SAAO;QAGlB,qBACE,KAACN;sBACC,cAAA,KAACwB;gBAAIC,WAAU;gBAAUC,kBAAgB;0BAwBvC,cAAA,KAACC;oBACCC,MAAK;oBACLC,OAAO;wBACLC,SAAS;wBACTC,cAAc;wBACdC,iBAAiB;wBACjBC,OAAO;wBACPC,QAAQ;oBACV;oBACAC,SAAS,CAACC;wBACRA,EAAEC,cAAc;wBAChBlC,mBAAmBI;oBACrB;8BACD;;;;IAOT;IAEA,OAAOH;AACT,EAAE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Node } from "@tiptap/core";
|
|
2
|
+
export interface VideoOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Controls if the image node should be inline or not.
|
|
5
|
+
* @default false
|
|
6
|
+
* @example true
|
|
7
|
+
*/
|
|
8
|
+
inline: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Controls if base64 images are allowed. Enable this if you want to allow
|
|
11
|
+
* base64 image urls in the `src` attribute.
|
|
12
|
+
* @default false
|
|
13
|
+
* @example true
|
|
14
|
+
*/
|
|
15
|
+
allowBase64: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* HTML attributes to add to the image element.
|
|
18
|
+
* @default {}
|
|
19
|
+
* @example { class: 'foo' }
|
|
20
|
+
*/
|
|
21
|
+
HTMLAttributes: Record<string, any>;
|
|
22
|
+
}
|
|
23
|
+
declare module "@tiptap/core" {
|
|
24
|
+
interface Commands<ReturnType> {
|
|
25
|
+
video: {
|
|
26
|
+
/**
|
|
27
|
+
* Add an image
|
|
28
|
+
* @param options The image attributes
|
|
29
|
+
* @example
|
|
30
|
+
* editor
|
|
31
|
+
* .commands
|
|
32
|
+
* .setVideo({ src: 'https://tiptap.dev/logo.png', alt: 'tiptap', title: 'tiptap logo' })
|
|
33
|
+
*/
|
|
34
|
+
setVideo: (options: {
|
|
35
|
+
src: string;
|
|
36
|
+
alt?: string;
|
|
37
|
+
title?: string;
|
|
38
|
+
poster?: string;
|
|
39
|
+
}) => ReturnType;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Matches an image to a  on input.
|
|
45
|
+
*/
|
|
46
|
+
export declare const inputRegex: RegExp;
|
|
47
|
+
/**
|
|
48
|
+
* This extension allows you to insert images.
|
|
49
|
+
* @see https://www.tiptap.dev/api/nodes/image
|
|
50
|
+
*/
|
|
51
|
+
export declare const Video: Node<VideoOptions, any>;
|
|
52
|
+
//# sourceMappingURL=Video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Video.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Video/Video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAiB,MAAM,cAAc,CAAC;AAEpE,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;OAKG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC;AAED,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,KAAK,EAAE;YACL;;;;;;;eAOG;YACH,QAAQ,EAAE,CAAC,OAAO,EAAE;gBAClB,GAAG,EAAE,MAAM,CAAC;gBACZ,GAAG,CAAC,EAAE,MAAM,CAAC;gBACb,KAAK,CAAC,EAAE,MAAM,CAAC;gBACf,MAAM,CAAC,EAAE,MAAM,CAAC;aACjB,KAAK,UAAU,CAAC;SAClB,CAAC;KACH;CACF;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,QACqC,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,KAAK,yBAiFhB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { mergeAttributes, Node, nodeInputRule } from "@tiptap/core";
|
|
2
|
+
/**
|
|
3
|
+
* Matches an image to a  on input.
|
|
4
|
+
*/ export const inputRegex = /(?:^|\s)(!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\))$/;
|
|
5
|
+
/**
|
|
6
|
+
* This extension allows you to insert images.
|
|
7
|
+
* @see https://www.tiptap.dev/api/nodes/image
|
|
8
|
+
*/ export const Video = Node.create({
|
|
9
|
+
name: "video",
|
|
10
|
+
addOptions () {
|
|
11
|
+
return {
|
|
12
|
+
inline: false,
|
|
13
|
+
allowBase64: false,
|
|
14
|
+
HTMLAttributes: {}
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
inline () {
|
|
18
|
+
return this.options.inline;
|
|
19
|
+
},
|
|
20
|
+
group () {
|
|
21
|
+
return this.options.inline ? "inline" : "block";
|
|
22
|
+
},
|
|
23
|
+
draggable: true,
|
|
24
|
+
addAttributes () {
|
|
25
|
+
return {
|
|
26
|
+
src: {
|
|
27
|
+
default: null
|
|
28
|
+
},
|
|
29
|
+
alt: {
|
|
30
|
+
default: null
|
|
31
|
+
},
|
|
32
|
+
title: {
|
|
33
|
+
default: null
|
|
34
|
+
},
|
|
35
|
+
poster: {
|
|
36
|
+
default: null
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
parseHTML () {
|
|
41
|
+
return [
|
|
42
|
+
{
|
|
43
|
+
tag: this.options.allowBase64 ? "video[src]" : 'video[src]:not([src^="data:"])'
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
},
|
|
47
|
+
renderHTML ({ HTMLAttributes }) {
|
|
48
|
+
return [
|
|
49
|
+
"video",
|
|
50
|
+
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
|
|
51
|
+
];
|
|
52
|
+
},
|
|
53
|
+
addCommands () {
|
|
54
|
+
return {
|
|
55
|
+
setVideo: (options)=>({ commands })=>{
|
|
56
|
+
return commands.insertContent({
|
|
57
|
+
type: this.name,
|
|
58
|
+
attrs: options
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
addInputRules () {
|
|
64
|
+
return [
|
|
65
|
+
nodeInputRule({
|
|
66
|
+
find: inputRegex,
|
|
67
|
+
type: this.type,
|
|
68
|
+
getAttributes: (match)=>{
|
|
69
|
+
const [, , alt, src, title] = match;
|
|
70
|
+
return {
|
|
71
|
+
src,
|
|
72
|
+
alt,
|
|
73
|
+
title
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=Video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Video/Video.ts"],"sourcesContent":["import { mergeAttributes, Node, nodeInputRule } from \"@tiptap/core\";\n\nexport interface VideoOptions {\n /**\n * Controls if the image node should be inline or not.\n * @default false\n * @example true\n */\n inline: boolean;\n\n /**\n * Controls if base64 images are allowed. Enable this if you want to allow\n * base64 image urls in the `src` attribute.\n * @default false\n * @example true\n */\n allowBase64: boolean;\n\n /**\n * HTML attributes to add to the image element.\n * @default {}\n * @example { class: 'foo' }\n */\n HTMLAttributes: Record<string, any>;\n}\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n video: {\n /**\n * Add an image\n * @param options The image attributes\n * @example\n * editor\n * .commands\n * .setVideo({ src: 'https://tiptap.dev/logo.png', alt: 'tiptap', title: 'tiptap logo' })\n */\n setVideo: (options: {\n src: string;\n alt?: string;\n title?: string;\n poster?: string;\n }) => ReturnType;\n };\n }\n}\n\n/**\n * Matches an image to a  on input.\n */\nexport const inputRegex =\n /(?:^|\\s)(!\\[(.+|:?)]\\((\\S+)(?:(?:\\s+)[\"'](\\S+)[\"'])?\\))$/;\n\n/**\n * This extension allows you to insert images.\n * @see https://www.tiptap.dev/api/nodes/image\n */\nexport const Video = Node.create<VideoOptions>({\n name: \"video\",\n\n addOptions() {\n return {\n inline: false,\n allowBase64: false,\n HTMLAttributes: {},\n };\n },\n\n inline() {\n return this.options.inline;\n },\n\n group() {\n return this.options.inline ? \"inline\" : \"block\";\n },\n\n draggable: true,\n\n addAttributes() {\n return {\n src: {\n default: null,\n },\n alt: {\n default: null,\n },\n title: {\n default: null,\n },\n poster: {\n default: null,\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: this.options.allowBase64\n ? \"video[src]\"\n : 'video[src]:not([src^=\"data:\"])',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"video\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n ];\n },\n\n addCommands() {\n return {\n setVideo:\n (options) =>\n ({ commands }) => {\n return commands.insertContent({\n type: this.name,\n attrs: options,\n });\n },\n };\n },\n\n addInputRules() {\n return [\n nodeInputRule({\n find: inputRegex,\n type: this.type,\n getAttributes: (match) => {\n const [, , alt, src, title] = match;\n\n return { src, alt, title };\n },\n }),\n ];\n },\n});\n"],"names":["mergeAttributes","Node","nodeInputRule","inputRegex","Video","create","name","addOptions","inline","allowBase64","HTMLAttributes","options","group","draggable","addAttributes","src","default","alt","title","poster","parseHTML","tag","renderHTML","addCommands","setVideo","commands","insertContent","type","attrs","addInputRules","find","getAttributes","match"],"mappings":"AAAA,SAASA,eAAe,EAAEC,IAAI,EAAEC,aAAa,QAAQ,eAAe;AA+CpE;;CAEC,GACD,OAAO,MAAMC,aACX,2DAA2D;AAE7D;;;CAGC,GACD,OAAO,MAAMC,QAAQH,KAAKI,MAAM,CAAe;IAC7CC,MAAM;IAENC;QACE,OAAO;YACLC,QAAQ;YACRC,aAAa;YACbC,gBAAgB,CAAC;QACnB;IACF;IAEAF;QACE,OAAO,IAAI,CAACG,OAAO,CAACH,MAAM;IAC5B;IAEAI;QACE,OAAO,IAAI,CAACD,OAAO,CAACH,MAAM,GAAG,WAAW;IAC1C;IAEAK,WAAW;IAEXC;QACE,OAAO;YACLC,KAAK;gBACHC,SAAS;YACX;YACAC,KAAK;gBACHD,SAAS;YACX;YACAE,OAAO;gBACLF,SAAS;YACX;YACAG,QAAQ;gBACNH,SAAS;YACX;QACF;IACF;IAEAI;QACE,OAAO;YACL;gBACEC,KAAK,IAAI,CAACV,OAAO,CAACF,WAAW,GACzB,eACA;YACN;SACD;IACH;IAEAa,YAAW,EAAEZ,cAAc,EAAE;QAC3B,OAAO;YACL;YACAV,gBAAgB,IAAI,CAACW,OAAO,CAACD,cAAc,EAAEA;SAC9C;IACH;IAEAa;QACE,OAAO;YACLC,UACE,CAACb,UACD,CAAC,EAAEc,QAAQ,EAAE;oBACX,OAAOA,SAASC,aAAa,CAAC;wBAC5BC,MAAM,IAAI,CAACrB,IAAI;wBACfsB,OAAOjB;oBACT;gBACF;QACJ;IACF;IAEAkB;QACE,OAAO;YACL3B,cAAc;gBACZ4B,MAAM3B;gBACNwB,MAAM,IAAI,CAACA,IAAI;gBACfI,eAAe,CAACC;oBACd,MAAM,KAAKf,KAAKF,KAAKG,MAAM,GAAGc;oBAE9B,OAAO;wBAAEjB;wBAAKE;wBAAKC;oBAAM;gBAC3B;YACF;SACD;IACH;AACF,GAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/Video/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/Video/index.ts"],"sourcesContent":["export * from \"./Video.js\";\n"],"names":[],"mappings":"AAAA,cAAc,aAAa"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Range } from "@tiptap/core";
|
|
2
|
+
declare module "@tiptap/core" {
|
|
3
|
+
interface Commands<ReturnType> {
|
|
4
|
+
videoBlock: {
|
|
5
|
+
setVideoBlock: (attributes: {
|
|
6
|
+
src: string;
|
|
7
|
+
poster: string;
|
|
8
|
+
}) => ReturnType;
|
|
9
|
+
setVideoBlockAt: (attributes: {
|
|
10
|
+
src: string;
|
|
11
|
+
poster: string;
|
|
12
|
+
pos: number | Range;
|
|
13
|
+
}) => ReturnType;
|
|
14
|
+
setVideoBlockAlign: (align: "left" | "center" | "right") => ReturnType;
|
|
15
|
+
setVideoBlockWidth: (width: number) => ReturnType;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export declare const VideoBlock: import("@tiptap/react").Node<import("../Video/Video.js").VideoOptions, any>;
|
|
20
|
+
export default VideoBlock;
|
|
21
|
+
//# sourceMappingURL=VideoBlock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoBlock.d.ts","sourceRoot":"","sources":["../../../../../../src/fields/TiptapEditor/extensions/VideoBlock/VideoBlock.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,EAAE,MAAM,cAAc,CAAC;AAKtD,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,UAAU,EAAE;YACV,aAAa,EAAE,CAAC,UAAU,EAAE;gBAC1B,GAAG,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM,CAAC;aAChB,KAAK,UAAU,CAAC;YACjB,eAAe,EAAE,CAAC,UAAU,EAAE;gBAC5B,GAAG,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM,CAAC;gBACf,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;aACrB,KAAK,UAAU,CAAC;YACjB,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,KAAK,UAAU,CAAC;YACvE,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,UAAU,CAAC;SACnD,CAAC;KACH;CACF;AAED,eAAO,MAAM,UAAU,6EAqGrB,CAAC;AAEH,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { ReactNodeViewRenderer } from "@tiptap/react";
|
|
3
|
+
import { mergeAttributes } from "@tiptap/core";
|
|
4
|
+
import { VideoBlockView } from "./components/VideoBlockView.js";
|
|
5
|
+
import { Video } from "../Video/Video.js";
|
|
6
|
+
export const VideoBlock = Video.extend({
|
|
7
|
+
name: "videoBlock",
|
|
8
|
+
group: "block",
|
|
9
|
+
defining: true,
|
|
10
|
+
isolating: true,
|
|
11
|
+
addAttributes () {
|
|
12
|
+
return {
|
|
13
|
+
src: {
|
|
14
|
+
default: "",
|
|
15
|
+
parseHTML: (element)=>element.getAttribute("src"),
|
|
16
|
+
renderHTML: (attributes)=>({
|
|
17
|
+
src: attributes.src
|
|
18
|
+
})
|
|
19
|
+
},
|
|
20
|
+
poster: {
|
|
21
|
+
default: "",
|
|
22
|
+
parseHTML: (element)=>element.getAttribute("poster"),
|
|
23
|
+
renderHTML: (attributes)=>({
|
|
24
|
+
poster: attributes.poster
|
|
25
|
+
})
|
|
26
|
+
},
|
|
27
|
+
width: {
|
|
28
|
+
default: "100%",
|
|
29
|
+
parseHTML: (element)=>element.getAttribute("data-width"),
|
|
30
|
+
renderHTML: (attributes)=>({
|
|
31
|
+
"data-width": attributes.width
|
|
32
|
+
})
|
|
33
|
+
},
|
|
34
|
+
align: {
|
|
35
|
+
default: "center",
|
|
36
|
+
parseHTML: (element)=>element.getAttribute("data-align"),
|
|
37
|
+
renderHTML: (attributes)=>({
|
|
38
|
+
"data-align": attributes.align
|
|
39
|
+
})
|
|
40
|
+
},
|
|
41
|
+
alt: {
|
|
42
|
+
default: undefined,
|
|
43
|
+
parseHTML: (element)=>element.getAttribute("alt"),
|
|
44
|
+
renderHTML: (attributes)=>({
|
|
45
|
+
alt: attributes.alt
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
parseHTML () {
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
tag: 'video[src*="tiptap.dev"]:not([src^="data:"]), video[src*="windows.net"]:not([src^="data:"])'
|
|
54
|
+
}
|
|
55
|
+
];
|
|
56
|
+
},
|
|
57
|
+
renderHTML ({ HTMLAttributes }) {
|
|
58
|
+
return [
|
|
59
|
+
"video",
|
|
60
|
+
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)
|
|
61
|
+
];
|
|
62
|
+
},
|
|
63
|
+
addCommands () {
|
|
64
|
+
return {
|
|
65
|
+
setVideoBlock: (attrs)=>({ commands })=>{
|
|
66
|
+
return commands.insertContent({
|
|
67
|
+
type: "videoBlock",
|
|
68
|
+
attrs: {
|
|
69
|
+
src: attrs.src,
|
|
70
|
+
poster: attrs.poster
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
setVideoBlockAt: (attrs)=>({ commands })=>{
|
|
75
|
+
return commands.insertContentAt(attrs.pos, {
|
|
76
|
+
type: "videoBlock",
|
|
77
|
+
attrs: {
|
|
78
|
+
src: attrs.src,
|
|
79
|
+
poster: attrs.poster
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
setVideoBlockAlign: (align)=>({ commands })=>commands.updateAttributes("videoBlock", {
|
|
84
|
+
align
|
|
85
|
+
}),
|
|
86
|
+
setVideoBlockWidth: (width)=>({ commands })=>commands.updateAttributes("videoBlock", {
|
|
87
|
+
width: `${Math.max(0, Math.min(100, width))}%`
|
|
88
|
+
})
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
addNodeView () {
|
|
92
|
+
return ReactNodeViewRenderer(VideoBlockView);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
export default VideoBlock;
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=VideoBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/fields/TiptapEditor/extensions/VideoBlock/VideoBlock.ts"],"sourcesContent":["\"use client\";\n\nimport { ReactNodeViewRenderer } from \"@tiptap/react\";\nimport { mergeAttributes, Range } from \"@tiptap/core\";\n\nimport { VideoBlockView } from \"./components/VideoBlockView.js\";\nimport { Video } from \"../Video/Video.js\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n videoBlock: {\n setVideoBlock: (attributes: {\n src: string;\n poster: string;\n }) => ReturnType;\n setVideoBlockAt: (attributes: {\n src: string;\n poster: string;\n pos: number | Range;\n }) => ReturnType;\n setVideoBlockAlign: (align: \"left\" | \"center\" | \"right\") => ReturnType;\n setVideoBlockWidth: (width: number) => ReturnType;\n };\n }\n}\n\nexport const VideoBlock = Video.extend({\n name: \"videoBlock\",\n\n group: \"block\",\n\n defining: true,\n\n isolating: true,\n\n addAttributes() {\n return {\n src: {\n default: \"\",\n parseHTML: (element) => element.getAttribute(\"src\"),\n renderHTML: (attributes) => ({\n src: attributes.src,\n }),\n },\n poster: {\n default: \"\",\n parseHTML: (element) => element.getAttribute(\"poster\"),\n renderHTML: (attributes) => ({\n poster: attributes.poster,\n }),\n },\n width: {\n default: \"100%\",\n parseHTML: (element) => element.getAttribute(\"data-width\"),\n renderHTML: (attributes) => ({\n \"data-width\": attributes.width,\n }),\n },\n align: {\n default: \"center\",\n parseHTML: (element) => element.getAttribute(\"data-align\"),\n renderHTML: (attributes) => ({\n \"data-align\": attributes.align,\n }),\n },\n alt: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"alt\"),\n renderHTML: (attributes) => ({\n alt: attributes.alt,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'video[src*=\"tiptap.dev\"]:not([src^=\"data:\"]), video[src*=\"windows.net\"]:not([src^=\"data:\"])',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"video\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n ];\n },\n\n addCommands() {\n return {\n setVideoBlock:\n (attrs) =>\n ({ commands }) => {\n return commands.insertContent({\n type: \"videoBlock\",\n attrs: { src: attrs.src, poster: attrs.poster },\n });\n },\n\n setVideoBlockAt:\n (attrs) =>\n ({ commands }) => {\n return commands.insertContentAt(attrs.pos, {\n type: \"videoBlock\",\n attrs: { src: attrs.src, poster: attrs.poster },\n });\n },\n\n setVideoBlockAlign:\n (align) =>\n ({ commands }) =>\n commands.updateAttributes(\"videoBlock\", { align }),\n\n setVideoBlockWidth:\n (width) =>\n ({ commands }) =>\n commands.updateAttributes(\"videoBlock\", {\n width: `${Math.max(0, Math.min(100, width))}%`,\n }),\n };\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(VideoBlockView);\n },\n});\n\nexport default VideoBlock;\n"],"names":["ReactNodeViewRenderer","mergeAttributes","VideoBlockView","Video","VideoBlock","extend","name","group","defining","isolating","addAttributes","src","default","parseHTML","element","getAttribute","renderHTML","attributes","poster","width","align","alt","undefined","tag","HTMLAttributes","options","addCommands","setVideoBlock","attrs","commands","insertContent","type","setVideoBlockAt","insertContentAt","pos","setVideoBlockAlign","updateAttributes","setVideoBlockWidth","Math","max","min","addNodeView"],"mappings":"AAAA;AAEA,SAASA,qBAAqB,QAAQ,gBAAgB;AACtD,SAASC,eAAe,QAAe,eAAe;AAEtD,SAASC,cAAc,QAAQ,iCAAiC;AAChE,SAASC,KAAK,QAAQ,oBAAoB;AAoB1C,OAAO,MAAMC,aAAaD,MAAME,MAAM,CAAC;IACrCC,MAAM;IAENC,OAAO;IAEPC,UAAU;IAEVC,WAAW;IAEXC;QACE,OAAO;YACLC,KAAK;gBACHC,SAAS;gBACTC,WAAW,CAACC,UAAYA,QAAQC,YAAY,CAAC;gBAC7CC,YAAY,CAACC,aAAgB,CAAA;wBAC3BN,KAAKM,WAAWN,GAAG;oBACrB,CAAA;YACF;YACAO,QAAQ;gBACNN,SAAS;gBACTC,WAAW,CAACC,UAAYA,QAAQC,YAAY,CAAC;gBAC7CC,YAAY,CAACC,aAAgB,CAAA;wBAC3BC,QAAQD,WAAWC,MAAM;oBAC3B,CAAA;YACF;YACAC,OAAO;gBACLP,SAAS;gBACTC,WAAW,CAACC,UAAYA,QAAQC,YAAY,CAAC;gBAC7CC,YAAY,CAACC,aAAgB,CAAA;wBAC3B,cAAcA,WAAWE,KAAK;oBAChC,CAAA;YACF;YACAC,OAAO;gBACLR,SAAS;gBACTC,WAAW,CAACC,UAAYA,QAAQC,YAAY,CAAC;gBAC7CC,YAAY,CAACC,aAAgB,CAAA;wBAC3B,cAAcA,WAAWG,KAAK;oBAChC,CAAA;YACF;YACAC,KAAK;gBACHT,SAASU;gBACTT,WAAW,CAACC,UAAYA,QAAQC,YAAY,CAAC;gBAC7CC,YAAY,CAACC,aAAgB,CAAA;wBAC3BI,KAAKJ,WAAWI,GAAG;oBACrB,CAAA;YACF;QACF;IACF;IAEAR;QACE,OAAO;YACL;gBACEU,KAAK;YACP;SACD;IACH;IAEAP,YAAW,EAAEQ,cAAc,EAAE;QAC3B,OAAO;YACL;YACAvB,gBAAgB,IAAI,CAACwB,OAAO,CAACD,cAAc,EAAEA;SAC9C;IACH;IAEAE;QACE,OAAO;YACLC,eACE,CAACC,QACD,CAAC,EAAEC,QAAQ,EAAE;oBACX,OAAOA,SAASC,aAAa,CAAC;wBAC5BC,MAAM;wBACNH,OAAO;4BAAEjB,KAAKiB,MAAMjB,GAAG;4BAAEO,QAAQU,MAAMV,MAAM;wBAAC;oBAChD;gBACF;YAEFc,iBACE,CAACJ,QACD,CAAC,EAAEC,QAAQ,EAAE;oBACX,OAAOA,SAASI,eAAe,CAACL,MAAMM,GAAG,EAAE;wBACzCH,MAAM;wBACNH,OAAO;4BAAEjB,KAAKiB,MAAMjB,GAAG;4BAAEO,QAAQU,MAAMV,MAAM;wBAAC;oBAChD;gBACF;YAEFiB,oBACE,CAACf,QACD,CAAC,EAAES,QAAQ,EAAE,GACXA,SAASO,gBAAgB,CAAC,cAAc;wBAAEhB;oBAAM;YAEpDiB,oBACE,CAAClB,QACD,CAAC,EAAEU,QAAQ,EAAE,GACXA,SAASO,gBAAgB,CAAC,cAAc;wBACtCjB,OAAO,CAAC,EAAEmB,KAAKC,GAAG,CAAC,GAAGD,KAAKE,GAAG,CAAC,KAAKrB,QAAQ,CAAC,CAAC;oBAChD;QACN;IACF;IAEAsB;QACE,OAAOzC,sBAAsBE;IAC/B;AACF,GAAG;AAEH,eAAeE,WAAW"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoBlockMenu.d.ts","sourceRoot":"","sources":["../../../../../../../src/fields/TiptapEditor/extensions/VideoBlock/components/VideoBlockMenu.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAuB,MAAM,OAAO,CAAC;AASvD,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAM7D,eAAO,MAAM,cAAc,yBAA0B,SAAS,KAAG,SA6GhE,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react";
|
|
3
|
+
import { useCallback, useRef } from "react";
|
|
4
|
+
import { sticky } from "tippy.js";
|
|
5
|
+
import { v4 as uuid } from "uuid";
|
|
6
|
+
import { AlignHorizontalDistributeCenter, AlignHorizontalDistributeEnd, AlignHorizontalDistributeStart } from "lucide-react";
|
|
7
|
+
import { Icon } from "../../../features/ui/Icon.js";
|
|
8
|
+
import { Toolbar } from "../../../features/ui/Toolbar.js";
|
|
9
|
+
import { getRenderContainer } from "../../../lib/utils/index.js";
|
|
10
|
+
import { VideoBlockWidth } from "./VideoBlockWidth.js";
|
|
11
|
+
export const VideoBlockMenu = ({ editor, appendTo })=>{
|
|
12
|
+
const menuRef = useRef(null);
|
|
13
|
+
const tippyInstance = useRef(null);
|
|
14
|
+
const getReferenceClientRect = useCallback(()=>{
|
|
15
|
+
const renderContainer = getRenderContainer(editor, "node-videoBlock");
|
|
16
|
+
const rect = renderContainer?.getBoundingClientRect() || new DOMRect(-1000, -1000, 0, 0);
|
|
17
|
+
return rect;
|
|
18
|
+
}, [
|
|
19
|
+
editor
|
|
20
|
+
]);
|
|
21
|
+
const shouldShow = useCallback(()=>{
|
|
22
|
+
const isActive = editor.isActive("videoBlock");
|
|
23
|
+
return isActive;
|
|
24
|
+
}, [
|
|
25
|
+
editor
|
|
26
|
+
]);
|
|
27
|
+
const onAlignVideoLeft = useCallback(()=>{
|
|
28
|
+
editor.chain().focus(undefined, {
|
|
29
|
+
scrollIntoView: false
|
|
30
|
+
}).setVideoBlockAlign("left").run();
|
|
31
|
+
}, [
|
|
32
|
+
editor
|
|
33
|
+
]);
|
|
34
|
+
const onAlignVideoCenter = useCallback(()=>{
|
|
35
|
+
editor.chain().focus(undefined, {
|
|
36
|
+
scrollIntoView: false
|
|
37
|
+
}).setVideoBlockAlign("center").run();
|
|
38
|
+
}, [
|
|
39
|
+
editor
|
|
40
|
+
]);
|
|
41
|
+
const onAlignVideoRight = useCallback(()=>{
|
|
42
|
+
editor.chain().focus(undefined, {
|
|
43
|
+
scrollIntoView: false
|
|
44
|
+
}).setVideoBlockAlign("right").run();
|
|
45
|
+
}, [
|
|
46
|
+
editor
|
|
47
|
+
]);
|
|
48
|
+
const onWidthChange = useCallback((value)=>{
|
|
49
|
+
editor.chain().focus(undefined, {
|
|
50
|
+
scrollIntoView: false
|
|
51
|
+
}).setVideoBlockWidth(value).run();
|
|
52
|
+
}, [
|
|
53
|
+
editor
|
|
54
|
+
]);
|
|
55
|
+
return /*#__PURE__*/ _jsx(BaseBubbleMenu, {
|
|
56
|
+
editor: editor,
|
|
57
|
+
pluginKey: `videoBlockMenu-${uuid()}`,
|
|
58
|
+
shouldShow: shouldShow,
|
|
59
|
+
updateDelay: 0,
|
|
60
|
+
tippyOptions: {
|
|
61
|
+
offset: [
|
|
62
|
+
0,
|
|
63
|
+
8
|
|
64
|
+
],
|
|
65
|
+
popperOptions: {
|
|
66
|
+
modifiers: [
|
|
67
|
+
{
|
|
68
|
+
name: "flip",
|
|
69
|
+
enabled: false
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
getReferenceClientRect,
|
|
74
|
+
onCreate: (instance)=>{
|
|
75
|
+
tippyInstance.current = instance;
|
|
76
|
+
},
|
|
77
|
+
appendTo: ()=>{
|
|
78
|
+
return appendTo?.current;
|
|
79
|
+
},
|
|
80
|
+
plugins: [
|
|
81
|
+
sticky
|
|
82
|
+
],
|
|
83
|
+
sticky: "popper"
|
|
84
|
+
},
|
|
85
|
+
children: /*#__PURE__*/ _jsxs(Toolbar.Wrapper, {
|
|
86
|
+
shouldShowContent: shouldShow(),
|
|
87
|
+
ref: menuRef,
|
|
88
|
+
children: [
|
|
89
|
+
/*#__PURE__*/ _jsx(Toolbar.Button, {
|
|
90
|
+
type: "button",
|
|
91
|
+
tooltip: "Align video left",
|
|
92
|
+
active: editor.isActive("videoBlock", {
|
|
93
|
+
align: "left"
|
|
94
|
+
}),
|
|
95
|
+
onClick: onAlignVideoLeft,
|
|
96
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
97
|
+
icon: AlignHorizontalDistributeStart
|
|
98
|
+
})
|
|
99
|
+
}),
|
|
100
|
+
/*#__PURE__*/ _jsx(Toolbar.Button, {
|
|
101
|
+
type: "button",
|
|
102
|
+
tooltip: "Align video center",
|
|
103
|
+
active: editor.isActive("videoBlock", {
|
|
104
|
+
align: "center"
|
|
105
|
+
}),
|
|
106
|
+
onClick: onAlignVideoCenter,
|
|
107
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
108
|
+
icon: AlignHorizontalDistributeCenter
|
|
109
|
+
})
|
|
110
|
+
}),
|
|
111
|
+
/*#__PURE__*/ _jsx(Toolbar.Button, {
|
|
112
|
+
type: "button",
|
|
113
|
+
tooltip: "Align video right",
|
|
114
|
+
active: editor.isActive("videoBlock", {
|
|
115
|
+
align: "right"
|
|
116
|
+
}),
|
|
117
|
+
onClick: onAlignVideoRight,
|
|
118
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
119
|
+
icon: AlignHorizontalDistributeEnd
|
|
120
|
+
})
|
|
121
|
+
}),
|
|
122
|
+
/*#__PURE__*/ _jsx(Toolbar.Divider, {}),
|
|
123
|
+
/*#__PURE__*/ _jsx(VideoBlockWidth, {
|
|
124
|
+
onChange: onWidthChange,
|
|
125
|
+
value: parseInt(editor.getAttributes("videoBlock").width)
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
export default VideoBlockMenu;
|
|
132
|
+
|
|
133
|
+
//# sourceMappingURL=VideoBlockMenu.js.map
|