Parcourir la source

fix(free-demo): comment sync value between editor model & form data (#166)

* fix(demo): sync value between editor model & form data

* feat(demo): comment node added to inital data
Louis Young il y a 8 mois
Parent
commit
1887d53ce9

+ 1 - 2
apps/demo-free-layout/src/components/comment/components/container.tsx

@@ -2,13 +2,12 @@ import type { ReactNode, FC, CSSProperties } from 'react';
 
 interface ICommentContainer {
   focused: boolean;
-  overflow: boolean;
   children?: ReactNode;
   style?: React.CSSProperties;
 }
 
 export const CommentContainer: FC<ICommentContainer> = (props) => {
-  const { focused, overflow, children, style } = props;
+  const { focused, children, style } = props;
 
   const scrollbarStyle = {
     // 滚动条样式

+ 1 - 12
apps/demo-free-layout/src/components/comment/components/editor.tsx

@@ -16,15 +16,7 @@ export const CommentEditor: FC<ICommentEditor> = (props) => {
   const { model, style, onChange } = props;
   const playground = usePlayground();
   const editorRef = useRef<HTMLTextAreaElement | null>(null);
-  const [value, setValue] = useState(model.value);
-  const [focused, setFocus] = useState(false);
-
-  const placeholder: string | undefined = useMemo(() => {
-    if (value || focused) {
-      return;
-    }
-    return 'Enter a comment...';
-  }, [value, focused]);
+  const placeholder = model.value || model.focused ? undefined : 'Enter a comment...';
 
   // 同步编辑器内部值变化
   useEffect(() => {
@@ -55,15 +47,12 @@ export const CommentEditor: FC<ICommentEditor> = (props) => {
         onChange={(e) => {
           const { value } = e.target;
           model.setValue(value);
-          setValue(value);
         }}
         onFocus={() => {
           model.setFocus(true);
-          setFocus(true);
         }}
         onBlur={() => {
           model.setFocus(false);
-          setFocus(false);
         }}
       />
     </div>

+ 1 - 1
apps/demo-free-layout/src/components/comment/components/render.tsx

@@ -55,7 +55,7 @@ export const CommentRender: FC<{
       <Form control={formControl}>
         <>
           {/* 背景 */}
-          <CommentContainer focused={focused} overflow={overflow} style={{ height }}>
+          <CommentContainer focused={focused} style={{ height }}>
             <Field name={CommentEditorFormField.Note}>
               {({ field }: FieldRenderProps<string>) => (
                 <>

+ 28 - 5
apps/demo-free-layout/src/components/comment/model.ts

@@ -8,7 +8,7 @@ export class CommentEditorModel {
 
   private emitter: Emitter<CommentEditorEventParams> = new Emitter();
 
-  private editor: HTMLTextAreaElement | null = null;
+  private editor: HTMLTextAreaElement;
 
   /** 注册事件 */
   public on = this.emitter.event;
@@ -20,10 +20,14 @@ export class CommentEditorModel {
 
   /** 外部设置模型值 */
   public setValue(value: string = CommentEditorDefaultValue): void {
+    if (!this.initialized) {
+      return;
+    }
     if (value === this.innerValue) {
       return;
     }
     this.innerValue = value;
+    this.syncEditorValue();
     this.emitter.fire({
       type: CommentEditorEvent.Change,
       value: this.innerValue,
@@ -31,7 +35,7 @@ export class CommentEditorModel {
   }
 
   public set element(el: HTMLTextAreaElement) {
-    if (Boolean(this.editor)) {
+    if (this.initialized) {
       return;
     }
     this.editor = el;
@@ -44,10 +48,13 @@ export class CommentEditorModel {
 
   /** 编辑器聚焦/失焦 */
   public setFocus(focused: boolean): void {
+    if (!this.initialized) {
+      return;
+    }
     if (focused && !this.focused) {
-      this.editor?.focus();
+      this.editor.focus();
     } else if (!focused && this.focused) {
-      this.editor?.blur();
+      this.editor.blur();
       this.deselect();
       this.emitter.fire({
         type: CommentEditorEvent.Blur,
@@ -57,7 +64,7 @@ export class CommentEditorModel {
 
   /** 选择末尾 */
   public selectEnd(): void {
-    if (!this.editor) {
+    if (!this.initialized) {
       return;
     }
     // 获取文本长度
@@ -80,4 +87,20 @@ export class CommentEditorModel {
       selection.removeAllRanges();
     }
   }
+
+  /** 是否初始化 */
+  private get initialized(): boolean {
+    return Boolean(this.editor);
+  }
+
+  /**
+   * 同步编辑器实例内容
+   * > **NOTICE:** *为确保不影响性能,应仅在外部值变更导致编辑器值与模型值不一致时调用*
+   */
+  private syncEditorValue(): void {
+    if (!this.initialized) {
+      return;
+    }
+    this.editor.value = this.innerValue;
+  }
 }

+ 21 - 4
apps/demo-free-layout/src/initial-data.ts

@@ -8,7 +8,7 @@ export const initialData: FlowDocumentJSON = {
       meta: {
         position: {
           x: 180,
-          y: 313.25,
+          y: 298,
         },
       },
       data: {
@@ -30,7 +30,7 @@ export const initialData: FlowDocumentJSON = {
       meta: {
         position: {
           x: 640,
-          y: 298.75,
+          y: 279.5,
         },
       },
       data: {
@@ -125,7 +125,7 @@ export const initialData: FlowDocumentJSON = {
       meta: {
         position: {
           x: 2220,
-          y: 313.25,
+          y: 298,
         },
       },
       data: {
@@ -146,7 +146,7 @@ export const initialData: FlowDocumentJSON = {
       meta: {
         position: {
           x: 1020,
-          y: 532.5,
+          y: 452,
         },
       },
       data: {
@@ -261,6 +261,23 @@ export const initialData: FlowDocumentJSON = {
         },
       ],
     },
+    {
+      id: '159623',
+      type: 'comment',
+      meta: {
+        position: {
+          x: 640,
+          y: 465.5,
+        },
+      },
+      data: {
+        size: {
+          width: 240,
+          height: 150,
+        },
+        note: 'hi ~\n\nthis is a comment node\n\n- flowgram.ai',
+      },
+    },
   ],
   edges: [
     {

+ 5 - 1
apps/demo-free-layout/src/typings/node.ts

@@ -25,7 +25,7 @@ export interface FlowNodeJSON extends FlowNodeJSONDefault {
     /**
      * Node title
      */
-    title: string;
+    title?: string;
     /**
      * Inputs data values
      */
@@ -38,6 +38,10 @@ export interface FlowNodeJSON extends FlowNodeJSONDefault {
      * Define the outputs data of the node by JsonSchema
      */
     outputs?: JsonSchema;
+    /**
+     * Rest properties
+     */
+    [key: string]: any;
   };
 }