@flowgram.ai/form-materials 0.4.5 → 0.4.6

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.
Files changed (41) hide show
  1. package/dist/esm/chunk-6OZSB6PD.js +10 -0
  2. package/dist/esm/chunk-6OZSB6PD.js.map +1 -0
  3. package/dist/esm/chunk-G4HQ7OSI.js +440 -0
  4. package/dist/esm/chunk-G4HQ7OSI.js.map +1 -0
  5. package/dist/esm/chunk-QIJ4QVB2.js +271 -0
  6. package/dist/esm/chunk-QIJ4QVB2.js.map +1 -0
  7. package/dist/esm/editor-6UMULJYB.js +180 -0
  8. package/dist/esm/editor-6UMULJYB.js.map +1 -0
  9. package/dist/esm/editor-E2BQTPCD.js +388 -0
  10. package/dist/esm/editor-E2BQTPCD.js.map +1 -0
  11. package/dist/esm/editor-H2R7JJLO.js +282 -0
  12. package/dist/esm/editor-H2R7JJLO.js.map +1 -0
  13. package/dist/esm/editor-JX42GFAZ.js +249 -0
  14. package/dist/esm/editor-JX42GFAZ.js.map +1 -0
  15. package/dist/esm/editor-YMNCDGUR.js +167 -0
  16. package/dist/esm/editor-YMNCDGUR.js.map +1 -0
  17. package/dist/esm/index.js +599 -2293
  18. package/dist/esm/index.js.map +1 -1
  19. package/dist/index.d.mts +133 -51
  20. package/dist/index.d.ts +133 -51
  21. package/dist/index.js +3499 -2802
  22. package/dist/index.js.map +1 -1
  23. package/package.json +6 -6
  24. package/src/components/code-editor/editor.tsx +96 -0
  25. package/src/components/code-editor/index.tsx +5 -89
  26. package/src/components/code-editor-mini/index.tsx +2 -2
  27. package/src/components/condition-row/index.tsx +4 -0
  28. package/src/components/db-condition-row/hooks/use-left.tsx +66 -0
  29. package/src/components/db-condition-row/hooks/use-op.tsx +59 -0
  30. package/src/components/db-condition-row/index.tsx +93 -0
  31. package/src/components/db-condition-row/styles.tsx +43 -0
  32. package/src/components/db-condition-row/types.ts +34 -0
  33. package/src/components/index.ts +1 -0
  34. package/src/components/json-editor-with-variables/editor.tsx +69 -0
  35. package/src/components/json-editor-with-variables/index.tsx +5 -60
  36. package/src/components/prompt-editor/editor.tsx +81 -0
  37. package/src/components/prompt-editor/index.tsx +5 -69
  38. package/src/components/prompt-editor-with-inputs/editor.tsx +25 -0
  39. package/src/components/prompt-editor-with-inputs/index.tsx +5 -15
  40. package/src/components/prompt-editor-with-variables/editor.tsx +22 -0
  41. package/src/components/prompt-editor-with-variables/index.tsx +5 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/form-materials",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -30,13 +30,13 @@
30
30
  "chalk": "^5.3.0",
31
31
  "inquirer": "^9.2.7",
32
32
  "immer": "~10.1.1",
33
- "@coze-editor/editor": "0.1.0-alpha.879fbb",
33
+ "@coze-editor/editor": "0.1.0-alpha.5a549c",
34
34
  "@codemirror/view": "~6.38.0",
35
35
  "@codemirror/state": "~6.5.2",
36
36
  "typescript": "^5.8.3",
37
37
  "zod": "^3.24.4",
38
- "@flowgram.ai/editor": "0.4.5",
39
- "@flowgram.ai/json-schema": "0.4.5"
38
+ "@flowgram.ai/editor": "0.4.6",
39
+ "@flowgram.ai/json-schema": "0.4.6"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/lodash": "^4.14.137",
@@ -52,8 +52,8 @@
52
52
  "tsup": "^8.0.1",
