SESSION 12.16 HIERARCHY CONNECTOR WIRED

Documentation for Sessions

Session 12.16 - Hierarchy Connector Mode Wired to Canvas

Overview

Completed the Hierarchy Connector Mode by wiring the visual UI to the canvas click behavior. When active, clicking a container now assigns it as the parent of the currently selected widget, instead of just selecting the container.

What Was Implemented

1. Canvas Input/Output Bindings ✅

File: libs/libs-ui/editor-ui/src/lib/components/editor-ui/editor-ui.component.html

Added two new bindings to the canvas:

<lib-editor-canvas
  ...
  [hierarchyConnectorModeInput]="hierarchyConnectorMode()"
  ...
  (containerClickedForConnection)="onContainerClickedForConnection($event)"
></lib-editor-canvas>

2. Canvas Component Changes ✅

File: libs/libs-widgets/widgets/src/lib/widgets/editor-canvas/editor-canvas.component.ts

A. Added Input for Hierarchy Connector Mode

@Input() set hierarchyConnectorModeInput(value: boolean) {
  this.hierarchyConnectorMode.set(value);
}

B. Added Output Event

@Output() containerClickedForConnection = new EventEmitter<string>(); // Emits container ID

C. Added Signal for Mode State

// 🔗 Hierarchy Connector Mode
readonly hierarchyConnectorMode = signal(false);

D. Modified Widget Selection Logic

onSelectWidget(widget: Widget): void {
  // 🔗 If hierarchy connector mode is active and widget is a container, connect instead of select
  if (this.hierarchyConnectorMode() && widget.type === 'container') {
    console.log('[Canvas] 🔗 Hierarchy Connector Mode - Container clicked:', widget.name, widget.id);
    this.containerClickedForConnection.emit(widget.id);
    return; // Don't select, just connect
  }
  
  this.selectionService.selectWidget(widget, this.widgetAction);
}

E. Added Canvas Class for Visual Feedback

readonly canvasClasses = computed(() => ({
  ...
  // 🔗 Hierarchy Connector Mode
  'hierarchy-connector-mode': this.hierarchyConnectorMode(),
  ...
}));

3. Visual Feedback Styles ✅

File: libs/libs-widgets/widgets/src/lib/widgets/editor-canvas/editor-canvas.component.scss

Added comprehensive styles for visual feedback when in connector mode:

// 🔗 Hierarchy Connector Mode Styles
.editor-canvas.hierarchy-connector-mode {
  cursor: crosshair !important;
  
  // Highlight all container widgets for connection
  ::ng-deep lib-container-widget {
    position: relative;
    
    &::before {
      content: '';
      position: absolute;
      top: -2px;
      left: -2px;
      right: -2px;
      bottom: -2px;
      border: 3px dashed #10b981;
      border-radius: 8px;
      background: rgba(16, 185, 129, 0.05);
      pointer-events: none;
      z-index: 1000;
      animation: connector-pulse 2s infinite;
    }
    
    &::after {
      content: '🔗 Click to Connect';
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background: #10b981;
      color: white;
      padding: 8px 16px;
      border-radius: 8px;
      font-size: 14px;
      font-weight: 600;
      pointer-events: none;
      z-index: 1001;
      box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
      animation: connector-bounce 1s infinite;
    }
    
    &:hover::before {
      border-color: #059669;
      background: rgba(5, 150, 105, 0.1);
      animation: connector-pulse-fast 1s infinite;
    }
    
    &:hover::after {
      background: #059669;
      transform: translate(-50%, -50%) scale(1.05);
    }
  }
}

Visual Effects:

4. Editor UI Event Handler ✅

File: libs/libs-ui/editor-ui/src/lib/components/editor-ui/editor-ui.component.ts

Added handler for when a container is clicked in connector mode:

/**
 * 🔗 Handle container clicked for connection in hierarchy connector mode
 */
onContainerClickedForConnection(containerId: string): void {
  const selectedWidget = this.selectedWidgets()[0];
  
  if (!selectedWidget) {
    console.warn('[EditorUI] No widget selected for connection');
    return;
  }

  console.log('[EditorUI] 🔗 Connecting widget to container:', {
    widgetId: selectedWidget.id,
    widgetName: selectedWidget.name,
    containerId,
  });

  // Re-parent the selected widget to the clicked container
  this.handleWidgetReparent(selectedWidget.id, containerId);

  // Deactivate hierarchy connector mode
  this.hierarchyConnectorMode.set(false);
  console.log('[EditorUI] ✅ Connection complete - Hierarchy Connector Mode DEACTIVATED');

  // TODO: Show toast notification
}

Logic Flow:

  1. Get the currently selected widget
  2. If no widget selected, warn and return
  3. Call handleWidgetReparent() to update parent/child relationships
  4. Auto-deactivate the connector mode
  5. Log success

How It Works (Complete Flow)

