mirror of
https://github.com/perfect-panel/ppanel-web.git
synced 2026-02-13 03:41:10 -05:00
🐛 fix(editor): Change value
This commit is contained in:
parent
57fae12653
commit
4fdfeb2b1c
@ -5,11 +5,9 @@ import { MarkdownEditor } from '@repo/ui/editor';
|
|||||||
import { toast } from '@shadcn/ui/lib/sonner';
|
import { toast } from '@shadcn/ui/lib/sonner';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { useTheme } from 'next-themes';
|
|
||||||
|
|
||||||
export default function Tos() {
|
export default function Tos() {
|
||||||
const t = useTranslations('system.tos');
|
const t = useTranslations('system.tos');
|
||||||
const { resolvedTheme } = useTheme();
|
|
||||||
const { data, refetch, isFetched } = useQuery({
|
const { data, refetch, isFetched } = useQuery({
|
||||||
queryKey: ['getTosConfig'],
|
queryKey: ['getTosConfig'],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export function JSONEditor(props: JSONEditorProps) {
|
|||||||
props.value && typeof props.value === 'string' ? value : JSON.parse(value),
|
props.value && typeof props.value === 'string' ? value : JSON.parse(value),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Invalid JSON input:', e);
|
console.log('Invalid JSON input:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { type OnMount } from '@monaco-editor/react';
|
import { type OnMount } from '@monaco-editor/react';
|
||||||
import { Button } from '@shadcn/ui/button';
|
import { Button } from '@shadcn/ui/button';
|
||||||
import { cn } from '@shadcn/ui/lib/utils';
|
import { cn } from '@shadcn/ui/lib/utils';
|
||||||
import { useSize } from 'ahooks';
|
import { useSize } from 'ahooks';
|
||||||
import { EyeIcon, EyeOff, FullscreenIcon, MinimizeIcon } from 'lucide-react';
|
import { EyeIcon, EyeOff, FullscreenIcon, MinimizeIcon } from 'lucide-react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
const Editor = dynamic(() => import('@monaco-editor/react'), { ssr: false });
|
const Editor = dynamic(() => import('@monaco-editor/react'), { ssr: false });
|
||||||
|
|
||||||
export interface MonacoEditorProps {
|
export interface MonacoEditorProps {
|
||||||
@ -22,8 +21,16 @@ export interface MonacoEditorProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function debounce<T extends (...args: any[]) => void>(func: T, delay: number) {
|
||||||
|
let timeoutId: ReturnType<typeof setTimeout>;
|
||||||
|
return function (...args: Parameters<T>) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(() => func(...args), delay);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function MonacoEditor({
|
export function MonacoEditor({
|
||||||
value,
|
value: propValue,
|
||||||
onChange,
|
onChange,
|
||||||
onBlur,
|
onBlur,
|
||||||
title = 'Editor Title',
|
title = 'Editor Title',
|
||||||
@ -34,22 +41,44 @@ export function MonacoEditor({
|
|||||||
language = 'markdown',
|
language = 'markdown',
|
||||||
className,
|
className,
|
||||||
}: MonacoEditorProps) {
|
}: MonacoEditorProps) {
|
||||||
|
const [internalValue, setInternalValue] = useState<string | undefined>(propValue);
|
||||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||||
const [isPreviewVisible, setIsPreviewVisible] = useState(false);
|
const [isPreviewVisible, setIsPreviewVisible] = useState(false);
|
||||||
|
|
||||||
const toggleFullscreen = () => setIsFullscreen(!isFullscreen);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const togglePreview = () => setIsPreviewVisible(!isPreviewVisible);
|
const size = useSize(ref);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(propValue);
|
||||||
|
}, [propValue]);
|
||||||
|
|
||||||
|
const debouncedOnChange = useRef(
|
||||||
|
debounce((newValue: string | undefined) => {
|
||||||
|
if (onChange) {
|
||||||
|
onChange(newValue);
|
||||||
|
}
|
||||||
|
}, 300),
|
||||||
|
).current;
|
||||||
|
|
||||||
const handleEditorDidMount: OnMount = (editor, monaco) => {
|
const handleEditorDidMount: OnMount = (editor, monaco) => {
|
||||||
if (onMount) onMount(editor, monaco);
|
if (onMount) onMount(editor, monaco);
|
||||||
|
|
||||||
|
editor.onDidChangeModelContent(() => {
|
||||||
|
const newValue = editor.getValue();
|
||||||
|
setInternalValue(newValue);
|
||||||
|
debouncedOnChange(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
editor.onDidBlurEditorWidget(() => {
|
editor.onDidBlurEditorWidget(() => {
|
||||||
if (onBlur) {
|
if (onBlur) {
|
||||||
onBlur(editor.getValue());
|
onBlur(editor.getValue());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
|
||||||
const size = useSize(ref);
|
const toggleFullscreen = () => setIsFullscreen(!isFullscreen);
|
||||||
|
const togglePreview = () => setIsPreviewVisible(!isPreviewVisible);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className='size-full'>
|
<div ref={ref} className='size-full'>
|
||||||
<div style={size}>
|
<div style={size}>
|
||||||
@ -86,8 +115,11 @@ export function MonacoEditor({
|
|||||||
>
|
>
|
||||||
<Editor
|
<Editor
|
||||||
language={language}
|
language={language}
|
||||||
value={value}
|
value={internalValue}
|
||||||
onChange={onChange}
|
onChange={(newValue) => {
|
||||||
|
setInternalValue(newValue);
|
||||||
|
debouncedOnChange(newValue);
|
||||||
|
}}
|
||||||
onMount={handleEditorDidMount}
|
onMount={handleEditorDidMount}
|
||||||
className=''
|
className=''
|
||||||
options={{
|
options={{
|
||||||
@ -122,7 +154,7 @@ export function MonacoEditor({
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{!value && placeholder && (
|
{!internalValue?.trim() && placeholder && (
|
||||||
<pre
|
<pre
|
||||||
className='text-muted-foreground pointer-events-none absolute left-7 top-4 text-sm'
|
className='text-muted-foreground pointer-events-none absolute left-7 top-4 text-sm'
|
||||||
style={{ userSelect: 'none' }}
|
style={{ userSelect: 'none' }}
|
||||||
@ -132,7 +164,7 @@ export function MonacoEditor({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{render && isPreviewVisible && (
|
{render && isPreviewVisible && (
|
||||||
<div className='w-1/2 flex-1 overflow-auto border-l p-4'>{render(value)}</div>
|
<div className='w-1/2 flex-1 overflow-auto border-l p-4'>{render(internalValue)}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user