@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
@@ -1,4 +1,4 @@
1
- import { useEditContext } from "../client/editContext";
1
+ import { useEditContext, EditorMode } from "../client/editContext";
2
2
  import { PageViewContext } from "../page-viewer/pageViewContext";
3
3
  import { InlineEditor } from "./InlineEditor";
4
4
  import { FieldActionsIndicators } from "./FieldActionIndicators";
@@ -12,11 +12,11 @@ import { CommentHighlightings } from "./CommentHighlightings";
12
12
 
13
13
  export function PageEditorChrome({
14
14
  iframe,
15
- mode,
15
+ compareView,
16
16
  pageViewContext,
17
17
  }: {
18
18
  iframe: HTMLIFrameElement;
19
- mode: "edit" | "compare" | "view";
19
+ compareView: boolean;
20
20
  pageViewContext: PageViewContext;
21
21
  }) {
22
22
  const editContext = useEditContext();
@@ -59,11 +59,11 @@ export function PageEditorChrome({
59
59
  const scale = pageViewContext.zoom;
60
60
  const x = Math.min(
61
61
  pageViewContext.viewport.width - 20,
62
- Math.max(20, insertingPosition.x * (scale || 1))
62
+ Math.max(20, insertingPosition.x * (scale || 1)),
63
63
  );
64
64
  const y = Math.min(
65
65
  pageViewContext.viewport.height - 20,
66
- Math.max(20, insertingPosition.y * (scale || 1))
66
+ Math.max(20, insertingPosition.y * (scale || 1)),
67
67
  );
68
68
 
69
69
  return {
@@ -79,10 +79,10 @@ export function PageEditorChrome({
79
79
 
80
80
  return (
81
81
  <>
82
- <FrameMenus mode={mode} pageViewContext={pageViewContext} />
82
+ <FrameMenus pageViewContext={pageViewContext} compareView={compareView} />
83
83
  <InlineEditor
84
- mode={mode === "edit" ? "edit" : "view"}
85
84
  pageViewContext={pageViewContext}
85
+ compareView={compareView}
86
86
  />
87
87
  <LockedFieldIndicator />
88
88
  <FieldActionsIndicators />
@@ -95,7 +95,7 @@ export function PageEditorChrome({
95
95
 
96
96
  <FieldEditedIndicators pageViewContext={pageViewContext} />
97
97
 
98
- {mode === "edit" && (
98
+ {editContext.mode === "edit" && (
99
99
  <>
100
100
  <PlaceholderDropZones
101
101
  iframe={pageViewContext?.editorIframeRef.current}
@@ -104,12 +104,9 @@ export function PageEditorChrome({
104
104
  <PictureEditorOverlay />
105
105
 
106
106
  {insertingStyle && (
107
- <div
108
- className="absolute flex h-8 w-8"
109
- style={insertingStyle}
110
- >
111
- <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75"></span>
112
- <span className="relative inline-flex rounded-full h-8 w-8 bg-sky-500"></span>
107
+ <div className="absolute flex h-8 w-8" style={insertingStyle}>
108
+ <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-sky-400 opacity-75"></span>
109
+ <span className="relative inline-flex h-8 w-8 rounded-full bg-sky-500"></span>
113
110
  </div>
114
111
  )}
115
112
  </>
@@ -47,7 +47,7 @@ export function PlaceholderDropZone({
47
47
  placeholder.key,
48
48
  index,
49
49
  spotPositionElement,
50
- spotPositionAnchor
50
+ spotPositionAnchor,
51
51
  );
52
52
  }
53
53
 
@@ -64,11 +64,10 @@ export function PlaceholderDropZone({
64
64
  if (isHovering) {
65
65
  editContext.setStatusMessage(
66
66
  <div>
67
- Drop into placeholder{" "}
68
- <span className="font-bold">{parentName}</span> /{" "}
69
- <span className="font-bold">{description || placeholder.name}</span>{" "}
67
+ Drop into placeholder <span className="font-bold">{parentName}</span>{" "}
68
+ / <span className="font-bold">{description || placeholder.name}</span>{" "}
70
69
  at position <span className="font-bold">{index + 1}</span>
71
- </div>
70
+ </div>,
72
71
  );
73
72
  } else {
74
73
  editContext.setStatusMessage("");
@@ -91,7 +90,7 @@ export function PlaceholderDropZone({
91
90
  // ? undefined
92
91
  // : placeholderKeyComponents[0];
93
92
  const insertOption = placeholder.insertOptions.find(
94
- (x) => x.typeId === editContext.selectedForInsertion
93
+ (x) => x.typeId === editContext.selectedForInsertion,
95
94
  );
96
95
  if (insertOption) {
97
96
  editContext!.droppedInPlaceholder(
@@ -99,7 +98,7 @@ export function PlaceholderDropZone({
99
98
  index,
100
99
  spotPositionElement,
101
100
  spotPositionAnchor,
102
- insertOption
101
+ insertOption,
103
102
  );
104
103
 
105
104
  return;
@@ -122,7 +121,7 @@ export function PlaceholderDropZone({
122
121
  editContext.operations.addComponent(
123
122
  x.typeId,
124
123
  placeholder.key,
125
- index
124
+ index,
126
125
  );
127
126
  },
128
127
  })) || ([] as MenuItem[]);
@@ -134,23 +133,21 @@ export function PlaceholderDropZone({
134
133
  disabled: true,
135
134
  className: "border-b border-gray-400 pb-2 pl-2",
136
135
  template: () => {
137
- return (
138
- <span className="text-black text-sm ">Insert</span>
139
- );
136
+ return <span className="text-sm text-black">Insert</span>;
140
137
  },
141
138
  },
142
139
  ...insertOptions,
143
140
  ]);
144
141
  e.preventDefault();
145
142
  }}
146
- className="placeholder cursor-pointer placeholder-dropzone"
143
+ className="placeholder placeholder-dropzone cursor-pointer"
147
144
  >
148
145
  <div
149
146
  className={classNames(
150
147
  isHovering
151
- ? "z-30 shadow-xl shadow-black w-20 h-20 shadow-blue-500/50"
152
- : "z-30 w-10 h-10 hover:scale-[1.1]",
153
- "transition-all duration-200 text-white text-center p-2 text-sm flex justify-center items-center bg-blue-500 rounded-full absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 test-ph-dropzone tour-placeholder-dropzone"
148
+ ? "z-30 h-20 w-20 shadow-xl shadow-black shadow-blue-500/50"
149
+ : "z-30 h-10 w-10 hover:scale-[1.1]",
150
+ "test-ph-dropzone tour-placeholder-dropzone absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-blue-500 p-2 text-center text-sm text-white opacity-100 transition-all duration-300 ease-in-out",
154
151
  )}
155
152
  data-testid="placeholder-dropzone-button"
156
153
  >
@@ -4,7 +4,7 @@ import { useEditContext } from "../client/editContext";
4
4
  import { getAllPlaceholders } from "../componentTreeHelper";
5
5
  import { findComponentRect } from "../utils";
6
6
  import { PlaceholderDropZone } from "./PlaceholderDropZone";
7
- import { Placeholder } from "../pageModel";
7
+ import { Placeholder, Component } from "../pageModel";
8
8
 
9
9
  export function PlaceholderDropZones({
10
10
  scale,
@@ -31,22 +31,31 @@ export function PlaceholderDropZones({
31
31
  )
32
32
  return null;
33
33
 
34
- const matchingPlaceholders = placeholders.filter(
35
- (x) =>
36
- x.parentComponent?.id === editContext.selectedForInsertion ||
37
- x.insertOptions?.find(
38
- (y) =>
39
- y.typeId === editContext.selectedForInsertion ||
40
- y.typeId === editContext.dragObject?.typeId ||
41
- y.typeId === editContext.dragObject?.templateId ||
42
- y.compatibleTemplates?.find(
43
- (z) => z == editContext.dragObject?.typeId
44
- ) !== undefined ||
45
- y.typeId === editContext.dragObject?.templateId ||
46
- y.compatibleTemplates?.find(
47
- (z) => z == editContext.dragObject?.templateId
48
- ) !== undefined
49
- )
34
+ const matchingPlaceholders = placeholders.filter((x) => {
35
+ // x.parentComponent?.id === editContext.selectedForInsertion ||
36
+ const matchingInsertOptions = x.insertOptions?.find(
37
+ (y) =>
38
+ // y.typeId === editContext.selectedForInsertion ||
39
+ y.typeId === editContext.dragObject?.typeId,
40
+ // ||
41
+ // y.typeId === editContext.dragObject?.templateId ||
42
+ // y.compatibleTypeIds?.find(
43
+ // (z) => z == editContext.dragObject?.typeId,
44
+ // ) !== undefined ||
45
+ // y.typeId === editContext.dragObject?.templateId ||
46
+ // y.compatibleTypeIds?.find(
47
+ // (z) => z == editContext.dragObject?.templateId,
48
+ // ) !== undefined,
49
+ );
50
+
51
+ return matchingInsertOptions !== undefined;
52
+ });
53
+
54
+ console.log(
55
+ "matching placeholders: ",
56
+ matchingPlaceholders,
57
+ editContext.selectedForInsertion,
58
+ editContext.dragObject,
50
59
  );
51
60
 
52
61
  if (!iframe) return;
@@ -65,10 +74,13 @@ export function PlaceholderDropZones({
65
74
  .documentElement.scrollHeight || 0;
66
75
 
67
76
  matchingPlaceholders.forEach((placeholder) => {
68
- const placeholderElement =
69
- iframe!.contentWindow?.document.body.querySelector(
70
- "[data-placeholder-start='" + placeholder.key + "']"
71
- );
77
+ let placeholderElement = iframe!.contentWindow?.document.body.querySelector(
78
+ "[data-placeholder-start='" + placeholder.key + "']",
79
+ );
80
+
81
+ if (!placeholderElement && placeholder.components.length > 0) {
82
+ placeholderElement = placeholder.components[0]?.firstDOMElement;
83
+ }
72
84
 
73
85
  if (!placeholderElement) return;
74
86
 
@@ -77,7 +89,13 @@ export function PlaceholderDropZones({
77
89
  const nextOrParent =
78
90
  getNextElement(placeholderElement) || placeholderElement.parentElement;
79
91
 
80
- const orientation = placeholderElement?.getAttribute("data-orientation");
92
+ let orientation = placeholderElement?.getAttribute("data-orientation");
93
+
94
+ if (!orientation)
95
+ orientation = detectOrientation(
96
+ placeholderElement,
97
+ placeholder.components,
98
+ );
81
99
 
82
100
  const rect = (prev ?? nextOrParent)!.getBoundingClientRect();
83
101
  const zoom = pageViewContext.zoom;
@@ -121,60 +139,81 @@ export function PlaceholderDropZones({
121
139
  description,
122
140
  });
123
141
 
124
- let nextElement = placeholderElement?.nextElementSibling;
125
- while (nextElement) {
126
- nextElement = nextElement?.nextElementSibling;
127
- if (nextElement) {
128
- if (
129
- nextElement.getAttribute("data-placeholder-end") === placeholder.key
130
- ) {
131
- break;
132
- }
142
+ placeholder.components.forEach((component) => {
143
+ const componentRect = findComponentRect(iframe, component);
144
+ if (!componentRect) return;
133
145
 
134
- if (nextElement.getAttribute("data-component-end")) {
135
- const componentRect = findComponentRect(
136
- iframe,
137
- (nextElement.getAttribute("data-component-end") ||
138
- nextElement.getAttribute("data-dropzone"))!
139
- );
140
- if (!componentRect) continue;
141
- const position = getPositionFromRect(
142
- componentRect.rect,
143
- pageViewContext.zoom,
144
- orientation
145
- );
146
- index++;
147
- zones.push({
148
- placeholder,
149
- position,
150
- index,
151
- anchor: orientation === "horizontal" ? "right" : "bottom",
152
- element: componentRect.elements[componentRect.elements.length - 1]!,
153
- });
154
- } else if (nextElement.getAttribute("data-dropzone")) {
155
- const rect = nextElement.getBoundingClientRect();
156
- const position = getPositionFromRect(rect, pageViewContext.zoom);
157
- index++;
158
- zones.push({
159
- placeholder,
160
- position,
161
- index,
162
- anchor: orientation === "horizontal" ? "left" : "top",
163
- element: nextElement,
164
- });
165
- }
166
- }
167
- }
146
+ const position = getPositionFromRect(
147
+ componentRect.rect,
148
+ pageViewContext.zoom,
149
+ orientation,
150
+ );
151
+
152
+ index++;
153
+
154
+ zones.push({
155
+ placeholder,
156
+ position,
157
+ index,
158
+ anchor: orientation === "horizontal" ? "right" : "bottom",
159
+ element: componentRect.elements[componentRect.elements.length - 1]!,
160
+ });
161
+ });
162
+
163
+ // let nextElement = placeholderElement?.nextElementSibling;
164
+ // while (nextElement) {
165
+ // nextElement = nextElement?.nextElementSibling;
166
+ // if (nextElement) {
167
+ // if (
168
+ // nextElement.getAttribute("data-placeholder-end") === placeholder.key
169
+ // ) {
170
+ // break;
171
+ // }
172
+
173
+ // if (nextElement.getAttribute("data-component-end")) {
174
+ // const componentRect = findComponentRect(
175
+ // iframe,
176
+ // (nextElement.getAttribute("data-component-end") ||
177
+ // nextElement.getAttribute("data-dropzone"))!,
178
+ // );
179
+ // if (!componentRect) continue;
180
+ // const position = getPositionFromRect(
181
+ // componentRect.rect,
182
+ // pageViewContext.zoom,
183
+ // orientation,
184
+ // );
185
+ // index++;
186
+ // zones.push({
187
+ // placeholder,
188
+ // position,
189
+ // index,
190
+ // anchor: orientation === "horizontal" ? "right" : "bottom",
191
+ // element: componentRect.elements[componentRect.elements.length - 1]!,
192
+ // });
193
+ // } else if (nextElement.getAttribute("data-dropzone")) {
194
+ // const rect = nextElement.getBoundingClientRect();
195
+ // const position = getPositionFromRect(rect, pageViewContext.zoom);
196
+ // index++;
197
+ // zones.push({
198
+ // placeholder,
199
+ // position,
200
+ // index,
201
+ // anchor: orientation === "horizontal" ? "left" : "top",
202
+ // element: nextElement,
203
+ // });
204
+ // }
205
+ // }
206
+ // }
168
207
  });
169
208
 
170
209
  return zones.map((zone, index) => {
171
210
  const x = Math.min(
172
211
  pageViewContext.viewport.width - 20,
173
- Math.max(20, zone.position.x * (scale || 1))
212
+ Math.max(20, zone.position.x * (scale || 1)),
174
213
  );
175
214
  const y = Math.min(
176
215
  scrollHeight - 20,
177
- Math.max(20 - pageViewContext.scroll, zone.position.y * (scale || 1))
216
+ Math.max(20 - pageViewContext.scroll, zone.position.y * (scale || 1)),
178
217
  );
179
218
 
180
219
  return (
@@ -216,7 +255,7 @@ function getNextElement(element: Element): Element | null {
216
255
  function getPositionFromRect(
217
256
  rect: { x: number; y: number; width: number; height: number },
218
257
  zoom: number,
219
- orientation?: string | null
258
+ orientation?: string | null,
220
259
  ) {
221
260
  const position =
222
261
  orientation === "horizontal"
@@ -231,3 +270,55 @@ function getPositionFromRect(
231
270
 
232
271
  return position;
233
272
  }
273
+
274
+ function detectOrientation(
275
+ placeholderElement: Element,
276
+ components: Component[],
277
+ ): "horizontal" | "vertical" {
278
+ // Check parent element for flex/grid direction
279
+ const parentElement = placeholderElement.parentElement;
280
+ if (parentElement) {
281
+ const parentStyle = window.getComputedStyle(parentElement);
282
+ const display = parentStyle.getPropertyValue("display");
283
+
284
+ // Check for flex direction
285
+ if (display === "flex" || display === "inline-flex") {
286
+ const flexDirection = parentStyle.getPropertyValue("flex-direction");
287
+ if (flexDirection === "row" || flexDirection === "row-reverse") {
288
+ return "horizontal";
289
+ }
290
+ if (flexDirection === "column" || flexDirection === "column-reverse") {
291
+ return "vertical";
292
+ }
293
+ }
294
+
295
+ // Check for grid layout
296
+ if (display === "grid" || display === "inline-grid") {
297
+ const gridAutoFlow = parentStyle.getPropertyValue("grid-auto-flow");
298
+ if (gridAutoFlow.includes("column")) {
299
+ return "horizontal";
300
+ }
301
+ if (gridAutoFlow.includes("row")) {
302
+ return "vertical";
303
+ }
304
+ }
305
+ }
306
+
307
+ // Analyze sibling positions if available
308
+ if (components.length > 1) {
309
+ const prevRect = components[0]?.firstDOMElement?.getBoundingClientRect();
310
+ const nextRect = components[1]?.firstDOMElement?.getBoundingClientRect();
311
+
312
+ if (!prevRect || !nextRect) return "horizontal";
313
+
314
+ // Compare the position differences
315
+ const horizontalDiff = Math.abs(nextRect.x - prevRect.x);
316
+ const verticalDiff = Math.abs(nextRect.y - prevRect.y);
317
+
318
+ // If horizontal difference is greater, it's likely a horizontal layout
319
+ return horizontalDiff > verticalDiff ? "horizontal" : "vertical";
320
+ }
321
+
322
+ // Default to vertical if we can't determine
323
+ return "vertical";
324
+ }
@@ -15,15 +15,18 @@ import { SimpleTabs, Tab } from "../ui/SimpleTabs";
15
15
  export function EditorForm({
16
16
  pageViewContext,
17
17
  readonly,
18
+ compareView,
18
19
  }: {
19
20
  pageViewContext?: PageViewContext;
20
21
  readonly?: boolean;
22
+ compareView: boolean;
21
23
  }) {
22
24
  const editContext = useEditContext()!;
23
25
  if (!pageViewContext) pageViewContext = editContext.pageView;
24
26
 
25
27
  const setInsertMode = editContext.setInsertMode;
26
- const insertMode = editContext.insertMode;
28
+ const insertMode =
29
+ editContext.insertMode && editContext.mode === "edit" && !compareView;
27
30
  const [activeTabKey, setActiveTabKey] = useState("content");
28
31
  const [item, setItem] = useState<RenderedItem>();
29
32
  const [component, setComponent] = useState<Component>();
@@ -32,8 +35,6 @@ export function EditorForm({
32
35
  if (insertMode) {
33
36
  setInsertMode(false);
34
37
  } else {
35
- // if (editContext.selection.length > 0)
36
- // editContext.setSelectedForInsertion(editContext.selection[0]);
37
38
  setInsertMode(true);
38
39
  }
39
40
  };
@@ -141,7 +142,7 @@ export function EditorForm({
141
142
  label: headline,
142
143
  content: (
143
144
  <div className="relative h-full">
144
- <div className="absolute inset-0 overflow-auto px-3">
145
+ <div className="absolute inset-0 overflow-auto">
145
146
  <FieldList
146
147
  fields={fields}
147
148
  validators={validators}
@@ -159,7 +160,7 @@ export function EditorForm({
159
160
  if (itemFields.length > 0)
160
161
  tabPanels.push(getFieldsTab(itemFields, "Content", "content"));
161
162
 
162
- //TODO: generalize this
163
+ //TODO: generalize thisdata-field-id
163
164
  if (editorFields) {
164
165
  Object.keys(editorFields).forEach((key) => {
165
166
  if (key !== "Content" && key !== "Design") {
@@ -181,7 +182,7 @@ export function EditorForm({
181
182
  label: "Advanced",
182
183
  content: (
183
184
  <div className="relative h-full">
184
- <div className="absolute inset-0 overflow-auto px-3">
185
+ <div className="absolute inset-0 overflow-auto">
185
186
  <ItemInfo item={item} />
186
187
  <FieldList
187
188
  fields={[{ fields: item.fields }]}
@@ -211,7 +212,7 @@ export function EditorForm({
211
212
  )}
212
213
  {editContext.selection.length === 0 && <div className="w-12" />}
213
214
  <div
214
- className="flex-1 text-center"
215
+ className="flex-1 text-center text-gray-800"
215
216
  id="item-name"
216
217
  data-testid="component-name"
217
218
  >
@@ -228,7 +229,12 @@ export function EditorForm({
228
229
  onClick={() => toggleInsertMode()}
229
230
  label={insertMode ? "Continue editing" : "Insert component"}
230
231
  size="large"
231
- disabled={!editContext.page?.item.canWriteItem || !item?.canWriteItem}
232
+ disabled={
233
+ !editContext.page?.item.canWriteItem ||
234
+ !item?.canWriteItem ||
235
+ editContext.mode !== "edit" ||
236
+ compareView
237
+ }
232
238
  />
233
239
  </h1>
234
240
 
@@ -237,7 +243,7 @@ export function EditorForm({
237
243
  <SimpleTabs
238
244
  key="editor-tabs"
239
245
  tabs={tabPanels}
240
- className="flex flex-1 items-center justify-center border-b border-gray-200 bg-gray-50 py-3 text-sm"
246
+ className="flex flex-1 items-center justify-center border-b border-gray-200 bg-gray-50 py-2.5 text-sm"
241
247
  activeTab={tabPanels.findIndex((x) => x.id === activeTabKey) || 0}
242
248
  setActiveTab={(index) => setActiveTabKey(tabPanels[index]?.id!)}
243
249
  ></SimpleTabs>
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef } from "react";
2
- import { useEditContext } from "../client/editContext";
2
+ import { useEditContext, EditorMode } from "../client/editContext";
3
3
  import { PlaceholderDropZones } from "../page-editor-chrome/PlaceholderDropZones";
4
4
  import { FieldEditedIndicators } from "../page-editor-chrome/FieldEditedIndicators";
5
5
  import { PageViewContext } from "./pageViewContext";
@@ -9,13 +9,13 @@ export function MiniMap({
9
9
  deviceHeight,
10
10
  scroll,
11
11
  mainViewIframeRef,
12
- mode,
12
+ compareView,
13
13
  pageViewContext,
14
14
  }: {
15
15
  deviceHeight?: number;
16
16
  scroll: number;
17
17
  mainViewIframeRef: React.RefObject<HTMLIFrameElement | null>;
18
- mode: "edit" | "compare" | "view";
18
+ compareView: boolean;
19
19
  pageViewContext: PageViewContext;
20
20
  }) {
21
21
  const editContext = useEditContext();
@@ -331,7 +331,7 @@ export function MiniMap({
331
331
  }}
332
332
  ></div>
333
333
  )}
334
- {mode === "edit" && (
334
+ {editContext.mode === "edit" && (
335
335
  <PlaceholderDropZones
336
336
  scale={scale}
337
337
  iframe={iframeRef.current}
@@ -5,19 +5,19 @@ import { PageViewerFrame } from "./PageViewerFrame";
5
5
  import { useEffect, useState } from "react";
6
6
  import { useRef } from "react";
7
7
  import { SimpleIconButton } from "../ui/SimpleIconButton";
8
- import { useEditContext } from "../client/editContext";
8
+ import { EditorMode, useEditContext } from "../client/editContext";
9
9
  import { useDebouncedCallback } from "use-debounce";
10
10
 
11
11
  export function PageViewer({
12
12
  pageViewContext,
13
13
  showFormEditor,
14
- mode,
14
+ compareView,
15
15
  name,
16
16
  followEditsDefault,
17
17
  }: {
18
18
  pageViewContext?: PageViewContext;
19
19
  showFormEditor: boolean;
20
- mode: "view" | "edit" | "compare";
20
+ compareView?: boolean;
21
21
  name: string;
22
22
  followEditsDefault?: boolean;
23
23
  }) {
@@ -26,7 +26,6 @@ export function PageViewer({
26
26
  const editContext = useEditContext();
27
27
 
28
28
  const [followEdits, setFollowEdits] = useState(followEditsDefault);
29
-
30
29
  const allotmentRef = useRef<AllotmentHandle>(null);
31
30
  const [formEditorWidth, setFormEditorWidth] = useState(0);
32
31
 
@@ -88,7 +87,8 @@ export function PageViewer({
88
87
  <div className="flex-1">
89
88
  <EditorForm
90
89
  pageViewContext={pageViewContext}
91
- readonly={mode !== "edit"}
90
+ readonly={editContext?.mode !== "edit"}
91
+ compareView={compareView || false}
92
92
  />
93
93
  </div>
94
94
  <div className="flex items-center justify-between gap-1 bg-gray-50 p-1">
@@ -107,7 +107,7 @@ export function PageViewer({
107
107
 
108
108
  panels.push(
109
109
  <PageViewerFrame
110
- mode={mode}
110
+ compareView={compareView || false}
111
111
  pageViewContext={pageViewContext}
112
112
  key="frame"
113
113
  />,