@alpaca-editor/core 1.0.3962 → 1.0.3964
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 +11 -10
- 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/ApproveAndPublish.d.ts +1 -1
- package/dist/editor/menubar/ApproveAndPublish.js +4 -1
- package/dist/editor/menubar/ApproveAndPublish.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/WorkflowButton.js +2 -0
- package/dist/editor/menubar/WorkflowButton.js.map +1 -1
- 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 +41 -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/page-viewer/EditorForm.js +10 -7
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/reviews/reviewCommands.js +3 -2
- package/dist/editor/reviews/reviewCommands.js.map +1 -1
- 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/ui/SimpleIconButton.js +3 -5
- package/dist/editor/ui/SimpleIconButton.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 +23 -28
- package/package.json +1 -1
- package/src/config/config.tsx +17 -14
- 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/ApproveAndPublish.tsx +4 -2
- 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/WorkflowButton.tsx +1 -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 +60 -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/page-viewer/EditorForm.tsx +19 -8
- package/src/editor/reviews/reviewCommands.tsx +3 -2
- 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/ui/SimpleIconButton.tsx +6 -7
- 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 +15 -8
- 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
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { useThrottledCallback } from "use-debounce";
|
|
20
20
|
import { SimpleIconButton } from "./ui/SimpleIconButton";
|
|
21
21
|
import { FieldHistory } from "./FieldHistory";
|
|
22
|
+
import { Copy } from "lucide-react";
|
|
22
23
|
|
|
23
24
|
export default function FieldListField({
|
|
24
25
|
field,
|
|
@@ -53,6 +54,7 @@ export default function FieldListField({
|
|
|
53
54
|
const [isModified, setIsModified] = useState(false);
|
|
54
55
|
const [isSaved, setIsSaved] = useState(false);
|
|
55
56
|
const [historyEntry, setHistoryEntry] = useState<FieldHistoryItem>();
|
|
57
|
+
const [showCopiedHint, setShowCopiedHint] = useState(false);
|
|
56
58
|
async function handleActionClick(action: FieldButton): Promise<void> {
|
|
57
59
|
editContext?.triggerFieldAction(field.descriptor, action);
|
|
58
60
|
}
|
|
@@ -247,7 +249,7 @@ export default function FieldListField({
|
|
|
247
249
|
!simplified) && <span className="text-xs">·</span>}
|
|
248
250
|
{!field.isFallback && field.rawValue !== null ? (
|
|
249
251
|
<button
|
|
250
|
-
className="p-0 text-xs"
|
|
252
|
+
className="text-gray-1 p-0 text-xs"
|
|
251
253
|
onClick={() => {
|
|
252
254
|
editContext?.operations.editField({
|
|
253
255
|
field: field.descriptor,
|
|
@@ -260,11 +262,12 @@ export default function FieldListField({
|
|
|
260
262
|
) : (
|
|
261
263
|
showFallbackButton
|
|
262
264
|
)}
|
|
265
|
+
|
|
263
266
|
{config?.buttons?.map((x) => {
|
|
264
267
|
return (
|
|
265
268
|
<button
|
|
266
269
|
key={x.id}
|
|
267
|
-
className="p-0 text-xs"
|
|
270
|
+
className="text-gray-1 p-0 text-xs"
|
|
268
271
|
onClick={() =>
|
|
269
272
|
editContext.triggerFieldAction(field.descriptor, x)
|
|
270
273
|
}
|
|
@@ -275,7 +278,7 @@ export default function FieldListField({
|
|
|
275
278
|
})}
|
|
276
279
|
{!simplified && (
|
|
277
280
|
<button
|
|
278
|
-
className="p-0 text-xs"
|
|
281
|
+
className="text-gray-1 p-0 text-xs"
|
|
279
282
|
onClick={() => {
|
|
280
283
|
setShowRawValue(!showRawValue);
|
|
281
284
|
}}
|
|
@@ -289,6 +292,31 @@ export default function FieldListField({
|
|
|
289
292
|
Raw
|
|
290
293
|
</button>
|
|
291
294
|
)}
|
|
295
|
+
{field.rawValue && (
|
|
296
|
+
<div className="relative">
|
|
297
|
+
<button
|
|
298
|
+
className="text-gray-1 flex items-center gap-1 p-0 text-xs"
|
|
299
|
+
onClick={() => {
|
|
300
|
+
navigator.clipboard.writeText(field.rawValue!);
|
|
301
|
+
setShowCopiedHint(true);
|
|
302
|
+
setTimeout(() => setShowCopiedHint(false), 2000);
|
|
303
|
+
}}
|
|
304
|
+
>
|
|
305
|
+
<Copy strokeWidth={1} className="h-3 w-3" /> Copy
|
|
306
|
+
</button>
|
|
307
|
+
{showCopiedHint && (
|
|
308
|
+
<div
|
|
309
|
+
className="absolute -top-8 left-1/2 animate-pulse rounded bg-gray-800 px-2 py-1 text-xs whitespace-nowrap text-white shadow-lg"
|
|
310
|
+
style={{
|
|
311
|
+
animation: "fadeOut 2s ease-out forwards",
|
|
312
|
+
transform: "translateX(calc(-50% + 15px))",
|
|
313
|
+
}}
|
|
314
|
+
>
|
|
315
|
+
Copied!
|
|
316
|
+
</div>
|
|
317
|
+
)}
|
|
318
|
+
</div>
|
|
319
|
+
)}
|
|
292
320
|
<div className="ml-auto flex items-center gap-1">
|
|
293
321
|
<SimpleIconButton
|
|
294
322
|
icon="pi pi-comment"
|
|
@@ -45,7 +45,7 @@ export function ImageEditButton({
|
|
|
45
45
|
|
|
46
46
|
const defaultTriggerButton = (
|
|
47
47
|
<button
|
|
48
|
-
className={`text-dark border-gray-3 hover:bg-gray-5 absolute right-2 bottom-2 flex items-center justify-center gap-2 border bg-white p-
|
|
48
|
+
className={`text-dark border-gray-3 hover:bg-gray-5 absolute right-2 bottom-2 flex items-center justify-center gap-2 rounded border bg-white p-1.5 text-xs font-medium opacity-70 shadow-lg transition-opacity hover:opacity-85 ${buttonClassName || ""}`}
|
|
49
49
|
onClick={(e) => {
|
|
50
50
|
e.stopPropagation();
|
|
51
51
|
}}
|
|
@@ -78,7 +78,8 @@ export default function MainLayout(props: MainLayoutProps) {
|
|
|
78
78
|
{!props.view.hideViewSelector && <LeftToolbar />}
|
|
79
79
|
<div className="flex flex-1 flex-col">
|
|
80
80
|
{editContext?.view?.titlebar}
|
|
81
|
-
{editContext?.view?.
|
|
81
|
+
{editContext?.view?.toolbarFactory &&
|
|
82
|
+
editContext?.view?.toolbarFactory(editContext)}
|
|
82
83
|
<div className="bg-gray-4 flex-1">
|
|
83
84
|
<Splitter
|
|
84
85
|
splitterClassName="bg-transparent -mr-2 md:w-[8px]"
|
|
@@ -2,12 +2,14 @@ import { useEditContext } from "../client/editContext";
|
|
|
2
2
|
|
|
3
3
|
export function ApproveAndPublishButton() {
|
|
4
4
|
const editContext = useEditContext();
|
|
5
|
+
console.log("USER", editContext?.user);
|
|
6
|
+
if (editContext?.user?.isLimitedPreviewUser) return null;
|
|
5
7
|
return (
|
|
6
8
|
<div
|
|
7
|
-
className="bg-alpaca-blue hover:bg-alpaca-blue-light
|
|
9
|
+
className="bg-alpaca-blue hover:bg-alpaca-blue-light cursor-pointer rounded-l-full p-4 text-sm text-white"
|
|
8
10
|
onClick={() => {
|
|
9
11
|
const workboxView = editContext?.configuration.editor.views.find(
|
|
10
|
-
(x) => x.name == "workbox"
|
|
12
|
+
(x) => x.name == "workbox",
|
|
11
13
|
);
|
|
12
14
|
if (workboxView) editContext?.switchView(workboxView.name);
|
|
13
15
|
}}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Separator } from "./Separator";
|
|
3
|
+
|
|
4
|
+
export interface ToolbarSection {
|
|
5
|
+
key: string;
|
|
6
|
+
component: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface GenericToolbarProps {
|
|
10
|
+
left?: ToolbarSection[];
|
|
11
|
+
center?: ToolbarSection[];
|
|
12
|
+
right?: ToolbarSection[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function GenericToolbar({
|
|
16
|
+
left = [],
|
|
17
|
+
center = [],
|
|
18
|
+
right = [],
|
|
19
|
+
}: GenericToolbarProps) {
|
|
20
|
+
const renderSections = (sections: ToolbarSection[]) => {
|
|
21
|
+
return sections.map((section, index) => (
|
|
22
|
+
<React.Fragment key={section.key}>
|
|
23
|
+
{index > 0 && <Separator size="large" />}
|
|
24
|
+
{section.component}
|
|
25
|
+
</React.Fragment>
|
|
26
|
+
));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className="flex items-center justify-between gap-2 border-b px-4 py-2">
|
|
31
|
+
{/* Left section */}
|
|
32
|
+
<div className="flex items-center gap-2">{renderSections(left)}</div>
|
|
33
|
+
|
|
34
|
+
{/* Center section */}
|
|
35
|
+
{center.length > 0 && (
|
|
36
|
+
<div className="flex items-center gap-2">{renderSections(center)}</div>
|
|
37
|
+
)}
|
|
38
|
+
|
|
39
|
+
{/* Right section */}
|
|
40
|
+
<div className="flex items-center gap-2">{renderSections(right)}</div>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEditContext } from "../client/editContext";
|
|
2
|
+
import { CompareIcon } from "../ui/Icons";
|
|
3
|
+
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
4
|
+
|
|
5
|
+
export function ItemToolbar() {
|
|
6
|
+
const editContext = useEditContext();
|
|
7
|
+
|
|
8
|
+
if (!editContext) return null;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div className="flex items-center justify-center gap-2 border-b px-4 py-2">
|
|
12
|
+
<SimpleIconButton
|
|
13
|
+
icon={<CompareIcon className="h-6 w-6 p-1" />}
|
|
14
|
+
label="Compare"
|
|
15
|
+
size="large"
|
|
16
|
+
className={
|
|
17
|
+
editContext.compareMode ? "text-gray-600" : "hover:text-gray-600"
|
|
18
|
+
}
|
|
19
|
+
selected={editContext.compareMode}
|
|
20
|
+
onClick={() => editContext.setCompareMode(!editContext.compareMode)}
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -11,6 +11,7 @@ export function WorkflowButton() {
|
|
|
11
11
|
const editContext = useEditContext();
|
|
12
12
|
|
|
13
13
|
if (!editContext?.currentItemDescriptor) return null;
|
|
14
|
+
if (editContext?.user?.isLimitedPreviewUser) return null;
|
|
14
15
|
|
|
15
16
|
// Find the current item in workboxItems to get its workflow commands
|
|
16
17
|
const currentWorkboxItem = editContext.workboxItems?.find(
|
|
@@ -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
|
+
}
|