@alpaca-editor/core 1.0.3962 → 1.0.3963
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/config/config.js +8 -8
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +2 -1
- package/dist/editor/ContentTree.js +3 -2
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/FieldListField.js +13 -4
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/ImageEditButton.js +1 -1
- package/dist/editor/ImageEditButton.js.map +1 -1
- package/dist/editor/MainLayout.js +2 -1
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/menubar/GenericToolbar.d.ts +11 -0
- package/dist/editor/menubar/GenericToolbar.js +10 -0
- package/dist/editor/menubar/GenericToolbar.js.map +1 -0
- package/dist/editor/menubar/ItemToolbar.d.ts +1 -0
- package/dist/editor/menubar/ItemToolbar.js +11 -0
- package/dist/editor/menubar/ItemToolbar.js.map +1 -0
- package/dist/editor/menubar/PageToolbar.d.ts +1 -0
- package/dist/editor/menubar/PageToolbar.js +33 -0
- package/dist/editor/menubar/PageToolbar.js.map +1 -0
- package/dist/editor/menubar/PageViewerControls.js +2 -28
- package/dist/editor/menubar/PageViewerControls.js.map +1 -1
- package/dist/editor/menubar/ToolbarFactory.d.ts +2 -0
- package/dist/editor/menubar/ToolbarFactory.js +52 -0
- package/dist/editor/menubar/ToolbarFactory.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/CompareControls.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/CompareControls.js +11 -0
- package/dist/editor/menubar/toolbar-sections/CompareControls.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/EditControls.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/EditControls.js +16 -0
- package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/InsertControls.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/InsertControls.js +15 -0
- package/dist/editor/menubar/toolbar-sections/InsertControls.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/ReviewCommands.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/ReviewCommands.js +40 -0
- package/dist/editor/menubar/toolbar-sections/ReviewCommands.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/UtilityControls.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js +13 -0
- package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/ViewportControls.d.ts +1 -0
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js +20 -0
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -0
- package/dist/editor/menubar/toolbar-sections/index.d.ts +6 -0
- package/dist/editor/menubar/toolbar-sections/index.js +7 -0
- package/dist/editor/menubar/toolbar-sections/index.js.map +1 -0
- package/dist/editor/sidebar/ComponentPalette.js +1 -1
- package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
- package/dist/editor/sidebar/ComponentTree.js +1 -1
- package/dist/editor/sidebar/SidebarView.js +2 -2
- package/dist/editor/sidebar/SidebarView.js.map +1 -1
- package/dist/editor/sidebar/Translations.js +8 -6
- package/dist/editor/sidebar/Translations.js.map +1 -1
- package/dist/editor/ui/Icons.js +2 -2
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/Section.js +1 -1
- package/dist/editor/ui/Section.js.map +1 -1
- package/dist/editor/views/CompareView.js +2 -2
- package/dist/editor/views/CompareView.js.map +1 -1
- package/dist/editor/views/ItemEditor.js +1 -1
- package/dist/editor/views/ItemEditor.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/RecentPages.js +1 -1
- package/dist/splash-screen/RecentPages.js.map +1 -1
- package/dist/styles.css +20 -19
- package/package.json +1 -1
- package/src/config/config.tsx +10 -10
- package/src/config/types.ts +3 -1
- package/src/editor/ContentTree.tsx +10 -4
- package/src/editor/FieldListField.tsx +31 -3
- package/src/editor/ImageEditButton.tsx +1 -1
- package/src/editor/MainLayout.tsx +2 -1
- package/src/editor/menubar/GenericToolbar.tsx +43 -0
- package/src/editor/menubar/ItemToolbar.tsx +24 -0
- package/src/editor/menubar/PageToolbar.tsx +154 -0
- package/src/editor/menubar/PageViewerControls.tsx +2 -160
- package/src/editor/menubar/ToolbarFactory.tsx +68 -0
- package/src/editor/menubar/toolbar-sections/CompareControls.tsx +22 -0
- package/src/editor/menubar/toolbar-sections/EditControls.tsx +54 -0
- package/src/editor/menubar/toolbar-sections/InsertControls.tsx +28 -0
- package/src/editor/menubar/toolbar-sections/ReviewCommands.tsx +59 -0
- package/src/editor/menubar/toolbar-sections/UtilityControls.tsx +33 -0
- package/src/editor/menubar/toolbar-sections/ViewportControls.tsx +58 -0
- package/src/editor/menubar/toolbar-sections/index.ts +6 -0
- package/src/editor/sidebar/ComponentPalette.tsx +1 -1
- package/src/editor/sidebar/ComponentTree.tsx +1 -1
- package/src/editor/sidebar/SidebarView.tsx +4 -2
- package/src/editor/sidebar/Translations.tsx +17 -15
- package/src/editor/ui/Icons.tsx +4 -4
- package/src/editor/ui/Section.tsx +1 -1
- package/src/editor/views/CompareView.tsx +2 -2
- package/src/editor/views/ItemEditor.tsx +1 -1
- package/src/revision.ts +2 -2
- package/src/splash-screen/RecentPages.tsx +1 -1
- package/styles.css +1 -0
- package/dist/editor/menubar/Menu.d.ts +0 -1
- package/dist/editor/menubar/Menu.js +0 -63
- package/dist/editor/menubar/Menu.js.map +0 -1
- package/src/editor/menubar/Menu.tsx +0 -83
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { useEditContext } from "../client/editContext";
|
|
2
|
+
import { Separator } from "./Separator";
|
|
3
|
+
import { CompareIcon } from "../ui/Icons";
|
|
4
|
+
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
5
|
+
import {
|
|
6
|
+
EyeIcon,
|
|
7
|
+
MessagesSquare,
|
|
8
|
+
Pencil,
|
|
9
|
+
Monitor,
|
|
10
|
+
Smartphone,
|
|
11
|
+
Table,
|
|
12
|
+
Plus,
|
|
13
|
+
Layers,
|
|
14
|
+
} from "lucide-react";
|
|
15
|
+
import { EnterFullScreenIcon } from "@radix-ui/react-icons";
|
|
16
|
+
|
|
17
|
+
export function PageToolbar() {
|
|
18
|
+
const editContext = useEditContext();
|
|
19
|
+
|
|
20
|
+
if (!editContext) return null;
|
|
21
|
+
|
|
22
|
+
const pageViewContext = editContext.pageView;
|
|
23
|
+
|
|
24
|
+
const device = pageViewContext.device;
|
|
25
|
+
const setDevice = pageViewContext.setDevice;
|
|
26
|
+
|
|
27
|
+
// Insert mode logic
|
|
28
|
+
const insertMode = editContext.insertMode;
|
|
29
|
+
|
|
30
|
+
const toggleInsertMode = () => {
|
|
31
|
+
editContext.setInsertMode(true);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Calculate total count of comments and suggestions
|
|
35
|
+
const commentsCount =
|
|
36
|
+
editContext.comments?.filter((x) => !x.isResolved).length || 0;
|
|
37
|
+
const suggestionsCount =
|
|
38
|
+
editContext.suggestedEdits?.filter((x) => x.status === "pending").length ||
|
|
39
|
+
0;
|
|
40
|
+
const totalCount = commentsCount + suggestionsCount;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="flex items-center justify-between gap-2 border-b px-4 py-2">
|
|
44
|
+
<div className="flex items-center gap-2">
|
|
45
|
+
{!editContext.user?.isLimitedPreviewUser && (
|
|
46
|
+
<SimpleIconButton
|
|
47
|
+
icon={<Pencil className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
48
|
+
label="Edit"
|
|
49
|
+
size="large"
|
|
50
|
+
selected={editContext.mode === "edit"}
|
|
51
|
+
onClick={() => editContext.setMode("edit")}
|
|
52
|
+
/>
|
|
53
|
+
)}
|
|
54
|
+
|
|
55
|
+
<SimpleIconButton
|
|
56
|
+
icon={<EyeIcon className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
57
|
+
label="Preview"
|
|
58
|
+
size="large"
|
|
59
|
+
selected={editContext.mode === "preview"}
|
|
60
|
+
onClick={() => editContext.setMode("preview")}
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<div className="relative">
|
|
64
|
+
<SimpleIconButton
|
|
65
|
+
selected={editContext?.mode === "suggestions"}
|
|
66
|
+
icon={<MessagesSquare strokeWidth={1} className="h-6 w-6 p-1" />}
|
|
67
|
+
label="Write suggestions"
|
|
68
|
+
size="large"
|
|
69
|
+
onClick={() => editContext?.setMode("suggestions")}
|
|
70
|
+
/>
|
|
71
|
+
{totalCount > 0 && (
|
|
72
|
+
<div className="bg-theme-secondary text-3xs absolute -top-1 -right-1 flex h-[16px] min-w-[16px] items-center justify-center rounded-full px-1 text-white">
|
|
73
|
+
{totalCount > 99 ? "99+" : totalCount}
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
<Separator size="large" />
|
|
78
|
+
<SimpleIconButton
|
|
79
|
+
icon={<Plus className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
80
|
+
label="Add Component"
|
|
81
|
+
size="large"
|
|
82
|
+
selected={insertMode}
|
|
83
|
+
onClick={toggleInsertMode}
|
|
84
|
+
disabled={
|
|
85
|
+
!editContext.page?.item.canWriteItem || editContext.mode !== "edit"
|
|
86
|
+
}
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
{!editContext.isMobile && (
|
|
90
|
+
<div className="flex items-center gap-2">
|
|
91
|
+
<SimpleIconButton
|
|
92
|
+
icon={<Monitor className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
93
|
+
label="Desktop"
|
|
94
|
+
size="large"
|
|
95
|
+
selected={device === "desktop"}
|
|
96
|
+
onClick={() => setDevice("desktop")}
|
|
97
|
+
/>
|
|
98
|
+
<SimpleIconButton
|
|
99
|
+
icon={<Smartphone className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
100
|
+
label="Mobile"
|
|
101
|
+
size="large"
|
|
102
|
+
selected={Boolean(device && device !== "desktop")}
|
|
103
|
+
onClick={() => {
|
|
104
|
+
if (editContext.configuration.devices[0]) {
|
|
105
|
+
setDevice(editContext.configuration.devices[0].name);
|
|
106
|
+
}
|
|
107
|
+
}}
|
|
108
|
+
/>
|
|
109
|
+
<SimpleIconButton
|
|
110
|
+
icon={<Table className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
111
|
+
label="Form"
|
|
112
|
+
size="large"
|
|
113
|
+
selected={!device}
|
|
114
|
+
onClick={() => setDevice("")}
|
|
115
|
+
/>
|
|
116
|
+
<Separator size="large" />
|
|
117
|
+
{!editContext.isMobile && (
|
|
118
|
+
<SimpleIconButton
|
|
119
|
+
icon={<CompareIcon className="h-6 w-6 p-1" />}
|
|
120
|
+
label="Compare"
|
|
121
|
+
size="large"
|
|
122
|
+
className={
|
|
123
|
+
editContext.compareMode
|
|
124
|
+
? "text-gray-600"
|
|
125
|
+
: "hover:text-gray-600"
|
|
126
|
+
}
|
|
127
|
+
selected={editContext.compareMode}
|
|
128
|
+
onClick={() =>
|
|
129
|
+
editContext.setCompareMode(!editContext.compareMode)
|
|
130
|
+
}
|
|
131
|
+
/>
|
|
132
|
+
)}
|
|
133
|
+
</div>
|
|
134
|
+
)}
|
|
135
|
+
<div className="flex items-center gap-2">
|
|
136
|
+
<SimpleIconButton
|
|
137
|
+
icon={<EnterFullScreenIcon className="h-6 w-6 p-1" />}
|
|
138
|
+
label="Fullscreen"
|
|
139
|
+
size="large"
|
|
140
|
+
onClick={() => pageViewContext.setFullscreen(true)}
|
|
141
|
+
/>
|
|
142
|
+
<SimpleIconButton
|
|
143
|
+
icon={<Layers className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
144
|
+
label="Component Navigator"
|
|
145
|
+
size="large"
|
|
146
|
+
selected={editContext.showRightSidebar}
|
|
147
|
+
onClick={() =>
|
|
148
|
+
editContext.setShowRightSidebar(!editContext.showRightSidebar)
|
|
149
|
+
}
|
|
150
|
+
/>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
@@ -1,168 +1,10 @@
|
|
|
1
1
|
import { useEditContext } from "../client/editContext";
|
|
2
|
-
import {
|
|
3
|
-
import { CompareIcon, FormEditIcon } from "../ui/Icons";
|
|
4
|
-
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
5
|
-
import {
|
|
6
|
-
EyeIcon,
|
|
7
|
-
MessagesSquare,
|
|
8
|
-
Pencil,
|
|
9
|
-
Monitor,
|
|
10
|
-
Smartphone,
|
|
11
|
-
Table,
|
|
12
|
-
Plus,
|
|
13
|
-
Layers,
|
|
14
|
-
} from "lucide-react";
|
|
15
|
-
import { EnterFullScreenIcon } from "@radix-ui/react-icons";
|
|
2
|
+
import { createEditToolbar } from "./ToolbarFactory";
|
|
16
3
|
|
|
17
4
|
export function PageViewerControls() {
|
|
18
5
|
const editContext = useEditContext();
|
|
19
6
|
|
|
20
7
|
if (!editContext) return null;
|
|
21
8
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const pageViewContext = editContext.pageView;
|
|
25
|
-
|
|
26
|
-
const device = pageViewContext.device;
|
|
27
|
-
const setDevice = pageViewContext.setDevice;
|
|
28
|
-
|
|
29
|
-
// Insert mode logic
|
|
30
|
-
const insertMode = editContext.insertMode;
|
|
31
|
-
|
|
32
|
-
const toggleInsertMode = () => {
|
|
33
|
-
editContext.setInsertMode(true);
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Calculate total count of comments and suggestions
|
|
37
|
-
const commentsCount =
|
|
38
|
-
editContext.comments?.filter((x) => !x.isResolved).length || 0;
|
|
39
|
-
const suggestionsCount =
|
|
40
|
-
editContext.suggestedEdits?.filter((x) => x.status === "pending").length ||
|
|
41
|
-
0;
|
|
42
|
-
const totalCount = commentsCount + suggestionsCount;
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<div className="flex items-center justify-between gap-2 border-b px-4 py-2">
|
|
46
|
-
{hasLayout && (
|
|
47
|
-
<>
|
|
48
|
-
<div className="flex items-center gap-2">
|
|
49
|
-
{!editContext.user?.isLimitedPreviewUser && (
|
|
50
|
-
<SimpleIconButton
|
|
51
|
-
icon={<Pencil className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
52
|
-
label="Edit"
|
|
53
|
-
size="large"
|
|
54
|
-
selected={editContext.mode === "edit"}
|
|
55
|
-
onClick={() => editContext.setMode("edit")}
|
|
56
|
-
/>
|
|
57
|
-
)}
|
|
58
|
-
|
|
59
|
-
<SimpleIconButton
|
|
60
|
-
icon={<EyeIcon className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
61
|
-
label="Preview"
|
|
62
|
-
size="large"
|
|
63
|
-
selected={editContext.mode === "preview"}
|
|
64
|
-
onClick={() => editContext.setMode("preview")}
|
|
65
|
-
/>
|
|
66
|
-
|
|
67
|
-
<div className="relative">
|
|
68
|
-
<SimpleIconButton
|
|
69
|
-
selected={editContext?.mode === "suggestions"}
|
|
70
|
-
icon={
|
|
71
|
-
<MessagesSquare strokeWidth={1} className="h-6 w-6 p-1" />
|
|
72
|
-
}
|
|
73
|
-
label="Write suggestions"
|
|
74
|
-
size="large"
|
|
75
|
-
onClick={() => editContext?.setMode("suggestions")}
|
|
76
|
-
/>
|
|
77
|
-
{totalCount > 0 && (
|
|
78
|
-
<div className="bg-theme-secondary text-3xs absolute -top-1 -right-1 flex h-[16px] min-w-[16px] items-center justify-center rounded-full px-1 text-white">
|
|
79
|
-
{totalCount > 99 ? "99+" : totalCount}
|
|
80
|
-
</div>
|
|
81
|
-
)}
|
|
82
|
-
</div>
|
|
83
|
-
<Separator size="large" />
|
|
84
|
-
<SimpleIconButton
|
|
85
|
-
icon={<Plus className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
86
|
-
label="Add Component"
|
|
87
|
-
size="large"
|
|
88
|
-
selected={insertMode}
|
|
89
|
-
onClick={toggleInsertMode}
|
|
90
|
-
disabled={
|
|
91
|
-
!editContext.page?.item.canWriteItem ||
|
|
92
|
-
editContext.mode !== "edit"
|
|
93
|
-
}
|
|
94
|
-
/>
|
|
95
|
-
</div>
|
|
96
|
-
{!editContext.isMobile && (
|
|
97
|
-
<div className="flex items-center gap-2">
|
|
98
|
-
<SimpleIconButton
|
|
99
|
-
icon={<Monitor className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
100
|
-
label="Desktop"
|
|
101
|
-
size="large"
|
|
102
|
-
selected={device === "desktop"}
|
|
103
|
-
onClick={() => setDevice("desktop")}
|
|
104
|
-
/>
|
|
105
|
-
<SimpleIconButton
|
|
106
|
-
icon={<Smartphone className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
107
|
-
label="Mobile"
|
|
108
|
-
size="large"
|
|
109
|
-
selected={Boolean(device && device !== "desktop")}
|
|
110
|
-
onClick={() => {
|
|
111
|
-
if (editContext.configuration.devices[0]) {
|
|
112
|
-
setDevice(editContext.configuration.devices[0].name);
|
|
113
|
-
}
|
|
114
|
-
}}
|
|
115
|
-
/>
|
|
116
|
-
<SimpleIconButton
|
|
117
|
-
icon={<Table className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
118
|
-
label="Form"
|
|
119
|
-
size="large"
|
|
120
|
-
selected={!device}
|
|
121
|
-
onClick={() => setDevice("")}
|
|
122
|
-
/>
|
|
123
|
-
<Separator size="large" />
|
|
124
|
-
{!editContext.isMobile && (
|
|
125
|
-
<SimpleIconButton
|
|
126
|
-
icon={<CompareIcon className="h-6 w-6 p-1" />}
|
|
127
|
-
label="Compare"
|
|
128
|
-
size="large"
|
|
129
|
-
className={
|
|
130
|
-
editContext.compareMode
|
|
131
|
-
? "text-gray-600"
|
|
132
|
-
: "hover:text-gray-600"
|
|
133
|
-
}
|
|
134
|
-
selected={editContext.compareMode}
|
|
135
|
-
onClick={() =>
|
|
136
|
-
editContext.setCompareMode(!editContext.compareMode)
|
|
137
|
-
}
|
|
138
|
-
/>
|
|
139
|
-
)}
|
|
140
|
-
</div>
|
|
141
|
-
)}
|
|
142
|
-
{/* <i
|
|
143
|
-
className="pi pi-external-link cursor-pointer rounded-full p-2 text-gray-400 hover:bg-gray-200 hover:text-gray-800"
|
|
144
|
-
title="Fullscreen"
|
|
145
|
-
onClick={() => pageViewContext.setFullscreen(true)}
|
|
146
|
-
/> */}
|
|
147
|
-
<div className="flex items-center gap-2">
|
|
148
|
-
<SimpleIconButton
|
|
149
|
-
icon={<EnterFullScreenIcon className="h-6 w-6 p-1" />}
|
|
150
|
-
label="Fullscreen"
|
|
151
|
-
size="large"
|
|
152
|
-
onClick={() => pageViewContext.setFullscreen(true)}
|
|
153
|
-
/>
|
|
154
|
-
<SimpleIconButton
|
|
155
|
-
icon={<Layers className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
156
|
-
label="Component Navigator"
|
|
157
|
-
size="large"
|
|
158
|
-
selected={editContext.showRightSidebar}
|
|
159
|
-
onClick={() =>
|
|
160
|
-
editContext.setShowRightSidebar(!editContext.showRightSidebar)
|
|
161
|
-
}
|
|
162
|
-
/>
|
|
163
|
-
</div>
|
|
164
|
-
</>
|
|
165
|
-
)}
|
|
166
|
-
</div>
|
|
167
|
-
);
|
|
9
|
+
return createEditToolbar(editContext);
|
|
168
10
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { EditContextType } from "../client/editContext";
|
|
2
|
+
import { GenericToolbar, ToolbarSection } from "./GenericToolbar";
|
|
3
|
+
import {
|
|
4
|
+
ReviewCommands,
|
|
5
|
+
EditControls,
|
|
6
|
+
InsertControls,
|
|
7
|
+
ViewportControls,
|
|
8
|
+
UtilityControls,
|
|
9
|
+
CompareControls,
|
|
10
|
+
} from "./toolbar-sections";
|
|
11
|
+
|
|
12
|
+
export function createEditToolbar(editContext: EditContextType) {
|
|
13
|
+
if (!editContext) return null;
|
|
14
|
+
|
|
15
|
+
const hasLayout = editContext.contentEditorItem?.hasLayout;
|
|
16
|
+
const isReviewsView = editContext.viewName === "reviews";
|
|
17
|
+
|
|
18
|
+
// For items without layout (simple content editor)
|
|
19
|
+
if (!hasLayout) {
|
|
20
|
+
const left: ToolbarSection[] = [
|
|
21
|
+
{
|
|
22
|
+
key: "compare",
|
|
23
|
+
component: <CompareControls />,
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
return <GenericToolbar left={left} />;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// For pages with layout
|
|
31
|
+
const left: ToolbarSection[] = [];
|
|
32
|
+
const right: ToolbarSection[] = [];
|
|
33
|
+
const center: ToolbarSection[] = [];
|
|
34
|
+
|
|
35
|
+
// Add review commands if in reviews view
|
|
36
|
+
|
|
37
|
+
// Standard edit controls
|
|
38
|
+
left.push({
|
|
39
|
+
key: "edit-controls",
|
|
40
|
+
component: <EditControls />,
|
|
41
|
+
});
|
|
42
|
+
if (isReviewsView) {
|
|
43
|
+
left.push({
|
|
44
|
+
key: "review-commands",
|
|
45
|
+
component: <ReviewCommands />,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Insert controls
|
|
50
|
+
left.push({
|
|
51
|
+
key: "insert-controls",
|
|
52
|
+
component: <InsertControls />,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Viewport controls (desktop/mobile/form)
|
|
56
|
+
center.push({
|
|
57
|
+
key: "viewport-controls",
|
|
58
|
+
component: <ViewportControls />,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Utility controls (compare, fullscreen, sidebar)
|
|
62
|
+
right.push({
|
|
63
|
+
key: "utility-controls",
|
|
64
|
+
component: <UtilityControls />,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return <GenericToolbar left={left} right={right} center={center} />;
|
|
68
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEditContext } from "../../client/editContext";
|
|
2
|
+
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
3
|
+
import { CompareIcon } from "../../ui/Icons";
|
|
4
|
+
|
|
5
|
+
export function CompareControls() {
|
|
6
|
+
const editContext = useEditContext();
|
|
7
|
+
|
|
8
|
+
if (!editContext) return null;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<SimpleIconButton
|
|
12
|
+
icon={<CompareIcon className="h-6 w-6 p-1" />}
|
|
13
|
+
label="Compare"
|
|
14
|
+
size="large"
|
|
15
|
+
className={
|
|
16
|
+
editContext.compareMode ? "text-gray-600" : "hover:text-gray-600"
|
|
17
|
+
}
|
|
18
|
+
selected={editContext.compareMode}
|
|
19
|
+
onClick={() => editContext.setCompareMode(!editContext.compareMode)}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useEditContext } from "../../client/editContext";
|
|
2
|
+
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
3
|
+
import { EyeIcon, MessagesSquare, Pencil } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
export function EditControls() {
|
|
6
|
+
const editContext = useEditContext();
|
|
7
|
+
|
|
8
|
+
if (!editContext) return null;
|
|
9
|
+
|
|
10
|
+
// Calculate total count of comments and suggestions
|
|
11
|
+
const commentsCount =
|
|
12
|
+
editContext.comments?.filter((x) => !x.isResolved).length || 0;
|
|
13
|
+
const suggestionsCount =
|
|
14
|
+
editContext.suggestedEdits?.filter((x) => x.status === "pending").length ||
|
|
15
|
+
0;
|
|
16
|
+
const totalCount = commentsCount + suggestionsCount;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<>
|
|
20
|
+
{!editContext.user?.isLimitedPreviewUser && (
|
|
21
|
+
<SimpleIconButton
|
|
22
|
+
icon={<Pencil className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
23
|
+
label="Edit"
|
|
24
|
+
size="large"
|
|
25
|
+
selected={editContext.mode === "edit"}
|
|
26
|
+
onClick={() => editContext.setMode("edit")}
|
|
27
|
+
/>
|
|
28
|
+
)}
|
|
29
|
+
|
|
30
|
+
<SimpleIconButton
|
|
31
|
+
icon={<EyeIcon className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
32
|
+
label="Preview"
|
|
33
|
+
size="large"
|
|
34
|
+
selected={editContext.mode === "preview"}
|
|
35
|
+
onClick={() => editContext.setMode("preview")}
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
<div className="relative">
|
|
39
|
+
<SimpleIconButton
|
|
40
|
+
selected={editContext?.mode === "suggestions"}
|
|
41
|
+
icon={<MessagesSquare strokeWidth={1} className="h-6 w-6 p-1" />}
|
|
42
|
+
label="Write suggestions"
|
|
43
|
+
size="large"
|
|
44
|
+
onClick={() => editContext?.setMode("suggestions")}
|
|
45
|
+
/>
|
|
46
|
+
{totalCount > 0 && (
|
|
47
|
+
<div className="bg-theme-secondary text-3xs absolute -top-1 -right-1 flex h-[16px] min-w-[16px] items-center justify-center rounded-full px-1 text-white">
|
|
48
|
+
{totalCount > 99 ? "99+" : totalCount}
|
|
49
|
+
</div>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useEditContext } from "../../client/editContext";
|
|
2
|
+
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
3
|
+
import { Plus } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
export function InsertControls() {
|
|
6
|
+
const editContext = useEditContext();
|
|
7
|
+
|
|
8
|
+
if (!editContext) return null;
|
|
9
|
+
|
|
10
|
+
const insertMode = editContext.insertMode;
|
|
11
|
+
|
|
12
|
+
const toggleInsertMode = () => {
|
|
13
|
+
editContext.setInsertMode(true);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<SimpleIconButton
|
|
18
|
+
icon={<Plus className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
19
|
+
label="Add Component"
|
|
20
|
+
size="large"
|
|
21
|
+
selected={insertMode}
|
|
22
|
+
onClick={toggleInsertMode}
|
|
23
|
+
disabled={
|
|
24
|
+
!editContext.page?.item.canWriteItem || editContext.mode !== "edit"
|
|
25
|
+
}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useEditContext } from "../../client/editContext";
|
|
2
|
+
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
3
|
+
import { Check, X } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
export function ReviewCommands() {
|
|
6
|
+
const editContext = useEditContext();
|
|
7
|
+
|
|
8
|
+
if (!editContext) return null;
|
|
9
|
+
|
|
10
|
+
const reviewCommands = editContext.configuration.commands.reviewcommands;
|
|
11
|
+
const contentEditorItem = editContext.contentEditorItem;
|
|
12
|
+
|
|
13
|
+
if (!contentEditorItem || !reviewCommands?.length) return null;
|
|
14
|
+
|
|
15
|
+
const executeReviewCommand = async (command: any, event?: any) => {
|
|
16
|
+
if (command && contentEditorItem) {
|
|
17
|
+
await editContext.executeCommand({
|
|
18
|
+
command: command,
|
|
19
|
+
data: { items: [contentEditorItem] },
|
|
20
|
+
event: event || null,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
{reviewCommands.map((command: any) => {
|
|
28
|
+
const isDisabled = editContext.isCommandDisabled({
|
|
29
|
+
command: command,
|
|
30
|
+
data: { items: [contentEditorItem] },
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Use appropriate icons for approve/reject commands
|
|
34
|
+
const getIcon = () => {
|
|
35
|
+
if (command.id === "approve-review") {
|
|
36
|
+
return <Check className="h-6 w-6 p-1" strokeWidth={1} />;
|
|
37
|
+
}
|
|
38
|
+
if (command.id === "reject-review") {
|
|
39
|
+
return <X className="h-6 w-6 p-1" strokeWidth={1} />;
|
|
40
|
+
}
|
|
41
|
+
return (
|
|
42
|
+
command.icon || <Check className="h-6 w-6 p-1" strokeWidth={1} />
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<SimpleIconButton
|
|
48
|
+
key={command.id}
|
|
49
|
+
icon={getIcon()}
|
|
50
|
+
label={command.label}
|
|
51
|
+
size="large"
|
|
52
|
+
disabled={isDisabled}
|
|
53
|
+
onClick={(event) => executeReviewCommand(command, event)}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
})}
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEditContext } from "../../client/editContext";
|
|
2
|
+
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
3
|
+
import { Layers } from "lucide-react";
|
|
4
|
+
import { EnterFullScreenIcon } from "@radix-ui/react-icons";
|
|
5
|
+
import { CompareIcon } from "../../ui/Icons";
|
|
6
|
+
|
|
7
|
+
export function UtilityControls() {
|
|
8
|
+
const editContext = useEditContext();
|
|
9
|
+
|
|
10
|
+
if (!editContext) return null;
|
|
11
|
+
|
|
12
|
+
const pageViewContext = editContext.pageView;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
<SimpleIconButton
|
|
17
|
+
icon={<EnterFullScreenIcon className="h-6 w-6 p-1" />}
|
|
18
|
+
label="Fullscreen"
|
|
19
|
+
size="large"
|
|
20
|
+
onClick={() => pageViewContext.setFullscreen(true)}
|
|
21
|
+
/>
|
|
22
|
+
<SimpleIconButton
|
|
23
|
+
icon={<Layers className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
24
|
+
label="Component Navigator"
|
|
25
|
+
size="large"
|
|
26
|
+
selected={editContext.showRightSidebar}
|
|
27
|
+
onClick={() =>
|
|
28
|
+
editContext.setShowRightSidebar(!editContext.showRightSidebar)
|
|
29
|
+
}
|
|
30
|
+
/>
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { CompareIcon } from "../../ui/Icons";
|
|
2
|
+
import { useEditContext } from "../../client/editContext";
|
|
3
|
+
import { SimpleIconButton } from "../../ui/SimpleIconButton";
|
|
4
|
+
import { Monitor, Smartphone, Table } from "lucide-react";
|
|
5
|
+
import { Separator } from "../Separator";
|
|
6
|
+
|
|
7
|
+
export function ViewportControls() {
|
|
8
|
+
const editContext = useEditContext();
|
|
9
|
+
|
|
10
|
+
if (!editContext || editContext.isMobile) return null;
|
|
11
|
+
|
|
12
|
+
const pageViewContext = editContext.pageView;
|
|
13
|
+
const device = pageViewContext.device;
|
|
14
|
+
const setDevice = pageViewContext.setDevice;
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<SimpleIconButton
|
|
19
|
+
icon={<Monitor className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
20
|
+
label="Desktop"
|
|
21
|
+
size="large"
|
|
22
|
+
selected={device === "desktop"}
|
|
23
|
+
onClick={() => setDevice("desktop")}
|
|
24
|
+
/>
|
|
25
|
+
<SimpleIconButton
|
|
26
|
+
icon={<Smartphone className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
27
|
+
label="Mobile"
|
|
28
|
+
size="large"
|
|
29
|
+
selected={Boolean(device && device !== "desktop")}
|
|
30
|
+
onClick={() => {
|
|
31
|
+
if (editContext.configuration.devices[0]) {
|
|
32
|
+
setDevice(editContext.configuration.devices[0].name);
|
|
33
|
+
}
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
<SimpleIconButton
|
|
37
|
+
icon={<Table className="h-6 w-6 p-1" strokeWidth={1} />}
|
|
38
|
+
label="Form"
|
|
39
|
+
size="large"
|
|
40
|
+
selected={!device}
|
|
41
|
+
onClick={() => setDevice("")}
|
|
42
|
+
/>
|
|
43
|
+
<Separator size="large" />
|
|
44
|
+
{!editContext.isMobile && (
|
|
45
|
+
<SimpleIconButton
|
|
46
|
+
icon={<CompareIcon className="h-6 w-6 p-1" />}
|
|
47
|
+
label="Compare"
|
|
48
|
+
size="large"
|
|
49
|
+
className={
|
|
50
|
+
editContext.compareMode ? "text-gray-600" : "hover:text-gray-600"
|
|
51
|
+
}
|
|
52
|
+
selected={editContext.compareMode}
|
|
53
|
+
onClick={() => editContext.setCompareMode(!editContext.compareMode)}
|
|
54
|
+
/>
|
|
55
|
+
)}
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ReviewCommands } from "./ReviewCommands";
|
|
2
|
+
export { EditControls } from "./EditControls";
|
|
3
|
+
export { InsertControls } from "./InsertControls";
|
|
4
|
+
export { ViewportControls } from "./ViewportControls";
|
|
5
|
+
export { UtilityControls } from "./UtilityControls";
|
|
6
|
+
export { CompareControls } from "./CompareControls";
|
|
@@ -482,7 +482,7 @@ export function ComponentTree({}) {
|
|
|
482
482
|
|
|
483
483
|
if (!page)
|
|
484
484
|
return (
|
|
485
|
-
<div className="flex h-full items-center justify-center text-
|
|
485
|
+
<div className="flex h-full items-center justify-center text-xs text-gray-500">
|
|
486
486
|
This item has no layout.
|
|
487
487
|
</div>
|
|
488
488
|
);
|