@leviosa-ai/detail-page-editor 0.17.0 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
detailPageEditorProfile,
|
|
40
40
|
type DetailPageEditorFormat,
|
|
41
41
|
} from "../../lib/detail-page/editor-profile";
|
|
42
|
-
import {
|
|
42
|
+
import { exceededCanvasLimit } from "../../lib/detail-page/canvas-limits";
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* hookable-style 다운로드 팝오버 — 다운로드 버튼 바로 아래에 떠서 **등록 플랫폼을
|
|
@@ -332,12 +332,13 @@ export const DetailPageDownloadDialog = observer(function DetailPageDownloadDial
|
|
|
332
332
|
const maxBytes = chosen?.maxBytes ?? null;
|
|
333
333
|
// 상세페이지는 세로로 길어서, 병합하면 아트보드 한계를 넘길 수 있다.
|
|
334
334
|
const aiOverflow = isPdfFormat(format) && single && totalHeight > AI_MAX_ARTBOARD;
|
|
335
|
-
// 병합 PNG/JPG 는 한 캔버스에 쌓는다.
|
|
336
|
-
//
|
|
337
|
-
const
|
|
338
|
-
isRasterFormat(format) &&
|
|
339
|
-
|
|
340
|
-
|
|
335
|
+
// 병합 PNG/JPG 는 한 캔버스에 쌓는다. 이 브라우저의 캔버스 한계를 넘으면 **빈 그림**이
|
|
336
|
+
// 나오므로 병합을 끄고 페이지별 ZIP 으로 내린다.
|
|
337
|
+
const mergeLimit =
|
|
338
|
+
isRasterFormat(format) && selectedPages.length > 1
|
|
339
|
+
? exceededCanvasLimit(outWidth, outHeight)
|
|
340
|
+
: null;
|
|
341
|
+
const mergeTooLarge = mergeLimit !== null;
|
|
341
342
|
const merge = single && !mergeTooLarge;
|
|
342
343
|
|
|
343
344
|
// 내려받기가 끝난 뒤. 말할 것이 없으면 창을 닫고, 있으면 열어 둔 채 알린다 —
|
|
@@ -638,7 +639,7 @@ export const DetailPageDownloadDialog = observer(function DetailPageDownloadDial
|
|
|
638
639
|
{mergeTooLarge ? (
|
|
639
640
|
<p className="text-[10px] leading-relaxed text-le-warn-700">
|
|
640
641
|
{t("editor.mergeTooLargeHint", {
|
|
641
|
-
limit:
|
|
642
|
+
limit: mergeLimit?.toLocaleString(),
|
|
642
643
|
})}
|
|
643
644
|
</p>
|
|
644
645
|
) : null}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright © 2026 주식회사레비오사에이아이. All rights reserved. See LICENSE.
|
|
2
|
+
/**
|
|
3
|
+
* 지금 브라우저가 한 캔버스에 그릴 수 있는 크기. 넘기면 예외 없이 **빈 그림**이 나온다.
|
|
4
|
+
*
|
|
5
|
+
* 병합 PNG/JPG 는 모든 페이지를 한 캔버스에 쌓으므로 이 한계를 넘으면 페이지별로
|
|
6
|
+
* 내려야 한다. 한계는 브라우저마다 크게 다르다 — iOS 기준(1,670만 px)을 데스크톱에
|
|
7
|
+
* 걸면 860×19,000 남짓한 상세페이지부터 전부 쪼개진다.
|
|
8
|
+
*
|
|
9
|
+
* - iOS·iPadOS(모든 브라우저가 WebKit): 넓이 16,777,216
|
|
10
|
+
* - Firefox: 한 변 32,767, 넓이 268,435,456
|
|
11
|
+
* - 그 외(Chrome·Edge·데스크톱 Safari): 한 변 65,535, 넓이 268,435,456
|
|
12
|
+
*
|
|
13
|
+
* 수치는 jhildenbiddle/canvas-size 의 실측표를 따른다.
|
|
14
|
+
*/
|
|
15
|
+
export interface CanvasLimits {
|
|
16
|
+
/** 한 변의 최대 픽셀. */
|
|
17
|
+
side: number;
|
|
18
|
+
/** 넓이(가로×세로)의 최대 픽셀. */
|
|
19
|
+
area: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function canvasLimits(
|
|
23
|
+
userAgent = typeof navigator === "undefined" ? "" : navigator.userAgent,
|
|
24
|
+
maxTouchPoints = typeof navigator === "undefined" ? 0 : navigator.maxTouchPoints,
|
|
25
|
+
): CanvasLimits {
|
|
26
|
+
// iPadOS 는 데스크톱 Safari 로 자신을 소개한다 — 터치 지점으로 가린다.
|
|
27
|
+
const ios =
|
|
28
|
+
/iPad|iPhone|iPod/.test(userAgent) || (/Macintosh/.test(userAgent) && maxTouchPoints > 1);
|
|
29
|
+
if (ios) return { side: 16_777_216, area: 16_777_216 };
|
|
30
|
+
if (/Firefox\//.test(userAgent)) return { side: 32_767, area: 268_435_456 };
|
|
31
|
+
return { side: 65_535, area: 268_435_456 };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** 이 크기의 캔버스를 그릴 수 없으면 넘긴 한계(px)를, 그릴 수 있으면 null 을 준다. */
|
|
35
|
+
export function exceededCanvasLimit(
|
|
36
|
+
width: number,
|
|
37
|
+
height: number,
|
|
38
|
+
limits: CanvasLimits = canvasLimits(),
|
|
39
|
+
): number | null {
|
|
40
|
+
if (Math.max(width, height) > limits.side) return limits.side;
|
|
41
|
+
if (width * height > limits.area) return limits.area;
|
|
42
|
+
return null;
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leviosa-ai/detail-page-editor",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.2",
|
|
4
4
|
"description": "Leviosa detail-page editor shell. Source-only: consumers compile it through Next transpilePackages. Every app coupling (sourcing server, brand store, cache keys, toast) arrives through the DetailPageHost interface, and every URL it fetches comes from configureDetailPageEditor.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"woff2-encoder": "2.0.0"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@leviosa-ai/canvas": "0.9.
|
|
71
|
+
"@leviosa-ai/canvas": "0.9.1",
|
|
72
72
|
"@tanstack/react-query": "^5.100.3",
|
|
73
73
|
"konva": "^10.0.0",
|
|
74
74
|
"lucide-react": "^0.563.0 || ^1.0.0",
|