@memberjunction/ng-dashboards 5.10.1 → 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.
Files changed (231) hide show
  1. package/dist/AI/components/agents/agent-configuration.component.d.ts +34 -2
  2. package/dist/AI/components/agents/agent-configuration.component.d.ts.map +1 -1
  3. package/dist/AI/components/agents/agent-configuration.component.js +586 -223
  4. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  5. package/dist/AI/components/agents/agent-editor.component.js +2 -2
  6. package/dist/AI/components/agents/agent-filter-panel.component.d.ts +8 -0
  7. package/dist/AI/components/agents/agent-filter-panel.component.d.ts.map +1 -1
  8. package/dist/AI/components/agents/agent-filter-panel.component.js +85 -52
  9. package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
  10. package/dist/AI/components/charts/performance-heatmap.component.d.ts +1 -0
  11. package/dist/AI/components/charts/performance-heatmap.component.d.ts.map +1 -1
  12. package/dist/AI/components/charts/performance-heatmap.component.js +27 -5
  13. package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -1
  14. package/dist/AI/components/charts/time-series-chart.component.d.ts +5 -0
  15. package/dist/AI/components/charts/time-series-chart.component.d.ts.map +1 -1
  16. package/dist/AI/components/charts/time-series-chart.component.js +23 -8
  17. package/dist/AI/components/charts/time-series-chart.component.js.map +1 -1
  18. package/dist/AI/components/execution-monitoring.component.js +2 -2
  19. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  20. package/dist/AI/components/models/model-management.component.js +2 -2
  21. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
  22. package/dist/AI/components/prompts/prompt-filter-panel.component.js +2 -2
  23. package/dist/AI/components/prompts/prompt-management.component.js +3 -3
  24. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  25. package/dist/AI/components/prompts/prompt-version-control.component.js +2 -2
  26. package/dist/AI/components/requests/agent-requests-resource.component.d.ts +83 -0
  27. package/dist/AI/components/requests/agent-requests-resource.component.d.ts.map +1 -0
  28. package/dist/AI/components/requests/agent-requests-resource.component.js +547 -0
  29. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -0
  30. package/dist/AI/components/system/system-config-filter-panel.component.js +2 -2
  31. package/dist/AI/components/system/system-configuration.component.js +2 -2
  32. package/dist/AI/components/widgets/kpi-card.component.js +7 -7
  33. package/dist/AI/components/widgets/kpi-card.component.js.map +1 -1
  34. package/dist/AI/components/widgets/live-execution-widget.component.d.ts.map +1 -1
  35. package/dist/AI/components/widgets/live-execution-widget.component.js +6 -6
  36. package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -1
  37. package/dist/AI/index.d.ts +1 -0
  38. package/dist/AI/index.d.ts.map +1 -1
  39. package/dist/AI/index.js +2 -0
  40. package/dist/AI/index.js.map +1 -1
  41. package/dist/APIKeys/api-applications-panel.component.js +3 -3
  42. package/dist/APIKeys/api-applications-panel.component.js.map +1 -1
  43. package/dist/APIKeys/api-key-create-dialog.component.js +3 -3
  44. package/dist/APIKeys/api-key-create-dialog.component.js.map +1 -1
  45. package/dist/APIKeys/api-key-edit-panel.component.js +1 -1
  46. package/dist/APIKeys/api-key-edit-panel.component.js.map +1 -1
  47. package/dist/APIKeys/api-key-list.component.js +3 -3
  48. package/dist/APIKeys/api-key-list.component.js.map +1 -1
  49. package/dist/APIKeys/api-keys-resource.component.js +1 -1
  50. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  51. package/dist/APIKeys/api-scopes-panel.component.js +2 -2
  52. package/dist/APIKeys/api-usage-panel.component.js +2 -2
  53. package/dist/Actions/components/actions-overview.component.js +2 -2
  54. package/dist/Actions/components/execution-monitoring.component.js +2 -2
  55. package/dist/Actions/components/explorer/action-breadcrumb.component.js +2 -2
  56. package/dist/Actions/components/explorer/action-card.component.js +2 -2
  57. package/dist/Actions/components/explorer/action-explorer.component.js +2 -2
  58. package/dist/Actions/components/explorer/action-list-item.component.js +2 -2
  59. package/dist/Actions/components/explorer/action-toolbar.component.js +2 -2
  60. package/dist/Actions/components/explorer/action-tree-panel.component.js +2 -2
  61. package/dist/Actions/components/explorer/new-action-panel.component.js +2 -2
  62. package/dist/Actions/components/explorer/new-action-panel.component.js.map +1 -1
  63. package/dist/Actions/components/explorer/new-category-panel.component.js +2 -2
  64. package/dist/Actions/components/explorer/new-category-panel.component.js.map +1 -1
  65. package/dist/Communication/communication-dashboard.component.js +2 -2
  66. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  67. package/dist/Communication/communication-logs-resource.component.js +3 -3
  68. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  69. package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
  70. package/dist/Communication/communication-monitor-resource.component.js +5 -5
  71. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  72. package/dist/Communication/communication-providers-resource.component.d.ts.map +1 -1
  73. package/dist/Communication/communication-providers-resource.component.js +3 -3
  74. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  75. package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
  76. package/dist/Communication/communication-runs-resource.component.js +3 -3
  77. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  78. package/dist/Communication/communication-templates-resource.component.js +2 -2
  79. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  80. package/dist/ComponentStudio/component-studio-dashboard.component.js +2 -2
  81. package/dist/ComponentStudio/components/ai-assistant/ai-assistant-panel.component.js +2 -2
  82. package/dist/ComponentStudio/components/artifact-load-dialog.component.js +2 -2
  83. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -2
  84. package/dist/ComponentStudio/components/browser/component-browser.component.js +2 -2
  85. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js +2 -2
  86. package/dist/ComponentStudio/components/editors/code-editor-panel.component.js.map +1 -1
  87. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js +2 -2
  88. package/dist/ComponentStudio/components/editors/data-requirements-editor.component.js.map +1 -1
  89. package/dist/ComponentStudio/components/editors/requirements-editor.component.js +2 -2
  90. package/dist/ComponentStudio/components/editors/requirements-editor.component.js.map +1 -1
  91. package/dist/ComponentStudio/components/editors/spec-editor.component.js +2 -2
  92. package/dist/ComponentStudio/components/editors/spec-editor.component.js.map +1 -1
  93. package/dist/ComponentStudio/components/new-component-dialog/new-component-dialog.component.js +2 -2
  94. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js +2 -2
  95. package/dist/ComponentStudio/components/save-version-dialog/save-version-dialog.component.js.map +1 -1
  96. package/dist/ComponentStudio/components/text-import-dialog.component.js +2 -2
  97. package/dist/ComponentStudio/components/text-import-dialog.component.js.map +1 -1
  98. package/dist/ComponentStudio/components/workspace/component-preview.component.js +2 -2
  99. package/dist/ComponentStudio/components/workspace/editor-tabs.component.js +2 -2
  100. package/dist/ComponentStudio/components/workspace/editor-tabs.component.js.map +1 -1
  101. package/dist/Credentials/components/credentials-audit-resource.component.js +9 -9
  102. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  103. package/dist/Credentials/components/credentials-categories-resource.component.d.ts.map +1 -1
  104. package/dist/Credentials/components/credentials-categories-resource.component.js +11 -3
  105. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  106. package/dist/Credentials/components/credentials-list-resource.component.js +2 -2
  107. package/dist/Credentials/components/credentials-overview-resource.component.d.ts.map +1 -1
  108. package/dist/Credentials/components/credentials-overview-resource.component.js +12 -11
  109. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  110. package/dist/Credentials/components/credentials-types-resource.component.js +9 -9
  111. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  112. package/dist/Credentials/credentials-dashboard.component.js +2 -2
  113. package/dist/DashboardBrowser/dashboard-browser-resource.component.js +2 -2
  114. package/dist/DashboardBrowser/dashboard-share-dialog.component.js +2 -2
  115. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +2 -2
  116. package/dist/DataExplorer/components/navigation-panel/navigation-panel.component.js +2 -2
  117. package/dist/DataExplorer/components/view-selector/view-selector.component.js +2 -2
  118. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +6 -2
  119. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  120. package/dist/DataExplorer/data-explorer-dashboard.component.js +26 -8
  121. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  122. package/dist/Home/home-dashboard.component.js +2 -2
  123. package/dist/Integration/components/activity/activity.component.d.ts +1 -1
  124. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  125. package/dist/Integration/components/activity/activity.component.js +5 -5
  126. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  127. package/dist/Integration/components/connections/connections.component.d.ts +31 -2
  128. package/dist/Integration/components/connections/connections.component.d.ts.map +1 -1
  129. package/dist/Integration/components/connections/connections.component.js +753 -412
  130. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  131. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js +3 -3
  132. package/dist/Integration/components/mapping-workspace/mapping-workspace.component.js.map +1 -1
  133. package/dist/Integration/components/overview/overview.component.d.ts +0 -1
  134. package/dist/Integration/components/overview/overview.component.d.ts.map +1 -1
  135. package/dist/Integration/components/overview/overview.component.js +3 -6
  136. package/dist/Integration/components/overview/overview.component.js.map +1 -1
  137. package/dist/Integration/components/pipelines/pipelines.component.js +3 -3
  138. package/dist/Integration/components/pipelines/pipelines.component.js.map +1 -1
  139. package/dist/Integration/components/schedules/schedules.component.d.ts +20 -0
  140. package/dist/Integration/components/schedules/schedules.component.d.ts.map +1 -1
  141. package/dist/Integration/components/schedules/schedules.component.js +97 -5
  142. package/dist/Integration/components/schedules/schedules.component.js.map +1 -1
  143. package/dist/Integration/components/visual-editor/visual-editor.component.js +2 -2
  144. package/dist/Integration/components/widgets/integration-card.component.d.ts.map +1 -1
  145. package/dist/Integration/components/widgets/integration-card.component.js +5 -1
  146. package/dist/Integration/components/widgets/integration-card.component.js.map +1 -1
  147. package/dist/Integration/components/widgets/run-history-panel.component.js +2 -2
  148. package/dist/Integration/components/widgets/run-history-panel.component.js.map +1 -1
  149. package/dist/Integration/integration.module.d.ts +2 -1
  150. package/dist/Integration/integration.module.d.ts.map +1 -1
  151. package/dist/Integration/integration.module.js +7 -3
  152. package/dist/Integration/integration.module.js.map +1 -1
  153. package/dist/Integration/services/integration-data.service.d.ts +27 -2
  154. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  155. package/dist/Integration/services/integration-data.service.js +107 -4
  156. package/dist/Integration/services/integration-data.service.js.map +1 -1
  157. package/dist/Lists/components/lists-browse-resource.component.js +2 -2
  158. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  159. package/dist/Lists/components/lists-categories-resource.component.js +2 -2
  160. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  161. package/dist/Lists/components/lists-my-lists-resource.component.js +2 -2
  162. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  163. package/dist/Lists/components/lists-operations-resource.component.js +2 -2
  164. package/dist/Lists/components/lists-operations-resource.component.js.map +1 -1
  165. package/dist/Lists/components/venn-diagram/venn-diagram.component.js +3 -3
  166. package/dist/Lists/components/venn-diagram/venn-diagram.component.js.map +1 -1
  167. package/dist/MCP/components/mcp-connection-dialog.component.js +2 -2
  168. package/dist/MCP/components/mcp-log-detail-panel.component.js +2 -2
  169. package/dist/MCP/components/mcp-log-detail-panel.component.js.map +1 -1
  170. package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
  171. package/dist/MCP/components/mcp-test-tool-dialog.component.js +2 -2
  172. package/dist/MCP/components/mcp-test-tool-dialog.component.js.map +1 -1
  173. package/dist/MCP/mcp-dashboard.component.js +2 -2
  174. package/dist/MCP/mcp-filter-panel.component.js +2 -2
  175. package/dist/QueryBrowser/query-browser-resource.component.d.ts +55 -1
  176. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  177. package/dist/QueryBrowser/query-browser-resource.component.js +664 -199
  178. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  179. package/dist/Scheduling/components/index.d.ts +0 -1
  180. package/dist/Scheduling/components/index.d.ts.map +1 -1
  181. package/dist/Scheduling/components/index.js +0 -1
  182. package/dist/Scheduling/components/index.js.map +1 -1
  183. package/dist/Scheduling/components/scheduling-activity.component.js +2 -2
  184. package/dist/Scheduling/components/scheduling-jobs.component.d.ts +6 -9
  185. package/dist/Scheduling/components/scheduling-jobs.component.d.ts.map +1 -1
  186. package/dist/Scheduling/components/scheduling-jobs.component.js +118 -110
  187. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  188. package/dist/Scheduling/components/scheduling-overview.component.js +3 -3
  189. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  190. package/dist/Scheduling/scheduling-dashboard.component.js +2 -2
  191. package/dist/SystemDiagnostics/system-diagnostics.component.js +4 -4
  192. package/dist/SystemDiagnostics/system-diagnostics.component.js.map +1 -1
  193. package/dist/Testing/components/testing-analytics.component.js +2 -2
  194. package/dist/Testing/components/testing-analytics.component.js.map +1 -1
  195. package/dist/Testing/components/testing-dashboard-tab.component.js +4 -4
  196. package/dist/Testing/components/testing-dashboard-tab.component.js.map +1 -1
  197. package/dist/Testing/components/testing-explorer.component.js +2 -2
  198. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  199. package/dist/Testing/components/testing-review.component.d.ts.map +1 -1
  200. package/dist/Testing/components/testing-review.component.js +5 -5
  201. package/dist/Testing/components/testing-review.component.js.map +1 -1
  202. package/dist/Testing/components/testing-runs.component.js +2 -2
  203. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  204. package/dist/Testing/components/widgets/oracle-breakdown-table.component.js +2 -2
  205. package/dist/Testing/components/widgets/oracle-breakdown-table.component.js.map +1 -1
  206. package/dist/Testing/components/widgets/suite-tree.component.js +4 -4
  207. package/dist/Testing/components/widgets/suite-tree.component.js.map +1 -1
  208. package/dist/Testing/components/widgets/test-run-detail-panel.component.js +2 -2
  209. package/dist/Testing/components/widgets/test-run-detail-panel.component.js.map +1 -1
  210. package/dist/Testing/testing-dashboard.component.js +2 -2
  211. package/dist/VersionHistory/components/diff-resource.component.js +2 -2
  212. package/dist/VersionHistory/components/graph-resource.component.js +2 -2
  213. package/dist/VersionHistory/components/labels-resource.component.js +3 -3
  214. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  215. package/dist/VersionHistory/components/restore-resource.component.js +3 -3
  216. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  217. package/dist/__tests__/integration-data-service.test.js +1 -0
  218. package/dist/__tests__/integration-data-service.test.js.map +1 -1
  219. package/dist/module.d.ts +52 -49
  220. package/dist/module.d.ts.map +1 -1
  221. package/dist/module.js +25 -6
  222. package/dist/module.js.map +1 -1
  223. package/dist/public-api.d.ts +1 -1
  224. package/dist/public-api.d.ts.map +1 -1
  225. package/dist/public-api.js +1 -1
  226. package/dist/public-api.js.map +1 -1
  227. package/package.json +42 -40
  228. package/dist/Scheduling/components/job-slideout.component.d.ts +0 -45
  229. package/dist/Scheduling/components/job-slideout.component.d.ts.map +0 -1
  230. package/dist/Scheduling/components/job-slideout.component.js +0 -459
  231. package/dist/Scheduling/components/job-slideout.component.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"communication-runs-resource.component.js","sourceRoot":"","sources":["../../src/Communication/communication-runs-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ResourceData, MJCommunicationRunEntity } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunView } from '@memberjunction/core';\n@RegisterClass(BaseResourceComponent, 'CommunicationRunsResource')\n@Component({\n standalone: false,\n selector: 'mj-communication-runs-resource',\n template: `\n <div class=\"runs-wrapper\">\n <div class=\"card\">\n <div class=\"card-header\">\n <h3><i class=\"fa-solid fa-play-circle\"></i> Bulk Communication Runs</h3>\n <div class=\"header-actions\">\n <button class=\"tb-btn\" (click)=\"loadData()\">\n <i class=\"fa-solid fa-rotate\" [class.spinning]=\"isLoading\"></i> Refresh\n </button>\n </div>\n </div>\n <div class=\"card-body no-padding\">\n <!-- SUMMARY STATS -->\n <div class=\"runs-summary\">\n <div class=\"run-stat-card info\">\n <div class=\"run-stat-value\">{{summary.active}}</div>\n <div class=\"run-stat-label\">Active Runs</div>\n </div>\n <div class=\"run-stat-card success\">\n <div class=\"run-stat-value\">{{summary.completed}}</div>\n <div class=\"run-stat-label\">Completed (24h)</div>\n </div>\n <div class=\"run-stat-card neutral\">\n <div class=\"run-stat-value\">{{summary.successRate}}%</div>\n <div class=\"run-stat-label\">Success Rate</div>\n </div>\n </div>\n \n <!-- TIMELINE -->\n <div class=\"run-timeline\">\n @for (run of runs; track run) {\n <div class=\"run-entry\">\n <div class=\"run-timeline-dot\" [ngClass]=\"getRunDotClass(run.Status)\"></div>\n <div class=\"run-entry-content\">\n <div class=\"run-entry-header\">\n <span class=\"run-entry-title\">Run #{{run.ID.substring(0, 8)}}</span>\n <span class=\"run-status-badge\" [ngClass]=\"getStatusClass(run.Status)\">\n {{run.Status}}\n </span>\n </div>\n <div class=\"run-entry-meta\">\n <span><i class=\"fa-solid fa-user\"></i> {{run.User || 'System'}}</span>\n <span><i class=\"fa-solid fa-clock\"></i> {{run.StartedAt | date:'medium'}}</span>\n @if (run.EndedAt) {\n <span><i class=\"fa-solid fa-flag-checkered\"></i> {{run.EndedAt | date:'shortTime'}}</span>\n }\n </div>\n @if (run.Comments) {\n <div class=\"run-entry-comments\">\n {{run.Comments}}\n </div>\n }\n </div>\n </div>\n }\n \n @if (runs.length === 0 && !isLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-play-circle\"></i>\n <p>No communication runs found</p>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n `,\n styles: [`\n .runs-wrapper {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mat-sys-surface-container);\n }\n .card {\n background: var(--mat-sys-surface-container-lowest);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium, 12px);\n overflow: hidden;\n }\n .card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px 12px;\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n }\n .card-header h3 {\n font-size: 13px; font-weight: 700;\n color: var(--mat-sys-on-surface);\n display: flex; align-items: center; gap: 8px;\n margin: 0;\n }\n .card-header h3 i {\n color: var(--mat-sys-on-surface-variant); font-size: 12px;\n }\n .header-actions { display: flex; gap: 8px; }\n\n .tb-btn {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 6px 12px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface-container-lowest);\n color: var(--mat-sys-on-surface-variant);\n font-size: 12px; font-weight: 500;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn:hover {\n background: var(--mat-sys-surface-container-high);\n border-color: var(--mat-sys-outline);\n color: var(--mat-sys-on-surface);\n }\n .tb-btn i { font-size: 12px; }\n\n @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }\n .spinning { animation: spin 1s linear infinite; }\n\n .card-body.no-padding { padding: 0; }\n\n /* SUMMARY */\n .runs-summary {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 16px;\n padding: 20px;\n }\n .run-stat-card {\n border-radius: var(--mat-sys-corner-medium, 12px);\n padding: 16px 20px;\n text-align: center;\n }\n .run-stat-card.info { background: #ddf4ff; }\n .run-stat-card.success { background: #d4f8e0; }\n .run-stat-card.neutral { background: var(--mat-sys-surface-container-low); }\n\n .run-stat-value {\n font-size: 24px; font-weight: 800;\n color: var(--mat-sys-on-surface);\n }\n .run-stat-card.info .run-stat-value { color: #0969da; }\n .run-stat-card.success .run-stat-value { color: #1b873f; }\n\n .run-stat-label {\n font-size: 11px; font-weight: 600;\n text-transform: uppercase; letter-spacing: 0.5px;\n color: var(--mat-sys-on-surface-variant);\n margin-top: 2px;\n }\n\n /* TIMELINE */\n .run-timeline { padding: 8px 20px 20px; }\n .run-entry {\n display: flex; gap: 16px;\n padding: 16px 0;\n border-bottom: 1px solid var(--mat-sys-surface-container);\n align-items: flex-start;\n }\n .run-entry:last-child { border-bottom: none; }\n\n .run-timeline-dot {\n width: 12px; height: 12px;\n border-radius: 50%;\n margin-top: 4px; flex-shrink: 0;\n }\n .run-timeline-dot.complete { background: #1b873f; }\n .run-timeline-dot.failed { background: #cf222e; }\n .run-timeline-dot.in-progress {\n background: #0969da;\n animation: pulse-dot 1.5s ease-in-out infinite;\n }\n .run-timeline-dot.pending { background: #9a6700; }\n\n @keyframes pulse-dot {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(9,105,218,0.4); }\n 50% { box-shadow: 0 0 0 6px rgba(9,105,218,0); }\n }\n\n .run-entry-content { flex: 1; }\n .run-entry-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .run-entry-title {\n font-size: 13px; font-weight: 600;\n color: var(--mat-sys-on-surface);\n }\n .run-status-badge {\n font-size: 10px; font-weight: 700;\n text-transform: uppercase; letter-spacing: 0.3px;\n padding: 3px 8px;\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n }\n .run-status-badge.complete { background: #d4f8e0; color: #1b873f; }\n .run-status-badge.failed { background: #ffdce0; color: #cf222e; }\n .run-status-badge.pending { background: #fff0c7; color: #9a6700; }\n .run-status-badge.in-progress { background: #ddf4ff; color: #0969da; }\n\n .run-entry-meta {\n font-size: 11px;\n color: var(--mat-sys-on-surface-variant);\n margin-top: 4px;\n display: flex; align-items: center; gap: 12px;\n }\n .run-entry-meta span {\n display: flex; align-items: center; gap: 4px;\n }\n .run-entry-meta i { font-size: 10px; }\n\n .run-entry-comments {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n margin-top: 6px;\n font-style: italic;\n }\n\n /* EMPTY STATE */\n .empty-state {\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 48px 0; color: var(--mat-sys-on-surface-variant);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n `]\n})\nexport class CommunicationRunsResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public runs: MJCommunicationRunEntity[] = [];\n public isLoading = false;\n public summary = {\n active: 0,\n completed: 0,\n successRate: 0\n };\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void { }\n\n public async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.detectChanges();\n\n const rv = new RunView();\n const yesterday = new Date();\n yesterday.setDate(yesterday.getDate() - 1);\n const yesterdayIso = yesterday.toISOString();\n\n const [runsResult, activeResult, completedResult, failedResult] = await Promise.all([\n rv.RunView<MJCommunicationRunEntity>({\n EntityName: 'MJ: Communication Runs',\n OrderBy: 'StartedAt DESC',\n MaxRows: 50,\n ResultType: 'entity_object'\n }),\n rv.RunView({\n EntityName: 'MJ: Communication Runs',\n ExtraFilter: `Status = 'In-Progress'`,\n ResultType: 'count_only'\n }),\n rv.RunView({\n EntityName: 'MJ: Communication Runs',\n ExtraFilter: `EndedAt >= '${yesterdayIso}' AND Status = 'Complete'`,\n ResultType: 'count_only'\n }),\n rv.RunView({\n EntityName: 'MJ: Communication Runs',\n ExtraFilter: `EndedAt >= '${yesterdayIso}' AND Status = 'Failed'`,\n ResultType: 'count_only'\n })\n ]);\n\n if (runsResult.Success) {\n this.runs = runsResult.Results;\n }\n\n if (activeResult.Success) this.summary.active = activeResult.TotalRowCount;\n if (completedResult.Success) this.summary.completed = completedResult.TotalRowCount;\n\n const totalCompleted = this.summary.completed + (failedResult.Success ? failedResult.TotalRowCount : 0);\n this.summary.successRate = totalCompleted > 0\n ? Math.round((this.summary.completed / totalCompleted) * 100)\n : 100;\n\n } catch (error) {\n console.error('Error loading runs:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n public getRunDotClass(status: string): string {\n const s = (status || '').toLowerCase();\n if (s === 'complete') return 'complete';\n if (s === 'failed') return 'failed';\n if (s === 'in-progress') return 'in-progress';\n return 'pending';\n }\n\n public getStatusClass(status: string): string {\n const s = (status || '').toLowerCase();\n if (s === 'complete') return 'complete';\n if (s === 'failed') return 'failed';\n if (s === 'in-progress') return 'in-progress';\n return 'pending';\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Bulk Runs';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-play-circle';\n }\n}\n"]}
