live change value text
This commit is contained in:
@@ -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 => {
|
||||||
|
|||||||
Reference in New Issue
Block a user