@alpaca-editor/core 1.0.3813 → 1.0.3817

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 (207) 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 +4 -3
  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/EditorWarnings.js +1 -1
  14. package/dist/editor/EditorWarnings.js.map +1 -1
  15. package/dist/editor/FieldList.js +1 -1
  16. package/dist/editor/FieldList.js.map +1 -1
  17. package/dist/editor/FieldListFieldWithFallbacks.js +3 -3
  18. package/dist/editor/FieldListFieldWithFallbacks.js.map +1 -1
  19. package/dist/editor/ImageEditor.js +2 -2
  20. package/dist/editor/ImageEditor.js.map +1 -1
  21. package/dist/editor/ItemInfo.js +2 -2
  22. package/dist/editor/ItemInfo.js.map +1 -1
  23. package/dist/editor/MainLayout.js +3 -3
  24. package/dist/editor/MainLayout.js.map +1 -1
  25. package/dist/editor/Titlebar.js +1 -1
  26. package/dist/editor/Titlebar.js.map +1 -1
  27. package/dist/editor/ai/AiTerminal.js +19 -12
  28. package/dist/editor/ai/AiTerminal.js.map +1 -1
  29. package/dist/editor/client/EditorClient.js +90 -35
  30. package/dist/editor/client/EditorClient.js.map +1 -1
  31. package/dist/editor/client/editContext.d.ts +10 -4
  32. package/dist/editor/client/editContext.js.map +1 -1
  33. package/dist/editor/client/operations.d.ts +5 -1
  34. package/dist/editor/client/operations.js +112 -17
  35. package/dist/editor/client/operations.js.map +1 -1
  36. package/dist/editor/client/pageModelBuilder.js +8 -5
  37. package/dist/editor/client/pageModelBuilder.js.map +1 -1
  38. package/dist/editor/commands/componentCommands.js +15 -13
  39. package/dist/editor/commands/componentCommands.js.map +1 -1
  40. package/dist/editor/component-designer/ComponentDesigner.js +1 -1
  41. package/dist/editor/component-designer/ComponentDesigner.js.map +1 -1
  42. package/dist/editor/componentTreeHelper.js +3 -3
  43. package/dist/editor/componentTreeHelper.js.map +1 -1
  44. package/dist/editor/control-center/ControlCenterMenu.js +3 -3
  45. package/dist/editor/control-center/ControlCenterMenu.js.map +1 -1
  46. package/dist/editor/field-types/TreeListEditor.js +4 -4
  47. package/dist/editor/field-types/TreeListEditor.js.map +1 -1
  48. package/dist/editor/menubar/LanguageSelector.js +3 -3
  49. package/dist/editor/menubar/LanguageSelector.js.map +1 -1
  50. package/dist/editor/menubar/PageSelector.js +1 -1
  51. package/dist/editor/menubar/PageSelector.js.map +1 -1
  52. package/dist/editor/menubar/PageViewerControls.js +12 -7
  53. package/dist/editor/menubar/PageViewerControls.js.map +1 -1
  54. package/dist/editor/menubar/Separator.js +1 -1
  55. package/dist/editor/menubar/VersionSelector.js +1 -1
  56. package/dist/editor/menubar/VersionSelector.js.map +1 -1
  57. package/dist/editor/page-editor-chrome/FrameMenu.d.ts +2 -2
  58. package/dist/editor/page-editor-chrome/FrameMenu.js +66 -22
  59. package/dist/editor/page-editor-chrome/FrameMenu.js.map +1 -1
  60. package/dist/editor/page-editor-chrome/FrameMenus.d.ts +2 -2
  61. package/dist/editor/page-editor-chrome/FrameMenus.js +2 -2
  62. package/dist/editor/page-editor-chrome/FrameMenus.js.map +1 -1
  63. package/dist/editor/page-editor-chrome/InlineEditor.d.ts +2 -2
  64. package/dist/editor/page-editor-chrome/InlineEditor.js +175 -17
  65. package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
  66. package/dist/editor/page-editor-chrome/PageEditorChrome.d.ts +2 -2
  67. package/dist/editor/page-editor-chrome/PageEditorChrome.js +2 -2
  68. package/dist/editor/page-editor-chrome/PageEditorChrome.js.map +1 -1
  69. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js +5 -5
  70. package/dist/editor/page-editor-chrome/PlaceholderDropZone.js.map +1 -1
  71. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js +114 -45
  72. package/dist/editor/page-editor-chrome/PlaceholderDropZones.js.map +1 -1
  73. package/dist/editor/page-viewer/EditorForm.d.ts +2 -1
  74. package/dist/editor/page-viewer/EditorForm.js +9 -8
  75. package/dist/editor/page-viewer/EditorForm.js.map +1 -1
  76. package/dist/editor/page-viewer/MiniMap.d.ts +2 -2
  77. package/dist/editor/page-viewer/MiniMap.js +2 -2
  78. package/dist/editor/page-viewer/MiniMap.js.map +1 -1
  79. package/dist/editor/page-viewer/PageViewer.d.ts +2 -2
  80. package/dist/editor/page-viewer/PageViewer.js +3 -3
  81. package/dist/editor/page-viewer/PageViewer.js.map +1 -1
  82. package/dist/editor/page-viewer/PageViewerFrame.d.ts +2 -3
  83. package/dist/editor/page-viewer/PageViewerFrame.js +127 -223
  84. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  85. package/dist/editor/page-viewer/pageModelBuilder.d.ts +3 -0
  86. package/dist/editor/page-viewer/pageModelBuilder.js +299 -0
  87. package/dist/editor/page-viewer/pageModelBuilder.js.map +1 -0
  88. package/dist/editor/pageModel.d.ts +5 -0
  89. package/dist/editor/reviews/Comments.d.ts +2 -0
  90. package/dist/editor/reviews/Comments.js +26 -9
  91. package/dist/editor/reviews/Comments.js.map +1 -1
  92. package/dist/editor/reviews/DiffView.d.ts +17 -0
  93. package/dist/editor/reviews/DiffView.js +57 -0
  94. package/dist/editor/reviews/DiffView.js.map +1 -0
  95. package/dist/editor/reviews/SuggestedEdit.d.ts +4 -0
  96. package/dist/editor/reviews/SuggestedEdit.js +180 -0
  97. package/dist/editor/reviews/SuggestedEdit.js.map +1 -0
  98. package/dist/editor/services/suggestedEditsService.d.ts +17 -0
  99. package/dist/editor/services/suggestedEditsService.js +26 -0
  100. package/dist/editor/services/suggestedEditsService.js.map +1 -0
  101. package/dist/editor/sidebar/ComponentPalette.js +30 -30
  102. package/dist/editor/sidebar/ComponentPalette.js.map +1 -1
  103. package/dist/editor/sidebar/ComponentTree.js +7 -6
  104. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  105. package/dist/editor/sidebar/MainContentTree.js +1 -1
  106. package/dist/editor/sidebar/MainContentTree.js.map +1 -1
  107. package/dist/editor/sidebar/SidebarView.js +3 -3
  108. package/dist/editor/sidebar/SidebarView.js.map +1 -1
  109. package/dist/editor/ui/CopyToClipboardButton.js +2 -1
  110. package/dist/editor/ui/CopyToClipboardButton.js.map +1 -1
  111. package/dist/editor/ui/Icons.d.ts +0 -1
  112. package/dist/editor/ui/Icons.js +0 -3
  113. package/dist/editor/ui/Icons.js.map +1 -1
  114. package/dist/editor/ui/PerfectTree.js +3 -3
  115. package/dist/editor/ui/PerfectTree.js.map +1 -1
  116. package/dist/editor/ui/Section.js +1 -1
  117. package/dist/editor/ui/Section.js.map +1 -1
  118. package/dist/editor/ui/SimpleIconButton.js +3 -1
  119. package/dist/editor/ui/SimpleIconButton.js.map +1 -1
  120. package/dist/editor/ui/SimpleMenu.d.ts +1 -8
  121. package/dist/editor/ui/SimpleMenu.js +1 -1
  122. package/dist/editor/ui/SimpleMenu.js.map +1 -1
  123. package/dist/editor/utils.d.ts +2 -2
  124. package/dist/editor/utils.js +57 -9
  125. package/dist/editor/utils.js.map +1 -1
  126. package/dist/editor/views/CompareView.js +4 -13
  127. package/dist/editor/views/CompareView.js.map +1 -1
  128. package/dist/editor/views/EditView.js +2 -2
  129. package/dist/editor/views/EditView.js.map +1 -1
  130. package/dist/editor/views/SingleEditView.d.ts +2 -2
  131. package/dist/editor/views/SingleEditView.js +2 -2
  132. package/dist/editor/views/SingleEditView.js.map +1 -1
  133. package/dist/lib/safelist.js +1 -1
  134. package/dist/lib/safelist.js.map +1 -1
  135. package/dist/page-wizard/steps/BuildPageStep.js +2 -2
  136. package/dist/page-wizard/steps/BuildPageStep.js.map +1 -1
  137. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js +2 -2
  138. package/dist/page-wizard/steps/CreatePageAndLayoutStep.js.map +1 -1
  139. package/dist/splash-screen/SplashScreen.js +0 -1
  140. package/dist/splash-screen/SplashScreen.js.map +1 -1
  141. package/dist/styles.css +275 -58
  142. package/dist/types.d.ts +20 -2
  143. package/package.json +6 -2
  144. package/src/components/ui/context-menu.tsx +250 -0
  145. package/src/config/config.tsx +4 -4
  146. package/src/config/types.ts +4 -2
  147. package/src/editor/ComponentInfo.tsx +3 -5
  148. package/src/editor/ConfirmationDialog.tsx +1 -1
  149. package/src/editor/ContextMenu.tsx +68 -19
  150. package/src/editor/EditorWarnings.tsx +2 -2
  151. package/src/editor/FieldList.tsx +6 -6
  152. package/src/editor/FieldListFieldWithFallbacks.tsx +9 -9
  153. package/src/editor/ImageEditor.tsx +2 -2
  154. package/src/editor/ItemInfo.tsx +4 -4
  155. package/src/editor/MainLayout.tsx +3 -4
  156. package/src/editor/Titlebar.tsx +4 -4
  157. package/src/editor/ai/AiTerminal.tsx +31 -24
  158. package/src/editor/client/EditorClient.tsx +106 -57
  159. package/src/editor/client/editContext.ts +13 -4
  160. package/src/editor/client/operations.ts +162 -23
  161. package/src/editor/client/pageModelBuilder.ts +26 -18
  162. package/src/editor/commands/componentCommands.tsx +58 -39
  163. package/src/editor/component-designer/ComponentDesigner.tsx +1 -1
  164. package/src/editor/componentTreeHelper.tsx +3 -2
  165. package/src/editor/control-center/ControlCenterMenu.tsx +4 -4
  166. package/src/editor/field-types/TreeListEditor.tsx +11 -11
  167. package/src/editor/menubar/LanguageSelector.tsx +6 -6
  168. package/src/editor/menubar/PageSelector.tsx +11 -11
  169. package/src/editor/menubar/PageViewerControls.tsx +49 -23
  170. package/src/editor/menubar/Separator.tsx +2 -2
  171. package/src/editor/menubar/VersionSelector.tsx +1 -1
  172. package/src/editor/page-editor-chrome/FrameMenu.tsx +94 -29
  173. package/src/editor/page-editor-chrome/FrameMenus.tsx +6 -6
  174. package/src/editor/page-editor-chrome/InlineEditor.tsx +237 -26
  175. package/src/editor/page-editor-chrome/PageEditorChrome.tsx +11 -14
  176. package/src/editor/page-editor-chrome/PlaceholderDropZone.tsx +12 -15
  177. package/src/editor/page-editor-chrome/PlaceholderDropZones.tsx +159 -68
  178. package/src/editor/page-viewer/EditorForm.tsx +15 -9
  179. package/src/editor/page-viewer/MiniMap.tsx +4 -4
  180. package/src/editor/page-viewer/PageViewer.tsx +6 -6
  181. package/src/editor/page-viewer/PageViewerFrame.tsx +146 -309
  182. package/src/editor/page-viewer/pageModelBuilder.ts +412 -0
  183. package/src/editor/pageModel.ts +5 -0
  184. package/src/editor/reviews/Comments.tsx +56 -15
  185. package/src/editor/reviews/DiffView.tsx +109 -0
  186. package/src/editor/reviews/SuggestedEdit.tsx +316 -0
  187. package/src/editor/services/suggestedEditsService.ts +39 -0
  188. package/src/editor/sidebar/ComponentPalette.tsx +108 -106
  189. package/src/editor/sidebar/ComponentTree.tsx +10 -5
  190. package/src/editor/sidebar/MainContentTree.tsx +1 -1
  191. package/src/editor/sidebar/SidebarView.tsx +9 -9
  192. package/src/editor/ui/CopyToClipboardButton.tsx +2 -1
  193. package/src/editor/ui/Icons.tsx +0 -18
  194. package/src/editor/ui/PerfectTree.tsx +5 -5
  195. package/src/editor/ui/Section.tsx +4 -4
  196. package/src/editor/ui/SimpleIconButton.tsx +5 -3
  197. package/src/editor/ui/SimpleMenu.tsx +5 -13
  198. package/src/editor/utils.ts +74 -17
  199. package/src/editor/views/CompareView.tsx +13 -24
  200. package/src/editor/views/EditView.tsx +2 -2
  201. package/src/editor/views/SingleEditView.tsx +3 -3
  202. package/src/lib/safelist.tsx +4 -0
  203. package/src/page-wizard/steps/BuildPageStep.tsx +18 -25
  204. package/src/page-wizard/steps/CreatePageAndLayoutStep.tsx +16 -18
  205. package/src/splash-screen/SplashScreen.tsx +0 -1
  206. package/src/types.ts +20 -3
  207. 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";
