@alpaca-editor/core 1.0.3812 → 1.0.3815

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.
Files changed (117) hide show
  1. package/dist/components/ui/context-menu.d.ts +25 -0
  2. package/dist/components/ui/context-menu.js +51 -0
  3. package/dist/components/ui/context-menu.js.map +1 -0
  4. package/dist/config/config.js +3 -2
  5. package/dist/config/config.js.map +1 -1
  6. package/dist/config/types.d.ts +4 -2
  7. package/dist/editor/ComponentInfo.js +1 -1
  8. package/dist/editor/ComponentInfo.js.map +1 -1
  9. package/dist/editor/ConfirmationDialog.d.ts +1 -1
  10. package/dist/editor/ContextMenu.d.ts +1 -1
  11. package/dist/editor/ContextMenu.js +24 -9
  12. package/dist/editor/ContextMenu.js.map +1 -1
  13. package/dist/editor/ImageEditor.js +2 -2
  14. package/dist/editor/ImageEditor.js.map +1 -1
  15. package/dist/editor/ItemInfo.js +2 -2
  16. package/dist/editor/ItemInfo.js.map +1 -1
  17. package/dist/editor/MainLayout.js +3 -3
  18. package/dist/editor/MainLayout.js.map +1 -1
  19. package/dist/editor/Titlebar.js +1 -1
  20. package/dist/editor/Titlebar.js.map +1 -1
  21. package/dist/editor/ai/AiTerminal.js +19 -12
  22. package/dist/editor/ai/AiTerminal.js.map +1 -1
  23. package/dist/editor/client/EditorClient.js +19 -4
  24. package/dist/editor/client/EditorClient.js.map +1 -1
  25. package/dist/editor/client/editContext.d.ts +1 -1
  26. package/dist/editor/client/operations.js +15 -14
  27. package/dist/editor/client/operations.js.map +1 -1
  28. package/dist/editor/client/pageModelBuilder.js +8 -5
  29. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  30. package/dist/editor/commands/componentCommands.js +15 -13
  31. package/dist/editor/commands/componentCommands.js.map +1 -1
  32. package/dist/editor/componentTreeHelper.js +3 -3
  33. package/dist/editor/componentTreeHelper.js.map +1 -1
  34. package/dist/editor/control-center/ControlCenterMenu.js +3 -3
  35. package/dist/editor/control-center/ControlCenterMenu.js.map +1 -1
  36. package/dist/editor/field-types/TreeListEditor.js +4 -4
  37. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  38. package/dist/editor/page-editor-chrome/FrameMenu.js +52 -14
  39. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  40. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +5 -5
  41. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  42. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +114 -45
  43. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  44. package/dist/editor/page-viewer/PageViewerFrame.d.ts +0 -1
  45. package/dist/editor/page-viewer/PageViewerFrame.js +119 -215
  46. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  47. package/dist/editor/page-viewer/pageModelBuilder.d.ts +3 -0
  48. package/dist/editor/page-viewer/pageModelBuilder.js +299 -0
  49. package/dist/editor/page-viewer/pageModelBuilder.js.map +1 -0
  50. package/dist/editor/pageModel.d.ts +5 -0
  51. package/dist/editor/sidebar/ComponentPalette.js +30 -30
  52. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  53. package/dist/editor/sidebar/ComponentTree.js +7 -6
  54. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  55. package/dist/editor/sidebar/MainContentTree.js +1 -1
  56. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  57. package/dist/editor/sidebar/SidebarView.js +3 -3
  58. package/dist/editor/sidebar/SidebarView.js.map +1 -1
  59. package/dist/editor/ui/CopyToClipboardButton.js +2 -1
  60. package/dist/editor/ui/CopyToClipboardButton.js.map +1 -1
  61. package/dist/editor/ui/Icons.d.ts +0 -1
  62. package/dist/editor/ui/Icons.js +0 -3
  63. package/dist/editor/ui/Icons.js.map +1 -1
  64. package/dist/editor/ui/Section.js +1 -1
  65. package/dist/editor/ui/Section.js.map +1 -1
  66. package/dist/editor/ui/SimpleMenu.d.ts +1 -8
  67. package/dist/editor/ui/SimpleMenu.js +1 -1
  68. package/dist/editor/ui/SimpleMenu.js.map +1 -1
  69. package/dist/editor/utils.d.ts +2 -2
  70. package/dist/editor/utils.js +57 -9
  71. package/dist/editor/utils.js.map +1 -1
  72. package/dist/lib/safelist.js +1 -1
  73. package/dist/lib/safelist.js.map +1 -1
  74. package/dist/splash-screen/SplashScreen.js +0 -1
  75. package/dist/splash-screen/SplashScreen.js.map +1 -1
  76. package/dist/styles.css +242 -59
  77. package/dist/types.d.ts +2 -2
  78. package/package.json +3 -2
  79. package/src/components/ui/context-menu.tsx +250 -0
  80. package/src/config/config.tsx +2 -2
  81. package/src/config/types.ts +4 -2
  82. package/src/editor/ComponentInfo.tsx +3 -5
  83. package/src/editor/ConfirmationDialog.tsx +1 -1
  84. package/src/editor/ContextMenu.tsx +68 -19
  85. package/src/editor/ImageEditor.tsx +2 -2
  86. package/src/editor/ItemInfo.tsx +4 -4
  87. package/src/editor/MainLayout.tsx +3 -4
  88. package/src/editor/Titlebar.tsx +1 -1
  89. package/src/editor/ai/AiTerminal.tsx +31 -24
  90. package/src/editor/client/EditorClient.tsx +23 -6
  91. package/src/editor/client/editContext.ts +1 -1
  92. package/src/editor/client/operations.ts +16 -14
  93. package/src/editor/client/pageModelBuilder.ts +26 -18
  94. package/src/editor/commands/componentCommands.tsx +58 -39
  95. package/src/editor/componentTreeHelper.tsx +3 -2
  96. package/src/editor/control-center/ControlCenterMenu.tsx +4 -4
  97. package/src/editor/field-types/TreeListEditor.tsx +11 -11
  98. package/src/editor/page-editor-chrome/FrameMenu.tsx +81 -17
  99. package/src/editor/page-editor-chrome/InlineEditor.tsx +5 -5
  100. package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +12 -15
  101. package/src/editor/page-editor-chrome/PlaceholderDropZones.tsx +159 -68
  102. package/src/editor/page-viewer/PageViewerFrame.tsx +131 -300
  103. package/src/editor/page-viewer/pageModelBuilder.ts +412 -0
  104. package/src/editor/pageModel.ts +5 -0
  105. package/src/editor/sidebar/ComponentPalette.tsx +108 -106
  106. package/src/editor/sidebar/ComponentTree.tsx +10 -5
  107. package/src/editor/sidebar/MainContentTree.tsx +1 -1
  108. package/src/editor/sidebar/SidebarView.tsx +9 -9
  109. package/src/editor/ui/CopyToClipboardButton.tsx +2 -1
  110. package/src/editor/ui/Icons.tsx +0 -18
  111. package/src/editor/ui/Section.tsx +4 -4
  112. package/src/editor/ui/SimpleMenu.tsx +5 -13
  113. package/src/editor/utils.ts +74 -17
  114. package/src/lib/safelist.tsx +2 -0
  115. package/src/splash-screen/SplashScreen.tsx +0 -1
  116. package/src/types.ts +2 -4
  117. package/styles.css +58 -17
