@alpaca-editor/core 1.0.4064 → 1.0.4065

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 (49) hide show
  1. package/dist/editor/ContextMenu.js +0 -2
  2. package/dist/editor/ContextMenu.js.map +1 -1
  3. package/dist/editor/ai/Agents.js +33 -8
  4. package/dist/editor/ai/Agents.js.map +1 -1
  5. package/dist/editor/client/EditorClient.js +17 -19
  6. package/dist/editor/client/EditorClient.js.map +1 -1
  7. package/dist/editor/client/editContext.d.ts +2 -2
  8. package/dist/editor/client/operations.js +9 -6
  9. package/dist/editor/client/operations.js.map +1 -1
  10. package/dist/editor/commands/componentCommands.js +1 -1
  11. package/dist/editor/field-types/richtext/contextMenuFactory.js +0 -3
  12. package/dist/editor/field-types/richtext/contextMenuFactory.js.map +1 -1
  13. package/dist/editor/menubar/ToolbarFactory.js +5 -2
  14. package/dist/editor/menubar/ToolbarFactory.js.map +1 -1
  15. package/dist/editor/menubar/toolbar-sections/UtilityControls.js +1 -1
  16. package/dist/editor/menubar/toolbar-sections/UtilityControls.js.map +1 -1
  17. package/dist/editor/page-viewer/PageViewerFrame.js +70 -4
  18. package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
  19. package/dist/editor/reviews/CommentEditor.js +2 -2
  20. package/dist/editor/reviews/CommentEditor.js.map +1 -1
  21. package/dist/editor/reviews/Reviews.js +2 -2
  22. package/dist/editor/reviews/Reviews.js.map +1 -1
  23. package/dist/editor/sidebar/ComponentTree.js +157 -49
  24. package/dist/editor/sidebar/ComponentTree.js.map +1 -1
  25. package/dist/editor/sidebar/Debug.js +1 -1
  26. package/dist/editor/sidebar/Debug.js.map +1 -1
  27. package/dist/revision.d.ts +2 -2
  28. package/dist/revision.js +2 -2
  29. package/dist/styles.css +5 -4
  30. package/dist/types.d.ts +1 -1
  31. package/package.json +1 -1
  32. package/src/editor/ContextMenu.tsx +0 -2
  33. package/src/editor/ai/Agents.tsx +62 -15
  34. package/src/editor/client/EditorClient.tsx +18 -20
  35. package/src/editor/client/editContext.ts +2 -2
  36. package/src/editor/client/operations.ts +9 -8
  37. package/src/editor/commands/componentCommands.tsx +1 -1
  38. package/src/editor/field-types/richtext/components/EditorDropdown.css +1 -0
  39. package/src/editor/field-types/richtext/contextMenuFactory.tsx +0 -4
  40. package/src/editor/menubar/ToolbarFactory.tsx +6 -2
  41. package/src/editor/menubar/toolbar-sections/UtilityControls.tsx +23 -19
  42. package/src/editor/page-viewer/PageViewerFrame.tsx +80 -4
  43. package/src/editor/reviews/CommentEditor.tsx +2 -2
  44. package/src/editor/reviews/Reviews.tsx +2 -0
  45. package/src/editor/sidebar/ComponentTree.tsx +223 -69
  46. package/src/editor/sidebar/Debug.tsx +1 -1
  47. package/src/revision.ts +2 -2
  48. package/src/types.ts +1 -1
  49. package/styles.css +0 -5
