@growgroup/visual-editor 0.1.2 → 0.1.4
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.
- package/dist/editor.css +1 -1
- package/package.json +2 -1
- package/src/editor/FrontendVisualEditor.tsx +28 -2
- package/src/editor/components/EditorHeader.tsx +5 -0
- package/src/editor/components/EditorLayerPanel.tsx +27 -10
- package/src/editor/components/comments/CommentBoard.tsx +499 -0
- package/src/editor/components/comments/CommentBoardPanel.tsx +133 -0
- package/src/editor/components/ppt/PptComments.tsx +9 -4
- package/src/editor/components/shell/LeftPanel.tsx +72 -8
- package/src/index.ts +15 -0
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Figma風UI
|
|
4
|
+
* Figma風UIの左パネル。
|
|
5
|
+
*
|
|
6
|
+
* 既定は2段構成:
|
|
5
7
|
* 上: ページ切替(PagesPanel。スライドのプレビュー付き)
|
|
6
8
|
* 下: 現在ページのレイヤーツリー(EditorLayerPanel hideSlideList)
|
|
7
9
|
*
|
|
10
|
+
* `pagesSlot` を渡すと、その中身と レイヤーツリー をタブで出し分ける。
|
|
11
|
+
* ページ一覧を利用側が持つ場合(Webページ・ページ数が固定のサイト等)に、
|
|
12
|
+
* 左端へ独自パネルをもう1枚並べずに済ませるための口。左に2枚パネルが並ぶと
|
|
13
|
+
* 「左=1枚 / 中央=キャンバス / 右=プロパティ」というFigmaの骨格が崩れる。
|
|
14
|
+
*
|
|
8
15
|
* 幅はこのラッパーが1本のハンドルで持つ。段ごとに幅・ハンドルを持たせると
|
|
9
16
|
* 上下で幅が食い違ったり、リサイズが二重になったりするため。
|
|
10
17
|
*/
|
|
11
18
|
|
|
19
|
+
import { useState, type ReactNode } from 'react';
|
|
12
20
|
import { useEditorContext } from '../../EditorContext';
|
|
13
21
|
import { useResizablePanel } from '../../hooks/useResizablePanel';
|
|
14
22
|
import { EditorLayerPanel } from '../EditorLayerPanel';
|
|
15
23
|
import { PagesPanel } from './PagesPanel';
|
|
16
24
|
import { can } from '../../../io';
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
type LeftTab = 'pages' | 'layers';
|
|
27
|
+
|
|
28
|
+
export function LeftPanel({ page, pagesSlot }: { page: number; pagesSlot?: ReactNode }) {
|
|
19
29
|
// 一覧のサムネイルは利用側が描く(io.renderContent)。描けないなら段ごと出さない。
|
|
20
30
|
// Webページの用途ではページ切替を利用側のUIが持つことが多い
|
|
21
31
|
const { editorMode } = useEditorContext();
|
|
@@ -28,16 +38,70 @@ export function LeftPanel({ page }: { page: number }) {
|
|
|
28
38
|
storageKey: 'gg-editor:left-panel-width',
|
|
29
39
|
});
|
|
30
40
|
|
|
41
|
+
/**
|
|
42
|
+
* 既定は「ページ」。レイヤーは要素を触りはじめてから使うもので、
|
|
43
|
+
* 開いた直後に知りたいのは「どのページを見ているか」のため
|
|
44
|
+
*/
|
|
45
|
+
const [tab, setTab] = useState<LeftTab>('pages');
|
|
46
|
+
|
|
31
47
|
return (
|
|
32
48
|
<div
|
|
33
|
-
className="relative flex shrink-0 flex-col overflow-hidden"
|
|
49
|
+
className="relative flex shrink-0 flex-col overflow-hidden border-r border-[#444444] bg-[#2c2c2c]"
|
|
34
50
|
style={{ width: `${width}px` }}
|
|
35
51
|
>
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
52
|
+
{pagesSlot ? (
|
|
53
|
+
<>
|
|
54
|
+
<div
|
|
55
|
+
role="tablist"
|
|
56
|
+
aria-label="左パネル"
|
|
57
|
+
className="flex shrink-0 items-stretch gap-1 border-b border-[#444444] px-1"
|
|
58
|
+
>
|
|
59
|
+
{([
|
|
60
|
+
['pages', 'ページ'],
|
|
61
|
+
['layers', 'レイヤー'],
|
|
62
|
+
] as const).map(([key, label]) => {
|
|
63
|
+
const active = tab === key;
|
|
64
|
+
return (
|
|
65
|
+
<button
|
|
66
|
+
key={key}
|
|
67
|
+
type="button"
|
|
68
|
+
role="tab"
|
|
69
|
+
aria-selected={active}
|
|
70
|
+
data-left-tab={key}
|
|
71
|
+
onClick={() => setTab(key)}
|
|
72
|
+
className={`relative flex-1 px-2 py-2 text-[11px] font-medium transition-colors ${
|
|
73
|
+
active ? 'text-white' : 'text-gray-400 hover:text-gray-200'
|
|
74
|
+
}`}
|
|
75
|
+
>
|
|
76
|
+
{label}
|
|
77
|
+
{active && (
|
|
78
|
+
<span className="absolute inset-x-2 bottom-0 h-0.5 rounded-full bg-[#0d99ff]" />
|
|
79
|
+
)}
|
|
80
|
+
</button>
|
|
81
|
+
);
|
|
82
|
+
})}
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
{/*
|
|
86
|
+
両方をマウントしたまま出し分ける。片方を外すと、戻ったときに
|
|
87
|
+
スクロール位置・検索語・展開状態が毎回初期化される
|
|
88
|
+
*/}
|
|
89
|
+
<div className={`min-h-0 flex-1 flex-col ${tab === 'pages' ? 'flex' : 'hidden'}`}>
|
|
90
|
+
{pagesSlot}
|
|
91
|
+
</div>
|
|
92
|
+
<div className={`min-h-0 flex-1 ${tab === 'layers' ? 'flex' : 'hidden'}`}>
|
|
93
|
+
<EditorLayerPanel hideSlideList />
|
|
94
|
+
</div>
|
|
95
|
+
</>
|
|
96
|
+
) : (
|
|
97
|
+
<>
|
|
98
|
+
{showPages && <PagesPanel page={page} />}
|
|
99
|
+
{/* 残りの高さいっぱいにレイヤーツリー(自前でスクロールする) */}
|
|
100
|
+
<div className="flex min-h-0 flex-1">
|
|
101
|
+
<EditorLayerPanel hideSlideList />
|
|
102
|
+
</div>
|
|
103
|
+
</>
|
|
104
|
+
)}
|
|
41
105
|
|
|
42
106
|
{/* リサイズハンドル(全高。上下どちらの段からでも掴める) */}
|
|
43
107
|
<div {...resizeHandleProps} />
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,21 @@ export { WEBPAGE_WIDTH, WEBPAGE_MIN_HEIGHT, SLIDE_WIDTH, SLIDE_HEIGHT, BREAKPOIN
|
|
|
27
27
|
|
|
28
28
|
export { registerAutoSaveFlush, flushAutoSave } from "./editor/autosave";
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* コメントの一覧(カンバン)。エディタとは別の画面に単独で置ける。
|
|
32
|
+
*
|
|
33
|
+
* - CommentBoardPanel … 配線済み。setEditorIO さえ渡してあれば props なしで動く
|
|
34
|
+
* - CommentBoard … 純UI。デッキも操作も自分で用意したい場合はこちら
|
|
35
|
+
*/
|
|
36
|
+
export { CommentBoardPanel } from "./editor/components/comments/CommentBoardPanel";
|
|
37
|
+
export type { CommentBoardPanelProps } from "./editor/components/comments/CommentBoardPanel";
|
|
38
|
+
export { CommentBoard } from "./editor/components/comments/CommentBoard";
|
|
39
|
+
export type { CommentBoardProps } from "./editor/components/comments/CommentBoard";
|
|
40
|
+
|
|
41
|
+
/** 配色。CommentBoard の theme に渡す(initialPptTheme はOS設定に追従する) */
|
|
42
|
+
export { initialPptTheme } from "./editor/components/ppt/PptChrome";
|
|
43
|
+
export type { PptTheme } from "./editor/components/ppt/PptChrome";
|
|
44
|
+
|
|
30
45
|
/** 置き場との境界。利用側が起動時に1回渡す */
|
|
31
46
|
export { setEditorIO, io, can } from "./io";
|
|
32
47
|
export type {
|