text alignment

This commit is contained in:
hamid zarghami
2026-05-06 09:32:36 +03:30
parent 5de205a84f
commit 1518e83c1d
4 changed files with 53 additions and 6 deletions
@@ -71,6 +71,7 @@ export const useDrawingHandlers = () => {
text: "متن جدید",
fontSize: defaults.fontSize,
lineHeight: 1.2,
textAlign: "right",
fontFamily: defaults.fontFamily,
fontWeight: defaults.fontWeight,
fill: defaults.fill,
@@ -21,6 +21,15 @@ const normalizeNumericInput = (value: string): string => {
const parseNumber = (value: string): number => Number(normalizeNumericInput(value));
const TextSettings = ({ selectedObject, onUpdate }: TextSettingsProps) => {
const textAlign = selectedObject.textAlign ?? "right";
const alignButtonClass = (align: "right" | "center" | "left") =>
`rounded-md border px-3 py-1 text-xs transition-colors ${
textAlign === align
? "border-blue-500 bg-blue-50 text-blue-700"
: "border-border text-foreground hover:bg-muted"
}`;
return (
<>
<Input
@@ -51,6 +60,32 @@ const TextSettings = ({ selectedObject, onUpdate }: TextSettingsProps) => {
})
}
/>
<div className="space-y-2">
<p className="text-sm">چینش متن</p>
<div className="grid grid-cols-3 gap-2">
<button
type="button"
className={alignButtonClass("right")}
onClick={() => onUpdate(selectedObject.id, { textAlign: "right" })}
>
راست
</button>
<button
type="button"
className={alignButtonClass("center")}
onClick={() => onUpdate(selectedObject.id, { textAlign: "center" })}
>
وسط
</button>
<button
type="button"
className={alignButtonClass("left")}
onClick={() => onUpdate(selectedObject.id, { textAlign: "left" })}
>
چپ
</button>
</div>
</div>
<ColorPicker
label="رنگ متن"
value={selectedObject.fill || "#000000"}
@@ -87,10 +87,18 @@ const TextShape = ({
const { width: rw, height: rh } = textNode.getClientRect({
skipTransform: true,
});
const w = Math.ceil(rw);
const measuredWidth = Math.ceil(rw);
const h = Math.ceil(rh);
if (w > 0 && h > 0 && (w !== obj.width || h !== obj.height)) {
onUpdate(obj.id, { width: w, height: h });
const nextWidth = obj.width && obj.width > 0 ? obj.width : measuredWidth;
// For text alignment to be visible, keep an existing text box width
// and only auto-calc width when the object has no width yet.
if (
nextWidth > 0 &&
h > 0 &&
(nextWidth !== obj.width || h !== obj.height)
) {
onUpdate(obj.id, { width: nextWidth, height: h });
}
textNode.getLayer()?.batchDraw();
};
@@ -156,6 +164,7 @@ const TextShape = ({
const fontFamily = useMemo(() => getFontFamily(obj.fontFamily), [obj.fontFamily]);
const konvaFontStyle = useMemo(() => getKonvaFontStyle(obj.fontWeight), [obj.fontWeight]);
const fillColor = useMemo(() => getColorWithOpacity(obj.fill, obj.opacity), [obj.fill, obj.opacity]);
const textAlign = obj.textAlign ?? "right";
const handleDblClick = () => {
if (!shapeRef.current || !groupRef.current) return;
@@ -203,7 +212,7 @@ const TextShape = ({
color: obj.fill || "#000000",
letterSpacing: `${(obj.letterSpacing || 0) * stageScale}px`,
lineHeight: textNode.lineHeight().toString(),
textAlign: "right",
textAlign,
direction: "rtl",
padding: "0",
margin: "0",
@@ -306,7 +315,7 @@ const TextShape = ({
>
<Text
ref={shapeRef}
x={0}
x={-(obj.width || 0)}
y={0}
text={obj.text || ""}
fontSize={obj.fontSize || 24}
@@ -315,7 +324,8 @@ const TextShape = ({
fontStyle={konvaFontStyle}
letterSpacing={obj.letterSpacing ?? 0}
lineHeight={obj.lineHeight ?? 1.2}
align="right"
width={obj.width || undefined}
align={textAlign}
/>
</Group>
);
@@ -46,6 +46,7 @@ export type EditorObject = {
text?: string;
fontSize?: number;
lineHeight?: number;
textAlign?: "left" | "center" | "right";
fontFamily?: string;
fontWeight?: string;
letterSpacing?: number;