@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
@@ -24,18 +24,11 @@ import { loadFieldButtons } from "../services/editService";
24
24
  import { usePathname } from "next/navigation";
25
25
  import { EditorWarnings } from "../EditorWarnings";
26
26
 
27
- import {
28
- Component,
29
- PageSkeleton,
30
- ComponentSkeleton,
31
- PlaceholderSkeleton,
32
- RenderedItemSkeleton,
33
- ItemDescriptor,
34
- } from "../pageModel";
27
+ import { Component, ItemDescriptor } from "../pageModel";
35
28
  import { NoLayout } from "../page-editor-chrome/NoLayout";
36
29
  import { Spinner } from "../ui/Spinner";
37
30
  import { DeviceToolbar } from "./DeviceToolbar";
38
-
31
+ import { buildPageModel } from "./pageModelBuilder";
39
32
  declare global {
40
33
  interface Window {
41
34
  requestRefresh?: (newUri?: string) => boolean;
@@ -109,278 +102,6 @@ export function PageViewerFrame({
109
102
 
110
103
  updateMiniMapVisibility();
111
104
 
112
- function buildPageModel(iframeDocument: Document | undefined) {
113
- if (
114
- !iframeDocument ||
115
- !editContextRef.current ||
116
- !pageViewContextRef.current
117
- )
118
- return;
119
-
120
- const pageItemDescriptor = pageViewContextRef.current?.pageItemDescriptor;
121
-
122
- if (!pageItemDescriptor) return;
123
-
124
- const pageItem: RenderedItemSkeleton = {
125
- ...pageItemDescriptor,
126
- renderedFieldIds: [],
127
- };
128
-
129
- const start = performance.now();
130
-
131
- const treeWalker = iframeDocument.createTreeWalker(
132
- iframeDocument.documentElement, // Root node to start traversal
133
- NodeFilter.SHOW_ELEMENT, // Only show element nodes
134
- null, // Optional filter function, can be `null`
135
- );
136
-
137
- const root: ComponentSkeleton = {
138
- placeholders: [],
139
- id: "page",
140
- type: "Page",
141
- typeId: "",
142
- name: "Page",
143
- items: [pageItem],
144
- datasourceItem: pageItem,
145
- renderedDictionaryKeys: [],
146
- editorFields: {},
147
- };
148
-
149
- let currentComponent: ComponentSkeleton | undefined = root;
150
- let currentPlaceholder: undefined | PlaceholderSkeleton;
151
-
152
- while (treeWalker.nextNode()) {
153
- const node = treeWalker.currentNode;
154
-
155
- if (node.nodeType !== Node.ELEMENT_NODE) continue;
156
-
157
- const element = node as Element;
158
-
159
- if (currentComponent && element.hasAttribute("data-fieldid")) {
160
- const fieldId = element.getAttribute("data-fieldid")!;
161
-
162
- const language =
163
- element.getAttribute("data-language") ||
164
- currentComponent.datasourceItem?.language ||
165
- pageItem.language;
166
- const version = element.hasAttribute("data-version")
167
- ? parseInt(element.getAttribute("data-version")!)
168
- : currentComponent.datasourceItem?.version || pageItem.version;
169
- const itemId =
170
- element.getAttribute("data-itemid") ||
171
- currentComponent.datasourceItem?.id;
172
-
173
- if (!itemId) continue;
174
-
175
- let renderedItem = currentComponent.items.find(
176
- (x) =>
177
- x.id === itemId && x.language === language && x.version === version,
178
- );
179
-
180
- if (!renderedItem) {
181
- renderedItem = {
182
- id: itemId,
183
- language,
184
- version,
185
- renderedFieldIds: [],
186
- };
187
- currentComponent.items.push(renderedItem);
188
- }
189
-
190
- if (renderedItem.renderedFieldIds.indexOf(fieldId) === -1) {
191
- renderedItem.renderedFieldIds.push(fieldId);
192
- }
193
- }
194
-
195
- if (element.tagName === "SCRIPT") {
196
- const placeholderStartId = element.getAttribute(
197
- "data-placeholder-start",
198
- );
199
- const placeholderEndId = element.getAttribute("data-placeholder-end");
200
- const componentStartId = element.getAttribute("data-component-start");
201
- const componentEndId = element.getAttribute("data-component-end");
202
- const dictionaryKeyStart = element.getAttribute(
203
- "data-dictionary-key-start",
204
- );
205
- const editorGroup = element.getAttribute("data-editor-group");
206
-
207
- if (currentComponent && editorGroup) {
208
- let group = currentComponent.editorFields[editorGroup];
209
- if (!group) {
210
- group = {
211
- addFields: [],
212
- removeFields: [],
213
- };
214
- currentComponent.editorFields[editorGroup] = group;
215
- }
216
- const addFields = element.getAttribute("data-add-fields")?.split(",");
217
- const removeFields = element
218
- .getAttribute("data-remove-fields")
219
- ?.split(",");
220
-
221
- group.addFields = [...group.addFields, ...(addFields || [])];
222
- group.removeFields = [...group.removeFields, ...(removeFields || [])];
223
- }
224
-
225
- if (dictionaryKeyStart) {
226
- if (!currentComponent) {
227
- console.error(
228
- "Dictionary key without component:",
229
- dictionaryKeyStart,
230
- );
231
- } else {
232
- currentComponent.renderedDictionaryKeys.push(dictionaryKeyStart);
233
- }
234
- }
235
- if (placeholderStartId) {
236
- if (!currentComponent) {
237
- console.error(
238
- "Placeholder start without component:",
239
- placeholderStartId,
240
- "Current placeholder",
241
- currentPlaceholder,
242
- );
243
- } else {
244
- currentPlaceholder = currentComponent.placeholders.find(
245
- (x) => x.key === placeholderStartId,
246
- );
247
-
248
- if (!currentPlaceholder) {
249
- currentPlaceholder = {
250
- key: placeholderStartId,
251
- name:
252
- placeholderStartId.indexOf(currentComponent.id + "_") === 0
253
- ? placeholderStartId.substring(
254
- currentComponent.id.length + 1,
255
- )
256
- : placeholderStartId,
257
- description: "",
258
- components: [],
259
- parentComponent: currentComponent,
260
- };
261
-
262
- currentComponent.placeholders.push(currentPlaceholder);
263
- }
264
- currentComponent = undefined;
265
- }
266
- }
267
-
268
- if (placeholderEndId) {
269
- currentComponent = currentPlaceholder?.parentComponent;
270
- if (currentPlaceholder?.key !== placeholderEndId) {
271
- console.error(
272
- "Placeholder end does not match start",
273
- currentPlaceholder,
274
- placeholderEndId,
275
- );
276
- }
277
- currentPlaceholder = undefined;
278
- }
279
-
280
- if (componentStartId) {
281
- if (!currentPlaceholder) {
282
- if (!currentComponent) {
283
- console.error(
284
- "Component start without parent component:",
285
- componentStartId,
286
- );
287
- continue;
288
- }
289
-
290
- currentPlaceholder = {
291
- key: "implicit_" + componentStartId,
292
- name: "no-placeholder",
293
- description: "",
294
- components: [],
295
- parentComponent: currentComponent,
296
- };
297
- if (!currentComponent) {
298
- console.error(
299
- "Component start without placeholder or parent component",
300
- );
301
- } else {
302
- currentComponent.placeholders.push(currentPlaceholder);
303
- }
304
- }
305
- if (currentPlaceholder) {
306
- const language =
307
- element.getAttribute("data-language") || pageItem.language;
308
- const version = element.hasAttribute("data-version")
309
- ? parseInt(element.getAttribute("data-version")!)
310
- : pageItem.version;
311
-
312
- const itemId = element.getAttribute("data-itemid");
313
-
314
- const datasourceItem = itemId
315
- ? {
316
- id: itemId,
317
- language,
318
- version,
319
- renderedFieldIds: [],
320
- }
321
- : undefined;
322
-
323
- const layoutId = element.getAttribute("data-layoutid");
324
-
325
- currentComponent = currentPlaceholder.components.find(
326
- (x) => x.id === componentStartId,
327
- );
328
-
329
- if (!currentComponent) {
330
- currentComponent = {
331
- id: componentStartId,
332
- name: "",
333
- type: element.getAttribute("data-type") || "",
334
- typeId: element.getAttribute("data-typeid") || "",
335
- items: datasourceItem ? [datasourceItem] : [],
336
- placeholders: [],
337
- parentPlaceholder: currentPlaceholder,
338
- renderedDictionaryKeys: [],
339
- datasourceItem,
340
- layoutId: layoutId || undefined,
341
- editorFields: {},
342
- };
343
-
344
- currentPlaceholder.components.push(currentComponent);
345
- }
346
- currentPlaceholder = undefined;
347
- }
348
- }
349
-
350
- if (componentEndId) {
351
- if (!currentComponent || currentComponent.id !== componentEndId) {
352
- console.error(
353
- "Component end does not match start",
354
- currentComponent,
355
- componentEndId,
356
- );
357
-
358
- // Placeholder closed implicitly
359
- if (currentPlaceholder?.parentComponent.id === componentEndId) {
360
- currentComponent = currentPlaceholder.parentComponent;
361
- currentPlaceholder = undefined;
362
- }
363
- }
364
- currentPlaceholder = currentComponent?.parentPlaceholder;
365
-
366
- if (currentPlaceholder?.key.startsWith("implicit_")) {
367
- currentComponent = currentPlaceholder.parentComponent;
368
- } else currentComponent = undefined;
369
- }
370
- }
371
- }
372
-
373
- const page: PageSkeleton = {
374
- rootComponent: root,
375
- item: pageItem,
376
- editRevision: editContextRef.current?.revision ?? "",
377
- };
378
- const time = performance.now() - start;
379
-
380
- console.log("PAGE MODEL SKELETON", page, time);
381
- pageViewContextRef.current?.setPageSkeleton(page);
382
- }
383
-
384
105
  const buildPageModelThrottled = useThrottledCallback(buildPageModel, 1000);
385
106
 
386
107
  const [iframeSrc, setIframeSrc] = useState<string>();
@@ -401,10 +122,12 @@ export function PageViewerFrame({
401
122
  "sc_version",
402
123
  pageItemDescriptor.version.toString(),
403
124
  );
404
- renderUrl.searchParams.set(
405
- "sc_mode",
406
- editContext.previewMode ? "preview" : "edit",
407
- );
125
+ if (editContext.previewMode) {
126
+ renderUrl.searchParams.set("alpaca_preview", "1");
127
+ } else {
128
+ renderUrl.searchParams.set("alpaca_editor", "1");
129
+ }
130
+ renderUrl.searchParams.set("sc_mode", "edit");
408
131
  renderUrl.searchParams.set("alpaca_editor", "1");
409
132
  renderUrl.searchParams.set("sc_database", "master");
410
133
  //renderUrl.searchParams.set(
@@ -528,12 +251,22 @@ export function PageViewerFrame({
528
251
  const parser = new DOMParser();
529
252
  const newDoc = parser.parseFromString(text, "text/html");
530
253
  morphdom(doc.documentElement, newDoc.documentElement);
254
+ if ((iframeRef.current!.contentWindow as any).XA) {
255
+ console.log("init XA");
256
+ (iframeRef.current!.contentWindow as any).XA.init();
257
+ }
531
258
  setShowSpinner(false);
532
259
  }
533
260
 
534
- if (mode === "edit" && !editContext.previewMode) injectEditorCSS(doc);
261
+ if (mode === "edit" && !editContext.previewMode)
262
+ injectEditorCSS(doc, true);
263
+ else injectEditorCSS(doc, false);
264
+
265
+ setTimeout(() => {
266
+ injectSXAScripts(iframeRef.current!);
267
+ }, 1000);
535
268
 
536
- buildPageModel(doc);
269
+ buildPageModel(doc, editContextRef, pageViewContextRef);
537
270
  }
538
271
  };
539
272
 
@@ -544,12 +277,15 @@ export function PageViewerFrame({
544
277
  )
545
278
  return;
546
279
 
547
- const rect = findComponentRect(
548
- iframeRef.current!,
280
+ const component = getComponentById(
549
281
  editContext.scrollIntoView,
550
- true,
282
+ pageViewContextRef.current!.page!,
551
283
  );
552
284
 
285
+ if (!component) return;
286
+
287
+ const rect = findComponentRect(iframeRef.current!, component, true);
288
+
553
289
  if (!rect) return;
554
290
 
555
291
  // Check if element is already in viewport
@@ -633,7 +369,7 @@ export function PageViewerFrame({
633
369
  );
634
370
 
635
371
  editContextRef.current?.setSelectedRange({
636
- itemId: fieldId,
372
+ itemId: fieldElement.getAttribute("data-itemid") || "",
637
373
  fieldId: fieldId,
638
374
  startOffset: globalStartOffset,
639
375
  endOffset: globalEndOffset,
@@ -652,7 +388,8 @@ export function PageViewerFrame({
652
388
  if (editContextRef.current?.isRefreshing) return;
653
389
 
654
390
  const componentId = findParentComponentId(target);
655
- editContextRef.current?.setCurrentOverlay(undefined);
391
+ if (editContextRef.current?.currentOverlay)
392
+ editContextRef.current?.setCurrentOverlay(undefined);
656
393
 
657
394
  if (componentId) {
658
395
  if (event.ctrlKey) {
@@ -660,7 +397,9 @@ export function PageViewerFrame({
660
397
  if (currentSelection.indexOf(componentId) === -1)
661
398
  editContextRef.current?.select([...currentSelection, componentId]);
662
399
  } else {
663
- editContextRef.current?.select([componentId]);
400
+ if (editContextRef.current?.selection.indexOf(componentId) === -1) {
401
+ editContextRef.current?.select([componentId]);
402
+ }
664
403
  }
665
404
 
666
405
  // if (mode !== "edit") {
@@ -680,7 +419,10 @@ export function PageViewerFrame({
680
419
  );
681
420
  blockBlurEventRef.current = Date.now() + 500;
682
421
 
683
- if (hasLock) {
422
+ if (
423
+ hasLock &&
424
+ editContextRef.current?.inlineEditingFieldElement !== fieldElement
425
+ ) {
684
426
  editContextRef.current?.setInlineEditingFieldElement(fieldElement);
685
427
  }
686
428
  }
@@ -727,7 +469,6 @@ export function PageViewerFrame({
727
469
 
728
470
  if (componentId) {
729
471
  if (!editContextRef.current?.selection.includes(componentId)) {
730
- console.log("Selecting component CONTEXT MENU", componentId);
731
472
  editContextRef.current!.select([componentId]);
732
473
  }
733
474
  }
@@ -837,7 +578,11 @@ export function PageViewerFrame({
837
578
  ),
838
579
  )
839
580
  ) {
840
- buildPageModelThrottled(iframeDocument);
581
+ buildPageModelThrottled(
582
+ iframeDocument,
583
+ editContextRef,
584
+ pageViewContextRef,
585
+ );
841
586
  }
842
587
  });
843
588
 
@@ -849,7 +594,7 @@ export function PageViewerFrame({
849
594
  //attributes: true, // observe attribute changes (like style or class)
850
595
  });
851
596
 
852
- buildPageModel(iframeDocument);
597
+ buildPageModel(iframeDocument, editContextRef, pageViewContextRef);
853
598
  }
854
599
  };
855
600
 
@@ -980,24 +725,110 @@ export function PageViewerFrame({
980
725
  );
981
726
  }
982
727
 
983
- export function injectEditorCSS(iframeDocument: Document) {
728
+ function injectEditorCSS(iframeDocument: Document, editMode: boolean) {
984
729
  if (!iframeDocument) return;
985
730
  const style = iframeDocument.createElement("style");
986
- style.textContent = `[contentEditable]:empty:before {
731
+ style.textContent = editMode
732
+ ? `[contentEditable]:empty:before {
987
733
  content: attr(placeholder);
988
734
  opacity: 0.6;
989
735
  }
990
736
 
737
+ .scChromeData, code {
738
+ display: none;
739
+ }
740
+
991
741
  [contenteditable] {
992
742
  outline: 0px solid transparent;
993
743
  }
994
- `;
744
+ `
745
+ : `
746
+ .scChromeData, code {
747
+ display: none;
748
+ }
749
+ `;
995
750
 
996
751
  if (iframeDocument && iframeDocument.head) {
997
752
  iframeDocument.head.appendChild(style);
998
753
  }
999
754
  }
1000
755
 
756
+ function injectSXAScripts(iframe: HTMLIFrameElement): void {
757
+ if (!iframe) return;
758
+ const iframeDocument = iframe.contentDocument;
759
+ const iframeWindow = iframe.contentWindow as any;
760
+ if (!iframeDocument || !iframeWindow) return;
761
+
762
+ iframeWindow.Sitecore = {
763
+ PageModes: {
764
+ HoverFrame: {
765
+ extend: () => {
766
+ // console.log("extend hoverframe");
767
+ },
768
+ },
769
+ ChromeManager: {
770
+ chromes: () => {
771
+ // console.log("chromes");
772
+ return [];
773
+ },
774
+ resetChromes: () => {
775
+ // console.log("resetChromes");
776
+ iframeWindow.XA.init();
777
+ },
778
+ chromesReseted: {
779
+ observe: () => {
780
+ // console.log("chromesReseted.observe");
781
+ },
782
+ },
783
+ // Dummy selectionChanged with an _callbacks array
784
+ selectionChanged: {
785
+ _callbacks: [] as any[],
786
+ // Optionally, you can add a method to trigger all callbacks if needed.
787
+ trigger: function (...args: any[]): void {
788
+ this._callbacks.forEach((callback: Function) => callback(...args));
789
+ },
790
+ },
791
+ },
792
+
793
+ ChromeControls: function () {},
794
+ ChromeTypes: {
795
+ PlaceholderSorting: function () {},
796
+ Rendering: function () {},
797
+ },
798
+ },
799
+ };
800
+
801
+ // Option 1: Use main window's jQuery if available.
802
+ if (iframeWindow.jQuery) {
803
+ // Be cautious: if the iframe's document is different, it's better to load jQuery within the iframe.
804
+ iframeWindow.$sc = iframeWindow.jQuery;
805
+ } else {
806
+ // Option 2: Dynamically load jQuery in the iframe.
807
+ const jqueryScript = iframeDocument.createElement("script");
808
+ jqueryScript.type = "text/javascript";
809
+ jqueryScript.src = "https://code.jquery.com/jquery-3.6.0.min.js"; // Use the version you prefer.
810
+ jqueryScript.onload = () => {
811
+ // Once loaded, assign it to $sc using noConflict to avoid global collisions.
812
+ iframeWindow.$sc = iframeWindow.jQuery.noConflict();
813
+ // console.log("jQuery loaded in iframe and assigned to $sc");
814
+ };
815
+ (iframeDocument.head || iframeDocument.body).appendChild(jqueryScript);
816
+ }
817
+
818
+ // Add a dummy implementation for renderExpandCommand on the ChromeControls prototype.
819
+ iframeWindow.Sitecore.PageModes.ChromeControls.prototype.renderExpandCommand =
820
+ function () {
821
+ console.log("renderExpandCommand called");
822
+ // Return a dummy value if needed. For example, you might return a dummy HTML string.
823
+ return "<div>Dummy Expand Command</div>";
824
+ };
825
+
826
+ iframeWindow.Sitecore.PageModes.ChromeTypes.PlaceholderSorting.prototype.insertSortingHandle =
827
+ function () {
828
+ console.log("insertSortingHandle called");
829
+ };
830
+ }
831
+
1001
832
  /**
1002
833
  * Calculates the global offset of a given target node and its local offset,
1003
834
  * relative to the container's complete text content.