Widget Builder Quick Reference

Quick reference guide for developers working with the widget builder system

Widget Builder Quick Reference ๐Ÿ“–

Fast reference for common widget builder tasks.


๐Ÿš€ Quick Start

Create a New Widget

import { inject } from '@angular/core';
import { WidgetStorageService } from '@libs-widgets/widget-builder';

const widgetStorage = inject(WidgetStorageService);

const widget = await widgetStorage.createWidget(
  'button',                    // WidgetType
  'space-123',                 // spaceId
  'universe-456',              // universeId (optional)
  'user-789',                  // userId
  {
    name: 'My Custom Button',
    description: 'A custom button widget',
    propertyGroups: [/* ... */],
    propertyValues: {/* ... */}
  }
);

Load Widgets for a Space

const widgets = await widgetStorage.listWidgets('space-123');

Update a Widget

await widgetStorage.updateWidget(
  'widget-123',
  {
    name: 'Updated Name',
    propertyValues: { color: 'blue' }
  },
  'space-123',
  'universe-456'
);

๐ŸŽจ Property Groups

Define Property Groups

import { PropertyGroup, PropertyDefinition } from '@widgets';

const propertyGroups: PropertyGroup[] = [
  {
    id: 'appearance',
    title: 'Appearance',
    icon: 'fa-paint-brush',
    expanded: true,
    order: 0,
    properties: [
      {
        key: 'color',
        label: 'Color',
        type: 'string',
        controlType: 'color-picker',
        getValue: (widget) => widget.propertyValues?.color || '#000000',
        setValue: (widget, value) => {
          widget.propertyValues = { ...widget.propertyValues, color: value };
          return widget;
        }
      }
    ]
  }
];

Access Property Groups

import { WidgetRegistrySyncService } from '@libs-widgets/widget-builder';

const registrySync = inject(WidgetRegistrySyncService);

// Get property groups for a widget type
const propertyGroups = registrySync.getPropertyGroups('button');

๐Ÿ”„ Event System

Emit Widget Saved Event

// Automatically emitted by workspace component
window.dispatchEvent(new CustomEvent('widget-builder:widget-saved', { 
  detail: { widgetId: 'widget-123' } 
}));

Listen for Widget Events

window.addEventListener('widget-builder:widget-saved', (event: CustomEvent) => {
  console.log('Widget saved:', event.detail.widgetId);
});

window.addEventListener('widget-builder:widget-published', (event: CustomEvent) => {
  console.log('Widget published:', event.detail.widgetId);
});

๐Ÿ“ฆ Widget Registry

Access Widget Registry

import { WidgetMetadataRegistry } from '@widgets';

const registry = inject(WidgetMetadataRegistry);

// Get all widget types
const types = registry.listWidgetTypes();

// Get widget metadata
const metadata = registry.tryGet('button');

// Get widgets by category
const byCategory = registry.getRegistrationsByCategory();

Sync with Registry

import { WidgetRegistryBridgeService } from '@libs-widgets/widget-builder';

const bridge = inject(WidgetRegistryBridgeService);

bridge.syncWidget(widget, moduleDefinition, propertyGroups);

๐Ÿ’พ Storage Patterns

Storage Keys

// Space-scoped widget
`space_${spaceId}_widget_${widgetId}`

// Workspace state (flash persistence)
`widget-builder:workspace:state`

// Current widget tracking
`widget-builder:current-widget`

Storage Service

import { GgStorage } from '@storage-system';

const storage = inject(GgStorage);

// Store widget
await storage.put(`space_${spaceId}_widget_${id}`, widget);

// Retrieve widget
const widget = await storage.get<Widget>(`space_${spaceId}_widget_${id}`);

// List widgets
const keys = await storage.list();
const widgetKeys = keys.filter(k => k.startsWith(`space_${spaceId}_widget_`));

๐ŸŽฏ Widget Manager

Refresh Widgets

import { WidgetsManagerService } from '@libs-widgets/widgets-manager';

const manager = inject(WidgetsManagerService);

// Manual refresh
await manager.refresh();

// Access widgets
const widgets = manager.widgets();
const stats = manager.stats();

Search Widgets

const results = manager.searchWidgets({
  query: 'button',
  category: 'basic',
  scope: 'private'
});