53
53
  "typescript": "^5.8.3",
54
54
  "vitest": "^0.34.6",
55
- "@flowgram.ai/ts-config": "0.4.5",
56
- "@flowgram.ai/eslint-config": "0.4.5"
55
+ "@flowgram.ai/eslint-config": "0.4.6",
56
+ "@flowgram.ai/ts-config": "0.4.6"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "react": ">=16.8",
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { useEffect, useRef } from 'react';
7
+
8
+ import {
9
+ ActiveLinePlaceholder,
10
+ createRenderer,
11
+ EditorProvider,
12
+ InferValues,
13
+ } from '@coze-editor/editor/react';
14
+ import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
15
+ import { EditorView } from '@codemirror/view';
16
+
17
+ import { getSuffixByLanguageId } from './utils';
18
+ import { initTsWorker } from './language-features';
19
+
20
+ import './theme';
21
+ import './language-features';
22
+
23
+ const OriginCodeEditor = createRenderer(preset, [
24
+ EditorView.theme({
25
+ '&.cm-focused': {
26
+ outline: 'none',
27
+ },
28
+ }),
29
+ ]);
30
+
31
+ type Preset = typeof preset;
32
+ type Options = Partial<InferValues<Preset[number]>>;
33
+
34
+ export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
35
+ value?: string;
36
+ onChange?: (value: string) => void;
37
+ languageId: 'python' | 'typescript' | 'shell' | 'json';
38
+ theme?: 'dark' | 'light';
39
+ placeholder?: string;
40
+ activeLinePlaceholder?: string;
41
+ readonly?: boolean;
42
+ options?: Options;
43
+ }
44
+
45
+ export function CodeEditor({
46
+ value,
47
+ onChange,
48
+ languageId = 'python',
49
+ theme = 'light',
50
+ children,
51
+ placeholder,
52
+ activeLinePlaceholder,
53
+ options,
54
+ readonly,
55
+ }: CodeEditorPropsType) {
56
+ const editorRef = useRef<EditorAPI | null>(null);
57
+
58
+ useEffect(() => {
59
+ if (languageId === 'typescript') {
60
+ initTsWorker();
61
+ }
62
+ }, [languageId]);
63
+
64
+ useEffect(() => {
65
+ // listen to value change
66
+ if (editorRef.current?.getValue() !== value) {
67
+ editorRef.current?.setValue(String(value || ''));
68
+ }
69
+ }, [value]);
70
+
71
+ return (
72
+ <EditorProvider>
73
+ <OriginCodeEditor
74
+ defaultValue={String(value || '')}
75
+ options={{
76
+ uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
77
+ languageId,
78
+ theme,
79
+ placeholder,
80
+ readOnly: readonly,
81
+ editable: !readonly,
82
+ ...(options || {}),
83
+ }}
84
+ didMount={(editor: EditorAPI) => {
85
+ editorRef.current = editor;
86
+ }}
87
+ onChange={(e) => onChange?.(e.value)}
88
+ >
89
+ {activeLinePlaceholder && (
90
+ <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
91
+ )}
92
+ {children}
93
+ </OriginCodeEditor>
94
+ </EditorProvider>
95
+ );
96
+ }
@@ -3,94 +3,10 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import React, { useEffect, useRef } from 'react';
6
+ import { lazy } from 'react';
7
7
 
8
- import {
9
- ActiveLinePlaceholder,
10
- createRenderer,
11
- EditorProvider,
12
- InferValues,
13
- } from '@coze-editor/editor/react';
14
- import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
15
- import { EditorView } from '@codemirror/view';
8
+ export const CodeEditor = lazy(() =>
9
+ import('./editor').then((module) => ({ default: module.CodeEditor }))
10
+ );
16
11
 
