CUSTOM WIDGET GUIDE

Ecosistema completo para organización y gestión de contenido con interfaces espaciales

Custom Widget Creation Guide

🚀 Widget Builder: Create Reusable Widgets

The Widget Builder is your visual tool for creating custom, reusable widgets that can be used across your entire platform.


📍 Where to Find the Widget Builder

Route

/space/{spaceSlug}/editor/widget-builder

From Landing Editor

Navigate to:

http://localhost:5200/space/space-{id}/editor/widget-builder

From Editor Navigation

  1. Go to the Editor landing page
  2. Click the widget builder option (if available in nav)
  3. Or directly navigate to the route above

🎨 Widget Builder Features

1. Design Panel

Visually design your widget's appearance and structure

2. Inputs Panel

Configure widget inputs (properties/parameters):

3. Theme Integration Panel

Map widget properties to theme variables:

This makes your widget automatically adapt to theme changes!

4. Preview Panel

Test your widget across breakpoints:

5. Export Panel

Three export options:


🛠️ Creating a Custom Widget

Step 1: Start from Template or Blank

Widget Templates Available:

// Button Widget
{ id: 'button', name: 'Custom Button', icon: 'hand-pointer' }

// Card Widget
{ id: 'card', name: 'Info Card', icon: 'id-card' }

// Form Widget
{ id: 'form', name: 'Form Builder', icon: 'wpforms' }

// Chart Widget
{ id: 'chart', name: 'Chart Widget', icon: 'chart-line' }

// List Widget
{ id: 'list', name: 'Dynamic List', icon: 'list' }

// Image Gallery Widget
{ id: 'gallery', name: 'Image Gallery', icon: 'images' }

Or click "Create Blank Widget" to start from scratch.

Step 2: Define Inputs

Click "Add Input" in the Inputs panel:

// Example: Button Widget Inputs
{
  name: 'label',
  type: 'string',
  description: 'Button text',
  required: true,
  defaultValue: 'Click me'
}

{
  name: 'variant',
  type: 'string',
  description: 'Button style variant',
  required: false,
  defaultValue: 'primary',
  options: ['primary', 'secondary', 'danger', 'success']
}

{
  name: 'disabled',
  type: 'boolean',
  description: 'Disable button',
  required: false,
  defaultValue: false
}

{
  name: 'icon',
  type: 'string',
  description: 'Icon class (e.g., fas fa-check)',
  required: false
}

Step 3: Define Outputs (Events)

Click "Add Output" for widget events:

// Example: Button Widget Outputs
{
  name: 'onClick',
  type: 'event',
  description: 'Fired when button is clicked'
}

{
  name: 'onHover',
  type: 'event',
  description: 'Fired when button is hovered'
}

Step 4: Theme Integration

Map widget styles to theme variables:

Background Color → --theme-primary
Text Color → --theme-text-primary
Border Color → --theme-border

This ensures your widget respects the active theme!

Step 5: Generate Code

Click "Generate Code" to see the Angular component code:

@Component({
  selector: 'custom-button',
  standalone: true,
  template: `
    <button 
      [class]="'btn btn-' + variant()"
      [disabled]="disabled()"
      (click)="handleClick()">
      @if (icon()) {
        <i [class]="icon()"></i>
      }
      {{ label() }}
    </button>
  `,
  styles: [`
    .btn {
      background: var(--theme-primary);
      color: var(--theme-text-primary);
      border: 1px solid var(--theme-border);
    }
  `]
})
export class CustomButtonWidget {
  // Inputs
  label = input<string>('Click me');
  variant = input<string>('primary');
  disabled = input<boolean>(false);
  icon = input<string | null>(null);
  
  // Outputs
  onClick = output<void>();
  onHover = output<void>();
  
  handleClick() {
    if (!this.disabled()) {
      this.onClick.emit();
    }
  }
}

Step 6: Save to Registry

Click "Save to Registry" to make your widget available platform-wide!


📊 Widget Registration Flow