1
+ {"version":3,"file":"communication-runs-resource.component.js","sourceRoot":"","sources":["../../src/Communication/communication-runs-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ResourceData, MJCommunicationRunEntity } from '@memberjunction/core-entities';\nimport { RegisterClass } from '@memberjunction/global';\nimport { BaseResourceComponent } from '@memberjunction/ng-shared';\nimport { RunView } from '@memberjunction/core';\n@RegisterClass(BaseResourceComponent, 'CommunicationRunsResource')\n@Component({\n standalone: false,\n selector: 'mj-communication-runs-resource',\n template: `\n <div class=\"runs-wrapper\">\n <div class=\"card\">\n <div class=\"card-header\">\n <h3><i class=\"fa-solid fa-play-circle\"></i> Bulk Communication Runs</h3>\n <div class=\"header-actions\">\n <button class=\"tb-btn\" (click)=\"loadData()\">\n <i class=\"fa-solid fa-rotate\" [class.spinning]=\"isLoading\"></i> Refresh\n </button>\n </div>\n </div>\n <div class=\"card-body no-padding\">\n <!-- SUMMARY STATS -->\n <div class=\"runs-summary\">\n <div class=\"run-stat-card info\">\n <div class=\"run-stat-value\">{{summary.active}}</div>\n <div class=\"run-stat-label\">Active Runs</div>\n </div>\n <div class=\"run-stat-card success\">\n <div class=\"run-stat-value\">{{summary.completed}}</div>\n <div class=\"run-stat-label\">Completed (24h)</div>\n </div>\n <div class=\"run-stat-card neutral\">\n <div class=\"run-stat-value\">{{summary.successRate}}%</div>\n <div class=\"run-stat-label\">Success Rate</div>\n </div>\n </div>\n \n <!-- TIMELINE -->\n <div class=\"run-timeline\">\n @for (run of runs; track run) {\n <div class=\"run-entry\">\n <div class=\"run-timeline-dot\" [ngClass]=\"getRunDotClass(run.Status)\"></div>\n <div class=\"run-entry-content\">\n <div class=\"run-entry-header\">\n <span class=\"run-entry-title\">Run #{{run.ID.substring(0, 8)}}</span>\n <span class=\"run-status-badge\" [ngClass]=\"getStatusClass(run.Status)\">\n {{run.Status}}\n </span>\n </div>\n <div class=\"run-entry-meta\">\n <span><i class=\"fa-solid fa-user\"></i> {{run.User || 'System'}}</span>\n <span><i class=\"fa-solid fa-clock\"></i> {{run.StartedAt | date:'medium'}}</span>\n @if (run.EndedAt) {\n <span><i class=\"fa-solid fa-flag-checkered\"></i> {{run.EndedAt | date:'shortTime'}}</span>\n }\n </div>\n @if (run.Comments) {\n <div class=\"run-entry-comments\">\n {{run.Comments}}\n </div>\n }\n </div>\n </div>\n }\n \n @if (runs.length === 0 && !isLoading) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-play-circle\"></i>\n <p>No communication runs found</p>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n `,\n styles: [`\n .runs-wrapper {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n }\n .card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n }\n .card-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n }\n .card-header h3 {\n font-size: 13px; font-weight: 700;\n color: var(--mj-text-primary);\n display: flex; align-items: center; gap: 8px;\n margin: 0;\n }\n .card-header h3 i {\n color: var(--mj-text-muted); font-size: 12px;\n }\n .header-actions { display: flex; gap: 8px; }\n\n .tb-btn {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n font-size: 12px; font-weight: 500;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n }\n .tb-btn i { font-size: 12px; }\n\n @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }\n .spinning { animation: spin 1s linear infinite; }\n\n .card-body.no-padding { padding: 0; }\n\n /* SUMMARY */\n .runs-summary {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 16px;\n padding: 20px;\n }\n .run-stat-card {\n border-radius: 12px;\n padding: 16px 20px;\n text-align: center;\n }\n .run-stat-card.info {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n }\n .run-stat-card.success {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n }\n .run-stat-card.neutral {\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n }\n\n .run-stat-value {\n font-size: 24px; font-weight: 800;\n color: var(--mj-text-primary);\n }\n .run-stat-card.info .run-stat-value { color: var(--mj-brand-primary); }\n .run-stat-card.success .run-stat-value { color: var(--mj-status-success); }\n\n .run-stat-label {\n font-size: 11px; font-weight: 600;\n text-transform: uppercase; letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n /* TIMELINE */\n .run-timeline { padding: 8px 20px 20px; }\n .run-entry {\n display: flex; gap: 16px;\n padding: 16px 0;\n border-bottom: 1px solid var(--mj-border-default);\n align-items: flex-start;\n }\n .run-entry:last-child { border-bottom: none; }\n\n .run-timeline-dot {\n width: 12px; height: 12px;\n border-radius: 50%;\n margin-top: 4px; flex-shrink: 0;\n }\n .run-timeline-dot.complete { background: var(--mj-status-success); }\n .run-timeline-dot.failed { background: var(--mj-status-error); }\n .run-timeline-dot.in-progress {\n background: var(--mj-brand-primary);\n animation: pulse-dot 1.5s ease-in-out infinite;\n }\n .run-timeline-dot.pending { background: var(--mj-status-warning); }\n\n @keyframes pulse-dot {\n 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mj-brand-primary) 40%, transparent); }\n 50% { box-shadow: 0 0 0 6px transparent; }\n }\n\n .run-entry-content { flex: 1; }\n .run-entry-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .run-entry-title {\n font-size: 13px; font-weight: 600;\n color: var(--mj-text-primary);\n }\n .run-status-badge {\n font-size: 10px; font-weight: 700;\n text-transform: uppercase; letter-spacing: 0.3px;\n padding: 3px 8px;\n border-radius: 4px;\n }\n .run-status-badge.complete {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n }\n .run-status-badge.failed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, transparent);\n }\n .run-status-badge.pending {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border: 1px solid color-mix(in srgb, var(--mj-status-warning) 30%, transparent);\n }\n .run-status-badge.in-progress {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n }\n\n .run-entry-meta {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n display: flex; align-items: center; gap: 12px;\n }\n .run-entry-meta span {\n display: flex; align-items: center; gap: 4px;\n }\n .run-entry-meta i { font-size: 10px; }\n\n .run-entry-comments {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-top: 6px;\n font-style: italic;\n }\n\n /* EMPTY STATE */\n .empty-state {\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 48px 0; color: var(--mj-text-muted);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n `]\n})\nexport class CommunicationRunsResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public runs: MJCommunicationRunEntity[] = [];\n public isLoading = false;\n public summary = {\n active: 0,\n completed: 0,\n successRate: 0\n };\n\n constructor(private cdr: ChangeDetectorRef) {\n super();\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void { }\n\n public async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.detectChanges();\n\n const rv = new RunView();\n const yesterday = new Date();\n yesterday.setDate(yesterday.getDate() - 1);\n const yesterdayIso = yesterday.toISOString();\n\n const [runsResult, activeResult, completedResult, failedResult] = await Promise.all([\n rv.RunView<MJCommunicationRunEntity>({\n EntityName: 'MJ: Communication Runs',\n OrderBy: 'StartedAt DESC',\n MaxRows: 50,\n ResultType: 'entity_object'\n }),\n rv.RunView({\n EntityName: 'MJ: Communication Runs',\n ExtraFilter: `Status = 'In-Progress'`,\n ResultType: 'count_only'\n }),\n rv.RunView({\n EntityName: 'MJ: Communication Runs',\n ExtraFilter: `EndedAt >= '${yesterdayIso}' AND Status = 'Complete'`,\n ResultType: 'count_only'\n }),\n rv.RunView({\n EntityName: 'MJ: Communication Runs',\n ExtraFilter: `EndedAt >= '${yesterdayIso}' AND Status = 'Failed'`,\n ResultType: 'count_only'\n })\n ]);\n\n if (runsResult.Success) {\n this.runs = runsResult.Results;\n }\n\n if (activeResult.Success) this.summary.active = activeResult.TotalRowCount;\n if (completedResult.Success) this.summary.completed = completedResult.TotalRowCount;\n\n const totalCompleted = this.summary.completed + (failedResult.Success ? failedResult.TotalRowCount : 0);\n this.summary.successRate = totalCompleted > 0\n ? Math.round((this.summary.completed / totalCompleted) * 100)\n : 100;\n\n } catch (error) {\n console.error('Error loading runs:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n public getRunDotClass(status: string): string {\n const s = (status || '').toLowerCase();\n if (s === 'complete') return 'complete';\n if (s === 'failed') return 'failed';\n if (s === 'in-progress') return 'in-progress';\n return 'pending';\n }\n\n public getStatusClass(status: string): string {\n const s = (status || '').toLowerCase();\n if (s === 'complete') return 'complete';\n if (s === 'failed') return 'failed';\n if (s === 'in-progress') return 'in-progress';\n return 'pending';\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Bulk Runs';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-play-circle';\n }\n}\n"]}
@@ -281,7 +281,7 @@ let CommunicationTemplatesResourceComponent = class CommunicationTemplatesResour
281
281
  i0.ɵɵconditional(!ctx.isLoading ? 15 : -1);
