@alpaca-editor/core 1.0.3883 → 1.0.3885

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 (41) hide show
  1. package/dist/editor/MainLayout.js +7 -3
  2. package/dist/editor/MainLayout.js.map +1 -1
  3. package/dist/editor/MobileLayout.js +4 -2
  4. package/dist/editor/MobileLayout.js.map +1 -1
  5. package/dist/editor/Terminal.js +2 -2
  6. package/dist/editor/Terminal.js.map +1 -1
  7. package/dist/editor/ai/AiTerminal.js +0 -1
  8. package/dist/editor/ai/AiTerminal.js.map +1 -1
  9. package/dist/editor/client/EditorClient.js +1 -1
  10. package/dist/editor/client/EditorClient.js.map +1 -1
  11. package/dist/editor/page-editor-chrome/CommentHighlighting.js +28 -16
  12. package/dist/editor/page-editor-chrome/CommentHighlighting.js.map +1 -1
  13. package/dist/editor/page-viewer/PageViewerFrame.js +2 -2
  14. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  15. package/dist/editor/sidebar/Translations.js +1 -1
  16. package/dist/editor/sidebar/Translations.js.map +1 -1
  17. package/dist/editor/sidebar/ViewSelector.js.map +1 -1
  18. package/dist/editor/ui/PerfectTree.js +0 -1
  19. package/dist/editor/ui/PerfectTree.js.map +1 -1
  20. package/dist/editor/ui/Splitter.d.ts +1 -0
  21. package/dist/editor/ui/Splitter.js +6 -5
  22. package/dist/editor/ui/Splitter.js.map +1 -1
  23. package/dist/editor/utils.js +0 -7
  24. package/dist/editor/utils.js.map +1 -1
  25. package/dist/revision.d.ts +2 -2
  26. package/dist/revision.js +2 -2
  27. package/dist/styles.css +33 -0
  28. package/package.json +1 -1
  29. package/src/editor/MainLayout.tsx +20 -13
  30. package/src/editor/MobileLayout.tsx +19 -7
  31. package/src/editor/Terminal.tsx +15 -15
  32. package/src/editor/ai/AiTerminal.tsx +0 -2
  33. package/src/editor/client/EditorClient.tsx +1 -1
  34. package/src/editor/page-editor-chrome/CommentHighlighting.tsx +41 -25
  35. package/src/editor/page-viewer/PageViewerFrame.tsx +6 -2
  36. package/src/editor/sidebar/Translations.tsx +1 -1
  37. package/src/editor/sidebar/ViewSelector.tsx +0 -9
  38. package/src/editor/ui/PerfectTree.tsx +0 -1
  39. package/src/editor/ui/Splitter.tsx +11 -11
  40. package/src/editor/utils.ts +0 -8
  41. package/src/revision.ts +2 -2
@@ -19,7 +19,7 @@ export const Terminal = forwardRef<
19
19
  {
20
20
  commandHandler: (
21
21
  text: string,
22
- callback: (text: React.ReactNode, finished: boolean) => void
22
+ callback: (text: React.ReactNode, finished: boolean) => void,
23
23
  ) => void;
24
24
  prompt: string;
25
25
  setPrompt: (text: string) => void;
@@ -51,7 +51,7 @@ export const Terminal = forwardRef<
51
51
  const [promptHistory, setPromptHistory] = useState<string[]>(() => {
52
52
  if (typeof window !== "undefined") {
53
53
  return JSON.parse(
54
- localStorage.getItem("editor.ai.promptHistory") || "[]"
54
+ localStorage.getItem("editor.ai.promptHistory") || "[]",
55
55
  );
56
56
  }
57
57
  return [];
@@ -61,7 +61,7 @@ export const Terminal = forwardRef<
61
61
  useEffect(() => {
62
62
  localStorage.setItem(
63
63
  "editor.ai.promptHistory",
64
- JSON.stringify(promptHistory)
64
+ JSON.stringify(promptHistory),
65
65
  );
66
66
  }, [promptHistory]);
67
67
 
@@ -153,20 +153,20 @@ export const Terminal = forwardRef<
153
153
  }));
154
154
 
