@flowgram.ai/form-materials 0.4.4 → 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.
- package/dist/esm/chunk-6OZSB6PD.js +10 -0
- package/dist/esm/chunk-6OZSB6PD.js.map +1 -0
- package/dist/esm/chunk-G4HQ7OSI.js +440 -0
- package/dist/esm/chunk-G4HQ7OSI.js.map +1 -0
- package/dist/esm/chunk-QIJ4QVB2.js +271 -0
- package/dist/esm/chunk-QIJ4QVB2.js.map +1 -0
- package/dist/esm/editor-6UMULJYB.js +180 -0
- package/dist/esm/editor-6UMULJYB.js.map +1 -0
- package/dist/esm/editor-E2BQTPCD.js +388 -0
- package/dist/esm/editor-E2BQTPCD.js.map +1 -0
- package/dist/esm/editor-H2R7JJLO.js +282 -0
- package/dist/esm/editor-H2R7JJLO.js.map +1 -0
- package/dist/esm/editor-JX42GFAZ.js +249 -0
- package/dist/esm/editor-JX42GFAZ.js.map +1 -0
- package/dist/esm/editor-YMNCDGUR.js +167 -0
- package/dist/esm/editor-YMNCDGUR.js.map +1 -0
- package/dist/esm/index.js +1388 -3029
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +144 -51
- package/dist/index.d.ts +144 -51
- package/dist/index.js +3511 -2759
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/components/code-editor/editor.tsx +96 -0
- package/src/components/code-editor/index.tsx +5 -89
- package/src/components/code-editor/theme/dark.ts +49 -30
- package/src/components/code-editor/theme/light.ts +56 -32
- package/src/components/code-editor-mini/index.tsx +2 -2
- package/src/components/condition-row/index.tsx +4 -0
- package/src/components/db-condition-row/hooks/use-left.tsx +66 -0
- package/src/components/db-condition-row/hooks/use-op.tsx +59 -0
- package/src/components/db-condition-row/index.tsx +93 -0
- package/src/components/db-condition-row/styles.tsx +43 -0
- package/src/components/db-condition-row/types.ts +34 -0
- package/src/components/index.ts +1 -0
- package/src/components/json-editor-with-variables/editor.tsx +69 -0
- package/src/components/json-editor-with-variables/extensions/variable-tag.tsx +4 -3
- package/src/components/json-editor-with-variables/index.tsx +5 -60
- package/src/components/prompt-editor/editor.tsx +81 -0
- package/src/components/prompt-editor/index.tsx +5 -69
- package/src/components/prompt-editor-with-inputs/editor.tsx +25 -0
- package/src/components/prompt-editor-with-inputs/index.tsx +5 -15
- package/src/components/prompt-editor-with-variables/editor.tsx +22 -0
- package/src/components/prompt-editor-with-variables/extensions/variable-tag.tsx +10 -18
- package/src/components/prompt-editor-with-variables/index.tsx +5 -13
- package/src/shared/index.ts +1 -0
- package/src/shared/polyfill-create-root/index.tsx +33 -0
|
@@ -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
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -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
|
+
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import React, { useLayoutEffect } from 'react';
|
|
7
7
|
|
|
8
|
-
import { createRoot, Root } from 'react-dom/client';
|
|
9
8
|
import { isEqual, last } from 'lodash';
|
|
10
9
|
import {
|
|
11
10
|
BaseVariableField,
|
|
@@ -26,6 +25,8 @@ import {
|
|
|
26
25
|
WidgetType,
|
|
27
26
|
} from '@codemirror/view';
|
|
28
27
|
|
|
28
|
+
import { IPolyfillRoot, polyfillCreateRoot } from '@/shared';
|
|
29
|
+
|
|
29
30
|
import { UIPopoverContent, UIRootTitle, UITag, UIVarName } from '../styles';
|
|
30
31
|
|
|
31
32
|
class VariableTagWidget extends WidgetType {
|
|
@@ -35,7 +36,7 @@ class VariableTagWidget extends WidgetType {
|
|
|
35
36
|
|
|
36
37
|
scope: Scope;
|
|
37
38
|
|
|
38
|
-
root:
|
|
39
|
+
root: IPolyfillRoot;
|
|
39
40
|
|
|
40
41
|
constructor({ keyPath, scope }: { keyPath?: string[]; scope: Scope }) {
|
|
41
42
|
super();
|
|
@@ -90,7 +91,7 @@ class VariableTagWidget extends WidgetType {
|
|
|
90
91
|
toDOM(view: EditorView): HTMLElement {
|
|
91
92
|
const dom = document.createElement('span');
|
|
92
93
|
|
|
93
|
-
this.root =
|
|
94
|
+
this.root = polyfillCreateRoot(dom);
|
|
94
95
|
|
|
95
96
|
this.toDispose.push(
|
|
96
97
|
Disposable.create(() => {
|
|
@@ -3,65 +3,10 @@
|
|
|
3
3
|
* SPDX-License-Identifier: MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import { lazy } from 'react';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
import {
|
|
8
|
+
export const JsonEditorWithVariables = lazy(() =>
|
|
9
|
+
import('./editor').then((module) => ({ default: module.JsonEditorWithVariables }))
|
|
10
|
+
);
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { VariableTree } from './extensions/variable-tree';
|
|
14
|
-
import { VariableTagInject } from './extensions/variable-tag';
|
|
15
|
-
import { I18n } from '@flowgram.ai/editor';
|
|
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 function JsonEditorWithVariables(props: Omit<CodeEditorPropsType, 'languageId'>) {
|
|
53
|
-
return (
|
|
54
|
-
<CodeEditor
|
|
55
|
-
languageId="json"
|
|
56
|
-
activeLinePlaceholder={I18n.t("Press '@' to Select variable")}
|
|
57
|
-
{...props}
|
|
58
|
-
options={{
|
|
59
|
-
transformer,
|
|
60
|
-
...(props.options || {}),
|
|
61
|
-
}}
|
|
62
|
-
>
|
|
63
|
-
<VariableTree />
|
|
64
|
-
<VariableTagInject />
|
|
65
|
-
</CodeEditor>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
12
|
+
export type { JsonEditorWithVariablesProps } from './editor';
|
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
Renderer,
|
|
10
|
+
EditorProvider,
|
|
11
|
+
ActiveLinePlaceholder,
|
|
12
|
+
InferValues,
|
|
13
|
+
} from '@coze-editor/editor/react';
|
|
14
|
+
import preset, { EditorAPI } from '@coze-editor/editor/preset-prompt';
|
|
15
|
+
|
|
16
|
+
import { PropsType } from './types';
|
|
17
|
+
import { UIContainer } from './styles';
|
|
18
|
+
import MarkdownHighlight from './extensions/markdown';
|
|
19
|
+
import LanguageSupport from './extensions/language-support';
|
|
20
|
+
import JinjaHighlight from './extensions/jinja';
|
|
21
|
+
|
|
22
|
+
type Preset = typeof preset;
|
|
23
|
+
type Options = Partial<InferValues<Preset[number]>>;
|
|
24
|
+
|
|
25
|
+
export interface PromptEditorPropsType extends PropsType {
|
|
26
|
+
options?: Options;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function PromptEditor(props: PromptEditorPropsType) {
|
|
30
|
+
const {
|
|
31
|
+
value,
|
|
32
|
+
onChange,
|
|
33
|
+
readonly,
|
|
34
|
+
placeholder,
|
|
35
|
+
activeLinePlaceholder,
|
|
36
|
+
style,
|
|
37
|
+
hasError,
|
|
38
|
+
children,
|
|
39
|
+
disableMarkdownHighlight,
|
|
40
|
+
options,
|
|
41
|
+
} = props || {};
|
|
42
|
+
|
|
43
|
+
const editorRef = useRef<EditorAPI | null>(null);
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
// listen to value change
|
|
47
|
+
if (editorRef.current?.getValue() !== value?.content) {
|
|
48
|
+
editorRef.current?.setValue(String(value?.content || ''));
|
|
49
|
+
}
|
|
50
|
+
}, [value]);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<UIContainer $hasError={hasError} style={style}>
|
|
54
|
+
<EditorProvider>
|
|
55
|
+
<Renderer
|
|
56
|
+
didMount={(editor: EditorAPI) => {
|
|
57
|
+
editorRef.current = editor;
|
|
58
|
+
}}
|
|
59
|
+
plugins={preset}
|
|
60
|
+
defaultValue={String(value?.content)}
|
|
61
|
+
options={{
|
|
62
|
+
readOnly: readonly,
|
|
63
|
+
editable: !readonly,
|
|
64
|
+
placeholder,
|
|
65
|
+
...options,
|
|
66
|
+
}}
|
|
67
|
+
onChange={(e) => {
|
|
68
|
+
onChange({ type: 'template', content: e.value });
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
71
|
+
{activeLinePlaceholder && (
|
|
72
|
+
<ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
|
|
73
|
+
)}
|
|
74
|
+
{!disableMarkdownHighlight && <MarkdownHighlight />}
|
|
75
|
+
<LanguageSupport />
|
|
76
|
+
<JinjaHighlight />
|
|
77
|
+
{children}
|
|
78
|
+
</EditorProvider>
|
|
79
|
+
</UIContainer>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -3,74 +3,10 @@
|
|
|
3
3
|
* SPDX-License-Identifier: MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import { lazy } from 'react';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
import
|
|
8
|
+
export const PromptEditor = lazy(() =>
|
|
9
|
+
import('./editor').then((module) => ({ default: module.PromptEditor }))
|
|
10
|
+
);
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
import { UIContainer } from './styles';
|
|
13
|
-
import MarkdownHighlight from './extensions/markdown';
|
|
14
|
-
import LanguageSupport from './extensions/language-support';
|
|
15
|
-
import JinjaHighlight from './extensions/jinja';
|
|
16
|
-
|
|
17
|
-
type Preset = typeof preset;
|
|
18
|
-
type Options = Partial<InferValues<Preset[number]>>;
|
|
19
|
-
|
|
20
|
-
export interface PromptEditorPropsType extends PropsType {
|
|
21
|
-
options?: Options;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function PromptEditor(props: PromptEditorPropsType) {
|
|
25
|
-
const {
|
|
26
|
-
value,
|
|
27
|
-
onChange,
|
|
28
|
-
readonly,
|
|
29
|
-
placeholder,
|
|
30
|
-
activeLinePlaceholder,
|
|
31
|
-
style,
|
|
32
|
-
hasError,
|
|
33
|
-
children,
|
|
34
|
-
disableMarkdownHighlight,
|
|
35
|
-
options,
|
|
36
|
-
} = props || {};
|
|
37
|
-
|
|
38
|
-
const editorRef = useRef<EditorAPI | null>(null);
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
// listen to value change
|
|
42
|
-
if (editorRef.current?.getValue() !== value?.content) {
|
|
43
|
-
editorRef.current?.setValue(String(value?.content || ''));
|
|
44
|
-
}
|
|
45
|
-
}, [value]);
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<UIContainer $hasError={hasError} style={style}>
|
|
49
|
-
<EditorProvider>
|
|
50
|
-
<Renderer
|
|
51
|
-
didMount={(editor: EditorAPI) => {
|
|
52
|
-
editorRef.current = editor;
|
|
53
|
-
}}
|
|
54
|
-
plugins={preset}
|
|
55
|
-
defaultValue={String(value?.content)}
|
|
56
|
-
options={{
|
|
57
|
-
readOnly: readonly,
|
|
58
|
-
editable: !readonly,
|
|
59
|
-
placeholder,
|
|
60
|
-
...options
|
|
61
|
-
}}
|
|
62
|
-
onChange={(e) => {
|
|
63
|
-
onChange({ type: 'template', content: e.value });
|
|
64
|
-
}}
|
|
65
|
-
/>
|
|
66
|
-
{activeLinePlaceholder && (
|
|
67
|
-
<ActiveLinePlaceholder>{activeLinePlaceholder}</ActiveLinePlaceholder>
|
|
68
|
-
)}
|
|
69
|
-
{!disableMarkdownHighlight && <MarkdownHighlight />}
|
|
70
|
-
<LanguageSupport />
|
|
71
|
-
<JinjaHighlight />
|
|
72
|
-
{children}
|
|
73
|
-
</EditorProvider>
|
|
74
|
-
</UIContainer>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
12
|
+
export type { PromptEditorPropsType } from './editor';
|
|
@@ -0,0 +1,25 @@
|
|
|
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 { PromptEditor, PromptEditorPropsType } from '@/components/prompt-editor';
|
|
9
|
+
|
|
10
|
+
import { InputsTree } from './extensions/inputs-tree';
|
|
11
|
+
|
|
12
|
+
export interface PromptEditorWithInputsProps extends PromptEditorPropsType {
|
|
13
|
+
inputsValues: any;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function PromptEditorWithInputs({
|
|
17
|
+
inputsValues,
|
|
18
|
+
...restProps
|
|
19
|
+
}: PromptEditorWithInputsProps) {
|
|
20
|
+
return (
|
|
21
|
+
<PromptEditor {...restProps}>
|
|
22
|
+
<InputsTree inputsValues={inputsValues} />
|
|
23
|
+
</PromptEditor>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -3,20 +3,10 @@
|
|
|
3
3
|
* SPDX-License-Identifier: MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import { lazy } from 'react';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
export const PromptEditorWithInputs = lazy(() =>
|
|
9
|
+
import('./editor').then((module) => ({ default: module.PromptEditorWithInputs }))
|
|
10
|
+
);
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
interface PropsType extends PromptEditorPropsType {
|
|
13
|
-
inputsValues: any;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function PromptEditorWithInputs({ inputsValues, ...restProps }: PropsType) {
|
|
17
|
-
return (
|
|
18
|
-
<PromptEditor {...restProps}>
|
|
19
|
-
<InputsTree inputsValues={inputsValues} />
|
|
20
|
-
</PromptEditor>
|
|
21
|
-
);
|
|
22
|
-
}
|
|
12
|
+
export type { PromptEditorWithInputsProps } from './editor';
|
|
@@ -0,0 +1,22 @@
|
|
|
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 { PromptEditor, PromptEditorPropsType } from '@/components/prompt-editor';
|
|
9
|
+
|
|
10
|
+
import { VariableTree } from './extensions/variable-tree';
|
|
11
|
+
import { VariableTagInject } from './extensions/variable-tag';
|
|
12
|
+
|
|
13
|
+
export interface PromptEditorWithVariablesProps extends PromptEditorPropsType {}
|
|
14
|
+
|
|
15
|
+
export function PromptEditorWithVariables(props: PromptEditorWithVariablesProps) {
|
|
16
|
+
return (
|
|
17
|
+
<PromptEditor {...props}>
|
|
18
|
+
<VariableTree />
|
|
19
|
+
<VariableTagInject />
|
|
20
|
+
</PromptEditor>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* SPDX-License-Identifier: MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import ReactDOM from 'react-dom';
|
|
7
6
|
import React, { useLayoutEffect } from 'react';
|
|
8
7
|
|
|
9
8
|
import { isEqual, last } from 'lodash';
|
|
@@ -26,6 +25,8 @@ import {
|
|
|
26
25
|
WidgetType,
|
|
27
26
|
} from '@codemirror/view';
|
|
28
27
|
|
|
28
|
+
import { IPolyfillRoot, polyfillCreateRoot } from '@/shared';
|
|
29
|
+
|
|
29
30
|
import { UIPopoverContent, UIRootTitle, UITag, UIVarName } from '../styles';
|
|
30
31
|
|
|
31
32
|
class VariableTagWidget extends WidgetType {
|
|
@@ -35,7 +36,7 @@ class VariableTagWidget extends WidgetType {
|
|
|
35
36
|
|
|
36
37
|
scope: Scope;
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
root: IPolyfillRoot;
|
|
39
40
|
|
|
40
41
|
constructor({ keyPath, scope }: { keyPath?: string[]; scope: Scope }) {
|
|
41
42
|
super();
|
|
@@ -52,14 +53,9 @@ class VariableTagWidget extends WidgetType {
|
|
|
52
53
|
return icon;
|
|
53
54
|
};
|
|
54
55
|
|
|
55
|
-
renderReact(jsx: React.ReactElement) {
|
|
56
|
-
// NOTICE: For React 19, upgrade to 'react-dom/client'
|
|
57
|
-
ReactDOM.render(jsx, this.rootDOM!);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
56
|
renderVariable(v?: BaseVariableField) {
|
|
61
57
|
if (!v) {
|
|
62
|
-
this.
|
|
58
|
+
this.root.render(
|
|
63
59
|
<UITag prefixIcon={<IconIssueStroked />} color="amber">
|
|
64
60
|
Unknown
|
|
65
61
|
</UITag>
|
|
@@ -67,17 +63,14 @@ class VariableTagWidget extends WidgetType {
|
|
|
67
63
|
return;
|
|
68
64
|
}
|
|
69
65
|
|
|
70
|
-
const rootField = last(v.parentFields)
|
|
71
|
-
const isRoot = v.parentFields.length === 0;
|
|
66
|
+
const rootField = last(v.parentFields);
|
|
72
67
|
|
|
73
68
|
const rootTitle = (
|
|
74
|
-
<UIRootTitle>
|
|
75
|
-
{rootField?.meta.title ? `${rootField.meta.title} ${isRoot ? '' : '-'} ` : ''}
|
|
76
|
-
</UIRootTitle>
|
|
69
|
+
<UIRootTitle>{rootField?.meta.title ? `${rootField.meta.title} -` : ''}</UIRootTitle>
|
|
77
70
|
);
|
|
78
71
|
const rootIcon = this.renderIcon(rootField?.meta.icon);
|
|
79
72
|
|
|
80
|
-
this.
|
|
73
|
+
this.root.render(
|
|
81
74
|
<Popover
|
|
82
75
|
content={
|
|
83
76
|
<UIPopoverContent>
|
|
@@ -89,7 +82,7 @@ class VariableTagWidget extends WidgetType {
|
|
|
89
82
|
>
|
|
90
83
|
<UITag prefixIcon={rootIcon}>
|
|
91
84
|
{rootTitle}
|
|
92
|
-
|
|
85
|
+
<UIVarName>{v?.key}</UIVarName>
|
|
93
86
|
</UITag>
|
|
94
87
|
</Popover>
|
|
95
88
|
);
|
|
@@ -98,12 +91,11 @@ class VariableTagWidget extends WidgetType {
|
|
|
98
91
|
toDOM(view: EditorView): HTMLElement {
|
|
99
92
|
const dom = document.createElement('span');
|
|
100
93
|
|
|
101
|
-
this.
|
|
94
|
+
this.root = polyfillCreateRoot(dom);
|
|
102
95
|
|
|
103
96
|
this.toDispose.push(
|
|
104
97
|
Disposable.create(() => {
|
|
105
|
-
|
|
106
|
-
ReactDOM.unmountComponentAtNode(this.rootDOM!);
|
|
98
|
+
this.root.unmount();
|
|
107
99
|
})
|
|
108
100
|
);
|
|
109
101
|
|