This commit is contained in:
Hamid
2026-05-16 23:06:23 -07:00
parent f51c7c302c
commit b3e0378af5
3 changed files with 221 additions and 18 deletions
+48 -10
View File
@@ -3,7 +3,13 @@ import { type PageData } from '../types';
import type { EditorObject } from '@/pages/editor/store/editorStore';
import { toCssLinearGradient } from '@/pages/editor/utils/gradient';
import { getFontFamily } from '@/pages/editor/utils/fontFamily';
import { getCssFontWeight, getScaledTextWidth, isSingleLineText } from '@/pages/editor/utils/textStyle';
import {
getCssFontWeight,
getEffectiveTextWidth,
getScaledTextWidth,
usesWrappedLayout,
SINGLE_LINE_WIDTH_SLACK_PX,
} from '@/pages/editor/utils/textStyle';
import '@/pages/viewer/styles/entranceAnimations.css';
import { mergeEntranceAnimationStyle } from '@/pages/viewer/utils/entranceAnimationStyle';
import { useBookPageEntranceSequence } from '@/pages/viewer/hooks/useBookPageEntranceSequence';
@@ -123,10 +129,35 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
case 'text': {
// برای text، opacity در رنگ اعمال می‌شود، پس باید opacity را از baseStyle حذف کنیم
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { opacity, ...textBaseStyle } = baseStyle;
const singleLine = isSingleLineText(obj.text);
const textWidth = getScaledTextWidth(obj.width, scale, singleLine);
const textLeft = Math.round(((obj.x || 0) - (obj.width || 0)) * scale);
const { opacity, transform: _baseTransform, ...textBaseStyle } = baseStyle;
const lineHeight = obj.lineHeight ?? 1.2;
const wrapped = usesWrappedLayout(obj.text, obj.height, obj.fontSize || 24, lineHeight);
const rotation = obj.rotation || 0;
const fontSize = obj.fontSize || 24;
const measureOpts = {
fontSize,
fontFamily: obj.fontFamily,
fontWeight: obj.fontWeight,
letterSpacing: obj.letterSpacing ?? 0,
lineHeight,
};
const layoutWidth = wrapped
? getEffectiveTextWidth(obj.width, obj.text, measureOpts, false)
: undefined;
const textWidth = wrapped ? getScaledTextWidth(layoutWidth, scale) : undefined;
// getScaledTextWidth adds SINGLE_LINE_WIDTH_SLACK_PX to prevent unwanted CSS wrapping.
// Compensate by shifting textLeft left by the same amount so the right edge stays at obj.x * scale.
const textSlackPx = textWidth !== undefined ? Math.ceil(SINGLE_LINE_WIDTH_SLACK_PX * scale) : 0;
const textLeft = wrapped
? Math.round(((obj.x || 0) - (layoutWidth || obj.width || 0)) * scale) - textSlackPx
: Math.round((obj.x || 0) * scale);
const textTransform = wrapped
? rotation
? `rotate(${rotation}deg)`
: undefined
: rotation
? `rotate(${rotation}deg) translateX(-100%)`
: 'translateX(-100%)';
return (
<div
key={obj.id || index}
@@ -134,20 +165,27 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
{
...textBaseStyle,
left: `${textLeft}px`,
width: textWidth ? `${textWidth}px` : undefined,
fontSize: `${(obj.fontSize || 16) * scale}px`,
width: wrapped ? (textWidth ? `${textWidth}px` : undefined) : 'max-content',
maxWidth: wrapped ? undefined : 'none',
fontSize: `${fontSize * scale}px`,
fontFamily: getFontFamily(obj.fontFamily),
fontWeight: getCssFontWeight(obj.fontWeight),
lineHeight: obj.lineHeight ?? 1.2,
lineHeight,
textAlign: obj.textAlign ?? 'right',
direction: 'rtl',
color: getColorWithOpacity(obj.fill, obj.opacity),
whiteSpace: singleLine ? 'nowrap' : 'pre-wrap',
whiteSpace: wrapped ? 'pre-wrap' : 'nowrap',
overflowWrap: wrapped ? 'break-word' : 'normal',
letterSpacing: obj.letterSpacing ? `${obj.letterSpacing * scale}px` : undefined,
boxSizing: 'content-box',
transform: textTransform,
transformOrigin: wrapped ? 'top left' : 'top right',
},
obj,
index,
wrapped
? { rotationDeg: rotation, transformOrigin: 'top left' }
: { rotationDeg: rotation, transformOrigin: 'top right' },
)}
>
{obj.text || ''}
@@ -212,7 +250,7 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(
width: obj.width ? `${obj.width * scale}px` : 'auto',
height: obj.height ? `${obj.height * scale}px` : 'auto',
color: obj.fill || '#3b82f6',
fontSize: `${(obj.fontSize || 16) * scale}px`,
fontSize: `${(obj.fontSize || 24) * scale}px`,
fontFamily: getFontFamily(obj.fontFamily),
fontWeight: getCssFontWeight(obj.fontWeight),
textDecoration: 'underline',