17
- import { getSuffixByLanguageId } from './utils';
18
- import { initTsWorker } from './language-features';
19
-
20
- import './theme';
21
- import './language-features';
22
-
23
- const OriginCodeEditor = createRenderer(preset, [
24
- EditorView.theme({
25
- '&.cm-focused': {
26
- outline: 'none',
27
- },
28
- }),
29
- ]);
30
-
31
- type Preset = typeof preset;
32
- type Options = Partial<InferValues<Preset[number]>>;
33
-
34
- export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
35
- value?: string;
36
- onChange?: (value: string) => void;
37
- languageId: 'python' | 'typescript' | 'shell' | 'json';
38
- theme?: 'dark' | 'light';
39
- placeholder?: string;
40
- activeLinePlaceholder?: string;
41
- readonly?: boolean;
42
- options?: Options;
43
- }
44
-
45
- export function CodeEditor({
46
- value,
47
- onChange,
48
- languageId = 'python',
49
- theme = 'light',
50
- children,
51
- placeholder,
52
- activeLinePlaceholder,
53
- options,
54
- readonly,
55
- }: CodeEditorPropsType) {
56
- const editorRef = useRef<EditorAPI | null>(null);
57
-
58
- useEffect(() => {
59
- if (languageId === 'typescript') {
60
- initTsWorker();
61
- }
62
- }, [languageId]);
63
-
64
- useEffect(() => {
65
- // listen to value change
66
- if (editorRef.current?.getValue() !== value) {
67
- editorRef.current?.setValue(String(value || ''));
68
- }
69
- }, [value]);
70
-
71
- return (
72
- <EditorProvider>
73
- <OriginCodeEditor
74
- defaultValue={value}
75
- options={{
76
- uri: `file:///untitled${getSuffixByLanguageId(languageId)}`,
77
- languageId,
78
- theme,
79
- placeholder,
80
- readOnly: readonly,
81
- editable: !readonly,
82
- ...(options || {}),
83
- }}
84
- didMount={(editor: EditorAPI) => {
85
- editorRef.current = editor;
86
- }}
87
- onChange={(e) => onChange?.(e.value)}
88
- >
89
- {activeLinePlaceholder && (
90
- <ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
91
- )}
92
- {children}
93
- </OriginCodeEditor>
94
- </EditorProvider>
95
- );
96
- }
12
+ export type { CodeEditorPropsType } from './editor';
@@ -7,11 +7,10 @@ import React from 'react';
7
7
 
8
8
  import styled from 'styled-components';
9
9
 
10
- import { CodeEditor, CodeEditorPropsType } from '@/components/code-editor';
10
+ import { CodeEditor, type CodeEditorPropsType } from '@/components/code-editor';
11
11
 
12
12
  const UIMini = styled.div`
13
13
  .ͼ1 .cm-content {
14
- padding: 0;
15
14
  }
16
15
  `;
17
16
 