@@ -0,0 +1,250 @@
1
+ import * as React from "react";
2
+ import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
3
+ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
4
+
5
+ import { cn } from "../../lib/utils";
6
+
7
+ function ContextMenu({
8
+ ...props
9
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Root>) {
10
+ return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;
11
+ }
12
+
13
+ function ContextMenuTrigger({
14
+ ...props
15
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) {
16
+ return (
17
+ <ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} />
18
+ );
19
+ }
20
+
21
+ function ContextMenuGroup({
22
+ ...props
23
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Group>) {
24
+ return (
25
+ <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />
26
+ );
27
+ }
28
+
29
+ function ContextMenuPortal({
30
+ ...props
31
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
32
+ return (
33
+ <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />
34
+ );
35
+ }
36
+
37
+ function ContextMenuSub({
38
+ ...props
39
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) {
40
+ return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />;
41
+ }
42
+
43
+ function ContextMenuRadioGroup({
44
+ ...props
45
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) {
46
+ return (
47
+ <ContextMenuPrimitive.RadioGroup
48
+ data-slot="context-menu-radio-group"
49
+ {...props}
50
+ />
51
+ );
52
+ }
53
+
54
+ function ContextMenuSubTrigger({
55
+ className,
56
+ inset,
57
+ children,
58
+ ...props
59
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {
60
+ inset?: boolean;
61
+ }) {
62
+ return (
63
+ <ContextMenuPrimitive.SubTrigger
64
+ data-slot="context-menu-sub-trigger"
65
+ data-inset={inset}
66
+ className={cn(
67
+ "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
68
+ className,
69
+ )}
70
+ {...props}
71
+ >
72
+ {children}
73
+ <ChevronRightIcon className="ml-auto" />
74
+ </ContextMenuPrimitive.SubTrigger>
75
+ );
76
+ }
77
+
78
+ function ContextMenuSubContent({
79
+ className,
80
+ ...props
81
+ }: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) {
82
+ return (
83
+ <ContextMenuPrimitive.SubContent
84
+ data-slot="context-menu-sub-content"
85
+ className={cn(
86
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
87
+ className,
88
+ )}
89
+ {...props}
90
+ />
91
+ );
92
+ }
93
+
94
+ function ContextMenuContent({
95
+ className,
96
+ ...props
97
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {
98
+ return (
99
+ <ContextMenuPrimitive.Portal>
100
+ <ContextMenuPrimitive.Content
101
+ data-slot="context-menu-content"
102
+ className={cn(
103
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
104
+ className,
105
+ )}
106
+ {...props}
107
+ />
108
+ </ContextMenuPrimitive.Portal>
109
+ );
110
+ }
111
+
112
+ function ContextMenuItem({
113
+ className,
114
+ inset,
115
+ variant = "default",
116
+ ...props
117
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
118
+ inset?: boolean;
119
+ variant?: "default" | "destructive";
120
+ }) {
121
+ return (
122
+ <ContextMenuPrimitive.Item
123
+ data-slot="context-menu-item"
124
+ data-inset={inset}
125
+ data-variant={variant}
126
+ className={cn(
127
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
128
+ className,
129
+ )}
130
+ {...props}
131
+ />
132
+ );
133
+ }
134
+
135
+ function ContextMenuCheckboxItem({
136
+ className,
137
+ children,
138
+ checked,
139
+ ...props
140
+ }: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {
141
+ return (
142
+ <ContextMenuPrimitive.CheckboxItem
143
+ data-slot="context-menu-checkbox-item"
144
+ className={cn(
145
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
146
+ className,
147
+ )}
148
+ checked={checked}
149
+ {...props}
150
+ >
151
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
152
+ <ContextMenuPrimitive.ItemIndicator>
153
+ <CheckIcon className="size-4" />
154
+ </ContextMenuPrimitive.ItemIndicator>
155
+ </span>
156
+ {children}
157
+ </ContextMenuPrimitive.CheckboxItem>
158
+ );
159
+ }
160
+
161
+ function ContextMenuRadioItem({
162
+ className,
163
+ children,
164
+ ...props
165
+ }: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {
166
+ return (
167
+ <ContextMenuPrimitive.RadioItem
168
+ data-slot="context-menu-radio-item"
169
+ className={cn(
170
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
171
+ className,
172
+ )}
173
+ {...props}
174
+ >
175
+ <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
176
+ <ContextMenuPrimitive.ItemIndicator>
177
+ <CircleIcon className="size-2 fill-current" />
178
+ </ContextMenuPrimitive.ItemIndicator>
179
+ </span>
180
+ {children}
181
+ </ContextMenuPrimitive.RadioItem>
182
+ );
183
+ }
184
+
185
+ function ContextMenuLabel({
186
+ className,
187
+ inset,
188
+ ...props
189
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Label> & {
190
+ inset?: boolean;
191
+ }) {
192
+ return (
193
+ <ContextMenuPrimitive.Label
194
+ data-slot="context-menu-label"
195
+ data-inset={inset}
196
+ className={cn(
197
+ "text-foreground px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
198
+ className,
199
+ )}
200
+ {...props}
201
+ />
202
+ );
203
+ }
204
+
205
+ function ContextMenuSeparator({
206
+ className,
207
+ ...props
208
+ }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) {
209
+ return (
210
+ <ContextMenuPrimitive.Separator
211
+ data-slot="context-menu-separator"
212
+ className={cn("bg-border -mx-1 my-1 h-px", className)}
213
+ {...props}
214
+ />
215
+ );
216
+ }
217
+
218
+ function ContextMenuShortcut({
219
+ className,
220
+ ...props
221
+ }: React.ComponentProps<"span">) {
222
+ return (
223
+ <span
224
+ data-slot="context-menu-shortcut"
225
+ className={cn(
226
+ "text-muted-foreground ml-auto text-xs tracking-widest",
227
+ className,
228
+ )}
229
+ {...props}
230
+ />
231
+ );
232
+ }
233
+
234
+ export {
235
+ ContextMenu,
236
+ ContextMenuTrigger,
237
+ ContextMenuContent,
238
+ ContextMenuItem,
239
+ ContextMenuCheckboxItem,
240
+ ContextMenuRadioItem,
241
+ ContextMenuLabel,
242
+ ContextMenuSeparator,
243
+ ContextMenuShortcut,
244
+ ContextMenuGroup,
245
+ ContextMenuPortal,
246
+ ContextMenuSub,
247
+ ContextMenuSubContent,
248
+ ContextMenuSubTrigger,
249
+ ContextMenuRadioGroup,
250
+ };
@@ -31,7 +31,6 @@ import {
31
31
  EditIcon,
32
32
  GraphQLIcon,
33
33
  JsonIcon,
34
- NavigatorIcon,
35
34
  PageWizardIcon,
36
35
  WizardIcon,
37
36
  } from "../editor/ui/Icons";
@@ -91,6 +90,7 @@ import { getWizards } from "../page-wizard/service";
91
90
  import { startPageWizardCommand } from "../page-wizard/startPageWizardCommand";
92
91
  import { ImageFieldEditor } from "../editor/field-types/ImageFieldEditor";
93
92
  import { FieldAction } from "./types";
93
+ import { Layers } from "lucide-react";
94
94
 
95
95
  const defaultRichTextEditorProfile: RichTextEditorProfile = {
96
96
  toolbar: {
@@ -129,7 +129,7 @@ const pageEditorRightSidebar = {
129
129
  panels: [
130
130
  {
131
131
  name: "component-tree",
132
- icon: <NavigatorIcon />,
132
+ icon: <Layers size={14} />,
133
133
  title: "Component Navigator",
134
134
  content: <ComponentTree />,
135
135
  initialSize: 20,
@@ -85,10 +85,12 @@ export type ViewPanel = {
85
85
 
86
86
  export type MenuItem = {
87
87
  id: string;
88
- label: string;
89
- icon: ReactNode;
88
+ label?: string;
89
+ icon?: ReactNode;
90
90
  items?: MenuItem[];
91
91
  command?: (event: any) => Promise<void>;
92
+ disabled?: boolean;
93
+ separator?: boolean;
92
94
  };
93
95
 
94
96
  export type EditorConfiguration = {
@@ -47,13 +47,11 @@ export function ComponentInfo({ component }: { component: Component | null }) {
47
47
 
48
48
  return (
49
49
  <div>
50
- <h2 className="py-3 px-3 text-l font-bold my-2">
51
- {component.name}
52
- </h2>
50
+ <h2 className="text-l my-2 px-3 py-3 font-bold">{component.name}</h2>
53
51
  <Section title="Info">
54
- <div className="grid grid-cols-[min-content_1fr] gap-3 text-xs bg-gray-100">
52
+ <div className="grid grid-cols-[min-content_1fr] gap-3 bg-gray-100 text-xs">
55
53
  <div className="font-bold">ID:</div>
56
- <div>
54
+ <div className="flex items-center gap-1">
57
55
  {component.id} <CopyToClipboardButton text={component.id} />
58
56
  </div>
59
57
  <div className="font-bold">Template</div>
@@ -11,7 +11,7 @@ export type ConfirmationProps = {
11
11
  header?: React.ReactNode;
12
12
  acceptLabel?: string;
13
13
  rejectLabel?: string;
14
- icon?: string;
14
+ icon?: React.ReactNode;
15
15
  accept: () => void;
16
16
  reject?: () => void;
17
17
  showCancel?: boolean;
@@ -1,11 +1,16 @@
1
- import { MenuItem, MenuItemCommandEvent } from "primereact/menuitem";
2
-
3
1
  import { EditContextType } from "./client/editContext";
4
2
  import { forwardRef, useImperativeHandle, useRef, useState } from "react";
5
- import { ContextMenu } from "primereact/contextmenu";
6
3
 
7
4
  import { FieldDescriptor } from "../types";
8
5
  import { Component, FieldButton } from "./pageModel";
6
+ import {
7
+ ContextMenu,
8
+ ContextMenuContent,
9
+ ContextMenuItem,
10
+ ContextMenuSeparator,
11
+ ContextMenuTrigger,
12
+ } from "../components/ui/context-menu";
13
+ import { MenuItem } from "../config/types";
9
14
 
10
15
  // export function getFieldContextMenu(
11
16
  // field: Field,
@@ -64,11 +69,11 @@ export function showComponentContextMenu(
64
69
  components: Component[],
65
70
  editContext: EditContextType,
66
71
  field?: FieldDescriptor,
67
- fieldButtons?: FieldButton[]
72
+ fieldButtons?: FieldButton[],
68
73
  ) {
69
74
  const componentCommandMenuItems = getComponentMenuItems(
70
75
  editContext,
71
- components
76
+ components,
72
77
  );
73
78
 
74
79
  const menuItems = componentCommandMenuItems;
@@ -76,28 +81,29 @@ export function showComponentContextMenu(
76
81
  if (!editContext.readonly && field && fieldButtons?.length) {
77
82
  if (menuItems.length)
78
83
  menuItems.push({
84
+ id: "separator",
79
85
  separator: true,
80
86
  });
81
87
 
82
88
  fieldButtons.forEach((button) => {
83
89
  menuItems.push({
90
+ id: button.id,
84
91
  label: button.label,
85
- command: () => {
92
+ command: async () => {
86
93
  editContext!.triggerFieldAction(field, button);
87
94
  },
88
- icon: button.icon ? "pi " + button.icon : undefined,
95
+ icon: button.icon ? <img src={button.icon} width={16} /> : undefined,
89
96
  });
90
97
  });
91
98
  }
92
99
 
93
100
  return (e: any) => {
94
- if (!e.shiftKey && !e.altKey) {
95
- if(menuItems.length) {
96
-
97
- // editContext.select([component.id]);
101
+ if (!e.shiftKey && !e.altKey) {
102
+ if (menuItems.length) {
103
+ // editContext.select([component.id]);
98
104
  editContext!.showContextMenu(e, menuItems);
99
105
  }
100
-
106
+
101
107
  return true;
102
108
  }
103
109
  return false;
@@ -115,7 +121,8 @@ export const EditContextMenu = forwardRef<
115
121
  EditContextMenuRef,
116
122
  EditContextMenuProps
117
123
  >((props, ref) => {
118
- const cm = useRef<ContextMenu>(null);
124
+ const canvasRef = useRef<HTMLSpanElement>(null);
125
+
119
126
  const [menuItems, setMenuItems] = useState<MenuItem[]>([]);
120
127
  if (!props) return;
121
128
  useImperativeHandle(ref, () => ({
@@ -123,30 +130,72 @@ export const EditContextMenu = forwardRef<
123
130
  if (!e.ctrlKey && !e.shiftKey && !e.altKey) {
124
131
  setMenuItems(items);
125
132
  e.preventDefault();
126
- cm.current?.show(e);
133
+ triggerRightClick(canvasRef.current!, {
134
+ position: { x: e.clientX, y: e.clientY },
135
+ });
127
136
  }
128
137
  },
129
138
  close: (event: any) => {
130
- cm.current?.hide(event);
139
+ // cm.current?.hide(event);
131
140
  },
132
141
  }));
133
142
 
134
- return <ContextMenu model={menuItems} ref={cm} />;
143
+ const triggerRightClick = (
144
+ element: HTMLSpanElement,
145
+ { position }: { position: any },
146
+ ) => {
147
+ const event = new MouseEvent("contextmenu", {
148
+ bubbles: true,
149
+ cancelable: true,
150
+ clientX: position.x,
151
+ clientY: position.y,
152
+ });
153
+ element.dispatchEvent(event);
154
+ };
155
+
156
+ return (
157
+ <ContextMenu>
158
+ <ContextMenuTrigger>
159
+ <span id="contextmenu_canvas" ref={canvasRef}>
160
+ CM trigger
161
+ </span>
162
+ </ContextMenuTrigger>
163
+ <ContextMenuContent>
164
+ {menuItems.map((item, index) =>
165
+ item.separator ? (
166
+ <ContextMenuSeparator />
167
+ ) : (
168
+ <ContextMenuItem
169
+ key={index}
170
+ onClick={item.command}
171
+ disabled={item.disabled}
172
+ className="cursor-pointer"
173
+ >
174
+ {item.icon}
175
+ {item.label}
176
+ </ContextMenuItem>
177
+ ),
178
+ )}
179
+ </ContextMenuContent>
180
+ </ContextMenu>
181
+ );
182
+ // return <ContextMenu model={menuItems} ref={cm} />;
135
183
  });
136
184
  function getComponentMenuItems(
137
185
  editContext: EditContextType,
138
- components: Component[]
186
+ components: Component[],
139
187
  ): MenuItem[] {
140
188
  const componentCommands = editContext.getComponentCommands(components);
141
189
 
142
190
  const componentCommandMenuItems = componentCommands.map((x) => {
143
191
  return {
192
+ id: x.id,
144
193
  label: x.label,
145
194
  icon: x.icon,
146
- command: (ev: MenuItemCommandEvent) =>
195
+ command: (ev: React.SyntheticEvent) =>
147
196
  editContext.executeCommand({
148
197
  command: x,
149
- event: ev.originalEvent,
198
+ event: ev,
150
199
  }),
151
200
  disabled: editContext.isCommandDisabled({ command: x }),
152
201
  };
@@ -11,7 +11,7 @@ export function ImageEditor({
11
11
  field: ImageField;
12
12
  style?: React.CSSProperties;
13
13
  }) {
14
- const [showMenu, setShowMenu] = useState(false);
14
+ const [showMenu, setShowMenu] = useState(true);
15
15
  const editContext = useEditContext();
16
16
  const dialogContext = useDialog();
17
17
 
@@ -72,7 +72,7 @@ export function ImageEditor({
72
72
  />
73
73
  )}
74
74
  {showMenu && (
75
- <div className="absolute inset-0 grid grid-cols-1 items-stretch justify-center gap-1.5 bg-black/50 p-3 text-sm">
75
+ <div className="absolute inset-0 grid grid-cols-1 items-center justify-center gap-1.5 bg-black/50 p-3 text-sm">
76
76
  <Btn
77
77
  label={getImageSrc() ? "Change Image" : "Select Image"}
78
78
  icon="pi pi-image"
@@ -20,7 +20,7 @@ export function ItemInfo({ item }: { item: FullItem | null }) {
20
20
 
21
21
  return (
22
22
  <div>
23
- <div className="flex items-center py-2 px-3 my-2">
23
+ <div className="my-2 flex items-center px-3 py-2">
24
24
  <img
25
25
  src={item.largeIcon}
26
26
  alt="Icon"
@@ -45,11 +45,11 @@ export function ItemInfo({ item }: { item: FullItem | null }) {
45
45
  <Section title="Info">
46
46
  <div className="grid grid-cols-[min-content_1fr] gap-3 text-xs">
47
47
  <div className="font-bold">ID:</div>
48
- <div>
48
+ <div className="flex items-center gap-1">
49
49
  {item.id} <CopyToClipboardButton text={item.id} />
50
50
  </div>
51
51
  <div className="font-bold">Path:</div>
52
- <div>
52
+ <div className="flex items-center gap-1">
53
53
  {item.path} <CopyToClipboardButton text={item.path} />
54
54
  </div>
55
55
  <div className="font-bold">Language:</div>
@@ -57,7 +57,7 @@ export function ItemInfo({ item }: { item: FullItem | null }) {
57
57
  <div className="font-bold">Version:</div>
58
58
  <div>{item.versions > 0 ? item.version : "No versions"}</div>
59
59
  <div className="font-bold">Template:</div>
60
- <div>
60
+ <div className="flex items-center gap-1">
61
61
  <span
62
62
  className="cursor-pointer hover:underline"
63
63
  onClick={() => {
@@ -4,11 +4,11 @@ import { EditorView } from "../config/types";
4
4
 
5
5
  import { classNames } from "primereact/utils";
6
6
  import { useEditContext } from "./client/editContext";
7
- import { NavigatorIcon } from "./ui/Icons";
8
7
 
9
8
  import { SidebarView } from "./sidebar/SidebarView";
10
9
  import { Splitter, SplitterPanel } from "./ui/Splitter";
11
10
  import { ViewSelector } from "./sidebar/ViewSelector";
11
+ import { Layers } from "lucide-react";
12
12
 
13
13
  export default function MainLayout({
14
14
  view,
@@ -36,7 +36,7 @@ export default function MainLayout({
36
36
  defaultSize: 350,
37
37
  content: (
38
38
  <div
39
- className="w-full h-full"
39
+ className="h-full w-full"
40
40
  ref={leftSidebarRef}
41
41
  style={{ wordBreak: "normal" }}
42
42
  >
@@ -80,8 +80,7 @@ export default function MainLayout({
80
80
  localStorageKey="editor.panelSizes"
81
81
  expandLabel={
82
82
  <div className="flex items-center justify-center">
83
- <NavigatorIcon />
84
-
83
+ <Layers size={14} />
85
84
  <div className="mt-3">{rightSidebarTitle} </div>
86
85
  </div>
87
86
  }
@@ -14,7 +14,7 @@ export function Titlebar() {
14
14
  >
15
15
  <i className="pi pi-sparkles text-pink-400" />
16
16
  </a>{" "}
17
- <span className="ml-2 font-mono">editor</span>
17
+ <span className="ml-2 font-mono">workbench</span>
18
18
  </div>
19
19
  <div>{editContext?.view.primaryControls}</div>
20
20
  <div>{editContext?.view.secondaryControls}</div>