Widget Builder
    ↓
  Generate Code
    ↓
  Save to Registry (WidgetRegistryService)
    ↓
  Widget Metadata Stored (Flash Persistence)
    ↓
  Widget Available in Editor Palette
    ↓
  Widget appears in EditorService.widgetCategories
    ↓
  Users can drag-and-drop your widget!

🔧 Widget Registry Service

The WidgetRegistryService manages all registered widgets:

Storage Key

flash:widget-registry-state

Registered Widget Structure

{
  "widget-123": {
    "id": "widget-123",
    "name": "Custom Button",
    "category": "custom",
    "isPublic": true,
    "tags": ["custom", "button", "interactive"],
    "metadata": {
      "createdAt": "2025-01-01T00:00:00Z",
      "updatedAt": "2025-01-01T00:00:00Z",
      "version": "1.0.0",
      "author": "Widget Builder"
    },
    "inputs": [...],
    "outputs": [...],
    "themeVariables": {...},
    "html": "...",
    "typescript": "..."
  }
}

🎯 Export Options Explained

1. Standalone Component (Quick & Simple)

Use when: Creating a widget for a specific feature

2. NX Library (Enterprise-Ready)

Use when: Creating reusable widgets for the team

3. Widget Registry (Platform-Wide)

Use when: You want instant platform-wide availability


🧩 Using Your Custom Widget

After Registration

Your widget becomes available in the Editor:

  1. Editor Palette: Appears in the "Custom" category
  2. Drag & Drop: Users can drag it onto the canvas
  3. Properties Panel: All inputs appear as editable properties
  4. Events Panel: All outputs appear as bindable events

Widget Appears Here

// In EditorService.widgetCategories computed signal
{
  name: 'Personalizados',
  types: [
    ...
    'custom-button',  // ← Your widget!
    ...
  ]
}

📝 Best Practices

1. Clear Naming

2. Comprehensive Inputs

3. Theme Variables

4. Responsive Design

5. Documentation


🔄 Workflow Example

Creating a "Product Card" Widget

  1. Navigate to Widget Builder

    /space/my-space/editor/widget-builder
    
  2. Click "Card" Template

    • Starts with basic card structure
  3. Define Inputs

    • productName (string, required)
    • price (number, required)
    • imageUrl (string, required)
    • description (string, optional)
    • inStock (boolean, default: true)
  4. Define Outputs

    • onAddToCart (event)
    • onViewDetails (event)
  5. Theme Integration

    • Card background → --theme-surface
    • Text → --theme-text-primary
    • Price → --theme-primary
    • Border → --theme-border
  6. Preview

    • Test on mobile, tablet, desktop
    • Adjust spacing/sizing
  7. Generate Code

    • Review the generated Angular component
    • Tweak if needed
  8. Save to Registry

    • Widget is now platform-wide!
    • Available in ALL editors
  9. Use in Editor

    • Open any page in Editor
    • Find "Product Card" in Custom widgets
    • Drag onto canvas
    • Configure properties
    • Bind onAddToCart event to actions

🚀 Next Steps

After creating your widget:

  1. Test Thoroughly: Use it in real pages
  2. Get Feedback: Share with team
  3. Iterate: Improve based on usage
  4. Version: Update when adding features
  5. Document: Write usage guides
  6. Share: Export as NX lib for other projects

🎨 Advanced: Custom Widget Templates

You can create widget templates for common patterns:

Template Structure

{
  id: 'my-template',
  name: 'My Custom Template',
  description: 'Template for X use case',
  icon: 'magic',
  category: 'custom',
  baseStructure: {
    html: '<div class="template">...</div>',
    typescript: '// Template logic',
    styles: '.template { ... }',
    inputs: [...],
    outputs: [...]
  }
}

Add templates in:

libs/editor-web-lib/src/lib/components/widget-builder/widget-builder.component.ts

📚 Related Documentation


🎯 Quick Reference

Feature Location Storage Key
Widget Builder /editor/widget-builder -
Widget Registry WidgetRegistryService flash:widget-registry-state
Current Widget WidgetBuilderService flash:widget-builder-state
Editor Palette EditorService flash:editor-state

Happy Widget Building! 🎨✨