refactoring
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import tippy, { sticky } from 'tippy.js'
|
import tippy from 'tippy.js'
|
||||||
import { Editor, EditorContent, VueRenderer } from '@tiptap/vue'
|
import { Editor, EditorContent, VueRenderer } from '@tiptap/vue'
|
||||||
import Document from '@tiptap/extension-document'
|
import Document from '@tiptap/extension-document'
|
||||||
import Paragraph from '@tiptap/extension-paragraph'
|
import Paragraph from '@tiptap/extension-paragraph'
|
||||||
@@ -34,7 +34,7 @@ export default {
|
|||||||
items: query => {
|
items: query => {
|
||||||
return ['Hans', 'Philipp', 'Kris'].filter(item => item.startsWith(query))
|
return ['Hans', 'Philipp', 'Kris'].filter(item => item.startsWith(query))
|
||||||
},
|
},
|
||||||
renderer: () => {
|
render: () => {
|
||||||
let component
|
let component
|
||||||
let popup
|
let popup
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ Have a look at all of the core commands listed below. They should give you a goo
|
|||||||
| .lift() | Removes an existing wrap. |
|
| .lift() | Removes an existing wrap. |
|
||||||
| .liftEmptyBlock() | Lift block if empty. |
|
| .liftEmptyBlock() | Lift block if empty. |
|
||||||
| .newlineInCode() | Add a newline character in code. |
|
| .newlineInCode() | Add a newline character in code. |
|
||||||
|
| .replace() | Replaces text with a node within a range. |
|
||||||
| .resetNodeAttributes() | Resets all node attributes to the default value. |
|
| .resetNodeAttributes() | Resets all node attributes to the default value. |
|
||||||
| .selectParentNode() | Select the parent node. |
|
| .selectParentNode() | Select the parent node. |
|
||||||
| .setMark() | Add a mark with new attributes. |
|
| .setMark() | Add a mark with new attributes. |
|
||||||
|
|||||||
29
packages/core/src/commands/replace.ts
Normal file
29
packages/core/src/commands/replace.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { NodeType } from 'prosemirror-model'
|
||||||
|
import getNodeType from '../helpers/getNodeType'
|
||||||
|
import { Command } from '../types'
|
||||||
|
|
||||||
|
export type Range = {
|
||||||
|
from: number,
|
||||||
|
to: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces text with a node within a range.
|
||||||
|
*/
|
||||||
|
export const replace = (range: Range | null = null, typeOrName: string | NodeType, attrs = {}): Command => ({ tr, state, dispatch }) => {
|
||||||
|
const type = getNodeType(typeOrName, state.schema)
|
||||||
|
const { $from, $to } = state.selection
|
||||||
|
const index = $from.index()
|
||||||
|
const from = range ? range.from : $from.pos
|
||||||
|
const to = range ? range.to : $to.pos
|
||||||
|
|
||||||
|
if (!$from.parent.canReplaceWith(index, index, type)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dispatch) {
|
||||||
|
tr.replaceWith(from, to, type.create(attrs))
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ import * as lift from '../commands/lift'
|
|||||||
import * as liftEmptyBlock from '../commands/liftEmptyBlock'
|
import * as liftEmptyBlock from '../commands/liftEmptyBlock'
|
||||||
import * as liftListItem from '../commands/liftListItem'
|
import * as liftListItem from '../commands/liftListItem'
|
||||||
import * as newlineInCode from '../commands/newlineInCode'
|
import * as newlineInCode from '../commands/newlineInCode'
|
||||||
|
import * as replace from '../commands/replace'
|
||||||
import * as resetNodeAttributes from '../commands/resetNodeAttributes'
|
import * as resetNodeAttributes from '../commands/resetNodeAttributes'
|
||||||
import * as scrollIntoView from '../commands/scrollIntoView'
|
import * as scrollIntoView from '../commands/scrollIntoView'
|
||||||
import * as selectAll from '../commands/selectAll'
|
import * as selectAll from '../commands/selectAll'
|
||||||
@@ -63,6 +64,7 @@ export const Commands = Extension.create({
|
|||||||
...liftEmptyBlock,
|
...liftEmptyBlock,
|
||||||
...liftListItem,
|
...liftListItem,
|
||||||
...newlineInCode,
|
...newlineInCode,
|
||||||
|
...replace,
|
||||||
...resetNodeAttributes,
|
...resetNodeAttributes,
|
||||||
...scrollIntoView,
|
...scrollIntoView,
|
||||||
...selectAll,
|
...selectAll,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const Mention = Node.create({
|
|||||||
|
|
||||||
defaultOptions: <MentionOptions>{
|
defaultOptions: <MentionOptions>{
|
||||||
char: '@',
|
char: '@',
|
||||||
renderer: () => ({}),
|
render: () => ({}),
|
||||||
},
|
},
|
||||||
|
|
||||||
group: 'inline',
|
group: 'inline',
|
||||||
@@ -47,6 +47,13 @@ export const Mention = Node.create({
|
|||||||
Suggestion({
|
Suggestion({
|
||||||
editor: this.editor,
|
editor: this.editor,
|
||||||
...this.options,
|
...this.options,
|
||||||
|
command: ({ range }) => {
|
||||||
|
this.editor
|
||||||
|
.chain()
|
||||||
|
.replace(range, 'mention')
|
||||||
|
.insertText(' ')
|
||||||
|
.run()
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ export interface SuggestionOptions {
|
|||||||
allowSpaces?: boolean,
|
allowSpaces?: boolean,
|
||||||
startOfLine?: boolean,
|
startOfLine?: boolean,
|
||||||
suggestionClass?: string,
|
suggestionClass?: string,
|
||||||
command?: () => any,
|
command?: (props: any) => any,
|
||||||
items?: (query: string) => any[],
|
items?: (query: string) => any[],
|
||||||
renderer?: () => {
|
render?: () => {
|
||||||
onStart?: (props: any) => void,
|
onStart?: (props: any) => void,
|
||||||
onUpdate?: (props: any) => void,
|
onUpdate?: (props: any) => void,
|
||||||
onExit?: (props: any) => void,
|
onExit?: (props: any) => void,
|
||||||
@@ -21,21 +21,16 @@ export interface SuggestionOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Suggestion({
|
export function Suggestion({
|
||||||
editor,
|
|
||||||
char = '@',
|
char = '@',
|
||||||
allowSpaces = false,
|
allowSpaces = false,
|
||||||
startOfLine = false,
|
startOfLine = false,
|
||||||
suggestionClass = 'suggestion',
|
suggestionClass = 'suggestion',
|
||||||
command = () => null,
|
command = () => null,
|
||||||
items = () => [],
|
items = () => [],
|
||||||
// onStart = () => null,
|
render = () => ({}),
|
||||||
// onUpdate = () => null,
|
|
||||||
// onExit = () => null,
|
|
||||||
// onKeyDown = () => null,
|
|
||||||
renderer = () => ({}),
|
|
||||||
}: SuggestionOptions) {
|
}: SuggestionOptions) {
|
||||||
|
|
||||||
const testRenderer = renderer?.()
|
const renderer = render?.()
|
||||||
|
|
||||||
return new Plugin({
|
return new Plugin({
|
||||||
key: new PluginKey('suggestions'),
|
key: new PluginKey('suggestions'),
|
||||||
@@ -67,45 +62,30 @@ export function Suggestion({
|
|||||||
range: state.range,
|
range: state.range,
|
||||||
query: state.query,
|
query: state.query,
|
||||||
text: state.text,
|
text: state.text,
|
||||||
|
items: (handleChange || handleStart)
|
||||||
|
? await items(state.query)
|
||||||
|
: [],
|
||||||
|
command: () => {
|
||||||
|
command({ range: state.range })
|
||||||
|
},
|
||||||
decorationNode,
|
decorationNode,
|
||||||
// build a virtual node for popper.js or tippy.js
|
// build a virtual node for popper.js or tippy.js
|
||||||
// this can be used for building popups without a DOM node
|
// this can be used for building popups without a DOM node
|
||||||
virtualNode: decorationNode
|
virtualNode: decorationNode
|
||||||
? getVirtualNode(decorationNode)
|
? getVirtualNode(decorationNode)
|
||||||
: null,
|
: null,
|
||||||
items: (handleChange || handleStart)
|
|
||||||
? await items(state.query)
|
|
||||||
: [],
|
|
||||||
command: () => {
|
|
||||||
console.log('command')
|
|
||||||
},
|
|
||||||
// command: ({ range, attrs }) => {
|
|
||||||
// command({
|
|
||||||
// range,
|
|
||||||
// attrs,
|
|
||||||
// schema: view.state.schema,
|
|
||||||
// })(view.state, view.dispatch, view)
|
|
||||||
|
|
||||||
// if (appendText) {
|
|
||||||
// insertText(appendText)(view.state, view.dispatch, view)
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger the hooks when necessary
|
|
||||||
if (handleExit) {
|
|
||||||
// onExit(props)
|
|
||||||
testRenderer?.onExit?.(props)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handleChange) {
|
|
||||||
// onUpdate(props)
|
|
||||||
testRenderer?.onUpdate?.(props)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handleStart) {
|
if (handleStart) {
|
||||||
// onStart(props)
|
renderer?.onStart?.(props)
|
||||||
testRenderer?.onStart?.(props)
|
}
|
||||||
|
|
||||||
|
if (handleChange) {
|
||||||
|
renderer?.onUpdate?.(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handleExit) {
|
||||||
|
renderer?.onExit?.(props)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -123,8 +103,8 @@ export function Suggestion({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Apply changes to the plugin state from a view transaction.
|
// Apply changes to the plugin state from a view transaction.
|
||||||
apply(tr, prev) {
|
apply(transaction, prev) {
|
||||||
const { selection } = tr
|
const { selection } = transaction
|
||||||
const next = { ...prev }
|
const next = { ...prev }
|
||||||
|
|
||||||
// We can only be suggesting if there is no selection
|
// We can only be suggesting if there is no selection
|
||||||
@@ -178,7 +158,7 @@ export function Suggestion({
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return testRenderer?.onKeyDown?.({ view, event, range }) || false
|
return renderer?.onKeyDown?.({ view, event, range }) || false
|
||||||
},
|
},
|
||||||
|
|
||||||
// Setup decorator on the currently active suggestion.
|
// Setup decorator on the currently active suggestion.
|
||||||
|
|||||||
Reference in New Issue
Block a user