@@ -51,7 +50,7 @@ import { ItemLanguageVersion } from "../editor/menubar/ItemLanguageVersion";
51
50
  import { ActiveUsers } from "../editor/menubar/ActiveUsers";
52
51
  import { Validation } from "../editor/sidebar/Validation";
53
52
  import { Separator } from "../editor/menubar/Separator";
54
- import { Field, FieldButton, FullItem } from "../editor/pageModel";
53
+ import { FullItem } from "../editor/pageModel";
55
54
  import { LinkValue } from "../editor/fieldTypes";
56
55
  import {
57
56
  deleteItemCommand,
@@ -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,
@@ -388,7 +388,7 @@ export const getConfiguration = (): EditorConfiguration => {
388
388
  {
389
389
  name: "comments",
390
390
  icon: "pi pi-comments",
391
- title: "Comments",
391
+ title: "Comments & Suggestions",
392
392
  content: <Comments />,
393
393
  initialSize: 65,
394
394
  noOverflow: true,
@@ -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 type EditorWarningProps = {
11
11
 
12
12
  export function EditorWarnings({ item }: { item?: FullItem }) {
13
13
  var context = useEditContext();
14
- if (!context || context.previewMode) return;
14
+ if (!context || context.mode === "preview") return;
15
15
 
16
16
  if (!item) {
17
17
  item = context.page?.item;
@@ -26,7 +26,7 @@ export function EditorWarnings({ item }: { item?: FullItem }) {
26
26
  item,
27
27
  key: "warning" + i,
28
28
  editContext: context!,
29
- })
29
+ }),
30
30
  )}
31
31
  </div>
32
32
  );
