Просмотр исходного кода

chore(material): lazy import editors (#748)

Yiwei Mao 4 месяцев назад
Родитель
Сommit
d610a1293d

+ 1 - 1
packages/materials/form-materials/src/components/code-editor-mini/index.tsx

@@ -7,7 +7,7 @@ import React from 'react';
 
 import styled from 'styled-components';
 
-import { CodeEditor, CodeEditorPropsType } from '@/components/code-editor';
+import { CodeEditor, type CodeEditorPropsType } from '@/components/code-editor';
 
 const UIMini = styled.div`
   .ͼ1 .cm-content {

+ 96 - 0
packages/materials/form-materials/src/components/code-editor/editor.tsx

@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React, { useEffect, useRef } from 'react';
+
+import {
+  ActiveLinePlaceholder,
+  createRenderer,
+  EditorProvider,
+  InferValues,
+} from '@coze-editor/editor/react';
+import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
+import { EditorView } from '@codemirror/view';
+
+import { getSuffixByLanguageId } from './utils';
+import { initTsWorker } from './language-features';
+
+import './theme';
+import './language-features';
+
+const OriginCodeEditor = createRenderer(preset, [
+  EditorView.theme({
+    '&.cm-focused': {
+      outline: 'none',
+    },
+  }),
+]);
+
+type Preset = typeof preset;
+type Options = Partial<InferValues<Preset[number]>>;
+
+export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
+  value?: string;
+  onChange?: (value: string) => void;
+  languageId: 'python' | 'typescript' | 'shell' | 'json';
+  theme?: 'dark' | 'light';
+  placeholder?: string;
+  activeLinePlaceholder?: string;
+  readonly?: boolean;
+  options?: Options;
+}
+
+export function CodeEditor({
+  value,
+  onChange,
+  languageId = 'python',
+  theme = 'light',
+  children,
+  placeholder,
+  activeLinePlaceholder,
+  options,
+  readonly,
+}: CodeEditorPropsType) {
+  const editorRef = useRef<EditorAPI | null>(null);
+
+  useEffect(() => {
+    if (languageId === 'typescript') {
+      initTsWorker();
+    }
+  }, [languageId]);
+
+  useEffect(() => {
+    // listen to value change
+    if (editorRef.current?.getValue() !== value) {
+      editorRef.current?.setValue(String(value || ''));
+    }
+  }, [value]);
+
+  return (
+    <EditorProvider>
+      <OriginCodeEditor
+        defaultValue={String(value || '')}
+        options={{
+          uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
+          languageId,
+          theme,
+          placeholder,
+          readOnly: readonly,
+          editable: !readonly,
+          ...(options || {}),
+        }}
+        didMount={(editor: EditorAPI) => {
+          editorRef.current = editor;
+        }}
+        onChange={(e) => onChange?.(e.value)}
+      >
+        {activeLinePlaceholder && (
+          <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
+        )}
+        {children}
+      </OriginCodeEditor>
+    </EditorProvider>
+  );
+}

+ 5 - 89
packages/materials/form-materials/src/components/code-editor/index.tsx

@@ -3,94 +3,10 @@
  * SPDX-License-Identifier: MIT
  */
 
-import React, { useEffect, useRef } from 'react';
+import { lazy } from 'react';
 
-import {
-  ActiveLinePlaceholder,
-  createRenderer,
-  EditorProvider,
-  InferValues,
-} from '@coze-editor/editor/react';
-import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
-import { EditorView } from '@codemirror/view';
+export const CodeEditor = lazy(() =>
+  import('./editor').then((module) => ({ default: module.CodeEditor }))
+);
 
-import { getSuffixByLanguageId } from './utils';
-import { initTsWorker } from './language-features';
-
-import './theme';
-import './language-features';
-
-const OriginCodeEditor = createRenderer(preset, [
-  EditorView.theme({
-    '&.cm-focused': {
-      outline: 'none',
-    },
-  }),
-]);
-
-type Preset = typeof preset;
-type Options = Partial<InferValues<Preset[number]>>;
-
-export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
-  value?: string;
-  onChange?: (value: string) => void;
-  languageId: 'python' | 'typescript' | 'shell' | 'json';
-  theme?: 'dark' | 'light';
-  placeholder?: string;
-  activeLinePlaceholder?: string;
-  readonly?: boolean;
-  options?: Options;
-}
-
-export function CodeEditor({
-  value,
-  onChange,
-  languageId = 'python',
-  theme = 'light',
-  children,
-  placeholder,
-  activeLinePlaceholder,
-  options,
-  readonly,
-}: CodeEditorPropsType) {
-  const editorRef = useRef<EditorAPI | null>(null);
-
-  useEffect(() => {
-    if (languageId === 'typescript') {
-      initTsWorker();
-    }
-  }, [languageId]);
-
-  useEffect(() => {
-    // listen to value change
-    if (editorRef.current?.getValue() !== value) {
-      editorRef.current?.setValue(String(value || ''));
-    }
-  }, [value]);
-
-  return (
-    <EditorProvider>
-      <OriginCodeEditor
-        defaultValue={String(value || '')}
-        options={{
-          uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
-          languageId,
-          theme,
-          placeholder,
-          readOnly: readonly,
-          editable: !readonly,
-          ...(options || {}),
-        }}
-        didMount={(editor: EditorAPI) => {
-          editorRef.current = editor;
-        }}
-        onChange={(e) => onChange?.(e.value)}
-      >
-        {activeLinePlaceholder && (
-          <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
-        )}
-        {children}
-      </OriginCodeEditor>
-    </EditorProvider>
-  );
-}
+export type { CodeEditorPropsType } from './editor';

+ 69 - 0
packages/materials/form-materials/src/components/json-editor-with-variables/editor.tsx

@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React from 'react';
+
+import { I18n } from '@flowgram.ai/editor';
+import { transformerCreator } from '@coze-editor/editor/preset-code';
+import { Text } from '@coze-editor/editor/language-json';
+
+import { CodeEditor, type CodeEditorPropsType } from '@/components/code-editor';
+
+import { VariableTree } from './extensions/variable-tree';
+import { VariableTagInject } from './extensions/variable-tag';
+
+type Match = { match: string; range: [number, number] };
+function findAllMatches(inputString: string, regex: RegExp): Match[] {
+  const globalRegex = new RegExp(
+    regex,
+    regex.flags.includes('g') ? regex.flags : regex.flags + 'g'
+  );
+  let match;
+  const matches: Match[] = [];
+
+  while ((match = globalRegex.exec(inputString)) !== null) {
+    if (match.index === globalRegex.lastIndex) {
+      globalRegex.lastIndex++;
+    }
+    matches.push({
+      match: match[0],
+      range: [match.index, match.index + match[0].length],
+    });
+  }
+
+  return matches;
+}
+
+const transformer = transformerCreator((text: Text) => {
+  const originalSource = text.toString();
+  const matches = findAllMatches(originalSource, /\{\{([^\}]*)\}\}/g);
+
+  if (matches.length > 0) {
+    matches.forEach(({ range }) => {
+      text.replaceRange(range[0], range[1], 'null');
+    });
+  }
+
+  return text;
+});
+
+export interface JsonEditorWithVariablesProps extends Omit<CodeEditorPropsType, 'languageId'> {}
+
+export function JsonEditorWithVariables(props: JsonEditorWithVariablesProps) {
+  return (
+    <CodeEditor
+      languageId="json"
+      activeLinePlaceholder={I18n.t("Press '@' to Select variable")}
+      {...props}
+      options={{
+        transformer,
+        ...(props.options || {}),
+      }}
+    >
+      <VariableTree />
+      <VariableTagInject />
+    </CodeEditor>
+  );
+}

+ 5 - 60
packages/materials/form-materials/src/components/json-editor-with-variables/index.tsx

@@ -3,65 +3,10 @@
  * SPDX-License-Identifier: MIT
  */
 
-import React from 'react';
+import { lazy } from 'react';
 
-import { transformerCreator } from '@coze-editor/editor/preset-code';
-import { Text } from '@coze-editor/editor/language-json';
+export const JsonEditorWithVariables = lazy(() =>
+  import('./editor').then((module) => ({ default: module.JsonEditorWithVariables }))
+);
 
-import { CodeEditor, type CodeEditorPropsType } from '@/components/code-editor';
-
-import { VariableTree } from './extensions/variable-tree';
-import { VariableTagInject } from './extensions/variable-tag';
-import { I18n } from '@flowgram.ai/editor';
-
-type Match = { match: string; range: [number, number] };
-function findAllMatches(inputString: string, regex: RegExp): Match[] {
-  const globalRegex = new RegExp(
-    regex,
-    regex.flags.includes('g') ? regex.flags : regex.flags + 'g'
-  );
-  let match;
-  const matches: Match[] = [];
-
-  while ((match = globalRegex.exec(inputString)) !== null) {
-    if (match.index === globalRegex.lastIndex) {
-      globalRegex.lastIndex++;
-    }
-    matches.push({
-      match: match[0],
-      range: [match.index, match.index + match[0].length],
-    });
-  }
-
-  return matches;
-}
-
-const transformer = transformerCreator((text: Text) => {
-  const originalSource = text.toString();
-  const matches = findAllMatches(originalSource, /\{\{([^\}]*)\}\}/g);
-
-  if (matches.length > 0) {
-    matches.forEach(({ range }) => {
-      text.replaceRange(range[0], range[1], 'null');
-    });
-  }
-
-  return text;
-});
-
-export function JsonEditorWithVariables(props: Omit<CodeEditorPropsType, 'languageId'>) {
-  return (
-    <CodeEditor
-      languageId="json"
-      activeLinePlaceholder={I18n.t("Press '@' to Select variable")}
-      {...props}
-      options={{
-        transformer,
-        ...(props.options || {}),
-      }}
-    >
-      <VariableTree />
-      <VariableTagInject />
-    </CodeEditor>
-  );
-}
+export type { JsonEditorWithVariablesProps } from './editor';

+ 25 - 0
packages/materials/form-materials/src/components/prompt-editor-with-inputs/editor.tsx

@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React from 'react';
+
+import { PromptEditor, PromptEditorPropsType } from '@/components/prompt-editor';
+
+import { InputsTree } from './extensions/inputs-tree';
+
+export interface PromptEditorWithInputsProps extends PromptEditorPropsType {
+  inputsValues: any;
+}
+
+export function PromptEditorWithInputs({
+  inputsValues,
+  ...restProps
+}: PromptEditorWithInputsProps) {
+  return (
+    <PromptEditor {...restProps}>
+      <InputsTree inputsValues={inputsValues} />
+    </PromptEditor>
+  );
+}

+ 5 - 15
packages/materials/form-materials/src/components/prompt-editor-with-inputs/index.tsx

@@ -3,20 +3,10 @@
  * SPDX-License-Identifier: MIT
  */
 
-import React from 'react';
+import { lazy } from 'react';
 
-import { PromptEditor, PromptEditorPropsType } from '@/components/prompt-editor';
+export const PromptEditorWithInputs = lazy(() =>
+  import('./editor').then((module) => ({ default: module.PromptEditorWithInputs }))
+);
 
-import { InputsTree } from './extensions/inputs-tree';
-
-interface PropsType extends PromptEditorPropsType {
-  inputsValues: any;
-}
-
-export function PromptEditorWithInputs({ inputsValues, ...restProps }: PropsType) {
-  return (
-    <PromptEditor {...restProps}>
-      <InputsTree inputsValues={inputsValues} />
-    </PromptEditor>
-  );
-}
+export type { PromptEditorWithInputsProps } from './editor';

+ 22 - 0
packages/materials/form-materials/src/components/prompt-editor-with-variables/editor.tsx

@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React from 'react';
+
+import { PromptEditor, PromptEditorPropsType } from '@/components/prompt-editor';
+
+import { VariableTree } from './extensions/variable-tree';
+import { VariableTagInject } from './extensions/variable-tag';
+
+export interface PromptEditorWithVariablesProps extends PromptEditorPropsType {}
+
+export function PromptEditorWithVariables(props: PromptEditorWithVariablesProps) {
+  return (
+    <PromptEditor {...props}>
+      <VariableTree />
+      <VariableTagInject />
+    </PromptEditor>
+  );
+}

+ 5 - 13
packages/materials/form-materials/src/components/prompt-editor-with-variables/index.tsx

@@ -3,18 +3,10 @@
  * SPDX-License-Identifier: MIT
  */
 
-import React from 'react';
+import { lazy } from 'react';
 
-import { PromptEditor, PromptEditorPropsType } from '@/components/prompt-editor';
+export const PromptEditorWithVariables = lazy(() =>
+  import('./editor').then((module) => ({ default: module.PromptEditorWithVariables }))
+);
 
-import { VariableTree } from './extensions/variable-tree';
-import { VariableTagInject } from './extensions/variable-tag';
-
-export function PromptEditorWithVariables(props: PromptEditorPropsType) {
-  return (
-    <PromptEditor {...props}>
-      <VariableTree />
-      <VariableTagInject />
-    </PromptEditor>
-  );
-}
+export type { PromptEditorWithVariablesProps } from './editor';

+ 81 - 0
packages/materials/form-materials/src/components/prompt-editor/editor.tsx

@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
+ * SPDX-License-Identifier: MIT
+ */
+
+import React, { useEffect, useRef } from 'react';
+
+import {
+  Renderer,
+  EditorProvider,
+  ActiveLinePlaceholder,
+  InferValues,
+} from '@coze-editor/editor/react';
+import preset, { EditorAPI } from '@coze-editor/editor/preset-prompt';
+
+import { PropsType } from './types';
+import { UIContainer } from './styles';
+import MarkdownHighlight from './extensions/markdown';
+import LanguageSupport from './extensions/language-support';
+import JinjaHighlight from './extensions/jinja';
+
+type Preset = typeof preset;
+type Options = Partial<InferValues<Preset[number]>>;
+
+export interface PromptEditorPropsType extends PropsType {
+  options?: Options;
+}
+
+export function PromptEditor(props: PromptEditorPropsType) {
+  const {
+    value,
+    onChange,
+    readonly,
+    placeholder,
+    activeLinePlaceholder,
+    style,
+    hasError,
+    children,
+    disableMarkdownHighlight,
+    options,
+  } = props || {};
+
+  const editorRef = useRef<EditorAPI | null>(null);
+
+  useEffect(() => {
+    // listen to value change
+    if (editorRef.current?.getValue() !== value?.content) {
+      editorRef.current?.setValue(String(value?.content || ''));
+    }
+  }, [value]);
+
+  return (
+    <UIContainer $hasError={hasError} style={style}>
+      <EditorProvider>
+        <Renderer
+          didMount={(editor: EditorAPI) => {
+            editorRef.current = editor;
+          }}
+          plugins={preset}
+          defaultValue={String(value?.content)}
+          options={{
+            readOnly: readonly,
+            editable: !readonly,
+            placeholder,
+            ...options,
+          }}
+          onChange={(e) => {
+            onChange({ type: 'template', content: e.value });
+          }}
+        />
+        {activeLinePlaceholder && (
+          <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
+        )}
+        {!disableMarkdownHighlight && <MarkdownHighlight />}
+        <LanguageSupport />
+        <JinjaHighlight />
+        {children}
+      </EditorProvider>
+    </UIContainer>
+  );
+}

+ 5 - 69
packages/materials/form-materials/src/components/prompt-editor/index.tsx

@@ -3,74 +3,10 @@
  * SPDX-License-Identifier: MIT
  */
 
-import React, { useEffect, useRef } from 'react';
+import { lazy } from 'react';
 
-import { Renderer, EditorProvider, ActiveLinePlaceholder, InferValues } from '@coze-editor/editor/react';
-import preset, { EditorAPI } from '@coze-editor/editor/preset-prompt';
+export const PromptEditor = lazy(() =>
+  import('./editor').then((module) => ({ default: module.PromptEditor }))
+);
 
-import { PropsType } from './types';
-import { UIContainer } from './styles';
-import MarkdownHighlight from './extensions/markdown';
-import LanguageSupport from './extensions/language-support';
-import JinjaHighlight from './extensions/jinja';
-
-type Preset = typeof preset;
-type Options = Partial<InferValues<Preset[number]>>;
-
-export interface PromptEditorPropsType extends PropsType {
-  options?: Options;
-}
-
-export function PromptEditor(props: PromptEditorPropsType) {
-  const {
-    value,
-    onChange,
-    readonly,
-    placeholder,
-    activeLinePlaceholder,
-    style,
-    hasError,
-    children,
-    disableMarkdownHighlight,
-    options,
-  } = props || {};
-
-  const editorRef = useRef<EditorAPI | null>(null);
-
-  useEffect(() => {
-    // listen to value change
-    if (editorRef.current?.getValue() !== value?.content) {
-      editorRef.current?.setValue(String(value?.content || ''));
-    }
-  }, [value]);
-
-  return (
-    <UIContainer $hasError={hasError} style={style}>
-      <EditorProvider>
-        <Renderer
-          didMount={(editor: EditorAPI) => {
-            editorRef.current = editor;
-          }}
-          plugins={preset}
-          defaultValue={String(value?.content)}
-          options={{
-            readOnly: readonly,
-            editable: !readonly,
-            placeholder,
-            ...options
-          }}
-          onChange={(e) => {
-            onChange({ type: 'template', content: e.value });
-          }}
-        />
-        {activeLinePlaceholder && (
-          <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
-        )}
-        {!disableMarkdownHighlight && <MarkdownHighlight />}
-        <LanguageSupport />
-        <JinjaHighlight />
-        {children}
-      </EditorProvider>
-    </UIContainer>
-  );
-}
+export type { PromptEditorPropsType } from './editor';