282
282
  i0.ɵɵadvance();
283
283
  i0.ɵɵconditional(!ctx.isLoading ? 16 : -1);
284
- } }, dependencies: [i2.LoadingComponent, i3.DatePipe], styles: [".templates-wrapper[_ngcontent-%COMP%] {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mat-sys-surface-container);\n }\n\n \n\n .templates-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n }\n .templates-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 800;\n color: var(--mat-sys-on-surface);\n }\n .templates-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n }\n .header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .search-input-wrapper[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small, 8px);\n background: var(--mat-sys-surface-container-lowest);\n transition: border-color 0.15s, box-shadow 0.15s;\n min-width: 220px;\n }\n .search-input-wrapper[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mat-sys-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mat-sys-primary) 15%, transparent);\n }\n .search-input-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mat-sys-on-surface-variant); font-size: 12px; }\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1; border: none; outline: none;\n background: transparent; font-size: 12px;\n font-family: inherit; color: var(--mat-sys-on-surface);\n }\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mat-sys-on-surface-variant); }\n\n .tb-btn[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 8px 16px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface-container-lowest);\n color: var(--mat-sys-on-surface-variant);\n font-size: 12px; font-weight: 600;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn.primary[_ngcontent-%COMP%] {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary, #fff);\n border-color: var(--mat-sys-primary);\n }\n .tb-btn.primary[_ngcontent-%COMP%]:hover { filter: brightness(1.1); }\n\n .loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n \n\n .category-filters[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n }\n .filter-chip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 5px 14px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 16px;\n background: var(--mat-sys-surface-container-lowest);\n font-size: 12px; font-weight: 500;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer; transition: all 0.15s;\n }\n .filter-chip[_ngcontent-%COMP%]:hover {\n border-color: var(--mat-sys-outline);\n background: var(--mat-sys-surface-container);\n }\n .filter-chip.active[_ngcontent-%COMP%] {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n }\n\n \n\n .templates-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card[_ngcontent-%COMP%] {\n background: var(--mat-sys-surface-container-lowest);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium, 12px);\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 6px 2px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.04);\n border-color: var(--mat-sys-outline);\n }\n\n .template-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon[_ngcontent-%COMP%] {\n width: 40px; height: 40px;\n border-radius: var(--mat-sys-corner-small, 8px);\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n .template-name[_ngcontent-%COMP%] {\n font-size: 14px; font-weight: 700;\n color: var(--mat-sys-on-surface);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mat-sys-on-surface-variant);\n margin-top: 2px;\n }\n\n .template-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface-variant);\n }\n .content-type-chip.empty[_ngcontent-%COMP%] {\n font-style: italic;\n }\n .template-updated[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n }\n\n \n\n .empty-state[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mat-sys-on-surface-variant);\n }\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] { margin: 0; font-size: 13px; }"] });
284
+ } }, dependencies: [i2.LoadingComponent, i3.DatePipe], styles: [".templates-wrapper[_ngcontent-%COMP%] {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n }\n\n \n\n .templates-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n }\n .templates-header[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 800;\n color: var(--mj-text-primary);\n }\n .templates-header[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n }\n .header-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .search-input-wrapper[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color 0.15s, box-shadow 0.15s;\n min-width: 220px;\n }\n .search-input-wrapper[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .search-input-wrapper[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { color: var(--mj-text-muted); font-size: 12px; }\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1; border: none; outline: none;\n background: transparent; font-size: 12px;\n font-family: inherit; color: var(--mj-text-primary);\n }\n .search-input-wrapper[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-text-muted); }\n\n .tb-btn[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n font-size: 12px; font-weight: 600;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n }\n .tb-btn.primary[_ngcontent-%COMP%]:hover { filter: brightness(1.1); }\n\n .loading-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n \n\n .category-filters[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n }\n .filter-chip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 5px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 12px; font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer; transition: all 0.15s;\n }\n .filter-chip[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface);\n }\n .filter-chip.active[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n \n\n .templates-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card[_ngcontent-%COMP%]:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon[_ngcontent-%COMP%] {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n .template-name[_ngcontent-%COMP%] {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty[_ngcontent-%COMP%] {\n font-style: italic;\n }\n .template-updated[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n \n\n .empty-state[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] { margin: 0; font-size: 13px; }"] });
285
285
  };
