text alignment
This commit is contained in:
@@ -71,6 +71,7 @@ export const useDrawingHandlers = () => {
|
|||||||
text: "متن جدید",
|
text: "متن جدید",
|
||||||
fontSize: defaults.fontSize,
|
fontSize: defaults.fontSize,
|
||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
|
textAlign: "right",
|
||||||
fontFamily: defaults.fontFamily,
|
fontFamily: defaults.fontFamily,
|
||||||
fontWeight: defaults.fontWeight,
|
fontWeight: defaults.fontWeight,
|
||||||
fill: defaults.fill,
|
fill: defaults.fill,
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ const normalizeNumericInput = (value: string): string => {
|
|||||||
const parseNumber = (value: string): number => Number(normalizeNumericInput(value));
|
const parseNumber = (value: string): number => Number(normalizeNumericInput(value));
|
||||||
|
|
||||||
const TextSettings = ({ selectedObject, onUpdate }: TextSettingsProps) => {
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Input
|
<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
|
<ColorPicker
|
||||||
label="رنگ متن"
|
label="رنگ متن"
|
||||||
value={selectedObject.fill || "#000000"}
|
value={selectedObject.fill || "#000000"}
|
||||||
|
|||||||
@@ -87,10 +87,18 @@ const TextShape = ({
|
|||||||
const { width: rw, height: rh } = textNode.getClientRect({
|
const { width: rw, height: rh } = textNode.getClientRect({
|
||||||
skipTransform: true,
|
skipTransform: true,
|
||||||
});
|
});
|
||||||
const w = Math.ceil(rw);
|
const measuredWidth = Math.ceil(rw);
|
||||||
const h = Math.ceil(rh);
|
const h = Math.ceil(rh);
|
||||||
if (w > 0 && h > 0 && (w !== obj.width || h !== obj.height)) {
|
const nextWidth = obj.width && obj.width > 0 ? obj.width : measuredWidth;
|
||||||
onUpdate(obj.id, { width: w, height: h });
|
|
||||||
|
// 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();
|
textNode.getLayer()?.batchDraw();
|
||||||
};
|
};
|
||||||
@@ -156,6 +164,7 @@ const TextShape = ({
|
|||||||
const fontFamily = useMemo(() => getFontFamily(obj.fontFamily), [obj.fontFamily]);
|
const fontFamily = useMemo(() => getFontFamily(obj.fontFamily), [obj.fontFamily]);
|
||||||
const konvaFontStyle = useMemo(() => getKonvaFontStyle(obj.fontWeight), [obj.fontWeight]);
|
const konvaFontStyle = useMemo(() => getKonvaFontStyle(obj.fontWeight), [obj.fontWeight]);
|
||||||
const fillColor = useMemo(() => getColorWithOpacity(obj.fill, obj.opacity), [obj.fill, obj.opacity]);
|
const fillColor = useMemo(() => getColorWithOpacity(obj.fill, obj.opacity), [obj.fill, obj.opacity]);
|
||||||
|
const textAlign = obj.textAlign ?? "right";
|
||||||
|
|
||||||
const handleDblClick = () => {
|
const handleDblClick = () => {
|
||||||
if (!shapeRef.current || !groupRef.current) return;
|
if (!shapeRef.current || !groupRef.current) return;
|
||||||
@@ -203,7 +212,7 @@ const TextShape = ({
|
|||||||
color: obj.fill || "#000000",
|
color: obj.fill || "#000000",
|
||||||
letterSpacing: `${(obj.letterSpacing || 0) * stageScale}px`,
|
letterSpacing: `${(obj.letterSpacing || 0) * stageScale}px`,
|
||||||
lineHeight: textNode.lineHeight().toString(),
|
lineHeight: textNode.lineHeight().toString(),
|
||||||
textAlign: "right",
|
textAlign,
|
||||||
direction: "rtl",
|
direction: "rtl",
|
||||||
padding: "0",
|
padding: "0",
|
||||||
margin: "0",
|
margin: "0",
|
||||||
@@ -306,7 +315,7 @@ const TextShape = ({
|
|||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
ref={shapeRef}
|
ref={shapeRef}
|
||||||
x={0}
|
x={-(obj.width || 0)}
|
||||||
y={0}
|
y={0}
|
||||||
text={obj.text || ""}
|
text={obj.text || ""}
|
||||||
fontSize={obj.fontSize || 24}
|
fontSize={obj.fontSize || 24}
|
||||||
@@ -315,7 +324,8 @@ const TextShape = ({
|
|||||||
fontStyle={konvaFontStyle}
|
fontStyle={konvaFontStyle}
|
||||||
letterSpacing={obj.letterSpacing ?? 0}
|
letterSpacing={obj.letterSpacing ?? 0}
|
||||||
lineHeight={obj.lineHeight ?? 1.2}
|
lineHeight={obj.lineHeight ?? 1.2}
|
||||||
align="right"
|
width={obj.width || undefined}
|
||||||
|
align={textAlign}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export type EditorObject = {
|
|||||||
text?: string;
|
text?: string;
|
||||||
fontSize?: number;
|
fontSize?: number;
|
||||||
lineHeight?: number;
|
lineHeight?: number;
|
||||||
|
textAlign?: "left" | "center" | "right";
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
fontWeight?: string;
|
fontWeight?: string;
|
||||||
letterSpacing?: number;
|
letterSpacing?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user