live change value text

This commit is contained in:
hamid zarghami
2026-01-08 09:02:22 +03:30
parent 879c086069
commit 985c79b96b
2 changed files with 47 additions and 61 deletions
@@ -2,7 +2,6 @@ import { type FC, useState, useEffect, useMemo } from "react";
import Input from "@/components/Input"; import Input from "@/components/Input";
import Select from "@/components/Select"; import Select from "@/components/Select";
import ColorPicker from "@/components/ColorPicker"; import ColorPicker from "@/components/ColorPicker";
import Button from "@/components/Button";
import { useEditorStore } from "@/pages/editor/store/editorStore"; import { useEditorStore } from "@/pages/editor/store/editorStore";
import { useTextDefaultsStore } from "@/pages/editor/store/textDefaultsStore"; import { useTextDefaultsStore } from "@/pages/editor/store/textDefaultsStore";
@@ -17,6 +16,7 @@ const fontWeightOptions = [
{ label: "Light", value: "300" }, { label: "Light", value: "300" },
]; ];
type TextFormState = { type TextFormState = {
text: string; text: string;
fontFamily: string; fontFamily: string;
@@ -61,7 +61,10 @@ const TextInstruction: FC = () => {
const handleChange = (field: keyof TextFormState, value: string | number) => { const handleChange = (field: keyof TextFormState, value: string | number) => {
if (isEditing && selectedObject) { if (isEditing && selectedObject) {
setFormState((prev) => ({ ...prev, [field]: value })); // اعمال تغییرات به صورت لایو
const newState = { ...formState, [field]: value };
setFormState(newState);
updateObject(selectedObject.id, { [field]: value });
} else { } else {
// text فقط برای حالت ویرایش است و نباید در defaults ذخیره شود // text فقط برای حالت ویرایش است و نباید در defaults ذخیره شود
if (field !== "text") { if (field !== "text") {
@@ -70,41 +73,13 @@ const TextInstruction: FC = () => {
} }
}; };
const handleSave = () => { // State محلی برای نمایش شفافیت
if (isEditing && selectedObject) { const [opacityDisplay, setOpacityDisplay] = useState<string>(`${formState.opacity}`);
updateObject(selectedObject.id, formState);
}
};
const isDirty = isEditing && selectedObject
? formState.text !== baseValues.text ||
formState.fontFamily !== baseValues.fontFamily ||
formState.fontWeight !== baseValues.fontWeight ||
formState.fontSize !== baseValues.fontSize ||
formState.fill !== baseValues.fill ||
formState.opacity !== baseValues.opacity ||
formState.letterSpacing !== baseValues.letterSpacing ||
formState.wordSpacing !== baseValues.wordSpacing
: false;
const opacityValue = formState.opacity;
const [opacityInput, setOpacityInput] = useState<string>(`${opacityValue}`);
useEffect(() => { useEffect(() => {
setOpacityInput(`${opacityValue}`); setOpacityDisplay(`${formState.opacity}`);
}, [opacityValue]); }, [formState.opacity]);
const handleOpacityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value.replace("%", "").trim();
setOpacityInput(value);
};
const handleOpacityBlur = () => {
const numValue = parseInt(opacityInput) || 0;
const clampedValue = Math.min(100, Math.max(0, numValue));
setOpacityInput(`${clampedValue}`);
handleChange("opacity", clampedValue);
};
return ( return (
<div> <div>
@@ -141,13 +116,14 @@ const TextInstruction: FC = () => {
/> />
<Input <Input
value={`${formState.fontSize}px`} type="number"
label="سایز" label="سایز"
value={formState.fontSize}
onChange={(e) => { onChange={(e) => {
const value = e.target.value.replace("px", "").trim(); const numValue = parseInt(e.target.value) || 0;
const numValue = parseInt(value) || 0;
handleChange("fontSize", numValue); handleChange("fontSize", numValue);
}} }}
min={1}
/> />
</div> </div>
@@ -160,24 +136,33 @@ const TextInstruction: FC = () => {
onChange={(value) => handleChange("fill", value)} onChange={(value) => handleChange("fill", value)}
/> />
<div className="w-28"> <div className="w-28">
<label className="text-sm">شفافیت</label> <Input
<div className="mt-1 flex h-10 items-center rounded-xl border border-border px-2 text-sm"> type="number"
<input label="شفافیت"
type="text" className="px-3"
className="w-full border-none bg-transparent text-center text-sm outline-none" value={opacityDisplay}
value={`${opacityInput}%`} onChange={(e) => {
onChange={handleOpacityChange} const value = e.target.value;
onBlur={handleOpacityBlur} setOpacityDisplay(value);
onKeyDown={(e) => {
if (e.key === "Enter") { // اعمال تغییرات به صورت لایو اگر مقدار معتبر است
e.currentTarget.blur(); const numValue = parseInt(value);
if (!isNaN(numValue) && numValue >= 0 && numValue <= 100) {
handleChange("opacity", numValue);
} }
}} }}
onBlur={(e) => {
const numValue = parseInt(e.target.value) || 0;
const clampedValue = Math.min(100, Math.max(0, numValue));
setOpacityDisplay(`${clampedValue}`);
handleChange("opacity", clampedValue);
}}
min={0}
max={100}
/> />
</div> </div>
</div> </div>
</div> </div>
</div>
{/* <div className="mt-4 flex gap-2"> {/* <div className="mt-4 flex gap-2">
<Input <Input
@@ -200,14 +185,6 @@ const TextInstruction: FC = () => {
}} }}
/> />
</div> */} </div> */}
{isEditing && (
<div className="mt-4">
<Button type="button" onClick={handleSave} disabled={!isDirty} className="w-full">
ذخیره تغییرات
</Button>
</div>
)}
</div> </div>
); );
}; };
@@ -12,12 +12,21 @@ const getFontFamily = (fontFamily?: string): string => {
}; };
const getFontWeight = (fontWeight?: string): string => { const getFontWeight = (fontWeight?: string): string => {
if (!fontWeight) return "normal";
// اگر عدد است، مستقیماً برگردان
const numValue = parseInt(fontWeight);
if (!isNaN(numValue)) {
return numValue.toString();
}
// برای مقادیر string قدیمی
const weightMap: Record<string, string> = { const weightMap: Record<string, string> = {
bold: "bold", bold: "bold",
normal: "normal", normal: "normal",
"300": "300", "300": "300",
}; };
return weightMap[fontWeight || "normal"] || "normal"; return weightMap[fontWeight] || "normal";
}; };
const getColorWithOpacity = (fill?: string, opacity?: number): string => { const getColorWithOpacity = (fill?: string, opacity?: number): string => {