EventNode.tsx2.2 KBView on GitHub 'use client';
import { Node, mergeAttributes } from '@tiptap/core';
import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';
import type { NodeViewProps } from '@tiptap/react';
import { EventChipContent } from '@/modules/documents/mention/EventChip';
/**
* Inline atom chip representing an event reference inserted via `{{` mention.
* Stores `eventId`, `eventType`, and a denormalized `title` snapshot so the
* chip renders without an extra fetch on first paint. The title is a snapshot
* — re-renaming the underlying event won't update old chips.
*
* The chip itself is `EventChipContent`, shared verbatim with the table grid — it renders
* AS the `NodeViewWrapper` so the DOM PM sees is unchanged by the extraction.
*/
function EventNodeView({ node }: NodeViewProps) {
return (
<EventChipContent
eventType={node.attrs.eventType as string | null}
title={node.attrs.title as string | null}
container={NodeViewWrapper}
containerProps={{ as: 'span', 'data-event-node': '', contentEditable: false }}
/>
);
}
export const EventNode = Node.create({
name: 'eventNode',
group: 'inline',
inline: true,
atom: true,
selectable: true,
draggable: false,
addAttributes() {
return {
eventId: {
default: null as string | null,
parseHTML: (element) => element.getAttribute('data-event-id'),
renderHTML: (attributes) =>
attributes.eventId ? { 'data-event-id': attributes.eventId } : {},
},
eventType: {
default: null as string | null,
parseHTML: (element) => element.getAttribute('data-event-type'),
renderHTML: (attributes) =>
attributes.eventType ? { 'data-event-type': attributes.eventType } : {},
},
title: {
default: null as string | null,
parseHTML: (element) => element.getAttribute('data-event-title'),
renderHTML: (attributes) =>
attributes.title ? { 'data-event-title': attributes.title } : {},
},
};
},
parseHTML() {
return [{ tag: 'span[data-event-node]' }];
},
renderHTML({ HTMLAttributes }) {
return ['span', mergeAttributes({ 'data-event-node': '' }, HTMLAttributes)];
},
addNodeView() {
return ReactNodeViewRenderer(EventNodeView);
},
});