@flowgram.ai/form-materials 0.2.22 → 0.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/form-materials",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  "@coze-editor/editor": "0.1.0-alpha.879fbb",
34
34
  "@codemirror/view": "~6.38.0",
35
35
  "@codemirror/state": "~6.5.2",
36
- "@flowgram.ai/editor": "0.2.22"
36
+ "@flowgram.ai/editor": "0.2.23"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/lodash": "^4.14.137",
@@ -49,8 +49,8 @@
49
49
  "tsup": "^8.0.1",
50
50
  "typescript": "^5.0.4",
51
51
  "vitest": "^0.34.6",
52
- "@flowgram.ai/eslint-config": "0.2.22",
53
- "@flowgram.ai/ts-config": "0.2.22"
52
+ "@flowgram.ai/ts-config": "0.2.23",
53
+ "@flowgram.ai/eslint-config": "0.2.23"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "react": ">=16.8",
@@ -3,9 +3,14 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import React, { useRef } from 'react';
6
+ import React, { useEffect, useRef } from 'react';
7
7
 
8
- import { createRenderer, EditorProvider } from '@coze-editor/editor/react';
8
+ import {
9
+ ActiveLinePlaceholder,
10
+ createRenderer,
11
+ EditorProvider,
12
+ InferValues,
13
+ } from '@coze-editor/editor/react';
9
14
  import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
10
15
  import { EditorView } from '@codemirror/view';
11
16
 
@@ -22,11 +27,18 @@ const OriginCodeEditor = createRenderer(preset, [
22
27
  }),
23
28
  ]);
24
29
 
30
+ type Preset = typeof preset;
31
+ type Options = Partial<InferValues<Preset[number]>>;
32
+
25
33
  export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
26
34
  value?: string;
27
35
  onChange?: (value: string) => void;
28
36
  languageId: 'python' | 'typescript' | 'shell' | 'json';
29
37
  theme?: 'dark' | 'light';
38
+ placeholder?: string;
39
+ activeLinePlaceholder?: string;
40
+ readonly?: boolean;
41
+ options?: Options;
30
42
  }
31
43
 
