mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-11-24 03:39:01 +08:00
feat(react): allow attrs to be a callback
This commit is contained in:
parent
c99627d7ce
commit
4ff2a4eaa1
5
.changeset/warm-bananas-call.md
Normal file
5
.changeset/warm-bananas-call.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/react": patch
|
||||
---
|
||||
|
||||
ReactNodeViewRenderer now accepts a callback for attrs of the wrapping element to be updated on each node view update
|
@ -1,6 +1,7 @@
|
||||
import {
|
||||
DecorationWithType,
|
||||
Editor,
|
||||
getRenderedAttributes,
|
||||
NodeView,
|
||||
NodeViewProps,
|
||||
NodeViewRenderer,
|
||||
@ -27,7 +28,12 @@ export interface ReactNodeViewRendererOptions extends NodeViewRendererOptions {
|
||||
| null
|
||||
as?: string
|
||||
className?: string
|
||||
attrs?: Record<string, string>
|
||||
attrs?:
|
||||
| Record<string, string>
|
||||
| ((props: {
|
||||
node: ProseMirrorNode
|
||||
HTMLAttributes: Record<string, any>
|
||||
}) => Record<string, string>)
|
||||
}
|
||||
|
||||
class ReactNodeView extends NodeView<
|
||||
@ -110,8 +116,9 @@ class ReactNodeView extends NodeView<
|
||||
props,
|
||||
as,
|
||||
className: `node-${this.node.type.name} ${className}`.trim(),
|
||||
attrs: this.options.attrs,
|
||||
})
|
||||
|
||||
this.updateElementAttributes()
|
||||
}
|
||||
|
||||
get dom() {
|
||||
@ -154,6 +161,9 @@ class ReactNodeView extends NodeView<
|
||||
update(node: ProseMirrorNode, decorations: DecorationWithType[]) {
|
||||
const updateProps = (props?: Record<string, any>) => {
|
||||
this.renderer.updateProps(props)
|
||||
if (typeof this.options.attrs === 'function') {
|
||||
this.updateElementAttributes()
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type !== this.node.type) {
|
||||
@ -207,6 +217,23 @@ class ReactNodeView extends NodeView<
|
||||
this.editor.off('selectionUpdate', this.handleSelectionUpdate)
|
||||
this.contentDOMElement = null
|
||||
}
|
||||
|
||||
updateElementAttributes() {
|
||||
if (this.options.attrs) {
|
||||
let attrsObj: Record<string, string> = {}
|
||||
|
||||
if (typeof this.options.attrs === 'function') {
|
||||
const extensionAttributes = this.editor.extensionManager.attributes
|
||||
const HTMLAttributes = getRenderedAttributes(this.node, extensionAttributes)
|
||||
|
||||
attrsObj = this.options.attrs({ node: this.node, HTMLAttributes })
|
||||
} else {
|
||||
attrsObj = this.options.attrs
|
||||
}
|
||||
|
||||
this.renderer.updateAttributes(attrsObj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function ReactNodeViewRenderer(
|
||||
|
@ -57,14 +57,6 @@ export interface ReactRendererOptions {
|
||||
* @example 'foo bar'
|
||||
*/
|
||||
className?: string,
|
||||
|
||||
/**
|
||||
* The attributes of the element.
|
||||
* @type {Record<string, string>}
|
||||
* @default {}
|
||||
* @example { 'data-foo': 'bar' }
|
||||
*/
|
||||
attrs?: Record<string, string>,
|
||||
}
|
||||
|
||||
type ComponentType<R, P> =
|
||||
@ -103,7 +95,6 @@ export class ReactRenderer<R = unknown, P = unknown> {
|
||||
props = {},
|
||||
as = 'div',
|
||||
className = '',
|
||||
attrs,
|
||||
}: ReactRendererOptions) {
|
||||
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
|
||||
this.component = component
|
||||
@ -116,12 +107,6 @@ export class ReactRenderer<R = unknown, P = unknown> {
|
||||
this.element.classList.add(...className.split(' '))
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
Object.keys(attrs).forEach(key => {
|
||||
this.element.setAttribute(key, attrs[key])
|
||||
})
|
||||
}
|
||||
|
||||
if (this.editor.isInitialized) {
|
||||
// On first render, we need to flush the render synchronously
|
||||
// Renders afterwards can be async, but this fixes a cursor positioning issue
|
||||
@ -163,4 +148,10 @@ export class ReactRenderer<R = unknown, P = unknown> {
|
||||
|
||||
editor?.contentComponent?.removeRenderer(this.id)
|
||||
}
|
||||
|
||||
updateAttributes(attributes: Record<string, string>): void {
|
||||
Object.keys(attributes).forEach(key => {
|
||||
this.element.setAttribute(key, attributes[key])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user