@praxisui/page-builder
Version:
Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).
1 lines • 68 kB
Source Map (JSON)
{"version":3,"file":"praxisui-page-builder.mjs","sources":["../../../projects/praxis-page-builder/src/lib/shim.ts","../../../projects/praxis-page-builder/src/lib/editor/confirm-dialog.component.ts","../../../projects/praxis-page-builder/src/lib/editor/tile-toolbar.component.ts","../../../projects/praxis-page-builder/src/lib/editor/floating-toolbar.component.ts","../../../projects/praxis-page-builder/src/lib/editor/component-palette-dialog.component.ts","../../../projects/praxis-page-builder/src/lib/editor/connection-builder.component.ts","../../../projects/praxis-page-builder/src/lib/editor/connection-builder.component.html","../../../projects/praxis-page-builder/src/public-api.ts","../../../projects/praxis-page-builder/src/praxisui-page-builder.ts"],"sourcesContent":["export const PLACEHOLDER = 1;\n\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, Inject } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatDialogModule, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';\nimport { MatIconModule } from '@angular/material/icon';\nimport { PraxisIconDirective } from '@praxisui/core';\n\nexport interface ConfirmDialogData {\n title?: string;\n message?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n icon?: string;\n}\n\n@Component({\n selector: 'praxis-confirm-dialog',\n standalone: true,\n imports: [CommonModule, MatDialogModule, MatButtonModule, MatIconModule, PraxisIconDirective],\n template: `\n <h2 mat-dialog-title>\n <mat-icon aria-hidden=\"true\" style=\"vertical-align: middle; margin-right: 8px;\" [praxisIcon]=\"data.icon || 'warning'\"></mat-icon>\n {{ data.title || 'Confirmar ação' }}\n </h2>\n <div mat-dialog-content>\n <p>{{ data.message || 'Tem certeza que deseja prosseguir?' }}</p>\n </div>\n <div mat-dialog-actions align=\"end\">\n <button mat-button mat-dialog-close>{{ data.cancelLabel || 'Cancelar' }}</button>\n <button mat-raised-button color=\"warn\" [mat-dialog-close]=\"true\">{{ data.confirmLabel || 'Excluir' }}</button>\n </div>\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ConfirmDialogComponent {\n constructor(\n @Inject(MAT_DIALOG_DATA) public data: ConfirmDialogData,\n public ref: MatDialogRef<ConfirmDialogComponent, boolean>,\n ) {}\n}\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { PraxisIconDirective } from '@praxisui/core';\n\n@Component({\n selector: 'praxis-tile-toolbar',\n standalone: true,\n imports: [CommonModule, MatButtonModule, MatIconModule, MatTooltipModule, PraxisIconDirective],\n template: `\n <div class=\"pdx-tile-toolbar\" [class.always-visible]=\"selected\" role=\"toolbar\" aria-label=\"Ações do widget\">\n <button\n mat-mini-fab\n (click)=\"settings.emit()\"\n [matTooltip]=\"'Configurar widget'\"\n aria-label=\"Configurar widget\"\n >\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button\n mat-mini-fab\n color=\"primary\"\n class=\"pdx-drag-handle\"\n [matTooltip]=\"'Arrastar tile'\"\n aria-label=\"Arrastar tile\"\n >\n <mat-icon [praxisIcon]=\"'drag_indicator'\"></mat-icon>\n </button>\n <button\n mat-mini-fab\n color=\"warn\"\n (click)=\"remove.emit()\"\n [matTooltip]=\"'Excluir widget'\"\n aria-label=\"Excluir widget\"\n >\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n </button>\n </div>\n `,\n styles: [\n `\n :host { position: absolute; inset: 0; pointer-events: none; }\n .pdx-tile-toolbar {\n position: absolute;\n right: 6px;\n top: -18px; /* half outside to keep clear of tile content, but close enough to not lose hover */\n display: flex;\n gap: 6px;\n z-index: 5;\n opacity: 0;\n transition: opacity 120ms ease-in-out;\n pointer-events: auto; /* enabled when visible via parent rule */\n background: color-mix(in oklab, var(--md-sys-color-surface) 92%, transparent);\n backdrop-filter: blur(4px);\n border-radius: 999px;\n padding: 4px;\n box-shadow: var(--mat-elevation-level3, 0 4px 8px rgba(0,0,0,0.2));\n }\n .pdx-tile-toolbar.always-visible { opacity: 1; }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TileToolbarComponent {\n @Input() selected = false;\n @Input() widgetType: string | null = null;\n @Output() remove = new EventEmitter<void>();\n @Output() settings = new EventEmitter<void>();\n}\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { PraxisIconDirective } from '@praxisui/core';\n\n@Component({\n selector: 'praxis-floating-toolbar',\n standalone: true,\n imports: [CommonModule, MatButtonModule, MatIconModule, MatTooltipModule, PraxisIconDirective],\n template: `\n <div class=\"pdx-floating-toolbar\" *ngIf=\"visible\">\n <button mat-fab color=\"primary\" class=\"pdx-fab\" [matTooltip]=\"'Ações rápidas'\">\n <mat-icon [praxisIcon]=\"'build'\"></mat-icon>\n </button>\n <div class=\"pdx-actions\">\n <button mat-mini-fab color=\"primary\" (click)=\"add.emit()\" [matTooltip]=\"'Inserir componente'\" aria-label=\"Inserir componente\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"connections.emit()\" [matTooltip]=\"'Visualizar conexões (Diagrama)'\" aria-label=\"Visualizar conexões (Diagrama)\">\n <mat-icon [praxisIcon]=\"'device_hub'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"connectionsVisual.emit()\" [matTooltip]=\"'Editor Visual (beta)'\" aria-label=\"Editor Visual (beta)\">\n <mat-icon [praxisIcon]=\"'schema'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"connectionsEdit.emit()\" [matTooltip]=\"'Editar conexões (Builder)'\" aria-label=\"Editar conexões (Builder)\">\n <mat-icon [praxisIcon]=\"'tune'\"></mat-icon>\n </button>\n <button mat-mini-fab color=\"accent\" (click)=\"save.emit()\" [matTooltip]=\"'Salvar página'\" aria-label=\"Salvar página\">\n <mat-icon [praxisIcon]=\"'save'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"undo.emit()\" [disabled]=\"!canUndo\" [matTooltip]=\"'Desfazer'\" aria-label=\"Desfazer\">\n <mat-icon [praxisIcon]=\"'undo'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"redo.emit()\" [disabled]=\"!canRedo\" [matTooltip]=\"'Refazer'\" aria-label=\"Refazer\">\n <mat-icon [praxisIcon]=\"'redo'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"settings.emit()\" [matTooltip]=\"'Configurações da página'\" aria-label=\"Configurações da página\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button mat-mini-fab (click)=\"preview.emit()\" [matTooltip]=\"'Pré-visualizar'\" aria-label=\"Pré-visualizar\">\n <mat-icon [praxisIcon]=\"'visibility'\"></mat-icon>\n </button>\n </div>\n </div>\n `,\n styles: [\n `\n :host { position: absolute; inset: 0; pointer-events: none; }\n .pdx-floating-toolbar { position: absolute; right: 16px; bottom: 16px; display: flex; gap: 8px; align-items: center; pointer-events: auto; }\n .pdx-actions { display: flex; gap: 8px; }\n .pdx-fab { box-shadow: var(--mat-elevation-transition), var(--mat-elevation-level6, 0 6px 12px rgba(0,0,0,0.24)); }\n @media (max-width: 720px) {\n .pdx-actions { gap: 6px; }\n .pdx-floating-toolbar { right: 12px; bottom: 12px; }\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FloatingToolbarComponent {\n @Input() visible = false;\n @Input() canUndo = false;\n @Input() canRedo = false;\n\n @Output() add = new EventEmitter<void>();\n @Output() undo = new EventEmitter<void>();\n @Output() redo = new EventEmitter<void>();\n @Output() settings = new EventEmitter<void>();\n @Output() preview = new EventEmitter<void>();\n @Output() connections = new EventEmitter<void>();\n @Output() connectionsEdit = new EventEmitter<void>();\n @Output() connectionsVisual = new EventEmitter<void>();\n @Output() save = new EventEmitter<void>();\n}\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, Inject, OnInit, computed, effect, signal } from '@angular/core';\nimport { MatDialogModule, MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatIconModule } from '@angular/material/icon';\nimport { PraxisIconDirective } from '@praxisui/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { FormsModule } from '@angular/forms';\nimport { ComponentMetadataRegistry } from '@praxisui/core';\nimport { ComponentDocMeta } from '@praxisui/core';\n\nexport interface ComponentPaletteData {\n title?: string;\n allowedWidgetIds?: string[];\n allowedWidgetTags?: string[];\n predicate?: (m: ComponentDocMeta) => boolean;\n}\n\n@Component({\n selector: 'praxis-component-palette-dialog',\n standalone: true,\n imports: [CommonModule, FormsModule, MatDialogModule, MatFormFieldModule, MatInputModule, MatIconModule, MatButtonModule, PraxisIconDirective],\n template: `\n <h2 mat-dialog-title>\n <div class=\"dlg-title\">\n <mat-icon class=\"dlg-icon\" [praxisIcon]=\"'widgets'\"></mat-icon>\n <div class=\"dlg-texts\">\n <div class=\"dlg-head\">{{ data?.title || 'Inserir componente' }}</div>\n <div class=\"dlg-sub\">Escolha um componente para adicionar à página · {{ filtered().length }} disponíveis</div>\n </div>\n </div>\n </h2>\n <div mat-dialog-content class=\"pdx-palette-content\">\n <div class=\"pdx-grid\" [ngClass]=\"density()\" *ngIf=\"filtered().length; else emptyState\">\n <div\n *ngFor=\"let m of filtered(); trackBy: trackById\"\n class=\"pdx-card mat-elevation-z2\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Adicionar ' + (m.friendlyName || m.id)\"\n (click)=\"select(m.id)\"\n (keydown.enter)=\"select(m.id)\"\n (keydown.space)=\"select(m.id)\"\n >\n <div class=\"pdx-card-icon\">\n <mat-icon [praxisIcon]=\"m.icon || 'widgets'\"></mat-icon>\n </div>\n <div class=\"pdx-card-body\">\n <div class=\"pdx-card-title\">{{ m.friendlyName || m.id }}</div>\n <div class=\"pdx-card-desc\">{{ m.description || m.selector }}</div>\n </div>\n </div>\n </div>\n\n <ng-template #emptyState>\n <div class=\"pdx-empty\">\n <mat-icon [praxisIcon]=\"'sentiment_dissatisfied'\"></mat-icon>\n <div>Nenhum componente disponível</div>\n </div>\n </ng-template>\n </div>\n <div mat-dialog-actions align=\"end\">\n <button mat-stroked-button color=\"primary\" mat-dialog-close>Cancelar</button>\n </div>\n `,\n styles: [\n `\n :host { display: block; }\n h2[mat-dialog-title] {\n margin: 0;\n padding: 12px 24px 10px 24px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant, rgba(0,0,0,0.12));\n }\n .dlg-title { display: flex; align-items: center; gap: 10px; }\n .dlg-icon { color: var(--md-sys-color-primary, #3f51b5); }\n .dlg-head { font-size: 18px; font-weight: 600; line-height: 1.2; }\n .dlg-sub { font-size: 12px; opacity: 0.85; color: var(--md-sys-color-on-surface-variant, rgba(0,0,0,0.62)); }\n .pdx-palette-content { min-width: 480px; max-width: 920px; padding-top: 8px; }\n .pdx-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }\n .pdx-grid.dense { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }\n .pdx-grid.roomy { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }\n .pdx-card {\n position: relative;\n display: grid;\n grid-template-columns: 44px 1fr;\n grid-template-rows: auto auto;\n gap: 10px;\n padding: 14px;\n border: 1px solid transparent;\n border-radius: 14px;\n cursor: pointer;\n outline: none;\n min-height: 92px;\n background: \n linear-gradient(var(--md-sys-color-surface), var(--md-sys-color-surface)) padding-box,\n linear-gradient(135deg,\n color-mix(in oklab, var(--md-sys-color-primary, #3f51b5) 55%, transparent),\n color-mix(in oklab, var(--md-sys-color-secondary, #ff4081) 45%, transparent)\n ) border-box;\n transition: box-shadow .2s ease, background .25s ease, transform .06s ease;\n }\n .pdx-grid.dense .pdx-card { padding: 10px; border-radius: 12px; min-height: 84px; }\n .pdx-grid.roomy .pdx-card { padding: 16px; border-radius: 16px; min-height: 100px; }\n .pdx-card:focus, .pdx-card:hover {\n box-shadow: var(--mat-elevation-transition), var(--mat-elevation-level6, 0 6px 12px rgba(0,0,0,0.22));\n background:\n linear-gradient(var(--md-sys-color-surface), var(--md-sys-color-surface)) padding-box,\n linear-gradient(135deg,\n color-mix(in oklab, var(--md-sys-color-primary) 70%, transparent),\n color-mix(in oklab, var(--md-sys-color-secondary) 55%, transparent)\n ) border-box;\n }\n .pdx-card:active { transform: translateY(1px); }\n .pdx-card-icon { grid-row: span 2; display: flex; align-items: center; justify-content: center; color: color-mix(in oklab, var(--md-sys-color-primary) 70%, #666); }\n .pdx-card-title { font-weight: 600; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .pdx-card-desc { color: rgba(0,0,0,0.7); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word; }\n .pdx-empty { padding: 24px; display: grid; place-items: center; color: rgba(0,0,0,0.6); gap: 8px; }\n @media (max-width: 600px) { .pdx-palette-content { min-width: 320px; } .pdx-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ComponentPaletteDialogComponent implements OnInit {\n query = '';\n private all = signal<ComponentDocMeta[]>([]);\n filtered = computed(() => this.applyFilters());\n density = computed(() => {\n const n = this.filtered().length;\n if (n <= 4) return 'roomy';\n if (n > 12) return 'dense';\n return 'normal';\n });\n\n constructor(\n private dialogRef: MatDialogRef<ComponentPaletteDialogComponent, string>,\n private registry: ComponentMetadataRegistry,\n @Inject(MAT_DIALOG_DATA) public data?: ComponentPaletteData,\n ) {}\n\n ngOnInit(): void {\n this.all.set(this.registry.getAll());\n }\n\n select(id: string): void {\n this.dialogRef.close(id);\n }\n\n trackById = (_: number, m: ComponentDocMeta) => m.id;\n\n getPreview(m: ComponentDocMeta): string {\n return (m.description || m.selector || m.friendlyName || m.id || '').toString();\n }\n\n // Create effect in injection context (field initializer is allowed)\n private _adjustSizeEffect = effect(() => {\n const n = this.filtered().length;\n let width = '720px';\n if (n <= 4) width = '560px';\n else if (n <= 8) width = '680px';\n const container: any = (this.dialogRef as any)._containerInstance;\n if (container && container._config) {\n container._config.width = width;\n }\n });\n\n private applyFilters(): ComponentDocMeta[] {\n const list = (this.all() || []);\n const q = (this.query || '').toLowerCase();\n const allowIds = new Set((this.data?.allowedWidgetIds || []).map((s) => s.toLowerCase()));\n const allowTags = new Set((this.data?.allowedWidgetTags || []).map((s) => s.toLowerCase()));\n return list.filter((m) => {\n if (q) {\n const hay = `${m.id} ${m.friendlyName || ''} ${m.description || ''} ${m.selector || ''}`.toLowerCase();\n if (!hay.includes(q)) return false;\n }\n if (allowIds.size > 0 && !allowIds.has((m.id || '').toLowerCase())) return false;\n if (allowTags.size > 0 && !m.tags?.some(t => allowTags.has(t.toLowerCase()))) return false;\n if (typeof this.data?.predicate === 'function' && !this.data.predicate(m)) return false;\n return true;\n });\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, computed, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatListModule } from '@angular/material/list';\nimport { MatAutocompleteModule } from '@angular/material/autocomplete';\nimport { MatDialog, MatDialogModule } from '@angular/material/dialog';\nimport { MatMenuModule } from '@angular/material/menu';\nimport { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';\nimport { PraxisIconDirective } from '@praxisui/core';\nimport { MatTabsModule } from '@angular/material/tabs';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { ScrollingModule } from '@angular/cdk/scrolling';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { ComponentMetadataRegistry } from '@praxisui/core';\nimport { GridPageDefinition, GridWidgetInstance } from '@praxisui/core';\nimport { WidgetConnection } from '@praxisui/core';\n\n@Component({\n selector: 'praxis-connection-builder',\n standalone: true,\n imports: [CommonModule, FormsModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatButtonModule, MatIconModule, MatListModule, MatDialogModule, MatAutocompleteModule, MatMenuModule, MatTabsModule, MatTooltipModule, MatProgressBarModule, MatCheckboxModule, MatSnackBarModule, ScrollingModule, PraxisIconDirective],\n templateUrl: './connection-builder.component.html',\n styleUrls: ['./connection-builder.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ConnectionBuilderComponent implements OnInit, OnChanges {\n @Input() page?: GridPageDefinition | string;\n @Input() widgets?: GridWidgetInstance[];\n @Output() pageChange = new EventEmitter<GridPageDefinition>();\n\n // State\n private originalSnapshot = '';\n showOnlyIssues = false;\n showFriendly = true;\n filterText = '';\n groupBy: 'none' | 'from' | 'to' | 'event' = 'none';\n sortBy: 'from' | 'to' = 'from';\n // Move braces-containing placeholder into TS (AGENTS.md policy)\n mapPlaceholder = 'payload | payload.id | ${payload.id}';\n\n // Signals\n connections = signal<WidgetConnection[]>([]);\n selectedIndex = signal<number>(-1);\n\n // Derived lists\n readonly filteredConnections = computed(() => this.applyFilters(this.connections()));\n readonly groupedConnections = computed(() => this.applyGrouping(this.filteredConnections()));\n\n constructor(private dialog: MatDialog, private registry: ComponentMetadataRegistry, private snack: MatSnackBar) {}\n\n ngOnInit(): void {\n const p = this.parsePage(this.page);\n const ws = this.widgets || p?.widgets || [];\n this.widgets = ws;\n const conns = [...(p?.connections || [])];\n this.connections.set(conns);\n this.originalSnapshot = JSON.stringify(conns);\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['page'] || changes['widgets']) {\n const p = this.parsePage(this.page);\n this.widgets = this.widgets || p?.widgets || [];\n const next = [...(p?.connections || [])];\n this.connections.set(next);\n this.originalSnapshot = JSON.stringify(next);\n }\n }\n\n // UI helpers\n isExpanded(i: number): boolean { return i === this.selectedIndex(); }\n toggleExpanded(i: number, ev?: Event): void { if (ev) ev.stopPropagation(); this.selectedIndex.set(this.selectedIndex() === i ? -1 : i); }\n setSortBy(v: 'from' | 'to'): void { this.sortBy = v; this.connections.set(this.sortList([...this.connections()])); }\n onGroupByChange(): void {}\n toggleShowOnlyIssues(): void { this.showOnlyIssues = !this.showOnlyIssues; }\n toggleFriendly(): void { this.showFriendly = !this.showFriendly; }\n trackByIndex = (i: number) => i;\n\n // Labels\n fromLabel(c: WidgetConnection): string { return `${c.from.widget}.${c.from.output}`; }\n toLabel(c: WidgetConnection): string { return `${c.to.widget}.${c.to.input}`; }\n fromFriendly(c: WidgetConnection): string { return `${this.widgetFriendlyNameForKey(c.from.widget)}.${c.from.output}`; }\n toFriendly(c: WidgetConnection): string { return `${this.widgetFriendlyNameForKey(c.to.widget)}.${c.to.input}`; }\n outputDescription(c: WidgetConnection): string { return this.registry.get(this.widgetTypeByKey(c.from.widget))?.outputs?.find(o => o.name === c.from.output)?.description || ''; }\n inputDescription(c: WidgetConnection): string { return this.registry.get(this.widgetTypeByKey(c.to.widget))?.inputs?.find(i => i.name === c.to.input)?.description || ''; }\n widgetFriendlyNameForKey(key: string): string { const id = this.widgetTypeByKey(key); return this.registry.get(id)?.friendlyName || id; }\n componentIconForKey(key: string): string { const id = this.widgetTypeByKey(key); return this.registry.get(id)?.icon || 'widgets'; }\n private widgetTypeByKey(key: string): string { return this.widgets?.find(w => w.key === key)?.definition?.id || key; }\n\n private applyFilters(list: WidgetConnection[]): WidgetConnection[] {\n const q = (this.filterText || '').toLowerCase();\n const arr = list.filter((c) => {\n if (this.showOnlyIssues && this.connectionStatus(c) === 'ok') return false;\n if (!q) return true;\n const hay = `${c.from.widget}.${c.from.output} ${c.to.widget}.${c.to.input} ${c.map || ''}`.toLowerCase();\n return hay.includes(q);\n });\n return this.sortList(arr);\n }\n\n private applyGrouping(list: WidgetConnection[]): Array<{ label: string; list: WidgetConnection[] }>\n {\n switch (this.groupBy) {\n case 'from': return this.groupByKey(list, c => `${c.from.widget}.${c.from.output}`);\n case 'to': return this.groupByKey(list, c => `${c.to.widget}.${c.to.input}`);\n case 'event': return this.groupByKey(list, c => `${c.from.output}`);\n default: return [{ label: 'Todas', list }];\n }\n }\n\n private groupByKey(list: WidgetConnection[], keyFn: (c: WidgetConnection) => string): Array<{ label: string; list: WidgetConnection[] }>\n {\n const map = new Map<string, WidgetConnection[]>();\n for (const c of list) { const k = keyFn(c); const arr = map.get(k) || []; arr.push(c); map.set(k, arr); }\n return Array.from(map.entries()).map(([k, v]) => ({ label: k, list: v }));\n }\n\n private sortList(list: WidgetConnection[]): WidgetConnection[] {\n return [...list].sort((a, b) => {\n if (this.sortBy === 'from') return this.fromLabel(a).localeCompare(this.fromLabel(b));\n return this.toLabel(a).localeCompare(this.toLabel(b));\n });\n }\n\n // Editing\n createNew(): void {\n const fromKey = this.widgets?.[0]?.key || '';\n const toKey = this.widgets?.[1]?.key || '';\n const conn: WidgetConnection = { from: { widget: fromKey, output: 'submit' }, to: { widget: toKey, input: 'context' } } as any;\n this.connections.set([conn, ...this.connections()]);\n }\n startEdit(index: number, _c: WidgetConnection): void { this.selectedIndex.set(index); }\n startEditByConn(c: WidgetConnection): void { const i = this.connections().indexOf(c); if (i >= 0) this.startEdit(i, c); }\n duplicateConnection(index: number): void { const next = [...this.connections()]; const c = next[index]; if (!c) return; next.splice(index + 1, 0, { ...c }); this.connections.set(next); }\n removeConnection(index: number): void { const next = [...this.connections()]; if (index < 0 || index >= next.length) return; next.splice(index, 1); this.connections.set(next); }\n\n // Validation\n connectionStatus(c: WidgetConnection): 'ok' | 'warn' | 'err' {\n if (!c.from?.widget || !c.from?.output || !c.to?.widget || !c.to?.input) return 'err';\n const wFrom = this.widgetTypeByKey(c.from.widget);\n const wTo = this.widgetTypeByKey(c.to.widget);\n const outOk = !!this.registry.get(wFrom)?.outputs?.some(o => o.name === c.from.output);\n const inOk = !!this.registry.get(wTo)?.inputs?.some(i => i.name === c.to.input);\n if (!outOk || !inOk) return 'warn';\n return 'ok';\n }\n\n // Persist/apply\n onSave(): void {\n const p = this.parsePage(this.page) || ({} as GridPageDefinition);\n const next: GridPageDefinition = { ...(p as any), connections: this.connections() };\n this.page = next;\n this.pageChange.emit(next);\n this.snack.open('Conexões salvas', undefined, { duration: 1000 });\n this.originalSnapshot = JSON.stringify(this.connections());\n }\n\n // Diagram helpers\n openDiagramFor(_c: WidgetConnection): void {\n import('./connection-graph/connection-graph.component').then(m => {\n this.dialog.open((m as any).ConnectionGraphComponent as any, { width: '95vw', height: '80vh', maxWidth: '100vw', panelClass: 'praxis-conn-graph-dialog' });\n });\n }\n openDiagramFullscreen(): void {\n import('./connection-graph/connection-graph.component').then(m => {\n this.dialog.open((m as any).ConnectionGraphComponent as any, { width: '95vw', height: '95vh', maxWidth: '100vw', panelClass: 'praxis-conn-graph-dialog', autoFocus: false, restoreFocus: false });\n });\n }\n\n private parsePage(input?: GridPageDefinition | string | null): GridPageDefinition | undefined {\n if (!input) return undefined;\n if (typeof input === 'string') { try { return JSON.parse(input) as GridPageDefinition; } catch { return undefined; } }\n return input;\n }\n}\n","<div class=\"pdx-conn-root\" role=\"region\" aria-label=\"Construtor de Conexões\">\n <div class=\"pdx-conn-head\">\n <span class=\"pdx-conn-title\">Conexões</span>\n <span class=\"pdx-conn-count\" aria-label=\"Conexões filtradas e total\">{{ filteredConnections().length }} / {{ connections().length }}</span>\n <mat-form-field appearance=\"outline\" class=\"pdx-conn-search\">\n <mat-label>Buscar</mat-label>\n <input matInput [(ngModel)]=\"filterText\" placeholder=\"Origem, Destino, Input, Map...\" />\n <button mat-icon-button matSuffix *ngIf=\"filterText\" (click)=\"filterText='';\" aria-label=\"Limpar busca\"><mat-icon [praxisIcon]=\"'close'\"></mat-icon></button>\n </mat-form-field>\n <span class=\"pdx-spacer\"></span>\n <button mat-button (click)=\"toggleShowOnlyIssues()\" [color]=\"showOnlyIssues ? 'primary': undefined\" aria-label=\"Somente avisos/erros\"><mat-icon [praxisIcon]=\"'report_problem'\"></mat-icon> Issues</button>\n <mat-form-field appearance=\"outline\" style=\"width: 160px;\">\n <mat-label>Ordenar por</mat-label>\n <mat-select [(ngModel)]=\"sortBy\" (ngModelChange)=\"setSortBy($event)\">\n <mat-option value=\"from\">Origem</mat-option>\n <mat-option value=\"to\">Destino</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" style=\"width: 170px;\">\n <mat-label>Agrupar por</mat-label>\n <mat-select [(ngModel)]=\"groupBy\" (ngModelChange)=\"onGroupByChange()\">\n <mat-option value=\"none\">Nenhum</mat-option>\n <mat-option value=\"from\">Origem</mat-option>\n <mat-option value=\"to\">Destino</mat-option>\n <mat-option value=\"event\">Evento</mat-option>\n </mat-select>\n </mat-form-field>\n <button mat-icon-button [color]=\"showFriendly ? 'primary' : undefined\" (click)=\"toggleFriendly()\" aria-label=\"Alternar nome amigável/técnico\"><mat-icon [praxisIcon]=\"'translate'\"></mat-icon></button>\n <button mat-stroked-button (click)=\"createNew()\" aria-label=\"Nova conexão\"><mat-icon [praxisIcon]=\"'add'\"></mat-icon> Nova Conexão</button>\n <button mat-flat-button color=\"accent\" class=\"pdx-diagram-cta\" (click)=\"openDiagramFullscreen()\" aria-label=\"Abrir diagrama em tela cheia\" matTooltip=\"Visualizar conexões em grafo\"><mat-icon [praxisIcon]=\"'schema'\"></mat-icon><span>Diagrama</span></button>\n </div>\n\n <div class=\"pdx-conn-grid\">\n <!-- Left: read-only list -->\n <div class=\"pdx-conn-list\" role=\"list\" aria-label=\"Lista de conexões\" cdkScrollable>\n <mat-list *ngIf=\"filteredConnections().length; else noConns\">\n <ng-container *ngIf=\"groupBy!=='none'; else flatList\">\n <div class=\"group-block\" *ngFor=\"let g of groupedConnections(); let gi = index\">\n <div class=\"group-header\">\n <span class=\"group-title\">{{ g.label }}</span>\n <span class=\"group-count\">{{ g.list.length }}</span>\n </div>\n <mat-divider></mat-divider>\n <div class=\"group-list\">\n <ng-container *ngFor=\"let c of g.list; let i = index\">\n <mat-list-item role=\"listitem\" (click)=\"startEdit(i, c)\" [class.selected]=\"selectedIndex()===i\">\n <div class=\"card-head\" matListItemTitle [matTooltip]=\"showFriendly ? (c.from.widget + '.' + c.from.output + ' → ' + (c.to.widget + '.' + c.to.input)) : ''\">\n <mat-icon class=\"comp-icon from\" [matTooltip]=\"widgetFriendlyNameForKey(c.from.widget)\">{{ componentIconForKey(c.from.widget) }}</mat-icon>\n <span class=\"pdx-badge from\" aria-hidden=\"true\"></span>\n <span class=\"from\">{{ showFriendly ? fromFriendly(c) : fromLabel(c) }}</span>\n <span class=\"arrow\">→</span>\n <mat-icon class=\"comp-icon to\" [matTooltip]=\"widgetFriendlyNameForKey(c.to.widget)\">{{ componentIconForKey(c.to.widget) }}</mat-icon>\n <span class=\"pdx-badge to\" aria-hidden=\"true\"></span>\n <span class=\"to\">{{ showFriendly ? toFriendly(c) : toLabel(c) }}</span>\n <span class=\"spacer\"></span>\n <span class=\"status-pill\" [class.ok]=\"connectionStatus(c)==='ok'\" [class.warn]=\"connectionStatus(c)==='warn'\" [class.err]=\"connectionStatus(c)==='err'\">\n <mat-icon *ngIf=\"connectionStatus(c)==='ok'\">check_circle</mat-icon>\n <mat-icon *ngIf=\"connectionStatus(c)==='warn'\">warning</mat-icon>\n <mat-icon *ngIf=\"connectionStatus(c)==='err'\">error</mat-icon>\n </span>\n <button mat-icon-button class=\"expand-btn\" [attr.aria-expanded]=\"isExpanded(i)\" (click)=\"toggleExpanded(i, $event)\" [matTooltip]=\"isExpanded(i) ? 'Recolher detalhes' : 'Expandir detalhes'\">\n <mat-icon>{{ isExpanded(i) ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </div>\n <div class=\"meta\" *ngIf=\"showFriendly\" matListItemLine>\n <span class=\"hint\">{{ outputDescription(c) }}</span>\n <span class=\"sep\" *ngIf=\"outputDescription(c) && inputDescription(c)\">•</span>\n <span class=\"hint\">{{ inputDescription(c) }}</span>\n </div>\n <div class=\"map-chip\" *ngIf=\"c.map\" [matTooltip]=\"c.map || ''\" matListItemLine (click)=\"startEditByConn(c)\" title=\"Clique para editar Map\">\n <span class=\"pdx-badge map\" aria-hidden=\"true\"></span>\n <mat-icon class=\"map-icon\" inline>bolt</mat-icon>\n <span class=\"mono\">{{ c.map }}</span>\n </div>\n <div class=\"card-actions\" matListItemLine (click)=\"$event.stopPropagation()\">\n <span class=\"action-group\">\n <button mat-icon-button (click)=\"startEdit(i, c)\" matTooltip=\"Editar\"><mat-icon>settings</mat-icon></button>\n <button mat-icon-button (click)=\"duplicateConnection(i)\" matTooltip=\"Duplicar\"><mat-icon>content_copy</mat-icon></button>\n </span>\n <span class=\"action-group\">\n <button mat-stroked-button color=\"primary\" (click)=\"openDiagramFor(c)\" matTooltip=\"Ver relação no diagrama\"><mat-icon>schema</mat-icon><span>Diagrama</span></button>\n </span>\n <span class=\"spacer\"></span>\n <span class=\"action-group\">\n <button mat-icon-button color=\"warn\" (click)=\"removeConnection(i)\" matTooltip=\"Remover\"><mat-icon>delete</mat-icon></button>\n </span>\n </div>\n <div class=\"card-details\" matListItemLine [class.expanded]=\"isExpanded(i)\" [style.maxHeight]=\"isExpanded(i) ? '240px' : '0px'\" [style.opacity]=\"isExpanded(i) ? 1 : 0\" [style.pointerEvents]=\"isExpanded(i) ? 'auto' : 'none'\">\n <div class=\"stepper\">\n <div class=\"step from-step\">\n <div class=\"dot from\"></div>\n <div class=\"content\">\n <div class=\"label\">De</div>\n <div class=\"value\">{{ showFriendly ? fromFriendly(c) : fromLabel(c) }}</div>\n </div>\n </div>\n <div class=\"step to-step\">\n <div class=\"dot to\"></div>\n <div class=\"content\">\n <div class=\"label\">Para</div>\n <div class=\"value\">{{ showFriendly ? toFriendly(c) : toLabel(c) }}</div>\n </div>\n </div>\n <div class=\"step map-step\" *ngIf=\"c.map\">\n <div class=\"dot map\"></div>\n <div class=\"content\">\n <div class=\"label\">Map</div>\n <div class=\"value mono\">{{ c.map }}</div>\n </div>\n </div>\n </div>\n </div>\n </mat-list-item>\n </ng-container>\n </div>\n </div>\n </ng-container>\n <ng-template #flatList>\n <ng-container *ngFor=\"let c of filteredConnections(); let i = index\">\n <mat-list-item role=\"listitem\" (click)=\"startEdit(i, c)\" [class.selected]=\"selectedIndex()===i\">\n <div class=\"card-head\" matListItemTitle [matTooltip]=\"showFriendly ? (c.from.widget + '.' + c.from.output + ' → ' + (c.to.widget + '.' + c.to.input)) : ''\">\n <mat-icon class=\"comp-icon from\" [matTooltip]=\"widgetFriendlyNameForKey(c.from.widget)\">{{ componentIconForKey(c.from.widget) }}</mat-icon>\n <span class=\"pdx-badge from\" aria-hidden=\"true\"></span>\n <span class=\"from\">{{ showFriendly ? fromFriendly(c) : fromLabel(c) }}</span>\n <span class=\"arrow\">→</span>\n <mat-icon class=\"comp-icon to\" [matTooltip]=\"widgetFriendlyNameForKey(c.to.widget)\">{{ componentIconForKey(c.to.widget) }}</mat-icon>\n <span class=\"pdx-badge to\" aria-hidden=\"true\"></span>\n <span class=\"to\">{{ showFriendly ? toFriendly(c) : toLabel(c) }}</span>\n <span class=\"spacer\"></span>\n <span class=\"status-pill\" [class.ok]=\"connectionStatus(c)==='ok'\" [class.warn]=\"connectionStatus(c)==='warn'\" [class.err]=\"connectionStatus(c)==='err'\">\n <mat-icon *ngIf=\"connectionStatus(c)==='ok'\">check_circle</mat-icon>\n <mat-icon *ngIf=\"connectionStatus(c)==='warn'\">warning</mat-icon>\n <mat-icon *ngIf=\"connectionStatus(c)==='err'\">error</mat-icon>\n </span>\n <button mat-icon-button class=\"expand-btn\" [attr.aria-expanded]=\"isExpanded(i)\" (click)=\"toggleExpanded(i, $event)\" [matTooltip]=\"isExpanded(i) ? 'Recolher detalhes' : 'Expandir detalhes'\">\n <mat-icon>{{ isExpanded(i) ? 'expand_less' : 'expand_more' }}</mat-icon>\n </button>\n </div>\n <div class=\"meta\" *ngIf=\"showFriendly\" matListItemLine>\n <span class=\"hint\">{{ outputDescription(c) }}</span>\n <span class=\"sep\" *ngIf=\"outputDescription(c) && inputDescription(c)\">•</span>\n <span class=\"hint\">{{ inputDescription(c) }}</span>\n </div>\n <div class=\"map-chip\" *ngIf=\"c.map\" [matTooltip]=\"c.map || ''\" matListItemLine (click)=\"startEditByConn(c)\" title=\"Clique para editar Map\">\n <span class=\"pdx-badge map\" aria-hidden=\"true\"></span>\n <mat-icon class=\"map-icon\" inline>bolt</mat-icon>\n <span class=\"mono\">{{ c.map }}</span>\n </div>\n <div class=\"card-actions\" matListItemLine (click)=\"$event.stopPropagation()\">\n <span class=\"action-group\">\n <button mat-icon-button (click)=\"startEdit(i, c)\" matTooltip=\"Editar\"><mat-icon>settings</mat-icon></button>\n <button mat-icon-button (click)=\"duplicateConnection(i)\" matTooltip=\"Duplicar\"><mat-icon>content_copy</mat-icon></button>\n </span>\n <span class=\"action-group\">\n <button mat-stroked-button color=\"primary\" (click)=\"openDiagramFor(c)\" matTooltip=\"Ver relação no diagrama\"><mat-icon>schema</mat-icon><span>Diagrama</span></button>\n </span>\n <span class=\"spacer\"></span>\n <span class=\"action-group\">\n <button mat-icon-button color=\"warn\" (click)=\"removeConnection(i)\" matTooltip=\"Remover\"><mat-icon>delete</mat-icon></button>\n </span>\n </div>\n <div class=\"card-details\" matListItemLine [class.expanded]=\"isExpanded(i)\" [style.maxHeight]=\"isExpanded(i) ? '240px' : '0px'\" [style.opacity]=\"isExpanded(i) ? 1 : 0\" [style.pointerEvents]=\"isExpanded(i) ? 'auto' : 'none'\">\n <div class=\"stepper\">\n <div class=\"step from-step\">\n <div class=\"dot from\"></div>\n <div class=\"content\">\n <div class=\"label\">De</div>\n <div class=\"value\">{{ showFriendly ? fromFriendly(c) : fromLabel(c) }}</div>\n </div>\n </div>\n <div class=\"step to-step\">\n <div class=\"dot to\"></div>\n <div class=\"content\">\n <div class=\"label\">Para</div>\n <div class=\"value\">{{ showFriendly ? toFriendly(c) : toLabel(c) }}</div>\n </div>\n </div>\n <div class=\"step map-step\" *ngIf=\"c.map\">\n <div class=\"dot map\"></div>\n <div class=\"content\">\n <div class=\"label\">Map</div>\n <div class=\"value mono\">{{ c.map }}</div>\n </div>\n </div>\n </div>\n </div>\n </mat-list-item>\n </ng-container>\n </ng-template>\n </mat-list>\n <ng-template #noConns>\n <div class=\"pdx-empty-list\" role=\"status\" aria-live=\"polite\">\n <mat-icon>link_off</mat-icon>\n <div>Nenhuma conexão definida. Use “Nova Conexão”.</div>\n </div>\n </ng-template>\n </div>\n\n <!-- Right: editor form -->\n <div class=\"pdx-conn-editor\" role=\"form\" aria-label=\"Editor de conexão\">\n <ng-container *ngIf=\"selectedIndex() >= 0; else emptyEditor\">\n <div class=\"form-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>Origem (widget.key)</mat-label>\n <input matInput [(ngModel)]=\"connections()[selectedIndex()].from.widget\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Evento (output)</mat-label>\n <input matInput [(ngModel)]=\"connections()[selectedIndex()].from.output\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Destino (widget.key)</mat-label>\n <input matInput [(ngModel)]=\"connections()[selectedIndex()].to.widget\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>Input</mat-label>\n <input matInput [(ngModel)]=\"connections()[selectedIndex()].to.input\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"full-span\">\n <mat-label>Map (opcional)</mat-label>\n <input matInput [(ngModel)]=\"connections()[selectedIndex()].map\" [placeholder]=\"mapPlaceholder\" />\n </mat-form-field>\n <div class=\"full-span\">\n <button mat-flat-button color=\"primary\" (click)=\"onSave()\"><mat-icon [praxisIcon]=\"'save'\"></mat-icon>Salvar</button>\n </div>\n </div>\n </ng-container>\n <ng-template #emptyEditor>\n <div class=\"pdx-empty-editor\">Selecione uma conexão para editar.</div>\n </ng-template>\n </div>\n </div>\n</div>\n","/*\n * Public API Surface of @praxisui/page-builder\n */\n\n// Temporary minimal export for build isolation\nexport * from './lib/shim';\nexport * from './lib/editor/confirm-dialog.component';\nexport * from './lib/editor/tile-toolbar.component';\nexport * from './lib/editor/floating-toolbar.component';\nexport * from './lib/editor/component-palette-dialog.component';\nexport * from './lib/editor/connection-builder.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1","i2","i3","i4","i5","i10","i11","i13"],"mappings":"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