32
44
  export function CodeEditor({
@@ -35,9 +47,20 @@ export function CodeEditor({
35
47
  languageId = 'python',
36
48
  theme = 'light',
37
49
  children,
50
+ placeholder,
51
+ activeLinePlaceholder,
52
+ options,
53
+ readonly,
38
54
  }: CodeEditorPropsType) {
39
55
  const editorRef = useRef<EditorAPI | null>(null);
40
56
 
57
+ useEffect(() => {
58
+ // listen to value change
59
+ if (editorRef.current?.getValue() !== value) {
60
+ editorRef.current?.setValue(String(value || ''));
61
+ }
62
+ }, [value]);
63
+
41
64
  return (
42
65
  <EditorProvider>
43
66
  <OriginCodeEditor
@@ -46,12 +69,19 @@ export function CodeEditor({
46
69
  uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
47
70
  languageId,
48
71
  theme,
72
+ placeholder,
73
+ readOnly: readonly,
74
+ editable: !readonly,
75
+ ...(options || {}),
49
76
  }}
50
77
  didMount={(editor: EditorAPI) => {
51
78
  editorRef.current = editor;
52
79
  }}
53
80
  onChange={(e) => onChange?.(e.value)}
54
81
  >
82
+ {activeLinePlaceholder && (
83
+ <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
84
+ )}
55
85
  {children}
56
86
  </OriginCodeEditor>
57
87
  </EditorProvider>
@@ -30,7 +30,7 @@ export const lightTheme: Extension = createTheme({
30
30
  gutterBorderColor: 'transparent',
31
31
  gutterBorderWidth: 0,
32
32
  lineHighlight: '#f0f0f0',
33
- bracketColors: ['#FFEF61', '#DD99FF', '#78B0FF'],
33
+ bracketColors: ['#FFD700', '#DD99FF', '#78B0FF'],
34
34
  tooltip: {
35
35
  backgroundColor: '#f0f0f0',
36
36
  color: '#000',
@@ -5,13 +5,59 @@
5
5
 
6
6
  import React from 'react';
7
7
 
8
+ import { transformerCreator } from '@coze-editor/editor/preset-code';
9
+ import { Text } from '@coze-editor/editor/language-json';
10
+
8
11
  import { VariableTree } from './extensions/variable-tree';
9
12
  import { VariableTagInject } from './extensions/variable-tag';
10
13
  import { CodeEditor, type CodeEditorPropsType } from '../code-editor';
11
14
 
15
+ type Match = { match: string; range: [number, number] };
16
+ function findAllMatches(inputString: string, regex: RegExp): Match[] {
17
+ const globalRegex = new RegExp(
18
+ regex,
19
+ regex.flags.includes('g') ? regex.flags : regex.flags + 'g'
20
+ );
21
+ let match;
22
+ const matches: Match[] = [];
23
+
24
+ while ((match = globalRegex.exec(inputString)) !== null) {
25
+ if (match.index === globalRegex.lastIndex) {
26
+ globalRegex.lastIndex++;
27
+ }
28
+ matches.push({
29
+ match: match[0],
30
+ range: [match.index, match.index + match[0].length],
31
+ });
32
+ }
33
+
34
+ return matches;
35
+ }
36
+
37
+ const transformer = transformerCreator((text: Text) => {
38
+ const originalSource = text.toString();
39
+ const matches = findAllMatches(originalSource, /\{\{([^\}]*)\}\}/g);
40
+
41
+ if (matches.length > 0) {
42
+ matches.forEach(({ range }) => {
43
+ text.replaceRange(range[0], range[1], 'null');
44
+ });
45
+ }
46
+
47
+ return text;
48
+ });
49
+
12
50
  export function JsonEditorWithVariables(props: Omit<CodeEditorPropsType, 'languageId'>) {
13
51
  return (
14
- <CodeEditor languageId="json" {...props}>
52
+ <CodeEditor
53
+ languageId="json"
54
+ activeLinePlaceholder="Press '@' to Select variable"
55
+ {...props}
56
+ options={{
57
+ transformer,
58
+ ...(props.options || {}),
59
+ }}
60
+ >
15
61
  <VariableTree />
16
62
  <VariableTagInject />
17
63
  </CodeEditor>
@@ -1,5 +1,13 @@
1
1
  {
2
2
  "name": "json-schema-editor",
3
- "depMaterials": ["type-selector", "typings/json-schema"],
4
- "depPackages": ["@douyinfe/semi-ui", "@douyinfe/semi-icons", "styled-components"]
3
+ "depMaterials": [
4
+ "type-selector",
5
+ "typings/json-schema",
6
+ "constant-inputs"
7
+ ],
8
+ "depPackages": [
9
+ "@douyinfe/semi-ui",
10
+ "@douyinfe/semi-icons",
11
+ "styled-components"
12
+ ]
5
13
  }
@@ -3,10 +3,10 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import React from 'react';
6
+ import React, { useEffect, useRef } from 'react';
7
7
 
8
8
  import { Renderer, EditorProvider, ActiveLinePlaceholder } from '@coze-editor/editor/react';
9
- import preset from '@coze-editor/editor/preset-prompt';
9
+ import preset, { EditorAPI } from '@coze-editor/editor/preset-prompt';
10
10
 
11
11
  import { PropsType } from './types';
12
12
  import { UIContainer } from './styles';
@@ -28,10 +28,22 @@ export function PromptEditor(props: PropsType) {
28
28
  children,
29
29
  } = props || {};
30
30
 
31
+ const editorRef = useRef<EditorAPI | null>(null);
32
+
33
+ useEffect(() => {
34
+ // listen to value change
35
+ if (editorRef.current?.getValue() !== value?.content) {
36
+ editorRef.current?.setValue(String(value?.content || ''));
37
+ }
38
+ }, [value]);
39
+
31
40
  return (
32
41
  <UIContainer $hasError={hasError} style={style}>
33
42
  <EditorProvider>
34
43
  <Renderer
44
+ didMount={(editor: EditorAPI) => {
45
+ editorRef.current = editor;
46
+ }}
35
47
  plugins={preset}
36
48
  defaultValue={String(value?.content)}
37
49
  options={{
@@ -3,9 +3,9 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
+ import ReactDOM from 'react-dom';
6
7
  import React, { useLayoutEffect } from 'react';
7
8
 
8
- import { createRoot, Root } from 'react-dom/client';
9
9
  import { isEqual, last } from 'lodash';
10
10
  import {
11
11
  BaseVariableField,
@@ -35,7 +35,7 @@ class VariableTagWidget extends WidgetType {
35
35
 
36
36
  scope: Scope;
37
37
 
38
- root: Root;
38
+ rootDOM?: HTMLSpanElement;
39
39
 
40
40
  constructor({ keyPath, scope }: { keyPath?: string[]; scope: Scope }) {
41
41
  super();
@@ -52,9 +52,14 @@ class VariableTagWidget extends WidgetType {
52
52
  return icon;
53
53
  };
54
54
 
55
+ renderReact(jsx: React.ReactElement) {
56
+ // NOTICE: For React 19, upgrade to 'react-dom/client'
57
+ ReactDOM.render(jsx, this.rootDOM!);
58
+ }
59
+
55
60
  renderVariable(v?: BaseVariableField) {
56
61
  if (!v) {
57
- this.root.render(
62
+ this.renderReact(
58
63
  <UITag prefixIcon={<IconIssueStroked />} color="amber">
59
64
  Unknown
60
65
  </UITag>
@@ -69,7 +74,7 @@ class VariableTagWidget extends WidgetType {
69
74
  );
70
75
  const rootIcon = this.renderIcon(rootField?.meta.icon);
71
76
 
72
- this.root.render(
77
+ this.renderReact(
73
78
  <Popover
74
79
  content={
75
80
  <UIPopoverContent>
@@ -90,11 +95,12 @@ class VariableTagWidget extends WidgetType {
90
95
  toDOM(view: EditorView): HTMLElement {
91
96
  const dom = document.createElement('span');
92
97
 
93
- this.root = createRoot(dom);
98
+ this.rootDOM = dom;
94
99
 
95
100
  this.toDispose.push(
96
101
  Disposable.create(() => {
97
- this.root.unmount();
102
+ // NOTICE: For React 19, upgrade to 'react-dom/client'
103
+ ReactDOM.unmountComponentAtNode(this.rootDOM!);
98
104
  })
99
105
  );
100
106