import { Component, Output, EventEmitter, ViewChild } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { buildCuratedFormSchema, } from '@memberjunction/interactive-component-types/forms';
import { MJReactComponent } from '@memberjunction/ng-react';
import { CompositeKey, LogError, RunView, } from '@memberjunction/core';
import { SharedService } from '@memberjunction/ng-shared';
import { buildFixtureFormHostProps } from '../../services/form-host-props-fixture';
import * as i0 from "@angular/core";
import * as i1 from "../../services/component-studio-state.service";
import * as i2 from "@angular/common";
import * as i3 from "@angular/forms";
import * as i4 from "@memberjunction/ng-react";
import * as i5 from "@memberjunction/ng-ui-components";
const _c0 = ["reactComponent"];
const _forTrack0 = ($index, $item) => $item.Size;
const _forTrack1 = ($index, $item) => $item.ID;
function ComponentPreviewComponent_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
    const _r1 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 14);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_3_Conditional_0_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.StopComponent()); });
    i0.ɵɵelement(1, "i", 15);
    i0.ɵɵelementStart(2, "span");
    i0.ɵɵtext(3, "Stop");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(4, "button", 16);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_3_Conditional_0_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RefreshComponent()); });
    i0.ɵɵelement(5, "i", 17);
    i0.ɵɵelementStart(6, "span");
    i0.ɵɵtext(7, "Refresh");
    i0.ɵɵelementEnd()();
} }
function ComponentPreviewComponent_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
    const _r3 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 18);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_3_Conditional_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RunSelectedComponent()); });
    i0.ɵɵelement(1, "i", 19);
    i0.ɵɵelementStart(2, "span");
    i0.ɵɵtext(3, "Run");
    i0.ɵɵelementEnd()();
} }
function ComponentPreviewComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵconditionalCreate(0, ComponentPreviewComponent_Conditional_3_Conditional_0_Template, 8, 0)(1, ComponentPreviewComponent_Conditional_3_Conditional_1_Template, 4, 0, "button", 13);
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵconditional(ctx_r1.State.IsRunning ? 0 : 1);
} }
function ComponentPreviewComponent_Conditional_5_For_2_Template(rf, ctx) { if (rf & 1) {
    const _r4 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 21);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_5_For_2_Template_button_click_0_listener() { const preset_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SetViewport(preset_r5.Size)); });
    i0.ɵɵelement(1, "i", 22);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const preset_r5 = ctx.$implicit;
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵclassProp("active", ctx_r1.ActiveViewport === preset_r5.Size);
    i0.ɵɵproperty("title", preset_r5.Label);
    i0.ɵɵadvance();
    i0.ɵɵproperty("ngClass", preset_r5.Icon);
} }
function ComponentPreviewComponent_Conditional_5_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "div", 5);
    i0.ɵɵrepeaterCreate(1, ComponentPreviewComponent_Conditional_5_For_2_Template, 2, 4, "button", 20, _forTrack0);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance();
    i0.ɵɵrepeater(ctx_r1.ViewportPresets);
} }
function ComponentPreviewComponent_Conditional_7_Template(rf, ctx) { if (rf & 1) {
    const _r6 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "button", 23);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_7_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SendErrorToAI()); });
    i0.ɵɵelement(1, "i", 24);
    i0.ɵɵelementStart(2, "span");
    i0.ɵɵtext(3, "Ask AI to Fix");
    i0.ɵɵelementEnd()();
} }
function ComponentPreviewComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "span", 8);
    i0.ɵɵelement(1, "i", 25);
    i0.ɵɵtext(2);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate1(" ", ctx_r1.GetComponentName(), " ");
} }
function ComponentPreviewComponent_Conditional_9_Conditional_12_For_7_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "option", 34);
    i0.ɵɵtext(1);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const r_r9 = ctx.$implicit;
    i0.ɵɵproperty("value", r_r9.ID);
    i0.ɵɵadvance();
    i0.ɵɵtextInterpolate(r_r9.Display);
} }
function ComponentPreviewComponent_Conditional_9_Conditional_12_Conditional_8_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "i", 35);
} }
function ComponentPreviewComponent_Conditional_9_Conditional_12_Template(rf, ctx) { if (rf & 1) {
    const _r8 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 31)(1, "label");
    i0.ɵɵtext(2, "Record");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(3, "select", 32);
    i0.ɵɵlistener("change", function ComponentPreviewComponent_Conditional_9_Conditional_12_Template_select_change_3_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnPickRecord($event)); });
    i0.ɵɵelementStart(4, "option", 33);
    i0.ɵɵtext(5, "\u2014 Fixture data \u2014");
    i0.ɵɵelementEnd();
    i0.ɵɵrepeaterCreate(6, ComponentPreviewComponent_Conditional_9_Conditional_12_For_7_Template, 2, 2, "option", 34, _forTrack1);
    i0.ɵɵelementEnd();
    i0.ɵɵconditionalCreate(8, ComponentPreviewComponent_Conditional_9_Conditional_12_Conditional_8_Template, 1, 0, "i", 35);
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(3);
    i0.ɵɵproperty("value", ctx_r1.SelectedRecordID ?? "");
    i0.ɵɵadvance(3);
    i0.ɵɵrepeater(ctx_r1.RecentRecords);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r1.IsLoadingRecord ? 8 : -1);
} }
function ComponentPreviewComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
    const _r7 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 9)(1, "div", 26);
    i0.ɵɵelement(2, "i", 27);
    i0.ɵɵtext(3, " PREVIEW \u2014 changes will not be saved ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "div", 28)(5, "div", 29)(6, "button", 30);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_9_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetFormPreviewMode("view")); });
    i0.ɵɵtext(7, "View");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "button", 30);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_9_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetFormPreviewMode("edit")); });
    i0.ɵɵtext(9, "Edit");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(10, "button", 30);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_9_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.SetFormPreviewMode("create")); });
    i0.ɵɵtext(11, "Create");
    i0.ɵɵelementEnd()();
    i0.ɵɵconditionalCreate(12, ComponentPreviewComponent_Conditional_9_Conditional_12_Template, 9, 2, "div", 31);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵadvance(6);
    i0.ɵɵclassProp("active", ctx_r1.FormPreviewMode === "view");
    i0.ɵɵadvance(2);
    i0.ɵɵclassProp("active", ctx_r1.FormPreviewMode === "edit");
    i0.ɵɵadvance(2);
    i0.ɵɵclassProp("active", ctx_r1.FormPreviewMode === "create");
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r1.FormPreviewMode !== "create" && ctx_r1.FormTargetEntity ? 12 : -1);
} }
function ComponentPreviewComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelement(0, "mj-empty-state", 11);
} }
function ComponentPreviewComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
    const _r10 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "mj-empty-state", 36);
    i0.ɵɵlistener("Action", function ComponentPreviewComponent_Conditional_12_Template_mj_empty_state_Action_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.RunSelectedComponent()); });
    i0.ɵɵelementEnd();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵproperty("Title", ctx_r1.GetComponentName())("Message", ctx_r1.GetComponentDescription() || "No description available");
} }
function ComponentPreviewComponent_Conditional_13_Conditional_3_For_10_Template(rf, ctx) { if (rf & 1) {
    i0.ɵɵelementStart(0, "li", 46)(1, "span", 47);
    i0.ɵɵtext(2);
    i0.ɵɵpipe(3, "date");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(4, "span", 48);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(6, "span", 49);
    i0.ɵɵtext(7);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const e_r13 = ctx.$implicit;
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(3, 3, e_r13.Timestamp, "HH:mm:ss"));
    i0.ɵɵadvance(3);
    i0.ɵɵtextInterpolate(e_r13.Type);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(e_r13.Payload);
} }
function ComponentPreviewComponent_Conditional_13_Conditional_3_Template(rf, ctx) { if (rf & 1) {
    const _r12 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 39)(1, "div", 41);
    i0.ɵɵelement(2, "i", 42);
    i0.ɵɵelementStart(3, "span");
    i0.ɵɵtext(4, "Events (sandboxed)");
    i0.ɵɵelementEnd();
    i0.ɵɵelement(5, "span", 43);
    i0.ɵɵelementStart(6, "button", 44);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_13_Conditional_3_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r12); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.ClearEventLog()); });
    i0.ɵɵtext(7, "Clear");
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(8, "ul", 45);
    i0.ɵɵrepeaterCreate(9, ComponentPreviewComponent_Conditional_13_Conditional_3_For_10_Template, 8, 6, "li", 46, i0.ɵɵrepeaterTrackByIndex);
    i0.ɵɵelementEnd()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(9);
    i0.ɵɵrepeater(ctx_r1.EventLog);
} }
function ComponentPreviewComponent_Conditional_13_Conditional_4_Template(rf, ctx) { if (rf & 1) {
    const _r14 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 40)(1, "div", 50)(2, "div", 51);
    i0.ɵɵelement(3, "i", 52);
    i0.ɵɵelementStart(4, "span", 53);
    i0.ɵɵtext(5);
    i0.ɵɵelementEnd()();
    i0.ɵɵelementStart(6, "p", 54);
    i0.ɵɵtext(7);
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(8, "div", 55)(9, "button", 56);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_13_Conditional_4_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.RefreshComponent()); });
    i0.ɵɵelement(10, "i", 17);
    i0.ɵɵtext(11, " Retry ");
    i0.ɵɵelementEnd();
    i0.ɵɵelementStart(12, "button", 57);
    i0.ɵɵlistener("click", function ComponentPreviewComponent_Conditional_13_Conditional_4_Template_button_click_12_listener() { i0.ɵɵrestoreView(_r14); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SendErrorToAI()); });
    i0.ɵɵelement(13, "i", 24);
    i0.ɵɵtext(14, " Ask AI to Fix ");
    i0.ɵɵelementEnd()()()();
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext(2);
    i0.ɵɵadvance(5);
    i0.ɵɵtextInterpolate(ctx_r1.State.CurrentError.type);
    i0.ɵɵadvance(2);
    i0.ɵɵtextInterpolate(ctx_r1.State.CurrentError.message);
} }
function ComponentPreviewComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
    const _r11 = i0.ɵɵgetCurrentView();
    i0.ɵɵelementStart(0, "div", 37)(1, "mj-react-component", 38, 0);
    i0.ɵɵlistener("componentEvent", function ComponentPreviewComponent_Conditional_13_Template_mj_react_component_componentEvent_1_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnComponentEvent($event)); })("initialized", function ComponentPreviewComponent_Conditional_13_Template_mj_react_component_initialized_1_listener() { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnReactInitialized()); })("openEntityRecord", function ComponentPreviewComponent_Conditional_13_Template_mj_react_component_openEntityRecord_1_listener($event) { i0.ɵɵrestoreView(_r11); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnOpenEntityRecord($event)); });
    i0.ɵɵelementEnd()();
    i0.ɵɵconditionalCreate(3, ComponentPreviewComponent_Conditional_13_Conditional_3_Template, 11, 0, "div", 39);
    i0.ɵɵconditionalCreate(4, ComponentPreviewComponent_Conditional_13_Conditional_4_Template, 15, 2, "div", 40);
} if (rf & 2) {
    const ctx_r1 = i0.ɵɵnextContext();
    i0.ɵɵstyleProp("max-width", ctx_r1.GetPreviewContainerMaxWidth());
    i0.ɵɵclassProp("mobile", ctx_r1.ActiveViewport === "mobile")("tablet", ctx_r1.ActiveViewport === "tablet")("desktop", ctx_r1.ActiveViewport === "desktop");
    i0.ɵɵadvance();
    i0.ɵɵproperty("component", ctx_r1.LocalComponentSpec)("componentProps", ctx_r1.FixtureFormHostProps);
    i0.ɵɵadvance(2);
    i0.ɵɵconditional(ctx_r1.IsFormRolePreview && ctx_r1.EventLog.length > 0 ? 3 : -1);
    i0.ɵɵadvance();
    i0.ɵɵconditional(ctx_r1.State.CurrentError ? 4 : -1);
} }
/**
 * Component Preview - TOP section of CENTER panel.
 * Renders the live React component preview with toolbar controls.
 */