@@ -46,7 +46,7 @@ export function FieldList({
46
46
 
47
47
  return (
48
48
  <div>
49
- <div className="sticky bg-gray-50 top-0 z-10 flex gap-2 border-y border-gray-200 items-center p-2 tour-field-list">
49
+ <div className="tour-field-list sticky top-0 z-10 ml-[1px] flex items-center gap-2 border-y border-gray-200 bg-gray-50 p-2">
50
50
  <i className="pi pi-search" />
51
51
  <div className="text-xs">Filter</div>
52
52
  <InputText
@@ -69,7 +69,7 @@ export function FieldList({
69
69
  checked={showStandardFields}
70
70
  onChange={(e: any) => setShowStandardFields(e.checked)}
71
71
  />{" "}
72
- <label htmlFor={uniqueId} className="text-xs cursor-pointer">
72
+ <label htmlFor={uniqueId} className="cursor-pointer text-xs">
73
73
  Show standard fields
74
74
  </label>
75
75
  </>
@@ -79,7 +79,7 @@ export function FieldList({
79
79
  {fields.map((itemFields, index) => (
80
80
  <Fragment key={index}>
81
81
  {itemFields.headline && (
82
- <div className="text-sm mt-2 py-2 border-b flex items-center gap-1">
82
+ <div className="mt-2 flex items-center gap-1 border-b py-2 text-sm">
83
83
  <i className="pi pi-angle-right" /> {itemFields.headline}
84
84
  </div>
85
85
  )}
@@ -133,7 +133,7 @@ function FieldListForSingleItem({
133
133
  fieldsArray = fieldsArray.filter(
134
134
  (x) =>
135
135
  x.name?.toLowerCase().includes(searchFilterLower) ||
136
- x.displayName?.toLowerCase().includes(searchFilterLower)
136
+ x.displayName?.toLowerCase().includes(searchFilterLower),
137
137
  );
138
138
  }
139
139
 
@@ -158,7 +158,7 @@ function FieldListForSingleItem({
158
158
  const sectionList: Field[][] = Object.values(sectionsGrouping);
159
159
  sectionList.sort(
160
160
  (a: Field[], b: Field[]) =>
161
- (a[0]?.sectionSortOrder || 0) - (b[0]?.sectionSortOrder || 0)
161
+ (a[0]?.sectionSortOrder || 0) - (b[0]?.sectionSortOrder || 0),
162
162
  );
163
163
 
164
164
  function getSectionFields(fields: Field[]) {
@@ -185,6 +185,6 @@ function FieldListForSingleItem({
185
185
  <Section key={section} title={section!}>
186
186
  {getSectionFields(sectionsGrouping[section!])}
187
187
  </Section>
188
- )
188
+ ),
189
189
  );
190
190
  }
@@ -50,17 +50,17 @@ export function FieldListFieldWithFallbacks({
50
50
  async function loadFallback() {
51
51
  if (!field?.fallbackChain || !editContext) return;
52
52
  await editContext.itemsRepository.getItems(
53
- field.fallbackChain?.map((x) => x.item)
53
+ field.fallbackChain?.map((x) => x.item),
54
54
  );
55
55
 
56
56
  setFallbackChain(
57
57
  (
58
58
  await Promise.all(
59
59
  field.fallbackChain.map((x) =>
60
- editContext.itemsRepository.getField(x)
61
- )
60
+ editContext.itemsRepository.getField(x),
61
+ ),
62
62
  )
63
- ).filter((x) => x) as Field[]
63
+ ).filter((x) => x) as Field[],
64
64
  );
65
65
  //const chain = await loadFallbackChain(field.descriptor);
66
66
 
@@ -142,12 +142,12 @@ export function FieldListFieldWithFallbacks({
142
142
 
143
143
  const showFallbackButton = field?.isFallback && (
144
144
  <button
145
- className="text-xs p-0"
145
+ className="p-0 text-xs"
146
146
  onClick={() => setShowFallback(!showFallback)}
147
147
  >
148
148
  <i
149
149
  className={
150
- "text-xs pi " + (showFallback ? "pi-check-square" : "pi-stop")
150
+ "pi text-xs " + (showFallback ? "pi-check-square" : "pi-stop")
151
151
  }
152
152
  />{" "}
153
153
  Fallback
@@ -163,7 +163,7 @@ export function FieldListFieldWithFallbacks({
163
163
  key={field.id}
164
164
  data-field-id={field.id}
165
165
  ref={ref}
166
- className="[&:not(:first-child)]:mt-4"
166
+ className="px-2 [&:not(:first-child)]:mt-4"
167
167
  onClickCapture={() => {
168
168
  editContext.setFocusedField(field.descriptor, field.canWrite || false);
169
169
  }}
@@ -183,8 +183,8 @@ export function FieldListFieldWithFallbacks({
183
183
  {fallbackChain &&
184
184
  fallbackChain.map((x, i) => (
185
185
  <div className="ml-3" key={i}>
186
- <div className="text-center mb-4">
187
- <i className="pi pi-arrow-up text-xl font-bold text-blue-300 fallback-arrow-animation relative top-3" />
186
+ <div className="mb-4 text-center">
187
+ <i className="pi pi-arrow-up fallback-arrow-animation relative top-3 text-xl font-bold text-blue-300" />
188
188
  </div>
189
189
  <FieldListField
190
190
  key={i}
@@ -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={() => {