@memberjunction/ng-dashboards 2.120.0 → 2.122.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AI/components/agents/agent-configuration.component.d.ts +23 -11
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +122 -95
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +88 -90
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js +2 -2
- package/dist/AI/components/execution-monitoring.component.d.ts +23 -10
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +143 -124
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management-v2.component.d.ts +17 -13
- package/dist/AI/components/models/model-management-v2.component.d.ts.map +1 -1
- package/dist/AI/components/models/model-management-v2.component.js +248 -266
- package/dist/AI/components/models/model-management-v2.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +76 -78
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-filter-panel.component.js +2 -2
- package/dist/AI/components/prompts/prompt-management-v2.component.d.ts +17 -15
- package/dist/AI/components/prompts/prompt-management-v2.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/prompt-management-v2.component.js +372 -397
- package/dist/AI/components/prompts/prompt-management-v2.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +100 -102
- package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
- package/dist/AI/components/system/system-config-filter-panel.component.js +2 -2
- package/dist/AI/components/system/system-configuration.component.d.ts +17 -10
- package/dist/AI/components/system/system-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +82 -61
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/widgets/kpi-card.component.d.ts.map +1 -1
- package/dist/AI/components/widgets/kpi-card.component.js +11 -7
- package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
- package/dist/AI/index.d.ts +4 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +6 -1
- package/dist/AI/index.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js +9 -9
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.d.ts +16 -13
- package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +62 -48
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +9 -9
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/code-management.component.d.ts +17 -7
- package/dist/Actions/components/code-management.component.d.ts.map +1 -1
- package/dist/Actions/components/code-management.component.js +45 -12
- package/dist/Actions/components/code-management.component.js.map +1 -1
- package/dist/Actions/components/entity-integration.component.d.ts +17 -7
- package/dist/Actions/components/entity-integration.component.d.ts.map +1 -1
- package/dist/Actions/components/entity-integration.component.js +45 -12
- package/dist/Actions/components/entity-integration.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.d.ts +16 -10
- package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +56 -30
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.d.ts +17 -7
- package/dist/Actions/components/scheduled-actions.component.d.ts.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.js +45 -12
- package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
- package/dist/Actions/components/security-permissions.component.d.ts +17 -7
- package/dist/Actions/components/security-permissions.component.d.ts.map +1 -1
- package/dist/Actions/components/security-permissions.component.js +45 -12
- package/dist/Actions/components/security-permissions.component.js.map +1 -1
- package/dist/Actions/index.d.ts +6 -1
- package/dist/Actions/index.d.ts.map +1 -1
- package/dist/Actions/index.js +9 -1
- package/dist/Actions/index.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +8 -8
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +52 -57
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +8 -9
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts +107 -0
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.d.ts.map +1 -0
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +553 -0
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js.map +1 -0
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts +179 -0
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.d.ts.map +1 -0
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js +814 -0
- package/dist/DataExplorer/components/view-config-panel/view-config-panel.component.js.map +1 -0
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +151 -0
- package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +1 -0
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +480 -0
- package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +1 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +439 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.js +2129 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -0
- package/dist/DataExplorer/index.d.ts +5 -0
- package/dist/DataExplorer/index.d.ts.map +1 -0
- package/dist/DataExplorer/index.js +10 -0
- package/dist/DataExplorer/index.js.map +1 -0
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +183 -0
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -0
- package/dist/DataExplorer/models/explorer-state.interface.js +31 -0
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -0
- package/dist/DataExplorer/services/explorer-state.service.d.ts +232 -0
- package/dist/DataExplorer/services/explorer-state.service.d.ts.map +1 -0
- package/dist/DataExplorer/services/explorer-state.service.js +912 -0
- package/dist/DataExplorer/services/explorer-state.service.js.map +1 -0
- package/dist/EntityAdmin/components/entity-details.component.d.ts.map +1 -1
- package/dist/EntityAdmin/components/entity-details.component.js +11 -13
- package/dist/EntityAdmin/components/entity-details.component.js.map +1 -1
- package/dist/EntityAdmin/components/entity-filter-panel.component.js +2 -2
- package/dist/EntityAdmin/components/erd-composite.component.js +2 -2
- package/dist/EntityAdmin/components/erd-diagram.component.js +2 -2
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.d.ts.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +14 -15
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.d.ts +122 -0
- package/dist/Home/home-dashboard.component.d.ts.map +1 -0
- package/dist/Home/home-dashboard.component.js +698 -0
- package/dist/Home/home-dashboard.component.js.map +1 -0
- package/dist/Scheduling/components/index.d.ts +11 -0
- package/dist/Scheduling/components/index.d.ts.map +1 -0
- package/dist/Scheduling/components/index.js +13 -0
- package/dist/Scheduling/components/index.js.map +1 -0
- package/dist/Scheduling/components/scheduling-health-resource.component.d.ts +20 -0
- package/dist/Scheduling/components/scheduling-health-resource.component.d.ts.map +1 -0
- package/dist/Scheduling/components/scheduling-health-resource.component.js +55 -0
- package/dist/Scheduling/components/scheduling-health-resource.component.js.map +1 -0
- package/dist/Scheduling/components/scheduling-health.component.js +7 -8
- package/dist/Scheduling/components/scheduling-health.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-history-resource.component.d.ts +20 -0
- package/dist/Scheduling/components/scheduling-history-resource.component.d.ts.map +1 -0
- package/dist/Scheduling/components/scheduling-history-resource.component.js +55 -0
- package/dist/Scheduling/components/scheduling-history-resource.component.js.map +1 -0
- package/dist/Scheduling/components/scheduling-history.component.js +7 -8
- package/dist/Scheduling/components/scheduling-history.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs-resource.component.d.ts +20 -0
- package/dist/Scheduling/components/scheduling-jobs-resource.component.d.ts.map +1 -0
- package/dist/Scheduling/components/scheduling-jobs-resource.component.js +55 -0
- package/dist/Scheduling/components/scheduling-jobs-resource.component.js.map +1 -0
- package/dist/Scheduling/components/scheduling-jobs.component.js +7 -8
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-monitor-resource.component.d.ts +20 -0
- package/dist/Scheduling/components/scheduling-monitor-resource.component.d.ts.map +1 -0
- package/dist/Scheduling/components/scheduling-monitor-resource.component.js +55 -0
- package/dist/Scheduling/components/scheduling-monitor-resource.component.js.map +1 -0
- package/dist/Scheduling/components/scheduling-monitoring.component.js +7 -8
- package/dist/Scheduling/components/scheduling-monitoring.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-types-resource.component.d.ts +20 -0
- package/dist/Scheduling/components/scheduling-types-resource.component.d.ts.map +1 -0
- package/dist/Scheduling/components/scheduling-types-resource.component.js +55 -0
- package/dist/Scheduling/components/scheduling-types-resource.component.js.map +1 -0
- package/dist/Scheduling/components/scheduling-types.component.js +7 -8
- package/dist/Scheduling/components/scheduling-types.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.d.ts +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +3 -3
- package/dist/Testing/components/index.d.ts +11 -0
- package/dist/Testing/components/index.d.ts.map +1 -0
- package/dist/Testing/components/index.js +13 -0
- package/dist/Testing/components/index.js.map +1 -0
- package/dist/Testing/components/testing-analytics-resource.component.d.ts +20 -0
- package/dist/Testing/components/testing-analytics-resource.component.d.ts.map +1 -0
- package/dist/Testing/components/testing-analytics-resource.component.js +55 -0
- package/dist/Testing/components/testing-analytics-resource.component.js.map +1 -0
- package/dist/Testing/components/testing-execution-resource.component.d.ts +20 -0
- package/dist/Testing/components/testing-execution-resource.component.d.ts.map +1 -0
- package/dist/Testing/components/testing-execution-resource.component.js +55 -0
- package/dist/Testing/components/testing-execution-resource.component.js.map +1 -0
- package/dist/Testing/components/testing-execution.component.js +3 -3
- package/dist/Testing/components/testing-execution.component.js.map +1 -1
- package/dist/Testing/components/testing-feedback-resource.component.d.ts +20 -0
- package/dist/Testing/components/testing-feedback-resource.component.d.ts.map +1 -0
- package/dist/Testing/components/testing-feedback-resource.component.js +55 -0
- package/dist/Testing/components/testing-feedback-resource.component.js.map +1 -0
- package/dist/Testing/components/testing-overview-resource.component.d.ts +20 -0
- package/dist/Testing/components/testing-overview-resource.component.d.ts.map +1 -0
- package/dist/Testing/components/testing-overview-resource.component.js +55 -0
- package/dist/Testing/components/testing-overview-resource.component.js.map +1 -0
- package/dist/Testing/components/testing-version-resource.component.d.ts +20 -0
- package/dist/Testing/components/testing-version-resource.component.d.ts.map +1 -0
- package/dist/Testing/components/testing-version-resource.component.js +55 -0
- package/dist/Testing/components/testing-version-resource.component.js.map +1 -0
- package/dist/Testing/testing-dashboard.component.d.ts +1 -1
- package/dist/Testing/testing-dashboard.component.js +23 -25
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/module.d.ts +83 -66
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +137 -19
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +6 -4
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +41 -13
- package/dist/public-api.js.map +1 -1
- package/package.json +17 -14
- package/dist/AI/ai-dashboard.component.d.ts +0 -62
- package/dist/AI/ai-dashboard.component.d.ts.map +0 -1
- package/dist/AI/ai-dashboard.component.js +0 -338
- package/dist/AI/ai-dashboard.component.js.map +0 -1
- package/dist/Actions/actions-management-dashboard.component.d.ts +0 -52
- package/dist/Actions/actions-management-dashboard.component.d.ts.map +0 -1
- package/dist/Actions/actions-management-dashboard.component.js +0 -308
- package/dist/Actions/actions-management-dashboard.component.js.map +0 -1
- package/dist/generic/base-dashboard.d.ts +0 -65
- package/dist/generic/base-dashboard.d.ts.map +0 -1
- package/dist/generic/base-dashboard.js +0 -74
- package/dist/generic/base-dashboard.js.map +0 -1
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { Component, ViewChild, HostListener } from '@angular/core';
|
|
8
|
-
import { BaseDashboard } from '
|
|
8
|
+
import { BaseDashboard } from '@memberjunction/ng-shared';
|
|
9
9
|
import { RegisterClass } from '@memberjunction/global';
|
|
10
10
|
import { RunView, CompositeKey, Metadata } from '@memberjunction/core';
|
|
11
11
|
import { Subject } from 'rxjs';
|
|
@@ -25,6 +25,7 @@ import * as i6 from "@progress/kendo-angular-layout";
|
|
|
25
25
|
import * as i7 from "@memberjunction/ng-code-editor";
|
|
26
26
|
import * as i8 from "@progress/kendo-angular-buttons";
|
|
27
27
|
import * as i9 from "@memberjunction/ng-react";
|
|
28
|
+
import * as i10 from "@memberjunction/ng-shared-generic";
|
|
28
29
|
const _c0 = ["fileInput"];
|
|
29
30
|
const _forTrack0 = ($index, $item) => $item.name;
|
|
30
31
|
function _forTrack1($index, $item) { return this.getComponentId($item); }
|
|
@@ -237,8 +238,7 @@ function ComponentStudioDashboardComponent_Conditional_37_Template(rf, ctx) { if
|
|
|
237
238
|
} }
|
|
238
239
|
function ComponentStudioDashboardComponent_Conditional_39_Template(rf, ctx) { if (rf & 1) {
|
|
239
240
|
i0.ɵɵelementStart(0, "div", 32);
|
|
240
|
-
i0.ɵɵelement(1, "
|
|
241
|
-
i0.ɵɵtext(2, " Loading components... ");
|
|
241
|
+
i0.ɵɵelement(1, "mj-loading", 69);
|
|
242
242
|
i0.ɵɵelementEnd();
|
|
243
243
|
} }
|
|
244
244
|
function ComponentStudioDashboardComponent_Conditional_40_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -701,7 +701,7 @@ function ComponentStudioDashboardComponent_Conditional_44_ng_template_11_Conditi
|
|
|
701
701
|
function ComponentStudioDashboardComponent_Conditional_44_ng_template_11_For_11_ng_template_1_Template(rf, ctx) { if (rf & 1) {
|
|
702
702
|
const _r27 = i0.ɵɵgetCurrentView();
|
|
703
703
|
i0.ɵɵelementStart(0, "mj-code-editor", 141);
|
|
704
|
-
i0.ɵɵlistener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_44_ng_template_11_For_11_ng_template_1_Template_mj_code_editor_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r27); const ɵ$
|
|
704
|
+
i0.ɵɵlistener("ngModelChange", function ComponentStudioDashboardComponent_Conditional_44_ng_template_11_For_11_ng_template_1_Template_mj_code_editor_ngModelChange_0_listener($event) { i0.ɵɵrestoreView(_r27); const ɵ$index_559_r28 = i0.ɵɵnextContext().$index; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onCodeSectionChange($event, ɵ$index_559_r28)); });
|
|
705
705
|
i0.ɵɵelementEnd();
|
|
706
706
|
} if (rf & 2) {
|
|
707
707
|
const section_r29 = i0.ɵɵnextContext().$implicit;
|
|
@@ -1984,7 +1984,7 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
|
|
|
1984
1984
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.fileInput = _t.first);
|
|
1985
1985
|
} }, hostBindings: function ComponentStudioDashboardComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
1986
1986
|
i0.ɵɵlistener("click", function ComponentStudioDashboardComponent_click_HostBindingHandler($event) { return ctx.onDocumentClick($event); }, false, i0.ɵɵresolveDocument);
|
|
1987
|
-
} }, features: [i0.ɵɵInheritDefinitionFeature], decls: 46, vars: 22, consts: [["fileInput", ""], [1, "component-studio"], [1, "dashboard-header"], [1, "header-content"], [1, "fa-solid", "fa-puzzle-piece"], [1, "header-subtitle"], [1, "header-buttons"], ["kendoButton", "", 3, "themeColor"], [1, "import-dropdown"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-file-import"], [1, "fa-solid", "fa-chevron-down", 2, "margin-left", "5px", "font-size", "10px"], [1, "dropdown-menu"], [1, "export-dropdown", 3, "open"], ["kendoButton", "", 3, "click", "disabled"], [1, "fa-solid", "fa-sync"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["orientation", "horizontal"], [3, "min", "max", "size"], [1, "components-panel"], [1, "panel-header"], [1, "panel-header-top"], [1, "header-actions"], [1, "filter-toggle-btn", 3, "click", "title"], [1, "fa-solid", "fa-sliders"], [1, "filter-count-badge"], [1, "component-count"], [1, "search-box"], ["placeholder", "Search components...", 3, "valueChange", "value", "clearButton"], ["kendoTextBoxPrefixTemplate", ""], [1, "filter-panel"], [1, "components-list"], [1, "loading-message"], [1, "empty-message"], [3, "min"], [1, "component-display"], [1, "empty-state"], [1, "fa-solid", "fa-eye"], [1, "fa-solid", "fa-eye-slash"], [1, "dropdown-item", 3, "click"], [1, "fa-solid", "fa-database"], [1, "fa-solid", "fa-file"], [1, "fa-solid", "fa-keyboard"], [1, "export-dropdown"], [1, "fa-solid", "fa-file-export"], [1, "fa-solid", "fa-save"], [1, "fa-solid", "fa-clipboard"], [1, "fa-solid", "fa-search"], [1, "filter-panel-header", 3, "click"], [1, "fa-solid", "fa-chevron-down"], [1, "filter-count-text"], [1, "filter-panel-content"], [1, "filter-section"], [1, "filter-section-label"], [1, "filter-options"], [1, "filter-checkbox"], ["type", "checkbox", 3, "change", "checked"], [1, "deprecated-count"], [1, "filter-panel-footer"], [1, "category-pills-grid"], [1, "category-pill-compact", 3, "active", "--pill-color"], [1, "show-more-categories-btn"], [1, "category-pill-compact", 3, "click"], [1, "pill-name"], [1, "pill-count"], [1, "show-more-categories-btn", 3, "click"], [1, "fa-solid", "fa-chevron-up"], [1, "clear-all-btn", 3, "click"], [1, "fa-solid", "fa-times"], [
|
|
1987
|
+
} }, features: [i0.ɵɵInheritDefinitionFeature], decls: 46, vars: 22, consts: [["fileInput", ""], [1, "component-studio"], [1, "dashboard-header"], [1, "header-content"], [1, "fa-solid", "fa-puzzle-piece"], [1, "header-subtitle"], [1, "header-buttons"], ["kendoButton", "", 3, "themeColor"], [1, "import-dropdown"], ["kendoButton", "", 3, "click", "themeColor"], [1, "fa-solid", "fa-file-import"], [1, "fa-solid", "fa-chevron-down", 2, "margin-left", "5px", "font-size", "10px"], [1, "dropdown-menu"], [1, "export-dropdown", 3, "open"], ["kendoButton", "", 3, "click", "disabled"], [1, "fa-solid", "fa-sync"], ["type", "file", "accept", ".json", 2, "display", "none", 3, "change"], ["orientation", "horizontal"], [3, "min", "max", "size"], [1, "components-panel"], [1, "panel-header"], [1, "panel-header-top"], [1, "header-actions"], [1, "filter-toggle-btn", 3, "click", "title"], [1, "fa-solid", "fa-sliders"], [1, "filter-count-badge"], [1, "component-count"], [1, "search-box"], ["placeholder", "Search components...", 3, "valueChange", "value", "clearButton"], ["kendoTextBoxPrefixTemplate", ""], [1, "filter-panel"], [1, "components-list"], [1, "loading-message"], [1, "empty-message"], [3, "min"], [1, "component-display"], [1, "empty-state"], [1, "fa-solid", "fa-eye"], [1, "fa-solid", "fa-eye-slash"], [1, "dropdown-item", 3, "click"], [1, "fa-solid", "fa-database"], [1, "fa-solid", "fa-file"], [1, "fa-solid", "fa-keyboard"], [1, "export-dropdown"], [1, "fa-solid", "fa-file-export"], [1, "fa-solid", "fa-save"], [1, "fa-solid", "fa-clipboard"], [1, "fa-solid", "fa-search"], [1, "filter-panel-header", 3, "click"], [1, "fa-solid", "fa-chevron-down"], [1, "filter-count-text"], [1, "filter-panel-content"], [1, "filter-section"], [1, "filter-section-label"], [1, "filter-options"], [1, "filter-checkbox"], ["type", "checkbox", 3, "change", "checked"], [1, "deprecated-count"], [1, "filter-panel-footer"], [1, "category-pills-grid"], [1, "category-pill-compact", 3, "active", "--pill-color"], [1, "show-more-categories-btn"], [1, "category-pill-compact", 3, "click"], [1, "pill-name"], [1, "pill-count"], [1, "show-more-categories-btn", 3, "click"], [1, "fa-solid", "fa-chevron-up"], [1, "clear-all-btn", 3, "click"], [1, "fa-solid", "fa-times"], ["text", "Loading components...", "size", "small"], [1, "fa-solid", "fa-info-circle"], [1, "component-card", 3, "expanded", "running", "file-loaded"], [1, "component-card"], [1, "card-header", 3, "click"], [1, "card-icon"], [1, "fa-solid", 3, "ngClass"], [1, "favorite-btn", 3, "is-favorite", "title"], [1, "card-info"], [1, "card-name"], [1, "file-badge", 3, "title"], [1, "card-meta"], [1, "card-type"], [1, "card-version"], [1, "status-badge", "deprecated"], [1, "status-badge", "published"], [1, "status-badge", "draft"], [1, "card-namespace"], [1, "namespace-chip", 3, "title"], [1, "fa-solid", "fa-folder-tree"], [1, "card-chevron"], [1, "card-details"], [1, "favorite-btn", 3, "click", "title"], [1, "fa-solid", "fa-star"], [1, "fa-regular", "fa-star"], [1, "status-badge", "text"], [1, "status-badge", "file"], [1, "detail-section"], [1, "info-grid"], [1, "info-item"], [1, "info-label"], [1, "info-value"], [1, "card-actions"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "themeColor"], [1, "fa-solid", "fa-stop"], ["kendoButton", "", "title", "Stop current component and run this one", 3, "click", "themeColor"], [1, "fa-solid", "fa-play"], [3, "size"], [1, "component-runtime"], [1, "run-empty-state"], [1, "editor-tabs", 3, "tabSelect"], [3, "title", "selected"], ["kendoTabContent", ""], [1, "error-display"], [3, "component"], [1, "error-container"], [1, "error-header"], [1, "fa-solid", "fa-exclamation-triangle"], ["title", "Copy error details", 1, "copy-button", 3, "click"], [1, "fa-solid", "fa-copy"], [1, "error-intro"], [1, "error-details"], [1, "technical-details"], [1, "error-help"], [1, "error-actions"], ["kendoButton", "", 3, "click"], [1, "fa-solid", "fa-rotate"], [3, "componentEvent", "openEntityRecord", "component"], [1, "fa-solid", "fa-play-circle", "fa-3x"], ["kendoButton", "", 3, "click", "themeColor", "size"], [1, "tab-content", "spec-tab"], [1, "editor-header"], [1, "fa-solid", "fa-code"], [1, "editor-actions"], [1, "editor-wrapper"], [2, "height", "100%", "width", "100%", 3, "ngModelChange", "ngModel", "language", "readonly"], [1, "fa-solid", "fa-check"], [1, "tab-content", "code-tab"], [1, "fa-solid", "fa-file-code"], [1, "code-sections"], [3, "title", "expanded"], ["kendoPanelBarContent", ""], [2, "height", "400px", "width", "100%", 3, "ngModelChange", "ngModel", "language", "readonly"], [1, "fa-solid", "fa-rocket", "fa-3x"]], template: function ComponentStudioDashboardComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1988
1988
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
1989
1989
|
i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div")(4, "h1");
|
|
1990
1990
|
i0.ɵɵelement(5, "i", 4);
|
|
@@ -2027,7 +2027,7 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
|
|
|
2027
2027
|
i0.ɵɵtemplate(37, ComponentStudioDashboardComponent_Conditional_37_Template, 23, 7, "div", 30);
|
|
2028
2028
|
i0.ɵɵelementEnd();
|
|
2029
2029
|
i0.ɵɵelementStart(38, "div", 31);
|
|
2030
|
-
i0.ɵɵtemplate(39, ComponentStudioDashboardComponent_Conditional_39_Template,
|
|
2030
|
+
i0.ɵɵtemplate(39, ComponentStudioDashboardComponent_Conditional_39_Template, 2, 0, "div", 32)(40, ComponentStudioDashboardComponent_Conditional_40_Template, 6, 0, "div", 33)(41, ComponentStudioDashboardComponent_Conditional_41_Template, 2, 0);
|
|
2031
2031
|
i0.ɵɵelementEnd()()();
|
|
2032
2032
|
i0.ɵɵelementStart(42, "kendo-splitter-pane", 34)(43, "div", 35);
|
|
2033
2033
|
i0.ɵɵtemplate(44, ComponentStudioDashboardComponent_Conditional_44_Template, 13, 8)(45, ComponentStudioDashboardComponent_Conditional_45_Template, 6, 0, "div", 36);
|
|
@@ -2064,7 +2064,7 @@ ${this.currentError.technicalDetails ? '\nTechnical Details:\n' + JSON.stringify
|
|
|
2064
2064
|
i0.ɵɵproperty("min", "400px");
|
|
2065
2065
|
i0.ɵɵadvance(2);
|
|
2066
2066
|
i0.ɵɵconditional(ctx.selectedComponent ? 44 : 45);
|
|
2067
|
-
} }, dependencies: [i3.NgClass, i4.NgControlStatus, i4.NgModel, i5.TextBoxComponent, i5.TextBoxPrefixTemplateDirective, i6.PanelBarComponent, i6.PanelBarItemComponent, i6.PanelBarContentDirective, i6.SplitterComponent, i6.SplitterPaneComponent, i6.TabStripComponent, i6.TabStripTabComponent, i6.TabContentDirective, i7.CodeEditorComponent, i8.ButtonComponent, i9.MJReactComponent, i3.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n \n .import-dropdown, .export-dropdown {\n position: relative;\n \n .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n z-index: 1000;\n min-width: 180px;\n \n .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: #212529;\n transition: background-color 0.2s;\n \n &:hover {\n background-color: #f8f9fa;\n }\n \n &:not(:last-child) {\n border-bottom: 1px solid #e9ecef;\n }\n \n i {\n width: 16px;\n text-align: center;\n color: #6366f1;\n }\n }\n }\n }\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n .panel-header-top {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n\n .header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n \n .favorites-toggle,\n .deprecated-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n font-size: 14px;\n }\n }\n\n .favorites-toggle.active {\n background: #fff3cd;\n border-color: #ffc107;\n color: #856404;\n\n i {\n color: #ffc107;\n }\n }\n\n .deprecated-toggle.active {\n background: #ffe4e1;\n border-color: #ff6b6b;\n color: #c92a2a;\n\n i {\n color: #ff6b6b;\n }\n }\n\n .count-badge {\n margin-left: 4px;\n background: #f59e0b;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .deprecated-toggle.active .count-badge {\n background: #ff6b6b;\n }\n\n .component-count {\n font-size: 13px;\n color: #6c757d;\n background: #f8f9fa;\n padding: 4px 10px;\n border-radius: 12px;\n font-weight: 500;\n }\n }\n }\n \n .category-filters {\n margin-bottom: 16px;\n \n .filter-pills {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n \n .category-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n overflow: hidden;\n \n &:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n \n &.active {\n border-color: var(--pill-color);\n background: var(--pill-color);\n color: white;\n \n .pill-count {\n background: rgba(255, 255, 255, 0.3);\n color: white;\n }\n }\n \n .pill-name {\n font-weight: 500;\n }\n \n .pill-count {\n background: #f1f3f5;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n min-width: 20px;\n text-align: center;\n }\n }\n \n .more-button,\n .clear-filters-button {\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n \n i {\n font-size: 11px;\n margin-right: 4px;\n }\n }\n \n .clear-filters-button {\n background: #fee2e2;\n border-color: #fca5a5;\n color: #dc2626;\n \n &:hover {\n background: #fca5a5;\n color: white;\n }\n }\n }\n }\n \n .search-box {\n margin-bottom: 12px;\n\n kendo-textbox {\n width: 100%;\n }\n\n // Reduce search input font size\n ::ng-deep .k-input-inner {\n font-size: 13px;\n }\n }\n\n // New filter toggle button\n .filter-toggle-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px 10px;\n border: 1px solid #ced4da;\n background: white;\n border-radius: 4px;\n font-size: 13px;\n color: #495057;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #e9ecef;\n border-color: #adb5bd;\n }\n\n &.active {\n background: #e7f3ff;\n border-color: #1e40af;\n color: #1e40af;\n }\n\n i {\n font-size: 13px;\n }\n\n .filter-count-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n background: #1e40af;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n min-width: 18px;\n text-align: center;\n }\n }\n\n // Collapsible filter panel\n .filter-panel {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n overflow: hidden;\n animation: slideDown 0.2s ease;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .filter-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #e9ecef;\n cursor: pointer;\n font-weight: 600;\n font-size: 12px;\n color: #495057;\n user-select: none;\n\n &:hover {\n background: #dee2e6;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n\n .filter-count-text {\n font-size: 11px;\n font-weight: 500;\n color: #6c757d;\n }\n }\n\n .filter-panel-content {\n padding: 14px;\n }\n\n .filter-section {\n margin-bottom: 16px;\n\n &:last-child {\n margin-bottom: 0;\n }\n\n .filter-section-label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #495057;\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .filter-options {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .filter-checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 13px;\n color: #212529;\n padding: 6px 0;\n\n input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n\n span {\n user-select: none;\n }\n\n .deprecated-count {\n color: #6c757d;\n font-size: 12px;\n margin-left: 4px;\n }\n }\n\n .category-pills-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .category-pill-compact {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: #495057;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n border-color: #adb5bd;\n transform: translateY(-1px);\n }\n\n &.active {\n border-color: var(--pill-color, #6366f1);\n background: var(--pill-color, #6366f1);\n color: white;\n }\n\n .pill-name {\n font-weight: 500;\n }\n\n .pill-count {\n font-size: 11px;\n opacity: 0.8;\n }\n }\n\n .show-more-categories-btn {\n padding: 5px 10px;\n border: 1px dashed #dee2e6;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n }\n }\n\n .filter-panel-footer {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid #dee2e6;\n\n .clear-all-btn {\n width: 100%;\n padding: 8px;\n border: 1px solid #dc3545;\n background: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #dc3545;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #dc3545;\n color: white;\n }\n\n i {\n margin-right: 6px;\n }\n }\n }\n }\n\n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .favorite-btn {\n position: absolute;\n top: 12px;\n right: 48px; // Leave room for chevron\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 50%;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n transform: scale(1.1);\n }\n \n &.is-favorite {\n color: #ffc107;\n border-color: #ffc107;\n background: #fff3cd;\n \n &:hover {\n background: #ffe69c;\n }\n }\n \n i {\n font-size: 14px;\n }\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n\n &.deprecated {\n background: #ffe4e1;\n color: #c92a2a;\n border: 1px solid #ff6b6b;\n }\n\n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n \n &.text {\n background: #f3e8ff;\n color: #6b21a8;\n }\n }\n }\n \n .card-namespace {\n margin-top: 8px;\n \n .namespace-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: white;\n \n i {\n font-size: 11px;\n opacity: 0.9;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] Removed[_ngcontent-%COMP%] tree[_ngcontent-%COMP%] view[_ngcontent-%COMP%] styles[_ngcontent-%COMP%] -[_ngcontent-%COMP%] using[_ngcontent-%COMP%] modern[_ngcontent-%COMP%] category[_ngcontent-%COMP%] filters[_ngcontent-%COMP%] instead\n\n@keyframes[_ngcontent-%COMP%] slideDown[_ngcontent-%COMP%] {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}"] });
|
|
2067
|
+
} }, dependencies: [i3.NgClass, i4.NgControlStatus, i4.NgModel, i5.TextBoxComponent, i5.TextBoxPrefixTemplateDirective, i6.PanelBarComponent, i6.PanelBarItemComponent, i6.PanelBarContentDirective, i6.SplitterComponent, i6.SplitterPaneComponent, i6.TabStripComponent, i6.TabStripTabComponent, i6.TabContentDirective, i7.CodeEditorComponent, i8.ButtonComponent, i9.MJReactComponent, i10.LoadingComponent, i3.DatePipe], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n \n .import-dropdown, .export-dropdown {\n position: relative;\n \n .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n z-index: 1000;\n min-width: 180px;\n \n .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: #212529;\n transition: background-color 0.2s;\n \n &:hover {\n background-color: #f8f9fa;\n }\n \n &:not(:last-child) {\n border-bottom: 1px solid #e9ecef;\n }\n \n i {\n width: 16px;\n text-align: center;\n color: #6366f1;\n }\n }\n }\n }\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n .panel-header-top {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n\n .header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n \n .favorites-toggle,\n .deprecated-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n font-size: 14px;\n }\n }\n\n .favorites-toggle.active {\n background: #fff3cd;\n border-color: #ffc107;\n color: #856404;\n\n i {\n color: #ffc107;\n }\n }\n\n .deprecated-toggle.active {\n background: #ffe4e1;\n border-color: #ff6b6b;\n color: #c92a2a;\n\n i {\n color: #ff6b6b;\n }\n }\n\n .count-badge {\n margin-left: 4px;\n background: #f59e0b;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .deprecated-toggle.active .count-badge {\n background: #ff6b6b;\n }\n\n .component-count {\n font-size: 13px;\n color: #6c757d;\n background: #f8f9fa;\n padding: 4px 10px;\n border-radius: 12px;\n font-weight: 500;\n }\n }\n }\n \n .category-filters {\n margin-bottom: 16px;\n \n .filter-pills {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n \n .category-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n overflow: hidden;\n \n &:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n \n &.active {\n border-color: var(--pill-color);\n background: var(--pill-color);\n color: white;\n \n .pill-count {\n background: rgba(255, 255, 255, 0.3);\n color: white;\n }\n }\n \n .pill-name {\n font-weight: 500;\n }\n \n .pill-count {\n background: #f1f3f5;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n min-width: 20px;\n text-align: center;\n }\n }\n \n .more-button,\n .clear-filters-button {\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n \n i {\n font-size: 11px;\n margin-right: 4px;\n }\n }\n \n .clear-filters-button {\n background: #fee2e2;\n border-color: #fca5a5;\n color: #dc2626;\n \n &:hover {\n background: #fca5a5;\n color: white;\n }\n }\n }\n }\n \n .search-box {\n margin-bottom: 12px;\n\n kendo-textbox {\n width: 100%;\n }\n\n // Reduce search input font size\n ::ng-deep .k-input-inner {\n font-size: 13px;\n }\n }\n\n // New filter toggle button\n .filter-toggle-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px 10px;\n border: 1px solid #ced4da;\n background: white;\n border-radius: 4px;\n font-size: 13px;\n color: #495057;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #e9ecef;\n border-color: #adb5bd;\n }\n\n &.active {\n background: #e7f3ff;\n border-color: #1e40af;\n color: #1e40af;\n }\n\n i {\n font-size: 13px;\n }\n\n .filter-count-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n background: #1e40af;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n min-width: 18px;\n text-align: center;\n }\n }\n\n // Collapsible filter panel\n .filter-panel {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n overflow: hidden;\n animation: slideDown 0.2s ease;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .filter-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #e9ecef;\n cursor: pointer;\n font-weight: 600;\n font-size: 12px;\n color: #495057;\n user-select: none;\n\n &:hover {\n background: #dee2e6;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n\n .filter-count-text {\n font-size: 11px;\n font-weight: 500;\n color: #6c757d;\n }\n }\n\n .filter-panel-content {\n padding: 14px;\n }\n\n .filter-section {\n margin-bottom: 16px;\n\n &:last-child {\n margin-bottom: 0;\n }\n\n .filter-section-label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #495057;\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .filter-options {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .filter-checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 13px;\n color: #212529;\n padding: 6px 0;\n\n input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n\n span {\n user-select: none;\n }\n\n .deprecated-count {\n color: #6c757d;\n font-size: 12px;\n margin-left: 4px;\n }\n }\n\n .category-pills-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .category-pill-compact {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: #495057;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n border-color: #adb5bd;\n transform: translateY(-1px);\n }\n\n &.active {\n border-color: var(--pill-color, #6366f1);\n background: var(--pill-color, #6366f1);\n color: white;\n }\n\n .pill-name {\n font-weight: 500;\n }\n\n .pill-count {\n font-size: 11px;\n opacity: 0.8;\n }\n }\n\n .show-more-categories-btn {\n padding: 5px 10px;\n border: 1px dashed #dee2e6;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n }\n }\n\n .filter-panel-footer {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid #dee2e6;\n\n .clear-all-btn {\n width: 100%;\n padding: 8px;\n border: 1px solid #dc3545;\n background: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #dc3545;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #dc3545;\n color: white;\n }\n\n i {\n margin-right: 6px;\n }\n }\n }\n }\n\n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .favorite-btn {\n position: absolute;\n top: 12px;\n right: 48px; // Leave room for chevron\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 50%;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n transform: scale(1.1);\n }\n \n &.is-favorite {\n color: #ffc107;\n border-color: #ffc107;\n background: #fff3cd;\n \n &:hover {\n background: #ffe69c;\n }\n }\n \n i {\n font-size: 14px;\n }\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n\n &.deprecated {\n background: #ffe4e1;\n color: #c92a2a;\n border: 1px solid #ff6b6b;\n }\n\n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n \n &.text {\n background: #f3e8ff;\n color: #6b21a8;\n }\n }\n }\n \n .card-namespace {\n margin-top: 8px;\n \n .namespace-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: white;\n \n i {\n font-size: 11px;\n opacity: 0.9;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] Removed[_ngcontent-%COMP%] tree[_ngcontent-%COMP%] view[_ngcontent-%COMP%] styles[_ngcontent-%COMP%] -[_ngcontent-%COMP%] using[_ngcontent-%COMP%] modern[_ngcontent-%COMP%] category[_ngcontent-%COMP%] filters[_ngcontent-%COMP%] instead\n\n@keyframes[_ngcontent-%COMP%] slideDown[_ngcontent-%COMP%] {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}"] });
|
|
2068
2068
|
};
|
|
2069
2069
|
ComponentStudioDashboardComponent = __decorate([
|
|
2070
2070
|
RegisterClass(BaseDashboard, 'ComponentStudioDashboard')
|
|
@@ -2072,7 +2072,7 @@ ComponentStudioDashboardComponent = __decorate([
|
|
|
2072
2072
|
export { ComponentStudioDashboardComponent };
|
|
2073
2073
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentStudioDashboardComponent, [{
|
|
2074
2074
|
type: Component,
|
|
2075
|
-
args: [{ selector: 'mj-component-studio-dashboard', template: "<div class=\"component-studio\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-content\">\n <div>\n <h1><i class=\"fa-solid fa-puzzle-piece\"></i> Component Studio</h1>\n <p class=\"header-subtitle\">Testing components without required custom properties</p>\n </div>\n <div class=\"header-buttons\">\n @if (selectedComponent && isRunning) {\n <button kendoButton (click)=\"toggleDetailsPane()\" [themeColor]=\"'base'\">\n @if (isDetailsPaneCollapsed) {\n <span class=\"fa-solid fa-eye\"></span> Show Details\n } @else {\n <span class=\"fa-solid fa-eye-slash\"></span> Hide Details\n }\n </button>\n }\n <div class=\"import-dropdown\" [class.open]=\"importDropdownOpen\">\n <button kendoButton (click)=\"toggleImportDropdown()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-file-import\"></span> Import\n <span class=\"fa-solid fa-chevron-down\" style=\"margin-left: 5px; font-size: 10px;\"></span>\n </button>\n @if (importDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"importFromArtifact()\">\n <i class=\"fa-solid fa-database\"></i> Import from Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"importFromFile()\">\n <i class=\"fa-solid fa-file\"></i> Import from File\n </button>\n <button class=\"dropdown-item\" (click)=\"importFromText()\">\n <i class=\"fa-solid fa-keyboard\"></i> Import from Text\n </button>\n </div>\n }\n </div>\n @if (selectedComponent && isRunning) {\n <div class=\"export-dropdown\" [class.open]=\"exportDropdownOpen\">\n <button kendoButton (click)=\"toggleExportDropdown()\" [themeColor]=\"'primary'\">\n <span class=\"fa-solid fa-file-export\"></span> Export\n <span class=\"fa-solid fa-chevron-down\" style=\"margin-left: 5px; font-size: 10px;\"></span>\n </button>\n @if (exportDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"exportToArtifact()\">\n <i class=\"fa-solid fa-save\"></i> Export to Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"exportToFile()\">\n <i class=\"fa-solid fa-file\"></i> Export to File\n </button>\n <button class=\"dropdown-item\" (click)=\"exportToClipboard()\">\n <i class=\"fa-solid fa-clipboard\"></i> Export to Clipboard\n </button>\n </div>\n }\n </div>\n }\n <button kendoButton (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <span class=\"fa-solid fa-sync\"></span> Refresh\n </button>\n </div>\n <!-- Hidden file input -->\n <input #fileInput type=\"file\" accept=\".json\" (change)=\"handleFileSelect($event)\" style=\"display: none;\" />\n </div>\n </div>\n\n <!-- Main Content with Splitter -->\n <kendo-splitter orientation=\"horizontal\">\n <!-- Left Panel - Component List -->\n <kendo-splitter-pane [min]=\"'350px'\" [max]=\"'650px'\" [size]=\"'400px'\">\n <div class=\"components-panel\">\n <div class=\"panel-header\">\n <!-- Clean Header with Filter Button -->\n <div class=\"panel-header-top\">\n <div class=\"header-actions\">\n <button\n class=\"filter-toggle-btn\"\n [class.active]=\"isFilterPanelExpanded || GetActiveFilterCount() > 0\"\n (click)=\"ToggleFilterPanel()\"\n [title]=\"isFilterPanelExpanded ? 'Hide filters' : 'Show filters'\">\n <i class=\"fa-solid fa-sliders\"></i>\n @if (GetActiveFilterCount() > 0) {\n <span class=\"filter-count-badge\">{{ GetActiveFilterCount() }}</span>\n }\n </button>\n <span class=\"component-count\">{{ filteredComponents.length }} of {{ allComponents.length }}</span>\n </div>\n </div>\n\n <!-- Search (Always Visible) -->\n <div class=\"search-box\">\n <kendo-textbox\n [value]=\"searchQuery\"\n (valueChange)=\"onSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n\n <!-- Collapsible Filter Panel -->\n @if (isFilterPanelExpanded) {\n <div class=\"filter-panel\">\n <div class=\"filter-panel-header\" (click)=\"ToggleFilterPanel()\">\n <span><i class=\"fa-solid fa-chevron-down\"></i> Filters</span>\n <span class=\"filter-count-text\">{{ filteredComponents.length }} of {{ allComponents.length }}</span>\n </div>\n\n <div class=\"filter-panel-content\">\n <!-- Quick Filters -->\n <div class=\"filter-section\">\n <label class=\"filter-section-label\">Quick Filters</label>\n <div class=\"filter-options\">\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"showOnlyFavorites\"\n (change)=\"toggleShowOnlyFavorites()\">\n <span>Show favorites only</span>\n </label>\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"!showDeprecatedComponents\"\n (change)=\"toggleShowDeprecatedComponents()\">\n <span>Hide deprecated\n @if (getDeprecatedCount() > 0) {\n <span class=\"deprecated-count\">({{ getDeprecatedCount() }} hidden)</span>\n }\n </span>\n </label>\n </div>\n </div>\n\n <!-- Category Filters -->\n @if (availableCategories.length > 0) {\n <div class=\"filter-section\">\n <label class=\"filter-section-label\">Categories</label>\n <div class=\"category-pills-grid\">\n @for (category of getVisibleCategories(); track category.name) {\n <button\n class=\"category-pill-compact\"\n [class.active]=\"isCategorySelected(category.name)\"\n [style.--pill-color]=\"category.color\"\n (click)=\"toggleCategory(category.name)\">\n <span class=\"pill-name\">{{ category.name }}</span>\n <span class=\"pill-count\">{{ category.count }}</span>\n </button>\n }\n </div>\n @if (availableCategories.length > 5) {\n <button\n class=\"show-more-categories-btn\"\n (click)=\"toggleShowAllCategories()\">\n @if (showAllCategories) {\n <i class=\"fa-solid fa-chevron-up\"></i> Show less\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i> Show {{ availableCategories.length - 5 }} more\n }\n </button>\n }\n </div>\n }\n\n <!-- Clear All Button -->\n @if (GetActiveFilterCount() > 0) {\n <div class=\"filter-panel-footer\">\n <button class=\"clear-all-btn\" (click)=\"ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear All Filters\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n \n <div class=\"components-list\">\n @if (isLoading) {\n <div class=\"loading-message\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading components...\n </div>\n } @else if (filteredComponents.length === 0) {\n <div class=\"empty-message\">\n <i class=\"fa-solid fa-info-circle\"></i> No components found without required custom properties.\n <br>\n <small>Components with optional custom props can be tested, but not those with required props.</small>\n </div>\n } @else {\n <!-- Component Cards -->\n @for (component of filteredComponents; track getComponentId(component)) {\n <div class=\"component-card\" \n [class.expanded]=\"expandedComponent && getComponentId(expandedComponent) === getComponentId(component)\"\n [class.running]=\"selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning\"\n [class.file-loaded]=\"isFileLoadedComponent(component)\">\n \n <!-- Card Header - Always visible -->\n <div class=\"card-header\" (click)=\"toggleComponentExpansion(component)\">\n <div class=\"card-icon\" [style.color]=\"getComponentTypeColor(getComponentType(component))\">\n <i class=\"fa-solid\" [ngClass]=\"getComponentTypeIcon(getComponentType(component))\"></i>\n </div>\n @if (!isFileLoadedComponent(component)) {\n <button \n class=\"favorite-btn\"\n [class.is-favorite]=\"isFavorite(component)\"\n (click)=\"toggleFavorite(component, $event)\"\n [title]=\"isFavorite(component) ? 'Remove from favorites' : 'Add to favorites'\">\n @if (isFavorite(component)) {\n <i class=\"fa-solid fa-star\"></i>\n } @else {\n <i class=\"fa-regular fa-star\"></i>\n }\n </button>\n }\n <div class=\"card-info\">\n <div class=\"card-name\">\n {{ getComponentName(component) }}\n @if (isFileLoadedComponent(component)) {\n <span class=\"file-badge\" [title]=\"getComponentStatus(component) === 'Text' ? 'Imported from text input' : 'Loaded from ' + getComponentFilename(component)\">\n @if (getComponentStatus(component) === 'Text') {\n <i class=\"fa-solid fa-keyboard\"></i> Text Import\n } @else {\n <i class=\"fa-solid fa-file\"></i> {{ getComponentFilename(component) }}\n }\n </span>\n }\n </div>\n <div class=\"card-meta\">\n <span class=\"card-type\">{{ getComponentType(component) || 'Component' }}</span>\n <span class=\"card-version\">v{{ getComponentVersion(component) }}</span>\n @if (isFileLoadedComponent(component)) {\n @if (getComponentStatus(component) === 'Text') {\n <span class=\"status-badge text\">Text</span>\n } @else {\n <span class=\"status-badge file\">File</span>\n }\n } @else if (getComponentStatus(component) === 'Deprecated') {\n <span class=\"status-badge deprecated\">Deprecated</span>\n } @else if (getComponentStatus(component) === 'Published') {\n <span class=\"status-badge published\">Published</span>\n } @else {\n <span class=\"status-badge draft\">Draft</span>\n }\n </div>\n <!-- Namespace chip with color coding -->\n <div class=\"card-namespace\">\n <span class=\"namespace-chip\" \n [style.background-color]=\"getNamespaceColor(getComponentNamespace(component))\"\n [title]=\"getComponentNamespace(component) || 'Uncategorized'\">\n <i class=\"fa-solid fa-folder-tree\"></i>\n {{ formatNamespace(getComponentNamespace(component)) }}\n </span>\n </div>\n </div>\n <div class=\"card-chevron\">\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <i class=\"fa-solid fa-chevron-up\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </div>\n </div>\n \n <!-- Card Details - Only visible when expanded -->\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <div class=\"card-details\">\n @if (getComponentDescription(component)) {\n <div class=\"detail-section\">\n <label>Description</label>\n <p>{{ getComponentDescription(component) }}</p>\n </div>\n }\n \n <div class=\"detail-section\">\n <label>Component Info</label>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type:</span>\n <span class=\"info-value\">{{ getComponentType(component) || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version:</span>\n <span class=\"info-value\">{{ getComponentVersion(component) }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status:</span>\n <span class=\"info-value\">{{ getComponentStatus(component) || 'Draft' }}</span>\n </div>\n @if (isFileLoadedComponent(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Loaded:</span>\n <span class=\"info-value\">{{ getComponentLoadedAt(component) | date:'short' }}</span>\n </div>\n } @else if (!isFileLoadedComponent(component) && getComponentUpdatedAt(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated:</span>\n <span class=\"info-value\">{{ getComponentUpdatedAt(component) | date:'short' }}</span>\n </div>\n }\n </div>\n </div>\n \n <div class=\"card-actions\">\n @if (selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning) {\n <button kendoButton \n [themeColor]=\"'error'\"\n (click)=\"stopComponent(); $event.stopPropagation()\">\n <span class=\"fa-solid fa-stop\"></span> Stop Component\n </button>\n } @else if (isRunning && selectedComponent && getComponentId(selectedComponent) !== getComponentId(component)) {\n <button kendoButton \n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Switch to This Component\n </button>\n } @else {\n <button kendoButton \n [themeColor]=\"'primary'\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </kendo-splitter-pane>\n\n <!-- Right Panel - Component Display with Editor Splitter -->\n <kendo-splitter-pane [min]=\"'400px'\">\n <div class=\"component-display\">\n @if (selectedComponent) {\n <kendo-splitter orientation=\"horizontal\">\n <kendo-splitter-pane [size]=\"isDetailsPaneCollapsed ? '100%' : '50%'\">\n <div class=\"component-runtime\">\n @if (isRunning && componentSpec) {\n @if (currentError) {\n <!-- Error Display -->\n <div class=\"error-display\">\n <div class=\"error-container\">\n <div class=\"error-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>Component Error</h3>\n <button class=\"copy-button\" (click)=\"copyErrorToClipboard()\" title=\"Copy error details\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n \n <p class=\"error-intro\">\n The component could not be rendered due to the following error:\n </p>\n \n <div class=\"error-details\">\n <strong>Error Type:</strong> {{ currentError.type }}<br>\n <strong>Message:</strong> {{ currentError.message }}\n @if (currentError.technicalDetails) {\n <details class=\"technical-details\">\n <summary>Technical Details (click to expand)</summary>\n <pre>{{ formatTechnicalDetails(currentError.technicalDetails) }}</pre>\n </details>\n }\n </div>\n \n <div class=\"error-help\">\n <strong>What to do:</strong>\n <ol>\n <li>Check that the component code is valid JavaScript/React</li>\n <li>Ensure all required dependencies are available</li>\n <li>Review the technical details for specific error information</li>\n <li>Contact your system administrator if the issue persists</li>\n </ol>\n </div>\n \n <div class=\"error-actions\">\n <button kendoButton (click)=\"retryComponent()\">\n <span class=\"fa-solid fa-rotate\"></span> Retry\n </button>\n <button kendoButton (click)=\"stopComponent()\" [themeColor]=\"'error'\">\n <span class=\"fa-solid fa-stop\"></span> Stop\n </button>\n </div>\n </div>\n </div>\n } @else {\n <!-- React Component -->\n <mj-react-component \n [component]=\"componentSpec\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-react-component>\n }\n } @else {\n <!-- Component Not Running State -->\n <div class=\"run-empty-state\">\n <i class=\"fa-solid fa-play-circle fa-3x\"></i>\n <h3>Component: {{ getComponentName(selectedComponent) }}</h3>\n <p>{{ getComponentDescription(selectedComponent) || 'No description available' }}</p>\n <button kendoButton [themeColor]=\"'primary'\" [size]=\"'large'\" (click)=\"runComponent(selectedComponent)\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n </div>\n }\n </div>\n\n </kendo-splitter-pane>\n <kendo-splitter-pane [size]=\"isDetailsPaneCollapsed ? '0px' : '50%'\">\n <div>\n <kendo-tabstrip (tabSelect)=\"onTabSelect($event)\" class=\"editor-tabs\">\n <!-- Spec Tab -->\n <kendo-tabstrip-tab [title]=\"'Spec'\" [selected]=\"activeTab === 0\">\n <ng-template kendoTabContent>\n <div class=\"tab-content spec-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-code\"></i> Component Specification (JSON)</h4>\n <div class=\"editor-actions\">\n @if (isEditingSpec) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applySpecChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n <div class=\"editor-wrapper\">\n <mj-code-editor\n [(ngModel)]=\"editableSpec\"\n (ngModelChange)=\"onSpecChange($event)\"\n [language]=\"'json'\"\n [readonly]=\"false\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n \n <!-- Code Tab -->\n <kendo-tabstrip-tab [title]=\"'Code'\" [selected]=\"activeTab === 1\">\n <ng-template kendoTabContent>\n <div class=\"tab-content code-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-file-code\"></i> Component Code (JavaScript/React)</h4>\n <div class=\"editor-actions\">\n @if (isEditingCode) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applyCodeChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n \n <!-- Always use panel bar for consistency and to show all components -->\n <div class=\"editor-wrapper\">\n <kendo-panelbar class=\"code-sections\">\n @for (section of getComponentCodeSections(); track section.title; let i = $index) {\n <kendo-panelbar-item [title]=\"section.title\" [expanded]=\"section.expanded\">\n <ng-template kendoPanelBarContent>\n <mj-code-editor\n [ngModel]=\"section.code\"\n (ngModelChange)=\"onCodeSectionChange($event, i)\"\n [language]=\"'javascript'\"\n [readonly]=\"false\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n </ng-template>\n </kendo-panelbar-item>\n }\n </kendo-panelbar>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n </kendo-tabstrip>\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n\n @if (!isDetailsPaneCollapsed) {\n \n }\n } @else {\n <!-- Empty State when no component selected -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-rocket fa-3x\"></i>\n <h2>Ready to Test Components</h2>\n <p>Select a component from the list to view its details and run it</p>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div>", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n \n .import-dropdown, .export-dropdown {\n position: relative;\n \n .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n z-index: 1000;\n min-width: 180px;\n \n .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: #212529;\n transition: background-color 0.2s;\n \n &:hover {\n background-color: #f8f9fa;\n }\n \n &:not(:last-child) {\n border-bottom: 1px solid #e9ecef;\n }\n \n i {\n width: 16px;\n text-align: center;\n color: #6366f1;\n }\n }\n }\n }\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n .panel-header-top {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n\n .header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n \n .favorites-toggle,\n .deprecated-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n font-size: 14px;\n }\n }\n\n .favorites-toggle.active {\n background: #fff3cd;\n border-color: #ffc107;\n color: #856404;\n\n i {\n color: #ffc107;\n }\n }\n\n .deprecated-toggle.active {\n background: #ffe4e1;\n border-color: #ff6b6b;\n color: #c92a2a;\n\n i {\n color: #ff6b6b;\n }\n }\n\n .count-badge {\n margin-left: 4px;\n background: #f59e0b;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .deprecated-toggle.active .count-badge {\n background: #ff6b6b;\n }\n\n .component-count {\n font-size: 13px;\n color: #6c757d;\n background: #f8f9fa;\n padding: 4px 10px;\n border-radius: 12px;\n font-weight: 500;\n }\n }\n }\n \n .category-filters {\n margin-bottom: 16px;\n \n .filter-pills {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n \n .category-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n overflow: hidden;\n \n &:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n \n &.active {\n border-color: var(--pill-color);\n background: var(--pill-color);\n color: white;\n \n .pill-count {\n background: rgba(255, 255, 255, 0.3);\n color: white;\n }\n }\n \n .pill-name {\n font-weight: 500;\n }\n \n .pill-count {\n background: #f1f3f5;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n min-width: 20px;\n text-align: center;\n }\n }\n \n .more-button,\n .clear-filters-button {\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n \n i {\n font-size: 11px;\n margin-right: 4px;\n }\n }\n \n .clear-filters-button {\n background: #fee2e2;\n border-color: #fca5a5;\n color: #dc2626;\n \n &:hover {\n background: #fca5a5;\n color: white;\n }\n }\n }\n }\n \n .search-box {\n margin-bottom: 12px;\n\n kendo-textbox {\n width: 100%;\n }\n\n // Reduce search input font size\n ::ng-deep .k-input-inner {\n font-size: 13px;\n }\n }\n\n // New filter toggle button\n .filter-toggle-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px 10px;\n border: 1px solid #ced4da;\n background: white;\n border-radius: 4px;\n font-size: 13px;\n color: #495057;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #e9ecef;\n border-color: #adb5bd;\n }\n\n &.active {\n background: #e7f3ff;\n border-color: #1e40af;\n color: #1e40af;\n }\n\n i {\n font-size: 13px;\n }\n\n .filter-count-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n background: #1e40af;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n min-width: 18px;\n text-align: center;\n }\n }\n\n // Collapsible filter panel\n .filter-panel {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n overflow: hidden;\n animation: slideDown 0.2s ease;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .filter-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #e9ecef;\n cursor: pointer;\n font-weight: 600;\n font-size: 12px;\n color: #495057;\n user-select: none;\n\n &:hover {\n background: #dee2e6;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n\n .filter-count-text {\n font-size: 11px;\n font-weight: 500;\n color: #6c757d;\n }\n }\n\n .filter-panel-content {\n padding: 14px;\n }\n\n .filter-section {\n margin-bottom: 16px;\n\n &:last-child {\n margin-bottom: 0;\n }\n\n .filter-section-label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #495057;\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .filter-options {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .filter-checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 13px;\n color: #212529;\n padding: 6px 0;\n\n input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n\n span {\n user-select: none;\n }\n\n .deprecated-count {\n color: #6c757d;\n font-size: 12px;\n margin-left: 4px;\n }\n }\n\n .category-pills-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .category-pill-compact {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: #495057;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n border-color: #adb5bd;\n transform: translateY(-1px);\n }\n\n &.active {\n border-color: var(--pill-color, #6366f1);\n background: var(--pill-color, #6366f1);\n color: white;\n }\n\n .pill-name {\n font-weight: 500;\n }\n\n .pill-count {\n font-size: 11px;\n opacity: 0.8;\n }\n }\n\n .show-more-categories-btn {\n padding: 5px 10px;\n border: 1px dashed #dee2e6;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n }\n }\n\n .filter-panel-footer {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid #dee2e6;\n\n .clear-all-btn {\n width: 100%;\n padding: 8px;\n border: 1px solid #dc3545;\n background: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #dc3545;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #dc3545;\n color: white;\n }\n\n i {\n margin-right: 6px;\n }\n }\n }\n }\n\n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .favorite-btn {\n position: absolute;\n top: 12px;\n right: 48px; // Leave room for chevron\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 50%;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n transform: scale(1.1);\n }\n \n &.is-favorite {\n color: #ffc107;\n border-color: #ffc107;\n background: #fff3cd;\n \n &:hover {\n background: #ffe69c;\n }\n }\n \n i {\n font-size: 14px;\n }\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n\n &.deprecated {\n background: #ffe4e1;\n color: #c92a2a;\n border: 1px solid #ff6b6b;\n }\n\n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n \n &.text {\n background: #f3e8ff;\n color: #6b21a8;\n }\n }\n }\n \n .card-namespace {\n margin-top: 8px;\n \n .namespace-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: white;\n \n i {\n font-size: 11px;\n opacity: 0.9;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n// Removed tree view styles - using modern category filters instead\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}"] }]
|
|
2075
|
+
args: [{ selector: 'mj-component-studio-dashboard', template: "<div class=\"component-studio\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-content\">\n <div>\n <h1><i class=\"fa-solid fa-puzzle-piece\"></i> Component Studio</h1>\n <p class=\"header-subtitle\">Testing components without required custom properties</p>\n </div>\n <div class=\"header-buttons\">\n @if (selectedComponent && isRunning) {\n <button kendoButton (click)=\"toggleDetailsPane()\" [themeColor]=\"'base'\">\n @if (isDetailsPaneCollapsed) {\n <span class=\"fa-solid fa-eye\"></span> Show Details\n } @else {\n <span class=\"fa-solid fa-eye-slash\"></span> Hide Details\n }\n </button>\n }\n <div class=\"import-dropdown\" [class.open]=\"importDropdownOpen\">\n <button kendoButton (click)=\"toggleImportDropdown()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-file-import\"></span> Import\n <span class=\"fa-solid fa-chevron-down\" style=\"margin-left: 5px; font-size: 10px;\"></span>\n </button>\n @if (importDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"importFromArtifact()\">\n <i class=\"fa-solid fa-database\"></i> Import from Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"importFromFile()\">\n <i class=\"fa-solid fa-file\"></i> Import from File\n </button>\n <button class=\"dropdown-item\" (click)=\"importFromText()\">\n <i class=\"fa-solid fa-keyboard\"></i> Import from Text\n </button>\n </div>\n }\n </div>\n @if (selectedComponent && isRunning) {\n <div class=\"export-dropdown\" [class.open]=\"exportDropdownOpen\">\n <button kendoButton (click)=\"toggleExportDropdown()\" [themeColor]=\"'primary'\">\n <span class=\"fa-solid fa-file-export\"></span> Export\n <span class=\"fa-solid fa-chevron-down\" style=\"margin-left: 5px; font-size: 10px;\"></span>\n </button>\n @if (exportDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"exportToArtifact()\">\n <i class=\"fa-solid fa-save\"></i> Export to Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"exportToFile()\">\n <i class=\"fa-solid fa-file\"></i> Export to File\n </button>\n <button class=\"dropdown-item\" (click)=\"exportToClipboard()\">\n <i class=\"fa-solid fa-clipboard\"></i> Export to Clipboard\n </button>\n </div>\n }\n </div>\n }\n <button kendoButton (click)=\"refreshData()\" [disabled]=\"isLoading\">\n <span class=\"fa-solid fa-sync\"></span> Refresh\n </button>\n </div>\n <!-- Hidden file input -->\n <input #fileInput type=\"file\" accept=\".json\" (change)=\"handleFileSelect($event)\" style=\"display: none;\" />\n </div>\n </div>\n\n <!-- Main Content with Splitter -->\n <kendo-splitter orientation=\"horizontal\">\n <!-- Left Panel - Component List -->\n <kendo-splitter-pane [min]=\"'350px'\" [max]=\"'650px'\" [size]=\"'400px'\">\n <div class=\"components-panel\">\n <div class=\"panel-header\">\n <!-- Clean Header with Filter Button -->\n <div class=\"panel-header-top\">\n <div class=\"header-actions\">\n <button\n class=\"filter-toggle-btn\"\n [class.active]=\"isFilterPanelExpanded || GetActiveFilterCount() > 0\"\n (click)=\"ToggleFilterPanel()\"\n [title]=\"isFilterPanelExpanded ? 'Hide filters' : 'Show filters'\">\n <i class=\"fa-solid fa-sliders\"></i>\n @if (GetActiveFilterCount() > 0) {\n <span class=\"filter-count-badge\">{{ GetActiveFilterCount() }}</span>\n }\n </button>\n <span class=\"component-count\">{{ filteredComponents.length }} of {{ allComponents.length }}</span>\n </div>\n </div>\n\n <!-- Search (Always Visible) -->\n <div class=\"search-box\">\n <kendo-textbox\n [value]=\"searchQuery\"\n (valueChange)=\"onSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n\n <!-- Collapsible Filter Panel -->\n @if (isFilterPanelExpanded) {\n <div class=\"filter-panel\">\n <div class=\"filter-panel-header\" (click)=\"ToggleFilterPanel()\">\n <span><i class=\"fa-solid fa-chevron-down\"></i> Filters</span>\n <span class=\"filter-count-text\">{{ filteredComponents.length }} of {{ allComponents.length }}</span>\n </div>\n\n <div class=\"filter-panel-content\">\n <!-- Quick Filters -->\n <div class=\"filter-section\">\n <label class=\"filter-section-label\">Quick Filters</label>\n <div class=\"filter-options\">\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"showOnlyFavorites\"\n (change)=\"toggleShowOnlyFavorites()\">\n <span>Show favorites only</span>\n </label>\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"!showDeprecatedComponents\"\n (change)=\"toggleShowDeprecatedComponents()\">\n <span>Hide deprecated\n @if (getDeprecatedCount() > 0) {\n <span class=\"deprecated-count\">({{ getDeprecatedCount() }} hidden)</span>\n }\n </span>\n </label>\n </div>\n </div>\n\n <!-- Category Filters -->\n @if (availableCategories.length > 0) {\n <div class=\"filter-section\">\n <label class=\"filter-section-label\">Categories</label>\n <div class=\"category-pills-grid\">\n @for (category of getVisibleCategories(); track category.name) {\n <button\n class=\"category-pill-compact\"\n [class.active]=\"isCategorySelected(category.name)\"\n [style.--pill-color]=\"category.color\"\n (click)=\"toggleCategory(category.name)\">\n <span class=\"pill-name\">{{ category.name }}</span>\n <span class=\"pill-count\">{{ category.count }}</span>\n </button>\n }\n </div>\n @if (availableCategories.length > 5) {\n <button\n class=\"show-more-categories-btn\"\n (click)=\"toggleShowAllCategories()\">\n @if (showAllCategories) {\n <i class=\"fa-solid fa-chevron-up\"></i> Show less\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i> Show {{ availableCategories.length - 5 }} more\n }\n </button>\n }\n </div>\n }\n\n <!-- Clear All Button -->\n @if (GetActiveFilterCount() > 0) {\n <div class=\"filter-panel-footer\">\n <button class=\"clear-all-btn\" (click)=\"ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear All Filters\n </button>\n </div>\n }\n </div>\n </div>\n }\n </div>\n \n <div class=\"components-list\">\n @if (isLoading) {\n <div class=\"loading-message\">\n <mj-loading text=\"Loading components...\" size=\"small\"></mj-loading>\n </div>\n } @else if (filteredComponents.length === 0) {\n <div class=\"empty-message\">\n <i class=\"fa-solid fa-info-circle\"></i> No components found without required custom properties.\n <br>\n <small>Components with optional custom props can be tested, but not those with required props.</small>\n </div>\n } @else {\n <!-- Component Cards -->\n @for (component of filteredComponents; track getComponentId(component)) {\n <div class=\"component-card\" \n [class.expanded]=\"expandedComponent && getComponentId(expandedComponent) === getComponentId(component)\"\n [class.running]=\"selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning\"\n [class.file-loaded]=\"isFileLoadedComponent(component)\">\n \n <!-- Card Header - Always visible -->\n <div class=\"card-header\" (click)=\"toggleComponentExpansion(component)\">\n <div class=\"card-icon\" [style.color]=\"getComponentTypeColor(getComponentType(component))\">\n <i class=\"fa-solid\" [ngClass]=\"getComponentTypeIcon(getComponentType(component))\"></i>\n </div>\n @if (!isFileLoadedComponent(component)) {\n <button \n class=\"favorite-btn\"\n [class.is-favorite]=\"isFavorite(component)\"\n (click)=\"toggleFavorite(component, $event)\"\n [title]=\"isFavorite(component) ? 'Remove from favorites' : 'Add to favorites'\">\n @if (isFavorite(component)) {\n <i class=\"fa-solid fa-star\"></i>\n } @else {\n <i class=\"fa-regular fa-star\"></i>\n }\n </button>\n }\n <div class=\"card-info\">\n <div class=\"card-name\">\n {{ getComponentName(component) }}\n @if (isFileLoadedComponent(component)) {\n <span class=\"file-badge\" [title]=\"getComponentStatus(component) === 'Text' ? 'Imported from text input' : 'Loaded from ' + getComponentFilename(component)\">\n @if (getComponentStatus(component) === 'Text') {\n <i class=\"fa-solid fa-keyboard\"></i> Text Import\n } @else {\n <i class=\"fa-solid fa-file\"></i> {{ getComponentFilename(component) }}\n }\n </span>\n }\n </div>\n <div class=\"card-meta\">\n <span class=\"card-type\">{{ getComponentType(component) || 'Component' }}</span>\n <span class=\"card-version\">v{{ getComponentVersion(component) }}</span>\n @if (isFileLoadedComponent(component)) {\n @if (getComponentStatus(component) === 'Text') {\n <span class=\"status-badge text\">Text</span>\n } @else {\n <span class=\"status-badge file\">File</span>\n }\n } @else if (getComponentStatus(component) === 'Deprecated') {\n <span class=\"status-badge deprecated\">Deprecated</span>\n } @else if (getComponentStatus(component) === 'Published') {\n <span class=\"status-badge published\">Published</span>\n } @else {\n <span class=\"status-badge draft\">Draft</span>\n }\n </div>\n <!-- Namespace chip with color coding -->\n <div class=\"card-namespace\">\n <span class=\"namespace-chip\" \n [style.background-color]=\"getNamespaceColor(getComponentNamespace(component))\"\n [title]=\"getComponentNamespace(component) || 'Uncategorized'\">\n <i class=\"fa-solid fa-folder-tree\"></i>\n {{ formatNamespace(getComponentNamespace(component)) }}\n </span>\n </div>\n </div>\n <div class=\"card-chevron\">\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <i class=\"fa-solid fa-chevron-up\"></i>\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i>\n }\n </div>\n </div>\n \n <!-- Card Details - Only visible when expanded -->\n @if (expandedComponent && getComponentId(expandedComponent) === getComponentId(component)) {\n <div class=\"card-details\">\n @if (getComponentDescription(component)) {\n <div class=\"detail-section\">\n <label>Description</label>\n <p>{{ getComponentDescription(component) }}</p>\n </div>\n }\n \n <div class=\"detail-section\">\n <label>Component Info</label>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type:</span>\n <span class=\"info-value\">{{ getComponentType(component) || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version:</span>\n <span class=\"info-value\">{{ getComponentVersion(component) }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status:</span>\n <span class=\"info-value\">{{ getComponentStatus(component) || 'Draft' }}</span>\n </div>\n @if (isFileLoadedComponent(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Loaded:</span>\n <span class=\"info-value\">{{ getComponentLoadedAt(component) | date:'short' }}</span>\n </div>\n } @else if (!isFileLoadedComponent(component) && getComponentUpdatedAt(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated:</span>\n <span class=\"info-value\">{{ getComponentUpdatedAt(component) | date:'short' }}</span>\n </div>\n }\n </div>\n </div>\n \n <div class=\"card-actions\">\n @if (selectedComponent && getComponentId(selectedComponent) === getComponentId(component) && isRunning) {\n <button kendoButton \n [themeColor]=\"'error'\"\n (click)=\"stopComponent(); $event.stopPropagation()\">\n <span class=\"fa-solid fa-stop\"></span> Stop Component\n </button>\n } @else if (isRunning && selectedComponent && getComponentId(selectedComponent) !== getComponentId(component)) {\n <button kendoButton \n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Switch to This Component\n </button>\n } @else {\n <button kendoButton \n [themeColor]=\"'primary'\"\n (click)=\"runComponent(component); $event.stopPropagation()\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n </div>\n </kendo-splitter-pane>\n\n <!-- Right Panel - Component Display with Editor Splitter -->\n <kendo-splitter-pane [min]=\"'400px'\">\n <div class=\"component-display\">\n @if (selectedComponent) {\n <kendo-splitter orientation=\"horizontal\">\n <kendo-splitter-pane [size]=\"isDetailsPaneCollapsed ? '100%' : '50%'\">\n <div class=\"component-runtime\">\n @if (isRunning && componentSpec) {\n @if (currentError) {\n <!-- Error Display -->\n <div class=\"error-display\">\n <div class=\"error-container\">\n <div class=\"error-header\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <h3>Component Error</h3>\n <button class=\"copy-button\" (click)=\"copyErrorToClipboard()\" title=\"Copy error details\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n </div>\n \n <p class=\"error-intro\">\n The component could not be rendered due to the following error:\n </p>\n \n <div class=\"error-details\">\n <strong>Error Type:</strong> {{ currentError.type }}<br>\n <strong>Message:</strong> {{ currentError.message }}\n @if (currentError.technicalDetails) {\n <details class=\"technical-details\">\n <summary>Technical Details (click to expand)</summary>\n <pre>{{ formatTechnicalDetails(currentError.technicalDetails) }}</pre>\n </details>\n }\n </div>\n \n <div class=\"error-help\">\n <strong>What to do:</strong>\n <ol>\n <li>Check that the component code is valid JavaScript/React</li>\n <li>Ensure all required dependencies are available</li>\n <li>Review the technical details for specific error information</li>\n <li>Contact your system administrator if the issue persists</li>\n </ol>\n </div>\n \n <div class=\"error-actions\">\n <button kendoButton (click)=\"retryComponent()\">\n <span class=\"fa-solid fa-rotate\"></span> Retry\n </button>\n <button kendoButton (click)=\"stopComponent()\" [themeColor]=\"'error'\">\n <span class=\"fa-solid fa-stop\"></span> Stop\n </button>\n </div>\n </div>\n </div>\n } @else {\n <!-- React Component -->\n <mj-react-component \n [component]=\"componentSpec\"\n (componentEvent)=\"onComponentEvent($event)\"\n (openEntityRecord)=\"onOpenEntityRecord($event)\">\n </mj-react-component>\n }\n } @else {\n <!-- Component Not Running State -->\n <div class=\"run-empty-state\">\n <i class=\"fa-solid fa-play-circle fa-3x\"></i>\n <h3>Component: {{ getComponentName(selectedComponent) }}</h3>\n <p>{{ getComponentDescription(selectedComponent) || 'No description available' }}</p>\n <button kendoButton [themeColor]=\"'primary'\" [size]=\"'large'\" (click)=\"runComponent(selectedComponent)\">\n <span class=\"fa-solid fa-play\"></span> Run Component\n </button>\n </div>\n }\n </div>\n\n </kendo-splitter-pane>\n <kendo-splitter-pane [size]=\"isDetailsPaneCollapsed ? '0px' : '50%'\">\n <div>\n <kendo-tabstrip (tabSelect)=\"onTabSelect($event)\" class=\"editor-tabs\">\n <!-- Spec Tab -->\n <kendo-tabstrip-tab [title]=\"'Spec'\" [selected]=\"activeTab === 0\">\n <ng-template kendoTabContent>\n <div class=\"tab-content spec-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-code\"></i> Component Specification (JSON)</h4>\n <div class=\"editor-actions\">\n @if (isEditingSpec) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applySpecChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n <div class=\"editor-wrapper\">\n <mj-code-editor\n [(ngModel)]=\"editableSpec\"\n (ngModelChange)=\"onSpecChange($event)\"\n [language]=\"'json'\"\n [readonly]=\"false\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n \n <!-- Code Tab -->\n <kendo-tabstrip-tab [title]=\"'Code'\" [selected]=\"activeTab === 1\">\n <ng-template kendoTabContent>\n <div class=\"tab-content code-tab\">\n <div class=\"editor-header\">\n <h4><i class=\"fa-solid fa-file-code\"></i> Component Code (JavaScript/React)</h4>\n <div class=\"editor-actions\">\n @if (isEditingCode) {\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"applyCodeChanges()\">\n <span class=\"fa-solid fa-check\"></span> Apply Changes\n </button>\n <button kendoButton (click)=\"initializeEditors()\">\n <span class=\"fa-solid fa-times\"></span> Cancel\n </button>\n }\n @if (isRunning) {\n <button kendoButton (click)=\"refreshComponent()\" [themeColor]=\"'info'\">\n <span class=\"fa-solid fa-sync\"></span> Refresh Component\n </button>\n }\n </div>\n </div>\n \n <!-- Always use panel bar for consistency and to show all components -->\n <div class=\"editor-wrapper\">\n <kendo-panelbar class=\"code-sections\">\n @for (section of getComponentCodeSections(); track section.title; let i = $index) {\n <kendo-panelbar-item [title]=\"section.title\" [expanded]=\"section.expanded\">\n <ng-template kendoPanelBarContent>\n <mj-code-editor\n [ngModel]=\"section.code\"\n (ngModelChange)=\"onCodeSectionChange($event, i)\"\n [language]=\"'javascript'\"\n [readonly]=\"false\"\n style=\"height: 400px; width: 100%;\">\n </mj-code-editor>\n </ng-template>\n </kendo-panelbar-item>\n }\n </kendo-panelbar>\n </div>\n </div>\n </ng-template>\n </kendo-tabstrip-tab>\n </kendo-tabstrip>\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n\n @if (!isDetailsPaneCollapsed) {\n \n }\n } @else {\n <!-- Empty State when no component selected -->\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-rocket fa-3x\"></i>\n <h2>Ready to Test Components</h2>\n <p>Select a component from the list to view its details and run it</p>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n</div>", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #f8f9fa;\n overflow: hidden;\n position: relative;\n\n .dashboard-header {\n background: white;\n border-bottom: 1px solid #dee2e6;\n padding: 16px 24px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n \n .header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n \n .header-buttons {\n display: flex;\n gap: 8px;\n \n .import-dropdown, .export-dropdown {\n position: relative;\n \n .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n z-index: 1000;\n min-width: 180px;\n \n .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: #212529;\n transition: background-color 0.2s;\n \n &:hover {\n background-color: #f8f9fa;\n }\n \n &:not(:last-child) {\n border-bottom: 1px solid #e9ecef;\n }\n \n i {\n width: 16px;\n text-align: center;\n color: #6366f1;\n }\n }\n }\n }\n }\n \n h1 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: #212529;\n display: flex;\n align-items: center;\n gap: 12px;\n \n i {\n color: #6366f1;\n }\n }\n \n .header-subtitle {\n margin: 4px 0 0 0;\n font-size: 13px;\n color: #6c757d;\n font-weight: normal;\n }\n }\n }\n\n kendo-splitter {\n flex: 1;\n background: white;\n display: flex;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n \n ::ng-deep .k-pane {\n overflow: hidden;\n height: 100%;\n }\n }\n\n .components-panel {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: #f8f9fa;\n \n .panel-header {\n padding: 20px;\n background: white;\n border-bottom: 1px solid #dee2e6;\n \n .panel-header-top {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n\n .header-actions {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n \n .favorites-toggle,\n .deprecated-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 500;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n font-size: 14px;\n }\n }\n\n .favorites-toggle.active {\n background: #fff3cd;\n border-color: #ffc107;\n color: #856404;\n\n i {\n color: #ffc107;\n }\n }\n\n .deprecated-toggle.active {\n background: #ffe4e1;\n border-color: #ff6b6b;\n color: #c92a2a;\n\n i {\n color: #ff6b6b;\n }\n }\n\n .count-badge {\n margin-left: 4px;\n background: #f59e0b;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .deprecated-toggle.active .count-badge {\n background: #ff6b6b;\n }\n\n .component-count {\n font-size: 13px;\n color: #6c757d;\n background: #f8f9fa;\n padding: 4px 10px;\n border-radius: 12px;\n font-weight: 500;\n }\n }\n }\n \n .category-filters {\n margin-bottom: 16px;\n \n .filter-pills {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n \n .category-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n overflow: hidden;\n \n &:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n }\n \n &.active {\n border-color: var(--pill-color);\n background: var(--pill-color);\n color: white;\n \n .pill-count {\n background: rgba(255, 255, 255, 0.3);\n color: white;\n }\n }\n \n .pill-name {\n font-weight: 500;\n }\n \n .pill-count {\n background: #f1f3f5;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n min-width: 20px;\n text-align: center;\n }\n }\n \n .more-button,\n .clear-filters-button {\n padding: 6px 12px;\n border: 1px solid #dee2e6;\n background: white;\n border-radius: 20px;\n font-size: 13px;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n \n i {\n font-size: 11px;\n margin-right: 4px;\n }\n }\n \n .clear-filters-button {\n background: #fee2e2;\n border-color: #fca5a5;\n color: #dc2626;\n \n &:hover {\n background: #fca5a5;\n color: white;\n }\n }\n }\n }\n \n .search-box {\n margin-bottom: 12px;\n\n kendo-textbox {\n width: 100%;\n }\n\n // Reduce search input font size\n ::ng-deep .k-input-inner {\n font-size: 13px;\n }\n }\n\n // New filter toggle button\n .filter-toggle-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px 10px;\n border: 1px solid #ced4da;\n background: white;\n border-radius: 4px;\n font-size: 13px;\n color: #495057;\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: #e9ecef;\n border-color: #adb5bd;\n }\n\n &.active {\n background: #e7f3ff;\n border-color: #1e40af;\n color: #1e40af;\n }\n\n i {\n font-size: 13px;\n }\n\n .filter-count-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n background: #1e40af;\n color: white;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n line-height: 1;\n min-width: 18px;\n text-align: center;\n }\n }\n\n // Collapsible filter panel\n .filter-panel {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n overflow: hidden;\n animation: slideDown 0.2s ease;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .filter-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #e9ecef;\n cursor: pointer;\n font-weight: 600;\n font-size: 12px;\n color: #495057;\n user-select: none;\n\n &:hover {\n background: #dee2e6;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n\n .filter-count-text {\n font-size: 11px;\n font-weight: 500;\n color: #6c757d;\n }\n }\n\n .filter-panel-content {\n padding: 14px;\n }\n\n .filter-section {\n margin-bottom: 16px;\n\n &:last-child {\n margin-bottom: 0;\n }\n\n .filter-section-label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: #495057;\n margin-bottom: 8px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .filter-options {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .filter-checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 13px;\n color: #212529;\n padding: 6px 0;\n\n input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n cursor: pointer;\n }\n\n span {\n user-select: none;\n }\n\n .deprecated-count {\n color: #6c757d;\n font-size: 12px;\n margin-left: 4px;\n }\n }\n\n .category-pills-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .category-pill-compact {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 2px solid #e9ecef;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: #495057;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n border-color: #adb5bd;\n transform: translateY(-1px);\n }\n\n &.active {\n border-color: var(--pill-color, #6366f1);\n background: var(--pill-color, #6366f1);\n color: white;\n }\n\n .pill-name {\n font-weight: 500;\n }\n\n .pill-count {\n font-size: 11px;\n opacity: 0.8;\n }\n }\n\n .show-more-categories-btn {\n padding: 5px 10px;\n border: 1px dashed #dee2e6;\n background: white;\n border-radius: 16px;\n font-size: 12px;\n color: #6c757d;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #f8f9fa;\n border-color: #adb5bd;\n }\n\n i {\n margin-right: 4px;\n font-size: 10px;\n }\n }\n }\n\n .filter-panel-footer {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px solid #dee2e6;\n\n .clear-all-btn {\n width: 100%;\n padding: 8px;\n border: 1px solid #dc3545;\n background: white;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #dc3545;\n cursor: pointer;\n transition: all 0.15s ease;\n\n &:hover {\n background: #dc3545;\n color: white;\n }\n\n i {\n margin-right: 6px;\n }\n }\n }\n }\n\n .components-list {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px;\n \n .loading-message,\n .empty-message {\n padding: 48px 24px;\n text-align: center;\n color: #6c757d;\n font-size: 14px;\n \n i {\n margin-right: 8px;\n }\n }\n \n .component-card {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 8px;\n margin-bottom: 12px;\n transition: all 0.2s ease;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n }\n \n &.expanded {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n border-color: #6366f1;\n }\n \n &.running {\n border-color: #10b981;\n box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);\n background: linear-gradient(to right, rgba(16, 185, 129, 0.03) 0%, white 100%);\n \n .card-header {\n &::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 4px;\n background: #10b981;\n }\n }\n }\n \n &.file-loaded {\n background: linear-gradient(135deg, #f0f8ff 0%, white 100%);\n border-style: dashed;\n border-color: #3b82f6;\n \n &:hover {\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.15);\n }\n \n &.expanded {\n border-style: solid;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);\n }\n }\n \n .card-header {\n display: flex;\n align-items: center;\n padding: 16px;\n cursor: pointer;\n user-select: none;\n position: relative;\n \n &:hover {\n background: #f8f9fa;\n }\n \n .card-icon {\n font-size: 24px;\n margin-right: 16px;\n width: 32px;\n text-align: center;\n flex-shrink: 0;\n }\n \n .favorite-btn {\n position: absolute;\n top: 12px;\n right: 48px; // Leave room for chevron\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 50%;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: #6c757d;\n \n &:hover {\n background: #f8f9fa;\n transform: scale(1.1);\n }\n \n &.is-favorite {\n color: #ffc107;\n border-color: #ffc107;\n background: #fff3cd;\n \n &:hover {\n background: #ffe69c;\n }\n }\n \n i {\n font-size: 14px;\n }\n }\n \n .card-info {\n flex: 1;\n min-width: 0;\n \n .card-name {\n font-size: 15px;\n font-weight: 600;\n color: #212529;\n margin-bottom: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n gap: 8px;\n \n .file-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n background: #e0f2fe;\n color: #0369a1;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n flex-shrink: 0;\n \n i {\n font-size: 10px;\n }\n }\n }\n \n .card-meta {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #6c757d;\n \n .card-type {\n font-weight: 500;\n }\n \n .card-version {\n color: #868e96;\n }\n \n .status-badge {\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n \n &.published {\n background: #d1fae5;\n color: #065f46;\n }\n \n &.draft {\n background: #fef3c7;\n color: #92400e;\n }\n\n &.deprecated {\n background: #ffe4e1;\n color: #c92a2a;\n border: 1px solid #ff6b6b;\n }\n\n &.file {\n background: #e0f2fe;\n color: #0369a1;\n }\n \n &.text {\n background: #f3e8ff;\n color: #6b21a8;\n }\n }\n }\n \n .card-namespace {\n margin-top: 8px;\n \n .namespace-chip {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: white;\n \n i {\n font-size: 11px;\n opacity: 0.9;\n }\n }\n }\n }\n \n .card-chevron {\n color: #6c757d;\n font-size: 12px;\n margin-left: 12px;\n transition: transform 0.2s ease;\n }\n }\n \n .card-details {\n padding: 0 16px 16px 16px;\n border-top: 1px solid #e9ecef;\n animation: slideDown 0.2s ease;\n \n .detail-section {\n margin-top: 16px;\n \n label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 8px;\n }\n \n p {\n margin: 0;\n font-size: 13px;\n color: #495057;\n line-height: 1.5;\n }\n \n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n \n .info-item {\n display: flex;\n align-items: baseline;\n gap: 6px;\n font-size: 13px;\n \n .info-label {\n font-weight: 500;\n color: #6c757d;\n min-width: 50px;\n }\n \n .info-value {\n color: #212529;\n }\n }\n }\n }\n \n .card-actions {\n margin-top: 16px;\n display: flex;\n gap: 8px;\n \n button {\n flex: 1;\n }\n }\n }\n }\n }\n }\n\n .component-display {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow: hidden;\n \n .empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n color: #868e96;\n padding: 48px;\n text-align: center;\n \n i {\n color: #dee2e6;\n margin-bottom: 24px;\n }\n \n h2 {\n margin: 0 0 12px 0;\n font-size: 24px;\n font-weight: 600;\n color: #495057;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n max-width: 400px;\n }\n }\n \n .error-display {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: #f8f9fa;\n \n .error-container {\n width: 100%;\n max-width: 600px;\n background: white;\n border: 2px solid #dc3545;\n border-radius: 8px;\n padding: 24px;\n box-shadow: 0 4px 12px rgba(220, 53, 69, 0.15);\n \n .error-header {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 20px;\n color: #dc3545;\n position: relative;\n \n i {\n font-size: 24px;\n }\n \n h3 {\n margin: 0;\n font-size: 20px;\n flex: 1;\n }\n \n .copy-button {\n background: white;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 6px 10px;\n cursor: pointer;\n color: #6c757d;\n transition: all 0.2s;\n \n &:hover {\n background: #e9ecef;\n color: #495057;\n }\n \n i {\n font-size: 14px;\n }\n }\n }\n \n .error-intro {\n color: #495057;\n margin-bottom: 20px;\n font-size: 14px;\n }\n \n .error-details {\n background: #f8f9fa;\n border: 1px solid #dee2e6;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-family: 'SF Mono', Monaco, 'Courier New', monospace;\n font-size: 13px;\n \n .technical-details {\n margin-top: 12px;\n \n summary {\n cursor: pointer;\n color: #0066cc;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n \n &:hover {\n text-decoration: underline;\n }\n }\n \n pre {\n margin-top: 8px;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 11px;\n color: #495057;\n max-height: 200px;\n overflow-y: auto;\n }\n }\n }\n \n .error-help {\n background: #e7f3ff;\n border: 1px solid #b3d9ff;\n border-radius: 4px;\n padding: 16px;\n margin-bottom: 20px;\n font-size: 13px;\n \n strong {\n display: block;\n margin-bottom: 8px;\n font-size: 14px;\n color: #0066cc;\n }\n \n ol {\n margin: 0;\n padding-left: 20px;\n \n li {\n margin-bottom: 4px;\n color: #495057;\n }\n }\n }\n \n .error-actions {\n display: flex;\n gap: 12px;\n \n button {\n min-width: 100px;\n }\n }\n }\n }\n \n mj-react-component {\n flex: 1;\n width: 100%;\n height: 100%;\n display: block;\n overflow-y: auto;\n overflow-x: hidden;\n }\n \n // Component and editor splitter\n .component-editor-splitter {\n height: 100%;\n overflow: hidden;\n \n ::ng-deep .k-splitter-bar {\n background: #6366f1; // Same blue as Import button\n width: 6px; // Make it slightly wider for visibility\n \n &:hover {\n background: #4f52d9; // Darker blue on hover\n }\n \n .k-resize-handle {\n background-color: rgba(255, 255, 255, 0.3);\n }\n }\n \n ::ng-deep .k-pane {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n }\n \n // Component runtime area\n .component-runtime {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: white;\n position: relative;\n overflow-y: auto;\n overflow-x: hidden;\n \n .run-empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px;\n text-align: center;\n \n i {\n color: #10b981;\n margin-bottom: 24px;\n }\n \n h3 {\n margin: 0 0 12px 0;\n font-size: 20px;\n font-weight: 600;\n color: #212529;\n }\n \n p {\n margin: 0 0 24px 0;\n font-size: 14px;\n color: #6c757d;\n max-width: 400px;\n }\n }\n }\n \n // Editor tabs on the right\n .editor-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n ::ng-deep .k-tabstrip-items-wrapper {\n background: #f8f9fa;\n border-bottom: 2px solid #dee2e6;\n flex-shrink: 0;\n }\n \n ::ng-deep .k-tabstrip-content {\n flex: 1;\n padding: 0;\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n }\n \n ::ng-deep .k-item.k-tabstrip-item {\n font-weight: 500;\n \n &.k-active {\n background: white;\n border-bottom-color: white;\n }\n }\n }\n \n .tab-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n \n &.spec-tab, &.code-tab {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n \n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #dee2e6;\n flex-shrink: 0;\n min-width: 0; // Fix width issue\n \n h4 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 1; // Allow title to shrink\n min-width: 0; // Prevent overflow\n \n i {\n color: #6366f1;\n flex-shrink: 0; // Keep icon from shrinking\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0; // Prevent buttons from shrinking\n \n button {\n min-width: auto;\n padding: 4px 12px;\n font-size: 13px;\n white-space: nowrap; // Prevent button text wrapping\n }\n }\n }\n \n .editor-wrapper {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n position: relative;\n }\n \n ::ng-deep .monaco-editor {\n border: 1px solid #dee2e6;\n }\n }\n \n .code-sections {\n height: 100%;\n \n ::ng-deep .k-panelbar-item-header {\n background: #f8f9fa;\n font-weight: 500;\n font-size: 14px;\n }\n \n ::ng-deep .k-panelbar-content {\n padding: 0;\n }\n }\n }\n }\n}\n\n// Removed tree view styles - using modern category filters instead\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}"] }]
|
|
2076
2076
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.DialogService }, { type: i0.ViewContainerRef }, { type: i2.MJNotificationService }], { fileInput: [{
|
|
2077
2077
|
type: ViewChild,
|
|
2078
2078
|
args: ['fileInput', { static: false }]
|