155
155
  return (
156
- <div className={classNames("flex flex-col h-full", className)}>
157
- <div className="p-1 border-b border-gray-200 flex justify-between gap-2 text-xs items-center">
156
+ <div className={classNames("flex h-full flex-col", className)}>
157
+ <div className="flex items-center justify-between gap-2 border-b border-gray-200 p-1 text-xs">
158
158
  <button
159
159
  onClick={() => {
160
160
  setMessages([]);
161
161
  onReset();
162
162
  }}
163
163
  >
164
- <i className="pi pi-trash text-sm m-1" />
164
+ <i className="pi pi-trash m-1 text-sm" />
165
165
  </button>
166
166
  {toolbar}
167
167
  </div>
168
- <div className="overflow-y-auto h-full overflow-x-hidden p-2">
169
- <div className="flex flex-col gap-3 items-end select-text">
168
+ <div className="h-full overflow-x-hidden overflow-y-auto p-2">
169
+ <div className="flex flex-col items-end gap-3 select-text">
170
170
  {messages.map((m, i) => (
171
171
  <div key={i} className={getClasses(m)}>
172
172
  {m.text}
@@ -175,11 +175,11 @@ export const Terminal = forwardRef<
175
175
 
176
176
  {response != null && (
177
177
  <div className={responseBoxClasses}>
178
- <div className="flex text-xs">
179
- <div className="text-xs mr-4">
180
- <i className="pi pi-spin pi-spinner"></i>{" "}
181
- </div>
182
- {response}
178
+ <div className="flex text-xs">{response}</div>
179
+ <div className="mr-4 flex items-center justify-end space-x-1 text-xs text-gray-400">
180
+ <div className="h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.3s]"></div>
181
+ <div className="h-1 w-1 animate-bounce rounded-full bg-gray-400 [animation-delay:-0.15s]"></div>
182
+ <div className="h-1 w-1 animate-bounce rounded-full bg-gray-400"></div>
183
183
  </div>
184
184
  </div>
185
185
  )}
@@ -191,14 +191,14 @@ export const Terminal = forwardRef<
191
191
  <InputTextarea
192
192
  ref={inputRef}
193
193
  value={prompt}
194
- className="border-gray-300 border rounded flex-1 text-xs resize-none self-stretch"
194
+ className="flex-1 resize-none self-stretch rounded border border-gray-300 text-xs"
195
195
  onKeyDown={handleKeyPress}
196
196
  onChange={(e) => setPrompt(e.target.value)}
197
197
  rows={4}
198
198
  cols={30}
199
199
  disabled={disabled}
200
200
  />
201
- <div className="flex justify-between items-center py-1">
201
+ <div className="flex items-center justify-between py-1">
202
202
  {statusbar}
203
203
  <Button
204
204
  icon={"pi pi-send"}
@@ -211,8 +211,6 @@ export function AiTerminal({
211
211
  ...newMessages,
212
212
  ];
213
213
 
214
- console.log(messages);
215
-
216
214
  const response = await executePrompt(
217
215
  activeProfile.id,
218
216
  messages,
@@ -438,7 +438,7 @@ export function EditorClient({
438
438
 
439
439
  if (message.type === "comment-deleted") {
440
440
  setComments((x) => {
441
- return x.filter((c) => c.id !== message.payload.id);
441
+ return x.filter((c) => c.id !== message.payload.commentId);
442
442
  });
443
443
  }
444
444
 
@@ -2,12 +2,13 @@ import {
2
2
  useEditContext,
3
3
  useModifiedFieldsContext,
4
4
  } from "../client/editContext";
5
- import { findFieldElement } from "../utils";
5
+ import { findComponentRect, findFieldElement } from "../utils";
6
6
  import { Comment } from "../../types";
7
7
  import { useState } from "react";
8
8
  import { useEffect } from "react";
9
9
  import { classNames } from "primereact/utils";
10
10
  import { CommentIcon } from "../ui/Icons";
11
+ import { getComponentById } from "../componentTreeHelper";
11
12
 
12
13
  export function CommentHighlighting({
13
14
  comment,
@@ -73,22 +74,21 @@ export function CommentHighlighting({
73
74
 
74
75
  if (!editContext) return null;
75
76
 
76
- if (!comment.fieldId) return null;
77
-
78
- const fieldElement = findFieldElement(iframe, {
79
- item: {
80
- id: comment.itemId,
81
- language: comment.language,
82
- version: comment.version,
83
- },
84
- fieldId: comment.fieldId,
85
- });
86
-
87
- if (!fieldElement) return null;
77
+ const fieldElement = comment.fieldId
78
+ ? findFieldElement(iframe, {
79
+ item: {
80
+ id: comment.itemId,
81
+ language: comment.language,
82
+ version: comment.version,
83
+ },
84
+ fieldId: comment.fieldId,
85
+ })
86
+ : undefined;
88
87
 
89
88
  let rects: DOMRectList | null = null;
89
+ let isTextRange = false;
90
90
 
91
- if (range[0] !== undefined && range[1] !== undefined) {
91
+ if (fieldElement && range[0] !== undefined && range[1] !== undefined) {
92
92
  const startData = getTextNodeAtOffset(fieldElement, range[0]);
93
93
  const endData = getTextNodeAtOffset(fieldElement, range[1]);
94
94
 
@@ -97,11 +97,25 @@ export function CommentHighlighting({
97
97
  textRange.setStart(startData.node, startData.offset);
98
98
  textRange.setEnd(endData.node, endData.offset);
99
99
  rects = textRange.getClientRects();
100
+ isTextRange = true;
100
101
  }
101
102
  }
102
103
 
103
104
  if (!rects || rects.length === 0) {
104
- const fallbackRect = fieldElement.getBoundingClientRect();
105
+ let fallbackElement = fieldElement;
106
+ if (!fallbackElement && comment.itemId && editContext.page) {
107
+ const componentStart = iframe.contentWindow?.document.body.querySelector(
108
+ "[data-component-start='" + comment.itemId + "']",
109
+ );
110
+
111
+ fallbackElement = componentStart?.nextElementSibling;
112
+ while (fallbackElement && fallbackElement.tagName === "SCRIPT") {
113
+ fallbackElement = fallbackElement.nextElementSibling;
114
+ }
115
+ }
116
+ if (!fallbackElement) return null;
117
+ const fallbackRect = fallbackElement.getBoundingClientRect();
118
+ if (!fallbackRect) return null;
105
119
  rects = {
106
120
  length: 1,
107
121
  0: fallbackRect,
@@ -146,16 +160,18 @@ export function CommentHighlighting({
146
160
  <CommentIcon className="text-blue-500 hover:text-blue-600" />
147
161
  </div>
148
162
  )}
149
- <div
150
- className="opacity-45"
151
- style={{
152
- width: "100%",
153
- height: "100%",
154
- backgroundColor: comment.isResolved
155
- ? "rgba(0, 255, 0, 0.45)"
156
- : "rgba(255, 0, 0, 0.45)",
157
- }}
158
- ></div>
163
+ {isTextRange && (
164
+ <div
165
+ className="opacity-45"
166
+ style={{
167
+ width: "100%",
168
+ height: "100%",
169
+ backgroundColor: comment.isResolved
170
+ ? "rgba(0, 255, 0, 0.45)"
171
+ : "rgba(255, 0, 0, 0.45)",
172
+ }}
173
+ ></div>
174
+ )}
159
175
  </div>
160
176
  ))}
161
177
  </>
@@ -273,7 +273,7 @@ export function PageViewerFrame({
273
273
  injectSXAScripts(iframeRef.current!);
274
274
  }, 1000);
275
275
 
276
- buildPageModelSkeleton(doc, editContextRef, pageViewContextRef);
276
+ buildPageModelThrottled(doc, editContextRef, pageViewContextRef);
277
277
  }
278
278
  };
279
279
 
@@ -604,7 +604,11 @@ export function PageViewerFrame({
604
604
  //attributes: true, // observe attribute changes (like style or class)
605
605
  });
606
606
 
607
- //buildPageModel(iframeDocument, editContextRef, pageViewContextRef);
607
+ buildPageModelThrottled(
608
+ iframeDocument,
609
+ editContextRef,
610
+ pageViewContextRef,
611
+ );
608
612
  }
609
613
  };
610
614
 
@@ -68,7 +68,7 @@ export function Translation() {
68
68
  return (
69
69
  <div
70
70
  key={language.languageCode}
71
- className="flex gap-2"
71
+ className="flex items-center gap-2"
72
72
  onClick={() => selectLanguage(language)}
73
73
  >
74
74
  <img src={language.icon} className="h-5" /> {language.name}
@@ -46,15 +46,6 @@ export function ViewSelector() {
46
46
  )}
47
47
  </div>
48
48
  ))}
49
- {/* <div
50
- title="Tour"
51
- className={
52
- "text-gray-400 hover:text-gray-900 cursor-pointer p-3"
53
- }
54
- onClick={() => editContext!.startTour()}
55
- >
56
- <i className="pi pi-question-circle text-xl" />
57
- </div> */}
58
49
  </div>
59
50
  );
60
51
  }
@@ -105,7 +105,6 @@ const DropZone = memo(
105
105
  if (isDragging) {
106
106
  if (isValidDropZone) {
107
107
  const isValid = isValidDropZone(parent, index);
108
- console.log("CHECK RESULT", parent, index, isValid);
109
108
  setIsValidDrop(isValid);
110
109
  } else {
111
110
  setIsValidDrop(false);
@@ -5,6 +5,7 @@ export type SplitterPanel = {
5
5
  name: string;
6
6
  content: React.ReactNode;
7
7
  collapsible?: boolean;
8
+ hidden?: boolean;
8
9
  };
9
10
 
10
11
  interface SplitterProps {
@@ -155,7 +156,7 @@ export const Splitter: React.FC<SplitterProps> = ({
155
156
  document.addEventListener("mousemove", onMouseMove);
156
157
  document.addEventListener("mouseup", onMouseUp, true);
157
158
  },
158
- [panels, panelSizes]
159
+ [panels, panelSizes],
159
160
  );
160
161
 
161
162
  const isLastResizer = (index: number) => index === panels.length - 2;
@@ -184,7 +185,7 @@ export const Splitter: React.FC<SplitterProps> = ({
184
185
  return (
185
186
  <div
186
187
  onClick={!isResizing ? toggleLastPanelCollapse : undefined}
187
- className="select-none p-1 bg-gray-200 flex items-center justify-center text-gray-500 hover:bg-blue-700 hover:text-white cursor-pointer"
188
+ className="flex cursor-pointer items-center justify-center bg-gray-200 p-1 text-gray-500 select-none hover:bg-blue-700 hover:text-white"
188
189
  style={{ writingMode: "vertical-rl", userSelect: "none" }}
189
190
  >
190
191
  {expandLabel}
@@ -200,7 +201,7 @@ export const Splitter: React.FC<SplitterProps> = ({
200
201
  return (
201
202
  <div
202
203
  className={
203
- " bg-gray-200 cursor-ew-resize select-none flex items-center justify-center hover:bg-blue-700 w-[4px] relative z-1000"
204
+ "relative z-1000 flex w-[4px] cursor-ew-resize items-center justify-center bg-gray-200 select-none hover:bg-blue-700"
204
205
  }
205
206
  onDoubleClick={
206
207
  isLastResizer(index) ? toggleLastPanelCollapse : undefined
@@ -213,10 +214,7 @@ export const Splitter: React.FC<SplitterProps> = ({
213
214
  };
214
215
 
215
216
  return (
216
- <div
217
- className="flex w-full h-full overflow-hidden"
218
- ref={splitterRef}
219
- >
217
+ <div className="flex h-full w-full overflow-hidden" ref={splitterRef}>
220
218
  {panels.map((panel, index) => (
221
219
  <React.Fragment key={panel.name}>
222
220
  <div
@@ -226,13 +224,15 @@ export const Splitter: React.FC<SplitterProps> = ({
226
224
  className="relative"
227
225
  style={{
228
226
  flex: `${panel.defaultSize === "auto" ? 1 : 0} 1 ${getFlexBasis(
229
- index
227
+ index,
230
228
  )}`,
229
+
231
230
  minWidth: 0,
232
231
  display:
233
- panel.collapsible &&
234
- isLastPanelCollapsed &&
235
- index === totalPanels - 1
232
+ (panel.collapsible &&
233
+ isLastPanelCollapsed &&
234
+ index === totalPanels - 1) ||
235
+ panel.hidden
236
236
  ? "none"
237
237
  : "block",
238
238
  }}
@@ -319,14 +319,6 @@ export function findComponentRect(
319
319
  const elements =
320
320
  startElement === endElement ? [startElement] : [startElement, endElement];
321
321
 
322
- // console.log(
323
- // "start rect",
324
- // startRect,
325
- // startElement,
326
- // iframe.contentWindow?.scrollY,
327
- // takeScrollPositionIntoAccount
328
- // );
329
-
330
322
  return {
331
323
  rect: {
332
324
  x: startRect.x,
package/src/revision.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = "1.0.3883";
2
- export const buildDate = "2025-05-20 09:23:06";
1
+ export const version = "1.0.3885";
2
+ export const buildDate = "2025-05-20 13:49:48";