forked from 77media/video-flow
76 lines
1.4 KiB
TypeScript
76 lines
1.4 KiB
TypeScript
import { Node, mergeAttributes } from '@tiptap/core'
|
|
import React from 'react'
|
|
import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'
|
|
|
|
declare module '@tiptap/core' {
|
|
interface Commands<ReturnType> {
|
|
readonlyText: {
|
|
insertReadonlyText: (text: string) => ReturnType
|
|
}
|
|
}
|
|
}
|
|
|
|
export const ReadonlyText = Node.create({
|
|
name: 'readonlyText',
|
|
|
|
group: 'inline',
|
|
inline: true,
|
|
atom: true, // 不可拆分
|
|
selectable: false,
|
|
|
|
addAttributes() {
|
|
return {
|
|
text: {
|
|
default: '',
|
|
},
|
|
}
|
|
},
|
|
|
|
parseHTML() {
|
|
return [
|
|
{
|
|
tag: 'span[data-readonly-text]',
|
|
},
|
|
]
|
|
},
|
|
|
|
renderHTML({ HTMLAttributes }) {
|
|
return [
|
|
'span',
|
|
mergeAttributes(HTMLAttributes, {
|
|
'data-readonly-text': '',
|
|
}),
|
|
]
|
|
},
|
|
|
|
addNodeView() {
|
|
return ReactNodeViewRenderer(ReadonlyTextView)
|
|
},
|
|
|
|
addCommands() {
|
|
return {
|
|
insertReadonlyText:
|
|
(text: string) =>
|
|
({ commands }) => {
|
|
return commands.insertContent({
|
|
type: this.name,
|
|
attrs: { text },
|
|
})
|
|
},
|
|
}
|
|
},
|
|
})
|
|
|
|
const ReadonlyTextView = (props: any) => {
|
|
return (
|
|
<NodeViewWrapper
|
|
as="span"
|
|
className="text-gray-400 px-1 select-none pointer-events-none"
|
|
contentEditable={false}
|
|
data-readonly-text
|
|
>
|
|
{props.node.attrs.text}
|
|
</NodeViewWrapper>
|
|
)
|
|
}
|