๐Ÿ”จ Code Generation

Generate Widget Code

import { WidgetGeneratorService } from '@libs-widgets/widget-builder';

const generator = inject(WidgetGeneratorService);

const result = await generator.generateWidget({
  id: 'custom-button',
  name: 'Custom Button',
  description: 'A custom button widget',
  type: 'button',
  properties: [/* ... */],
  propertyGroups: [/* ... */],
  variants: [/* ... */]
});

console.log(result.files.component);  // TypeScript
console.log(result.files.template);   // HTML
console.log(result.files.styles);     // SCSS

๐ŸŽจ Live Preview

Setup Live Preview

import { WidgetLivePreviewComponent } from '@libs-widgets/widget-builder';

// In template:
<lib-widget-live-preview
  [widget]="previewWidget()"
  [breakpoint]="previewBreakpoint()"
  [zoom]="previewZoom()"
/>

๐Ÿงช Common Patterns

Create Widget with Variants

const widget = await widgetStorage.createWidget(
  'button',
  spaceId,
  universeId,
  userId,
  {
    name: 'Multi-Style Button',
    variants: [
      {
        id: 'primary',
        name: 'Primary',
        description: 'Primary button style',
        properties: { color: '#007bff' },
        createdAt: new Date(),
        updatedAt: new Date()
      },
      {
        id: 'secondary',
        name: 'Secondary',
        description: 'Secondary button style',
        properties: { color: '#6c757d' },
        createdAt: new Date(),
        updatedAt: new Date()
      }
    ],
    defaultVariant: 'primary'
  }
);

Add Property Group Dynamically

// In workspace component
addPropertyGroup() {
  const newGroup: PropertyGroup = {
    id: `group-${Date.now()}`,
    title: 'New Group',
    icon: 'fa-cog',
    expanded: true,
    order: this.propertyGroups().length,
    properties: []
  };
  
  this.propertyGroups.update(groups => [...groups, newGroup]);
}

Flash Persistence Setup

import { effect } from '@angular/core';

constructor() {
  // Auto-save on any signal change
  effect(() => {
    const state = {
      widgetName: this.widgetName(),
      propertyGroups: this.propertyGroups(),
      propertyValues: this.propertyValues(),
      // ... other state
    };
    
    this.storage.put('widget-builder:workspace:state', state);
  });
}

๐Ÿ” Debugging Tips

Check Widget Registration

const registry = inject(WidgetMetadataRegistry);
console.log('Registered types:', registry.listWidgetTypes());
console.log('Button metadata:', registry.tryGet('button'));

Verify Storage Keys

const storage = inject(GgStorage);
const keys = await storage.list();
console.log('All keys:', keys);
console.log('Widget keys:', keys.filter(k => k.includes('widget')));

Monitor Events

window.addEventListener('widget-builder:widget-saved', (e) => {
  console.log('Widget saved event:', e);
});

window.addEventListener('widget-storage:updated', (e) => {
  console.log('Storage updated:', e);
});

๐Ÿ“š Type Definitions

Core Types

import { 
  Widget,
  WidgetType,
  WidgetVariant,
  PropertyGroup,
  PropertyDefinition,
  WidgetPropertyValues
} from '@libs-widgets/widget-builder';

import { 
  SpaceWidget,
  WidgetSearchCriteria,
  WidgetStats
} from '@libs-widgets/widgets-manager';

import {
  WidgetRegistration,
  WidgetMetadata
} from '@widgets';

๐Ÿšจ Common Errors & Solutions

Error: "Widget type not registered"

Solution: Ensure widget type is registered in WidgetMetadataRegistry

const registry = inject(WidgetMetadataRegistry);
if (!registry.has('my-widget')) {
  console.error('Widget type not registered');
}

Error: "Property groups undefined"

Solution: Always initialize propertyGroups array

const widget = {
  // ...
  propertyGroups: [], // Always include
  propertyValues: {}  // Always include
};

Error: "Storage key not found"

Solution: Check space ID and widget ID format

const key = `space_${spaceId}_widget_${widgetId}`;
const exists = await storage.get(key);
if (!exists) {
  console.error('Widget not found at key:', key);
}

๐Ÿ“– Related Documentation


Updated: November 15, 2025