User Journey

  1. User selects a widget (e.g., Text Widget) on the canvas
  2. Opens Properties Panel → Hierarchy section
  3. Clicks "Visual Connect" button
    • Button turns green with pulsing animation
    • hierarchyConnectorMode signal set to true
    • Signal propagates to canvas via [hierarchyConnectorModeInput]
  4. Canvas applies visual feedback
    • Cursor changes to crosshair
    • All containers get green pulsing border + "🔗 Click to Connect" label
  5. User clicks on a container
    • Canvas onSelectWidget() detects the mode is active
    • Instead of selecting, emits containerClickedForConnection event with container ID
  6. Editor UI handles the connection
    • Receives container ID via onContainerClickedForConnection()
    • Calls handleWidgetReparent() to update widget's parentId
    • Updates parent/child arrays
    • Emits widgetsChange event
  7. Mode auto-deactivates
    • hierarchyConnectorMode set back to false
    • Visual feedback removed
    • Button returns to normal blue gradient
  8. Widget is now nested
    • Widget disappears from canvas top-level (filtered by topLevelWidgets())
    • Widget appears inside container (via childWidgets)
    • Widget Tree updates to show correct hierarchy

Testing Instructions

Test 1: Hierarchy Connector Mode (NEW!)

  1. Refresh browser (Ctrl+Shift+R / Cmd+Shift+R)
  2. Create a Text Widget and a Container Widget on canvas
  3. Select the Text Widget
  4. Open Properties Panel → scroll to Hierarchy section
  5. Click "Visual Connect" button
  6. Expected visual changes:
    • Button turns green with pulsing animation ✅
    • Text changes to "Click container to connect..." ✅
    • Cursor becomes crosshair across canvas ✅
    • Container widget gets:
      • Green pulsing dashed border ✅
      • "🔗 Click to Connect" label in center ✅
  7. Click on the Container Widget
  8. Expected results:
    • Text Widget disappears from canvas top-level ✅
    • Text Widget appears inside container ✅
    • Widget Tree updates to show Text Widget nested under Container ✅
    • Connector mode auto-deactivates (button returns to blue) ✅
    • Console shows success logs ✅

Test 2: Mode Cancellation

  1. Activate connector mode (click "Visual Connect")
  2. Instead of clicking a container, click the button again
  3. Expected: Mode deactivates, visual feedback removed

Test 3: No Widget Selected

  1. Deselect all widgets (click on canvas background)
  2. Try to activate connector mode
  3. Expected: Button should be disabled (no widget to connect)

Console Logs to Watch For

When everything works correctly, you should see:

[PropertiesPanel] 🔗 Hierarchy Connector Mode: ACTIVATED
[EditorUI] 🔗 Hierarchy Connector Mode: ACTIVATED
[Canvas] 🔗 Hierarchy Connector Mode - Container clicked: Container Widget <container-id>
[EditorUI] 🔗 Connecting widget to container: { widgetId: ..., widgetName: ..., containerId: ... }
[EditorUI] 🏗️ Re-parenting widget <widget-id> to <container-id>
[Canvas] 🎯 Top-level widgets: 1 / 2
[WidgetTree] 🌲 Top-level widgets for tree: 1 / 2
[EditorUI] ✅ Connection complete - Hierarchy Connector Mode DEACTIVATED

Known Issues & Next Steps

✅ DONE

⏳ TODO


Drag-and-Drop Status

The user reported that drag-and-drop from palette → container is still not working. Initial investigation shows:

Possible causes:

  1. Z-index issue: Container might be behind other elements
  2. Event propagation: Some event handler might be stopping propagation
  3. Data format mismatch: Palette might be setting drag data in a format the container doesn't recognize
  4. Pointer events: Container might have pointer-events: none in some cases

Next debugging step: Add console logs to see if the container's DropZoneDirective is even firing when dragging from palette.


Files Modified

Core Functionality

Documentation


Key Architectural Decisions

Why Not Select the Container?

When in connector mode, clicking a container should NOT select it because:

  1. The user's intent is to connect the currently selected widget, not to select a new widget
  2. Selecting would change the Properties Panel, losing the connection context
  3. It provides clear, predictable behavior: one action, one outcome

Why Auto-Deactivate?

The mode auto-deactivates after connection because:

  1. Most users will only want to connect once
  2. It prevents accidental connections
  3. The visual feedback (crosshair, borders) is intense and should be temporary
  4. Users can easily re-activate if needed

Why Use ::ng-deep?

The visual feedback uses ::ng-deep to pierce Angular's view encapsulation because:

  1. Container widgets are separate components with their own encapsulation
  2. The feedback needs to be applied from the canvas level
  3. It's the most reliable way to ensure all containers get the effect
  4. Alternative would be to add a class directly to containers, which is more complex

User Feedback Integration

"it did not work. When we click on the container, it selects it, instead of activating the inheritance."

Status: ✅ FIXED - Container clicks now trigger connection instead of selection

"This is why I said the active mode has to be smart, intuitive, and modify the behavior of the normal clicks/ui/ux."

Status: ✅ IMPLEMENTED - Mode changes cursor, adds visual feedback, and modifies click behavior

"And do not forget to FIX the drag and drop inside the container, that's still broken - maybe just be some silly z-index or not recognizing where a new container is."

Status: ⏳ INVESTIGATING - Need to add more diagnostic logs to identify the issue


Session Progress

Session 12.16 - Wired Hierarchy Connector Mode to canvas, implemented visual feedback, and enabled click-to-connect functionality.

Next Session 12.17 - Debug and fix drag-and-drop from palette → container.