保留颜色草稿卸载时的修改

组件卸载前提交仍未关闭的颜色草稿,避免切换面板或删除组件导致颜色丢失
This commit is contained in:
2026-09-03 13:17:15 +08:00
parent 08caa1f29f
commit 79d3e5e6de
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { type RgbaColor, RgbaColorPicker } from 'react-colorful';
import type { FontSizing } from '../../../../../features/ui-editor/types/FontSizing';
@@ -22,6 +22,11 @@ export function TextPanel({
}: TextEditorProps) {
const [colorOpen, setColorOpen] = useState(false);
const [colorDraft, setColorDraft] = useState<RgbaColor | null>(null);
const colorDraftRef = useRef<RgbaColor | null>(null);
const componentRef = useRef(component);
const onChangeRef = useRef(onChange);
componentRef.current = component;
onChangeRef.current = onChange;
const committedRgba: RgbaColor = {
r: component.color[0] ?? 255,
g: component.color[1] ?? 255,
@@ -29,11 +34,26 @@ export function TextPanel({
a: (component.color[3] ?? 255) / 255,
};
const rgba = colorDraft ?? committedRgba;
useEffect(() => setColorDraft(null), [component.color]);
useEffect(() => {
colorDraftRef.current = null;
setColorDraft(null);
}, [component.color]);
useEffect(
() => () => {
const draft = colorDraftRef.current;
if (!draft) return;
onChangeRef.current({
...componentRef.current,
color: [draft.r, draft.g, draft.b, Math.round(draft.a * 255)],
});
},
[],
);
const bestFit =
'BestFit' in component.font_sizing ? component.font_sizing.BestFit : null;
const commitColor = (next: RgbaColor = rgba) => {
if (!colorDraft) return;
if (!colorDraftRef.current) return;
colorDraftRef.current = null;
setColorDraft(null);
onChange({
...component,
@@ -182,10 +202,18 @@ export function TextPanel({
</ComponentField>
{colorOpen && !readOnly ? (
<div className="absolute right-0 top-full z-20 mt-2 w-64 rounded-xl border border-(--platform-subpanel-border) bg-white p-3 shadow-xl">
<div onPointerCancel={() => setColorDraft(null)}>
<div
onPointerCancel={() => {
colorDraftRef.current = null;
setColorDraft(null);
}}
>
<RgbaColorPicker
color={rgba}
onChange={setColorDraft}
onChange={(next) => {
colorDraftRef.current = next;
setColorDraft(next);
}}
onChangeEnd={commitColor}
/>
</div>
@@ -196,6 +224,7 @@ export function TextPanel({
step={1}
value={Math.round(rgba.a * 255)}
onChange={(event) => {
colorDraftRef.current = null;
setColorDraft(null);
onChange({
...component,