link to another pager

This commit is contained in:
hamid zarghami
2026-01-07 15:02:44 +03:30
parent 9e1dd09097
commit 7a2bdfba56
3 changed files with 312 additions and 57 deletions
+86 -24
View File
@@ -5,6 +5,7 @@ import type { EditorObject } from '@/pages/editor/store/editorStore';
type BookPageProps = {
page: PageData;
scale?: number;
onLinkClick?: (linkUrl: string) => void;
};
/**
@@ -14,7 +15,7 @@ type BookPageProps = {
* این کامپوننت به عنوان child برای HTMLFlipBook استفاده می‌شود
* نیاز به forwardRef دارد تا react-pageflip بتواند ref را مدیریت کند
*/
const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 }, ref) => {
const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1, onLinkClick }, ref) => {
// تابع برای تبدیل opacity به رنگ (مثل editor)
// در editor، getColorWithOpacity انتظار opacity 0-100 دارد
// در dataTransformer، opacity از 0-1 به 0-100 تبدیل شده است
@@ -108,33 +109,94 @@ const BookPage = forwardRef<HTMLDivElement, BookPageProps>(({ page, scale = 1 },
width: obj.width ? `${obj.width * scale}px` : 'auto',
height: obj.height ? `${obj.height * scale}px` : 'auto',
objectFit: 'contain',
zIndex: index,
pointerEvents: 'auto',
}}
onClick={(e) => {
e.stopPropagation();
}}
onMouseDown={(e) => {
e.stopPropagation();
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
/>
);
case 'link':
return (
<a
key={obj.id || index}
href={obj.linkUrl || '#'}
target="_blank"
rel="noopener noreferrer"
style={{
...baseStyle,
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`,
fontFamily: obj.fontFamily || 'irancell, sans-serif',
textDecoration: 'underline',
display: 'flex',
alignItems: 'center',
whiteSpace: 'pre-wrap',
}}
>
{obj.text || obj.linkUrl || ''}
</a>
);
case 'link': {
const isInternalLink = obj.linkUrl?.startsWith('page://');
const linkStyle = {
...baseStyle,
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`,
fontFamily: obj.fontFamily || 'irancell, sans-serif',
textDecoration: 'underline',
display: 'flex',
alignItems: 'center',
whiteSpace: 'pre-wrap' as const,
cursor: 'pointer',
};
if (isInternalLink) {
// لینک داخلی - از button با onClick استفاده می‌کنیم
return (
<button
key={obj.id || index}
type="button"
style={{
...linkStyle,
zIndex: 9999,
pointerEvents: 'auto',
border: 'none',
background: 'none',
padding: 0,
cursor: 'pointer',
}}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
if (obj.linkUrl && onLinkClick) {
onLinkClick(obj.linkUrl);
}
}}
onMouseDown={(e) => {
e.stopPropagation();
}}
onTouchStart={(e) => {
e.stopPropagation();
}}
>
{obj.text || obj.linkUrl || ''}
</button>
);
} else {
// لینک خارجی - از <a> با target="_blank" استفاده می‌کنیم
return (
<a
key={obj.id || index}
href={obj.linkUrl || '#'}
target="_blank"
rel="noopener noreferrer"
style={{
...linkStyle,
zIndex: 9999,
pointerEvents: 'auto',
}}
onClick={(e) => {
e.stopPropagation();
}}
onMouseDown={(e) => {
e.stopPropagation();
}}
>
{obj.text || obj.linkUrl || ''}
</a>
);
}
}
case 'rectangle': {
if (obj.shapeType === 'circle') {