286
286
  CommunicationTemplatesResourceComponent = __decorate([
287
287
  RegisterClass(BaseResourceComponent, 'CommunicationTemplatesResource')
@@ -382,7 +382,7 @@ export { CommunicationTemplatesResourceComponent };
382
382
  </div>
383
383
  }
384
384
  </div>
385
- `, styles: ["\n .templates-wrapper {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mat-sys-surface-container);\n }\n\n /* HEADER */\n .templates-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n }\n .templates-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 800;\n color: var(--mat-sys-on-surface);\n }\n .templates-header p {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n }\n .header-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .search-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small, 8px);\n background: var(--mat-sys-surface-container-lowest);\n transition: border-color 0.15s, box-shadow 0.15s;\n min-width: 220px;\n }\n .search-input-wrapper:focus-within {\n border-color: var(--mat-sys-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mat-sys-primary) 15%, transparent);\n }\n .search-input-wrapper i { color: var(--mat-sys-on-surface-variant); font-size: 12px; }\n .search-input-wrapper input {\n flex: 1; border: none; outline: none;\n background: transparent; font-size: 12px;\n font-family: inherit; color: var(--mat-sys-on-surface);\n }\n .search-input-wrapper input::placeholder { color: var(--mat-sys-on-surface-variant); }\n\n .tb-btn {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 8px 16px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface-container-lowest);\n color: var(--mat-sys-on-surface-variant);\n font-size: 12px; font-weight: 600;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn.primary {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary, #fff);\n border-color: var(--mat-sys-primary);\n }\n .tb-btn.primary:hover { filter: brightness(1.1); }\n\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* CATEGORY FILTERS */\n .category-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n }\n .filter-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 5px 14px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 16px;\n background: var(--mat-sys-surface-container-lowest);\n font-size: 12px; font-weight: 500;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer; transition: all 0.15s;\n }\n .filter-chip:hover {\n border-color: var(--mat-sys-outline);\n background: var(--mat-sys-surface-container);\n }\n .filter-chip.active {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mat-sys-surface-container-lowest);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium, 12px);\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 6px 2px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.04);\n border-color: var(--mat-sys-outline);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: var(--mat-sys-corner-small, 8px);\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mat-sys-on-surface);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mat-sys-on-surface-variant);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface-variant);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mat-sys-on-surface-variant);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n "] }]
385
+ `, styles: ["\n .templates-wrapper {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n }\n\n /* HEADER */\n .templates-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n }\n .templates-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 800;\n color: var(--mj-text-primary);\n }\n .templates-header p {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n }\n .header-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .search-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color 0.15s, box-shadow 0.15s;\n min-width: 220px;\n }\n .search-input-wrapper:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .search-input-wrapper i { color: var(--mj-text-muted); font-size: 12px; }\n .search-input-wrapper input {\n flex: 1; border: none; outline: none;\n background: transparent; font-size: 12px;\n font-family: inherit; color: var(--mj-text-primary);\n }\n .search-input-wrapper input::placeholder { color: var(--mj-text-muted); }\n\n .tb-btn {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n font-size: 12px; font-weight: 600;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n }\n .tb-btn.primary:hover { filter: brightness(1.1); }\n\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* CATEGORY FILTERS */\n .category-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n }\n .filter-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 5px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 12px; font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer; transition: all 0.15s;\n }\n .filter-chip:hover {\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface);\n }\n .filter-chip.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n "] }]
386
386
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.NavigationService }], null); })();
387
387
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CommunicationTemplatesResourceComponent, { className: "CommunicationTemplatesResourceComponent", filePath: "src/Communication/communication-templates-resource.component.ts", lineNumber: 311 }); })();
388
388
  //# sourceMappingURL=communication-templates-resource.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"communication-templates-resource.component.js","sourceRoot":"","sources":["../../src/Communication/communication-templates-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ResourceData, MJTemplateEntity, MJTemplateContentEntity } from '@memberjunction/core-entities';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { Metadata, RunView, CompositeKey } from '@memberjunction/core';\n\ninterface TemplateCardData {\n Entity: MJTemplateEntity;\n ContentTypes: string[];\n LastUpdated: Date | null;\n CategoryName: string;\n}\n@RegisterClass(BaseResourceComponent, 'CommunicationTemplatesResource')\n@Component({\n standalone: false,\n selector: 'mj-communication-templates-resource',\n template: `\n <div class=\"templates-wrapper\">\n <!-- HEADER -->\n <div class=\"templates-header\">\n <div>\n <h2>Communication Templates</h2>\n <p>Manage reusable message templates</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\" placeholder=\"Search templates...\" (input)=\"onSearch($event)\">\n </div>\n <button class=\"tb-btn primary\" (click)=\"addNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> New Template\n </button>\n </div>\n </div>\n \n <!-- LOADING -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading templates...\"></mj-loading>\n </div>\n }\n \n <!-- CATEGORY FILTERS -->\n @if (!isLoading) {\n <div class=\"category-filters\">\n <div class=\"filter-chip\" [class.active]=\"categoryFilter === ''\"\n (click)=\"onCategoryFilter('')\">\n All ({{allTemplates.length}})\n </div>\n @for (cat of categories; track cat) {\n <div class=\"filter-chip\"\n [class.active]=\"categoryFilter === cat\"\n (click)=\"onCategoryFilter(cat)\">\n {{cat}} ({{getCategoryCount(cat)}})\n </div>\n }\n </div>\n }\n \n <!-- TEMPLATES GRID -->\n @if (!isLoading) {\n <div class=\"templates-grid\">\n @for (card of filteredTemplates; track card) {\n <div class=\"template-card\"\n (click)=\"openTemplate(card.Entity)\">\n <div class=\"template-card-header\">\n <div class=\"template-icon\">\n <i class=\"fa-solid fa-file-lines\"></i>\n </div>\n <div class=\"template-title-area\">\n <div class=\"template-name\">{{card.Entity.Name}}</div>\n <div class=\"template-category\">{{card.CategoryName}}</div>\n </div>\n </div>\n @if (card.Entity.Description) {\n <div class=\"template-description\">\n {{card.Entity.Description}}\n </div>\n }\n <div class=\"template-meta\">\n <div class=\"template-content-types\">\n @for (ct of card.ContentTypes; track ct) {\n <span class=\"content-type-chip\">\n <i [class]=\"getContentTypeIcon(ct)\"></i> {{ct}}\n </span>\n }\n @if (card.ContentTypes.length === 0) {\n <span class=\"content-type-chip empty\">\n No content\n </span>\n }\n </div>\n @if (card.LastUpdated) {\n <div class=\"template-updated\">\n Updated {{card.LastUpdated | date:'mediumDate'}}\n </div>\n }\n </div>\n </div>\n }\n @if (filteredTemplates.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-file-lines\"></i>\n <p>No templates found matching your criteria</p>\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .templates-wrapper {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mat-sys-surface-container);\n }\n\n /* HEADER */\n .templates-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n }\n .templates-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 800;\n color: var(--mat-sys-on-surface);\n }\n .templates-header p {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface-variant);\n }\n .header-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .search-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-small, 8px);\n background: var(--mat-sys-surface-container-lowest);\n transition: border-color 0.15s, box-shadow 0.15s;\n min-width: 220px;\n }\n .search-input-wrapper:focus-within {\n border-color: var(--mat-sys-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mat-sys-primary) 15%, transparent);\n }\n .search-input-wrapper i { color: var(--mat-sys-on-surface-variant); font-size: 12px; }\n .search-input-wrapper input {\n flex: 1; border: none; outline: none;\n background: transparent; font-size: 12px;\n font-family: inherit; color: var(--mat-sys-on-surface);\n }\n .search-input-wrapper input::placeholder { color: var(--mat-sys-on-surface-variant); }\n\n .tb-btn {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 8px 16px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface-container-lowest);\n color: var(--mat-sys-on-surface-variant);\n font-size: 12px; font-weight: 600;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn.primary {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary, #fff);\n border-color: var(--mat-sys-primary);\n }\n .tb-btn.primary:hover { filter: brightness(1.1); }\n\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* CATEGORY FILTERS */\n .category-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n }\n .filter-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 5px 14px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 16px;\n background: var(--mat-sys-surface-container-lowest);\n font-size: 12px; font-weight: 500;\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer; transition: all 0.15s;\n }\n .filter-chip:hover {\n border-color: var(--mat-sys-outline);\n background: var(--mat-sys-surface-container);\n }\n .filter-chip.active {\n border-color: var(--mat-sys-primary);\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mat-sys-surface-container-lowest);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-medium, 12px);\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 6px 2px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.04);\n border-color: var(--mat-sys-outline);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: var(--mat-sys-corner-small, 8px);\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mat-sys-on-surface);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mat-sys-on-surface-variant);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mat-sys-surface-container);\n color: var(--mat-sys-on-surface-variant);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mat-sys-on-surface-variant);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n `]\n})\nexport class CommunicationTemplatesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public allTemplates: TemplateCardData[] = [];\n public filteredTemplates: TemplateCardData[] = [];\n public categories: string[] = [];\n public categoryFilter = '';\n public isLoading = false;\n private searchTerm = '';\n\n constructor(private cdr: ChangeDetectorRef, private navService: NavigationService) {\n super();\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void { }\n\n public async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.detectChanges();\n\n const rv = new RunView();\n const [templatesResult, contentsResult] = await Promise.all([\n rv.RunView<MJTemplateEntity>({\n EntityName: 'MJ: Templates',\n OrderBy: 'Name ASC',\n ResultType: 'entity_object'\n }),\n rv.RunView<MJTemplateContentEntity>({\n EntityName: 'MJ: Template Contents',\n ResultType: 'entity_object'\n })\n ]);\n\n if (templatesResult.Success) {\n const contents = contentsResult.Success ? contentsResult.Results : [];\n this.allTemplates = templatesResult.Results.map(t => this.buildTemplateCard(t, contents));\n this.categories = this.extractCategories(this.allTemplates);\n this.applyFilter();\n }\n } catch (error) {\n console.error('Error loading templates:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private buildTemplateCard(template: MJTemplateEntity, allContents: MJTemplateContentEntity[]): TemplateCardData {\n const templateContents = allContents.filter(c => UUIDsEqual(c.TemplateID, template.ID));\n const contentTypes = [...new Set(templateContents.map(c => c.TypeID ? 'Content' : 'Text'))];\n const category = template.Category || 'Uncategorized';\n const lastUpdated = template.Get('__mj_UpdatedAt') as Date | null;\n\n return {\n Entity: template,\n ContentTypes: contentTypes.length > 0 ? contentTypes : [],\n LastUpdated: lastUpdated,\n CategoryName: category\n };\n }\n\n private extractCategories(cards: TemplateCardData[]): string[] {\n const cats = new Set(cards.map(c => c.CategoryName));\n return Array.from(cats).sort();\n }\n\n public getCategoryCount(category: string): number {\n return this.allTemplates.filter(t => t.CategoryName === category).length;\n }\n\n public onSearch(event: Event): void {\n this.searchTerm = (event.target as HTMLInputElement).value.toLowerCase();\n this.applyFilter();\n }\n\n public onCategoryFilter(category: string): void {\n this.categoryFilter = category;\n this.applyFilter();\n }\n\n private applyFilter(): void {\n let filtered = this.allTemplates;\n\n if (this.categoryFilter) {\n filtered = filtered.filter(t => t.CategoryName === this.categoryFilter);\n }\n\n if (this.searchTerm) {\n filtered = filtered.filter(t =>\n t.Entity.Name?.toLowerCase().includes(this.searchTerm) ||\n t.Entity.Description?.toLowerCase().includes(this.searchTerm) ||\n t.CategoryName.toLowerCase().includes(this.searchTerm)\n );\n }\n\n this.filteredTemplates = filtered;\n this.cdr.detectChanges();\n }\n\n public openTemplate(template: MJTemplateEntity): void {\n const pk = new CompositeKey();\n pk.LoadFromEntityInfoAndRecord(new Metadata().Entities.find(e => e.Name === 'MJ: Templates')!, template);\n this.navService.OpenEntityRecord('MJ: Templates', pk);\n }\n\n public addNewTemplate(): void {\n this.navService.OpenEntityRecord('MJ: Templates', new CompositeKey());\n }\n\n public getContentTypeIcon(type: string): string {\n const t = type.toLowerCase();\n if (t.includes('html')) return 'fa-solid fa-code';\n if (t.includes('text') || t.includes('plain')) return 'fa-solid fa-align-left';\n if (t.includes('sms')) return 'fa-solid fa-comment-sms';\n return 'fa-solid fa-file';\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Templates';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-file-lines';\n }\n}\n"]}
1
+ {"version":3,"file":"communication-templates-resource.component.js","sourceRoot":"","sources":["../../src/Communication/communication-templates-resource.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';\nimport { ResourceData, MJTemplateEntity, MJTemplateContentEntity } from '@memberjunction/core-entities';\nimport { RegisterClass , UUIDsEqual } from '@memberjunction/global';\nimport { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';\nimport { Metadata, RunView, CompositeKey } from '@memberjunction/core';\n\ninterface TemplateCardData {\n Entity: MJTemplateEntity;\n ContentTypes: string[];\n LastUpdated: Date | null;\n CategoryName: string;\n}\n@RegisterClass(BaseResourceComponent, 'CommunicationTemplatesResource')\n@Component({\n standalone: false,\n selector: 'mj-communication-templates-resource',\n template: `\n <div class=\"templates-wrapper\">\n <!-- HEADER -->\n <div class=\"templates-header\">\n <div>\n <h2>Communication Templates</h2>\n <p>Manage reusable message templates</p>\n </div>\n <div class=\"header-actions\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\" placeholder=\"Search templates...\" (input)=\"onSearch($event)\">\n </div>\n <button class=\"tb-btn primary\" (click)=\"addNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> New Template\n </button>\n </div>\n </div>\n \n <!-- LOADING -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <mj-loading text=\"Loading templates...\"></mj-loading>\n </div>\n }\n \n <!-- CATEGORY FILTERS -->\n @if (!isLoading) {\n <div class=\"category-filters\">\n <div class=\"filter-chip\" [class.active]=\"categoryFilter === ''\"\n (click)=\"onCategoryFilter('')\">\n All ({{allTemplates.length}})\n </div>\n @for (cat of categories; track cat) {\n <div class=\"filter-chip\"\n [class.active]=\"categoryFilter === cat\"\n (click)=\"onCategoryFilter(cat)\">\n {{cat}} ({{getCategoryCount(cat)}})\n </div>\n }\n </div>\n }\n \n <!-- TEMPLATES GRID -->\n @if (!isLoading) {\n <div class=\"templates-grid\">\n @for (card of filteredTemplates; track card) {\n <div class=\"template-card\"\n (click)=\"openTemplate(card.Entity)\">\n <div class=\"template-card-header\">\n <div class=\"template-icon\">\n <i class=\"fa-solid fa-file-lines\"></i>\n </div>\n <div class=\"template-title-area\">\n <div class=\"template-name\">{{card.Entity.Name}}</div>\n <div class=\"template-category\">{{card.CategoryName}}</div>\n </div>\n </div>\n @if (card.Entity.Description) {\n <div class=\"template-description\">\n {{card.Entity.Description}}\n </div>\n }\n <div class=\"template-meta\">\n <div class=\"template-content-types\">\n @for (ct of card.ContentTypes; track ct) {\n <span class=\"content-type-chip\">\n <i [class]=\"getContentTypeIcon(ct)\"></i> {{ct}}\n </span>\n }\n @if (card.ContentTypes.length === 0) {\n <span class=\"content-type-chip empty\">\n No content\n </span>\n }\n </div>\n @if (card.LastUpdated) {\n <div class=\"template-updated\">\n Updated {{card.LastUpdated | date:'mediumDate'}}\n </div>\n }\n </div>\n </div>\n }\n @if (filteredTemplates.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-file-lines\"></i>\n <p>No templates found matching your criteria</p>\n </div>\n }\n </div>\n }\n </div>\n `,\n styles: [`\n .templates-wrapper {\n height: 100%;\n padding: 24px;\n overflow-y: auto;\n background: var(--mj-bg-surface);\n }\n\n /* HEADER */\n .templates-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 20px;\n }\n .templates-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 800;\n color: var(--mj-text-primary);\n }\n .templates-header p {\n margin: 4px 0 0;\n font-size: 13px;\n color: var(--mj-text-muted);\n }\n .header-actions {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n .search-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color 0.15s, box-shadow 0.15s;\n min-width: 220px;\n }\n .search-input-wrapper:focus-within {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n .search-input-wrapper i { color: var(--mj-text-muted); font-size: 12px; }\n .search-input-wrapper input {\n flex: 1; border: none; outline: none;\n background: transparent; font-size: 12px;\n font-family: inherit; color: var(--mj-text-primary);\n }\n .search-input-wrapper input::placeholder { color: var(--mj-text-muted); }\n\n .tb-btn {\n display: inline-flex; align-items: center;\n gap: 6px; padding: 8px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n font-size: 12px; font-weight: 600;\n cursor: pointer; transition: all 0.15s ease;\n font-family: inherit;\n }\n .tb-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n }\n .tb-btn.primary:hover { filter: brightness(1.1); }\n\n .loading-state {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 80px 0;\n }\n\n /* CATEGORY FILTERS */\n .category-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-bottom: 20px;\n }\n .filter-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 5px 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n background: var(--mj-bg-surface-card);\n font-size: 12px; font-weight: 500;\n color: var(--mj-text-muted);\n cursor: pointer; transition: all 0.15s;\n }\n .filter-chip:hover {\n border-color: var(--mj-border-strong);\n background: var(--mj-bg-surface);\n }\n .filter-chip.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n /* GRID */\n .templates-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 16px;\n }\n\n .template-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.15s ease;\n }\n .template-card:hover {\n box-shadow: 0 2px 8px var(--mj-shadow-md);\n border-color: var(--mj-border-strong);\n }\n\n .template-card-header {\n display: flex;\n align-items: center;\n gap: 14px;\n margin-bottom: 12px;\n }\n .template-icon {\n width: 40px; height: 40px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex; align-items: center; justify-content: center;\n font-size: 16px; flex-shrink: 0;\n }\n .template-title-area { flex: 1; min-width: 0; }\n .template-name {\n font-size: 14px; font-weight: 700;\n color: var(--mj-text-primary);\n white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n }\n .template-category {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\n }\n\n .template-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-bottom: 12px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .template-meta {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .template-content-types {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n .content-type-chip {\n display: inline-flex; align-items: center;\n gap: 4px; padding: 3px 8px;\n border-radius: 10px; font-size: 10px; font-weight: 500;\n background: var(--mj-bg-surface);\n color: var(--mj-text-muted);\n }\n .content-type-chip.empty {\n font-style: italic;\n }\n .template-updated {\n font-size: 10px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n }\n\n /* EMPTY STATE */\n .empty-state {\n grid-column: 1 / -1;\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 64px 0; color: var(--mj-text-muted);\n }\n .empty-state i { font-size: 2rem; margin-bottom: 12px; opacity: 0.5; }\n .empty-state p { margin: 0; font-size: 13px; }\n `]\n})\nexport class CommunicationTemplatesResourceComponent extends BaseResourceComponent implements OnInit, OnDestroy {\n public allTemplates: TemplateCardData[] = [];\n public filteredTemplates: TemplateCardData[] = [];\n public categories: string[] = [];\n public categoryFilter = '';\n public isLoading = false;\n private searchTerm = '';\n\n constructor(private cdr: ChangeDetectorRef, private navService: NavigationService) {\n super();\n }\n\n async ngOnInit(): Promise<void> {\n await this.loadData();\n this.NotifyLoadComplete();\n }\n\n ngOnDestroy(): void { }\n\n public async loadData(): Promise<void> {\n try {\n this.isLoading = true;\n this.cdr.detectChanges();\n\n const rv = new RunView();\n const [templatesResult, contentsResult] = await Promise.all([\n rv.RunView<MJTemplateEntity>({\n EntityName: 'MJ: Templates',\n OrderBy: 'Name ASC',\n ResultType: 'entity_object'\n }),\n rv.RunView<MJTemplateContentEntity>({\n EntityName: 'MJ: Template Contents',\n ResultType: 'entity_object'\n })\n ]);\n\n if (templatesResult.Success) {\n const contents = contentsResult.Success ? contentsResult.Results : [];\n this.allTemplates = templatesResult.Results.map(t => this.buildTemplateCard(t, contents));\n this.categories = this.extractCategories(this.allTemplates);\n this.applyFilter();\n }\n } catch (error) {\n console.error('Error loading templates:', error);\n } finally {\n this.isLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n private buildTemplateCard(template: MJTemplateEntity, allContents: MJTemplateContentEntity[]): TemplateCardData {\n const templateContents = allContents.filter(c => UUIDsEqual(c.TemplateID, template.ID));\n const contentTypes = [...new Set(templateContents.map(c => c.TypeID ? 'Content' : 'Text'))];\n const category = template.Category || 'Uncategorized';\n const lastUpdated = template.Get('__mj_UpdatedAt') as Date | null;\n\n return {\n Entity: template,\n ContentTypes: contentTypes.length > 0 ? contentTypes : [],\n LastUpdated: lastUpdated,\n CategoryName: category\n };\n }\n\n private extractCategories(cards: TemplateCardData[]): string[] {\n const cats = new Set(cards.map(c => c.CategoryName));\n return Array.from(cats).sort();\n }\n\n public getCategoryCount(category: string): number {\n return this.allTemplates.filter(t => t.CategoryName === category).length;\n }\n\n public onSearch(event: Event): void {\n this.searchTerm = (event.target as HTMLInputElement).value.toLowerCase();\n this.applyFilter();\n }\n\n public onCategoryFilter(category: string): void {\n this.categoryFilter = category;\n this.applyFilter();\n }\n\n private applyFilter(): void {\n let filtered = this.allTemplates;\n\n if (this.categoryFilter) {\n filtered = filtered.filter(t => t.CategoryName === this.categoryFilter);\n }\n\n if (this.searchTerm) {\n filtered = filtered.filter(t =>\n t.Entity.Name?.toLowerCase().includes(this.searchTerm) ||\n t.Entity.Description?.toLowerCase().includes(this.searchTerm) ||\n t.CategoryName.toLowerCase().includes(this.searchTerm)\n );\n }\n\n this.filteredTemplates = filtered;\n this.cdr.detectChanges();\n }\n\n public openTemplate(template: MJTemplateEntity): void {\n const pk = new CompositeKey();\n pk.LoadFromEntityInfoAndRecord(new Metadata().Entities.find(e => e.Name === 'MJ: Templates')!, template);\n this.navService.OpenEntityRecord('MJ: Templates', pk);\n }\n\n public addNewTemplate(): void {\n this.navService.OpenEntityRecord('MJ: Templates', new CompositeKey());\n }\n\n public getContentTypeIcon(type: string): string {\n const t = type.toLowerCase();\n if (t.includes('html')) return 'fa-solid fa-code';\n if (t.includes('text') || t.includes('plain')) return 'fa-solid fa-align-left';\n if (t.includes('sms')) return 'fa-solid fa-comment-sms';\n return 'fa-solid fa-file';\n }\n\n async GetResourceDisplayName(data: ResourceData): Promise<string> {\n return 'Templates';\n }\n\n async GetResourceIconClass(data: ResourceData): Promise<string> {\n return 'fa-solid fa-file-lines';\n }\n}\n"]}
@@ -969,7 +969,7 @@ let ComponentStudioDashboardComponent = class ComponentStudioDashboardComponent
969
969
  i0.ɵɵconditional(ctx.ShowNewComponentDialog ? 39 : -1);
