@memberjunction/ng-dashboards 5.11.0 → 5.12.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 +34 -2
- package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +586 -223
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +2 -2
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts +8 -0
- package/dist/AI/components/agents/agent-filter-panel.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js +85 -52
- package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.d.ts +1 -0
- package/dist/AI/components/charts/performance-heatmap.component.d.ts.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.js +27 -5
- package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -1
- package/dist/AI/components/charts/time-series-chart.component.d.ts +5 -0
- package/dist/AI/components/charts/time-series-chart.component.d.ts.map +1 -1
- package/dist/AI/components/charts/time-series-chart.component.js +23 -8
- package/dist/AI/components/charts/time-series-chart.component.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +2 -2
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +2 -2
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
- package/dist/AI/components/prompts/prompt-filter-panel.component.js +2 -2
- package/dist/AI/components/prompts/prompt-management.component.js +3 -3
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +2 -2
- package/dist/AI/components/requests/agent-requests-resource.component.d.ts +83 -0
- package/dist/AI/components/requests/agent-requests-resource.component.d.ts.map +1 -0
- package/dist/AI/components/requests/agent-requests-resource.component.js +547 -0
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -0
- package/dist/AI/components/system/system-config-filter-panel.component.js +2 -2
- package/dist/AI/components/system/system-configuration.component.js +2 -2
- package/dist/AI/components/widgets/kpi-card.component.js +7 -7
- package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
- package/dist/AI/components/widgets/live-execution-widget.component.d.ts.map +1 -1
- package/dist/AI/components/widgets/live-execution-widget.component.js +6 -6
- package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -1
- package/dist/AI/index.d.ts +1 -0
- package/dist/AI/index.d.ts.map +1 -1
- package/dist/AI/index.js +2 -0
- package/dist/AI/index.js.map +1 -1
- package/dist/APIKeys/api-applications-panel.component.js +3 -3
- package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-create-dialog.component.js +3 -3
- package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js +1 -1
- package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
- package/dist/APIKeys/api-key-list.component.js +3 -3
- package/dist/APIKeys/api-key-list.component.js.map +1 -1
- package/dist/APIKeys/api-keys-resource.component.js +1 -1
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/APIKeys/api-scopes-panel.component.js +2 -2
- package/dist/APIKeys/api-usage-panel.component.js +2 -2
- package/dist/Actions/components/actions-overview.component.js +2 -2
- package/dist/Actions/components/execution-monitoring.component.js +2 -2
- package/dist/Actions/components/explorer/action-breadcrumb.component.js +2 -2
- package/dist/Actions/components/explorer/action-card.component.js +2 -2
- package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
- package/dist/Actions/components/explorer/action-list-item.component.js +2 -2
- package/dist/Actions/components/explorer/action-toolbar.component.js +2 -2
- package/dist/Actions/components/explorer/action-tree-panel.component.js +2 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js +2 -2
- package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
- package/dist/Actions/components/explorer/new-category-panel.component.js +2 -2
- package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
- package/dist/Communication/communication-dashboard.component.js +2 -2
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +3 -3
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +5 -5
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +3 -3
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +3 -3
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +2 -2
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +2 -2
- package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +2 -2
- package/dist/ComponentStudio/components/artifact-load-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/browser/component-browser.component.js +2 -2
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +2 -2
- package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +2 -2
- package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js +2 -2
- package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/editors/spec-editor.component.js +2 -2
- package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
- package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/text-import-dialog.component.js +2 -2
- package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/components/workspace/component-preview.component.js +2 -2
- package/dist/ComponentStudio/components/workspace/editor-tabs.component.js +2 -2
- package/dist/ComponentStudio/components/workspace/editor-tabs.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +9 -9
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +11 -3
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +2 -2
- package/dist/Credentials/components/credentials-overview-resource.component.d.ts.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +12 -11
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +9 -9
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/Credentials/credentials-dashboard.component.js +2 -2
- package/dist/DashboardBrowser/dashboard-browser-resource.component.js +2 -2
- package/dist/DashboardBrowser/dashboard-share-dialog.component.js +2 -2
- package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +2 -2
- package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +2 -2
- package/dist/DataExplorer/components/view-selector/view-selector.component.js +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.js +4 -4
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/Integration/components/activity/activity.component.d.ts +1 -1
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +5 -5
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.d.ts +31 -2
- package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +753 -412
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +3 -3
- package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.d.ts +0 -1
- package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +3 -6
- package/dist/Integration/components/overview/overview.component.js.map +1 -1
- package/dist/Integration/components/pipelines/pipelines.component.js +3 -3
- package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.d.ts +20 -0
- package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
- package/dist/Integration/components/schedules/schedules.component.js +97 -5
- package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
- package/dist/Integration/components/visual-editor/visual-editor.component.js +2 -2
- package/dist/Integration/components/widgets/integration-card.component.d.ts.map +1 -1
- package/dist/Integration/components/widgets/integration-card.component.js +5 -1
- package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
- package/dist/Integration/components/widgets/run-history-panel.component.js +2 -2
- package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
- package/dist/Integration/integration.module.d.ts +2 -1
- package/dist/Integration/integration.module.d.ts.map +1 -1
- package/dist/Integration/integration.module.js +7 -3
- package/dist/Integration/integration.module.js.map +1 -1
- package/dist/Integration/services/integration-data.service.d.ts +27 -2
- package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
- package/dist/Integration/services/integration-data.service.js +107 -4
- package/dist/Integration/services/integration-data.service.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +2 -2
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +2 -2
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +2 -2
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-operations-resource.component.js +2 -2
- package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js +3 -3
- package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
- package/dist/MCP/components/mcp-connection-dialog.component.js +2 -2
- package/dist/MCP/components/mcp-log-detail-panel.component.js +2 -2
- package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
- package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
- package/dist/MCP/components/mcp-test-tool-dialog.component.js +2 -2
- package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +2 -2
- package/dist/MCP/mcp-filter-panel.component.js +2 -2
- package/dist/QueryBrowser/query-browser-resource.component.js +7 -7
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/Scheduling/components/index.d.ts +0 -1
- package/dist/Scheduling/components/index.d.ts.map +1 -1
- package/dist/Scheduling/components/index.js +0 -1
- package/dist/Scheduling/components/index.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +2 -2
- package/dist/Scheduling/components/scheduling-jobs.component.d.ts +6 -9
- package/dist/Scheduling/components/scheduling-jobs.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +118 -110
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +3 -3
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +2 -2
- package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -4
- package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
- package/dist/Testing/components/testing-analytics.component.js +2 -2
- package/dist/Testing/components/testing-analytics.component.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab.component.js +4 -4
- package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +2 -2
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-review.component.js +5 -5
- package/dist/Testing/components/testing-review.component.js.map +1 -1
- package/dist/Testing/components/testing-runs.component.js +2 -2
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/components/widgets/oracle-breakdown-table.component.js +2 -2
- package/dist/Testing/components/widgets/oracle-breakdown-table.component.js.map +1 -1
- package/dist/Testing/components/widgets/suite-tree.component.js +4 -4
- package/dist/Testing/components/widgets/suite-tree.component.js.map +1 -1
- package/dist/Testing/components/widgets/test-run-detail-panel.component.js +2 -2
- package/dist/Testing/components/widgets/test-run-detail-panel.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +2 -2
- package/dist/VersionHistory/components/diff-resource.component.js +2 -2
- package/dist/VersionHistory/components/graph-resource.component.js +2 -2
- package/dist/VersionHistory/components/labels-resource.component.js +3 -3
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +3 -3
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/__tests__/integration-data-service.test.js +1 -0
- package/dist/__tests__/integration-data-service.test.js.map +1 -1
- package/dist/module.d.ts +52 -49
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +25 -6
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +1 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +42 -40
- package/dist/Scheduling/components/job-slideout.component.d.ts +0 -45
- package/dist/Scheduling/components/job-slideout.component.d.ts.map +0 -1
- package/dist/Scheduling/components/job-slideout.component.js +0 -459
- package/dist/Scheduling/components/job-slideout.component.js.map +0 -1
|
@@ -620,11 +620,11 @@ export class ComponentBrowserComponent {
|
|
|
620
620
|
i0.ɵɵconditional(ctx.State.IsFilterPanelExpanded ? 21 : -1);
|
|
621
621
|
i0.ɵɵadvance(2);
|
|
622
622
|
i0.ɵɵconditional(ctx.State.IsLoading ? 23 : ctx.State.FilteredComponents.length === 0 ? 24 : 25);
|
|
623
|
-
} }, dependencies: [i2.NgClass, i3.TextBoxComponent, i3.TextBoxPrefixTemplateDirective, i4.ButtonComponent, i5.LoadingComponent, i2.DatePipe], styles: ["\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.component-browser[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mat-sys-surface-container-low);\n overflow: hidden;\n}\n\n\n\n\n\n\n\n\n.browser-header[_ngcontent-%COMP%] {\n padding: 12px 14px 8px;\n border-bottom: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface);\n flex-shrink: 0;\n}\n\n.browser-header[_ngcontent-%COMP%] .header-top-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.browser-header[_ngcontent-%COMP%] .header-controls-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.browser-header[_ngcontent-%COMP%] .component-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n margin-left: auto;\n}\n\n\n\n\n\n\n\n\n.import-dropdown[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-chevron[_ngcontent-%COMP%] {\n margin-left: 4px;\n font-size: 10px;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n min-width: 180px;\n margin-top: 4px;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-extra-small);\n box-shadow: var(--mat-sys-elevation-2);\n overflow: hidden;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: none;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n cursor: pointer;\n text-align: left;\n transition: background 0.15s;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-variant);\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 16px;\n text-align: center;\n color: var(--mat-sys-on-surface-variant);\n}\n\n\n\n\n\n\n\n\n.filter-toggle-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-extra-small);\n background: var(--mat-sys-surface);\n color: var(--mat-sys-on-surface-variant);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n}\n\n.filter-toggle-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mat-sys-on-surface-variant);\n color: var(--mat-sys-on-surface);\n}\n\n.filter-toggle-btn.active[_ngcontent-%COMP%] {\n border-color: var(--mat-sys-primary);\n color: var(--mat-sys-primary);\n background: #eff6ff;\n}\n\n.filter-toggle-btn[_ngcontent-%COMP%] .filter-count-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mat-sys-primary);\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n}\n\n\n\n\n\n\n\n\n.search-box[_ngcontent-%COMP%] {\n padding: 8px 14px;\n flex-shrink: 0;\n}\n\n.search-box[_ngcontent-%COMP%] .search-icon[_ngcontent-%COMP%] {\n color: var(--mat-sys-on-surface-variant);\n margin-left: 6px;\n}\n\n\n\n\n\n\n\n\n.filter-panel[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface);\n flex-shrink: 0;\n}\n\n.filter-panel[_ngcontent-%COMP%] .filter-panel-content[_ngcontent-%COMP%] {\n padding: 8px 14px 12px;\n}\n\n.filter-section[_ngcontent-%COMP%] {\n margin-bottom: 10px;\n}\n\n.filter-section[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.filter-section[_ngcontent-%COMP%] .filter-section-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n}\n\n.filter-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n transition: background 0.15s;\n}\n\n.filter-checkbox[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-variant);\n}\n\n.filter-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 14px;\n height: 14px;\n accent-color: var(--mat-sys-primary);\n cursor: pointer;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .filter-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .favorites-icon[_ngcontent-%COMP%] {\n color: #eab308;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .deprecated-icon[_ngcontent-%COMP%] {\n color: #94a3b8;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .deprecated-count[_ngcontent-%COMP%] {\n color: #94a3b8;\n font-size: 12px;\n}\n\n\n\n\n\n\n\n\n.category-pills[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.category-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n border: 1px solid var(--mat-sys-outline);\n border-radius: 14px;\n background: var(--mat-sys-surface);\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.category-pill[_ngcontent-%COMP%] .pill-name[_ngcontent-%COMP%] {\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.category-pill[_ngcontent-%COMP%] .pill-count[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-variant);\n padding: 0 5px;\n border-radius: 8px;\n line-height: 16px;\n}\n\n.category-pill[_ngcontent-%COMP%]:hover {\n border-color: var(--pill-color, var(--mat-sys-primary));\n background: var(--mat-sys-surface-container-lowest);\n}\n\n.category-pill.active[_ngcontent-%COMP%] {\n border-color: var(--pill-color, var(--mat-sys-primary));\n background: var(--pill-color, var(--mat-sys-primary));\n color: #fff;\n}\n\n.category-pill.active[_ngcontent-%COMP%] .pill-count[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.25);\n color: #fff;\n}\n\n.show-more-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-top: 6px;\n padding: 2px 0;\n border: none;\n background: none;\n font-size: 12px;\n color: var(--mat-sys-primary);\n cursor: pointer;\n}\n\n.show-more-btn[_ngcontent-%COMP%]:hover {\n color: var(--mat-sys-primary);\n text-decoration: underline;\n}\n\n.filter-panel-footer[_ngcontent-%COMP%] {\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.clear-all-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n border-radius: 4px;\n background: none;\n font-size: 12px;\n color: #ef4444;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.clear-all-btn[_ngcontent-%COMP%]:hover {\n background: #fef2f2;\n}\n\n\n\n\n\n\n\n\n.component-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px 10px;\n}\n\n\n\n\n\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--mat-sys-outline);\n margin-bottom: 12px;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n margin: 0 0 4px;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-subtitle[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n margin: 0;\n}\n\n\n\n\n\n\n\n\n.component-card[_ngcontent-%COMP%] {\n margin-bottom: 6px;\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-small);\n background: var(--mat-sys-surface);\n transition: all 0.15s;\n overflow: hidden;\n}\n\n.component-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mat-sys-elevation-1);\n border-color: var(--mat-sys-outline);\n}\n\n\n\n.component-card.running[_ngcontent-%COMP%] {\n border-left: 3px solid #10b981;\n}\n\n\n\n.component-card.file-loaded[_ngcontent-%COMP%] {\n border-style: dashed;\n border-color: #94a3b8;\n}\n\n.component-card.file-loaded[_ngcontent-%COMP%]:hover {\n border-color: #64748b;\n}\n\n\n\n.component-card.expanded[_ngcontent-%COMP%] {\n border-color: var(--mat-sys-primary);\n box-shadow: 0 2px 12px rgba(59, 130, 246, 0.1);\n}\n\n.component-card.expanded.running[_ngcontent-%COMP%] {\n border-color: var(--mat-sys-primary);\n border-left: 3px solid #10b981;\n}\n\n.component-card.expanded.file-loaded[_ngcontent-%COMP%] {\n border-style: solid;\n border-color: var(--mat-sys-primary);\n}\n\n\n\n\n\n\n\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n cursor: pointer;\n user-select: none;\n}\n\n.card-header[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container-lowest);\n}\n\n.card-type-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n background: var(--mat-sys-surface-variant);\n border-radius: var(--mat-sys-corner-extra-small);\n margin-top: 2px;\n}\n\n.card-body[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.card-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n margin-bottom: 4px;\n}\n\n.card-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.file-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px;\n border-radius: 4px;\n background: #f0f9ff;\n color: #0284c7;\n font-size: 10px;\n font-weight: 500;\n white-space: nowrap;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-meta-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.version-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-variant);\n padding: 1px 6px;\n border-radius: 4px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 1px 7px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.status-badge.published[_ngcontent-%COMP%] {\n background: #d1fae5;\n color: #065f46;\n}\n\n.status-badge.draft[_ngcontent-%COMP%] {\n background: #e0e7ff;\n color: #3730a3;\n}\n\n.status-badge.deprecated[_ngcontent-%COMP%] {\n background: #fee2e2;\n color: #991b1b;\n}\n\n.status-badge.file[_ngcontent-%COMP%] {\n background: #fef3c7;\n color: #92400e;\n}\n\n.status-badge.text[_ngcontent-%COMP%] {\n background: #ede9fe;\n color: #5b21b6;\n}\n\n.status-badge.artifact[_ngcontent-%COMP%] {\n background: #cffafe;\n color: #155e75;\n}\n\n.namespace-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n color: #fff;\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.namespace-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n opacity: 0.8;\n}\n\n\n\n\n\n\n\n\n.card-end[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.favorite-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mat-sys-outline);\n font-size: 14px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.favorite-btn[_ngcontent-%COMP%]:hover {\n color: #eab308;\n background: #fefce8;\n}\n\n.favorite-btn.is-favorite[_ngcontent-%COMP%] {\n color: #eab308;\n}\n\n.remove-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mat-sys-outline);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.remove-btn[_ngcontent-%COMP%]:hover {\n color: #ef4444;\n background: #fef2f2;\n}\n\n.card-chevron[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--mat-sys-on-surface-variant);\n font-size: 11px;\n}\n\n\n\n\n\n\n\n\n.card-details[_ngcontent-%COMP%] {\n padding: 0 12px 12px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.detail-description[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.detail-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n line-height: 1.5;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px 16px;\n padding: 8px 0;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] .info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] .info-label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] .info-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n}\n\n.detail-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}"] });
|
|
623
|
+
} }, dependencies: [i2.NgClass, i3.TextBoxComponent, i3.TextBoxPrefixTemplateDirective, i4.ButtonComponent, i5.LoadingComponent, i2.DatePipe], styles: ["\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.component-browser[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n\n\n\n\n\n\n\n.browser-header[_ngcontent-%COMP%] {\n padding: 12px 14px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n}\n\n.browser-header[_ngcontent-%COMP%] .header-top-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.browser-header[_ngcontent-%COMP%] .header-controls-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.browser-header[_ngcontent-%COMP%] .component-count[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-left: auto;\n}\n\n\n\n\n\n\n\n\n.import-dropdown[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-chevron[_ngcontent-%COMP%] {\n margin-left: 4px;\n font-size: 10px;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n min-width: 180px;\n margin-top: 4px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: none;\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n text-align: left;\n transition: background 0.15s;\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.import-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 16px;\n text-align: center;\n color: var(--mj-text-secondary);\n}\n\n\n\n\n\n\n\n\n.filter-toggle-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n}\n\n.filter-toggle-btn[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-text-secondary);\n color: var(--mj-text-primary);\n}\n\n.filter-toggle-btn.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.filter-toggle-btn[_ngcontent-%COMP%] .filter-count-badge[_ngcontent-%COMP%] {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n}\n\n\n\n\n\n\n\n\n.search-box[_ngcontent-%COMP%] {\n padding: 8px 14px;\n flex-shrink: 0;\n}\n\n.search-box[_ngcontent-%COMP%] .search-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n margin-left: 6px;\n}\n\n\n\n\n\n\n\n\n.filter-panel[_ngcontent-%COMP%] {\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n}\n\n.filter-panel[_ngcontent-%COMP%] .filter-panel-content[_ngcontent-%COMP%] {\n padding: 8px 14px 12px;\n}\n\n.filter-section[_ngcontent-%COMP%] {\n margin-bottom: 10px;\n}\n\n.filter-section[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n.filter-section[_ngcontent-%COMP%] .filter-section-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n}\n\n.filter-options[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: background 0.15s;\n}\n\n.filter-checkbox[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 14px;\n height: 14px;\n accent-color: var(--mj-brand-primary);\n cursor: pointer;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .filter-icon[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .favorites-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .deprecated-icon[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.filter-checkbox[_ngcontent-%COMP%] .deprecated-count[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n\n\n\n\n\n\n\n.category-pills[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.category-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 14px;\n background: var(--mj-bg-surface);\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.category-pill[_ngcontent-%COMP%] .pill-name[_ngcontent-%COMP%] {\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.category-pill[_ngcontent-%COMP%] .pill-count[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 0 5px;\n border-radius: 8px;\n line-height: 16px;\n}\n\n.category-pill[_ngcontent-%COMP%]:hover {\n border-color: var(--pill-color, var(--mj-brand-primary));\n background: var(--mj-bg-surface);\n}\n\n.category-pill.active[_ngcontent-%COMP%] {\n border-color: var(--pill-color, var(--mj-brand-primary));\n background: var(--pill-color, var(--mj-brand-primary));\n color: var(--mj-text-inverse);\n}\n\n.category-pill.active[_ngcontent-%COMP%] .pill-count[_ngcontent-%COMP%] {\n background: rgba(255, 255, 255, 0.25);\n color: var(--mj-text-inverse);\n}\n\n.show-more-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-top: 6px;\n padding: 2px 0;\n border: none;\n background: none;\n font-size: 12px;\n color: var(--mj-brand-primary);\n cursor: pointer;\n}\n\n.show-more-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n}\n\n.filter-panel-footer[_ngcontent-%COMP%] {\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.clear-all-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n border-radius: 4px;\n background: none;\n font-size: 12px;\n color: var(--mj-status-error);\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.clear-all-btn[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n\n\n\n\n\n\n\n.component-list[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 8px 10px;\n}\n\n\n\n\n\n\n\n\n.loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-icon[_ngcontent-%COMP%] {\n font-size: 32px;\n color: var(--mj-border-default);\n margin-bottom: 12px;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-title[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 4px;\n}\n\n.empty-state[_ngcontent-%COMP%] .empty-subtitle[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n\n\n\n\n\n\n\n.component-card[_ngcontent-%COMP%] {\n margin-bottom: 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n transition: all 0.15s;\n overflow: hidden;\n}\n\n.component-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-sm);\n border-color: var(--mj-border-default);\n}\n\n\n\n.component-card.running[_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-status-success);\n}\n\n\n\n.component-card.file-loaded[_ngcontent-%COMP%] {\n border-style: dashed;\n border-color: var(--mj-text-muted);\n}\n\n.component-card.file-loaded[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-text-secondary);\n}\n\n\n\n.component-card.expanded[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.component-card.expanded.running[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n border-left: 3px solid var(--mj-status-success);\n}\n\n.component-card.expanded.file-loaded[_ngcontent-%COMP%] {\n border-style: solid;\n border-color: var(--mj-brand-primary);\n}\n\n\n\n\n\n\n\n\n.card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n cursor: pointer;\n user-select: none;\n}\n\n.card-header[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface);\n}\n\n.card-type-icon[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n margin-top: 2px;\n}\n\n.card-body[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.card-title-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n margin-bottom: 4px;\n}\n\n.card-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.file-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 10px;\n font-weight: 500;\n white-space: nowrap;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-meta-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.version-badge[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 1px 6px;\n border-radius: 4px;\n}\n\n.status-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n padding: 1px 7px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.status-badge.published[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-badge.draft[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.status-badge.deprecated[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.status-badge.file[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.status-badge.text[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.status-badge.artifact[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.namespace-chip[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.namespace-chip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 9px;\n opacity: 0.8;\n}\n\n\n\n\n\n\n\n\n.card-end[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.favorite-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mj-border-default);\n font-size: 14px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.favorite-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-warning);\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n}\n\n.favorite-btn.is-favorite[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.remove-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mj-border-default);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.remove-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.card-chevron[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--mj-text-secondary);\n font-size: 11px;\n}\n\n\n\n\n\n\n\n\n.card-details[_ngcontent-%COMP%] {\n padding: 0 12px 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.detail-description[_ngcontent-%COMP%] {\n padding: 8px 0;\n}\n\n.detail-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px 16px;\n padding: 8px 0;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] .info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] .info-label[_ngcontent-%COMP%] {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.detail-info-grid[_ngcontent-%COMP%] .info-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.detail-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}"] });
|
|
624
624
|
}
|
|
625
625
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentBrowserComponent, [{
|
|
626
626
|
type: Component,
|
|
627
|
-
args: [{ standalone: false, selector: 'mj-component-browser', template: "<div class=\"component-browser\">\n\n <!-- Header -->\n <div class=\"browser-header\">\n <div class=\"header-top-row\">\n <button kendoButton\n [themeColor]=\"'primary'\"\n (click)=\"OnNewComponent()\">\n <i class=\"fa-solid fa-plus\"></i> New Component\n </button>\n <div class=\"import-dropdown\" [class.open]=\"ImportDropdownOpen\">\n <button kendoButton\n [themeColor]=\"'base'\"\n (click)=\"ToggleImportDropdown()\">\n <i class=\"fa-solid fa-file-import\"></i> Import\n <i class=\"fa-solid fa-chevron-down dropdown-chevron\"></i>\n </button>\n @if (ImportDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"OnImportFromArtifact()\">\n <i class=\"fa-solid fa-database\"></i> From Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"OnImportFromFile()\">\n <i class=\"fa-solid fa-file\"></i> From File\n </button>\n <button class=\"dropdown-item\" (click)=\"OnImportFromText()\">\n <i class=\"fa-solid fa-keyboard\"></i> From Text\n </button>\n </div>\n }\n </div>\n </div>\n\n <div class=\"header-controls-row\">\n <button\n class=\"filter-toggle-btn\"\n [class.active]=\"State.IsFilterPanelExpanded || State.GetActiveFilterCount() > 0\"\n (click)=\"State.ToggleFilterPanel()\"\n [title]=\"State.IsFilterPanelExpanded ? 'Hide filters' : 'Show filters'\">\n <i class=\"fa-solid fa-sliders\"></i>\n @if (State.GetActiveFilterCount() > 0) {\n <span class=\"filter-count-badge\">{{ State.GetActiveFilterCount() }}</span>\n }\n </button>\n <span class=\"component-count\">\n {{ State.FilteredComponents.length }} of {{ State.AllComponents.length }}\n </span>\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-box\">\n <kendo-textbox\n [value]=\"State.SearchQuery\"\n (valueChange)=\"OnSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search search-icon\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n\n <!-- Collapsible Filter Panel -->\n @if (State.IsFilterPanelExpanded) {\n <div class=\"filter-panel\">\n <div class=\"filter-panel-content\">\n\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]=\"State.ShowOnlyFavorites\"\n (change)=\"State.ToggleShowOnlyFavorites()\">\n <i class=\"fa-solid fa-star filter-icon favorites-icon\"></i>\n <span>Favorites only</span>\n </label>\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"State.ShowDeprecatedComponents\"\n (change)=\"State.ToggleShowDeprecatedComponents()\">\n <i class=\"fa-solid fa-archive filter-icon deprecated-icon\"></i>\n <span>Show deprecated\n @if (State.GetDeprecatedCount() > 0) {\n <span class=\"deprecated-count\">({{ State.GetDeprecatedCount() }})</span>\n }\n </span>\n </label>\n </div>\n </div>\n\n <!-- Category Pills -->\n @if (State.AvailableCategories.length > 0) {\n <div class=\"filter-section\">\n <label class=\"filter-section-label\">Categories</label>\n <div class=\"category-pills\">\n @for (category of State.GetVisibleCategories(); track TrackByCategoryName($index, category)) {\n <button\n class=\"category-pill\"\n [class.active]=\"State.IsCategorySelected(category.name)\"\n [style.--pill-color]=\"category.color\"\n (click)=\"State.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 (State.AvailableCategories.length > 5) {\n <button\n class=\"show-more-btn\"\n (click)=\"State.ToggleShowAllCategories()\">\n @if (State.ShowAllCategories) {\n <i class=\"fa-solid fa-chevron-up\"></i> Show less\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i> Show {{ State.AvailableCategories.length - 5 }} more\n }\n </button>\n }\n </div>\n }\n\n <!-- Clear All -->\n @if (State.GetActiveFilterCount() > 0) {\n <div class=\"filter-panel-footer\">\n <button class=\"clear-all-btn\" (click)=\"State.ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear All Filters\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Component Card List -->\n <div class=\"component-list\">\n @if (State.IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading components...\" size=\"small\"></mj-loading>\n </div>\n } @else if (State.FilteredComponents.length === 0) {\n <div class=\"empty-state\">\n @if (State.AllComponents.length === 0) {\n <i class=\"fa-solid fa-puzzle-piece empty-icon\"></i>\n <p class=\"empty-title\">No components found</p>\n <p class=\"empty-subtitle\">Create a new component or import one to get started.</p>\n } @else {\n <i class=\"fa-solid fa-filter empty-icon\"></i>\n <p class=\"empty-title\">No matching components</p>\n <p class=\"empty-subtitle\">Try adjusting your search or filters.</p>\n }\n </div>\n } @else {\n @for (component of State.FilteredComponents; track TrackByComponentId($index, component)) {\n <div class=\"component-card\"\n [class.expanded]=\"IsExpanded(component)\"\n [class.running]=\"IsComponentRunning(component)\"\n [class.file-loaded]=\"State.IsFileLoadedComponent(component)\">\n\n <!-- Card Header (always visible) -->\n <div class=\"card-header\" (click)=\"ToggleComponentExpansion(component)\">\n <div class=\"card-type-icon\"\n [style.color]=\"State.GetComponentTypeColor(State.GetComponentType(component))\">\n <i class=\"fa-solid\"\n [ngClass]=\"State.GetComponentTypeIcon(State.GetComponentType(component))\"></i>\n </div>\n\n <div class=\"card-body\">\n <div class=\"card-title-row\">\n <span class=\"card-name\">{{ State.GetComponentName(component) }}</span>\n @if (State.IsFileLoadedComponent(component)) {\n <span class=\"file-badge\" [title]=\"GetFileBadgeTooltip(component)\">\n <i class=\"fa-solid\" [ngClass]=\"GetFileBadgeIcon(component)\"></i>\n {{ GetFileBadgeLabel(component) }}\n </span>\n }\n </div>\n <div class=\"card-meta-row\">\n <span class=\"version-badge\">v{{ State.GetComponentVersion(component) }}</span>\n <span class=\"status-badge\" [ngClass]=\"GetStatusBadgeClass(component)\">\n {{ GetStatusLabel(component) }}\n </span>\n <span class=\"namespace-chip\"\n [style.background-color]=\"State.GetNamespaceColor(State.GetComponentNamespace(component))\"\n [title]=\"State.GetComponentNamespace(component) || 'Uncategorized'\">\n <i class=\"fa-solid fa-folder-tree\"></i>\n {{ State.FormatNamespace(State.GetComponentNamespace(component)) }}\n </span>\n </div>\n </div>\n\n <div class=\"card-end\">\n @if (!State.IsFileLoadedComponent(component)) {\n <button\n class=\"favorite-btn\"\n [class.is-favorite]=\"State.IsFavorite(component)\"\n (click)=\"OnToggleFavorite(component, $event)\"\n [title]=\"State.IsFavorite(component) ? 'Remove from favorites' : 'Add to favorites'\">\n @if (State.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 @if (State.IsFileLoadedComponent(component)) {\n <button\n class=\"remove-btn\"\n (click)=\"OnRemoveFileComponent($any(component), $event)\"\n title=\"Remove imported component\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n <div class=\"card-chevron\">\n @if (IsExpanded(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 </div>\n\n <!-- Card Details (expanded) -->\n @if (IsExpanded(component)) {\n <div class=\"card-details\">\n @if (State.GetComponentDescription(component)) {\n <div class=\"detail-description\">\n <p>{{ State.GetComponentDescription(component) }}</p>\n </div>\n }\n\n <div class=\"detail-info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type</span>\n <span class=\"info-value\">{{ State.GetComponentType(component) || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version</span>\n <span class=\"info-value\">{{ State.GetComponentVersion(component) }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status</span>\n <span class=\"info-value\">{{ State.GetComponentStatus(component) || 'Draft' }}</span>\n </div>\n @if (State.IsFileLoadedComponent(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Loaded</span>\n <span class=\"info-value\">{{ State.GetComponentLoadedAt(component) | date:'short' }}</span>\n </div>\n } @else if (State.GetComponentUpdatedAt(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated</span>\n <span class=\"info-value\">{{ State.GetComponentUpdatedAt(component) | date:'short' }}</span>\n </div>\n }\n </div>\n\n <div class=\"detail-actions\">\n @if (IsComponentRunning(component)) {\n <button kendoButton\n [themeColor]=\"'error'\"\n (click)=\"OnStopComponent($event)\">\n <i class=\"fa-solid fa-stop\"></i> Stop\n </button>\n } @else if (IsAnotherComponentRunning(component)) {\n <button kendoButton\n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"OnSwitchComponent(component, $event)\">\n <i class=\"fa-solid fa-exchange-alt\"></i> Switch To This\n </button>\n } @else {\n <button kendoButton\n [themeColor]=\"'primary'\"\n (click)=\"OnRunComponent(component, $event)\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n</div>\n", styles: ["/* ============================================================ */\n/* Component Browser - Left Panel */\n/* ============================================================ */\n\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.component-browser {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mat-sys-surface-container-low);\n overflow: hidden;\n}\n\n/* ============================================================ */\n/* Header */\n/* ============================================================ */\n\n.browser-header {\n padding: 12px 14px 8px;\n border-bottom: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface);\n flex-shrink: 0;\n}\n\n.browser-header .header-top-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.browser-header .header-controls-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.browser-header .component-count {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n margin-left: auto;\n}\n\n/* ============================================================ */\n/* Import Dropdown */\n/* ============================================================ */\n\n.import-dropdown {\n position: relative;\n}\n\n.import-dropdown .dropdown-chevron {\n margin-left: 4px;\n font-size: 10px;\n}\n\n.import-dropdown .dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n min-width: 180px;\n margin-top: 4px;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-extra-small);\n box-shadow: var(--mat-sys-elevation-2);\n overflow: hidden;\n}\n\n.import-dropdown .dropdown-menu .dropdown-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: none;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n cursor: pointer;\n text-align: left;\n transition: background 0.15s;\n}\n\n.import-dropdown .dropdown-menu .dropdown-item:hover {\n background: var(--mat-sys-surface-variant);\n}\n\n.import-dropdown .dropdown-menu .dropdown-item i {\n width: 16px;\n text-align: center;\n color: var(--mat-sys-on-surface-variant);\n}\n\n/* ============================================================ */\n/* Filter Toggle Button */\n/* ============================================================ */\n\n.filter-toggle-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-extra-small);\n background: var(--mat-sys-surface);\n color: var(--mat-sys-on-surface-variant);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n}\n\n.filter-toggle-btn:hover {\n border-color: var(--mat-sys-on-surface-variant);\n color: var(--mat-sys-on-surface);\n}\n\n.filter-toggle-btn.active {\n border-color: var(--mat-sys-primary);\n color: var(--mat-sys-primary);\n background: #eff6ff;\n}\n\n.filter-toggle-btn .filter-count-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mat-sys-primary);\n color: #fff;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n}\n\n/* ============================================================ */\n/* Search Box */\n/* ============================================================ */\n\n.search-box {\n padding: 8px 14px;\n flex-shrink: 0;\n}\n\n.search-box .search-icon {\n color: var(--mat-sys-on-surface-variant);\n margin-left: 6px;\n}\n\n/* ============================================================ */\n/* Filter Panel */\n/* ============================================================ */\n\n.filter-panel {\n border-bottom: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface);\n flex-shrink: 0;\n}\n\n.filter-panel .filter-panel-content {\n padding: 8px 14px 12px;\n}\n\n.filter-section {\n margin-bottom: 10px;\n}\n\n.filter-section:last-child {\n margin-bottom: 0;\n}\n\n.filter-section .filter-section-label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n}\n\n.filter-options {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.filter-checkbox {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n transition: background 0.15s;\n}\n\n.filter-checkbox:hover {\n background: var(--mat-sys-surface-variant);\n}\n\n.filter-checkbox input[type=\"checkbox\"] {\n width: 14px;\n height: 14px;\n accent-color: var(--mat-sys-primary);\n cursor: pointer;\n}\n\n.filter-checkbox .filter-icon {\n font-size: 12px;\n}\n\n.filter-checkbox .favorites-icon {\n color: #eab308;\n}\n\n.filter-checkbox .deprecated-icon {\n color: #94a3b8;\n}\n\n.filter-checkbox .deprecated-count {\n color: #94a3b8;\n font-size: 12px;\n}\n\n/* ============================================================ */\n/* Category Pills */\n/* ============================================================ */\n\n.category-pills {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.category-pill {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n border: 1px solid var(--mat-sys-outline);\n border-radius: 14px;\n background: var(--mat-sys-surface);\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.category-pill .pill-name {\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.category-pill .pill-count {\n font-size: 10px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-variant);\n padding: 0 5px;\n border-radius: 8px;\n line-height: 16px;\n}\n\n.category-pill:hover {\n border-color: var(--pill-color, var(--mat-sys-primary));\n background: var(--mat-sys-surface-container-lowest);\n}\n\n.category-pill.active {\n border-color: var(--pill-color, var(--mat-sys-primary));\n background: var(--pill-color, var(--mat-sys-primary));\n color: #fff;\n}\n\n.category-pill.active .pill-count {\n background: rgba(255, 255, 255, 0.25);\n color: #fff;\n}\n\n.show-more-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-top: 6px;\n padding: 2px 0;\n border: none;\n background: none;\n font-size: 12px;\n color: var(--mat-sys-primary);\n cursor: pointer;\n}\n\n.show-more-btn:hover {\n color: var(--mat-sys-primary);\n text-decoration: underline;\n}\n\n.filter-panel-footer {\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.clear-all-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n border-radius: 4px;\n background: none;\n font-size: 12px;\n color: #ef4444;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.clear-all-btn:hover {\n background: #fef2f2;\n}\n\n/* ============================================================ */\n/* Component List (scrollable) */\n/* ============================================================ */\n\n.component-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 10px;\n}\n\n/* ============================================================ */\n/* Loading & Empty States */\n/* ============================================================ */\n\n.loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.empty-state .empty-icon {\n font-size: 32px;\n color: var(--mat-sys-outline);\n margin-bottom: 12px;\n}\n\n.empty-state .empty-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n margin: 0 0 4px;\n}\n\n.empty-state .empty-subtitle {\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n margin: 0;\n}\n\n/* ============================================================ */\n/* Component Card */\n/* ============================================================ */\n\n.component-card {\n margin-bottom: 6px;\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-small);\n background: var(--mat-sys-surface);\n transition: all 0.15s;\n overflow: hidden;\n}\n\n.component-card:hover {\n box-shadow: var(--mat-sys-elevation-1);\n border-color: var(--mat-sys-outline);\n}\n\n/* Running state: green left border */\n.component-card.running {\n border-left: 3px solid #10b981;\n}\n\n/* File-loaded state: dashed border */\n.component-card.file-loaded {\n border-style: dashed;\n border-color: #94a3b8;\n}\n\n.component-card.file-loaded:hover {\n border-color: #64748b;\n}\n\n/* Expanded state: blue border */\n.component-card.expanded {\n border-color: var(--mat-sys-primary);\n box-shadow: 0 2px 12px rgba(59, 130, 246, 0.1);\n}\n\n.component-card.expanded.running {\n border-color: var(--mat-sys-primary);\n border-left: 3px solid #10b981;\n}\n\n.component-card.expanded.file-loaded {\n border-style: solid;\n border-color: var(--mat-sys-primary);\n}\n\n/* ============================================================ */\n/* Card Header */\n/* ============================================================ */\n\n.card-header {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n cursor: pointer;\n user-select: none;\n}\n\n.card-header:hover {\n background: var(--mat-sys-surface-container-lowest);\n}\n\n.card-type-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n background: var(--mat-sys-surface-variant);\n border-radius: var(--mat-sys-corner-extra-small);\n margin-top: 2px;\n}\n\n.card-body {\n flex: 1;\n min-width: 0;\n}\n\n.card-title-row {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n margin-bottom: 4px;\n}\n\n.card-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.file-badge {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px;\n border-radius: 4px;\n background: #f0f9ff;\n color: #0284c7;\n font-size: 10px;\n font-weight: 500;\n white-space: nowrap;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-meta-row {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.version-badge {\n font-size: 11px;\n font-weight: 500;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-variant);\n padding: 1px 6px;\n border-radius: 4px;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n padding: 1px 7px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.status-badge.published {\n background: #d1fae5;\n color: #065f46;\n}\n\n.status-badge.draft {\n background: #e0e7ff;\n color: #3730a3;\n}\n\n.status-badge.deprecated {\n background: #fee2e2;\n color: #991b1b;\n}\n\n.status-badge.file {\n background: #fef3c7;\n color: #92400e;\n}\n\n.status-badge.text {\n background: #ede9fe;\n color: #5b21b6;\n}\n\n.status-badge.artifact {\n background: #cffafe;\n color: #155e75;\n}\n\n.namespace-chip {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n color: #fff;\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.namespace-chip i {\n font-size: 9px;\n opacity: 0.8;\n}\n\n/* ============================================================ */\n/* Card End (favorite, remove, chevron) */\n/* ============================================================ */\n\n.card-end {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.favorite-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mat-sys-outline);\n font-size: 14px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.favorite-btn:hover {\n color: #eab308;\n background: #fefce8;\n}\n\n.favorite-btn.is-favorite {\n color: #eab308;\n}\n\n.remove-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mat-sys-outline);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.remove-btn:hover {\n color: #ef4444;\n background: #fef2f2;\n}\n\n.card-chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--mat-sys-on-surface-variant);\n font-size: 11px;\n}\n\n/* ============================================================ */\n/* Card Details (expanded content) */\n/* ============================================================ */\n\n.card-details {\n padding: 0 12px 12px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.detail-description {\n padding: 8px 0;\n}\n\n.detail-description p {\n margin: 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n line-height: 1.5;\n}\n\n.detail-info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px 16px;\n padding: 8px 0;\n}\n\n.detail-info-grid .info-item {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.detail-info-grid .info-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.detail-info-grid .info-value {\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n}\n\n.detail-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n"] }]
|
|
627
|
+
args: [{ standalone: false, selector: 'mj-component-browser', template: "<div class=\"component-browser\">\n\n <!-- Header -->\n <div class=\"browser-header\">\n <div class=\"header-top-row\">\n <button kendoButton\n [themeColor]=\"'primary'\"\n (click)=\"OnNewComponent()\">\n <i class=\"fa-solid fa-plus\"></i> New Component\n </button>\n <div class=\"import-dropdown\" [class.open]=\"ImportDropdownOpen\">\n <button kendoButton\n [themeColor]=\"'base'\"\n (click)=\"ToggleImportDropdown()\">\n <i class=\"fa-solid fa-file-import\"></i> Import\n <i class=\"fa-solid fa-chevron-down dropdown-chevron\"></i>\n </button>\n @if (ImportDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"OnImportFromArtifact()\">\n <i class=\"fa-solid fa-database\"></i> From Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"OnImportFromFile()\">\n <i class=\"fa-solid fa-file\"></i> From File\n </button>\n <button class=\"dropdown-item\" (click)=\"OnImportFromText()\">\n <i class=\"fa-solid fa-keyboard\"></i> From Text\n </button>\n </div>\n }\n </div>\n </div>\n\n <div class=\"header-controls-row\">\n <button\n class=\"filter-toggle-btn\"\n [class.active]=\"State.IsFilterPanelExpanded || State.GetActiveFilterCount() > 0\"\n (click)=\"State.ToggleFilterPanel()\"\n [title]=\"State.IsFilterPanelExpanded ? 'Hide filters' : 'Show filters'\">\n <i class=\"fa-solid fa-sliders\"></i>\n @if (State.GetActiveFilterCount() > 0) {\n <span class=\"filter-count-badge\">{{ State.GetActiveFilterCount() }}</span>\n }\n </button>\n <span class=\"component-count\">\n {{ State.FilteredComponents.length }} of {{ State.AllComponents.length }}\n </span>\n </div>\n </div>\n\n <!-- Search -->\n <div class=\"search-box\">\n <kendo-textbox\n [value]=\"State.SearchQuery\"\n (valueChange)=\"OnSearchChange($event)\"\n placeholder=\"Search components...\"\n [clearButton]=\"true\">\n <ng-template kendoTextBoxPrefixTemplate>\n <i class=\"fa-solid fa-search search-icon\"></i>\n </ng-template>\n </kendo-textbox>\n </div>\n\n <!-- Collapsible Filter Panel -->\n @if (State.IsFilterPanelExpanded) {\n <div class=\"filter-panel\">\n <div class=\"filter-panel-content\">\n\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]=\"State.ShowOnlyFavorites\"\n (change)=\"State.ToggleShowOnlyFavorites()\">\n <i class=\"fa-solid fa-star filter-icon favorites-icon\"></i>\n <span>Favorites only</span>\n </label>\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"State.ShowDeprecatedComponents\"\n (change)=\"State.ToggleShowDeprecatedComponents()\">\n <i class=\"fa-solid fa-archive filter-icon deprecated-icon\"></i>\n <span>Show deprecated\n @if (State.GetDeprecatedCount() > 0) {\n <span class=\"deprecated-count\">({{ State.GetDeprecatedCount() }})</span>\n }\n </span>\n </label>\n </div>\n </div>\n\n <!-- Category Pills -->\n @if (State.AvailableCategories.length > 0) {\n <div class=\"filter-section\">\n <label class=\"filter-section-label\">Categories</label>\n <div class=\"category-pills\">\n @for (category of State.GetVisibleCategories(); track TrackByCategoryName($index, category)) {\n <button\n class=\"category-pill\"\n [class.active]=\"State.IsCategorySelected(category.name)\"\n [style.--pill-color]=\"category.color\"\n (click)=\"State.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 (State.AvailableCategories.length > 5) {\n <button\n class=\"show-more-btn\"\n (click)=\"State.ToggleShowAllCategories()\">\n @if (State.ShowAllCategories) {\n <i class=\"fa-solid fa-chevron-up\"></i> Show less\n } @else {\n <i class=\"fa-solid fa-chevron-down\"></i> Show {{ State.AvailableCategories.length - 5 }} more\n }\n </button>\n }\n </div>\n }\n\n <!-- Clear All -->\n @if (State.GetActiveFilterCount() > 0) {\n <div class=\"filter-panel-footer\">\n <button class=\"clear-all-btn\" (click)=\"State.ClearAllFilters()\">\n <i class=\"fa-solid fa-times\"></i> Clear All Filters\n </button>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Component Card List -->\n <div class=\"component-list\">\n @if (State.IsLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading components...\" size=\"small\"></mj-loading>\n </div>\n } @else if (State.FilteredComponents.length === 0) {\n <div class=\"empty-state\">\n @if (State.AllComponents.length === 0) {\n <i class=\"fa-solid fa-puzzle-piece empty-icon\"></i>\n <p class=\"empty-title\">No components found</p>\n <p class=\"empty-subtitle\">Create a new component or import one to get started.</p>\n } @else {\n <i class=\"fa-solid fa-filter empty-icon\"></i>\n <p class=\"empty-title\">No matching components</p>\n <p class=\"empty-subtitle\">Try adjusting your search or filters.</p>\n }\n </div>\n } @else {\n @for (component of State.FilteredComponents; track TrackByComponentId($index, component)) {\n <div class=\"component-card\"\n [class.expanded]=\"IsExpanded(component)\"\n [class.running]=\"IsComponentRunning(component)\"\n [class.file-loaded]=\"State.IsFileLoadedComponent(component)\">\n\n <!-- Card Header (always visible) -->\n <div class=\"card-header\" (click)=\"ToggleComponentExpansion(component)\">\n <div class=\"card-type-icon\"\n [style.color]=\"State.GetComponentTypeColor(State.GetComponentType(component))\">\n <i class=\"fa-solid\"\n [ngClass]=\"State.GetComponentTypeIcon(State.GetComponentType(component))\"></i>\n </div>\n\n <div class=\"card-body\">\n <div class=\"card-title-row\">\n <span class=\"card-name\">{{ State.GetComponentName(component) }}</span>\n @if (State.IsFileLoadedComponent(component)) {\n <span class=\"file-badge\" [title]=\"GetFileBadgeTooltip(component)\">\n <i class=\"fa-solid\" [ngClass]=\"GetFileBadgeIcon(component)\"></i>\n {{ GetFileBadgeLabel(component) }}\n </span>\n }\n </div>\n <div class=\"card-meta-row\">\n <span class=\"version-badge\">v{{ State.GetComponentVersion(component) }}</span>\n <span class=\"status-badge\" [ngClass]=\"GetStatusBadgeClass(component)\">\n {{ GetStatusLabel(component) }}\n </span>\n <span class=\"namespace-chip\"\n [style.background-color]=\"State.GetNamespaceColor(State.GetComponentNamespace(component))\"\n [title]=\"State.GetComponentNamespace(component) || 'Uncategorized'\">\n <i class=\"fa-solid fa-folder-tree\"></i>\n {{ State.FormatNamespace(State.GetComponentNamespace(component)) }}\n </span>\n </div>\n </div>\n\n <div class=\"card-end\">\n @if (!State.IsFileLoadedComponent(component)) {\n <button\n class=\"favorite-btn\"\n [class.is-favorite]=\"State.IsFavorite(component)\"\n (click)=\"OnToggleFavorite(component, $event)\"\n [title]=\"State.IsFavorite(component) ? 'Remove from favorites' : 'Add to favorites'\">\n @if (State.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 @if (State.IsFileLoadedComponent(component)) {\n <button\n class=\"remove-btn\"\n (click)=\"OnRemoveFileComponent($any(component), $event)\"\n title=\"Remove imported component\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n <div class=\"card-chevron\">\n @if (IsExpanded(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 </div>\n\n <!-- Card Details (expanded) -->\n @if (IsExpanded(component)) {\n <div class=\"card-details\">\n @if (State.GetComponentDescription(component)) {\n <div class=\"detail-description\">\n <p>{{ State.GetComponentDescription(component) }}</p>\n </div>\n }\n\n <div class=\"detail-info-grid\">\n <div class=\"info-item\">\n <span class=\"info-label\">Type</span>\n <span class=\"info-value\">{{ State.GetComponentType(component) || 'Unknown' }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Version</span>\n <span class=\"info-value\">{{ State.GetComponentVersion(component) }}</span>\n </div>\n <div class=\"info-item\">\n <span class=\"info-label\">Status</span>\n <span class=\"info-value\">{{ State.GetComponentStatus(component) || 'Draft' }}</span>\n </div>\n @if (State.IsFileLoadedComponent(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Loaded</span>\n <span class=\"info-value\">{{ State.GetComponentLoadedAt(component) | date:'short' }}</span>\n </div>\n } @else if (State.GetComponentUpdatedAt(component)) {\n <div class=\"info-item\">\n <span class=\"info-label\">Updated</span>\n <span class=\"info-value\">{{ State.GetComponentUpdatedAt(component) | date:'short' }}</span>\n </div>\n }\n </div>\n\n <div class=\"detail-actions\">\n @if (IsComponentRunning(component)) {\n <button kendoButton\n [themeColor]=\"'error'\"\n (click)=\"OnStopComponent($event)\">\n <i class=\"fa-solid fa-stop\"></i> Stop\n </button>\n } @else if (IsAnotherComponentRunning(component)) {\n <button kendoButton\n [themeColor]=\"'base'\"\n title=\"Stop current component and run this one\"\n (click)=\"OnSwitchComponent(component, $event)\">\n <i class=\"fa-solid fa-exchange-alt\"></i> Switch To This\n </button>\n } @else {\n <button kendoButton\n [themeColor]=\"'primary'\"\n (click)=\"OnRunComponent(component, $event)\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n</div>\n", styles: ["/* ============================================================ */\n/* Component Browser - Left Panel */\n/* ============================================================ */\n\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.component-browser {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n/* ============================================================ */\n/* Header */\n/* ============================================================ */\n\n.browser-header {\n padding: 12px 14px 8px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n}\n\n.browser-header .header-top-row {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.browser-header .header-controls-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.browser-header .component-count {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-left: auto;\n}\n\n/* ============================================================ */\n/* Import Dropdown */\n/* ============================================================ */\n\n.import-dropdown {\n position: relative;\n}\n\n.import-dropdown .dropdown-chevron {\n margin-left: 4px;\n font-size: 10px;\n}\n\n.import-dropdown .dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n min-width: 180px;\n margin-top: 4px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n box-shadow: var(--mj-shadow-md);\n overflow: hidden;\n}\n\n.import-dropdown .dropdown-menu .dropdown-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 8px 14px;\n border: none;\n background: none;\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n text-align: left;\n transition: background 0.15s;\n}\n\n.import-dropdown .dropdown-menu .dropdown-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.import-dropdown .dropdown-menu .dropdown-item i {\n width: 16px;\n text-align: center;\n color: var(--mj-text-secondary);\n}\n\n/* ============================================================ */\n/* Filter Toggle Button */\n/* ============================================================ */\n\n.filter-toggle-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 5px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s;\n position: relative;\n}\n\n.filter-toggle-btn:hover {\n border-color: var(--mj-text-secondary);\n color: var(--mj-text-primary);\n}\n\n.filter-toggle-btn.active {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n}\n\n.filter-toggle-btn .filter-count-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n}\n\n/* ============================================================ */\n/* Search Box */\n/* ============================================================ */\n\n.search-box {\n padding: 8px 14px;\n flex-shrink: 0;\n}\n\n.search-box .search-icon {\n color: var(--mj-text-secondary);\n margin-left: 6px;\n}\n\n/* ============================================================ */\n/* Filter Panel */\n/* ============================================================ */\n\n.filter-panel {\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n}\n\n.filter-panel .filter-panel-content {\n padding: 8px 14px 12px;\n}\n\n.filter-section {\n margin-bottom: 10px;\n}\n\n.filter-section:last-child {\n margin-bottom: 0;\n}\n\n.filter-section .filter-section-label {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n}\n\n.filter-options {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.filter-checkbox {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-secondary);\n transition: background 0.15s;\n}\n\n.filter-checkbox:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-checkbox input[type=\"checkbox\"] {\n width: 14px;\n height: 14px;\n accent-color: var(--mj-brand-primary);\n cursor: pointer;\n}\n\n.filter-checkbox .filter-icon {\n font-size: 12px;\n}\n\n.filter-checkbox .favorites-icon {\n color: var(--mj-status-warning);\n}\n\n.filter-checkbox .deprecated-icon {\n color: var(--mj-text-muted);\n}\n\n.filter-checkbox .deprecated-count {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n/* ============================================================ */\n/* Category Pills */\n/* ============================================================ */\n\n.category-pills {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.category-pill {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 3px 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 14px;\n background: var(--mj-bg-surface);\n font-size: 12px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.category-pill .pill-name {\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.category-pill .pill-count {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 0 5px;\n border-radius: 8px;\n line-height: 16px;\n}\n\n.category-pill:hover {\n border-color: var(--pill-color, var(--mj-brand-primary));\n background: var(--mj-bg-surface);\n}\n\n.category-pill.active {\n border-color: var(--pill-color, var(--mj-brand-primary));\n background: var(--pill-color, var(--mj-brand-primary));\n color: var(--mj-text-inverse);\n}\n\n.category-pill.active .pill-count {\n background: rgba(255, 255, 255, 0.25);\n color: var(--mj-text-inverse);\n}\n\n.show-more-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-top: 6px;\n padding: 2px 0;\n border: none;\n background: none;\n font-size: 12px;\n color: var(--mj-brand-primary);\n cursor: pointer;\n}\n\n.show-more-btn:hover {\n color: var(--mj-brand-primary);\n text-decoration: underline;\n}\n\n.filter-panel-footer {\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.clear-all-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n border-radius: 4px;\n background: none;\n font-size: 12px;\n color: var(--mj-status-error);\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.clear-all-btn:hover {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n/* ============================================================ */\n/* Component List (scrollable) */\n/* ============================================================ */\n\n.component-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 10px;\n}\n\n/* ============================================================ */\n/* Loading & Empty States */\n/* ============================================================ */\n\n.loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n.empty-state .empty-icon {\n font-size: 32px;\n color: var(--mj-border-default);\n margin-bottom: 12px;\n}\n\n.empty-state .empty-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 4px;\n}\n\n.empty-state .empty-subtitle {\n font-size: 13px;\n color: var(--mj-text-secondary);\n margin: 0;\n}\n\n/* ============================================================ */\n/* Component Card */\n/* ============================================================ */\n\n.component-card {\n margin-bottom: 6px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n transition: all 0.15s;\n overflow: hidden;\n}\n\n.component-card:hover {\n box-shadow: var(--mj-shadow-sm);\n border-color: var(--mj-border-default);\n}\n\n/* Running state: green left border */\n.component-card.running {\n border-left: 3px solid var(--mj-status-success);\n}\n\n/* File-loaded state: dashed border */\n.component-card.file-loaded {\n border-style: dashed;\n border-color: var(--mj-text-muted);\n}\n\n.component-card.file-loaded:hover {\n border-color: var(--mj-text-secondary);\n}\n\n/* Expanded state: blue border */\n.component-card.expanded {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.component-card.expanded.running {\n border-color: var(--mj-brand-primary);\n border-left: 3px solid var(--mj-status-success);\n}\n\n.component-card.expanded.file-loaded {\n border-style: solid;\n border-color: var(--mj-brand-primary);\n}\n\n/* ============================================================ */\n/* Card Header */\n/* ============================================================ */\n\n.card-header {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 12px;\n cursor: pointer;\n user-select: none;\n}\n\n.card-header:hover {\n background: var(--mj-bg-surface);\n}\n\n.card-type-icon {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n margin-top: 2px;\n}\n\n.card-body {\n flex: 1;\n min-width: 0;\n}\n\n.card-title-row {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n margin-bottom: 4px;\n}\n\n.card-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.file-badge {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 10px;\n font-weight: 500;\n white-space: nowrap;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card-meta-row {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.version-badge {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n padding: 1px 6px;\n border-radius: 4px;\n}\n\n.status-badge {\n display: inline-flex;\n align-items: center;\n padding: 1px 7px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.status-badge.published {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-badge.draft {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.status-badge.deprecated {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.status-badge.file {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.status-badge.text {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.status-badge.artifact {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.namespace-chip {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n color: var(--mj-text-inverse);\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.namespace-chip i {\n font-size: 9px;\n opacity: 0.8;\n}\n\n/* ============================================================ */\n/* Card End (favorite, remove, chevron) */\n/* ============================================================ */\n\n.card-end {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.favorite-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mj-border-default);\n font-size: 14px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.favorite-btn:hover {\n color: var(--mj-status-warning);\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n}\n\n.favorite-btn.is-favorite {\n color: var(--mj-status-warning);\n}\n\n.remove-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--mj-border-default);\n font-size: 12px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.remove-btn:hover {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.card-chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n color: var(--mj-text-secondary);\n font-size: 11px;\n}\n\n/* ============================================================ */\n/* Card Details (expanded content) */\n/* ============================================================ */\n\n.card-details {\n padding: 0 12px 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.detail-description {\n padding: 8px 0;\n}\n\n.detail-description p {\n margin: 0;\n font-size: 13px;\n color: var(--mj-text-secondary);\n line-height: 1.5;\n}\n\n.detail-info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px 16px;\n padding: 8px 0;\n}\n\n.detail-info-grid .info-item {\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.detail-info-grid .info-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n}\n\n.detail-info-grid .info-value {\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.detail-actions {\n display: flex;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n"] }]
|
|
628
628
|
}], () => [{ type: i1.ComponentStudioStateService }, { type: i0.ChangeDetectorRef }], { NewComponent: [{
|
|
629
629
|
type: Output
|
|
630
630
|
}], ImportFromFile: [{
|
|
@@ -264,7 +264,7 @@ export class CodeEditorPanelComponent {
|
|
|
264
264
|
i0.ɵɵconditional(ctx.State.IsEditingCode ? 17 : -1);
|
|
265
265
|
i0.ɵɵadvance(2);
|
|
266
266
|
i0.ɵɵconditional(ctx.ActiveSection ? 19 : 20);
|
|
267
|
-
} }, dependencies: [i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.ButtonComponent], styles: [".code-editor-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n \n\n .code-tab-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 36px;\n background: var(--
|
|
267
|
+
} }, dependencies: [i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.ButtonComponent], styles: [".code-editor-panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n \n\n .code-tab-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 2px;\n overflow-x: auto;\n }\n\n .code-tab[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n font-family: inherit;\n position: relative;\n }\n\n .code-tab[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .code-tab.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-weight: 600;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .dep-icon[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-brand-primary);\n }\n\n .modified-dot[_ngcontent-%COMP%] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-error);\n display: inline-block;\n margin-left: 2px;\n }\n\n \n\n .code-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 8px;\n }\n\n .view-mode-toggle[_ngcontent-%COMP%] {\n display: inline-flex;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n .mode-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .mode-btn[_ngcontent-%COMP%]:not(:last-child) {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .mode-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .mode-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .mode-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .toolbar-spacer[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .icon-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n }\n\n .icon-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n }\n\n .diff-nav[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: 4px;\n }\n\n .diff-count[_ngcontent-%COMP%] {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n padding: 0 4px;\n white-space: nowrap;\n }\n\n .icon-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.35;\n cursor: default;\n }\n\n \n\n .code-editor-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n }\n\n .editor-pane[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n }\n\n .editor-pane[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n }\n\n \n\n [_nghost-%COMP%] .diff-pane .cm-mergeView .cm-changedLine {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n }\n\n [_nghost-%COMP%] .diff-pane .cm-mergeView .cm-deletedChunk {\n background: color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n }\n\n \n\n .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }"] });
|
|
268
268
|
}
|
|
269
269
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CodeEditorPanelComponent, [{
|
|
270
270
|
type: Component,
|
|
@@ -371,7 +371,7 @@ export class CodeEditorPanelComponent {
|
|
|
371
371
|
}
|
|
372
372
|
</div>
|
|
373
373
|
</div>
|
|
374
|
-
`, styles: ["\n .code-editor-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n /* ---- Tab bar ---- */\n .code-tab-bar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 36px;\n background: var(--
|
|
374
|
+
`, styles: ["\n .code-editor-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n /* ---- Tab bar ---- */\n .code-tab-bar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 2px;\n overflow-x: auto;\n }\n\n .code-tab {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n font-family: inherit;\n position: relative;\n }\n\n .code-tab:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .code-tab.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-weight: 600;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .dep-icon {\n font-size: 10px;\n color: var(--mj-brand-primary);\n }\n\n .modified-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-error);\n display: inline-block;\n margin-left: 2px;\n }\n\n /* ---- Toolbar ---- */\n .code-toolbar {\n display: flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 8px;\n }\n\n .view-mode-toggle {\n display: inline-flex;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n .mode-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .mode-btn:not(:last-child) {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .mode-btn:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .mode-btn.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .mode-btn i {\n font-size: 10px;\n }\n\n .toolbar-spacer {\n flex: 1;\n }\n\n .icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n }\n\n .icon-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n\n .diff-nav {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: 4px;\n }\n\n .diff-count {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n padding: 0 4px;\n white-space: nowrap;\n }\n\n .icon-btn:disabled {\n opacity: 0.35;\n cursor: default;\n }\n\n /* ---- Editor body ---- */\n .code-editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n }\n\n .editor-pane {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n }\n\n .editor-pane mj-code-editor {\n display: block;\n height: 100%;\n }\n\n /* ---- Diff-specific styles ---- */\n :host ::ng-deep .diff-pane .cm-mergeView .cm-changedLine {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n }\n\n :host ::ng-deep .diff-pane .cm-mergeView .cm-deletedChunk {\n background: color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n }\n\n /* ---- Empty state ---- */\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n "] }]
|
|
375
375
|
}], () => [{ type: i1.ComponentStudioStateService }, { type: i0.ChangeDetectorRef }], { DiffEditorRef: [{
|
|
376
376
|
type: ViewChild,
|
|
377
377
|
args: ['diffEditor']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-editor-panel.component.js","sourceRoot":"","sources":["../../../../src/ComponentStudio/components/editors/code-editor-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef, ViewChild } from '@angular/core';\nimport { Extension } from '@codemirror/state';\nimport { EditorView } from '@codemirror/view';\nimport { unifiedMergeView, getChunks, goToNextChunk, goToPreviousChunk } from '@codemirror/merge';\nimport { ComponentStudioStateService, CodeSection } from '../../services/component-studio-state.service';\n\ntype CodeViewMode = 'current' | 'original' | 'diff';\n\n@Component({\n standalone: false,\n selector: 'mj-code-editor-panel',\n template: `\n <div class=\"code-editor-panel\">\n <!-- Tab bar: one tab per code section -->\n <div class=\"code-tab-bar\">\n @for (section of State.CodeSections; track section.title; let i = $index) {\n <button class=\"code-tab\"\n [class.active]=\"ActiveTabIndex === i\"\n (click)=\"SelectTab(i)\">\n @if (section.isDependency) {\n <i class=\"fa-solid fa-puzzle-piece dep-icon\"></i>\n }\n {{ section.title }}\n @if (HasChanges(section)) {\n <span class=\"modified-dot\" title=\"Modified\"></span>\n }\n </button>\n }\n </div>\n\n <!-- Toolbar: view mode toggle + actions -->\n <div class=\"code-toolbar\">\n <div class=\"view-mode-toggle\">\n <button class=\"mode-btn\" [class.active]=\"ViewMode === 'current'\" (click)=\"SetViewMode('current')\">\n Current\n </button>\n <button class=\"mode-btn\" [class.active]=\"ViewMode === 'original'\" (click)=\"SetViewMode('original')\">\n Original\n </button>\n <button class=\"mode-btn\" [class.active]=\"ViewMode === 'diff'\" (click)=\"SetViewMode('diff')\">\n <i class=\"fa-solid fa-code-compare\"></i> Diff\n </button>\n </div>\n @if (ViewMode === 'diff') {\n <div class=\"diff-nav\">\n <span class=\"diff-count\">{{ DiffChunkCount }} change{{ DiffChunkCount !== 1 ? 's' : '' }}</span>\n <button class=\"icon-btn\" (click)=\"GoToPreviousChunk()\" title=\"Previous change (↑)\" [disabled]=\"DiffChunkCount === 0\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button class=\"icon-btn\" (click)=\"GoToNextChunk()\" title=\"Next change (↓)\" [disabled]=\"DiffChunkCount === 0\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n }\n <span class=\"toolbar-spacer\"></span>\n <button class=\"icon-btn\" (click)=\"CopyCode()\" title=\"Copy code to clipboard\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n @if (State.IsEditingCode) {\n <div class=\"action-buttons\">\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"ApplyChanges()\">\n <i class=\"fa-solid fa-check\"></i> Apply\n </button>\n <button kendoButton [themeColor]=\"'base'\" (click)=\"CancelChanges()\">\n Cancel\n </button>\n </div>\n }\n </div>\n\n <!-- Editor body -->\n <div class=\"code-editor-body\">\n @if (ActiveSection) {\n @switch (ViewMode) {\n @case ('current') {\n <div class=\"editor-pane\">\n <mj-code-editor\n [(ngModel)]=\"ActiveSection.code\"\n [language]=\"'javascript'\"\n [indentWithTab]=\"true\"\n [placeholder]=\"'Enter component code...'\"\n (ngModelChange)=\"OnCodeChanged()\">\n </mj-code-editor>\n </div>\n }\n @case ('original') {\n <div class=\"editor-pane\">\n <mj-code-editor\n [ngModel]=\"ActiveSection.originalCode\"\n [language]=\"'javascript'\"\n [readonly]=\"true\">\n </mj-code-editor>\n </div>\n }\n @case ('diff') {\n <div class=\"editor-pane diff-pane\">\n <mj-code-editor\n #diffEditor\n [ngModel]=\"ActiveSection.code\"\n [language]=\"'javascript'\"\n [readonly]=\"true\"\n [extensions]=\"DiffExtensions\">\n </mj-code-editor>\n </div>\n }\n }\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-file-code\"></i>\n <p>No code sections available. Select a component to view its code.</p>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .code-editor-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n /* ---- Tab bar ---- */\n .code-tab-bar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 36px;\n background: var(--mat-sys-surface-container-low);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n flex-shrink: 0;\n gap: 2px;\n overflow-x: auto;\n }\n\n .code-tab {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n font-family: inherit;\n position: relative;\n }\n\n .code-tab:hover {\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface);\n }\n\n .code-tab.active {\n background: var(--mat-sys-surface);\n color: var(--mat-sys-primary);\n font-weight: 600;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .dep-icon {\n font-size: 10px;\n color: var(--mat-sys-tertiary, #7c3aed);\n }\n\n .modified-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mat-sys-error, #dc2626);\n display: inline-block;\n margin-left: 2px;\n }\n\n /* ---- Toolbar ---- */\n .code-toolbar {\n display: flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--mat-sys-surface-container-lowest);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n flex-shrink: 0;\n gap: 8px;\n }\n\n .view-mode-toggle {\n display: inline-flex;\n border: 1px solid var(--mat-sys-outline);\n border-radius: 8px;\n overflow: hidden;\n }\n\n .mode-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .mode-btn:not(:last-child) {\n border-right: 1px solid var(--mat-sys-outline);\n }\n\n .mode-btn:hover {\n background: var(--mat-sys-surface-container);\n }\n\n .mode-btn.active {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary, #fff);\n }\n\n .mode-btn i {\n font-size: 10px;\n }\n\n .toolbar-spacer {\n flex: 1;\n }\n\n .icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n }\n\n .icon-btn:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n }\n\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n\n .diff-nav {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: 4px;\n }\n\n .diff-count {\n font-size: 11px;\n font-weight: 500;\n color: var(--mat-sys-on-surface-variant);\n padding: 0 4px;\n white-space: nowrap;\n }\n\n .icon-btn:disabled {\n opacity: 0.35;\n cursor: default;\n }\n\n /* ---- Editor body ---- */\n .code-editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n }\n\n .editor-pane {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n }\n\n .editor-pane mj-code-editor {\n display: block;\n height: 100%;\n }\n\n /* ---- Diff-specific styles ---- */\n :host ::ng-deep .diff-pane .cm-mergeView .cm-changedLine {\n background: rgba(var(--mat-sys-primary-rgb, 99, 102, 241), 0.08);\n }\n\n :host ::ng-deep .diff-pane .cm-mergeView .cm-deletedChunk {\n background: rgba(220, 38, 38, 0.08);\n }\n\n /* ---- Empty state ---- */\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mat-sys-on-surface-variant);\n flex: 1;\n }\n\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n `]\n})\nexport class CodeEditorPanelComponent {\n ActiveTabIndex = 0;\n ViewMode: CodeViewMode = 'current';\n DiffExtensions: Extension[] = [];\n DiffChunkCount = 0;\n\n @ViewChild('diffEditor') set DiffEditorRef(ref: { view?: EditorView } | undefined) {\n if (ref?.view) {\n this.diffView = ref.view;\n this.updateChunkCount();\n }\n }\n private diffView: EditorView | null = null;\n\n constructor(\n public State: ComponentStudioStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n get ActiveSection(): CodeSection | null {\n const sections = this.State.CodeSections;\n if (sections.length === 0) return null;\n if (this.ActiveTabIndex >= sections.length) {\n this.ActiveTabIndex = 0;\n }\n return sections[this.ActiveTabIndex];\n }\n\n HasChanges(section: CodeSection): boolean {\n return section.code !== section.originalCode;\n }\n\n SelectTab(index: number): void {\n this.ActiveTabIndex = index;\n this.ViewMode = 'current';\n this.cdr.detectChanges();\n }\n\n SetViewMode(mode: CodeViewMode): void {\n this.ViewMode = mode;\n if (mode === 'diff') {\n this.buildDiffExtensions();\n }\n this.cdr.detectChanges();\n }\n\n OnCodeChanged(): void {\n this.State.IsEditingCode = true;\n }\n\n ApplyChanges(): void {\n this.State.ApplyCodeChanges();\n }\n\n CancelChanges(): void {\n this.State.InitializeEditors();\n this.ActiveTabIndex = 0;\n this.ViewMode = 'current';\n this.cdr.detectChanges();\n }\n\n CopyCode(): void {\n const section = this.ActiveSection;\n if (!section) return;\n\n const text = this.ViewMode === 'original' ? section.originalCode : section.code;\n navigator.clipboard.writeText(text).catch(err => {\n console.error('Failed to copy code to clipboard:', err);\n });\n }\n\n GoToNextChunk(): void {\n if (this.diffView) {\n goToNextChunk(this.diffView);\n }\n }\n\n GoToPreviousChunk(): void {\n if (this.diffView) {\n goToPreviousChunk(this.diffView);\n }\n }\n\n private updateChunkCount(): void {\n if (!this.diffView) {\n this.DiffChunkCount = 0;\n return;\n }\n // Schedule after the merge view has initialized\n Promise.resolve().then(() => {\n if (!this.diffView) return;\n const result = getChunks(this.diffView.state);\n this.DiffChunkCount = result ? result.chunks.length : 0;\n this.cdr.detectChanges();\n });\n }\n\n private buildDiffExtensions(): void {\n const section = this.ActiveSection;\n if (!section) {\n this.DiffExtensions = [];\n return;\n }\n\n this.DiffExtensions = unifiedMergeView({\n original: section.originalCode,\n highlightChanges: true,\n gutter: true\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"code-editor-panel.component.js","sourceRoot":"","sources":["../../../../src/ComponentStudio/components/editors/code-editor-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAqB,SAAS,EAAE,MAAM,eAAe,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;;;;;;;;;IAiBpF,wBAAiD;;;IAIjD,2BAAmD;;;;IARvD,kCAE+B;IAAvB,gNAAS,8BAAY,KAAC;IAC5B,+FAA4B;IAG5B,YACA;IAAA,kGAA2B;IAG7B,iBAAS;;;;;IATD,gEAAqC;IAE3C,cAEC;IAFD,kDAEC;IACD,cACA;IADA,iDACA;IAAA,cAEC;IAFD,wDAEC;;;;IAoBD,AADF,8BAAsB,eACK;IAAA,YAAgE;IAAA,iBAAO;IAChG,kCAAqH;IAA5F,6LAAS,0BAAmB,KAAC;IACpD,wBAAsC;IACxC,iBAAS;IACT,kCAA6G;IAApF,6LAAS,sBAAe,KAAC;IAChD,wBAAwC;IAE5C,AADE,iBAAS,EACL;;;IAPqB,eAAgE;IAAhE,mGAAgE;IACN,cAAiC;IAAjC,sDAAiC;IAGzC,eAAiC;IAAjC,sDAAiC;;;;IAW5G,AADF,+BAA4B,iBAC4C;IAAzB,6LAAS,qBAAc,KAAC;IACnE,wBAAiC;IAAC,uBACpC;IAAA,iBAAS;IACT,kCAAoE;IAA1B,6LAAS,sBAAe,KAAC;IACjE,wBACF;IACF,AADE,iBAAS,EACL;;IANgB,cAAwB;IAAxB,sCAAwB;IAGxB,eAAqB;IAArB,mCAAqB;;;;IAarC,AADF,+BAAyB,yBAMa;IAJlC,sVAAgC;IAIhC,6NAAiB,sBAAe,KAAC;IAErC,AADE,iBAAiB,EACb;;;IANF,cAAgC;IAAhC,yDAAgC;IAGhC,AADA,AADA,uCAAyB,uBACH,0CACmB;;;IAM7C,+BAAyB;IACvB,qCAIiB;IACnB,iBAAM;;;IAJF,cAAsC;IAEtC,AADA,AADA,2DAAsC,0BACb,kBACR;;;IAKrB,+BAAmC;IACjC,wCAMiB;IACnB,iBAAM;;;IALF,cAA8B;IAG9B,AADA,AADA,AADA,mDAA8B,0BACL,kBACR,qCACY;;;IAPnC,AATA,AAXA,mGAAmB,6EAWC,6EASJ;;;;IArBlB,iDAAA,SAAS,mBAAT,UAAU,mBAAV,MAAM,UAgCL;;;IAED,+BAAyB;IACvB,wBAAqC;IACrC,yBAAG;IAAA,gFAAgE;IACrE,AADqE,iBAAI,EACnE;;AA6NhB,MAAM,OAAO,wBAAwB;IAe1B;IACC;IAfV,cAAc,GAAG,CAAC,CAAC;IACnB,QAAQ,GAAiB,SAAS,CAAC;IACnC,cAAc,GAAgB,EAAE,CAAC;IACjC,cAAc,GAAG,CAAC,CAAC;IAEnB,IAA6B,aAAa,CAAC,GAAsC;QAC/E,IAAI,GAAG,EAAE,IAAI,EAAE,CAAC;YACd,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC;YACzB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IACO,QAAQ,GAAsB,IAAI,CAAC;IAE3C,YACS,KAAkC,EACjC,GAAsB;QADvB,UAAK,GAAL,KAAK,CAA6B;QACjC,QAAG,GAAH,GAAG,CAAmB;IAC7B,CAAC;IAEJ,IAAI,aAAa;QACf,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;QACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACvC,IAAI,IAAI,CAAC,cAAc,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC3C,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvC,CAAC;IAED,UAAU,CAAC,OAAoB;QAC7B,OAAO,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,YAAY,CAAC;IAC/C,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,WAAW,CAAC,IAAkB;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,aAAa;QACX,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;IAClC,CAAC;IAED,YAAY;QACV,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAChC,CAAC;IAED,aAAa;QACX,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC/B,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,QAAQ;QACN,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC;QACnC,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAChF,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;YAC9C,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,aAAa;QACX,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,gDAAgD;QAChD,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAC3B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC9C,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,mBAAmB;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,gBAAgB,CAAC;YACrC,QAAQ,EAAE,OAAO,CAAC,YAAY;YAC9B,gBAAgB,EAAE,IAAI;YACtB,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;IACL,CAAC;kHA7GU,wBAAwB;6DAAxB,wBAAwB;;;;;;YA7T/B,AAFF,8BAA+B,aAEH;YACxB,8FAYC;YACH,iBAAM;YAKF,AADF,AADF,8BAA0B,aACM,gBACsE;YAAjC,qGAAS,gBAAY,SAAS,CAAC,IAAC;YAC/F,yBACF;YAAA,iBAAS;YACT,iCAAoG;YAAlC,qGAAS,gBAAY,UAAU,CAAC,IAAC;YACjG,0BACF;YAAA,iBAAS;YACT,kCAA4F;YAA9B,sGAAS,gBAAY,MAAM,CAAC,IAAC;YACzF,wBAAwC;YAAC,uBAC3C;YACF,AADE,iBAAS,EACL;YACN,4FAA2B;YAW3B,2BAAoC;YACpC,mCAA6E;YAApD,sGAAS,cAAU,IAAC;YAC3C,yBAAgC;YAClC,iBAAS;YACT,6FAA2B;YAU7B,iBAAM;YAGN,gCAA8B;YAmC1B,AAlCF,kFAAqB,uEAkCZ;YAOb,AADE,iBAAM,EACF;;YAlGF,eAYC;YAZD,qCAYC;YAM0B,eAAuC;YAAvC,oDAAuC;YAGvC,eAAwC;YAAxC,qDAAwC;YAGxC,eAAoC;YAApC,iDAAoC;YAI/D,eAUC;YAVD,mDAUC;YAKD,eASC;YATD,mDASC;YAKD,eAuCC;YAvCD,6CAuCC;;;iFA4NI,wBAAwB;cAnUpC,SAAS;6BACI,KAAK,YACP,sBAAsB,YACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuGT;;kBA+NA,SAAS;mBAAC,YAAY;;kFANZ,wBAAwB","sourcesContent":["import { Component, ChangeDetectorRef, ViewChild } from '@angular/core';\nimport { Extension } from '@codemirror/state';\nimport { EditorView } from '@codemirror/view';\nimport { unifiedMergeView, getChunks, goToNextChunk, goToPreviousChunk } from '@codemirror/merge';\nimport { ComponentStudioStateService, CodeSection } from '../../services/component-studio-state.service';\n\ntype CodeViewMode = 'current' | 'original' | 'diff';\n\n@Component({\n standalone: false,\n selector: 'mj-code-editor-panel',\n template: `\n <div class=\"code-editor-panel\">\n <!-- Tab bar: one tab per code section -->\n <div class=\"code-tab-bar\">\n @for (section of State.CodeSections; track section.title; let i = $index) {\n <button class=\"code-tab\"\n [class.active]=\"ActiveTabIndex === i\"\n (click)=\"SelectTab(i)\">\n @if (section.isDependency) {\n <i class=\"fa-solid fa-puzzle-piece dep-icon\"></i>\n }\n {{ section.title }}\n @if (HasChanges(section)) {\n <span class=\"modified-dot\" title=\"Modified\"></span>\n }\n </button>\n }\n </div>\n\n <!-- Toolbar: view mode toggle + actions -->\n <div class=\"code-toolbar\">\n <div class=\"view-mode-toggle\">\n <button class=\"mode-btn\" [class.active]=\"ViewMode === 'current'\" (click)=\"SetViewMode('current')\">\n Current\n </button>\n <button class=\"mode-btn\" [class.active]=\"ViewMode === 'original'\" (click)=\"SetViewMode('original')\">\n Original\n </button>\n <button class=\"mode-btn\" [class.active]=\"ViewMode === 'diff'\" (click)=\"SetViewMode('diff')\">\n <i class=\"fa-solid fa-code-compare\"></i> Diff\n </button>\n </div>\n @if (ViewMode === 'diff') {\n <div class=\"diff-nav\">\n <span class=\"diff-count\">{{ DiffChunkCount }} change{{ DiffChunkCount !== 1 ? 's' : '' }}</span>\n <button class=\"icon-btn\" (click)=\"GoToPreviousChunk()\" title=\"Previous change (↑)\" [disabled]=\"DiffChunkCount === 0\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button class=\"icon-btn\" (click)=\"GoToNextChunk()\" title=\"Next change (↓)\" [disabled]=\"DiffChunkCount === 0\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n }\n <span class=\"toolbar-spacer\"></span>\n <button class=\"icon-btn\" (click)=\"CopyCode()\" title=\"Copy code to clipboard\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n @if (State.IsEditingCode) {\n <div class=\"action-buttons\">\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"ApplyChanges()\">\n <i class=\"fa-solid fa-check\"></i> Apply\n </button>\n <button kendoButton [themeColor]=\"'base'\" (click)=\"CancelChanges()\">\n Cancel\n </button>\n </div>\n }\n </div>\n\n <!-- Editor body -->\n <div class=\"code-editor-body\">\n @if (ActiveSection) {\n @switch (ViewMode) {\n @case ('current') {\n <div class=\"editor-pane\">\n <mj-code-editor\n [(ngModel)]=\"ActiveSection.code\"\n [language]=\"'javascript'\"\n [indentWithTab]=\"true\"\n [placeholder]=\"'Enter component code...'\"\n (ngModelChange)=\"OnCodeChanged()\">\n </mj-code-editor>\n </div>\n }\n @case ('original') {\n <div class=\"editor-pane\">\n <mj-code-editor\n [ngModel]=\"ActiveSection.originalCode\"\n [language]=\"'javascript'\"\n [readonly]=\"true\">\n </mj-code-editor>\n </div>\n }\n @case ('diff') {\n <div class=\"editor-pane diff-pane\">\n <mj-code-editor\n #diffEditor\n [ngModel]=\"ActiveSection.code\"\n [language]=\"'javascript'\"\n [readonly]=\"true\"\n [extensions]=\"DiffExtensions\">\n </mj-code-editor>\n </div>\n }\n }\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-file-code\"></i>\n <p>No code sections available. Select a component to view its code.</p>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .code-editor-panel {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n /* ---- Tab bar ---- */\n .code-tab-bar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n height: 36px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 2px;\n overflow-x: auto;\n }\n\n .code-tab {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n font-family: inherit;\n position: relative;\n }\n\n .code-tab:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .code-tab.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-weight: 600;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);\n }\n\n .dep-icon {\n font-size: 10px;\n color: var(--mj-brand-primary);\n }\n\n .modified-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-error);\n display: inline-block;\n margin-left: 2px;\n }\n\n /* ---- Toolbar ---- */\n .code-toolbar {\n display: flex;\n align-items: center;\n padding: 4px 8px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n gap: 8px;\n }\n\n .view-mode-toggle {\n display: inline-flex;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n .mode-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .mode-btn:not(:last-child) {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .mode-btn:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .mode-btn.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .mode-btn i {\n font-size: 10px;\n }\n\n .toolbar-spacer {\n flex: 1;\n }\n\n .icon-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--mj-text-secondary);\n cursor: pointer;\n font-size: 13px;\n transition: all 0.15s ease;\n }\n\n .icon-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n\n .diff-nav {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-left: 4px;\n }\n\n .diff-count {\n font-size: 11px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n padding: 0 4px;\n white-space: nowrap;\n }\n\n .icon-btn:disabled {\n opacity: 0.35;\n cursor: default;\n }\n\n /* ---- Editor body ---- */\n .code-editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-height: 0;\n }\n\n .editor-pane {\n flex: 1;\n overflow: hidden;\n min-height: 0;\n }\n\n .editor-pane mj-code-editor {\n display: block;\n height: 100%;\n }\n\n /* ---- Diff-specific styles ---- */\n :host ::ng-deep .diff-pane .cm-mergeView .cm-changedLine {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n }\n\n :host ::ng-deep .diff-pane .cm-mergeView .cm-deletedChunk {\n background: color-mix(in srgb, var(--mj-status-error) 8%, transparent);\n }\n\n /* ---- Empty state ---- */\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n `]\n})\nexport class CodeEditorPanelComponent {\n ActiveTabIndex = 0;\n ViewMode: CodeViewMode = 'current';\n DiffExtensions: Extension[] = [];\n DiffChunkCount = 0;\n\n @ViewChild('diffEditor') set DiffEditorRef(ref: { view?: EditorView } | undefined) {\n if (ref?.view) {\n this.diffView = ref.view;\n this.updateChunkCount();\n }\n }\n private diffView: EditorView | null = null;\n\n constructor(\n public State: ComponentStudioStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n get ActiveSection(): CodeSection | null {\n const sections = this.State.CodeSections;\n if (sections.length === 0) return null;\n if (this.ActiveTabIndex >= sections.length) {\n this.ActiveTabIndex = 0;\n }\n return sections[this.ActiveTabIndex];\n }\n\n HasChanges(section: CodeSection): boolean {\n return section.code !== section.originalCode;\n }\n\n SelectTab(index: number): void {\n this.ActiveTabIndex = index;\n this.ViewMode = 'current';\n this.cdr.detectChanges();\n }\n\n SetViewMode(mode: CodeViewMode): void {\n this.ViewMode = mode;\n if (mode === 'diff') {\n this.buildDiffExtensions();\n }\n this.cdr.detectChanges();\n }\n\n OnCodeChanged(): void {\n this.State.IsEditingCode = true;\n }\n\n ApplyChanges(): void {\n this.State.ApplyCodeChanges();\n }\n\n CancelChanges(): void {\n this.State.InitializeEditors();\n this.ActiveTabIndex = 0;\n this.ViewMode = 'current';\n this.cdr.detectChanges();\n }\n\n CopyCode(): void {\n const section = this.ActiveSection;\n if (!section) return;\n\n const text = this.ViewMode === 'original' ? section.originalCode : section.code;\n navigator.clipboard.writeText(text).catch(err => {\n console.error('Failed to copy code to clipboard:', err);\n });\n }\n\n GoToNextChunk(): void {\n if (this.diffView) {\n goToNextChunk(this.diffView);\n }\n }\n\n GoToPreviousChunk(): void {\n if (this.diffView) {\n goToPreviousChunk(this.diffView);\n }\n }\n\n private updateChunkCount(): void {\n if (!this.diffView) {\n this.DiffChunkCount = 0;\n return;\n }\n // Schedule after the merge view has initialized\n Promise.resolve().then(() => {\n if (!this.diffView) return;\n const result = getChunks(this.diffView.state);\n this.DiffChunkCount = result ? result.chunks.length : 0;\n this.cdr.detectChanges();\n });\n }\n\n private buildDiffExtensions(): void {\n const section = this.ActiveSection;\n if (!section) {\n this.DiffExtensions = [];\n return;\n }\n\n this.DiffExtensions = unifiedMergeView({\n original: section.originalCode,\n highlightChanges: true,\n gutter: true\n });\n }\n}\n"]}
|
|
@@ -158,7 +158,7 @@ export class DataRequirementsEditorComponent {
|
|
|
158
158
|
i0.ɵɵconditional(ctx.IsEditing ? 5 : -1);
|
|
159
159
|
i0.ɵɵadvance(2);
|
|
160
160
|
i0.ɵɵconditional(ctx.State.SelectedComponent ? 7 : 8);
|
|
161
|
-
} }, dependencies: [i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.ButtonComponent], styles: [".data-requirements-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--
|
|
161
|
+
} }, dependencies: [i2.NgControlStatus, i2.NgModel, i3.CodeEditorComponent, i4.ButtonComponent], styles: [".data-requirements-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n }\n .header-title[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n .header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 6px;\n color: var(--mj-text-secondary);\n }\n .action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n }\n .summary-bar[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 6px 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 12px;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n }\n .summary-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n .mode-badge[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n padding: 1px 8px;\n border-radius: 10px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 10px;\n }\n .editor-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n .json-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n }\n .json-editor-container[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n }\n .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n }\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }"] });
|
|
162
162
|
}
|
|
163
163
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DataRequirementsEditorComponent, [{
|
|
164
164
|
type: Component,
|
|
@@ -215,7 +215,7 @@ export class DataRequirementsEditorComponent {
|
|
|
215
215
|
}
|
|
216
216
|
</div>
|
|
217
217
|
</div>
|
|
218
|
-
`, styles: ["\n .data-requirements-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--
|
|
218
|
+
`, styles: ["\n .data-requirements-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n }\n .header-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n .header-title i {\n margin-right: 6px;\n color: var(--mj-text-secondary);\n }\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n .summary-bar {\n display: flex;\n gap: 12px;\n padding: 6px 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 12px;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n }\n .summary-item {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n .mode-badge {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n padding: 1px 8px;\n border-radius: 10px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 10px;\n }\n .editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n .json-editor-container {\n flex: 1;\n overflow: hidden;\n }\n .json-editor-container mj-code-editor {\n display: block;\n height: 100%;\n }\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n }\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n "] }]
|
|
219
219
|
}], () => [{ type: i1.ComponentStudioStateService }, { type: i0.ChangeDetectorRef }], null); })();
|
|
220
220
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(DataRequirementsEditorComponent, { className: "DataRequirementsEditorComponent", filePath: "src/ComponentStudio/components/editors/data-requirements-editor.component.ts", lineNumber: 148 }); })();
|
|
221
221
|
//# sourceMappingURL=data-requirements-editor.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-requirements-editor.component.js","sourceRoot":"","sources":["../../../../src/ComponentStudio/components/editors/data-requirements-editor.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef } from '@angular/core';\nimport { ComponentStudioStateService } from '../../services/component-studio-state.service';\nimport { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n@Component({\n standalone: false,\n selector: 'mj-data-requirements-editor',\n template: `\n <div class=\"data-requirements-editor\">\n <div class=\"editor-header\">\n <span class=\"header-title\">\n <i class=\"fa-solid fa-database\"></i>\n Data Requirements\n </span>\n @if (IsEditing) {\n <div class=\"action-buttons\">\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"ApplyChanges()\">\n <i class=\"fa-solid fa-check\"></i> Apply Changes\n </button>\n <button kendoButton [themeColor]=\"'base'\" (click)=\"CancelChanges()\">\n <i class=\"fa-solid fa-times\"></i> Cancel\n </button>\n </div>\n }\n </div>\n\n <div class=\"editor-body\">\n @if (State.SelectedComponent) {\n @if (HasDataRequirements) {\n <div class=\"summary-bar\">\n <span class=\"summary-item\">\n <i class=\"fa-solid fa-table\"></i>\n {{ EntityCount }} {{ EntityCount === 1 ? 'entity' : 'entities' }}\n </span>\n <span class=\"summary-item\">\n <i class=\"fa-solid fa-search\"></i>\n {{ QueryCount }} {{ QueryCount === 1 ? 'query' : 'queries' }}\n </span>\n <span class=\"summary-item mode-badge\">\n {{ DataMode }}\n </span>\n </div>\n }\n <div class=\"json-editor-container\">\n <mj-code-editor\n [(ngModel)]=\"EditableContent\"\n [language]=\"'json'\"\n [indentWithTab]=\"true\"\n [placeholder]=\"'Enter data requirements JSON...'\"\n (ngModelChange)=\"OnContentChanged()\">\n </mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-database\"></i>\n <p>Select a component to edit its data requirements.</p>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .data-requirements-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n background: var(--mat-sys-surface-container-lowest);\n flex-shrink: 0;\n }\n .header-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n }\n .header-title i {\n margin-right: 6px;\n color: var(--mat-sys-on-surface-variant);\n }\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n .summary-bar {\n display: flex;\n gap: 12px;\n padding: 6px 12px;\n background: var(--mat-sys-primary-container);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n font-size: 12px;\n color: var(--mat-sys-on-primary-container);\n flex-shrink: 0;\n }\n .summary-item {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n .mode-badge {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n padding: 1px 8px;\n border-radius: 10px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 10px;\n }\n .editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n .json-editor-container {\n flex: 1;\n overflow: hidden;\n }\n .json-editor-container mj-code-editor {\n display: block;\n height: 100%;\n }\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mat-sys-on-surface-variant);\n flex: 1;\n }\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n }\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n `]\n})\nexport class DataRequirementsEditorComponent {\n EditableContent: string = '';\n IsEditing: boolean = false;\n\n private _parsedRequirements: Record<string, unknown> | null = null;\n\n constructor(\n public State: ComponentStudioStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n get HasDataRequirements(): boolean {\n return this._parsedRequirements != null;\n }\n\n get EntityCount(): number {\n if (!this._parsedRequirements) return 0;\n const entities = this._parsedRequirements['entities'];\n return Array.isArray(entities) ? entities.length : 0;\n }\n\n get QueryCount(): number {\n if (!this._parsedRequirements) return 0;\n const queries = this._parsedRequirements['queries'];\n return Array.isArray(queries) ? queries.length : 0;\n }\n\n get DataMode(): string {\n if (!this._parsedRequirements) return '';\n return (this._parsedRequirements['mode'] as string) || 'views';\n }\n\n ngOnInit(): void {\n this.loadContent();\n this.State.StateChanged.subscribe(() => {\n this.loadContent();\n this.cdr.detectChanges();\n });\n }\n\n OnContentChanged(): void {\n this.IsEditing = true;\n this.parseContent();\n }\n\n ApplyChanges(): void {\n try {\n const spec: ComponentSpec = JSON.parse(this.State.EditableSpec);\n const dataReq = JSON.parse(this.EditableContent);\n spec.dataRequirements = dataReq;\n this.State.UpdateSpec(spec);\n this.IsEditing = false;\n } catch (error) {\n console.error('Error applying data requirements changes:', error);\n }\n }\n\n CancelChanges(): void {\n this.loadContent();\n this.IsEditing = false;\n this.cdr.detectChanges();\n }\n\n private loadContent(): void {\n try {\n const spec = JSON.parse(this.State.EditableSpec);\n const dataReq = spec.dataRequirements || { mode: 'views', entities: [], queries: [] };\n this.EditableContent = JSON.stringify(dataReq, null, 2);\n this.parseContent();\n } catch {\n this.EditableContent = '';\n this._parsedRequirements = null;\n }\n }\n\n private parseContent(): void {\n try {\n this._parsedRequirements = JSON.parse(this.EditableContent);\n } catch {\n this._parsedRequirements = null;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"data-requirements-editor.component.js","sourceRoot":"","sources":["../../../../src/ComponentStudio/components/editors/data-requirements-editor.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ChangeDetectorRef } from '@angular/core';\nimport { ComponentStudioStateService } from '../../services/component-studio-state.service';\nimport { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n@Component({\n standalone: false,\n selector: 'mj-data-requirements-editor',\n template: `\n <div class=\"data-requirements-editor\">\n <div class=\"editor-header\">\n <span class=\"header-title\">\n <i class=\"fa-solid fa-database\"></i>\n Data Requirements\n </span>\n @if (IsEditing) {\n <div class=\"action-buttons\">\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"ApplyChanges()\">\n <i class=\"fa-solid fa-check\"></i> Apply Changes\n </button>\n <button kendoButton [themeColor]=\"'base'\" (click)=\"CancelChanges()\">\n <i class=\"fa-solid fa-times\"></i> Cancel\n </button>\n </div>\n }\n </div>\n\n <div class=\"editor-body\">\n @if (State.SelectedComponent) {\n @if (HasDataRequirements) {\n <div class=\"summary-bar\">\n <span class=\"summary-item\">\n <i class=\"fa-solid fa-table\"></i>\n {{ EntityCount }} {{ EntityCount === 1 ? 'entity' : 'entities' }}\n </span>\n <span class=\"summary-item\">\n <i class=\"fa-solid fa-search\"></i>\n {{ QueryCount }} {{ QueryCount === 1 ? 'query' : 'queries' }}\n </span>\n <span class=\"summary-item mode-badge\">\n {{ DataMode }}\n </span>\n </div>\n }\n <div class=\"json-editor-container\">\n <mj-code-editor\n [(ngModel)]=\"EditableContent\"\n [language]=\"'json'\"\n [indentWithTab]=\"true\"\n [placeholder]=\"'Enter data requirements JSON...'\"\n (ngModelChange)=\"OnContentChanged()\">\n </mj-code-editor>\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-database\"></i>\n <p>Select a component to edit its data requirements.</p>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .data-requirements-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n }\n .header-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n }\n .header-title i {\n margin-right: 6px;\n color: var(--mj-text-secondary);\n }\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n .summary-bar {\n display: flex;\n gap: 12px;\n padding: 6px 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 12px;\n color: var(--mj-brand-primary);\n flex-shrink: 0;\n }\n .summary-item {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n .mode-badge {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n padding: 1px 8px;\n border-radius: 10px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 10px;\n }\n .editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n .json-editor-container {\n flex: 1;\n overflow: hidden;\n }\n .json-editor-container mj-code-editor {\n display: block;\n height: 100%;\n }\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n }\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n `]\n})\nexport class DataRequirementsEditorComponent {\n EditableContent: string = '';\n IsEditing: boolean = false;\n\n private _parsedRequirements: Record<string, unknown> | null = null;\n\n constructor(\n public State: ComponentStudioStateService,\n private cdr: ChangeDetectorRef\n ) {}\n\n get HasDataRequirements(): boolean {\n return this._parsedRequirements != null;\n }\n\n get EntityCount(): number {\n if (!this._parsedRequirements) return 0;\n const entities = this._parsedRequirements['entities'];\n return Array.isArray(entities) ? entities.length : 0;\n }\n\n get QueryCount(): number {\n if (!this._parsedRequirements) return 0;\n const queries = this._parsedRequirements['queries'];\n return Array.isArray(queries) ? queries.length : 0;\n }\n\n get DataMode(): string {\n if (!this._parsedRequirements) return '';\n return (this._parsedRequirements['mode'] as string) || 'views';\n }\n\n ngOnInit(): void {\n this.loadContent();\n this.State.StateChanged.subscribe(() => {\n this.loadContent();\n this.cdr.detectChanges();\n });\n }\n\n OnContentChanged(): void {\n this.IsEditing = true;\n this.parseContent();\n }\n\n ApplyChanges(): void {\n try {\n const spec: ComponentSpec = JSON.parse(this.State.EditableSpec);\n const dataReq = JSON.parse(this.EditableContent);\n spec.dataRequirements = dataReq;\n this.State.UpdateSpec(spec);\n this.IsEditing = false;\n } catch (error) {\n console.error('Error applying data requirements changes:', error);\n }\n }\n\n CancelChanges(): void {\n this.loadContent();\n this.IsEditing = false;\n this.cdr.detectChanges();\n }\n\n private loadContent(): void {\n try {\n const spec = JSON.parse(this.State.EditableSpec);\n const dataReq = spec.dataRequirements || { mode: 'views', entities: [], queries: [] };\n this.EditableContent = JSON.stringify(dataReq, null, 2);\n this.parseContent();\n } catch {\n this.EditableContent = '';\n this._parsedRequirements = null;\n }\n }\n\n private parseContent(): void {\n try {\n this._parsedRequirements = JSON.parse(this.EditableContent);\n } catch {\n this._parsedRequirements = null;\n }\n }\n}\n"]}
|
|
@@ -185,7 +185,7 @@ export class RequirementsEditorComponent {
|
|
|
185
185
|
i0.ɵɵclassProp("active", ctx.ViewMode === "edit");
|
|
186
186
|
i0.ɵɵadvance(4);
|
|
187
187
|
i0.ɵɵconditional(ctx.State.SelectedComponent ? 15 : 16);
|
|
188
|
-
} }, dependencies: [i2.NgClass, i3.NgControlStatus, i3.NgModel, i4.CodeEditorComponent, i5.ButtonComponent, i6.MarkdownComponent, i2.LowerCasePipe], styles: [".requirements-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--
|
|
188
|
+
} }, dependencies: [i2.NgClass, i3.NgControlStatus, i3.NgModel, i4.CodeEditorComponent, i5.ButtonComponent, i6.MarkdownComponent, i2.LowerCasePipe], styles: [".requirements-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n gap: 8px;\n }\n\n .header-title[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n }\n\n .header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 6px;\n color: var(--mj-brand-primary);\n }\n\n .header-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .action-buttons[_ngcontent-%COMP%] {\n display: flex;\n gap: 6px;\n }\n\n .action-btn[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .mode-toggle[_ngcontent-%COMP%] {\n display: inline-flex;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n .mode-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .mode-btn[_ngcontent-%COMP%]:not(:last-child) {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .mode-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .mode-btn.active[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .mode-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n\n .editor-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .preview-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: auto;\n padding: 16px 20px;\n }\n\n .code-editor-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n }\n\n .code-editor-container[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n }\n\n .empty-preview[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n }\n\n .empty-preview[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-preview[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 12px;\n font-size: 13px;\n }\n\n .edit-link[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .edit-link[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n }\n\n .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }"] });
|
|
189
189
|
}
|
|
190
190
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RequirementsEditorComponent, [{
|
|
191
191
|
type: Component,
|
|
@@ -253,7 +253,7 @@ export class RequirementsEditorComponent {
|
|
|
253
253
|
}
|
|
254
254
|
</div>
|
|
255
255
|
</div>
|
|
256
|
-
`, styles: ["\n .requirements-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--
|
|
256
|
+
`, styles: ["\n .requirements-editor {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n .editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n gap: 8px;\n }\n\n .header-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n }\n\n .header-title i {\n margin-right: 6px;\n color: var(--mj-brand-primary);\n }\n\n .header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .action-buttons {\n display: flex;\n gap: 6px;\n }\n\n .action-btn {\n font-size: 12px;\n }\n\n .mode-toggle {\n display: inline-flex;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n .mode-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n background: transparent;\n color: var(--mj-text-secondary);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .mode-btn:not(:last-child) {\n border-right: 1px solid var(--mj-border-default);\n }\n\n .mode-btn:hover {\n background: var(--mj-bg-surface-sunken);\n }\n\n .mode-btn.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n }\n\n .mode-btn i {\n font-size: 10px;\n }\n\n .editor-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .preview-container {\n flex: 1;\n overflow: auto;\n padding: 16px 20px;\n }\n\n .code-editor-container {\n flex: 1;\n overflow: hidden;\n }\n\n .code-editor-container mj-code-editor {\n display: block;\n height: 100%;\n }\n\n .empty-preview {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n }\n\n .empty-preview i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-preview p {\n margin: 0 0 12px;\n font-size: 13px;\n }\n\n .edit-link {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 6px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: transparent;\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n font-family: inherit;\n }\n\n .edit-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n }\n\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n color: var(--mj-text-secondary);\n flex: 1;\n }\n\n .empty-state i {\n font-size: 32px;\n margin-bottom: 12px;\n opacity: 0.4;\n }\n\n .empty-state p {\n margin: 0;\n font-size: 13px;\n text-align: center;\n }\n "] }]
|
|
257
257
|
}], () => [{ type: i1.ComponentStudioStateService }, { type: i0.ChangeDetectorRef }], { Field: [{
|
|
258
258
|
type: Input
|
|
259
259
|
}], Title: [{
|