Compare commits

...

2 Commits

Author SHA1 Message Date
Palanikannan M 8405f3740e Merge branch 'preview' into fix/node-view-rerenders 2025-09-01 20:33:15 +05:30
Palanikannan M 35c4d504a8 fix: add unique keys to add nodeview wrappers 2025-07-30 21:49:15 +05:30
5 changed files with 17 additions and 7 deletions
@@ -1,5 +1,6 @@
import { NodeViewContent, NodeViewProps, NodeViewWrapper } from "@tiptap/react";
import React, { useState } from "react";
import React, { useState, useMemo } from "react";
import { v4 as uuidv4 } from "uuid";
// constants
import { COLORS_LIST } from "@/constants/common";
// local components
@@ -22,11 +23,14 @@ export const CustomCalloutBlock: React.FC<CustomCalloutNodeViewProps> = (props)
// states
const [isEmojiPickerOpen, setIsEmojiPickerOpen] = useState(false);
const [isColorPickerOpen, setIsColorPickerOpen] = useState(false);
// unique id
const uniqueId = useMemo(() => uuidv4(), []);
// derived values
const activeBackgroundColor = COLORS_LIST.find((c) => node.attrs["data-background"] === c.key)?.backgroundColor;
return (
<NodeViewWrapper
key={`callout-block-${uniqueId}`}
className="editor-callout-component group/callout-node relative bg-custom-background-90 rounded-lg text-custom-text-100 p-4 my-2 flex items-start gap-4 transition-colors duration-500 break-words"
style={{
backgroundColor: activeBackgroundColor,
@@ -5,7 +5,8 @@ import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
import ts from "highlight.js/lib/languages/typescript";
import { common, createLowlight } from "lowlight";
import { CopyIcon, CheckIcon } from "lucide-react";
import { useState } from "react";
import { useState, useMemo } from "react";
import { v4 as uuidv4 } from "uuid";
// ui
import { Tooltip } from "@plane/ui";
// plane utils
@@ -22,6 +23,8 @@ type Props = {
export const CodeBlockComponent: React.FC<Props> = ({ node }) => {
const [copied, setCopied] = useState(false);
const uniqueId = useMemo(() => uuidv4(), []);
const copyToClipboard = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
try {
await navigator.clipboard.writeText(node.textContent);
@@ -35,7 +38,7 @@ export const CodeBlockComponent: React.FC<Props> = ({ node }) => {
};
return (
<NodeViewWrapper className="code-block relative group/code">
<NodeViewWrapper className="code-block relative group/code" key={`code-block-${uniqueId}`}>
<Tooltip tooltipContent="Copy code">
<button
type="button"
@@ -22,7 +22,7 @@ export type CustomImageNodeViewProps = Omit<NodeViewProps, "extension" | "update
export const CustomImageNodeView: React.FC<CustomImageNodeViewProps> = (props) => {
const { editor, extension, node } = props;
const { src: imgNodeSrc } = node.attrs;
const { src: imgNodeSrc, id: imageEntityId } = node.attrs;
const [isUploaded, setIsUploaded] = useState(!!imgNodeSrc);
const [resolvedSrc, setResolvedSrc] = useState<string | undefined>(undefined);
@@ -68,7 +68,7 @@ export const CustomImageNodeView: React.FC<CustomImageNodeViewProps> = (props) =
}, [imgNodeSrc, extension.options]);
return (
<NodeViewWrapper>
<NodeViewWrapper key={`custom-image-node-view-${imageEntityId}`}>
<div className="p-0 mx-0 my-2" data-drag-handle ref={imageComponentRef}>
{(isUploaded || imageFromFileSystem) && !failedToLoadImage ? (
<CustomImageBlock
@@ -17,7 +17,10 @@ export const MentionNodeView: React.FC<MentionNodeViewProps> = (props) => {
} = props;
return (
<NodeViewWrapper className="mention-component inline w-fit">
<NodeViewWrapper
key={`mention-node-view-${attrs[EMentionComponentAttributeNames.ENTITY_IDENTIFIER]}`}
className="mention-component inline w-fit"
>
{(extension.options as TMentionExtensionOptions).renderComponent({
entity_identifier: attrs[EMentionComponentAttributeNames.ENTITY_IDENTIFIER] ?? "",
entity_name: attrs[EMentionComponentAttributeNames.ENTITY_NAME] ?? "user_mention",
@@ -18,7 +18,7 @@ export const WorkItemEmbedExtension = (props: Props) =>
WorkItemEmbedExtensionConfig.extend({
addNodeView() {
return ReactNodeViewRenderer((issueProps: NodeViewProps) => (
<NodeViewWrapper>
<NodeViewWrapper key={`work-item-embed-node-view-${issueProps.node.attrs.entity_identifier}`}>
{props.widgetCallback({
issueId: issueProps.node.attrs.entity_identifier,
projectId: issueProps.node.attrs.project_identifier,