970
970
  i0.ɵɵadvance();
971
971
  i0.ɵɵconditional(ctx.ShowSaveVersionDialog ? 40 : -1);
972
- } }, styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mat-sys-surface-container);\n overflow: hidden;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .studio-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 0 8px;\n background: var(--mat-sys-surface);\n border-bottom: 1px solid var(--mat-sys-outline);\n flex-shrink: 0;\n z-index: 10;\n min-height: 42px;\n gap: 8px;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .toolbar-context[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 1;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .toolbar-spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .toolbar-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 10px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface);\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 line-height: 1;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n border-color: var(--mat-sys-outline);\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.icon-only[_ngcontent-%COMP%] {\n padding: 5px 7px;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.primary[_ngcontent-%COMP%] {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary, #fff);\n border-color: var(--mat-sys-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.primary[_ngcontent-%COMP%]:hover {\n opacity: 0.9;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.active-toggle[_ngcontent-%COMP%] {\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n border-color: var(--mat-sys-primary);\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .breadcrumb-type[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n}\n\n.component-studio[_ngcontent-%COMP%] .breadcrumb-type[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mat-sys-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .breadcrumb-sep[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mat-sys-outline);\n}\n\n.component-studio[_ngcontent-%COMP%] .component-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 240px;\n}\n\n.component-studio[_ngcontent-%COMP%] .running-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 2px 8px;\n background: #dcfce7;\n color: #15803d;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.component-studio[_ngcontent-%COMP%] .running-dot-small[_ngcontent-%COMP%] {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #22c55e;\n animation: _ngcontent-%COMP%_pulse 1.5s ease-in-out infinite;\n}\n\n.component-studio[_ngcontent-%COMP%] .unsaved-dot[_ngcontent-%COMP%] {\n display: inline-block;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #f59e0b;\n animation: _ngcontent-%COMP%_pulse 2s infinite;\n flex-shrink: 0;\n}\n\n.component-studio[_ngcontent-%COMP%] .toolbar-divider[_ngcontent-%COMP%] {\n width: 1px;\n height: 18px;\n background: var(--mat-sys-outline-variant);\n margin: 0 2px;\n flex-shrink: 0;\n}\n\n.component-studio[_ngcontent-%COMP%] .dropdown-icon[_ngcontent-%COMP%] {\n font-size: 9px;\n opacity: 0.6;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-small);\n box-shadow: var(--mat-sys-elevation-3);\n z-index: 100;\n min-width: 180px;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n transition: background 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container-high);\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:not(:last-child) {\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio[_ngcontent-%COMP%] .header-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-primary);\n font-size: 13px;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .studio-body[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mat-sys-surface);\n}\n\n.component-studio[_ngcontent-%COMP%] .panel-left[_ngcontent-%COMP%] {\n flex-shrink: 0;\n border-right: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface-container-low);\n}\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: row;\n min-width: 400px;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] .workspace-preview[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-right: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] .workspace-preview.full-width[_ngcontent-%COMP%] {\n border-right: none;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 10px;\n background: var(--mat-sys-surface-container-lowest);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n flex-shrink: 0;\n min-height: 32px;\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-left[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mat-sys-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio[_ngcontent-%COMP%] .toggle-editors-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface);\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .toggle-editors-btn[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio[_ngcontent-%COMP%] .toggle-editors-btn.active[_ngcontent-%COMP%] {\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n border-color: var(--mat-sys-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] .workspace-editors[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .panel-right[_ngcontent-%COMP%] {\n flex-shrink: 0;\n border-left: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface-container-low);\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 5px;\n cursor: col-resize;\n background: transparent;\n position: relative;\n z-index: 5;\n transition: background 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%]:hover, \n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mat-sys-primary) 25%, transparent);\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .resize-handle.center-divider[_ngcontent-%COMP%] {\n width: 7px;\n background: var(--mat-sys-outline-variant);\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle.center-divider[_ngcontent-%COMP%]:hover, \n.component-studio[_ngcontent-%COMP%] .resize-handle.center-divider[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mat-sys-primary) 40%, transparent);\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%] .divider-grip[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 3px;\n height: 32px;\n border-radius: 2px;\n background: var(--mat-sys-on-surface-variant);\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%]:hover .divider-grip[_ngcontent-%COMP%] {\n opacity: 0.5;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%]:not(.resizing) .panel[_ngcontent-%COMP%] {\n transition: width 0.15s ease, flex 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%]:not(.resizing) .workspace-preview[_ngcontent-%COMP%], \n.component-studio[_ngcontent-%COMP%]:not(.resizing) .workspace-editors[_ngcontent-%COMP%] {\n transition: flex 0.15s ease;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2px 16px;\n background: var(--mat-sys-surface-container);\n border-top: 1px solid var(--mat-sys-outline-variant);\n font-size: 11px;\n color: var(--mat-sys-on-surface-variant);\n flex-shrink: 0;\n min-height: 24px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .status-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .status-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 0 4px;\n font-size: 10px;\n font-family: inherit;\n line-height: 16px;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-container-high);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 3px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .shortcut-hint[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n opacity: 0.8;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] {\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-large, 16px);\n box-shadow: var(--mat-sys-elevation-3);\n width: 520px;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mat-sys-on-surface-variant);\n font-size: 16px;\n padding: 4px;\n border-radius: var(--mat-sys-corner-small, 4px);\n transition: background 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container-high);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] {\n padding: 16px 20px;\n overflow-y: auto;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-group[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-group[_ngcontent-%COMP%] + .shortcut-group[_ngcontent-%COMP%] {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-row[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n font-size: 12px;\n font-family: inherit;\n line-height: 20px;\n color: var(--mat-sys-on-surface);\n background: var(--mat-sys-surface-container-high);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 4px;\n box-shadow: 0 1px 0 var(--mat-sys-outline-variant);\n min-width: 24px;\n text-align: center;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mat-sys-surface-container-low);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] {\n text-align: center;\n max-width: 400px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .empty-state-icon[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 72px;\n height: 72px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--mat-sys-primary-container), var(--mat-sys-tertiary-container, var(--mat-sys-primary-container)));\n margin-bottom: 16px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .empty-state-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n color: var(--mat-sys-on-primary-container);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mat-sys-outline);\n margin-bottom: 16px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0 0 8px;\n font-size: 22px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 24px;\n color: var(--mat-sys-on-surface-variant);\n font-size: 14px;\n line-height: 1.5;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .empty-state-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex-wrap: wrap;\n margin-top: 16px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n margin-right: 4px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-container);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 16px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-btn[_ngcontent-%COMP%]:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n border-color: var(--mat-sys-outline);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mat-sys-primary);\n margin-bottom: 0;\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}"] });
972
+ } }, styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .studio-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 0 8px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n z-index: 10;\n min-height: 42px;\n gap: 8px;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .toolbar-context[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 1;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .toolbar-spacer[_ngcontent-%COMP%] {\n flex: 1;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .toolbar-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\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: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n line-height: 1;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.icon-only[_ngcontent-%COMP%] {\n padding: 5px 7px;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.primary[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.primary[_ngcontent-%COMP%]:hover {\n opacity: 0.9;\n}\n\n.component-studio[_ngcontent-%COMP%] .tb-btn.active-toggle[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .breadcrumb-type[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.component-studio[_ngcontent-%COMP%] .breadcrumb-type[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .breadcrumb-sep[_ngcontent-%COMP%] {\n font-size: 9px;\n color: var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .component-label[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 240px;\n}\n\n.component-studio[_ngcontent-%COMP%] .running-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.component-studio[_ngcontent-%COMP%] .running-dot-small[_ngcontent-%COMP%] {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-success);\n animation: _ngcontent-%COMP%_pulse 1.5s ease-in-out infinite;\n}\n\n.component-studio[_ngcontent-%COMP%] .unsaved-dot[_ngcontent-%COMP%] {\n display: inline-block;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--mj-status-warning);\n animation: _ngcontent-%COMP%_pulse 2s infinite;\n flex-shrink: 0;\n}\n\n.component-studio[_ngcontent-%COMP%] .toolbar-divider[_ngcontent-%COMP%] {\n width: 1px;\n height: 18px;\n background: var(--mj-border-default);\n margin: 0 2px;\n flex-shrink: 0;\n}\n\n.component-studio[_ngcontent-%COMP%] .dropdown-icon[_ngcontent-%COMP%] {\n font-size: 9px;\n opacity: 0.6;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 100;\n min-width: 180px;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: background 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio[_ngcontent-%COMP%] .header-dropdown[_ngcontent-%COMP%] .dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:not(:last-child) {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .header-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-brand-primary);\n font-size: 13px;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .studio-body[_ngcontent-%COMP%] {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .panel[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.component-studio[_ngcontent-%COMP%] .panel-left[_ngcontent-%COMP%] {\n flex-shrink: 0;\n border-right: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: row;\n min-width: 400px;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] .workspace-preview[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-right: 1px solid var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] .workspace-preview.full-width[_ngcontent-%COMP%] {\n border-right: none;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n min-height: 32px;\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-left[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-sub-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio[_ngcontent-%COMP%] .toggle-editors-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\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 cursor: pointer;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .toggle-editors-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .toggle-editors-btn.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .preview-body[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .panel-center[_ngcontent-%COMP%] .workspace-editors[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .panel-right[_ngcontent-%COMP%] {\n flex-shrink: 0;\n border-left: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%] {\n flex-shrink: 0;\n width: 5px;\n cursor: col-resize;\n background: transparent;\n position: relative;\n z-index: 5;\n transition: background 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%]:hover, \n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n\n\n.component-studio[_ngcontent-%COMP%] .resize-handle.center-divider[_ngcontent-%COMP%] {\n width: 7px;\n background: var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle.center-divider[_ngcontent-%COMP%]:hover, \n.component-studio[_ngcontent-%COMP%] .resize-handle.center-divider[_ngcontent-%COMP%]:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%] .divider-grip[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 3px;\n height: 32px;\n border-radius: 2px;\n background: var(--mj-text-secondary);\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .resize-handle[_ngcontent-%COMP%]:hover .divider-grip[_ngcontent-%COMP%] {\n opacity: 0.5;\n}\n\n\n\n.component-studio[_ngcontent-%COMP%]:not(.resizing) .panel[_ngcontent-%COMP%] {\n transition: width 0.15s ease, flex 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%]:not(.resizing) .workspace-preview[_ngcontent-%COMP%], \n.component-studio[_ngcontent-%COMP%]:not(.resizing) .workspace-editors[_ngcontent-%COMP%] {\n transition: flex 0.15s ease;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2px 16px;\n background: var(--mj-bg-surface-sunken);\n border-top: 1px solid var(--mj-border-default);\n font-size: 11px;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n min-height: 24px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .status-left[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .status-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .status-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 0 4px;\n font-size: 10px;\n font-family: inherit;\n line-height: 16px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 3px;\n}\n\n.component-studio[_ngcontent-%COMP%] .status-bar[_ngcontent-%COMP%] .shortcut-hint[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n opacity: 0.8;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n box-shadow: var(--mj-shadow-lg);\n width: 520px;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 16px;\n padding: 4px;\n border-radius: 4px;\n transition: background 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-header[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] {\n padding: 16px 20px;\n overflow-y: auto;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-group[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-group[_ngcontent-%COMP%] + .shortcut-group[_ngcontent-%COMP%] {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 0;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .shortcuts-overlay[_ngcontent-%COMP%] .shortcuts-panel[_ngcontent-%COMP%] .shortcuts-body[_ngcontent-%COMP%] .shortcut-row[_ngcontent-%COMP%] kbd[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n font-size: 12px;\n font-family: inherit;\n line-height: 20px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n box-shadow: 0 1px 0 var(--mj-border-default);\n min-width: 24px;\n text-align: center;\n}\n\n\n\n\n\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] {\n text-align: center;\n max-width: 400px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .empty-state-icon[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 72px;\n height: 72px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n margin-bottom: 16px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .empty-state-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 28px;\n color: var(--mj-brand-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-border-default);\n margin-bottom: 16px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n margin: 0 0 8px;\n font-size: 22px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 24px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n line-height: 1.5;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .empty-state-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex-wrap: wrap;\n margin-top: 16px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-right: 4px;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-default);\n}\n\n.component-studio[_ngcontent-%COMP%] .empty-state[_ngcontent-%COMP%] .empty-state-content[_ngcontent-%COMP%] .quick-start-templates[_ngcontent-%COMP%] .quick-start-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 11px;\n color: var(--mj-brand-primary);\n margin-bottom: 0;\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}"] });
973
973
  };
974
974
  ComponentStudioDashboardComponent = ComponentStudioDashboardComponent_1 = __decorate([
975
975
  RegisterClass(BaseDashboard, 'ComponentStudioDashboard')
@@ -977,7 +977,7 @@ ComponentStudioDashboardComponent = ComponentStudioDashboardComponent_1 = __deco
977
977
  export { ComponentStudioDashboardComponent };
978
978
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentStudioDashboardComponent, [{
979
979
  type: Component,
980
- args: [{ standalone: false, selector: 'mj-component-studio-dashboard', providers: [ComponentStudioStateService, ComponentVersionService], template: "<div class=\"component-studio\" [class.resizing]=\"IsResizing\" kendoDialogContainer>\n\n <!-- ============================================================\n TOOLBAR \u2014 Unified bar with integrated breadcrumb\n Left: hamburger + breadcrumb context\n Right: Save | Export | divider | AI | Keyboard | Refresh\n ============================================================ -->\n <div class=\"studio-toolbar\">\n <div class=\"toolbar-context\">\n <!-- Toggle left panel -->\n <button class=\"tb-btn icon-only\" title=\"Toggle browser panel\" (click)=\"ToggleLeftPanel()\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n @if (state.SelectedComponent) {\n <span class=\"breadcrumb-type\">\n <i class=\"fa-solid fa-cube\"></i>\n {{ state.GetComponentType(state.SelectedComponent) || 'Component' }}\n </span>\n <span class=\"breadcrumb-sep\"><i class=\"fa-solid fa-chevron-right\"></i></span>\n <span class=\"component-label\">{{ state.GetComponentName(state.SelectedComponent) }}</span>\n\n @if (state.IsRunning) {\n <span class=\"running-badge\">\n <span class=\"running-dot-small\"></span>\n Running\n </span>\n }\n @if (state.HasUnsavedChanges) {\n <span class=\"unsaved-dot\" title=\"Unsaved changes\"></span>\n }\n }\n </div>\n\n <div class=\"toolbar-spacer\"></div>\n\n <div class=\"toolbar-actions\">\n <!-- Save Version -->\n @if (state.SelectedComponent) {\n <button class=\"tb-btn primary\" (click)=\"SaveVersion()\" title=\"Save version (Ctrl+S)\">\n <i class=\"fa-solid fa-save\"></i> Save\n </button>\n }\n\n <!-- Refresh Component -->\n @if (state.SelectedComponent && state.IsRunning) {\n <button class=\"tb-btn\" (click)=\"RefreshComponent()\" title=\"Refresh component\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n }\n\n <!-- Export -->\n @if (state.SelectedComponent && state.IsRunning) {\n <div class=\"header-dropdown\" [class.open]=\"exportDropdownOpen\">\n <button class=\"tb-btn\" (click)=\"ToggleExportDropdown()\">\n <i class=\"fa-solid fa-file-export\"></i> Export\n <i class=\"fa-solid fa-chevron-down dropdown-icon\"></i>\n </button>\n @if (exportDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"ExportToArtifact()\">\n <i class=\"fa-solid fa-save\"></i> To Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"ExportToFile()\">\n <i class=\"fa-solid fa-file\"></i> To File\n </button>\n <button class=\"dropdown-item\" (click)=\"ExportToClipboard()\">\n <i class=\"fa-solid fa-clipboard\"></i> To Clipboard\n </button>\n </div>\n }\n </div>\n }\n\n <span class=\"toolbar-divider\"></span>\n\n <!-- AI Panel Toggle -->\n <button class=\"tb-btn icon-only\" [class.active-toggle]=\"!state.IsAIPanelCollapsed\"\n (click)=\"ToggleAIPanel()\"\n [title]=\"state.IsAIPanelCollapsed ? 'Show AI Assistant' : 'Hide AI Assistant'\">\n <i class=\"fa-solid fa-robot\"></i>\n </button>\n\n <!-- Keyboard Shortcuts -->\n <button class=\"tb-btn icon-only\" (click)=\"ShowKeyboardShortcuts = !ShowKeyboardShortcuts\"\n title=\"Keyboard shortcuts (?)\">\n <i class=\"fa-solid fa-keyboard\"></i>\n </button>\n\n <!-- Refresh -->\n <button class=\"tb-btn icon-only\" (click)=\"RefreshData()\" [disabled]=\"state.IsLoading\" title=\"Refresh data\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </button>\n </div>\n\n <!-- Hidden file input -->\n <input #fileInput type=\"file\" accept=\".json\" (change)=\"HandleFileSelect($event)\" style=\"display: none;\" />\n </div>\n\n <!-- ============================================================\n THREE-PANEL BODY\n ============================================================ -->\n <div class=\"studio-body\">\n\n <!-- Left Panel: Component Browser (collapsible) -->\n @if (!IsLeftPanelCollapsed) {\n <div class=\"panel panel-left\" [style.width.px]=\"leftPanelWidth\">\n <mj-component-browser\n (NewComponent)=\"OnNewComponent()\"\n (ImportFromFile)=\"ImportFromFile()\"\n (ImportFromText)=\"ImportFromText()\"\n (ImportFromArtifact)=\"ImportFromArtifact()\">\n </mj-component-browser>\n </div>\n\n <!-- Resize Handle: Left <-> Center -->\n <div class=\"resize-handle\" (mousedown)=\"OnLeftResizeStart($event)\"></div>\n }\n\n <!-- Center Panel: Workspace (side-by-side: Preview LEFT, Editor RIGHT) -->\n <div class=\"panel panel-center\">\n @if (state.SelectedComponent) {\n <!-- Preview (left side) -->\n <div class=\"workspace-preview\" [class.full-width]=\"IsEditorPanelCollapsed\" [style.flex]=\"IsEditorPanelCollapsed ? '1 1 100%' : previewFlex\">\n <div class=\"preview-sub-header\">\n <div class=\"preview-sub-left\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Preview</span>\n </div>\n <div class=\"preview-sub-right\">\n <!-- Toggle editor panel -->\n <button class=\"toggle-editors-btn\" [class.active]=\"!IsEditorPanelCollapsed\"\n (click)=\"ToggleEditorPanel()\" title=\"Toggle editor panel\">\n <i class=\"fa-solid fa-columns\"></i>\n </button>\n </div>\n </div>\n <div class=\"preview-body\">\n <mj-component-preview\n (AskAIToFix)=\"OnAskAIToFix($event)\">\n </mj-component-preview>\n </div>\n </div>\n\n <!-- Resize Handle: Preview <-> Editor (obvious center divider) -->\n @if (!IsEditorPanelCollapsed) {\n <div class=\"resize-handle center-divider\" (mousedown)=\"OnCenterResizeStart($event)\">\n <div class=\"divider-grip\"></div>\n </div>\n }\n\n <!-- Editor Tabs (right side, collapsible) -->\n @if (!IsEditorPanelCollapsed) {\n <div class=\"workspace-editors\" [style.flex]=\"editorFlex\">\n <mj-editor-tabs></mj-editor-tabs>\n </div>\n }\n } @else {\n <!-- Enhanced Empty State -->\n <div class=\"empty-state\">\n <div class=\"empty-state-content\">\n <div class=\"empty-state-icon\">\n <i class=\"fa-solid fa-rocket\"></i>\n </div>\n <h2>Ready to Build</h2>\n <p>Select a component from the browser or create a new one to get started</p>\n <div class=\"empty-state-actions\">\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"OnNewComponent()\">\n <span class=\"fa-solid fa-plus\"></span> New Component\n </button>\n <button kendoButton [themeColor]=\"'base'\" (click)=\"ImportFromFile()\">\n <span class=\"fa-solid fa-file-import\"></span> Import\n </button>\n </div>\n <div class=\"quick-start-templates\">\n <span class=\"quick-start-label\">Quick start:</span>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('dashboard')\">\n <i class=\"fa-solid fa-chart-line\"></i> Dashboard\n </button>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('report')\">\n <i class=\"fa-solid fa-file-alt\"></i> Report\n </button>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('chart')\">\n <i class=\"fa-solid fa-chart-pie\"></i> Chart\n </button>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('form')\">\n <i class=\"fa-solid fa-edit\"></i> Form\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Resize Handle: Center <-> Right -->\n @if (!state.IsAIPanelCollapsed) {\n <div class=\"resize-handle\" (mousedown)=\"OnRightResizeStart($event)\"></div>\n }\n\n <!-- Right Panel: AI Assistant -->\n @if (!state.IsAIPanelCollapsed) {\n <div class=\"panel panel-right\" [style.width.px]=\"rightPanelWidth\">\n <mj-ai-assistant-panel></mj-ai-assistant-panel>\n </div>\n }\n </div>\n\n <!-- ============================================================\n STATUS BAR\n ============================================================ -->\n <div class=\"status-bar\">\n <div class=\"status-left\">\n <span class=\"status-item\">\n <i class=\"fa-solid fa-cube\"></i>\n {{ state.FilteredComponents.length }} component{{ state.FilteredComponents.length !== 1 ? 's' : '' }}\n </span>\n </div>\n <div class=\"status-right\">\n @if (LastSavedTime) {\n <span class=\"status-item\">\n <i class=\"fa-solid fa-check-circle\"></i>\n Saved {{ LastSavedTime | date:'shortTime' }}\n </span>\n }\n <span class=\"status-item shortcut-hint\">\n <kbd>?</kbd> Shortcuts\n </span>\n </div>\n </div>\n\n <!-- ============================================================\n KEYBOARD SHORTCUTS OVERLAY\n ============================================================ -->\n @if (ShowKeyboardShortcuts) {\n <div class=\"shortcuts-overlay\" (click)=\"ShowKeyboardShortcuts = false\">\n <div class=\"shortcuts-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"shortcuts-header\">\n <h3>Keyboard Shortcuts</h3>\n <button class=\"shortcuts-close\" (click)=\"ShowKeyboardShortcuts = false\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcuts-body\">\n <div class=\"shortcut-group\">\n <h4>General</h4>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>Ctrl</kbd> + <kbd>S</kbd></span>\n <span class=\"shortcut-desc\">Save version</span>\n </div>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>Ctrl</kbd> + <kbd>N</kbd></span>\n <span class=\"shortcut-desc\">New component</span>\n </div>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>?</kbd></span>\n <span class=\"shortcut-desc\">Toggle shortcuts</span>\n </div>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>Esc</kbd></span>\n <span class=\"shortcut-desc\">Close overlay</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- ============================================================\n NEW COMPONENT DIALOG\n ============================================================ -->\n @if (ShowNewComponentDialog) {\n <mj-new-component-dialog\n [Visible]=\"ShowNewComponentDialog\"\n (Close)=\"OnNewComponentDialogClose($event)\">\n </mj-new-component-dialog>\n }\n\n @if (ShowSaveVersionDialog) {\n <mj-save-version-dialog\n [Visible]=\"ShowSaveVersionDialog\"\n [CurrentVersion]=\"versionService.CurrentVersionNumber\"\n (Save)=\"OnSaveVersionConfirm($event)\"\n (Cancel)=\"ShowSaveVersionDialog = false\">\n </mj-save-version-dialog>\n }\n</div>\n", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mat-sys-surface-container);\n overflow: hidden;\n}\n\n/* ============================================================\n TOOLBAR \u2014 unified bar with integrated breadcrumb\n ============================================================ */\n\n.component-studio .studio-toolbar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n background: var(--mat-sys-surface);\n border-bottom: 1px solid var(--mat-sys-outline);\n flex-shrink: 0;\n z-index: 10;\n min-height: 42px;\n gap: 8px;\n}\n\n/* Left: hamburger + breadcrumb context */\n.component-studio .toolbar-context {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 1;\n overflow: hidden;\n}\n\n.component-studio .toolbar-spacer {\n flex: 1;\n}\n\n/* Right: action buttons */\n.component-studio .toolbar-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n/* ---- Toolbar buttons ---- */\n.component-studio .tb-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 10px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface);\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 line-height: 1;\n}\n\n.component-studio .tb-btn:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n border-color: var(--mat-sys-outline);\n}\n\n.component-studio .tb-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.component-studio .tb-btn i {\n font-size: 12px;\n}\n\n.component-studio .tb-btn.icon-only {\n padding: 5px 7px;\n}\n\n.component-studio .tb-btn.primary {\n background: var(--mat-sys-primary);\n color: var(--mat-sys-on-primary, #fff);\n border-color: var(--mat-sys-primary);\n}\n\n.component-studio .tb-btn.primary:hover {\n opacity: 0.9;\n}\n\n.component-studio .tb-btn.active-toggle {\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n border-color: var(--mat-sys-primary);\n}\n\n/* ---- Breadcrumb elements inside toolbar ---- */\n.component-studio .breadcrumb-type {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n white-space: nowrap;\n}\n\n.component-studio .breadcrumb-type i {\n font-size: 11px;\n color: var(--mat-sys-primary);\n}\n\n.component-studio .breadcrumb-sep {\n font-size: 9px;\n color: var(--mat-sys-outline);\n}\n\n.component-studio .component-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 240px;\n}\n\n.component-studio .running-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 2px 8px;\n background: #dcfce7;\n color: #15803d;\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.component-studio .running-dot-small {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #22c55e;\n animation: pulse 1.5s ease-in-out infinite;\n}\n\n.component-studio .unsaved-dot {\n display: inline-block;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: #f59e0b;\n animation: pulse 2s infinite;\n flex-shrink: 0;\n}\n\n.component-studio .toolbar-divider {\n width: 1px;\n height: 18px;\n background: var(--mat-sys-outline-variant);\n margin: 0 2px;\n flex-shrink: 0;\n}\n\n.component-studio .dropdown-icon {\n font-size: 9px;\n opacity: 0.6;\n}\n\n/* ---- Dropdown menus ---- */\n.component-studio .header-dropdown {\n position: relative;\n}\n\n.component-studio .header-dropdown .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline);\n border-radius: var(--mat-sys-corner-small);\n box-shadow: var(--mat-sys-elevation-3);\n z-index: 100;\n min-width: 180px;\n overflow: hidden;\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n transition: background 0.15s ease;\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item:hover {\n background: var(--mat-sys-surface-container-high);\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item:not(:last-child) {\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item i {\n width: 16px;\n text-align: center;\n color: var(--mat-sys-primary);\n font-size: 13px;\n}\n\n/* ============================================================\n THREE-PANEL BODY\n ============================================================ */\n\n.component-studio .studio-body {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n\n.component-studio .panel {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mat-sys-surface);\n}\n\n.component-studio .panel-left {\n flex-shrink: 0;\n border-right: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface-container-low);\n}\n\n.component-studio .panel-center {\n flex: 1;\n display: flex;\n flex-direction: row;\n min-width: 400px;\n}\n\n/* Preview pane (left side of center) */\n.component-studio .panel-center .workspace-preview {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-right: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio .panel-center .workspace-preview.full-width {\n border-right: none;\n}\n\n/* Preview sub-header */\n.component-studio .preview-sub-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 10px;\n background: var(--mat-sys-surface-container-lowest);\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n flex-shrink: 0;\n min-height: 32px;\n}\n\n.component-studio .preview-sub-left {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n}\n\n.component-studio .preview-sub-left i {\n font-size: 11px;\n color: var(--mat-sys-primary);\n}\n\n.component-studio .preview-sub-right {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio .toggle-editors-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-extra-small, 4px);\n background: var(--mat-sys-surface);\n color: var(--mat-sys-on-surface-variant);\n cursor: pointer;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.component-studio .toggle-editors-btn:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio .toggle-editors-btn.active {\n background: var(--mat-sys-primary-container);\n color: var(--mat-sys-on-primary-container);\n border-color: var(--mat-sys-primary);\n}\n\n.component-studio .preview-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n/* Editor pane (right side of center) */\n.component-studio .panel-center .workspace-editors {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Right panel: AI Assistant */\n.component-studio .panel-right {\n flex-shrink: 0;\n border-left: 1px solid var(--mat-sys-outline);\n background: var(--mat-sys-surface-container-low);\n}\n\n/* ============================================================\n RESIZE HANDLES\n ============================================================ */\n\n.component-studio .resize-handle {\n flex-shrink: 0;\n width: 5px;\n cursor: col-resize;\n background: transparent;\n position: relative;\n z-index: 5;\n transition: background 0.15s ease;\n}\n\n.component-studio .resize-handle:hover,\n.component-studio .resize-handle:active {\n background: color-mix(in srgb, var(--mat-sys-primary) 25%, transparent);\n}\n\n/* Center divider \u2014 more obvious separator between preview and editors */\n.component-studio .resize-handle.center-divider {\n width: 7px;\n background: var(--mat-sys-outline-variant);\n}\n\n.component-studio .resize-handle.center-divider:hover,\n.component-studio .resize-handle.center-divider:active {\n background: color-mix(in srgb, var(--mat-sys-primary) 40%, transparent);\n}\n\n.component-studio .resize-handle .divider-grip {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 3px;\n height: 32px;\n border-radius: 2px;\n background: var(--mat-sys-on-surface-variant);\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.component-studio .resize-handle:hover .divider-grip {\n opacity: 0.5;\n}\n\n/* SMOOTH RESIZE TRANSITIONS */\n.component-studio:not(.resizing) .panel {\n transition: width 0.15s ease, flex 0.15s ease;\n}\n\n.component-studio:not(.resizing) .workspace-preview,\n.component-studio:not(.resizing) .workspace-editors {\n transition: flex 0.15s ease;\n}\n\n/* ============================================================\n STATUS BAR\n ============================================================ */\n\n.component-studio .status-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2px 16px;\n background: var(--mat-sys-surface-container);\n border-top: 1px solid var(--mat-sys-outline-variant);\n font-size: 11px;\n color: var(--mat-sys-on-surface-variant);\n flex-shrink: 0;\n min-height: 24px;\n}\n\n.component-studio .status-bar .status-left {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio .status-bar .status-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio .status-bar .status-item {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio .status-bar kbd {\n display: inline-block;\n padding: 0 4px;\n font-size: 10px;\n font-family: inherit;\n line-height: 16px;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-container-high);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 3px;\n}\n\n.component-studio .status-bar .shortcut-hint {\n display: flex;\n align-items: center;\n gap: 4px;\n opacity: 0.8;\n}\n\n/* ============================================================\n KEYBOARD SHORTCUTS OVERLAY\n ============================================================ */\n\n.component-studio .shortcuts-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel {\n background: var(--mat-sys-surface);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: var(--mat-sys-corner-large, 16px);\n box-shadow: var(--mat-sys-elevation-3);\n width: 520px;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header button {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mat-sys-on-surface-variant);\n font-size: 16px;\n padding: 4px;\n border-radius: var(--mat-sys-corner-small, 4px);\n transition: background 0.15s ease;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header button:hover {\n background: var(--mat-sys-surface-container-high);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body {\n padding: 16px 20px;\n overflow-y: auto;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-group h4 {\n margin: 0 0 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mat-sys-on-surface-variant);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-group + .shortcut-group {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid var(--mat-sys-outline-variant);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 0;\n font-size: 13px;\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-row kbd {\n display: inline-block;\n padding: 2px 8px;\n font-size: 12px;\n font-family: inherit;\n line-height: 20px;\n color: var(--mat-sys-on-surface);\n background: var(--mat-sys-surface-container-high);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 4px;\n box-shadow: 0 1px 0 var(--mat-sys-outline-variant);\n min-width: 24px;\n text-align: center;\n}\n\n/* ============================================================\n EMPTY STATE\n ============================================================ */\n\n.component-studio .empty-state {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mat-sys-surface-container-low);\n}\n\n.component-studio .empty-state .empty-state-content {\n text-align: center;\n max-width: 400px;\n}\n\n.component-studio .empty-state .empty-state-content .empty-state-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 72px;\n height: 72px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--mat-sys-primary-container), var(--mat-sys-tertiary-container, var(--mat-sys-primary-container)));\n margin-bottom: 16px;\n}\n\n.component-studio .empty-state .empty-state-content .empty-state-icon i {\n font-size: 28px;\n color: var(--mat-sys-on-primary-container);\n}\n\n.component-studio .empty-state .empty-state-content i {\n color: var(--mat-sys-outline);\n margin-bottom: 16px;\n}\n\n.component-studio .empty-state .empty-state-content h2 {\n margin: 0 0 8px;\n font-size: 22px;\n font-weight: 600;\n color: var(--mat-sys-on-surface);\n}\n\n.component-studio .empty-state .empty-state-content p {\n margin: 0 0 24px;\n color: var(--mat-sys-on-surface-variant);\n font-size: 14px;\n line-height: 1.5;\n}\n\n.component-studio .empty-state .empty-state-content .empty-state-actions {\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex-wrap: wrap;\n margin-top: 16px;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-label {\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n margin-right: 4px;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n font-size: 12px;\n color: var(--mat-sys-on-surface-variant);\n background: var(--mat-sys-surface-container);\n border: 1px solid var(--mat-sys-outline-variant);\n border-radius: 16px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-btn:hover {\n background: var(--mat-sys-surface-container-high);\n color: var(--mat-sys-on-surface);\n border-color: var(--mat-sys-outline);\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-btn i {\n font-size: 11px;\n color: var(--mat-sys-primary);\n margin-bottom: 0;\n}\n\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}\n"] }]
980
+ args: [{ standalone: false, selector: 'mj-component-studio-dashboard', providers: [ComponentStudioStateService, ComponentVersionService], template: "<div class=\"component-studio\" [class.resizing]=\"IsResizing\" kendoDialogContainer>\n\n <!-- ============================================================\n TOOLBAR \u2014 Unified bar with integrated breadcrumb\n Left: hamburger + breadcrumb context\n Right: Save | Export | divider | AI | Keyboard | Refresh\n ============================================================ -->\n <div class=\"studio-toolbar\">\n <div class=\"toolbar-context\">\n <!-- Toggle left panel -->\n <button class=\"tb-btn icon-only\" title=\"Toggle browser panel\" (click)=\"ToggleLeftPanel()\">\n <i class=\"fa-solid fa-bars\"></i>\n </button>\n\n @if (state.SelectedComponent) {\n <span class=\"breadcrumb-type\">\n <i class=\"fa-solid fa-cube\"></i>\n {{ state.GetComponentType(state.SelectedComponent) || 'Component' }}\n </span>\n <span class=\"breadcrumb-sep\"><i class=\"fa-solid fa-chevron-right\"></i></span>\n <span class=\"component-label\">{{ state.GetComponentName(state.SelectedComponent) }}</span>\n\n @if (state.IsRunning) {\n <span class=\"running-badge\">\n <span class=\"running-dot-small\"></span>\n Running\n </span>\n }\n @if (state.HasUnsavedChanges) {\n <span class=\"unsaved-dot\" title=\"Unsaved changes\"></span>\n }\n }\n </div>\n\n <div class=\"toolbar-spacer\"></div>\n\n <div class=\"toolbar-actions\">\n <!-- Save Version -->\n @if (state.SelectedComponent) {\n <button class=\"tb-btn primary\" (click)=\"SaveVersion()\" title=\"Save version (Ctrl+S)\">\n <i class=\"fa-solid fa-save\"></i> Save\n </button>\n }\n\n <!-- Refresh Component -->\n @if (state.SelectedComponent && state.IsRunning) {\n <button class=\"tb-btn\" (click)=\"RefreshComponent()\" title=\"Refresh component\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Refresh\n </button>\n }\n\n <!-- Export -->\n @if (state.SelectedComponent && state.IsRunning) {\n <div class=\"header-dropdown\" [class.open]=\"exportDropdownOpen\">\n <button class=\"tb-btn\" (click)=\"ToggleExportDropdown()\">\n <i class=\"fa-solid fa-file-export\"></i> Export\n <i class=\"fa-solid fa-chevron-down dropdown-icon\"></i>\n </button>\n @if (exportDropdownOpen) {\n <div class=\"dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"ExportToArtifact()\">\n <i class=\"fa-solid fa-save\"></i> To Artifact\n </button>\n <button class=\"dropdown-item\" (click)=\"ExportToFile()\">\n <i class=\"fa-solid fa-file\"></i> To File\n </button>\n <button class=\"dropdown-item\" (click)=\"ExportToClipboard()\">\n <i class=\"fa-solid fa-clipboard\"></i> To Clipboard\n </button>\n </div>\n }\n </div>\n }\n\n <span class=\"toolbar-divider\"></span>\n\n <!-- AI Panel Toggle -->\n <button class=\"tb-btn icon-only\" [class.active-toggle]=\"!state.IsAIPanelCollapsed\"\n (click)=\"ToggleAIPanel()\"\n [title]=\"state.IsAIPanelCollapsed ? 'Show AI Assistant' : 'Hide AI Assistant'\">\n <i class=\"fa-solid fa-robot\"></i>\n </button>\n\n <!-- Keyboard Shortcuts -->\n <button class=\"tb-btn icon-only\" (click)=\"ShowKeyboardShortcuts = !ShowKeyboardShortcuts\"\n title=\"Keyboard shortcuts (?)\">\n <i class=\"fa-solid fa-keyboard\"></i>\n </button>\n\n <!-- Refresh -->\n <button class=\"tb-btn icon-only\" (click)=\"RefreshData()\" [disabled]=\"state.IsLoading\" title=\"Refresh data\">\n <i class=\"fa-solid fa-arrows-rotate\"></i>\n </button>\n </div>\n\n <!-- Hidden file input -->\n <input #fileInput type=\"file\" accept=\".json\" (change)=\"HandleFileSelect($event)\" style=\"display: none;\" />\n </div>\n\n <!-- ============================================================\n THREE-PANEL BODY\n ============================================================ -->\n <div class=\"studio-body\">\n\n <!-- Left Panel: Component Browser (collapsible) -->\n @if (!IsLeftPanelCollapsed) {\n <div class=\"panel panel-left\" [style.width.px]=\"leftPanelWidth\">\n <mj-component-browser\n (NewComponent)=\"OnNewComponent()\"\n (ImportFromFile)=\"ImportFromFile()\"\n (ImportFromText)=\"ImportFromText()\"\n (ImportFromArtifact)=\"ImportFromArtifact()\">\n </mj-component-browser>\n </div>\n\n <!-- Resize Handle: Left <-> Center -->\n <div class=\"resize-handle\" (mousedown)=\"OnLeftResizeStart($event)\"></div>\n }\n\n <!-- Center Panel: Workspace (side-by-side: Preview LEFT, Editor RIGHT) -->\n <div class=\"panel panel-center\">\n @if (state.SelectedComponent) {\n <!-- Preview (left side) -->\n <div class=\"workspace-preview\" [class.full-width]=\"IsEditorPanelCollapsed\" [style.flex]=\"IsEditorPanelCollapsed ? '1 1 100%' : previewFlex\">\n <div class=\"preview-sub-header\">\n <div class=\"preview-sub-left\">\n <i class=\"fa-solid fa-eye\"></i>\n <span>Preview</span>\n </div>\n <div class=\"preview-sub-right\">\n <!-- Toggle editor panel -->\n <button class=\"toggle-editors-btn\" [class.active]=\"!IsEditorPanelCollapsed\"\n (click)=\"ToggleEditorPanel()\" title=\"Toggle editor panel\">\n <i class=\"fa-solid fa-columns\"></i>\n </button>\n </div>\n </div>\n <div class=\"preview-body\">\n <mj-component-preview\n (AskAIToFix)=\"OnAskAIToFix($event)\">\n </mj-component-preview>\n </div>\n </div>\n\n <!-- Resize Handle: Preview <-> Editor (obvious center divider) -->\n @if (!IsEditorPanelCollapsed) {\n <div class=\"resize-handle center-divider\" (mousedown)=\"OnCenterResizeStart($event)\">\n <div class=\"divider-grip\"></div>\n </div>\n }\n\n <!-- Editor Tabs (right side, collapsible) -->\n @if (!IsEditorPanelCollapsed) {\n <div class=\"workspace-editors\" [style.flex]=\"editorFlex\">\n <mj-editor-tabs></mj-editor-tabs>\n </div>\n }\n } @else {\n <!-- Enhanced Empty State -->\n <div class=\"empty-state\">\n <div class=\"empty-state-content\">\n <div class=\"empty-state-icon\">\n <i class=\"fa-solid fa-rocket\"></i>\n </div>\n <h2>Ready to Build</h2>\n <p>Select a component from the browser or create a new one to get started</p>\n <div class=\"empty-state-actions\">\n <button kendoButton [themeColor]=\"'primary'\" (click)=\"OnNewComponent()\">\n <span class=\"fa-solid fa-plus\"></span> New Component\n </button>\n <button kendoButton [themeColor]=\"'base'\" (click)=\"ImportFromFile()\">\n <span class=\"fa-solid fa-file-import\"></span> Import\n </button>\n </div>\n <div class=\"quick-start-templates\">\n <span class=\"quick-start-label\">Quick start:</span>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('dashboard')\">\n <i class=\"fa-solid fa-chart-line\"></i> Dashboard\n </button>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('report')\">\n <i class=\"fa-solid fa-file-alt\"></i> Report\n </button>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('chart')\">\n <i class=\"fa-solid fa-chart-pie\"></i> Chart\n </button>\n <button class=\"quick-start-btn\" (click)=\"OnQuickStart('form')\">\n <i class=\"fa-solid fa-edit\"></i> Form\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Resize Handle: Center <-> Right -->\n @if (!state.IsAIPanelCollapsed) {\n <div class=\"resize-handle\" (mousedown)=\"OnRightResizeStart($event)\"></div>\n }\n\n <!-- Right Panel: AI Assistant -->\n @if (!state.IsAIPanelCollapsed) {\n <div class=\"panel panel-right\" [style.width.px]=\"rightPanelWidth\">\n <mj-ai-assistant-panel></mj-ai-assistant-panel>\n </div>\n }\n </div>\n\n <!-- ============================================================\n STATUS BAR\n ============================================================ -->\n <div class=\"status-bar\">\n <div class=\"status-left\">\n <span class=\"status-item\">\n <i class=\"fa-solid fa-cube\"></i>\n {{ state.FilteredComponents.length }} component{{ state.FilteredComponents.length !== 1 ? 's' : '' }}\n </span>\n </div>\n <div class=\"status-right\">\n @if (LastSavedTime) {\n <span class=\"status-item\">\n <i class=\"fa-solid fa-check-circle\"></i>\n Saved {{ LastSavedTime | date:'shortTime' }}\n </span>\n }\n <span class=\"status-item shortcut-hint\">\n <kbd>?</kbd> Shortcuts\n </span>\n </div>\n </div>\n\n <!-- ============================================================\n KEYBOARD SHORTCUTS OVERLAY\n ============================================================ -->\n @if (ShowKeyboardShortcuts) {\n <div class=\"shortcuts-overlay\" (click)=\"ShowKeyboardShortcuts = false\">\n <div class=\"shortcuts-panel\" (click)=\"$event.stopPropagation()\">\n <div class=\"shortcuts-header\">\n <h3>Keyboard Shortcuts</h3>\n <button class=\"shortcuts-close\" (click)=\"ShowKeyboardShortcuts = false\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n <div class=\"shortcuts-body\">\n <div class=\"shortcut-group\">\n <h4>General</h4>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>Ctrl</kbd> + <kbd>S</kbd></span>\n <span class=\"shortcut-desc\">Save version</span>\n </div>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>Ctrl</kbd> + <kbd>N</kbd></span>\n <span class=\"shortcut-desc\">New component</span>\n </div>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>?</kbd></span>\n <span class=\"shortcut-desc\">Toggle shortcuts</span>\n </div>\n <div class=\"shortcut-row\">\n <span class=\"shortcut-keys\"><kbd>Esc</kbd></span>\n <span class=\"shortcut-desc\">Close overlay</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- ============================================================\n NEW COMPONENT DIALOG\n ============================================================ -->\n @if (ShowNewComponentDialog) {\n <mj-new-component-dialog\n [Visible]=\"ShowNewComponentDialog\"\n (Close)=\"OnNewComponentDialogClose($event)\">\n </mj-new-component-dialog>\n }\n\n @if (ShowSaveVersionDialog) {\n <mj-save-version-dialog\n [Visible]=\"ShowSaveVersionDialog\"\n [CurrentVersion]=\"versionService.CurrentVersionNumber\"\n (Save)=\"OnSaveVersionConfirm($event)\"\n (Cancel)=\"ShowSaveVersionDialog = false\">\n </mj-save-version-dialog>\n }\n</div>\n", styles: [":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n.component-studio {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n}\n\n/* ============================================================\n TOOLBAR \u2014 unified bar with integrated breadcrumb\n ============================================================ */\n\n.component-studio .studio-toolbar {\n display: flex;\n align-items: center;\n padding: 0 8px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n z-index: 10;\n min-height: 42px;\n gap: 8px;\n}\n\n/* Left: hamburger + breadcrumb context */\n.component-studio .toolbar-context {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n flex-shrink: 1;\n overflow: hidden;\n}\n\n.component-studio .toolbar-spacer {\n flex: 1;\n}\n\n/* Right: action buttons */\n.component-studio .toolbar-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n/* ---- Toolbar buttons ---- */\n.component-studio .tb-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\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: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n white-space: nowrap;\n line-height: 1;\n}\n\n.component-studio .tb-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-default);\n}\n\n.component-studio .tb-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.component-studio .tb-btn i {\n font-size: 12px;\n}\n\n.component-studio .tb-btn.icon-only {\n padding: 5px 7px;\n}\n\n.component-studio .tb-btn.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.component-studio .tb-btn.primary:hover {\n opacity: 0.9;\n}\n\n.component-studio .tb-btn.active-toggle {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n/* ---- Breadcrumb elements inside toolbar ---- */\n.component-studio .breadcrumb-type {\n display: flex;\n align-items: center;\n gap: 5px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.component-studio .breadcrumb-type i {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.component-studio .breadcrumb-sep {\n font-size: 9px;\n color: var(--mj-border-default);\n}\n\n.component-studio .component-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 240px;\n}\n\n.component-studio .running-badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 2px 8px;\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n font-size: 11px;\n font-weight: 600;\n border-radius: 10px;\n white-space: nowrap;\n}\n\n.component-studio .running-dot-small {\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--mj-status-success);\n animation: pulse 1.5s ease-in-out infinite;\n}\n\n.component-studio .unsaved-dot {\n display: inline-block;\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--mj-status-warning);\n animation: pulse 2s infinite;\n flex-shrink: 0;\n}\n\n.component-studio .toolbar-divider {\n width: 1px;\n height: 18px;\n background: var(--mj-border-default);\n margin: 0 2px;\n flex-shrink: 0;\n}\n\n.component-studio .dropdown-icon {\n font-size: 9px;\n opacity: 0.6;\n}\n\n/* ---- Dropdown menus ---- */\n.component-studio .header-dropdown {\n position: relative;\n}\n\n.component-studio .header-dropdown .dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 100;\n min-width: 180px;\n overflow: hidden;\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 10px 16px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: background 0.15s ease;\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item:not(:last-child) {\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.component-studio .header-dropdown .dropdown-menu .dropdown-item i {\n width: 16px;\n text-align: center;\n color: var(--mj-brand-primary);\n font-size: 13px;\n}\n\n/* ============================================================\n THREE-PANEL BODY\n ============================================================ */\n\n.component-studio .studio-body {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n\n.component-studio .panel {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--mj-bg-surface);\n}\n\n.component-studio .panel-left {\n flex-shrink: 0;\n border-right: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio .panel-center {\n flex: 1;\n display: flex;\n flex-direction: row;\n min-width: 400px;\n}\n\n/* Preview pane (left side of center) */\n.component-studio .panel-center .workspace-preview {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-right: 1px solid var(--mj-border-default);\n}\n\n.component-studio .panel-center .workspace-preview.full-width {\n border-right: none;\n}\n\n/* Preview sub-header */\n.component-studio .preview-sub-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n min-height: 32px;\n}\n\n.component-studio .preview-sub-left {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.component-studio .preview-sub-left i {\n font-size: 11px;\n color: var(--mj-brand-primary);\n}\n\n.component-studio .preview-sub-right {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio .toggle-editors-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\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 cursor: pointer;\n font-size: 12px;\n transition: all 0.15s ease;\n}\n\n.component-studio .toggle-editors-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n.component-studio .toggle-editors-btn.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.component-studio .preview-body {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n}\n\n/* Editor pane (right side of center) */\n.component-studio .panel-center .workspace-editors {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Right panel: AI Assistant */\n.component-studio .panel-right {\n flex-shrink: 0;\n border-left: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n}\n\n/* ============================================================\n RESIZE HANDLES\n ============================================================ */\n\n.component-studio .resize-handle {\n flex-shrink: 0;\n width: 5px;\n cursor: col-resize;\n background: transparent;\n position: relative;\n z-index: 5;\n transition: background 0.15s ease;\n}\n\n.component-studio .resize-handle:hover,\n.component-studio .resize-handle:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n/* Center divider \u2014 more obvious separator between preview and editors */\n.component-studio .resize-handle.center-divider {\n width: 7px;\n background: var(--mj-border-default);\n}\n\n.component-studio .resize-handle.center-divider:hover,\n.component-studio .resize-handle.center-divider:active {\n background: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n}\n\n.component-studio .resize-handle .divider-grip {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 3px;\n height: 32px;\n border-radius: 2px;\n background: var(--mj-text-secondary);\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.component-studio .resize-handle:hover .divider-grip {\n opacity: 0.5;\n}\n\n/* SMOOTH RESIZE TRANSITIONS */\n.component-studio:not(.resizing) .panel {\n transition: width 0.15s ease, flex 0.15s ease;\n}\n\n.component-studio:not(.resizing) .workspace-preview,\n.component-studio:not(.resizing) .workspace-editors {\n transition: flex 0.15s ease;\n}\n\n/* ============================================================\n STATUS BAR\n ============================================================ */\n\n.component-studio .status-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 2px 16px;\n background: var(--mj-bg-surface-sunken);\n border-top: 1px solid var(--mj-border-default);\n font-size: 11px;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n min-height: 24px;\n}\n\n.component-studio .status-bar .status-left {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio .status-bar .status-right {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.component-studio .status-bar .status-item {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.component-studio .status-bar kbd {\n display: inline-block;\n padding: 0 4px;\n font-size: 10px;\n font-family: inherit;\n line-height: 16px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 3px;\n}\n\n.component-studio .status-bar .shortcut-hint {\n display: flex;\n align-items: center;\n gap: 4px;\n opacity: 0.8;\n}\n\n/* ============================================================\n KEYBOARD SHORTCUTS OVERLAY\n ============================================================ */\n\n.component-studio .shortcuts-overlay {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: var(--mj-bg-overlay);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n box-shadow: var(--mj-shadow-lg);\n width: 520px;\n max-height: 80vh;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header button {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--mj-text-secondary);\n font-size: 16px;\n padding: 4px;\n border-radius: 4px;\n transition: background 0.15s ease;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-header button:hover {\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body {\n padding: 16px 20px;\n overflow-y: auto;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-group h4 {\n margin: 0 0 8px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-group + .shortcut-group {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 0;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.component-studio .shortcuts-overlay .shortcuts-panel .shortcuts-body .shortcut-row kbd {\n display: inline-block;\n padding: 2px 8px;\n font-size: 12px;\n font-family: inherit;\n line-height: 20px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n box-shadow: 0 1px 0 var(--mj-border-default);\n min-width: 24px;\n text-align: center;\n}\n\n/* ============================================================\n EMPTY STATE\n ============================================================ */\n\n.component-studio .empty-state {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface-sunken);\n}\n\n.component-studio .empty-state .empty-state-content {\n text-align: center;\n max-width: 400px;\n}\n\n.component-studio .empty-state .empty-state-content .empty-state-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 72px;\n height: 72px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n margin-bottom: 16px;\n}\n\n.component-studio .empty-state .empty-state-content .empty-state-icon i {\n font-size: 28px;\n color: var(--mj-brand-primary);\n}\n\n.component-studio .empty-state .empty-state-content i {\n color: var(--mj-border-default);\n margin-bottom: 16px;\n}\n\n.component-studio .empty-state .empty-state-content h2 {\n margin: 0 0 8px;\n font-size: 22px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.component-studio .empty-state .empty-state-content p {\n margin: 0 0 24px;\n color: var(--mj-text-secondary);\n font-size: 14px;\n line-height: 1.5;\n}\n\n.component-studio .empty-state .empty-state-content .empty-state-actions {\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n flex-wrap: wrap;\n margin-top: 16px;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n margin-right: 4px;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 12px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n border-color: var(--mj-border-default);\n}\n\n.component-studio .empty-state .empty-state-content .quick-start-templates .quick-start-btn i {\n font-size: 11px;\n color: var(--mj-brand-primary);\n margin-bottom: 0;\n}\n\n@keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.4; }\n}\n"] }]
981
981
  }], () => [{ type: i1.ComponentStudioStateService }, { type: i2.ComponentVersionService }, { type: i0.ChangeDetectorRef }, { type: i3.DialogService }, { type: i4.MJNotificationService }], { fileInput: [{
982
982
  type: ViewChild,
983
983
  args: ['fileInput', { static: false }]