@leviosa-ai/detail-page-editor 0.6.0 → 0.6.1

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.
@@ -23,10 +23,7 @@ import {
23
23
  import { CanvasStoreContext } from "./canvas-observer";
24
24
  import { LeviosaCanvasWorkspace } from "./leviosa-canvas-workspace";
25
25
  import { DetailPagePagesTimeline } from "./detail-page-pages-timeline";
26
- import {
27
- SidePanel as LeviosaSidePanel,
28
- ZoomButtons as LeviosaZoomButtons,
29
- } from "@leviosa-ai/canvas";
26
+ import { SidePanel as LeviosaSidePanel } from "@leviosa-ai/canvas";
30
27
  import { createCanvasStore } from "@leviosa-ai/canvas/store";
31
28
  import { collectFontRequests } from "@leviosa-ai/canvas/render/use-document-fonts";
32
29
  import { ensureCanvasKey } from "../../lib/detail-page-canvas/canvas-key";
@@ -709,10 +706,6 @@ export function DetailPageEditor({
709
706
  {findReplace}
710
707
  <DetailPagePagesTimeline store={store} />
711
708
  </LeviosaCanvasWorkspace>
712
- {/* 배율은 오른쪽 아래로 — 가운데 아래는 삽입 띠 자리다(작업 영역이 그린다). */}
713
- <div className="absolute bottom-4 right-4 z-20 rounded-dpe-lg border border-dpe-ink-200 bg-dpe-surface/95 px-2 py-1 shadow-sm backdrop-blur-sm">
714
- <LeviosaZoomButtons store={store} />
715
- </div>
716
709
  </div>
717
710
  </div>
718
711
  );
@@ -23,6 +23,19 @@ type StoreLike = {
23
23
  selectPage: (id: string) => void;
24
24
  };
25
25
 
26
+ /**
27
+ * 이 띠가 차지하는 높이와, 떠 있는지 여부.
28
+ *
29
+ * 아래 띠(삽입·배율)가 이 위로 비켜서야 하는데, 그 셈을 작업 영역이 따로 하면
30
+ * 두 벌이 갈라진다 — 여기가 정본이고 높이는 아래 style 로 자기가 쓴다.
31
+ */
32
+ export const PAGES_TIMELINE_HEIGHT = 53;
33
+
34
+ export function pagesTimelineVisible(store: unknown): boolean {
35
+ const pages = (store as StoreLike | null)?.pages;
36
+ return Array.isArray(pages) && pages.length >= 2;
37
+ }
38
+
26
39
  export const DetailPagePagesTimeline = observer(function DetailPagePagesTimeline({
27
40
  store,
28
41
  }: {
@@ -36,11 +49,12 @@ export const DetailPagePagesTimeline = observer(function DetailPagePagesTimeline
36
49
  );
37
50
  const activeId = s.activePage?.id;
38
51
 
39
- if (s.pages.length < 2) return null;
52
+ if (!pagesTimelineVisible(s)) return null;
40
53
 
41
54
  return (
42
55
  <div
43
56
  data-dp-pages-timeline=""
57
+ style={{ minHeight: PAGES_TIMELINE_HEIGHT }}
44
58
  className="pointer-events-auto absolute inset-x-0 bottom-0 z-20 flex items-center gap-1.5 overflow-x-auto border-t border-dpe-ink-200 bg-dpe-surface/95 px-3 py-1.5 backdrop-blur-sm"
45
59
  >
46
60
  {s.pages.map((page, index) => {
@@ -31,12 +31,17 @@ import { CanvasInsertToolbar } from "./canvas-insert-toolbar";
31
31
  import { CanvasOverlayHost } from "./canvas-overlay-host";
32
32
  import { CanvasSelectionTools } from "./canvas-selection-tools";
33
33
  import { DetailPagePageToolbar } from "./detail-page-page-toolbar";
34
+ import {
35
+ PAGES_TIMELINE_HEIGHT,
36
+ pagesTimelineVisible,
37
+ } from "./detail-page-pages-timeline";
34
38
  import { detailPageThumbnailBus } from "./detail-page-thumbnail-bus";
35
39
  import { GifAnimator } from "./gif-animator";
36
40
  import { GroupDrillIn } from "./group-drill-in";
37
41
  import { HoverHighlightOverlay } from "./hover-highlight-overlay";
38
42
  import { CanvasSectionHeightHandle } from "./section-height-handle";
39
43
  import { loadEditorFont } from "../../lib/detail-page-canvas/editor-fonts";
44
+ import { ZoomButtons } from "@leviosa-ai/canvas";
40
45
  import { CanvasView } from "@leviosa-ai/canvas/render/canvas-view";
41
46
  import { useCanvasVersion } from "@leviosa-ai/canvas/use-canvas";
42
47
  import type { CanvasStore } from "@leviosa-ai/canvas/store";
@@ -49,6 +54,9 @@ const clamp = (v: number, lo: number, hi: number) =>
49
54
  /** 썸네일 해상도. 페이지 패널의 칸이 작아 이 정도면 충분하다. */
50
55
  const THUMB_PIXEL_RATIO = 0.12;
51
56
 
57
+ /** 아래 띠가 가장자리·화면 목록에서 떨어지는 거리. */
58
+ const DOCK_GAP = 16;
59
+
52
60
  export function LeviosaCanvasWorkspace({
53
61
  store,
54
62
  gap = 4,
@@ -299,19 +307,37 @@ export function LeviosaCanvasWorkspace({
299
307
 
300
308
  {children}
301
309
 
302
- {/* 삽입 띠 — 글상자·기본 도형을 좌측 패널까지 가지 않고 넣는다. 화면 아래 가운데는
303
- 피그마·캔바가 모두 쓰는 자리라 손이 먼저 간다(배율은 오른쪽 아래로 비켰다). */}
310
+ {/* 아래 띠 한 줄 — 가운데는 삽입(글상자·기본 도형), 오른쪽 끝은 배율. 화면 아래
311
+ 가운데는 피그마·캔바가 모두 쓰는 자리라 손이 먼저 간다.
312
+
313
+ 화면 목록(가로 띠)이 떠 있으면 그 높이만큼 위로 비킨다 — 안 그러면 두 띠가
314
+ 겹쳐서 아래 것이 안 눌린다. 높이와 표시 규칙은 그 띠가 들고 있다. */}
304
315
  <div
305
- data-dp-insert-dock=""
316
+ data-dp-bottom-dock=""
306
317
  style={{
307
318
  position: "absolute",
308
- left: "50%",
309
- bottom: 16,
310
- transform: "translateX(-50%)",
319
+ left: 0,
320
+ right: 0,
321
+ bottom: pagesTimelineVisible(store)
322
+ ? PAGES_TIMELINE_HEIGHT + DOCK_GAP
323
+ : DOCK_GAP,
311
324
  zIndex: 30,
325
+ display: "flex",
326
+ alignItems: "center",
327
+ justifyContent: "center",
328
+ pointerEvents: "none",
312
329
  }}
313
330
  >
314
- <CanvasInsertToolbar store={store} />
331
+ <div data-dp-insert-dock="" style={{ pointerEvents: "auto" }}>
332
+ <CanvasInsertToolbar store={store} />
333
+ </div>
334
+ <div
335
+ data-dp-zoom-dock=""
336
+ style={{ position: "absolute", right: DOCK_GAP, pointerEvents: "auto" }}
337
+ className="rounded-dpe-lg border border-dpe-ink-200 bg-dpe-surface/95 px-2 py-1 shadow-sm backdrop-blur-sm"
338
+ >
339
+ <ZoomButtons store={store} />
340
+ </div>
315
341
  </div>
316
342
 
317
343
  {store.activePage ? (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leviosa-ai/detail-page-editor",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
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.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",