Skip to content

Commit 42d6937

Browse files
committed
fix: added react node view and pass react node as props
1 parent 42ef3d1 commit 42d6937

File tree

4 files changed

+33
-72
lines changed

4 files changed

+33
-72
lines changed

src/MixInput.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import { type MixInputProps, type MixInputRef, type MixInputValue } from './MixI
1313

1414
const DEFAULT_TAG_ATTRS = {
1515
id: undefined,
16-
label: undefined,
17-
class: undefined,
16+
label: 'undefined',
17+
className: undefined,
1818
style: undefined,
1919
}
2020

@@ -30,15 +30,15 @@ const MixInput = forwardRef((props: MixInputProps, ref: ForwardedRef<MixInputRef
3030
editorOptions,
3131
className,
3232
tagAttrs,
33-
tagEventHandlers,
33+
tagView,
3434
...restProps
3535
} = props
3636

3737
const editorRef = useRef<HTMLDivElement>(null)
3838

3939
const editor = useEditor({
4040
editorProps: {
41-
attributes: { class: `mix-input ${className}` },
41+
attributes: { class: `mix-input ${className || ''}` },
4242
},
4343
extensions: [
4444
Document,
@@ -50,7 +50,7 @@ const MixInput = forwardRef((props: MixInputProps, ref: ForwardedRef<MixInputRef
5050
TagExtension.configure({
5151
tagClassName,
5252
attrs: { ...DEFAULT_TAG_ATTRS, ...tagAttrs },
53-
eventHandlers: tagEventHandlers,
53+
tagView,
5454
}),
5555
],
5656
onUpdate: ({ editor }) => {

src/MixInputType.d.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import '@total-typescript/ts-reset'
2-
import { Editor, } from '@tiptap/core'
3-
import { EditorContentProps, UseEditorOptions } from '@tiptap/react'
2+
import { Editor, NodeViewProps } from '@tiptap/core'
3+
import { EditorContentProps, UseEditorOptions, NodeViewProps } from '@tiptap/react'
44

5-
import type { CSSProperties, HTMLAttributes } from 'react'
5+
import type { CSSProperties, HTMLAttributes, ReactNode } from 'react'
66
export interface Tag {
77
type: 'tag'
88
attrs: {
99
id?: string
1010
label?: string
11-
class?: string | string[]
11+
className?: string
1212
style?: CSSProperties
13-
[key: string]: string | string[] | CSSProperties | undefined
13+
[key: string]: string | CSSProperties | undefined
1414
}
1515
}
1616

@@ -26,7 +26,7 @@ export interface MixInputProps extends HTMLAttributes<HTMLDivElement>, Omit<Edit
2626
tagClassName?: string
2727
editorOptions?: UseEditorOptions
2828
tagAttrs?: Record<string, string | undefined>
29-
tagEventHandlers?: Record<string, (event: Event, view: Editor) => void>
29+
tagView?: (props: NodeViewProps) => React.ReactNode
3030
// multiline?: boolean
3131
// showTagDeleteBtn?: boolean
3232
}

src/Tag.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { type NodeViewProps, NodeViewWrapper } from '@tiptap/react'
2+
import React from 'react'
3+
4+
export default function Tag(props: NodeViewProps) {
5+
const { tagView, tagClassName } = props.extension.options
6+
const { label, ...restAttrs } = props.node.attrs
7+
return (
8+
<>
9+
<NodeViewWrapper className={`mi-tag ${tagClassName || ''}`} data-type="tag" as="span">
10+
{tagView ? tagView(props) : <span {...restAttrs}>{label}</span>}
11+
</NodeViewWrapper>
12+
{'\u200B'}
13+
</>
14+
)
15+
}

src/TagExtension.ts

Lines changed: 7 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { Attribute, mergeAttributes, Node } from "@tiptap/core";
2+
import { ReactNodeViewRenderer } from "@tiptap/react";
3+
import Tag from "./Tag";
24

35
export default Node.create({
46
name: "tag",
@@ -12,71 +14,15 @@ export default Node.create({
1214
{
1315
tag: `span[data-type="${this.name}"]`,
1416
},
15-
];
17+
]
1618
},
1719

1820
renderHTML({ HTMLAttributes }) {
1921
return ["span", mergeAttributes(HTMLAttributes)];
2022
},
2123

22-
23-
addNodeView: () => ({ node, extension }) => {
24-
const span = document.createElement('span');
25-
span.className = 'mi-tag'
26-
const { label, id, class: classes, style, ...restAttrs } = node.attrs
27-
span.innerHTML = label
28-
span.setAttribute('data-type', 'tag')
29-
30-
if (id) {
31-
span.setAttribute('data-id', id)
32-
}
33-
34-
if (extension.options.tagClassName) {
35-
span.classList.add(extension.options.tagClassName)
36-
}
37-
38-
if (classes) {
39-
if (Array.isArray(classes)) {
40-
classes.forEach((c) => {
41-
span.classList.add(c as string)
42-
})
43-
} else {
44-
span.classList.add(classes)
45-
}
46-
}
47-
48-
if (style) {
49-
Object.assign(span.style, style)
50-
}
51-
52-
if (Object.keys(restAttrs).length) {
53-
Object.keys(restAttrs).forEach((key) => {
54-
span.dataset[key] = restAttrs[key]
55-
})
56-
}
57-
58-
// Add event listeners
59-
if (extension.options.eventHandlers) {
60-
Object.entries(extension.options.eventHandlers).forEach(([eventName, handler]) => {
61-
span.addEventListener(eventName, handler as EventListener)
62-
})
63-
}
64-
65-
const dom = document.createElement('span')
66-
dom.appendChild(span)
67-
// add zero-width space to make caret visible to outside of tag
68-
dom.appendChild(document.createTextNode('\u200B'))
69-
70-
return {
71-
dom,
72-
destroy: () => {
73-
if (extension.options.eventHandlers) {
74-
Object.entries(extension.options.eventHandlers).forEach(([eventName, handler]) => {
75-
span.removeEventListener(eventName, handler as EventListener)
76-
})
77-
}
78-
}
79-
}
24+
addNodeView() {
25+
return ReactNodeViewRenderer(Tag)
8026
},
8127

8228
addAttributes() {
@@ -85,5 +31,5 @@ export default Node.create({
8531
extraAttrs[key] = { default: this.options.attrs[key] }
8632
}
8733
return extraAttrs
88-
}
89-
});
34+
},
35+
})

0 commit comments

Comments
 (0)