@@ -406,13 +406,69 @@ export function PageViewerFrame({
406
406
 
407
407
  if (editContextRef.current?.isRefreshing) return;
408
408
 
409
- const componentId = findNearestEditableComponentId(target as HTMLElement);
409
+ let componentId = findNearestEditableComponentId(target as HTMLElement);
410
+
411
+ // If layout components are hidden, block selection on layout components
412
+ if (
413
+ componentId &&
414
+ editContextRef.current &&
415
+ editContextRef.current.page &&
416
+ editContextRef.current.showLayoutComponents === false
417
+ ) {
418
+ const comp = getComponentById(componentId, editContextRef.current.page);
419
+ if (comp?.layoutId) {
420
+ componentId = undefined;
421
+ }
422
+ }
410
423
  if (editContextRef.current?.currentOverlay)
411
424
  editContextRef.current?.setCurrentOverlay(undefined);
412
425
 
413
426
  if (componentId) {
414
- if (event.ctrlKey) {
415
- const currentSelection = editContextRef.current?.selection || [];
427
+ const currentSelection = editContextRef.current?.selection || [];
428
+
429
+ if (event.shiftKey && currentSelection.length > 0) {
430
+ const page = pageViewContextRef.current?.page;
431
+ if (page) {
432
+ // Build ordered list of visible component ids by DOM order
433
+ const doc = iframeRef.current?.contentDocument;
434
+ const orderedIds: string[] = [];
435
+ if (doc) {
436
+ const all = Array.from(
437
+ doc.querySelectorAll("[data-component-id]"),
438
+ ) as HTMLElement[];
439
+ for (const el of all) {
440
+ const id = el.getAttribute("data-component-id");
441
+ if (!id) continue;
442
+ // Skip layout components when hidden
443
+ if (
444
+ editContextRef.current?.showLayoutComponents === false &&
445
+ getComponentById(id, page)?.layoutId
446
+ )
447
+ continue;
448
+ orderedIds.push(id);
449
+ }
450
+ }
451
+
452
+ const anchorId = currentSelection[currentSelection.length - 1]!;
453
+ const aIdx = orderedIds.indexOf(anchorId);
454
+ const bIdx = orderedIds.indexOf(componentId);
455
+ if (aIdx !== -1 && bIdx !== -1) {
456
+ const start = Math.min(aIdx, bIdx);
457
+ const end = Math.max(aIdx, bIdx);
458
+ const range = orderedIds.slice(start, end + 1);
459
+ if (event.ctrlKey) {
460
+ const union = new Set<string>([...currentSelection, ...range]);
461
+ editContextRef.current?.select(Array.from(union));
462
+ } else {
463
+ editContextRef.current?.select(range);
464
+ }
465
+ } else {
466
+ editContextRef.current?.select([componentId]);
467
+ }
468
+ } else {
469
+ editContextRef.current?.select([componentId]);
470
+ }
471
+ } else if (event.ctrlKey) {
416
472
  if (currentSelection.indexOf(componentId) === -1)
417
473
  editContextRef.current?.select([...currentSelection, componentId]);
418
474
  } else {
@@ -488,7 +544,19 @@ export function PageViewerFrame({
488
544
  event.preventDefault();
489
545
  event.stopPropagation();
490
546
 
491
- const componentId = findNearestEditableComponentId(target as HTMLElement);
547
+ let componentId = findNearestEditableComponentId(target as HTMLElement);
548
+
549
+ if (
550
+ componentId &&
551
+ editContextRef.current &&
552
+ editContextRef.current.page &&
553
+ editContextRef.current.showLayoutComponents === false
554
+ ) {
555
+ const comp = getComponentById(componentId, editContextRef.current.page);
556
+ if (comp?.layoutId) {
557
+ componentId = undefined;
558
+ }
559
+ }
492
560
 
493
561
  if (componentId) {
494
562
  // Only change selection if right-clicking on a component that's not in the current selection
@@ -511,6 +579,14 @@ export function PageViewerFrame({
511
579
  .map((id) => getComponentById(id, pageViewContextRef.current!.page!))
512
580
  .filter((x) => x) as Component[];
513
581
 
582
+ // If layout components are hidden, do not show context menu for them
583
+ if (
584
+ editContextRef.current?.showLayoutComponents === false &&
585
+ selectedComponents.some((c) => c.layoutId)
586
+ ) {
587
+ return;
588
+ }
589
+
514
590
  const iframeRect = iframe.getBoundingClientRect();
515
591
  const adjustedEvent = new MouseEvent("contextmenu", {
516
592
  bubbles: true,
@@ -42,13 +42,13 @@ export function CommentEditor({
42
42
 
43
43
  React.useEffect(() => {
44
44
  if (autoFocus && textareaRef.current) {
45
- // Focus after a short delay to ensure the component is mounted
45
+ // Focus after a longer delay to ensure the component is fully mounted, especially for dynamically created popovers
46
46
  const timer = setTimeout(() => {
47
47
  textareaRef.current?.focus();
48
48
  // Move cursor to end
49
49
  const len = textareaRef.current?.value.length || 0;
50
50
  textareaRef.current?.setSelectionRange(len, len);
51
- }, 100);
51
+ }, 200);
52
52
  return () => clearTimeout(timer);
53
53
  }
54
54
  }, [autoFocus]);
@@ -169,6 +169,7 @@ export function Reviews() {
169
169
  <SimpleIconButton
170
170
  label="Add Reviewer"
171
171
  icon="pi pi-plus"
172
+ data-testid="add-reviewer-button"
172
173
  onClick={(x) => {
173
174
  overlayPanelRef.current?.toggle(x);
174
175
  setTimeout(() => {
@@ -230,6 +231,7 @@ export function Reviews() {
230
231
  label="Add Reviewer"
231
232
  disabled={waiting}
232
233
  icon="pi pi-plus"
234
+ data-testid="add-reviewer-submit-button"
233
235
  onClick={async () => {
234
236
  if (!editContext?.contentEditorItem) return;
235
237
  setShowErrors(true);
@@ -13,7 +13,7 @@ import { PerfectTree, TreeNode } from "../ui/PerfectTree";
13
13
 
14
14
  import { isValidPlaceholder } from "../componentTreeHelper";
15
15
  import { getAbsoluteIconUrl } from "../utils";
16
- import { Plus, EyeIcon, EyeOff, Pentagon } from "lucide-react";
16
+ import { Plus, LayoutTemplate, Pentagon } from "lucide-react";
17
17
  import { SimpleIconButton } from "../ui/SimpleIconButton";
18
18
 
19
19
  type CustomTreeNode = TreeNode<Component | Placeholder> & {
@@ -171,14 +171,15 @@ export function ComponentTree({}) {
171
171
  tags: [],
172
172
  };
173
173
 
174
- if (editContext?.hideNonEditableComponents) {
175
- // Flatten the tree: collect all editable descendants directly
176
- const flattenedComponents: CustomTreeNode[] = [];
177
- for (const component of p.components) {
178
- const editableNodes = getEditableDescendants(component, node);
179
- flattenedComponents.push(...editableNodes);
180
- }
181
- node.children = flattenedComponents;
174
+ if (!editContext?.showLayoutComponents) {
175
+ // Map components and filter out layout components when hidden
176
+ const mappedComponents = p.components.map((c) =>
177
+ mapComponentNode(c, node),
178
+ );
179
+ node.children = mappedComponents.filter((componentNode) => {
180
+ const component = componentNode.data as Component;
181
+ return !component.layoutId;
182
+ });
182
183
  } else {
183
184
  // Always map components, but filter based on editability and descendants
184
185
  const mappedComponents = p.components.map((c) =>
@@ -201,36 +202,20 @@ export function ComponentTree({}) {
201
202
  return [];
202
203
  }
203
204
 
204
- if (editContext?.hideNonEditableComponents) {
205
- // Flatten the tree: collect all editable descendants from all placeholders
206
- const flattenedNodes: CustomTreeNode[] = [];
207
-
205
+ if (!editContext?.showLayoutComponents) {
206
+ // Show only non-layout components
207
+ const nodes: CustomTreeNode[] = [];
208
208
  for (const placeholder of c.placeholders) {
209
- if (placeholder.editable) {
210
- //If placeholder is editable, include it normally
211
- if (c.placeholders.length > 1 || !c.editable) {
212
- // Multiple placeholders - show placeholder node
213
- const placeholderNode = mapPlaceholderNode(placeholder, parent);
214
- flattenedNodes.push(placeholderNode);
215
- } else {
216
- // Single placeholder - map components directly
217
- for (const component of placeholder.components) {
218
- const editableNodes = getEditableDescendants(component, parent);
219
- flattenedNodes.push(...editableNodes);
220
- }
221
- }
222
- } else {
223
- // Placeholder is not editable - collect editable descendants from its components
224
- for (const component of placeholder.components) {
225
- const editableNodes = getEditableDescendants(component, parent);
226
- flattenedNodes.push(...editableNodes);
209
+ for (const component of placeholder.components) {
210
+ if (!component.layoutId) {
211
+ const componentNode = mapComponentNode(component, parent);
212
+ nodes.push(componentNode);
227
213
  }
228
214
  }
229
215
  }
230
-
231
- return flattenedNodes;
216
+ return nodes;
232
217
  } else {
233
- // Original logic for when hideNonEditableComponents is false
218
+ // Original logic for when showing layout components
234
219
  // Filter placeholders based on editable descendants
235
220
  let placeholdersToShow = c.placeholders.filter((p) => {
236
221
  // Show placeholder if it's editable or has editable descendants
@@ -424,22 +409,72 @@ export function ComponentTree({}) {
424
409
 
425
410
  setRootNodes(finalNodes);
426
411
  setNodeDictionary(dict);
427
- }, [page, editContext?.hideNonEditableComponents]);
412
+ }, [page, editContext?.showLayoutComponents]);
428
413
 
429
414
  const handleTreeSelection = useCallback(
430
415
  (key: string, event: React.MouseEvent) => {
431
- let newKeys = [key];
432
- if (event.ctrlKey) {
416
+ let newKeys: string[] = [];
417
+
418
+ // Helper: gather visible component keys using current tree data and expanded state
419
+ const getVisibleComponentKeys = (): string[] => {
420
+ const keys: string[] = [];
421
+ const visit = (nodes: CustomTreeNode[]) => {
422
+ for (const n of nodes) {
423
+ if (n.type === "component") keys.push(n.key);
424
+ if (n.children && expandedKeys.includes(n.key)) {
425
+ visit(n.children as CustomTreeNode[]);
426
+ }
427
+ }
428
+ };
429
+ visit(rootNodes as CustomTreeNode[]);
430
+ return keys;
431
+ };
432
+
433
+ if (event.shiftKey) {
434
+ const anchorKey =
435
+ selectedKeys && selectedKeys.length > 0
436
+ ? selectedKeys[selectedKeys.length - 1]!
437
+ : undefined;
438
+ const orderedKeys = getVisibleComponentKeys();
439
+ const aIdx = anchorKey ? orderedKeys.indexOf(anchorKey) : -1;
440
+ const bIdx = orderedKeys.indexOf(key);
441
+
442
+ if (aIdx !== -1 && bIdx !== -1) {
443
+ const start = Math.min(aIdx, bIdx);
444
+ const end = Math.max(aIdx, bIdx);
445
+ const rangeKeys = orderedKeys.slice(start, end + 1);
446
+ if (event.ctrlKey) {
447
+ const union = new Set<string>([
448
+ ...selectedKeys.filter(
449
+ (k) => nodeDictionary[k]?.type === "component",
450
+ ),
451
+ ...rangeKeys,
452
+ ]);
453
+ newKeys = Array.from(union);
454
+ } else {
455
+ newKeys = rangeKeys;
456
+ }
457
+ } else {
458
+ // Fallback to single selection when anchor or target not found
459
+ newKeys = [key];
460
+ }
461
+ } else if (event.ctrlKey) {
433
462
  if (selectedKeys.includes(key)) {
434
463
  newKeys = selectedKeys.filter((x) => x !== key);
435
464
  } else {
436
465
  newKeys = [...selectedKeys, key];
437
466
  }
467
+ } else {
468
+ newKeys = [key];
438
469
  }
439
470
 
440
- const selectedComponentIds = newKeys
441
- .filter((key) => nodeDictionary[key])
442
- .map((key) => nodeDictionary[key]!.componentId!);
471
+ const selectedComponentIds = Array.from(
472
+ new Set(
473
+ newKeys
474
+ .filter((k) => nodeDictionary[k]?.type === "component")
475
+ .map((k) => nodeDictionary[k]!.componentId!),
476
+ ),
477
+ );
443
478
 
444
479
  editContextRef.current?.select(selectedComponentIds);
445
480
 
@@ -597,6 +632,102 @@ export function ComponentTree({}) {
597
632
  return null;
598
633
  };
599
634
 
635
+ // Resolve placeholder and correct index for drop zones even when placeholders are hidden/flattened
636
+ const getSiblingsForParent = (
637
+ parent: CustomTreeNode | null,
638
+ ): CustomTreeNode[] => {
639
+ if (!parent) return (rootNodes as CustomTreeNode[]) || [];
640
+ const parentNode = nodeDictionary[parent.key];
641
+ return ((parentNode?.children as CustomTreeNode[]) ||
642
+ []) as CustomTreeNode[];
643
+ };
644
+
645
+ const findNearestComponentNeighbor = (
646
+ siblings: CustomTreeNode[],
647
+ index: number,
648
+ ): CustomTreeNode | null => {
649
+ // Prefer right neighbor
650
+ for (let i = index; i < siblings.length; i++) {
651
+ if (siblings[i]?.type === "component") return siblings[i]!;
652
+ }
653
+ // Fallback to left neighbor
654
+ for (let j = index - 1; j >= 0; j--) {
655
+ if (siblings[j]?.type === "component") return siblings[j]!;
656
+ }
657
+ return null;
658
+ };
659
+
660
+ const resolveDropContext = (
661
+ dragOverParent: CustomTreeNode | null,
662
+ index: number,
663
+ ): { placeholder: Placeholder | null; indexInPlaceholder: number } => {
664
+ // Direct placeholder parent
665
+ if (dragOverParent && dragOverParent.type === "placeholder") {
666
+ const placeholder = dragOverParent.data as Placeholder;
667
+ return {
668
+ placeholder: placeholder.editable ? placeholder : null,
669
+ indexInPlaceholder: Math.max(0, index),
670
+ };
671
+ }
672
+
673
+ // Single editable placeholder on a component
674
+ if (dragOverParent && dragOverParent.type === "component") {
675
+ const component = dragOverParent.data as Component;
676
+ const editablePlaceholders = (component.placeholders || []).filter(
677
+ (p) => p.editable,
678
+ );
679
+ const siblings = getSiblingsForParent(dragOverParent);
680
+ if (editablePlaceholders.length === 1) {
681
+ const ph = editablePlaceholders[0]!;
682
+ // Count how many siblings in this placeholder appear before the zone
683
+ const indexInPlaceholder = siblings
684
+ .slice(0, Math.max(0, index))
685
+ .filter(
686
+ (n) =>
687
+ n.type === "component" &&
688
+ (n.data as Component)?.parentPlaceholder?.key === ph.key,
689
+ ).length;
690
+ return { placeholder: ph, indexInPlaceholder };
691
+ }
692
+
693
+ // Multiple placeholders: infer from nearest neighbor component
694
+ const neighbor = findNearestComponentNeighbor(
695
+ siblings,
696
+ Math.max(0, index),
697
+ );
698
+ const ph = (neighbor?.data as Component | undefined)?.parentPlaceholder;
699
+ if (ph && ph.editable) {
700
+ const indexInPlaceholder = siblings
701
+ .slice(0, Math.max(0, index))
702
+ .filter(
703
+ (n) =>
704
+ n.type === "component" &&
705
+ (n.data as Component)?.parentPlaceholder?.key === ph.key,
706
+ ).length;
707
+ return { placeholder: ph, indexInPlaceholder };
708
+ }
709
+
710
+ return { placeholder: null, indexInPlaceholder: 0 };
711
+ }
712
+
713
+ // Root-level (no parent): infer from neighbors among root nodes
714
+ const siblings = getSiblingsForParent(null);
715
+ const neighbor = findNearestComponentNeighbor(siblings, Math.max(0, index));
716
+ const ph = (neighbor?.data as Component | undefined)?.parentPlaceholder;
717
+ if (ph && ph.editable) {
718
+ const indexInPlaceholder = siblings
719
+ .slice(0, Math.max(0, index))
720
+ .filter(
721
+ (n) =>
722
+ n.type === "component" &&
723
+ (n.data as Component)?.parentPlaceholder?.key === ph.key,
724
+ ).length;
725
+ return { placeholder: ph, indexInPlaceholder };
726
+ }
727
+
728
+ return { placeholder: null, indexInPlaceholder: 0 };
729
+ };
730
+
600
731
  // Handle drag over node
601
732
  const handleDragOverZone = (
602
733
  dragOverNode: CustomTreeNode | null,
@@ -604,9 +735,9 @@ export function ComponentTree({}) {
604
735
  event: React.DragEvent,
605
736
  ): boolean => {
606
737
  if (!editContext?.dragObject) return false;
607
- const placeholder = getPlaceholder(dragOverNode);
738
+ const { placeholder } = resolveDropContext(dragOverNode, index);
608
739
  if (!placeholder) return false;
609
- var isValid = isValidPlaceholder(placeholder, editContext.dragObject);
740
+ const isValid = isValidPlaceholder(placeholder, editContext.dragObject);
610
741
  event.dataTransfer.dropEffect = isValid ? "move" : "none";
611
742
  return isValid;
612
743
  };
@@ -617,10 +748,20 @@ export function ComponentTree({}) {
617
748
  index: number,
618
749
  event: React.DragEvent,
619
750
  ): void => {
620
- const placeholder = getPlaceholder(droppedOnNode);
621
- if (!placeholder) return;
751
+ // When dropping on a node (index < 0), use legacy behavior
752
+ if (index < 0) {
753
+ const placeholder = getPlaceholder(droppedOnNode);
754
+ if (!placeholder) return;
755
+ editContext!.droppedInPlaceholder(placeholder.key, index);
756
+ return;
757
+ }
622
758
 
623
- editContext!.droppedInPlaceholder(placeholder.key, index);
759
+ const { placeholder, indexInPlaceholder } = resolveDropContext(
760
+ droppedOnNode,
761
+ index,
762
+ );
763
+ if (!placeholder) return;
764
+ editContext!.droppedInPlaceholder(placeholder.key, indexInPlaceholder);
624
765
  };
625
766
 
626
767
  if (!page)
@@ -630,35 +771,45 @@ export function ComponentTree({}) {
630
771
  </div>
631
772
  );
632
773
 
633
- // Use the PerfectTree component
634
774
  return (
635
775
  <div className="flex h-full flex-col">
636
776
  {/* Toolbar */}
637
777
  <div className="flex items-center justify-between border-b border-gray-200 px-2 py-1">
638
- <SimpleIconButton
639
- icon={
640
- editContext?.hideNonEditableComponents ? (
641
- <EyeOff className="h-4 w-4" strokeWidth={1.5} />
642
- ) : (
643
- <EyeIcon className="h-4 w-4" strokeWidth={1.5} />
644
- )
645
- }
646
- label={
647
- editContext?.hideNonEditableComponents
648
- ? "Show non-editable components"
649
- : "Hide non-editable components"
650
- }
651
- size="small"
652
- selected={editContext?.hideNonEditableComponents}
653
- onClick={() =>
654
- editContext?.setHideNonEditableComponents(
655
- !editContext.hideNonEditableComponents,
656
- )
657
- }
658
- />
778
+ <div className="flex items-center gap-1">
779
+ <SimpleIconButton
780
+ icon={<Plus strokeWidth={1} className="h-4 w-4" />}
781
+ label="Add component"
782
+ size="small"
783
+ data-testid="component-tree-add-component"
784
+ onClick={(event) => {
785
+ if (
786
+ !editContext ||
787
+ editContext.readonly ||
788
+ editContext.mode !== "edit"
789
+ )
790
+ return;
791
+
792
+ editContext.setInsertMode(true);
793
+ }}
794
+ />
795
+ </div>
796
+ <div className="flex items-center gap-1">
797
+ <SimpleIconButton
798
+ icon={<LayoutTemplate strokeWidth={1} className="h-4 w-4" />}
799
+ label={
800
+ editContext?.showLayoutComponents ? "Hide layout" : "Show layout"
801
+ }
802
+ size="small"
803
+ selected={editContext?.showLayoutComponents}
804
+ onClick={() =>
805
+ editContext?.setShowLayoutComponents(
806
+ !editContext.showLayoutComponents,
807
+ )
808
+ }
809
+ />
810
+ </div>
659
811
  </div>
660
812
 
661
- {/* Tree content */}
662
813
  <div className="flex-1 p-2" ref={treeRef} data-testid="component-tree">
663
814
  <PerfectTree
664
815
  nodes={rootNodes}
@@ -673,7 +824,10 @@ export function ComponentTree({}) {
673
824
  handleDragOverZone(parent as CustomTreeNode | null, index, event)
674
825
  }
675
826
  isValidDropZone={(parent, index) => {
676
- const placeholder = getPlaceholder(parent as CustomTreeNode | null);
827
+ const { placeholder } = resolveDropContext(
828
+ parent as CustomTreeNode | null,
829
+ index,
830
+ );
677
831
  if (!placeholder) return false;
678
832
  if (!editContext?.dragObject) return false;
679
833
  const result = isValidPlaceholder(
@@ -106,7 +106,7 @@ export function Debug({}: {}) {
106
106
  tabs={tabs}
107
107
  activeTab={activeTab}
108
108
  setActiveTab={setActiveTab}
109
- className="alpaceditor-tabs border-gray-3 flex border-b px-2 pt-2 text-sm"
109
+ className="border-gray-3 flex border-b px-2 pt-2 text-xs"
110
110
  />
111
111
 
112
112
  <div className="absolute top-2 right-1 h-4 w-4">
package/src/revision.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const version = "1.0.4064";
2
- export const buildDate = "2025-08-25 01:54:20";
1
+ export const version = "1.0.4065";
2
+ export const buildDate = "2025-08-25 11:33:32";
package/src/types.ts CHANGED
@@ -169,7 +169,7 @@ export type UserPreferences = {
169
169
  showViewNames?: boolean;
170
170
  showComponentNavigator?: boolean;
171
171
  showAgentsPanel?: boolean;
172
- hideNonEditableComponents?: boolean;
172
+ showLayoutComponents?: boolean;
173
173
  };
174
174
 
175
175
  export type HistoryEntry = {
package/styles.css CHANGED
@@ -426,11 +426,6 @@ body {
426
426
  background-color: unset;
427
427
  }
428
428
 
429
- .alpaceditor-tabs {
430
- display: flex;
431
- flex-direction: column;
432
- }
433
-
434
429
  .alpaca-no-border {
435
430
  border: none !important;
436
431
  }