@@ -23,6 +22,7 @@ export function CodeEditorMini(props: CodeEditorPropsType) {
23
22
  options={{
24
23
  lineNumbersGutter: false,
25
24
  foldGutter: false,
25
+ minHeight: 24,
26
26
  ...(props.options || {}),
27
27
  }}
28
28
  />
@@ -15,6 +15,7 @@ import { ConditionRowValueType, IRules, OpConfigs } from './types';
15
15
  import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
16
16
  import { useRule } from './hooks/useRule';
17
17
  import { useOp } from './hooks/useOp';
18
+ import { defaultOpConfigs, defaultRules } from './constants';
18
19
 
19
20
  interface PropTypes {
20
21
  value?: ConditionRowValueType;
@@ -96,4 +97,7 @@ export function ConditionRow({
96
97
  );
97
98
  }
98
99
 
100
+ ConditionRow.defaultRules = defaultRules;
101
+ ConditionRow.defaultOpConfigs = defaultOpConfigs;
102
+
99
103
  export { type ConditionRowValueType };
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { useMemo } from 'react';
7
+ import React from 'react';
8
+
9
+ import { JsonSchemaTypeManager, useTypeManager } from '@flowgram.ai/json-schema';
10
+ import { Icon } from '@douyinfe/semi-ui';
11
+
12
+ import { ConditionRow } from '@/components';
13
+
14
+ import { DBConditionOptionType, IRules } from '../types';
15
+ import { UIOptionLabel, UISelect } from '../styles';
16
+
17
+ const defaultRules = ConditionRow.defaultRules;
18
+
19
+ interface HookParams {
20
+ left?: string;
21
+ options?: DBConditionOptionType[];
22
+ userRules?: IRules;
23
+ readonly?: boolean;
24
+ onChange: (leftKey: string) => void;
25
+ }
26
+
27
+ export function useLeft({ left, options, userRules, readonly, onChange }: HookParams) {
28
+ const rules = useMemo(() => ({ ...defaultRules, ...(userRules || {}) }), [userRules]);
29
+
30
+ const typeManager = useTypeManager() as JsonSchemaTypeManager;
31
+
32
+ const rule = useMemo(() => {
33
+ if (!left) return undefined;
34
+
35
+ const option = options?.find((item) => item.value === left);
36
+
37
+ if (!option?.schema?.type) {
38
+ return undefined;
39
+ }
40
+
41
+ return rules[option.schema.type];
42
+ }, [left, options, rules]);
43
+
44
+ const renderDBOptionSelect = () => (
45
+ <UISelect
46
+ disabled={readonly}
47
+ size="small"
48
+ style={{ width: '100%' }}
49
+ value={left}
50
+ onChange={(v) => onChange(v as string)}
51
+ optionList={
52
+ options?.map((item) => ({
53
+ label: (
54
+ <UIOptionLabel>
55
+ <Icon size="small" svg={typeManager.getDisplayIcon(item.schema)} />
56
+ {item.label}
57
+ </UIOptionLabel>
58
+ ),
59
+ value: item.value,
60
+ })) || []
61
+ }
62
+ />
63
+ );
64
+
65
+ return { rule, renderDBOptionSelect };
66
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { useMemo } from 'react';
7
+
8
+ import { I18n } from '@flowgram.ai/editor';
9
+ import { Button, Select } from '@douyinfe/semi-ui';
10
+ import { IconChevronDownStroked } from '@douyinfe/semi-icons';
11
+
12
+ import { ConditionRow } from '@/components';
13
+
14
+ import { IRule, OpConfigs } from '../types';
15
+
16
+ const defaultOpConfigs = ConditionRow.defaultOpConfigs;
17
+
18
+ interface HookParams {
19
+ rule?: IRule;
20
+ op?: string;
21
+ onChange: (op: string) => void;
22
+ readonly?: boolean;
23
+ userOps?: OpConfigs;
24
+ }
25
+
26
+ export function useOp({ rule, op, onChange, readonly, userOps }: HookParams) {
27
+ const options = useMemo(
28
+ () =>
29
+ Object.keys(rule || {}).map((_op) => ({
30
+ ...(defaultOpConfigs[_op] || {}),
31
+ ...(userOps?.[_op] || {}),
32
+ value: _op,
33
+ label: I18n.t(userOps?.[_op]?.label || defaultOpConfigs[_op]?.label),
34
+ })),
35
+ [rule, userOps]
36
+ );
37
+
38
+ const opConfig = useMemo(() => defaultOpConfigs[op as string], [op]);
39
+
40
+ const renderOpSelect = () => (
41
+ <Select
42
+ style={{ height: 22 }}
43
+ disabled={readonly}
44
+ size="small"
45
+ value={op}
46
+ optionList={options}
47
+ onChange={(v) => {
48
+ onChange(v as string);
49
+ }}
50
+ triggerRender={({ value }) => (
51
+ <Button size="small" disabled={!rule}>
52
+ {opConfig?.abbreviation || <IconChevronDownStroked size="small" />}
53
+ </Button>
54
+ )}
55
+ />
56
+ );
57
+
58
+ return { renderOpSelect, opConfig };
59
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { useMemo } from 'react';
7
+
8
+ import { I18n } from '@flowgram.ai/editor';
9
+ import { Input } from '@douyinfe/semi-ui';
10
+
11
+ import { InjectDynamicValueInput } from '@/components/dynamic-value-input';
12
+
13
+ import { DBConditionOptionType, DBConditionRowValueType, IRules, OpConfigs } from './types';
14
+ import { UIContainer, UILeft, UIOperator, UIRight, UIValues } from './styles';
15
+ import { useOp } from './hooks/use-op';
16
+ import { useLeft } from './hooks/use-left';
17
+
18
+ interface PropTypes {
19
+ value?: DBConditionRowValueType;
20
+ onChange: (value?: DBConditionRowValueType) => void;
21
+ style?: React.CSSProperties;
22
+ options?: DBConditionOptionType[];
23
+ readonly?: boolean;
24
+ ruleConfig?: {
25
+ ops?: OpConfigs;
26
+ rules?: IRules;
27
+ };
28
+ }
29
+
30
+ const defaultRuleConfig = {
31
+ ops: {},
32
+ rules: {},
33
+ };
34
+
35
+ export function DBConditionRow({
36
+ style,
37
+ value,
38
+ onChange,
39
+ readonly,
40
+ options,
41
+ ruleConfig = defaultRuleConfig,
42
+ }: PropTypes) {
43
+ const { left, operator, right } = value || {};
44
+
45
+ const { rule, renderDBOptionSelect } = useLeft({
46
+ left,
47
+ options,
48
+ onChange: (leftKey) => onChange({ ...value, left: leftKey }),
49
+ readonly,
50
+ userRules: ruleConfig.rules,
51
+ });
52
+
53
+ const { renderOpSelect, opConfig } = useOp({
54
+ rule,
55
+ op: operator,
56
+ onChange: (v) => onChange({ ...value, operator: v }),
57
+ readonly,
58
+ userOps: ruleConfig.ops,
59
+ });
60
+
61
+ const targetSchema = useMemo(() => {
62
+ const targetType: string | null = rule?.[operator || ''] || null;
63
+ return targetType ? { type: targetType, extra: { weak: true } } : null;
64
+ }, [rule, opConfig]);
65
+
66
+ return (
67
+ <UIContainer style={style}>
68
+ <UIOperator>{renderOpSelect()}</UIOperator>
69
+ <UIValues>
70
+ <UILeft>{renderDBOptionSelect()}</UILeft>
71
+ <UIRight>
72
+ {targetSchema ? (
73
+ <InjectDynamicValueInput
74
+ readonly={readonly || !rule}
75
+ value={right}
76
+ schema={targetSchema}
77
+ onChange={(v) => onChange({ ...value, right: v })}
78
+ />
79
+ ) : (
80
+ <Input
81
+ size="small"
82
+ disabled
83
+ style={{ pointerEvents: 'none' }}
84
+ value={opConfig?.rightDisplay || I18n.t('Empty')}
85
+ />
86
+ )}
87
+ </UIRight>
88
+ </UIValues>
89
+ </UIContainer>
90
+ );
91
+ }
92
+
93
+ export { type DBConditionRowValueType, type DBConditionOptionType };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import styled from 'styled-components';
7
+ import { Select } from '@douyinfe/semi-ui';
8
+
9
+ export const UIContainer = styled.div`
10
+ display: flex;
11
+ align-items: center;
12
+ gap: 4px;
13
+ `;
14
+
15
+ export const UIOperator = styled.div``;
16
+
17
+ export const UILeft = styled.div`
18
+ width: 100%;
19
+ `;
20
+
21
+ export const UIRight = styled.div`
22
+ width: 100%;
23
+ `;
24
+
25
+ export const UIValues = styled.div`
26
+ flex-grow: 1;
27
+ display: flex;
28
+ flex-direction: column;
29
+ align-items: center;
30
+ gap: 4px;
31
+ `;
32
+
33
+ export const UIOptionLabel = styled.div`
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 10px;
37
+ `;
38
+
39
+ export const UISelect = styled(Select)`
40
+ & .semi-select-selection {
41
+ margin-left: 5px;
42
+ }
43
+ `;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { IJsonSchema } from '@flowgram.ai/json-schema';
7
+
8
+ import { IFlowConstantRefValue } from '@/typings';
9
+
10
+ export interface OpConfig {
11
+ label: string;
12
+ abbreviation: string;
13
+ // When right is not a value, display this text
14
+ rightDisplay?: string;
15
+ }
16
+
17
+ export type OpConfigs = Record<string, OpConfig>;
18
+
19
+ export type IRule = Partial<Record<string, string | null>>;
20
+
21
+ export type IRules = Record<string, IRule>;
22
+
23
+ export interface DBConditionRowValueType {
24
+ left?: string;
25
+ schema?: IJsonSchema;
26
+ operator?: string;
27
+ right?: IFlowConstantRefValue;
28
+ }
29
+
30
+ export interface DBConditionOptionType {
31
+ label: string | JSX.Element;
32
+ value: string;
33
+ schema: IJsonSchema;
34
+ }
@@ -10,6 +10,7 @@ export * from './batch-variable-selector';
10
10
  export * from './constant-input';
11
11
  export * from './dynamic-value-input';
12
12
  export * from './condition-row';
13
+ export * from './db-condition-row';
13
14
  export * from './batch-outputs';
14
15
  export * from './prompt-editor';
15
16
  export * from './prompt-editor-with-variables';
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React from 'react';
7
+
8
+ import { I18n } from '@flowgram.ai/editor';
9
+ import { transformerCreator } from '@coze-editor/editor/preset-code';
10
+ import { Text } from '@coze-editor/editor/language-json';
11
+
12
+ import { CodeEditor, type CodeEditorPropsType } from '@/components/code-editor';
13
+
14
+ import { VariableTree } from './extensions/variable-tree';
15
+ import { VariableTagInject } from './extensions/variable-tag';
16
+
17
+ type Match = { match: string; range: [number, number] };
18
+ function findAllMatches(inputString: string, regex: RegExp): Match[] {
19
+ const globalRegex = new RegExp(
20
+ regex,
21
+ regex.flags.includes('g') ? regex.flags : regex.flags + 'g'
22
+ );
23
+ let match;
24
+ const matches: Match[] = [];
25
+
26
+ while ((match = globalRegex.exec(inputString)) !== null) {
27
+ if (match.index === globalRegex.lastIndex) {
28
+ globalRegex.lastIndex++;
29
+ }
30
+ matches.push({
31
+ match: match[0],
32
+ range: [match.index, match.index + match[0].length],
33
+ });
34
+ }
35
+
36
+ return matches;
37
+ }
38
+
39
+ const transformer = transformerCreator((text: Text) => {
40
+ const originalSource = text.toString();
41
+ const matches = findAllMatches(originalSource, /\{\{([^\}]*)\}\}/g);
42
+
43
+ if (matches.length > 0) {
44
+ matches.forEach(({ range }) => {
45
+ text.replaceRange(range[0], range[1], 'null');
46
+ });
47
+ }
48
+
49
+ return text;
50
+ });
51
+
52
+ export interface JsonEditorWithVariablesProps extends Omit<CodeEditorPropsType, 'languageId'> {}
53
+
54
+ export function JsonEditorWithVariables(props: JsonEditorWithVariablesProps) {
55
+ return (
56
+ <CodeEditor
57
+ languageId="json"
58
+ activeLinePlaceholder={I18n.t("Press '@' to Select variable")}
59
+ {...props}
60
+ options={{
61
+ transformer,
62
+ ...(props.options || {}),
63
+ }}
64
+ >
65
+ <VariableTree />
66
+ <VariableTagInject />
67
+ </CodeEditor>
68
+ );
69
+ }