82 lines
2.6 KiB
TypeScript
82 lines
2.6 KiB
TypeScript
import { Component } from '@angular/core';
|
|
import { NgFor } from '@angular/common';
|
|
import { CdkDrag, CdkDropList } from '@angular/cdk/drag-drop';
|
|
import { MatIconModule } from '@angular/material/icon';
|
|
import { MatListModule } from '@angular/material/list';
|
|
import { ComponentType, getComponentLabel, getComponentIcon } from '../../core/models/component';
|
|
import { BuilderStateService } from '../services/builder-state.service';
|
|
|
|
const CATEGORIES: { label: string; types: ComponentType[] }[] = [
|
|
{
|
|
label: 'Content',
|
|
types: ['HEADING', 'TEXT', 'DIVIDER'],
|
|
},
|
|
{
|
|
label: 'Media',
|
|
types: ['IMAGE', 'GALLERY', 'VIDEO'],
|
|
},
|
|
{
|
|
label: 'Interactive',
|
|
types: ['BUTTON', 'CONTACT_FORM', 'MAP'],
|
|
},
|
|
{
|
|
label: 'Advanced',
|
|
types: ['CUSTOM_HTML'],
|
|
},
|
|
];
|
|
|
|
@Component({
|
|
selector: 'app-component-palette',
|
|
standalone: true,
|
|
imports: [NgFor, CdkDropList, CdkDrag, MatIconModule, MatListModule],
|
|
template: `
|
|
<div class="p-3">
|
|
<h3 class="text-sm font-semibold text-gray-500 uppercase tracking-wider mb-3 px-2">Components</h3>
|
|
<div cdkDropList [cdkDropListData]="allTypes" (cdkDropListDropped)="noop()" class="space-y-4">
|
|
<div *ngFor="let cat of categories" class="mb-4">
|
|
<p class="text-xs text-gray-400 uppercase px-2 mb-2">{{ cat.label }}</p>
|
|
<div class="space-y-1">
|
|
<div *ngFor="let type of cat.types"
|
|
cdkDrag
|
|
[cdkDragData]="type"
|
|
class="flex items-center gap-2 px-3 py-2 rounded-md cursor-grab
|
|
text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600
|
|
transition-colors border border-transparent hover:border-blue-200"
|
|
(click)="addComponent(type)">
|
|
<mat-icon class="text-lg" style="width: 20px; height: 20px; font-size: 18px;">{{ getIcon(type) }}</mat-icon>
|
|
<span>{{ getLabel(type) }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`,
|
|
styles: [`
|
|
:host { display: block; }
|
|
.cdk-drag-preview {
|
|
@apply bg-white shadow-lg rounded-md border border-blue-200 px-3 py-2 text-sm;
|
|
}
|
|
.cdk-drag-placeholder { opacity: 0; }
|
|
`],
|
|
})
|
|
export class ComponentPalette {
|
|
categories = CATEGORIES;
|
|
allTypes: ComponentType[] = CATEGORIES.flatMap(c => c.types);
|
|
|
|
constructor(private state: BuilderStateService) {}
|
|
|
|
getLabel(type: ComponentType): string {
|
|
return getComponentLabel(type);
|
|
}
|
|
|
|
getIcon(type: ComponentType): string {
|
|
return getComponentIcon(type);
|
|
}
|
|
|
|
addComponent(type: ComponentType): void {
|
|
this.state.addComponent(type);
|
|
}
|
|
|
|
noop(): void {}
|
|
}
|