feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
120
frontend/packages/common/md-editor-adapter/src/editor.tsx
Normal file
120
frontend/packages/common/md-editor-adapter/src/editor.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import {
|
||||
useRef,
|
||||
useImperativeHandle,
|
||||
forwardRef,
|
||||
useState,
|
||||
useEffect,
|
||||
} from 'react';
|
||||
|
||||
import { TextArea, withField } from '@coze-arch/coze-design';
|
||||
|
||||
import {
|
||||
type EditorInputProps,
|
||||
type EditorHandle,
|
||||
type Editor,
|
||||
type Delta,
|
||||
} from './types';
|
||||
|
||||
export const EditorFullInputInner = forwardRef<EditorHandle, EditorInputProps>(
|
||||
(props: EditorInputProps, ref) => {
|
||||
const {
|
||||
value: propsValue,
|
||||
onChange: propsOnChange,
|
||||
getEditor,
|
||||
...restProps
|
||||
} = props;
|
||||
const [value, setValue] = useState(propsValue);
|
||||
|
||||
// 创建一个可变引用以存储最新的value值
|
||||
const valueRef = useRef(value);
|
||||
|
||||
// 当value更新时,同步更新valueRef
|
||||
useEffect(() => {
|
||||
valueRef.current = value;
|
||||
}, [value]);
|
||||
|
||||
const editorRef = useRef<Editor>({
|
||||
setHTML: (htmlContent: string) => {
|
||||
setValue(htmlContent);
|
||||
},
|
||||
setText: (text: string) => {
|
||||
setValue(text);
|
||||
},
|
||||
setContent: (content: { deltas: Delta[] }) => {
|
||||
setValue(content.deltas[0].insert);
|
||||
},
|
||||
getContent: () => ({
|
||||
deltas: [{ insert: valueRef.current ?? '' }],
|
||||
}),
|
||||
getText: () => valueRef.current || '',
|
||||
getRootContainer: () => null,
|
||||
getContentState: () => ({
|
||||
getZoneState: (zone: any) => null,
|
||||
}),
|
||||
selection: {
|
||||
getSelection: () => ({
|
||||
start: 0,
|
||||
end: 0,
|
||||
zoneId: '0',
|
||||
}),
|
||||
},
|
||||
registerCommand: () => null,
|
||||
scrollModule: {
|
||||
scrollTo: () => null,
|
||||
},
|
||||
on: () => null,
|
||||
});
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
setDeltaContent(delta) {
|
||||
editorRef.current && delta && editorRef.current.setContent(delta);
|
||||
},
|
||||
getEditor() {
|
||||
return editorRef.current;
|
||||
},
|
||||
getMarkdown() {
|
||||
return editorRef.current?.getText() || '';
|
||||
},
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
getEditor?.(editorRef.current);
|
||||
}, [getEditor]);
|
||||
|
||||
return (
|
||||
<TextArea
|
||||
{...restProps}
|
||||
value={value}
|
||||
onChange={v => {
|
||||
setValue(v);
|
||||
propsOnChange?.(v);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const EditorInput: typeof EditorFullInputInner = withField(
|
||||
EditorFullInputInner,
|
||||
{
|
||||
valueKey: 'value',
|
||||
onKeyChangeFnName: 'onChange',
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user