export class ComponentPreviewComponent {
    State;
    cdr;
    ReactComponentRef;
    AskAIToFix = new EventEmitter();
    // --- Viewport ---
    ActiveViewport = 'desktop';
    ViewportPresets = [
        { Size: 'mobile', Label: 'Mobile (375px)', Icon: 'fa-mobile-screen', MaxWidth: '375px' },
        { Size: 'tablet', Label: 'Tablet (768px)', Icon: 'fa-tablet-screen-button', MaxWidth: '768px' },
        { Size: 'desktop', Label: 'Desktop (100%)', Icon: 'fa-desktop', MaxWidth: '100%' }
    ];
    // --- Local spec for refresh cycle ---
    LocalComponentSpec = null;
    // ----- Form-role preview controls (sandboxed) -----
    /** Recent records of the target entity for the optional real-record picker. */
    RecentRecords = [];
    SelectedRecordID = null;
    /** When a real record is loaded, this holds its fields keyed by name. */
    LoadedRecordValues = null;
    IsLoadingRecord = false;
    /** Last 20 events emitted by the previewed component, newest first. */
    EventLog = [];
    destroy$ = new Subject();
    lastLoadedEntity = null;
    constructor(State, cdr) {
        this.State = State;
        this.cdr = cdr;
    }
    ngOnInit() {
        this.syncSpecFromState();
        this.State.StateChanged
            .pipe(takeUntil(this.destroy$))
            .subscribe(() => {
            this.syncSpecFromState();
            this.maybeRefreshRecentRecords();
            this.cdr.detectChanges();
        });
        this.State.RefreshComponent
            .pipe(takeUntil(this.destroy$))
            .subscribe(() => {
            this.refreshPreview();
        });
        this.maybeRefreshRecentRecords();
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    // ============================================================
    // TOOLBAR ACTIONS
    // ============================================================
    RunSelectedComponent() {
        if (this.State.SelectedComponent) {
            this.State.RunComponent(this.State.SelectedComponent);
        }
    }
    StopComponent() {
        MJReactComponent.forceClearRegistries();
        this.State.StopComponent();
    }
    RefreshComponent() {
        if (this.State.SelectedComponent && this.State.IsRunning) {
            MJReactComponent.forceClearRegistries();
            this.refreshPreview();
        }
    }
    SetViewport(size) {
        this.ActiveViewport = size;
        this.cdr.detectChanges();
    }
    SendErrorToAI() {
        if (this.State.CurrentError) {
            this.AskAIToFix.emit(this.State.CurrentError);
            this.State.SendErrorToAI.emit(this.State.CurrentError);
        }
    }
    // ============================================================
    // VIEWPORT HELPERS
    // ============================================================
    GetActivePreset() {
        return this.ViewportPresets.find(p => p.Size === this.ActiveViewport) || this.ViewportPresets[2];
    }
    GetPreviewContainerMaxWidth() {
        return this.GetActivePreset().MaxWidth;
    }
    // ============================================================
    // REACT COMPONENT EVENTS
    // ============================================================
    OnComponentEvent(event) {
        if (event.type === 'error') {
            this.State.CurrentError = {
                type: event.payload?.source || 'Component Error',
                message: event.payload?.error || 'An error occurred while rendering the component',
                technicalDetails: event.payload?.errorInfo || event.payload
            };
            this.cdr.detectChanges();
            return;
        }
        // Form-role event sandbox — log BeforeSave / BeforeDelete /
        // FieldChanged events but never let them persist. The previewed
        // component should treat the response as a no-op.
        if (this.IsFormRolePreview) {
            this.logEvent(event.type, event.payload);
            this.cdr.detectChanges();
        }
    }
    // ============================================================
    // FORM PREVIEW HELPERS
    // ============================================================
    /** True when the current spec is form-role (drives the sandbox UI). */
    get IsFormRolePreview() {
        const spec = this.LocalComponentSpec;
        return !!spec && (spec.componentRole === 'form' || spec.type === 'form');
    }
    /** Convenience for the template — the entity name the form binds to. */
    get FormTargetEntity() {
        return this.State.FormTargetEntityName;
    }
    /** Selected preview mode (delegates to the shared state). */
    get FormPreviewMode() {
        return this.State.FormPreviewMode;
    }
    SetFormPreviewMode(mode) {
        this.State.FormPreviewMode = mode;
        // Switching mode invalidates any loaded record diff — clear it so the
        // refreshed render starts fresh.
        if (mode === 'create') {
            this.SelectedRecordID = null;
            this.LoadedRecordValues = null;
        }
        this.refreshPreview();
    }
    /** Add an entry to the event log; keep the log bounded to 20 entries. */
    logEvent(type, payload) {
        const entry = {
            Timestamp: new Date(),
            Type: type,
            Payload: this.summarisePayload(payload),
        };
        this.EventLog = [entry, ...this.EventLog].slice(0, 20);
    }
    summarisePayload(payload) {
        if (payload == null)
            return '—';
        try {
            const s = JSON.stringify(payload);
            return s.length > 200 ? s.slice(0, 200) + '…' : s;
        }
        catch {
            return String(payload);
        }
    }
    ClearEventLog() {
        this.EventLog = [];
        this.cdr.detectChanges();
    }
    /**
     * Load the top 10 most-recent records for the target entity so the
     * preview can swap from fixture to real-record mode. Re-runs whenever
     * the target entity changes; quiet no-op if entity isn't set yet.
     */
    async maybeRefreshRecentRecords() {
        const entityName = this.State.FormTargetEntityName;
        if (!entityName || entityName === this.lastLoadedEntity)
            return;
        this.lastLoadedEntity = entityName;
        this.RecentRecords = [];
        try {
            const rv = RunView.FromMetadataProvider(this.State.Provider);
            const entityInfo = this.State.Provider.EntityByName(entityName);
            const nameField = entityInfo?.NameField?.Name ?? 'ID';
            const fields = nameField === 'ID' ? ['ID'] : ['ID', nameField];
            const result = await rv.RunView({
                EntityName: entityName,
                Fields: fields,
                OrderBy: '__mj_UpdatedAt DESC',
                MaxRows: 10,
                ResultType: 'simple',
            });
            if (result.Success && Array.isArray(result.Results)) {
                this.RecentRecords = result.Results.map(r => ({
                    ID: String(r['ID'] ?? ''),
                    Display: String(r[nameField] ?? r['ID'] ?? ''),
                })).filter(r => r.ID.length > 0);
            }
        }
        catch (err) {
            LogError(`ComponentPreview.maybeRefreshRecentRecords: ${err instanceof Error ? err.message : String(err)}`);
        }
        this.cdr.detectChanges();
    }
    /**
     * Load a real record for preview. We pull the full entity object then
     * extract its field values into a plain object for FormHostProps.
     * Sandboxed — any BeforeSave/BeforeDelete events emitted by the previewed
     * component are logged, never applied.
     */
    async OnPickRecord(event) {
        const id = event.target.value || null;
        this.SelectedRecordID = id;
        if (!id) {
            this.LoadedRecordValues = null;
            this.refreshPreview();
            return;
        }
        const entityName = this.State.FormTargetEntityName;
        if (!entityName)
            return;
        this.IsLoadingRecord = true;
        this.cdr.detectChanges();
        try {
            const provider = this.State.Provider;
            const entity = await provider.GetEntityObject(entityName, provider.CurrentUser);
            const compositeKey = CompositeKey.FromID(id);
            const loaded = await entity.InnerLoad(compositeKey);
            if (loaded) {
                const values = {};
                for (const f of entity.Fields) {
                    values[f.Name] = f.Value;
                }
                this.LoadedRecordValues = values;
            }
            else {
                this.LoadedRecordValues = null;
            }
        }
        catch (err) {
            LogError(`ComponentPreview.OnPickRecord: ${err instanceof Error ? err.message : String(err)}`);
            this.LoadedRecordValues = null;
        }
        finally {
            this.IsLoadingRecord = false;
        }
        this.refreshPreview();
    }
    /**
     * Fires once the React bridge has resolved the full component hierarchy from the
     * registry. The bridge stores the resolved spec (with real dependency code, not
     * registry-reference stubs) on its public `resolvedComponentSpec` field — pull it
     * across so the code-editor tabs can render actual source instead of "No code available".
     */
    OnReactInitialized() {
        const resolvedSpec = this.ReactComponentRef?.resolvedComponentSpec;
        if (resolvedSpec) {
            this.State.UpdateWithResolvedSpec(resolvedSpec);
            this.cdr.detectChanges();
        }
    }
    OnOpenEntityRecord(event) {
        SharedService.Instance.OpenEntityRecord(event.entityName, event.key);
    }
    // ============================================================
    // STATE HELPERS
    // ============================================================
    GetComponentName() {
        if (!this.State.SelectedComponent)
            return '';
        return this.State.GetComponentName(this.State.SelectedComponent);
    }
    GetComponentDescription() {
        if (!this.State.SelectedComponent)
            return undefined;
        return this.State.GetComponentDescription(this.State.SelectedComponent);
    }
    // ============================================================
    // PRIVATE
    // ============================================================
    syncSpecFromState() {
        this.LocalComponentSpec = this.State.ComponentSpec;
    }
    /**
     * Fixture `FormHostProps` for form-role component previews. Built from
     * the curated schema of `State.FormTargetEntityName` — the entity the
     * user picked in the Field Binding Inspector. Returns an empty object
     * when (a) the current spec isn't a form, (b) no target entity is
     * selected, or (c) the entity isn't registered with the provider — in
     * which case the previewed component sees `record === undefined` and
     * should handle that gracefully (the Studio skeleton does).
     *
     * The mode toggles to 'edit' so authors can see how inputs render
     * without manually flipping mode each refresh.
     */
    get FixtureFormHostProps() {
        const spec = this.LocalComponentSpec;
        if (!spec || (spec.componentRole !== 'form' && spec.type !== 'form')) {
            return {};
        }
        const entityName = this.State.FormTargetEntityName;
        if (!entityName) {
            return {};
        }
        const provider = this.State.Provider;
        if (!provider)
            return {};
        const schema = buildCuratedFormSchema(entityName, provider);
        if (!schema)
            return {};
        const mode = this.State.FormPreviewMode;
        const fixture = buildFixtureFormHostProps(schema, mode);
        // If the user picked a real record, overlay its field values on top of
        // the fixture (which has the right shape for entityMetadata + caps).
        // The record is still sandboxed — events fired by the previewed
        // component never reach a Save().
        if (this.LoadedRecordValues && mode !== 'create') {
            return {
                ...fixture,
                record: this.LoadedRecordValues,
                primaryKey: this.SelectedRecordID
                    ? { ID: this.SelectedRecordID }
                    : fixture.primaryKey,
            };
        }
        return fixture;
    }
    /**
     * Refresh the preview by nulling the spec, detecting changes,
     * then restoring the spec after a short delay. The bridge's own
     * `initializeComponent` purges the runtime registry + manager fetch cache
     * for the new spec's keys, so consumers don't need to clear anything here.
     */
    refreshPreview() {
        if (!this.State.SelectedComponent)
            return;
        const spec = this.State.ComponentSpec;
        // Null out to force React to unmount
        this.LocalComponentSpec = null;
        this.cdr.detectChanges();
        // Re-set after a brief pause to force fresh mount
        setTimeout(() => {
            this.LocalComponentSpec = spec;
            this.State.ComponentSpec = spec;
            this.State.CurrentError = null;
            try {
                this.cdr.detectChanges();
            }
            catch (error) {
                console.error('Error during refresh detectChanges:', error);
            }
        }, 10);
    }
    static ɵfac = function ComponentPreviewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ComponentPreviewComponent)(i0.ɵɵdirectiveInject(i1.ComponentStudioStateService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
    static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentPreviewComponent, selectors: [["mj-component-preview"]], viewQuery: function ComponentPreviewComponent_Query(rf, ctx) { if (rf & 1) {
            i0.ɵɵviewQuery(_c0, 5);
        } if (rf & 2) {
            let _t;
            i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.ReactComponentRef = _t.first);
        } }, outputs: { AskAIToFix: "AskAIToFix" }, standalone: false, decls: 14, vars: 6, consts: [["reactComponent", ""], [1, "component-preview"], [1, "preview-toolbar"], [1, "toolbar-left"], [1, "toolbar-center"], [1, "viewport-selector"], [1, "toolbar-right"], ["title", "Ask AI to fix this error", 1, "toolbar-btn", "ai-fix-btn"], [1, "running-indicator"], [1, "form-preview-bar"], [1, "preview-area"], ["Icon", "fa-solid fa-eye", "Title", "Select a component to preview", "Message", "Choose a component from the sidebar to see its live preview here."], ["Icon", "fa-solid fa-play-circle", "ActionText", "Run Component", "ActionIcon", "fa-solid fa-play", 3, "Title", "Message"], ["title", "Run component", 1, "toolbar-btn", "run-btn"], ["title", "Stop component", 1, "toolbar-btn", "stop-btn", 3, "click"], [1, "fa-solid", "fa-stop"], ["title", "Refresh component", 1, "toolbar-btn", 3, "click"], [1, "fa-solid", "fa-rotate-right"], ["title", "Run component", 1, "toolbar-btn", "run-btn", 3, "click"], [1, "fa-solid", "fa-play"], [1, "viewport-btn", 3, "active", "title"], [1, "viewport-btn", 3, "click", "title"], [1, "fa-solid", 3, "ngClass"], ["title", "Ask AI to fix this error", 1, "toolbar-btn", "ai-fix-btn", 3, "click"], [1, "fa-solid", "fa-wand-magic-sparkles"], [1, "fa-solid", "fa-circle", "running-dot"], [1, "form-preview-banner"], [1, "fa-solid", "fa-shield-halved"], [1, "form-preview-controls"], [1, "form-mode-pills"], [1, "form-mode-pill", 3, "click"], [1, "form-record-picker"], [3, "change", "value"], ["value", ""], [3, "value"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["Icon", "fa-solid fa-play-circle", "ActionText", "Run Component", "ActionIcon", "fa-solid fa-play", 3, "Action", "Title", "Message"], [1, "preview-container"], [3, "componentEvent", "initialized", "openEntityRecord", "component", "componentProps"], [1, "form-event-log"], [1, "error-overlay"], [1, "form-event-log-header"], [1, "fa-solid", "fa-list"], [1, "spacer"], [1, "form-event-log-clear", 3, "click"], [1, "form-event-log-list"], [1, "form-event-log-row"], [1, "form-event-log-ts"], [1, "form-event-log-type"], [1, "form-event-log-payload"], [1, "error-overlay-content"], [1, "error-overlay-header"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "error-overlay-title"], [1, "error-overlay-message"], [1, "error-overlay-actions"], [1, "toolbar-btn", 3, "click"], [1, "toolbar-btn", "ai-fix-btn", 3, "click"]], template: function ComponentPreviewComponent_Template(rf, ctx) { if (rf & 1) {
            i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3);
            i0.ɵɵconditionalCreate(3, ComponentPreviewComponent_Conditional_3_Template, 2, 1);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(4, "div", 4);
            i0.ɵɵconditionalCreate(5, ComponentPreviewComponent_Conditional_5_Template, 3, 0, "div", 5);
            i0.ɵɵelementEnd();
            i0.ɵɵelementStart(6, "div", 6);
            i0.ɵɵconditionalCreate(7, ComponentPreviewComponent_Conditional_7_Template, 4, 0, "button", 7);
            i0.ɵɵconditionalCreate(8, ComponentPreviewComponent_Conditional_8_Template, 3, 1, "span", 8);
            i0.ɵɵelementEnd()();
            i0.ɵɵconditionalCreate(9, ComponentPreviewComponent_Conditional_9_Template, 13, 7, "div", 9);
            i0.ɵɵelementStart(10, "div", 10);
            i0.ɵɵconditionalCreate(11, ComponentPreviewComponent_Conditional_11_Template, 1, 0, "mj-empty-state", 11)(12, ComponentPreviewComponent_Conditional_12_Template, 1, 2, "mj-empty-state", 12)(13, ComponentPreviewComponent_Conditional_13_Template, 5, 12);
            i0.ɵɵelementEnd()();
        } if (rf & 2) {
            i0.ɵɵadvance(3);
            i0.ɵɵconditional(ctx.State.SelectedComponent ? 3 : -1);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(ctx.State.IsRunning ? 5 : -1);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(ctx.State.CurrentError ? 7 : -1);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.State.IsRunning && ctx.State.SelectedComponent ? 8 : -1);
            i0.ɵɵadvance();
            i0.ɵɵconditional(ctx.IsFormRolePreview && ctx.State.IsRunning ? 9 : -1);
            i0.ɵɵadvance(2);
            i0.ɵɵconditional(!ctx.State.SelectedComponent ? 11 : !ctx.State.IsRunning ? 12 : ctx.LocalComponentSpec ? 13 : -1);
        } }, dependencies: [i2.NgClass, i3.NgSelectOption, i3.ɵNgSelectMultipleOption, i4.MJReactComponent, i5.MJEmptyStateComponent, i2.DatePipe], styles: ["[_nghost-%COMP%] {\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n\n.component-preview[_ngcontent-%COMP%] {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  background: var(--mj-bg-surface-sunken);\n  overflow: hidden;\n}\n\n\n\n\n\n\n.preview-toolbar[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 6px 12px;\n  background: var(--mj-bg-surface);\n  border-bottom: 1px solid var(--mj-border-default);\n  min-height: 42px;\n  gap: 12px;\n  flex-shrink: 0;\n}\n\n.preview-toolbar[_ngcontent-%COMP%]   .toolbar-left[_ngcontent-%COMP%], \n.preview-toolbar[_ngcontent-%COMP%]   .toolbar-center[_ngcontent-%COMP%], \n.preview-toolbar[_ngcontent-%COMP%]   .toolbar-right[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n}\n\n.preview-toolbar[_ngcontent-%COMP%]   .toolbar-left[_ngcontent-%COMP%] {\n  flex: 0 0 auto;\n}\n\n.preview-toolbar[_ngcontent-%COMP%]   .toolbar-center[_ngcontent-%COMP%] {\n  flex: 1 1 auto;\n  justify-content: center;\n}\n\n.preview-toolbar[_ngcontent-%COMP%]   .toolbar-right[_ngcontent-%COMP%] {\n  flex: 0 0 auto;\n}\n\n.toolbar-btn[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 5px;\n  padding: 4px 10px;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 5px;\n  background: var(--mj-bg-surface);\n  color: var(--mj-text-primary);\n  font-size: 12px;\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.15s ease;\n  white-space: nowrap;\n}\n\n.toolbar-btn[_ngcontent-%COMP%]:hover {\n  background: var(--mj-bg-surface-sunken);\n  border-color: var(--mj-border-strong);\n}\n\n.toolbar-btn[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n  font-size: 11px;\n}\n\n.run-btn[_ngcontent-%COMP%] {\n  color: var(--mj-status-success);\n  border-color: color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n  background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.run-btn[_ngcontent-%COMP%]:hover {\n  background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n  border-color: color-mix(in srgb, var(--mj-status-success) 60%, transparent);\n}\n\n.stop-btn[_ngcontent-%COMP%] {\n  color: var(--mj-status-error);\n  border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent);\n  background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.stop-btn[_ngcontent-%COMP%]:hover {\n  background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n  border-color: color-mix(in srgb, var(--mj-status-error) 60%, transparent);\n}\n\n.ai-fix-btn[_ngcontent-%COMP%] {\n  color: var(--mj-brand-primary);\n  border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n  background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.ai-fix-btn[_ngcontent-%COMP%]:hover {\n  background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n  border-color: color-mix(in srgb, var(--mj-brand-primary) 60%, transparent);\n}\n\n.running-indicator[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  font-size: 12px;\n  color: var(--mj-text-secondary);\n  font-weight: 500;\n  max-width: 200px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.running-indicator[_ngcontent-%COMP%]   .running-dot[_ngcontent-%COMP%] {\n  font-size: 7px;\n  color: var(--mj-status-success);\n  animation: _ngcontent-%COMP%_pulse-dot 1.5s ease-in-out infinite;\n}\n\n@keyframes _ngcontent-%COMP%_pulse-dot {\n  0%, 100% { opacity: 1; }\n  50% { opacity: 0.3; }\n}\n\n\n\n\n\n\n.viewport-selector[_ngcontent-%COMP%] {\n  display: inline-flex;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 4px;\n  overflow: hidden;\n  background: var(--mj-bg-surface);\n}\n\n.viewport-btn[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 34px;\n  height: 28px;\n  border: none;\n  background: transparent;\n  color: var(--mj-text-secondary);\n  cursor: pointer;\n  font-size: 13px;\n  transition: all 0.15s ease;\n}\n\n.viewport-btn[_ngcontent-%COMP%]:not(:last-child) {\n  border-right: 1px solid var(--mj-border-default);\n}\n\n.viewport-btn[_ngcontent-%COMP%]:hover {\n  background: var(--mj-bg-surface-sunken);\n  color: var(--mj-text-primary);\n}\n\n.viewport-btn.active[_ngcontent-%COMP%] {\n  background: var(--mj-brand-primary);\n  color: var(--mj-text-inverse);\n}\n\n.viewport-btn.active[_ngcontent-%COMP%]:hover {\n  background: var(--mj-brand-primary);\n}\n\n\n\n\n\n\n.preview-area[_ngcontent-%COMP%] {\n  flex: 1;\n  overflow: auto;\n  position: relative;\n  display: flex;\n  justify-content: center;\n}\n\n.preview-container[_ngcontent-%COMP%] {\n  width: 100%;\n  height: 100%;\n  margin: 0 auto;\n  transition: max-width 0.3s ease;\n  overflow: auto;\n  background: var(--mj-bg-surface);\n}\n\n.preview-container.mobile[_ngcontent-%COMP%], \n.preview-container.tablet[_ngcontent-%COMP%] {\n  border-left: 1px solid var(--mj-border-default);\n  border-right: 1px solid var(--mj-border-default);\n  box-shadow: var(--mj-shadow-sm);\n}\n\n.preview-container.desktop[_ngcontent-%COMP%] {\n  max-width: 100% !important;\n}\n\n\n\n\n\n\n\n\n\n\nmj-empty-state[_ngcontent-%COMP%] {\n  width: 100%;\n  height: 100%;\n}\n\n\n\n\n\n\n.error-overlay[_ngcontent-%COMP%] {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  z-index: 10;\n  background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n  border-top: 2px solid var(--mj-status-error);\n  backdrop-filter: blur(4px);\n  padding: 16px 20px;\n  animation: _ngcontent-%COMP%_slide-up 0.2s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slide-up {\n  from {\n    transform: translateY(100%);\n    opacity: 0;\n  }\n  to {\n    transform: translateY(0);\n    opacity: 1;\n  }\n}\n\n.error-overlay-content[_ngcontent-%COMP%] {\n  max-width: 600px;\n}\n\n.error-overlay-header[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 6px;\n}\n\n.error-overlay-header[_ngcontent-%COMP%]   i[_ngcontent-%COMP%] {\n  color: var(--mj-status-error);\n  font-size: 16px;\n}\n\n.error-overlay-header[_ngcontent-%COMP%]   .error-overlay-title[_ngcontent-%COMP%] {\n  font-size: 14px;\n  font-weight: 600;\n  color: var(--mj-status-error);\n}\n\n.error-overlay-message[_ngcontent-%COMP%] {\n  margin: 0 0 12px 0;\n  font-size: 13px;\n  color: var(--mj-text-primary);\n  line-height: 1.4;\n}\n\n.error-overlay-actions[_ngcontent-%COMP%] {\n  display: flex;\n  gap: 8px;\n}\n\n\n\n\n\n.form-preview-bar[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  padding: 6px 12px;\n  background: var(--mj-status-warning-bg);\n  border-bottom: 1px solid var(--mj-status-warning-border);\n  flex-wrap: wrap;\n}\n\n.form-preview-banner[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  font-size: 12px;\n  font-weight: 600;\n  color: var(--mj-status-warning-text);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.form-preview-controls[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  flex: 1;\n  flex-wrap: wrap;\n}\n\n.form-mode-pills[_ngcontent-%COMP%] {\n  display: inline-flex;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 6px;\n  overflow: hidden;\n  background: var(--mj-bg-surface);\n}\n\n.form-mode-pill[_ngcontent-%COMP%] {\n  padding: 4px 12px;\n  background: transparent;\n  border: none;\n  border-right: 1px solid var(--mj-border-default);\n  font-size: 12px;\n  color: var(--mj-text-secondary);\n  cursor: pointer;\n  font-family: inherit;\n  transition: all 0.15s ease;\n}\n\n.form-mode-pill[_ngcontent-%COMP%]:last-child {\n  border-right: none;\n}\n\n.form-mode-pill[_ngcontent-%COMP%]:hover {\n  background: var(--mj-bg-surface-hover);\n  color: var(--mj-text-primary);\n}\n\n.form-mode-pill.active[_ngcontent-%COMP%] {\n  background: var(--mj-brand-primary);\n  color: var(--mj-text-inverse);\n  font-weight: 600;\n}\n\n.form-record-picker[_ngcontent-%COMP%] {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  font-size: 12px;\n  color: var(--mj-text-primary);\n}\n\n.form-record-picker[_ngcontent-%COMP%]   label[_ngcontent-%COMP%] {\n  font-size: 11px;\n  color: var(--mj-text-muted);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.form-record-picker[_ngcontent-%COMP%]   select[_ngcontent-%COMP%] {\n  padding: 4px 8px;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 4px;\n  background: var(--mj-bg-surface);\n  color: var(--mj-text-primary);\n  font-size: 12px;\n  font-family: inherit;\n}\n\n\n\n\n\n.form-event-log[_ngcontent-%COMP%] {\n  position: absolute;\n  bottom: 8px;\n  left: 8px;\n  right: 8px;\n  max-height: 160px;\n  background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-default);\n  border-radius: 6px;\n  display: flex;\n  flex-direction: column;\n  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);\n  z-index: 10;\n}\n\n.form-event-log-header[_ngcontent-%COMP%] {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n  padding: 6px 10px;\n  font-size: 12px;\n  font-weight: 600;\n  color: var(--mj-text-secondary);\n  border-bottom: 1px solid var(--mj-border-default);\n  background: var(--mj-bg-surface-sunken);\n  border-radius: 6px 6px 0 0;\n}\n\n.form-event-log-header[_ngcontent-%COMP%]   .spacer[_ngcontent-%COMP%] {\n  flex: 1;\n}\n\n.form-event-log-clear[_ngcontent-%COMP%] {\n  padding: 2px 8px;\n  background: transparent;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 4px;\n  font-size: 11px;\n  color: var(--mj-text-secondary);\n  cursor: pointer;\n  font-family: inherit;\n}\n\n.form-event-log-list[_ngcontent-%COMP%] {\n  list-style: none;\n  margin: 0;\n  padding: 4px;\n  overflow-y: auto;\n  flex: 1;\n}\n\n.form-event-log-row[_ngcontent-%COMP%] {\n  display: flex;\n  gap: 8px;\n  padding: 4px 6px;\n  font-size: 11px;\n  font-family: ui-monospace, monospace;\n  border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.form-event-log-row[_ngcontent-%COMP%]:last-child {\n  border-bottom: none;\n}\n\n.form-event-log-ts[_ngcontent-%COMP%] {\n  color: var(--mj-text-muted);\n  flex-shrink: 0;\n}\n\n.form-event-log-type[_ngcontent-%COMP%] {\n  color: var(--mj-brand-primary);\n  font-weight: 600;\n  flex-shrink: 0;\n}\n\n.form-event-log-payload[_ngcontent-%COMP%] {\n  color: var(--mj-text-primary);\n  word-break: break-all;\n}\n\n.preview-area[_ngcontent-%COMP%] {\n  position: relative;\n}"] });
}
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentPreviewComponent, [{
        type: Component,
        args: [{ standalone: false, selector: 'mj-component-preview', template: "<div class=\"component-preview\">\n  <!-- Toolbar -->\n  <div class=\"preview-toolbar\">\n    <div class=\"toolbar-left\">\n      @if (State.SelectedComponent) {\n        @if (State.IsRunning) {\n          <button class=\"toolbar-btn stop-btn\" (click)=\"StopComponent()\" title=\"Stop component\">\n            <i class=\"fa-solid fa-stop\"></i>\n            <span>Stop</span>\n          </button>\n          <button class=\"toolbar-btn\" (click)=\"RefreshComponent()\" title=\"Refresh component\">\n            <i class=\"fa-solid fa-rotate-right\"></i>\n            <span>Refresh</span>\n          </button>\n        } @else {\n          <button class=\"toolbar-btn run-btn\" (click)=\"RunSelectedComponent()\" title=\"Run component\">\n            <i class=\"fa-solid fa-play\"></i>\n            <span>Run</span>\n          </button>\n        }\n      }\n    </div>\n\n    <div class=\"toolbar-center\">\n      <!-- Viewport Size Selector (segmented control) -->\n      @if (State.IsRunning) {\n        <div class=\"viewport-selector\">\n          @for (preset of ViewportPresets; track preset.Size) {\n            <button\n              class=\"viewport-btn\"\n              [class.active]=\"ActiveViewport === preset.Size\"\n              (click)=\"SetViewport(preset.Size)\"\n              [title]=\"preset.Label\">\n              <i class=\"fa-solid\" [ngClass]=\"preset.Icon\"></i>\n            </button>\n          }\n        </div>\n      }\n    </div>\n\n    <div class=\"toolbar-right\">\n      @if (State.CurrentError) {\n        <button class=\"toolbar-btn ai-fix-btn\" (click)=\"SendErrorToAI()\" title=\"Ask AI to fix this error\">\n          <i class=\"fa-solid fa-wand-magic-sparkles\"></i>\n          <span>Ask AI to Fix</span>\n        </button>\n      }\n      @if (State.IsRunning && State.SelectedComponent) {\n        <span class=\"running-indicator\">\n          <i class=\"fa-solid fa-circle running-dot\"></i>\n          {{ GetComponentName() }}\n        </span>\n      }\n    </div>\n  </div>\n\n  <!-- Form-role preview controls (banner + mode + real-record picker).\n       Visible only for componentRole==='form' components, since they're\n       the only ones that bind to a record. -->\n  @if (IsFormRolePreview && State.IsRunning) {\n    <div class=\"form-preview-bar\">\n      <div class=\"form-preview-banner\">\n        <i class=\"fa-solid fa-shield-halved\"></i>\n        PREVIEW \u2014 changes will not be saved\n      </div>\n      <div class=\"form-preview-controls\">\n        <!-- Mode pills synced with the Form Builder tab -->\n        <div class=\"form-mode-pills\">\n          <button class=\"form-mode-pill\"\n                  [class.active]=\"FormPreviewMode === 'view'\"\n                  (click)=\"SetFormPreviewMode('view')\">View</button>\n          <button class=\"form-mode-pill\"\n                  [class.active]=\"FormPreviewMode === 'edit'\"\n                  (click)=\"SetFormPreviewMode('edit')\">Edit</button>\n          <button class=\"form-mode-pill\"\n                  [class.active]=\"FormPreviewMode === 'create'\"\n                  (click)=\"SetFormPreviewMode('create')\">Create</button>\n        </div>\n\n        <!-- Real-record picker; null = fixture data -->\n        @if (FormPreviewMode !== 'create' && FormTargetEntity) {\n          <div class=\"form-record-picker\">\n            <label>Record</label>\n            <select [value]=\"SelectedRecordID ?? ''\" (change)=\"OnPickRecord($event)\">\n              <option value=\"\">\u2014 Fixture data \u2014</option>\n              @for (r of RecentRecords; track r.ID) {\n                <option [value]=\"r.ID\">{{ r.Display }}</option>\n              }\n            </select>\n            @if (IsLoadingRecord) {\n              <i class=\"fa-solid fa-spinner fa-spin\"></i>\n            }\n          </div>\n        }\n      </div>\n    </div>\n  }\n\n  <!-- Preview Area -->\n  <div class=\"preview-area\">\n    @if (!State.SelectedComponent) {\n      <!-- Empty State: No component selected -->\n      <mj-empty-state Icon=\"fa-solid fa-eye\"\n        Title=\"Select a component to preview\"\n        Message=\"Choose a component from the sidebar to see its live preview here.\" />\n    } @else if (!State.IsRunning) {\n      <!-- Component selected but not running -->\n      <mj-empty-state Icon=\"fa-solid fa-play-circle\"\n        [Title]=\"GetComponentName()\"\n        [Message]=\"GetComponentDescription() || 'No description available'\"\n        ActionText=\"Run Component\"\n        ActionIcon=\"fa-solid fa-play\"\n        (Action)=\"RunSelectedComponent()\" />\n    } @else if (LocalComponentSpec) {\n      <!-- Live Preview Container -->\n      <div class=\"preview-container\"\n           [style.max-width]=\"GetPreviewContainerMaxWidth()\"\n           [class.mobile]=\"ActiveViewport === 'mobile'\"\n           [class.tablet]=\"ActiveViewport === 'tablet'\"\n           [class.desktop]=\"ActiveViewport === 'desktop'\">\n        <mj-react-component\n          #reactComponent\n          [component]=\"LocalComponentSpec\"\n          [componentProps]=\"FixtureFormHostProps\"\n          (componentEvent)=\"OnComponentEvent($event)\"\n          (initialized)=\"OnReactInitialized()\"\n          (openEntityRecord)=\"OnOpenEntityRecord($event)\">\n        </mj-react-component>\n      </div>\n\n      <!-- Form-role sandboxed event log -->\n      @if (IsFormRolePreview && EventLog.length > 0) {\n        <div class=\"form-event-log\">\n          <div class=\"form-event-log-header\">\n            <i class=\"fa-solid fa-list\"></i>\n            <span>Events (sandboxed)</span>\n            <span class=\"spacer\"></span>\n            <button class=\"form-event-log-clear\" (click)=\"ClearEventLog()\">Clear</button>\n          </div>\n          <ul class=\"form-event-log-list\">\n            @for (e of EventLog; track $index) {\n              <li class=\"form-event-log-row\">\n                <span class=\"form-event-log-ts\">{{ e.Timestamp | date:'HH:mm:ss' }}</span>\n                <span class=\"form-event-log-type\">{{ e.Type }}</span>\n                <span class=\"form-event-log-payload\">{{ e.Payload }}</span>\n              </li>\n            }\n          </ul>\n        </div>\n      }\n\n      <!-- Error Overlay (inline, does not replace the component) -->\n      @if (State.CurrentError) {\n        <div class=\"error-overlay\">\n          <div class=\"error-overlay-content\">\n            <div class=\"error-overlay-header\">\n              <i class=\"fa-solid fa-exclamation-triangle\"></i>\n              <span class=\"error-overlay-title\">{{ State.CurrentError.type }}</span>\n            </div>\n            <p class=\"error-overlay-message\">{{ State.CurrentError.message }}</p>\n            <div class=\"error-overlay-actions\">\n              <button class=\"toolbar-btn\" (click)=\"RefreshComponent()\">\n                <i class=\"fa-solid fa-rotate-right\"></i> Retry\n              </button>\n              <button class=\"toolbar-btn ai-fix-btn\" (click)=\"SendErrorToAI()\">\n                <i class=\"fa-solid fa-wand-magic-sparkles\"></i> Ask AI to Fix\n              </button>\n            </div>\n          </div>\n        </div>\n      }\n    }\n  </div>\n</div>\n", styles: [":host {\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n\n.component-preview {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  background: var(--mj-bg-surface-sunken);\n  overflow: hidden;\n}\n\n/* ============================================================\n   TOOLBAR\n   ============================================================ */\n\n.preview-toolbar {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  padding: 6px 12px;\n  background: var(--mj-bg-surface);\n  border-bottom: 1px solid var(--mj-border-default);\n  min-height: 42px;\n  gap: 12px;\n  flex-shrink: 0;\n}\n\n.preview-toolbar .toolbar-left,\n.preview-toolbar .toolbar-center,\n.preview-toolbar .toolbar-right {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n}\n\n.preview-toolbar .toolbar-left {\n  flex: 0 0 auto;\n}\n\n.preview-toolbar .toolbar-center {\n  flex: 1 1 auto;\n  justify-content: center;\n}\n\n.preview-toolbar .toolbar-right {\n  flex: 0 0 auto;\n}\n\n.toolbar-btn {\n  display: inline-flex;\n  align-items: center;\n  gap: 5px;\n  padding: 4px 10px;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 5px;\n  background: var(--mj-bg-surface);\n  color: var(--mj-text-primary);\n  font-size: 12px;\n  font-weight: 500;\n  cursor: pointer;\n  transition: all 0.15s ease;\n  white-space: nowrap;\n}\n\n.toolbar-btn:hover {\n  background: var(--mj-bg-surface-sunken);\n  border-color: var(--mj-border-strong);\n}\n\n.toolbar-btn i {\n  font-size: 11px;\n}\n\n.run-btn {\n  color: var(--mj-status-success);\n  border-color: color-mix(in srgb, var(--mj-status-success) 40%, transparent);\n  background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n}\n\n.run-btn:hover {\n  background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n  border-color: color-mix(in srgb, var(--mj-status-success) 60%, transparent);\n}\n\n.stop-btn {\n  color: var(--mj-status-error);\n  border-color: color-mix(in srgb, var(--mj-status-error) 40%, transparent);\n  background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.stop-btn:hover {\n  background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n  border-color: color-mix(in srgb, var(--mj-status-error) 60%, transparent);\n}\n\n.ai-fix-btn {\n  color: var(--mj-brand-primary);\n  border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n  background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.ai-fix-btn:hover {\n  background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n  border-color: color-mix(in srgb, var(--mj-brand-primary) 60%, transparent);\n}\n\n.running-indicator {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  font-size: 12px;\n  color: var(--mj-text-secondary);\n  font-weight: 500;\n  max-width: 200px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.running-indicator .running-dot {\n  font-size: 7px;\n  color: var(--mj-status-success);\n  animation: pulse-dot 1.5s ease-in-out infinite;\n}\n\n@keyframes pulse-dot {\n  0%, 100% { opacity: 1; }\n  50% { opacity: 0.3; }\n}\n\n/* ============================================================\n   VIEWPORT SELECTOR (segmented control)\n   ============================================================ */\n\n.viewport-selector {\n  display: inline-flex;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 4px;\n  overflow: hidden;\n  background: var(--mj-bg-surface);\n}\n\n.viewport-btn {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 34px;\n  height: 28px;\n  border: none;\n  background: transparent;\n  color: var(--mj-text-secondary);\n  cursor: pointer;\n  font-size: 13px;\n  transition: all 0.15s ease;\n}\n\n.viewport-btn:not(:last-child) {\n  border-right: 1px solid var(--mj-border-default);\n}\n\n.viewport-btn:hover {\n  background: var(--mj-bg-surface-sunken);\n  color: var(--mj-text-primary);\n}\n\n.viewport-btn.active {\n  background: var(--mj-brand-primary);\n  color: var(--mj-text-inverse);\n}\n\n.viewport-btn.active:hover {\n  background: var(--mj-brand-primary);\n}\n\n/* ============================================================\n   PREVIEW AREA\n   ============================================================ */\n\n.preview-area {\n  flex: 1;\n  overflow: auto;\n  position: relative;\n  display: flex;\n  justify-content: center;\n}\n\n.preview-container {\n  width: 100%;\n  height: 100%;\n  margin: 0 auto;\n  transition: max-width 0.3s ease;\n  overflow: auto;\n  background: var(--mj-bg-surface);\n}\n\n.preview-container.mobile,\n.preview-container.tablet {\n  border-left: 1px solid var(--mj-border-default);\n  border-right: 1px solid var(--mj-border-default);\n  box-shadow: var(--mj-shadow-sm);\n}\n\n.preview-container.desktop {\n  max-width: 100% !important;\n}\n\n/* ============================================================\n   EMPTY STATES\n   ============================================================ */\n\n/* The preview-area is a flex-fill container; the empty/run-state placeholder\n   must fill it so its content centers (restores the old .empty-state\n   width/height:100%). */\nmj-empty-state {\n  width: 100%;\n  height: 100%;\n}\n\n/* ============================================================\n   ERROR OVERLAY\n   ============================================================ */\n\n.error-overlay {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  z-index: 10;\n  background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n  border-top: 2px solid var(--mj-status-error);\n  backdrop-filter: blur(4px);\n  padding: 16px 20px;\n  animation: slide-up 0.2s ease-out;\n}\n\n@keyframes slide-up {\n  from {\n    transform: translateY(100%);\n    opacity: 0;\n  }\n  to {\n    transform: translateY(0);\n    opacity: 1;\n  }\n}\n\n.error-overlay-content {\n  max-width: 600px;\n}\n\n.error-overlay-header {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 6px;\n}\n\n.error-overlay-header i {\n  color: var(--mj-status-error);\n  font-size: 16px;\n}\n\n.error-overlay-header .error-overlay-title {\n  font-size: 14px;\n  font-weight: 600;\n  color: var(--mj-status-error);\n}\n\n.error-overlay-message {\n  margin: 0 0 12px 0;\n  font-size: 13px;\n  color: var(--mj-text-primary);\n  line-height: 1.4;\n}\n\n.error-overlay-actions {\n  display: flex;\n  gap: 8px;\n}\n\n/* ============================================================\n   FORM PREVIEW BAR (banner + mode pills + record picker)\n   ============================================================ */\n.form-preview-bar {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  padding: 6px 12px;\n  background: var(--mj-status-warning-bg);\n  border-bottom: 1px solid var(--mj-status-warning-border);\n  flex-wrap: wrap;\n}\n\n.form-preview-banner {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  font-size: 12px;\n  font-weight: 600;\n  color: var(--mj-status-warning-text);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.form-preview-controls {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  flex: 1;\n  flex-wrap: wrap;\n}\n\n.form-mode-pills {\n  display: inline-flex;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 6px;\n  overflow: hidden;\n  background: var(--mj-bg-surface);\n}\n\n.form-mode-pill {\n  padding: 4px 12px;\n  background: transparent;\n  border: none;\n  border-right: 1px solid var(--mj-border-default);\n  font-size: 12px;\n  color: var(--mj-text-secondary);\n  cursor: pointer;\n  font-family: inherit;\n  transition: all 0.15s ease;\n}\n\n.form-mode-pill:last-child {\n  border-right: none;\n}\n\n.form-mode-pill:hover {\n  background: var(--mj-bg-surface-hover);\n  color: var(--mj-text-primary);\n}\n\n.form-mode-pill.active {\n  background: var(--mj-brand-primary);\n  color: var(--mj-text-inverse);\n  font-weight: 600;\n}\n\n.form-record-picker {\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  font-size: 12px;\n  color: var(--mj-text-primary);\n}\n\n.form-record-picker label {\n  font-size: 11px;\n  color: var(--mj-text-muted);\n  text-transform: uppercase;\n  letter-spacing: 0.5px;\n}\n\n.form-record-picker select {\n  padding: 4px 8px;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 4px;\n  background: var(--mj-bg-surface);\n  color: var(--mj-text-primary);\n  font-size: 12px;\n  font-family: inherit;\n}\n\n/* ============================================================\n   FORM EVENT LOG (sandboxed events strip)\n   ============================================================ */\n.form-event-log {\n  position: absolute;\n  bottom: 8px;\n  left: 8px;\n  right: 8px;\n  max-height: 160px;\n  background: var(--mj-bg-surface);\n  border: 1px solid var(--mj-border-default);\n  border-radius: 6px;\n  display: flex;\n  flex-direction: column;\n  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);\n  z-index: 10;\n}\n\n.form-event-log-header {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n  padding: 6px 10px;\n  font-size: 12px;\n  font-weight: 600;\n  color: var(--mj-text-secondary);\n  border-bottom: 1px solid var(--mj-border-default);\n  background: var(--mj-bg-surface-sunken);\n  border-radius: 6px 6px 0 0;\n}\n\n.form-event-log-header .spacer {\n  flex: 1;\n}\n\n.form-event-log-clear {\n  padding: 2px 8px;\n  background: transparent;\n  border: 1px solid var(--mj-border-default);\n  border-radius: 4px;\n  font-size: 11px;\n  color: var(--mj-text-secondary);\n  cursor: pointer;\n  font-family: inherit;\n}\n\n.form-event-log-list {\n  list-style: none;\n  margin: 0;\n  padding: 4px;\n  overflow-y: auto;\n  flex: 1;\n}\n\n.form-event-log-row {\n  display: flex;\n  gap: 8px;\n  padding: 4px 6px;\n  font-size: 11px;\n  font-family: ui-monospace, monospace;\n  border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.form-event-log-row:last-child {\n  border-bottom: none;\n}\n\n.form-event-log-ts {\n  color: var(--mj-text-muted);\n  flex-shrink: 0;\n}\n\n.form-event-log-type {\n  color: var(--mj-brand-primary);\n  font-weight: 600;\n  flex-shrink: 0;\n}\n\n.form-event-log-payload {\n  color: var(--mj-text-primary);\n  word-break: break-all;\n}\n\n.preview-area {\n  position: relative;\n}\n"] }]
    }], () => [{ type: i1.ComponentStudioStateService }, { type: i0.ChangeDetectorRef }], { ReactComponentRef: [{
            type: ViewChild,
            args: ['reactComponent']
        }], AskAIToFix: [{
            type: Output
        }] }); })();
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentPreviewComponent, { className: "ComponentPreviewComponent", filePath: "src/ComponentStudio/components/workspace/component-preview.component.ts", lineNumber: 54 }); })();
//# sourceMappingURL=component-preview.component.js.map