@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
@@ -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
+ }