@memberjunction/ng-dashboards 6.2.0-edge.5 → 6.2.0-edge.7

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 (293) hide show
  1. package/README.md +35 -0
  2. package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +2 -2
  3. package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
  4. package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/realtime/realtime-management.component.js +3 -1
  6. package/dist/AI/components/analytics/realtime/realtime-management.component.js.map +1 -1
  7. package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts +1 -1
  8. package/dist/AI/components/analytics/realtime/realtime-overview.component.js +3 -3
  9. package/dist/AI/components/analytics/realtime/realtime-overview.component.js.map +1 -1
  10. package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts +6 -4
  11. package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/realtime/realtime-session-data.js +8 -2
  13. package/dist/AI/components/analytics/realtime/realtime-session-data.js.map +1 -1
  14. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +1 -1
  15. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  16. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +21 -13
  17. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  18. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +1 -1
  19. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -1
  20. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -1
  21. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +1 -0
  22. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -1
  23. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -1
  24. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1 -0
  25. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -1
  26. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
  27. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1 -0
  28. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
  29. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +7 -1
  30. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  31. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +210 -57
  32. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  33. package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +12 -11
  34. package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -1
  35. package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +15 -15
  36. package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -1
  37. package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
  38. package/dist/AI/components/execution-monitoring.component.js +28 -16
  39. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  40. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
  41. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
  42. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +32 -8
  43. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
  44. package/dist/AI/components/tags/tags-resource.component.d.ts +1 -1
  45. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  46. package/dist/AI/components/tags/tags-resource.component.js +18 -9
  47. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  48. package/dist/AI/components/vectors/sensitive-fields.d.ts +9 -4
  49. package/dist/AI/components/vectors/sensitive-fields.d.ts.map +1 -1
  50. package/dist/AI/components/vectors/sensitive-fields.js +39 -14
  51. package/dist/AI/components/vectors/sensitive-fields.js.map +1 -1
  52. package/dist/AI/components/vectors/vector-document-rules.d.ts +13 -0
  53. package/dist/AI/components/vectors/vector-document-rules.d.ts.map +1 -1
  54. package/dist/AI/components/vectors/vector-document-rules.js +14 -0
  55. package/dist/AI/components/vectors/vector-document-rules.js.map +1 -1
  56. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +34 -14
  57. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  58. package/dist/AI/components/vectors/vector-management-resource.component.js +134 -51
  59. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  60. package/dist/AI/components/vectors/vector-store-selection.d.ts +32 -0
  61. package/dist/AI/components/vectors/vector-store-selection.d.ts.map +1 -0
  62. package/dist/AI/components/vectors/vector-store-selection.js +57 -0
  63. package/dist/AI/components/vectors/vector-store-selection.js.map +1 -0
  64. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  65. package/dist/AI/services/ai-instrumentation.service.js +4 -2
  66. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  67. package/dist/Actions/action-result-code.d.ts +80 -0
  68. package/dist/Actions/action-result-code.d.ts.map +1 -0
  69. package/dist/Actions/action-result-code.js +163 -0
  70. package/dist/Actions/action-result-code.js.map +1 -0
  71. package/dist/Actions/components/actions-overview.component.d.ts +8 -0
  72. package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
  73. package/dist/Actions/components/actions-overview.component.js +12 -9
  74. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  75. package/dist/Actions/components/execution-monitoring.component.d.ts +29 -9
  76. package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
  77. package/dist/Actions/components/execution-monitoring.component.js +65 -42
  78. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  79. package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
  80. package/dist/Actions/components/explorer/action-card.component.js +5 -4
  81. package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
  82. package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +198 -0
  83. package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -0
  84. package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +289 -0
  85. package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -0
  86. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts +29 -0
  87. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts.map +1 -0
  88. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js +666 -0
  89. package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js.map +1 -0
  90. package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts +56 -0
  91. package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts.map +1 -0
  92. package/dist/ChiefOfStaff/chief-of-staff-governance.component.js +515 -0
  93. package/dist/ChiefOfStaff/chief-of-staff-governance.component.js.map +1 -0
  94. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts +14 -0
  95. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts.map +1 -0
  96. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js +39 -0
  97. package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js.map +1 -0
  98. package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts +17 -0
  99. package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts.map +1 -0
  100. package/dist/ChiefOfStaff/chief-of-staff-overview.component.js +485 -0
  101. package/dist/ChiefOfStaff/chief-of-staff-overview.component.js.map +1 -0
  102. package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts +139 -0
  103. package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts.map +1 -0
  104. package/dist/ChiefOfStaff/chief-of-staff-page-base.js +602 -0
  105. package/dist/ChiefOfStaff/chief-of-staff-page-base.js.map +1 -0
  106. package/dist/ChiefOfStaff/index.d.ts +6 -0
  107. package/dist/ChiefOfStaff/index.d.ts.map +1 -0
  108. package/dist/ChiefOfStaff/index.js +6 -0
  109. package/dist/ChiefOfStaff/index.js.map +1 -0
  110. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  111. package/dist/Communication/communication-logs-resource.component.js +2 -1
  112. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  113. package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
  114. package/dist/Communication/communication-monitor-resource.component.js +26 -21
  115. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  116. package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
  117. package/dist/Communication/communication-runs-resource.component.js +14 -13
  118. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  119. package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
  120. package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
  121. package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
  122. package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
  123. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -1
  124. package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
  125. package/dist/ComponentStudio/services/component-version.service.d.ts.map +1 -1
  126. package/dist/ComponentStudio/services/component-version.service.js +3 -0
  127. package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
  128. package/dist/DashboardEditor/dashboard-editor.component.d.ts +17 -2
  129. package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -1
  130. package/dist/DashboardEditor/dashboard-editor.component.js +94 -43
  131. package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -1
  132. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +45 -2
  133. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  134. package/dist/DataExplorer/data-explorer-dashboard.component.js +178 -55
  135. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  136. package/dist/DataExplorer/models/explorer-state.interface.d.ts +2 -0
  137. package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
  138. package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
  139. package/dist/DevTools/graphql-console.component.js +2 -2
  140. package/dist/DevTools/lazy-module-status.component.js +2 -2
  141. package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
  142. package/dist/FormBuilder/form-builder-resource.component.js +5 -0
  143. package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
  144. package/dist/Integration/components/connections/connections.component.js +2 -2
  145. package/dist/Integration/services/integration-data.service.d.ts +1 -1
  146. package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
  147. package/dist/Integration/services/integration-data.service.js +4 -3
  148. package/dist/Integration/services/integration-data.service.js.map +1 -1
  149. package/dist/Lists/components/lists-browse-resource.component.js +1 -1
  150. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  151. package/dist/Lists/components/lists-my-lists-resource.component.js +1 -1
  152. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  153. package/dist/LoginStudio/login-studio-resource.component.d.ts +10 -2
  154. package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -1
  155. package/dist/LoginStudio/login-studio-resource.component.js +111 -77
  156. package/dist/LoginStudio/login-studio-resource.component.js.map +1 -1
  157. package/dist/MCP/mcp-dashboard.component.d.ts +24 -4
  158. package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
  159. package/dist/MCP/mcp-dashboard.component.js +118 -65
  160. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  161. package/dist/PredictiveStudio/business-predictions.view-models.d.ts +1 -1
  162. package/dist/PredictiveStudio/business-predictions.view-models.d.ts.map +1 -1
  163. package/dist/PredictiveStudio/business-predictions.view-models.js +3 -3
  164. package/dist/PredictiveStudio/business-predictions.view-models.js.map +1 -1
  165. package/dist/PredictiveStudio/components/ps-experiments.component.d.ts +6 -63
  166. package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
  167. package/dist/PredictiveStudio/components/ps-experiments.component.js +257 -521
  168. package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
  169. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts +0 -18
  170. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts.map +1 -1
  171. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +124 -251
  172. package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js.map +1 -1
  173. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts +5 -9
  174. package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
  175. package/dist/PredictiveStudio/components/ps-pipelines.component.js +98 -130
  176. package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
  177. package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts +53 -4
  178. package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
  179. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +338 -326
  180. package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
  181. package/dist/PredictiveStudio/components/ps-row-drivers.component.d.ts +19 -0
  182. package/dist/PredictiveStudio/components/ps-row-drivers.component.d.ts.map +1 -0
  183. package/dist/PredictiveStudio/components/ps-row-drivers.component.js +85 -0
  184. package/dist/PredictiveStudio/components/ps-row-drivers.component.js.map +1 -0
  185. package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts +19 -1
  186. package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
  187. package/dist/PredictiveStudio/engine/predictive-studio.engine.js +52 -2
  188. package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
  189. package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts +3 -1
  190. package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts.map +1 -1
  191. package/dist/PredictiveStudio/predictive-studio-agent-context.js +3 -0
  192. package/dist/PredictiveStudio/predictive-studio-agent-context.js.map +1 -1
  193. package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts +27 -4
  194. package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts.map +1 -1
  195. package/dist/PredictiveStudio/predictive-studio-score-history.service.js +94 -61
  196. package/dist/PredictiveStudio/predictive-studio-score-history.service.js.map +1 -1
  197. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +29 -5
  198. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
  199. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +186 -103
  200. package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
  201. package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +1 -1
  202. package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
  203. package/dist/QueryBrowser/query-browser-resource.component.d.ts +26 -0
  204. package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
  205. package/dist/QueryBrowser/query-browser-resource.component.js +375 -252
  206. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  207. package/dist/UserRoutines/user-routines-resource.component.d.ts +8 -1
  208. package/dist/UserRoutines/user-routines-resource.component.d.ts.map +1 -1
  209. package/dist/UserRoutines/user-routines-resource.component.js +22 -4
  210. package/dist/UserRoutines/user-routines-resource.component.js.map +1 -1
  211. package/dist/VersionHistory/components/diff-resource.component.d.ts.map +1 -1
  212. package/dist/VersionHistory/components/diff-resource.component.js +1 -0
  213. package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
  214. package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts +162 -0
  215. package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts.map +1 -0
  216. package/dist/VideoStudio/components/vs-archetype-editor.component.js +1105 -0
  217. package/dist/VideoStudio/components/vs-archetype-editor.component.js.map +1 -0
  218. package/dist/VideoStudio/components/vs-audio-options.component.d.ts +27 -0
  219. package/dist/VideoStudio/components/vs-audio-options.component.d.ts.map +1 -0
  220. package/dist/VideoStudio/components/vs-audio-options.component.js +119 -0
  221. package/dist/VideoStudio/components/vs-audio-options.component.js.map +1 -0
  222. package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts +105 -0
  223. package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts.map +1 -0
  224. package/dist/VideoStudio/components/vs-copilot-panel.component.js +560 -0
  225. package/dist/VideoStudio/components/vs-copilot-panel.component.js.map +1 -0
  226. package/dist/VideoStudio/components/vs-production-brief.component.d.ts +163 -0
  227. package/dist/VideoStudio/components/vs-production-brief.component.d.ts.map +1 -0
  228. package/dist/VideoStudio/components/vs-production-brief.component.js +1054 -0
  229. package/dist/VideoStudio/components/vs-production-brief.component.js.map +1 -0
  230. package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts +43 -0
  231. package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts.map +1 -0
  232. package/dist/VideoStudio/components/vs-setup-health-card.component.js +412 -0
  233. package/dist/VideoStudio/components/vs-setup-health-card.component.js.map +1 -0
  234. package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts +73 -0
  235. package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts.map +1 -0
  236. package/dist/VideoStudio/components/vs-studio-slide-in.component.js +271 -0
  237. package/dist/VideoStudio/components/vs-studio-slide-in.component.js.map +1 -0
  238. package/dist/VideoStudio/index.d.ts +12 -0
  239. package/dist/VideoStudio/index.d.ts.map +1 -0
  240. package/dist/VideoStudio/index.js +12 -0
  241. package/dist/VideoStudio/index.js.map +1 -0
  242. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts +118 -0
  243. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts.map +1 -0
  244. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js +964 -0
  245. package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js.map +1 -0
  246. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts +70 -0
  247. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts.map +1 -0
  248. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js +600 -0
  249. package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js.map +1 -0
  250. package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts +182 -0
  251. package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts.map +1 -0
  252. package/dist/VideoStudio/resources/video-studio-productions-resource.component.js +1481 -0
  253. package/dist/VideoStudio/resources/video-studio-productions-resource.component.js.map +1 -0
  254. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts +102 -0
  255. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts.map +1 -0
  256. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js +240 -0
  257. package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js.map +1 -0
  258. package/dist/VideoStudio/video-studio-agent-context.d.ts +495 -0
  259. package/dist/VideoStudio/video-studio-agent-context.d.ts.map +1 -0
  260. package/dist/VideoStudio/video-studio-agent-context.js +992 -0
  261. package/dist/VideoStudio/video-studio-agent-context.js.map +1 -0
  262. package/dist/ai-dashboards.module.d.ts +25 -21
  263. package/dist/ai-dashboards.module.d.ts.map +1 -1
  264. package/dist/ai-dashboards.module.js +25 -3
  265. package/dist/ai-dashboards.module.js.map +1 -1
  266. package/dist/module.d.ts +13 -12
  267. package/dist/module.d.ts.map +1 -1
  268. package/dist/module.js +7 -0
  269. package/dist/module.js.map +1 -1
  270. package/dist/public-api.d.ts +8 -0
  271. package/dist/public-api.d.ts.map +1 -1
  272. package/dist/public-api.js +10 -0
  273. package/dist/public-api.js.map +1 -1
  274. package/dist/shared/action-scheduled-job.d.ts.map +1 -1
  275. package/dist/shared/action-scheduled-job.js +2 -0
  276. package/dist/shared/action-scheduled-job.js.map +1 -1
  277. package/dist/video-studio-dashboards.module.d.ts +40 -0
  278. package/dist/video-studio-dashboards.module.d.ts.map +1 -0
  279. package/dist/video-studio-dashboards.module.js +159 -0
  280. package/dist/video-studio-dashboards.module.js.map +1 -0
  281. package/package.json +77 -71
  282. package/dist/PredictiveStudio/at-risk.view-models.d.ts +0 -120
  283. package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +0 -1
  284. package/dist/PredictiveStudio/at-risk.view-models.js +0 -261
  285. package/dist/PredictiveStudio/at-risk.view-models.js.map +0 -1
  286. package/dist/PredictiveStudio/components/ps-confirm-modal.component.d.ts +0 -109
  287. package/dist/PredictiveStudio/components/ps-confirm-modal.component.d.ts.map +0 -1
  288. package/dist/PredictiveStudio/components/ps-confirm-modal.component.js +0 -323
  289. package/dist/PredictiveStudio/components/ps-confirm-modal.component.js.map +0 -1
  290. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts +0 -137
  291. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts.map +0 -1
  292. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js +0 -826
  293. package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js.map +0 -1
@@ -0,0 +1,1105 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, Input, Output, } from '@angular/core';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { LogError, RunView } from '@memberjunction/core';
5
+ import { VideoStudioEngine, } from '@memberjunction/core-entities';
6
+ import { UUIDsEqual } from '@memberjunction/global';
7
+ import { ArtifactsModule, FormatVideoTime, } from '@memberjunction/ng-artifacts';
8
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
9
+ import { MJButtonDirective, MJDropdownComponent, MJNumericInputComponent, MJSwitchComponent, } from '@memberjunction/ng-ui-components';
10
+ import { ARCHETYPE_CATEGORIES, BuildArchetypeBeatStripItems, DeriveBeatKeyFromLabel, ParseArchetypeDefaultFormats, STUDIO_VIDEO_FORMATS, } from '../video-studio-agent-context';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/forms";
13
+ import * as i2 from "@memberjunction/ng-artifacts";
14
+ const _forTrack0 = ($index, $item) => $item.TrackId;
15
+ function VSArchetypeEditorComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
16
+ i0.ɵɵelementStart(0, "div", 2);
17
+ i0.ɵɵelement(1, "i", 46);
18
+ i0.ɵɵelementStart(2, "span");
19
+ i0.ɵɵtext(3);
20
+ i0.ɵɵelementEnd()();
21
+ } if (rf & 2) {
22
+ const ctx_r0 = i0.ɵɵnextContext();
23
+ i0.ɵɵadvance(3);
24
+ i0.ɵɵtextInterpolate(ctx_r0.SaveError);
25
+ } }
26
+ function VSArchetypeEditorComponent_For_58_Template(rf, ctx) { if (rf & 1) {
27
+ const _r2 = i0.ɵɵgetCurrentView();
28
+ i0.ɵɵelementStart(0, "button", 47);
29
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_For_58_Template_button_click_0_listener() { const format_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.ToggleFormat(format_r3)); });
30
+ i0.ɵɵelement(1, "mj-video-format-glyph", 48);
31
+ i0.ɵɵelementEnd();
32
+ } if (rf & 2) {
33
+ const format_r3 = ctx.$implicit;
34
+ const ctx_r0 = i0.ɵɵnextContext();
35
+ i0.ɵɵproperty("Toggleable", true)("Selected", ctx_r0.IsFormatSelected(format_r3))("disabled", ctx_r0.IsSaving);
36
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-format-" + format_r3);
37
+ i0.ɵɵadvance();
38
+ i0.ɵɵproperty("Format", format_r3);
39
+ } }
40
+ function VSArchetypeEditorComponent_Conditional_66_Template(rf, ctx) { if (rf & 1) {
41
+ const _r4 = i0.ɵɵgetCurrentView();
42
+ i0.ɵɵelementStart(0, "div", 33)(1, "span", 49);
43
+ i0.ɵɵtext(2);
44
+ i0.ɵɵelementEnd();
45
+ i0.ɵɵelementStart(3, "button", 50);
46
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_Conditional_66_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.FitBeatsToLength()); });
47
+ i0.ɵɵelementStart(4, "span");
48
+ i0.ɵɵtext(5, "Fit to length");
49
+ i0.ɵɵelementEnd()()();
50
+ } if (rf & 2) {
51
+ const ctx_r0 = i0.ɵɵnextContext();
52
+ i0.ɵɵadvance(2);
53
+ i0.ɵɵtextInterpolate2(" Beats add up to ", ctx_r0.FormatTime(ctx_r0.BeatsTotalSeconds), " of ", ctx_r0.FormatTime(ctx_r0.DefaultDurationSeconds), " ");
54
+ i0.ɵɵadvance();
55
+ i0.ɵɵproperty("disabled", ctx_r0.IsSaving);
56
+ } }
57
+ function VSArchetypeEditorComponent_For_69_Template(rf, ctx) { if (rf & 1) {
58
+ const _r5 = i0.ɵɵgetCurrentView();
59
+ i0.ɵɵelementStart(0, "div", 35)(1, "span", 51);
60
+ i0.ɵɵtext(2);
61
+ i0.ɵɵelementEnd();
62
+ i0.ɵɵelementStart(3, "input", 52);
63
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_For_69_Template_input_ngModelChange_3_listener($event) { const ɵ$index_137_r6 = i0.ɵɵrestoreView(_r5).$index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnBeatLabelChange(ɵ$index_137_r6, $event)); });
64
+ i0.ɵɵelementEnd();
65
+ i0.ɵɵelementStart(4, "input", 53);
66
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_For_69_Template_input_ngModelChange_4_listener($event) { const ɵ$index_137_r6 = i0.ɵɵrestoreView(_r5).$index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnBeatPurposeChange(ɵ$index_137_r6, $event)); });
67
+ i0.ɵɵelementEnd();
68
+ i0.ɵɵelementStart(5, "div", 54)(6, "mj-numeric-input", 55);
69
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_For_69_Template_mj_numeric_input_ngModelChange_6_listener($event) { const ɵ$index_137_r6 = i0.ɵɵrestoreView(_r5).$index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.OnBeatSecondsChange(ɵ$index_137_r6, $event)); });
70
+ i0.ɵɵelementEnd();
71
+ i0.ɵɵelementStart(7, "span", 56);
72
+ i0.ɵɵtext(8);
73
+ i0.ɵɵelementEnd()();
74
+ i0.ɵɵelementStart(9, "div", 57)(10, "button", 58);
75
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_For_69_Template_button_click_10_listener() { const ɵ$index_137_r6 = i0.ɵɵrestoreView(_r5).$index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.MoveBeatUp(ɵ$index_137_r6)); });
76
+ i0.ɵɵelement(11, "i", 59);
77
+ i0.ɵɵelementEnd();
78
+ i0.ɵɵelementStart(12, "button", 58);
79
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_For_69_Template_button_click_12_listener() { const ɵ$index_137_r6 = i0.ɵɵrestoreView(_r5).$index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.MoveBeatDown(ɵ$index_137_r6)); });
80
+ i0.ɵɵelement(13, "i", 60);
81
+ i0.ɵɵelementEnd();
82
+ i0.ɵɵelementStart(14, "button", 58);
83
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_For_69_Template_button_click_14_listener() { const ɵ$index_137_r6 = i0.ɵɵrestoreView(_r5).$index; const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.RemoveBeat(ɵ$index_137_r6)); });
84
+ i0.ɵɵelement(15, "i", 61);
85
+ i0.ɵɵelementEnd()()();
86
+ } if (rf & 2) {
87
+ const beat_r7 = ctx.$implicit;
88
+ const ɵ$index_137_r6 = ctx.$index;
89
+ const ctx_r0 = i0.ɵɵnextContext();
90
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-row-" + ɵ$index_137_r6);
91
+ i0.ɵɵadvance(2);
92
+ i0.ɵɵtextInterpolate1(" ", ɵ$index_137_r6 + 1, " ");
93
+ i0.ɵɵadvance();
94
+ i0.ɵɵproperty("ngModel", beat_r7.Label)("disabled", ctx_r0.IsSaving);
95
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-label-" + ɵ$index_137_r6)("aria-label", "Beat " + (ɵ$index_137_r6 + 1) + " label");
96
+ i0.ɵɵadvance();
97
+ i0.ɵɵproperty("ngModel", beat_r7.Purpose)("disabled", ctx_r0.IsSaving);
98
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-purpose-" + ɵ$index_137_r6)("aria-label", "Beat " + (ɵ$index_137_r6 + 1) + " purpose");
99
+ i0.ɵɵadvance(2);
100
+ i0.ɵɵproperty("AriaLabel", "Beat " + (ɵ$index_137_r6 + 1) + " seconds")("Min", 1)("Max", 600)("Step", 1)("Disabled", ctx_r0.IsSaving)("ngModel", beat_r7.Seconds);
101
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-seconds-" + ɵ$index_137_r6);
102
+ i0.ɵɵadvance(2);
103
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.FormatTime(beat_r7.Seconds), " ");
104
+ i0.ɵɵadvance(2);
105
+ i0.ɵɵproperty("AriaLabel", "Move beat " + (ɵ$index_137_r6 + 1) + " up")("disabled", ctx_r0.IsSaving || ɵ$index_137_r6 === 0);
106
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-up-" + ɵ$index_137_r6);
107
+ i0.ɵɵadvance(2);
108
+ i0.ɵɵproperty("AriaLabel", "Move beat " + (ɵ$index_137_r6 + 1) + " down")("disabled", ctx_r0.IsSaving || ɵ$index_137_r6 === ctx_r0.Beats.length - 1);
109
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-down-" + ɵ$index_137_r6);
110
+ i0.ɵɵadvance(2);
111
+ i0.ɵɵproperty("AriaLabel", "Remove beat " + (ɵ$index_137_r6 + 1))("disabled", ctx_r0.IsSaving || ctx_r0.Beats.length <= 1);
112
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-remove-" + ɵ$index_137_r6);
113
+ } }
114
+ function VSArchetypeEditorComponent_Conditional_80_For_22_Template(rf, ctx) { if (rf & 1) {
115
+ const _r9 = i0.ɵɵgetCurrentView();
116
+ i0.ɵɵelementStart(0, "div", 69)(1, "span", 70);
117
+ i0.ɵɵtext(2);
118
+ i0.ɵɵelementEnd();
119
+ i0.ɵɵelementStart(3, "div", 71)(4, "mj-switch", 72);
120
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Conditional_80_For_22_Template_mj_switch_ngModelChange_4_listener($event) { const beat_r10 = i0.ɵɵrestoreView(_r9).$implicit; i0.ɵɵtwoWayBindingSet(beat_r10.RequiresDataBinding, $event) || (beat_r10.RequiresDataBinding = $event); return i0.ɵɵresetView($event); });
121
+ i0.ɵɵelementEnd();
122
+ i0.ɵɵelementStart(5, "span", 6);
123
+ i0.ɵɵtext(6, "Data bound");
124
+ i0.ɵɵelementEnd()();
125
+ i0.ɵɵelementStart(7, "input", 73);
126
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Conditional_80_For_22_Template_input_ngModelChange_7_listener($event) { const beat_r10 = i0.ɵɵrestoreView(_r9).$implicit; i0.ɵɵtwoWayBindingSet(beat_r10.Guidance, $event) || (beat_r10.Guidance = $event); return i0.ɵɵresetView($event); });
127
+ i0.ɵɵelementEnd()();
128
+ } if (rf & 2) {
129
+ const beat_r10 = ctx.$implicit;
130
+ const ɵ$index_224_r11 = ctx.$index;
131
+ const ctx_r0 = i0.ɵɵnextContext(2);
132
+ i0.ɵɵadvance(2);
133
+ i0.ɵɵtextInterpolate2(" ", ɵ$index_224_r11 + 1, ". ", beat_r10.Label || "Beat " + (ɵ$index_224_r11 + 1), " ");
134
+ i0.ɵɵadvance(2);
135
+ i0.ɵɵproperty("AriaLabel", "Requires data binding for " + (beat_r10.Label || "Beat " + (ɵ$index_224_r11 + 1)))("Disabled", ctx_r0.IsSaving);
136
+ i0.ɵɵtwoWayProperty("ngModel", beat_r10.RequiresDataBinding);
137
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-databinding-" + ɵ$index_224_r11);
138
+ i0.ɵɵadvance(3);
139
+ i0.ɵɵtwoWayProperty("ngModel", beat_r10.Guidance);
140
+ i0.ɵɵproperty("disabled", ctx_r0.IsSaving);
141
+ i0.ɵɵattribute("data-testid", "vs-arch-editor-beat-guidance-" + ɵ$index_224_r11)("aria-label", "Guidance for " + (beat_r10.Label || "Beat " + (ɵ$index_224_r11 + 1)));
142
+ } }
143
+ function VSArchetypeEditorComponent_Conditional_80_Template(rf, ctx) { if (rf & 1) {
144
+ const _r8 = i0.ɵɵgetCurrentView();
145
+ i0.ɵɵelementStart(0, "div", 42)(1, "label", 3)(2, "span", 9);
146
+ i0.ɵɵtext(3, "Guidance (markdown)");
147
+ i0.ɵɵelementEnd();
148
+ i0.ɵɵelementStart(4, "textarea", 62);
149
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Conditional_80_Template_textarea_ngModelChange_4_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.Guidance, $event) || (ctx_r0.Guidance = $event); return i0.ɵɵresetView($event); });
150
+ i0.ɵɵelementEnd()();
151
+ i0.ɵɵelementStart(5, "div", 63)(6, "div", 3)(7, "div", 4)(8, "span", 64);
152
+ i0.ɵɵtext(9, " Average cut cadence (s) ");
153
+ i0.ɵɵelementEnd();
154
+ i0.ɵɵelementStart(10, "span", 65);
155
+ i0.ɵɵtext(11);
156
+ i0.ɵɵelementEnd()();
157
+ i0.ɵɵelementStart(12, "mj-numeric-input", 66);
158
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Conditional_80_Template_mj_numeric_input_ngModelChange_12_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.PacingAvgSeconds, $event) || (ctx_r0.PacingAvgSeconds = $event); return i0.ɵɵresetView($event); });
159
+ i0.ɵɵelementEnd()();
160
+ i0.ɵɵelementStart(13, "label", 3)(14, "span", 9);
161
+ i0.ɵɵtext(15, "Hold rules");
162
+ i0.ɵɵelementEnd();
163
+ i0.ɵɵelementStart(16, "input", 67);
164
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Conditional_80_Template_input_ngModelChange_16_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.PacingHoldRules, $event) || (ctx_r0.PacingHoldRules = $event); return i0.ɵɵresetView($event); });
165
+ i0.ɵɵelementEnd()()();
166
+ i0.ɵɵelementStart(17, "div", 3)(18, "span", 9);
167
+ i0.ɵɵtext(19, "Beat data binding & guidance");
168
+ i0.ɵɵelementEnd();
169
+ i0.ɵɵelementStart(20, "div", 68);
170
+ i0.ɵɵrepeaterCreate(21, VSArchetypeEditorComponent_Conditional_80_For_22_Template, 8, 10, "div", 69, _forTrack0);
171
+ i0.ɵɵelementEnd()()();
172
+ } if (rf & 2) {
173
+ const ctx_r0 = i0.ɵɵnextContext();
174
+ i0.ɵɵadvance(4);
175
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.Guidance);
176
+ i0.ɵɵproperty("disabled", ctx_r0.IsSaving);
177
+ i0.ɵɵadvance(7);
178
+ i0.ɵɵtextInterpolate1(" ", ctx_r0.FormatTime(ctx_r0.PacingAvgSeconds), " ");
179
+ i0.ɵɵadvance();
180
+ i0.ɵɵproperty("Min", 0.5)("Max", 60)("Step", 0.5)("Disabled", ctx_r0.IsSaving);
181
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.PacingAvgSeconds);
182
+ i0.ɵɵadvance(4);
183
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r0.PacingHoldRules);
184
+ i0.ɵɵproperty("disabled", ctx_r0.IsSaving);
185
+ i0.ɵɵadvance(5);
186
+ i0.ɵɵrepeater(ctx_r0.Beats);
187
+ } }
188
+ /**
189
+ * Dialog body component (`<vs-archetype-editor>`) for creating a company copy of any
190
+ * video archetype or editing an existing company archetype.
191
+ *
192
+ * Plan rules (§4.3, §12): shipped archetypes (`CompanyID === null`) are read-only
193
+ * templates; a company makes its own by copying one. `Name` is unique per company
194
+ * scope; `Category` is one of the 7 CHECK values; beats are persisted as a valid
195
+ * `VideoBeatTemplate[]` (`Key`, `Label`, `Purpose`, `MinDurationSeconds`,
196
+ * `MaxDurationSeconds`, `DefaultDurationSeconds`, optional `Guidance` and
197
+ * `RequiresDataBinding`); `Pacing` is `VideoPacing`. Saves go through the
198
+ * `MJ: Video Archetypes` entity object and refresh `VideoStudioEngine`.
199
+ */
200
+ export class VSArchetypeEditorComponent extends BaseAngularComponent {
201
+ Mode = 'copy';
202
+ SourceArchetypeId = null;
203
+ EditingArchetypeId = null;
204
+ Archetypes = null;
205
+ Companies = null;
206
+ InitialCompanyId = null;
207
+ Saved = new EventEmitter();
208
+ Cancelled = new EventEmitter();
209
+ AvailableArchetypes = [];
210
+ AvailableCompanies = [];
211
+ StartFromOptions = [];
212
+ CategoryOptions = ARCHETYPE_CATEGORIES.map((cat) => ({
213
+ Value: cat,
214
+ Text: cat === 'DataStory' ? 'Data Story' : cat,
215
+ }));
216
+ AvailableFormats = STUDIO_VIDEO_FORMATS;
217
+ SelectedSourceId = '';
218
+ Name = '';
219
+ Category = 'Explainer';
220
+ CompanyID = '';
221
+ Description = '';
222
+ DefaultDurationSeconds = 60;
223
+ MinDurationSeconds = 30;
224
+ MaxDurationSeconds = 120;
225
+ SelectedFormats = ['16:9'];
226
+ DefaultInteractionMode = 'Autonomous';
227
+ Beats = [];
228
+ IsAdvancedOpen = false;
229
+ Guidance = '';
230
+ PacingAvgSeconds = 5;
231
+ PacingHoldRules = '';
232
+ IsSaving = false;
233
+ SaveError = null;
234
+ nextBeatTrackId = 1;
235
+ lastAutoSuggestedName = '';
236
+ sourcePacing = null;
237
+ companiesLoadError = null;
238
+ cdr = inject(ChangeDetectorRef);
239
+ async ngOnInit() {
240
+ await this.initializeEditor();
241
+ }
242
+ get IsEditingExistingCompanyArchetype() {
243
+ if (this.Mode !== 'edit' || !this.EditingArchetypeId) {
244
+ return false;
245
+ }
246
+ const target = this.findArchetypeById(this.EditingArchetypeId);
247
+ if (!target) {
248
+ return true;
249
+ }
250
+ return Boolean(target.CompanyID && target.CompanyID.trim().length > 0);
251
+ }
252
+ get BeatsTotalSeconds() {
253
+ return this.Beats.reduce((sum, beat) => sum + Math.max(1, Math.round(Number(beat.Seconds) || 1)), 0);
254
+ }
255
+ get BeatsSumSeconds() {
256
+ return this.BeatsTotalSeconds;
257
+ }
258
+ get HasBeatsDurationMismatch() {
259
+ return (this.Beats.length > 0 &&
260
+ this.BeatsTotalSeconds !== Math.max(1, Math.round(Number(this.DefaultDurationSeconds) || 1)));
261
+ }
262
+ get HasDurationMismatch() {
263
+ return this.HasBeatsDurationMismatch;
264
+ }
265
+ get LiveBeatStripItems() {
266
+ const keys = this.resolveBeatKeys();
267
+ return this.Beats.map((beat, idx) => {
268
+ const label = (beat.Label ?? '').trim() || `Beat ${idx + 1}`;
269
+ const seconds = Math.max(1, Math.round(Number(beat.Seconds) || 1));
270
+ const detail = (beat.Purpose ?? '').trim();
271
+ return {
272
+ Key: keys[idx],
273
+ Label: label,
274
+ Seconds: seconds,
275
+ ...(detail ? { Detail: detail } : {}),
276
+ };
277
+ });
278
+ }
279
+ FormatTime(seconds) {
280
+ const safe = Number.isFinite(seconds) && seconds >= 0 ? Math.round(seconds) : 0;
281
+ return FormatVideoTime(safe);
282
+ }
283
+ OnStartFromChange(sourceId) {
284
+ const trimmed = (sourceId ?? '').trim();
285
+ if (!trimmed) {
286
+ return;
287
+ }
288
+ this.SelectedSourceId = trimmed;
289
+ const source = this.findArchetypeById(trimmed);
290
+ if (!source) {
291
+ return;
292
+ }
293
+ this.applySourceArchetype(source, false);
294
+ this.cdr.markForCheck();
295
+ }
296
+ OnDefaultDurationChange(value) {
297
+ const numeric = typeof value === 'number' ? value : Number(value);
298
+ if (Number.isFinite(numeric) && numeric > 0) {
299
+ this.DefaultDurationSeconds = Math.max(1, Math.round(numeric));
300
+ }
301
+ this.cdr.markForCheck();
302
+ }
303
+ OnMinDurationChange(value) {
304
+ const numeric = typeof value === 'number' ? value : Number(value);
305
+ if (Number.isFinite(numeric) && numeric > 0) {
306
+ this.MinDurationSeconds = Math.max(1, Math.round(numeric));
307
+ }
308
+ this.cdr.markForCheck();
309
+ }
310
+ OnMaxDurationChange(value) {
311
+ const numeric = typeof value === 'number' ? value : Number(value);
312
+ if (Number.isFinite(numeric) && numeric > 0) {
313
+ this.MaxDurationSeconds = Math.max(1, Math.round(numeric));
314
+ }
315
+ this.cdr.markForCheck();
316
+ }
317
+ IsFormatSelected(format) {
318
+ return this.SelectedFormats.includes(format);
319
+ }
320
+ ToggleFormat(format) {
321
+ if (this.SelectedFormats.includes(format)) {
322
+ if (this.SelectedFormats.length > 1) {
323
+ this.SelectedFormats = this.SelectedFormats.filter((f) => f !== format);
324
+ }
325
+ }
326
+ else {
327
+ this.SelectedFormats = [...this.SelectedFormats, format];
328
+ }
329
+ this.cdr.markForCheck();
330
+ }
331
+ OnBeatLabelChange(index, label) {
332
+ const beat = this.Beats[index];
333
+ if (!beat) {
334
+ return;
335
+ }
336
+ beat.Label = label ?? '';
337
+ this.Beats = [...this.Beats];
338
+ this.cdr.markForCheck();
339
+ }
340
+ OnBeatPurposeChange(index, purpose) {
341
+ const beat = this.Beats[index];
342
+ if (!beat) {
343
+ return;
344
+ }
345
+ beat.Purpose = purpose ?? '';
346
+ this.Beats = [...this.Beats];
347
+ this.cdr.markForCheck();
348
+ }
349
+ OnBeatSecondsChange(index, value) {
350
+ const beat = this.Beats[index];
351
+ if (!beat) {
352
+ return;
353
+ }
354
+ const numeric = typeof value === 'number' ? value : Number(value);
355
+ const seconds = Number.isFinite(numeric) && numeric >= 1 ? Math.round(numeric) : 1;
356
+ beat.Seconds = seconds;
357
+ beat.MinDurationSeconds =
358
+ beat.MinDurationSeconds > 0
359
+ ? Math.min(beat.MinDurationSeconds, seconds)
360
+ : Math.max(1, Math.floor(seconds * 0.6));
361
+ beat.MaxDurationSeconds = Math.max(seconds, beat.MaxDurationSeconds || seconds);
362
+ this.Beats = [...this.Beats];
363
+ this.cdr.markForCheck();
364
+ }
365
+ MoveBeatUp(index) {
366
+ if (index <= 0 || index >= this.Beats.length) {
367
+ return;
368
+ }
369
+ const next = [...this.Beats];
370
+ const temp = next[index - 1];
371
+ next[index - 1] = next[index];
372
+ next[index] = temp;
373
+ this.Beats = next;
374
+ this.cdr.markForCheck();
375
+ }
376
+ MoveBeatDown(index) {
377
+ if (index < 0 || index >= this.Beats.length - 1) {
378
+ return;
379
+ }
380
+ const next = [...this.Beats];
381
+ const temp = next[index + 1];
382
+ next[index + 1] = next[index];
383
+ next[index] = temp;
384
+ this.Beats = next;
385
+ this.cdr.markForCheck();
386
+ }
387
+ RemoveBeat(index) {
388
+ if (this.Beats.length <= 1 || index < 0 || index >= this.Beats.length) {
389
+ return;
390
+ }
391
+ this.Beats = this.Beats.filter((_, idx) => idx !== index);
392
+ this.cdr.markForCheck();
393
+ }
394
+ AddBeat() {
395
+ const nextIdx = this.Beats.length + 1;
396
+ this.Beats = [
397
+ ...this.Beats,
398
+ {
399
+ TrackId: this.nextBeatTrackId++,
400
+ Key: '',
401
+ Label: `Beat ${nextIdx}`,
402
+ Purpose: 'Advance the story with a clear visual focus.',
403
+ Seconds: 5,
404
+ MinDurationSeconds: 3,
405
+ MaxDurationSeconds: 10,
406
+ Guidance: '',
407
+ RequiresDataBinding: false,
408
+ },
409
+ ];
410
+ this.cdr.markForCheck();
411
+ }
412
+ /**
413
+ * Scales all beat durations with {@link BuildArchetypeBeatStripItems} so their
414
+ * integer `Seconds` sum to `DefaultDurationSeconds`.
415
+ */
416
+ FitBeatsToLength() {
417
+ if (this.Beats.length === 0) {
418
+ return;
419
+ }
420
+ const targetDuration = Math.max(this.Beats.length, Math.round(Number(this.DefaultDurationSeconds) || 30));
421
+ this.DefaultDurationSeconds = targetDuration;
422
+ const keys = this.resolveBeatKeys();
423
+ const inputs = this.Beats.map((b, idx) => ({
424
+ Key: keys[idx],
425
+ Label: b.Label,
426
+ Purpose: b.Purpose,
427
+ DefaultDurationSeconds: Math.max(1, Math.round(Number(b.Seconds) || 1)),
428
+ MinDurationSeconds: b.MinDurationSeconds,
429
+ MaxDurationSeconds: b.MaxDurationSeconds,
430
+ }));
431
+ const scaled = BuildArchetypeBeatStripItems(inputs, targetDuration);
432
+ this.Beats = this.Beats.map((beat, idx) => {
433
+ const nextSeconds = scaled[idx]?.Seconds ?? beat.Seconds;
434
+ return {
435
+ ...beat,
436
+ Seconds: nextSeconds,
437
+ MinDurationSeconds: beat.MinDurationSeconds > 0
438
+ ? Math.min(beat.MinDurationSeconds, nextSeconds)
439
+ : Math.max(1, Math.floor(nextSeconds * 0.6)),
440
+ MaxDurationSeconds: Math.max(nextSeconds, beat.MaxDurationSeconds),
441
+ };
442
+ });
443
+ this.cdr.markForCheck();
444
+ }
445
+ ToggleAdvanced() {
446
+ this.IsAdvancedOpen = !this.IsAdvancedOpen;
447
+ this.cdr.markForCheck();
448
+ }
449
+ BuildBeatTemplatePayload() {
450
+ const keys = this.resolveBeatKeys();
451
+ return this.Beats.map((beat, idx) => {
452
+ const label = (beat.Label ?? '').trim() || `Beat ${idx + 1}`;
453
+ const key = keys[idx];
454
+ const purpose = (beat.Purpose ?? '').trim() || label;
455
+ const defaultDur = Math.max(1, Math.round(Number(beat.Seconds) || 1));
456
+ const rawMin = Number(beat.MinDurationSeconds);
457
+ const minDur = Number.isFinite(rawMin) && rawMin > 0
458
+ ? Math.min(defaultDur, rawMin)
459
+ : Math.max(1, Math.floor(defaultDur * 0.6));
460
+ const rawMax = Number(beat.MaxDurationSeconds);
461
+ const maxDur = Number.isFinite(rawMax) && rawMax >= defaultDur
462
+ ? rawMax
463
+ : Math.max(defaultDur, Math.ceil(defaultDur * 1.5));
464
+ const guidance = (beat.Guidance ?? '').trim();
465
+ return {
466
+ Key: key,
467
+ Label: label,
468
+ Purpose: purpose,
469
+ MinDurationSeconds: minDur,
470
+ MaxDurationSeconds: maxDur,
471
+ DefaultDurationSeconds: defaultDur,
472
+ ...(guidance ? { Guidance: guidance } : {}),
473
+ ...(beat.RequiresDataBinding ? { RequiresDataBinding: true } : {}),
474
+ };
475
+ });
476
+ }
477
+ BuildPacingPayload() {
478
+ const numericAvg = Number(this.PacingAvgSeconds);
479
+ const avg = Number.isFinite(numericAvg) && numericAvg > 0
480
+ ? numericAvg
481
+ : 5;
482
+ return {
483
+ ...(this.sourcePacing ?? {}),
484
+ AvgSecondsBetweenChanges: avg,
485
+ HoldRules: (this.PacingHoldRules ?? '').trim(),
486
+ };
487
+ }
488
+ Cancel() {
489
+ this.Cancelled.emit();
490
+ }
491
+ async Save() {
492
+ if (this.IsSaving) {
493
+ return;
494
+ }
495
+ const trimmedName = (this.Name ?? '').trim();
496
+ if (!trimmedName) {
497
+ this.SaveError = 'Please enter a name for the archetype.';
498
+ this.cdr.markForCheck();
499
+ return;
500
+ }
501
+ const companyId = (this.CompanyID ?? '').trim();
502
+ if (!companyId) {
503
+ this.SaveError =
504
+ this.companiesLoadError || 'Please select a company for this archetype.';
505
+ this.cdr.markForCheck();
506
+ return;
507
+ }
508
+ if (this.Beats.length === 0) {
509
+ this.SaveError = 'Add at least one beat to the archetype.';
510
+ this.cdr.markForCheck();
511
+ return;
512
+ }
513
+ const rawDefaultDur = Number(this.DefaultDurationSeconds);
514
+ const rawMinDur = Number(this.MinDurationSeconds);
515
+ const rawMaxDur = Number(this.MaxDurationSeconds);
516
+ if (!Number.isFinite(rawDefaultDur) ||
517
+ !Number.isFinite(rawMinDur) ||
518
+ !Number.isFinite(rawMaxDur) ||
519
+ rawMinDur < 1 ||
520
+ rawDefaultDur < 1 ||
521
+ rawMaxDur < 1 ||
522
+ rawMinDur > rawDefaultDur ||
523
+ rawDefaultDur > rawMaxDur) {
524
+ this.SaveError =
525
+ 'Shortest length, default length, and longest length must satisfy Shortest <= Default <= Longest.';
526
+ this.cdr.markForCheck();
527
+ return;
528
+ }
529
+ const defaultDur = Math.round(rawDefaultDur);
530
+ const minDur = Math.round(rawMinDur);
531
+ const maxDur = Math.round(rawMaxDur);
532
+ const isEditing = this.IsEditingExistingCompanyArchetype;
533
+ const duplicate = this.AvailableArchetypes.find((arch) => {
534
+ if (!arch.CompanyID || !UUIDsEqual(arch.CompanyID, companyId)) {
535
+ return false;
536
+ }
537
+ if (isEditing && this.EditingArchetypeId && UUIDsEqual(arch.ID, this.EditingArchetypeId)) {
538
+ return false;
539
+ }
540
+ return (arch.Name ?? '').trim().toLowerCase() === trimmedName.toLowerCase();
541
+ });
542
+ if (duplicate) {
543
+ this.SaveError = `An archetype named "${trimmedName}" already exists for this company.`;
544
+ this.cdr.markForCheck();
545
+ return;
546
+ }
547
+ this.IsSaving = true;
548
+ this.SaveError = null;
549
+ this.cdr.markForCheck();
550
+ try {
551
+ const entity = await this.ProviderToUse.GetEntityObject('MJ: Video Archetypes', this.ProviderToUse.CurrentUser);
552
+ if (isEditing && this.EditingArchetypeId && typeof entity.Load === 'function') {
553
+ const loaded = await entity.Load(this.EditingArchetypeId);
554
+ if (!loaded) {
555
+ this.SaveError = 'Unable to load the company archetype for editing.';
556
+ return;
557
+ }
558
+ }
559
+ const beatTemplates = this.BuildBeatTemplatePayload();
560
+ const pacingPayload = this.BuildPacingPayload();
561
+ const formatsList = this.SelectedFormats.length > 0 ? this.SelectedFormats : ['16:9'];
562
+ entity.Name = trimmedName;
563
+ entity.Description = (this.Description ?? '').trim();
564
+ entity.Category = this.Category;
565
+ entity.CompanyID = companyId;
566
+ entity.DefaultDurationSeconds = defaultDur;
567
+ entity.MinDurationSeconds = minDur;
568
+ entity.MaxDurationSeconds = maxDur;
569
+ entity.DefaultFormats = formatsList.join(',');
570
+ entity.DefaultInteractionMode = (this.DefaultInteractionMode ||
571
+ 'Autonomous');
572
+ entity.Guidance = (this.Guidance ?? '').trim() || null;
573
+ if (!isEditing) {
574
+ entity.Status = 'Active';
575
+ }
576
+ entity.BeatTemplate = JSON.stringify(beatTemplates);
577
+ try {
578
+ entity.BeatTemplateObject = beatTemplates;
579
+ }
580
+ catch {
581
+ // Test doubles that do not implement BaseEntity JSON accessors still keep BeatTemplate.
582
+ }
583
+ entity.Pacing = JSON.stringify(pacingPayload);
584
+ try {
585
+ entity.PacingObject = pacingPayload;
586
+ }
587
+ catch {
588
+ // Test doubles that do not implement BaseEntity JSON accessors still keep Pacing.
589
+ }
590
+ const saved = await entity.Save();
591
+ if (!saved) {
592
+ this.SaveError =
593
+ entity.LatestResult?.CompleteMessage || 'Failed to save archetype.';
594
+ return;
595
+ }
596
+ try {
597
+ const engine = VideoStudioEngine.GetProviderInstance(this.ProviderToUse, VideoStudioEngine);
598
+ await engine.Config(true, this.ProviderToUse?.CurrentUser, this.ProviderToUse);
599
+ }
600
+ catch {
601
+ // Non-fatal in isolated component tests.
602
+ }
603
+ this.Saved.emit(entity.ID);
604
+ }
605
+ catch (err) {
606
+ const msg = err instanceof Error ? err.message : String(err);
607
+ LogError(msg);
608
+ this.SaveError = msg;
609
+ }
610
+ finally {
611
+ this.IsSaving = false;
612
+ this.cdr.markForCheck();
613
+ }
614
+ }
615
+ resolveBeatKeys() {
616
+ const usedKeys = new Set();
617
+ for (const beat of this.Beats) {
618
+ const existing = (beat.Key ?? '').trim();
619
+ if (existing) {
620
+ usedKeys.add(existing);
621
+ }
622
+ }
623
+ return this.Beats.map((beat, idx) => {
624
+ const existing = (beat.Key ?? '').trim();
625
+ if (existing) {
626
+ return existing;
627
+ }
628
+ const label = (beat.Label ?? '').trim() || `Beat ${idx + 1}`;
629
+ return DeriveBeatKeyFromLabel(label, idx + 1, usedKeys);
630
+ });
631
+ }
632
+ async initializeEditor() {
633
+ if (Array.isArray(this.Archetypes) && this.Archetypes.length > 0) {
634
+ this.AvailableArchetypes = [...this.Archetypes];
635
+ }
636
+ else {
637
+ await this.loadEngineArchetypes();
638
+ }
639
+ if (Array.isArray(this.Companies) && this.Companies.length > 0) {
640
+ this.AvailableCompanies = [...this.Companies];
641
+ }
642
+ else {
643
+ await this.loadAvailableCompanies();
644
+ }
645
+ if (this.companiesLoadError) {
646
+ this.SaveError = this.companiesLoadError;
647
+ }
648
+ this.StartFromOptions = this.AvailableArchetypes.map((arch) => {
649
+ const isShipped = arch.IsShipped !== undefined ? arch.IsShipped : arch.CompanyID == null;
650
+ const scopeSuffix = isShipped
651
+ ? 'Shipped'
652
+ : (arch.CompanyName ?? arch.Company ?? 'Company');
653
+ return {
654
+ ID: arch.ID,
655
+ Label: `${arch.Name} (${scopeSuffix})`,
656
+ };
657
+ });
658
+ const initialId = (this.Mode === 'edit' && this.EditingArchetypeId
659
+ ? this.EditingArchetypeId
660
+ : this.SourceArchetypeId) ?? '';
661
+ const initialSource = initialId ? this.findArchetypeById(initialId) : null;
662
+ if (initialSource) {
663
+ this.SelectedSourceId = initialSource.ID;
664
+ this.applySourceArchetype(initialSource, true);
665
+ }
666
+ else {
667
+ this.SelectedSourceId = '';
668
+ this.Name = '';
669
+ this.Description = '';
670
+ this.Category = 'Explainer';
671
+ this.CompanyID = this.resolveInitialCompanyId(null);
672
+ this.DefaultDurationSeconds = 30;
673
+ this.MinDurationSeconds = 15;
674
+ this.MaxDurationSeconds = 60;
675
+ this.SelectedFormats = ['16:9'];
676
+ this.DefaultInteractionMode = 'Autonomous';
677
+ this.Guidance = '';
678
+ this.sourcePacing = null;
679
+ this.PacingAvgSeconds = 5;
680
+ this.PacingHoldRules = '';
681
+ this.Beats = [
682
+ {
683
+ TrackId: this.nextBeatTrackId++,
684
+ Key: '',
685
+ Label: '',
686
+ Purpose: '',
687
+ Seconds: 30,
688
+ MinDurationSeconds: 15,
689
+ MaxDurationSeconds: 60,
690
+ Guidance: '',
691
+ RequiresDataBinding: false,
692
+ },
693
+ ];
694
+ }
695
+ this.cdr.markForCheck();
696
+ }
697
+ applySourceArchetype(source, isInitialLoad) {
698
+ const isEditingTarget = isInitialLoad &&
699
+ this.IsEditingExistingCompanyArchetype &&
700
+ this.EditingArchetypeId !== null &&
701
+ UUIDsEqual(source.ID, this.EditingArchetypeId);
702
+ if (isEditingTarget) {
703
+ this.Name = source.Name ?? '';
704
+ this.lastAutoSuggestedName = '';
705
+ }
706
+ else {
707
+ const copyName = `${source.Name} (Copy)`;
708
+ if (isInitialLoad || !this.Name.trim() || this.Name === this.lastAutoSuggestedName) {
709
+ this.Name = copyName;
710
+ this.lastAutoSuggestedName = copyName;
711
+ }
712
+ }
713
+ const rawCategory = (source.Category ?? 'Explainer').trim();
714
+ this.Category = ARCHETYPE_CATEGORIES.includes(rawCategory)
715
+ ? rawCategory
716
+ : 'Explainer';
717
+ this.Description = source.Description ?? '';
718
+ if (isInitialLoad) {
719
+ this.CompanyID = this.resolveInitialCompanyId(source.CompanyID ?? null);
720
+ }
721
+ const defaultDur = typeof source.DefaultDurationSeconds === 'number' &&
722
+ Number.isFinite(source.DefaultDurationSeconds) &&
723
+ source.DefaultDurationSeconds > 0
724
+ ? Math.round(source.DefaultDurationSeconds)
725
+ : 60;
726
+ const minDur = typeof source.MinDurationSeconds === 'number' &&
727
+ Number.isFinite(source.MinDurationSeconds) &&
728
+ source.MinDurationSeconds > 0
729
+ ? Math.round(source.MinDurationSeconds)
730
+ : 30;
731
+ const maxDur = typeof source.MaxDurationSeconds === 'number' &&
732
+ Number.isFinite(source.MaxDurationSeconds) &&
733
+ source.MaxDurationSeconds >= minDur
734
+ ? Math.round(source.MaxDurationSeconds)
735
+ : Math.max(defaultDur, 120);
736
+ this.DefaultDurationSeconds = defaultDur;
737
+ this.MinDurationSeconds = minDur;
738
+ this.MaxDurationSeconds = maxDur;
739
+ this.SelectedFormats = ParseArchetypeDefaultFormats(source.DefaultFormats);
740
+ this.DefaultInteractionMode = source.DefaultInteractionMode ?? 'Autonomous';
741
+ this.Guidance = source.Guidance ?? '';
742
+ const rawBeats = this.extractSourceBeats(source);
743
+ const scaledItems = BuildArchetypeBeatStripItems(rawBeats, defaultDur);
744
+ const allHaveExplicitDefault = rawBeats.length > 0 &&
745
+ rawBeats.every((b) => typeof b.DefaultDurationSeconds === 'number' && b.DefaultDurationSeconds > 0);
746
+ const rawExplicitSum = allHaveExplicitDefault
747
+ ? rawBeats.reduce((sum, b) => sum + (b.DefaultDurationSeconds ?? 0), 0)
748
+ : defaultDur;
749
+ const useScaledIntegerBeats = !allHaveExplicitDefault || Math.abs(rawExplicitSum - defaultDur) < 0.5;
750
+ if (rawBeats.length > 0) {
751
+ this.Beats = rawBeats.map((b, idx) => {
752
+ const seconds = useScaledIntegerBeats
753
+ ? (scaledItems[idx]?.Seconds ?? 5)
754
+ : Math.max(1, Math.round(b.DefaultDurationSeconds ?? 5));
755
+ return {
756
+ TrackId: this.nextBeatTrackId++,
757
+ Key: (b.Key ?? '').trim(),
758
+ Label: (b.Label ?? b.Key ?? '').trim() || `Beat ${idx + 1}`,
759
+ Purpose: (b.Purpose ?? '').trim(),
760
+ Seconds: seconds,
761
+ MinDurationSeconds: typeof b.MinDurationSeconds === 'number' &&
762
+ Number.isFinite(b.MinDurationSeconds) &&
763
+ b.MinDurationSeconds > 0
764
+ ? b.MinDurationSeconds
765
+ : Math.max(1, Math.floor(seconds * 0.6)),
766
+ MaxDurationSeconds: typeof b.MaxDurationSeconds === 'number' &&
767
+ Number.isFinite(b.MaxDurationSeconds) &&
768
+ b.MaxDurationSeconds > 0
769
+ ? b.MaxDurationSeconds
770
+ : Math.max(seconds, Math.ceil(seconds * 1.5)),
771
+ Guidance: (b.Guidance ?? '').trim(),
772
+ RequiresDataBinding: Boolean(b.RequiresDataBinding),
773
+ };
774
+ });
775
+ }
776
+ else {
777
+ this.Beats = [
778
+ {
779
+ TrackId: this.nextBeatTrackId++,
780
+ Key: '',
781
+ Label: 'Hook',
782
+ Purpose: 'Open with the core takeaway.',
783
+ Seconds: defaultDur,
784
+ MinDurationSeconds: minDur,
785
+ MaxDurationSeconds: maxDur,
786
+ Guidance: '',
787
+ RequiresDataBinding: false,
788
+ },
789
+ ];
790
+ }
791
+ const pacing = this.extractSourcePacing(source);
792
+ this.sourcePacing = pacing ? { ...pacing } : null;
793
+ this.PacingAvgSeconds =
794
+ pacing &&
795
+ typeof pacing.AvgSecondsBetweenChanges === 'number' &&
796
+ Number.isFinite(pacing.AvgSecondsBetweenChanges) &&
797
+ pacing.AvgSecondsBetweenChanges > 0
798
+ ? pacing.AvgSecondsBetweenChanges
799
+ : 5;
800
+ this.PacingHoldRules = pacing?.HoldRules ?? '';
801
+ }
802
+ extractSourceBeats(source) {
803
+ if (Array.isArray(source.Beats) && source.Beats.length > 0) {
804
+ return source.Beats;
805
+ }
806
+ if (Array.isArray(source.BeatTemplateObject) && source.BeatTemplateObject.length > 0) {
807
+ return source.BeatTemplateObject;
808
+ }
809
+ const rawJson = source.BeatTemplateRaw ?? source.BeatTemplate ?? null;
810
+ if (typeof rawJson === 'string' && rawJson.trim().startsWith('[')) {
811
+ try {
812
+ const parsed = JSON.parse(rawJson);
813
+ if (Array.isArray(parsed)) {
814
+ return parsed;
815
+ }
816
+ }
817
+ catch {
818
+ return [];
819
+ }
820
+ }
821
+ return [];
822
+ }
823
+ extractSourcePacing(source) {
824
+ let parsedFromRaw = null;
825
+ const rawJson = source.PacingRaw ?? (typeof source.Pacing === 'string' ? source.Pacing : null);
826
+ if (typeof rawJson === 'string' && rawJson.trim().startsWith('{')) {
827
+ try {
828
+ const parsed = JSON.parse(rawJson);
829
+ if (parsed && typeof parsed === 'object') {
830
+ parsedFromRaw = parsed;
831
+ }
832
+ }
833
+ catch {
834
+ parsedFromRaw = null;
835
+ }
836
+ }
837
+ const fromPacingObj = source.PacingObject && typeof source.PacingObject === 'object'
838
+ ? source.PacingObject
839
+ : null;
840
+ const fromPacingField = source.Pacing && typeof source.Pacing === 'object' ? source.Pacing : null;
841
+ if (!parsedFromRaw && !fromPacingObj && !fromPacingField) {
842
+ return null;
843
+ }
844
+ return {
845
+ ...(parsedFromRaw ?? {}),
846
+ ...(fromPacingField ?? {}),
847
+ ...(fromPacingObj ?? {}),
848
+ };
849
+ }
850
+ resolveInitialCompanyId(sourceCompanyId) {
851
+ if (this.InitialCompanyId &&
852
+ this.InitialCompanyId.trim().length > 0 &&
853
+ this.InitialCompanyId !== 'all') {
854
+ return this.InitialCompanyId.trim();
855
+ }
856
+ if (sourceCompanyId && sourceCompanyId.trim().length > 0) {
857
+ return sourceCompanyId.trim();
858
+ }
859
+ return this.AvailableCompanies[0]?.ID ?? '';
860
+ }
861
+ findArchetypeById(id) {
862
+ const trimmed = (id ?? '').trim();
863
+ if (!trimmed) {
864
+ return null;
865
+ }
866
+ return (this.AvailableArchetypes.find((a) => UUIDsEqual(a.ID, trimmed)) ?? null);
867
+ }
868
+ async loadEngineArchetypes() {
869
+ try {
870
+ const engine = VideoStudioEngine.GetProviderInstance(this.ProviderToUse, VideoStudioEngine);
871
+ await engine.Config(false, this.ProviderToUse?.CurrentUser, this.ProviderToUse);
872
+ this.AvailableArchetypes = [...(engine.Archetypes ?? [])];
873
+ }
874
+ catch {
875
+ this.AvailableArchetypes = [];
876
+ }
877
+ }
878
+ async loadAvailableCompanies() {
879
+ this.companiesLoadError = null;
880
+ try {
881
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
882
+ const res = await rv.RunView({
883
+ EntityName: 'MJ: Companies',
884
+ Fields: ['ID', 'Name'],
885
+ OrderBy: 'Name ASC',
886
+ ResultType: 'simple',
887
+ });
888
+ if (!res.Success) {
889
+ const msg = res.ErrorMessage || 'Failed to load companies.';
890
+ LogError(msg);
891
+ this.companiesLoadError = `Couldn't load companies: ${msg}`;
892
+ return;
893
+ }
894
+ if (Array.isArray(res.Results)) {
895
+ this.AvailableCompanies = res.Results.map((r) => ({
896
+ ID: r.ID,
897
+ Name: r.Name,
898
+ }));
899
+ }
900
+ }
901
+ catch (err) {
902
+ const msg = err instanceof Error ? err.message : String(err);
903
+ LogError(msg);
904
+ this.companiesLoadError = `Couldn't load companies: ${msg}`;
905
+ }
906
+ }
907
+ static ɵfac = /*@__PURE__*/ (() => { let ɵVSArchetypeEditorComponent_BaseFactory; return function VSArchetypeEditorComponent_Factory(__ngFactoryType__) { return (ɵVSArchetypeEditorComponent_BaseFactory || (ɵVSArchetypeEditorComponent_BaseFactory = i0.ɵɵgetInheritedFactory(VSArchetypeEditorComponent)))(__ngFactoryType__ || VSArchetypeEditorComponent); }; })();
908
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: VSArchetypeEditorComponent, selectors: [["vs-archetype-editor"]], inputs: { Mode: "Mode", SourceArchetypeId: "SourceArchetypeId", EditingArchetypeId: "EditingArchetypeId", Archetypes: "Archetypes", Companies: "Companies", InitialCompanyId: "InitialCompanyId" }, outputs: { Saved: "Saved", Cancelled: "Cancelled" }, features: [i0.ɵɵInheritDefinitionFeature], decls: 88, vars: 46, consts: [["data-testid", "vs-archetype-editor", 1, "vs-arch-editor"], [1, "vs-arch-editor__body"], ["role", "alert", "data-testid", "vs-arch-editor-error", 1, "vs-arch-editor__error"], [1, "vs-arch-editor__field"], [1, "vs-arch-editor__label-row"], ["id", "vs-arch-editor-start-from-label", 1, "vs-arch-editor__label"], [1, "vs-arch-editor__hint"], ["data-testid", "vs-arch-editor-start-from", "AriaLabelledBy", "vs-arch-editor-start-from-label", "Placeholder", "Choose an archetype to copy from...", "TextField", "Label", "ValueField", "ID", 3, "ngModelChange", "Data", "ValuePrimitive", "ngModel"], [1, "vs-arch-editor__row-3"], [1, "vs-arch-editor__label"], ["type", "text", "data-testid", "vs-arch-editor-name", "placeholder", "e.g. Quarterly Member Update", 1, "vs-arch-editor__input", 3, "ngModelChange", "ngModel", "disabled"], ["id", "vs-arch-editor-category-label", 1, "vs-arch-editor__label"], ["data-testid", "vs-arch-editor-category", "AriaLabelledBy", "vs-arch-editor-category-label", "TextField", "Text", "ValueField", "Value", 3, "ngModelChange", "Data", "ValuePrimitive", "ngModel"], ["id", "vs-arch-editor-company-label", 1, "vs-arch-editor__label"], ["data-testid", "vs-arch-editor-company", "AriaLabelledBy", "vs-arch-editor-company-label", "Placeholder", "Select a company...", "TextField", "Name", "ValueField", "ID", 3, "ngModelChange", "Data", "ValuePrimitive", "ngModel"], ["data-testid", "vs-arch-editor-description", "rows", "2", "placeholder", "Describe what this archetype is for and the story arc it follows...", 1, "vs-arch-editor__textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "vs-arch-editor__length-formats"], [1, "vs-arch-editor__length-group"], ["id", "vs-arch-editor-default-dur-label", 1, "vs-arch-editor__label"], ["data-testid", "vs-arch-editor-default-readout", 1, "vs-arch-editor__time-readout"], ["data-testid", "vs-arch-editor-default-duration", "AriaLabelledBy", "vs-arch-editor-default-dur-label", 3, "ngModelChange", "Min", "Max", "Step", "Disabled", "ngModel"], ["id", "vs-arch-editor-min-dur-label", 1, "vs-arch-editor__label"], ["data-testid", "vs-arch-editor-min-readout", 1, "vs-arch-editor__time-readout"], ["data-testid", "vs-arch-editor-min-duration", "AriaLabelledBy", "vs-arch-editor-min-dur-label", 3, "ngModelChange", "Min", "Max", "Step", "Disabled", "ngModel"], ["id", "vs-arch-editor-max-dur-label", 1, "vs-arch-editor__label"], ["data-testid", "vs-arch-editor-max-readout", 1, "vs-arch-editor__time-readout"], ["data-testid", "vs-arch-editor-max-duration", "AriaLabelledBy", "vs-arch-editor-max-dur-label", 3, "ngModelChange", "Min", "Max", "Step", "Disabled", "ngModel"], ["role", "group", "aria-label", "Default video formats", 1, "vs-arch-editor__format-toggles"], ["type", "button", "mjButton", "", "Variant", "outline", "Size", "sm", 3, "Toggleable", "Selected", "disabled"], ["data-testid", "vs-arch-editor-beats-section", 1, "vs-arch-editor__beats-section"], [1, "vs-arch-editor__beats-header"], ["data-testid", "vs-arch-editor-beats-sum", 1, "vs-arch-editor__time-readout"], ["data-testid", "vs-arch-editor-beat-strip", 3, "Beats"], ["data-testid", "vs-arch-editor-beats-mismatch", 1, "vs-arch-editor__mismatch"], [1, "vs-arch-editor__beat-rows"], [1, "vs-arch-editor__beat-row"], [1, "vs-arch-editor__beats-footer"], ["type", "button", "mjButton", "", "Variant", "outline", "Size", "sm", "data-testid", "vs-arch-editor-add-beat", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-plus"], [1, "vs-arch-editor__advanced"], ["type", "button", "data-testid", "vs-arch-editor-advanced-toggle", 1, "vs-arch-editor__advanced-toggle", 3, "click"], ["aria-hidden", "true", 1, "fa-solid"], ["data-testid", "vs-arch-editor-advanced-body", 1, "vs-arch-editor__advanced-body"], [1, "vs-arch-editor__footer"], ["type", "button", "mjButton", "", "Variant", "primary", "Size", "md", "data-testid", "vs-arch-editor-save", 3, "click", "disabled"], ["type", "button", "mjButton", "", "Variant", "secondary", "Size", "md", "data-testid", "vs-arch-editor-cancel", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-exclamation"], ["type", "button", "mjButton", "", "Variant", "outline", "Size", "sm", 3, "click", "Toggleable", "Selected", "disabled"], ["Size", "sm", 3, "Format"], [1, "vs-arch-editor__mismatch-text"], ["type", "button", "mjButton", "", "Variant", "flat", "Size", "sm", "data-testid", "vs-arch-editor-fit-to-length", 3, "click", "disabled"], ["aria-hidden", "true", 1, "vs-arch-editor__beat-index"], ["type", "text", "placeholder", "Beat label", 1, "vs-arch-editor__input", "vs-arch-editor__beat-label-input", 3, "ngModelChange", "ngModel", "disabled"], ["type", "text", "placeholder", "What this beat accomplishes", 1, "vs-arch-editor__input", "vs-arch-editor__beat-purpose-input", 3, "ngModelChange", "ngModel", "disabled"], [1, "vs-arch-editor__beat-seconds-wrap"], [3, "ngModelChange", "AriaLabel", "Min", "Max", "Step", "Disabled", "ngModel"], [1, "vs-arch-editor__beat-time-readout"], [1, "vs-arch-editor__beat-actions"], ["type", "button", "mjButton", "", "Variant", "icon", "Size", "sm", 3, "click", "AriaLabel", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-up"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-down"], ["aria-hidden", "true", 1, "fa-solid", "fa-trash-can"], ["data-testid", "vs-arch-editor-guidance", "rows", "3", "placeholder", "Markdown guidance for the Director and Storyboard...", 1, "vs-arch-editor__textarea", 3, "ngModelChange", "ngModel", "disabled"], [1, "vs-arch-editor__pacing-grid"], ["id", "vs-arch-editor-pacing-avg-label", 1, "vs-arch-editor__label"], [1, "vs-arch-editor__time-readout"], ["data-testid", "vs-arch-editor-pacing-avg", "AriaLabelledBy", "vs-arch-editor-pacing-avg-label", 3, "ngModelChange", "Min", "Max", "Step", "Disabled", "ngModel"], ["type", "text", "data-testid", "vs-arch-editor-pacing-hold-rules", "placeholder", "e.g. Hold key numbers and charts for at least 3 seconds", 1, "vs-arch-editor__input", 3, "ngModelChange", "ngModel", "disabled"], [1, "vs-arch-editor__advanced-beats"], [1, "vs-arch-editor__advanced-beat-row"], [1, "vs-arch-editor__advanced-beat-name"], [1, "vs-arch-editor__advanced-beat-switch"], [3, "ngModelChange", "AriaLabel", "Disabled", "ngModel"], ["type", "text", "placeholder", "Optional beat guidance...", 1, "vs-arch-editor__input", 3, "ngModelChange", "ngModel", "disabled"]], template: function VSArchetypeEditorComponent_Template(rf, ctx) { if (rf & 1) {
909
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1);
910
+ i0.ɵɵconditionalCreate(2, VSArchetypeEditorComponent_Conditional_2_Template, 4, 1, "div", 2);
911
+ i0.ɵɵelementStart(3, "div", 3)(4, "div", 4)(5, "span", 5);
912
+ i0.ɵɵtext(6, " Start from ");
913
+ i0.ɵɵelementEnd();
914
+ i0.ɵɵelementStart(7, "span", 6);
915
+ i0.ɵɵtext(8, " Copies fields into this form without changing the original ");
916
+ i0.ɵɵelementEnd()();
917
+ i0.ɵɵelementStart(9, "mj-dropdown", 7);
918
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_Template_mj_dropdown_ngModelChange_9_listener($event) { return ctx.OnStartFromChange($event); });
919
+ i0.ɵɵelementEnd()();
920
+ i0.ɵɵelementStart(10, "div", 8)(11, "label", 3)(12, "span", 9);
921
+ i0.ɵɵtext(13, "Name");
922
+ i0.ɵɵelementEnd();
923
+ i0.ɵɵelementStart(14, "input", 10);
924
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Template_input_ngModelChange_14_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.Name, $event) || (ctx.Name = $event); return $event; });
925
+ i0.ɵɵelementEnd()();
926
+ i0.ɵɵelementStart(15, "div", 3)(16, "span", 11);
927
+ i0.ɵɵtext(17, " Category ");
928
+ i0.ɵɵelementEnd();
929
+ i0.ɵɵelementStart(18, "mj-dropdown", 12);
930
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Template_mj_dropdown_ngModelChange_18_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.Category, $event) || (ctx.Category = $event); return $event; });
931
+ i0.ɵɵelementEnd()();
932
+ i0.ɵɵelementStart(19, "div", 3)(20, "span", 13);
933
+ i0.ɵɵtext(21, " Company ");
934
+ i0.ɵɵelementEnd();
935
+ i0.ɵɵelementStart(22, "mj-dropdown", 14);
936
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Template_mj_dropdown_ngModelChange_22_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.CompanyID, $event) || (ctx.CompanyID = $event); return $event; });
937
+ i0.ɵɵelementEnd()()();
938
+ i0.ɵɵelementStart(23, "label", 3)(24, "div", 4)(25, "span", 9);
939
+ i0.ɵɵtext(26, "Description");
940
+ i0.ɵɵelementEnd();
941
+ i0.ɵɵelementStart(27, "span", 6);
942
+ i0.ɵɵtext(28, " One short paragraph \u2014 the Director reads it to choose and shape this archetype ");
943
+ i0.ɵɵelementEnd()();
944
+ i0.ɵɵelementStart(29, "textarea", 15);
945
+ i0.ɵɵtwoWayListener("ngModelChange", function VSArchetypeEditorComponent_Template_textarea_ngModelChange_29_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.Description, $event) || (ctx.Description = $event); return $event; });
946
+ i0.ɵɵelementEnd()();
947
+ i0.ɵɵelementStart(30, "div", 16)(31, "div", 17)(32, "div", 3)(33, "div", 4)(34, "span", 18);
948
+ i0.ɵɵtext(35, " Default length (s) ");
949
+ i0.ɵɵelementEnd();
950
+ i0.ɵɵelementStart(36, "span", 19);
951
+ i0.ɵɵtext(37);
952
+ i0.ɵɵelementEnd()();
953
+ i0.ɵɵelementStart(38, "mj-numeric-input", 20);
954
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_Template_mj_numeric_input_ngModelChange_38_listener($event) { return ctx.OnDefaultDurationChange($event); });
955
+ i0.ɵɵelementEnd()();
956
+ i0.ɵɵelementStart(39, "div", 3)(40, "div", 4)(41, "span", 21);
957
+ i0.ɵɵtext(42, " Shortest (s) ");
958
+ i0.ɵɵelementEnd();
959
+ i0.ɵɵelementStart(43, "span", 22);
960
+ i0.ɵɵtext(44);
961
+ i0.ɵɵelementEnd()();
962
+ i0.ɵɵelementStart(45, "mj-numeric-input", 23);
963
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_Template_mj_numeric_input_ngModelChange_45_listener($event) { return ctx.OnMinDurationChange($event); });
964
+ i0.ɵɵelementEnd()();
965
+ i0.ɵɵelementStart(46, "div", 3)(47, "div", 4)(48, "span", 24);
966
+ i0.ɵɵtext(49, " Longest (s) ");
967
+ i0.ɵɵelementEnd();
968
+ i0.ɵɵelementStart(50, "span", 25);
969
+ i0.ɵɵtext(51);
970
+ i0.ɵɵelementEnd()();
971
+ i0.ɵɵelementStart(52, "mj-numeric-input", 26);
972
+ i0.ɵɵlistener("ngModelChange", function VSArchetypeEditorComponent_Template_mj_numeric_input_ngModelChange_52_listener($event) { return ctx.OnMaxDurationChange($event); });
973
+ i0.ɵɵelementEnd()()();
974
+ i0.ɵɵelementStart(53, "div", 3)(54, "span", 9);
975
+ i0.ɵɵtext(55, "Formats");
976
+ i0.ɵɵelementEnd();
977
+ i0.ɵɵelementStart(56, "div", 27);
978
+ i0.ɵɵrepeaterCreate(57, VSArchetypeEditorComponent_For_58_Template, 2, 5, "button", 28, i0.ɵɵrepeaterTrackByIdentity);
979
+ i0.ɵɵelementEnd()()();
980
+ i0.ɵɵelementStart(59, "section", 29)(60, "div", 30)(61, "span", 9);
981
+ i0.ɵɵtext(62);
982
+ i0.ɵɵelementEnd();
983
+ i0.ɵɵelementStart(63, "span", 31);
984
+ i0.ɵɵtext(64);
985
+ i0.ɵɵelementEnd()();
986
+ i0.ɵɵelement(65, "mj-video-beat-strip", 32);
987
+ i0.ɵɵconditionalCreate(66, VSArchetypeEditorComponent_Conditional_66_Template, 6, 3, "div", 33);
988
+ i0.ɵɵelementStart(67, "div", 34);
989
+ i0.ɵɵrepeaterCreate(68, VSArchetypeEditorComponent_For_69_Template, 16, 27, "div", 35, _forTrack0);
990
+ i0.ɵɵelementEnd();
991
+ i0.ɵɵelementStart(70, "div", 36)(71, "button", 37);
992
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_Template_button_click_71_listener() { return ctx.AddBeat(); });
993
+ i0.ɵɵelement(72, "i", 38);
994
+ i0.ɵɵelementStart(73, "span");
995
+ i0.ɵɵtext(74, "Add beat");
996
+ i0.ɵɵelementEnd()()()();
997
+ i0.ɵɵelementStart(75, "section", 39)(76, "button", 40);
998
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_Template_button_click_76_listener() { return ctx.ToggleAdvanced(); });
999
+ i0.ɵɵelement(77, "i", 41);
1000
+ i0.ɵɵelementStart(78, "span");
1001
+ i0.ɵɵtext(79, "Advanced (guidance, pacing, data binding)");
1002
+ i0.ɵɵelementEnd()();
1003
+ i0.ɵɵconditionalCreate(80, VSArchetypeEditorComponent_Conditional_80_Template, 23, 10, "div", 42);
1004
+ i0.ɵɵelementEnd()();
1005
+ i0.ɵɵelementStart(81, "footer", 43)(82, "button", 44);
1006
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_Template_button_click_82_listener() { return ctx.Save(); });
1007
+ i0.ɵɵelementStart(83, "span");
1008
+ i0.ɵɵtext(84);
1009
+ i0.ɵɵelementEnd()();
1010
+ i0.ɵɵelementStart(85, "button", 45);
1011
+ i0.ɵɵlistener("click", function VSArchetypeEditorComponent_Template_button_click_85_listener() { return ctx.Cancel(); });
1012
+ i0.ɵɵelementStart(86, "span");
1013
+ i0.ɵɵtext(87, "Cancel");
1014
+ i0.ɵɵelementEnd()()()();
1015
+ } if (rf & 2) {
1016
+ i0.ɵɵadvance(2);
1017
+ i0.ɵɵconditional(ctx.SaveError ? 2 : -1);
1018
+ i0.ɵɵadvance(7);
1019
+ i0.ɵɵproperty("Data", ctx.StartFromOptions)("ValuePrimitive", true)("ngModel", ctx.SelectedSourceId);
1020
+ i0.ɵɵadvance(5);
1021
+ i0.ɵɵtwoWayProperty("ngModel", ctx.Name);
1022
+ i0.ɵɵproperty("disabled", ctx.IsSaving);
1023
+ i0.ɵɵadvance(4);
1024
+ i0.ɵɵproperty("Data", ctx.CategoryOptions)("ValuePrimitive", true);
1025
+ i0.ɵɵtwoWayProperty("ngModel", ctx.Category);
1026
+ i0.ɵɵadvance(4);
1027
+ i0.ɵɵproperty("Data", ctx.AvailableCompanies)("ValuePrimitive", true);
1028
+ i0.ɵɵtwoWayProperty("ngModel", ctx.CompanyID);
1029
+ i0.ɵɵadvance(7);
1030
+ i0.ɵɵtwoWayProperty("ngModel", ctx.Description);
1031
+ i0.ɵɵproperty("disabled", ctx.IsSaving);
1032
+ i0.ɵɵadvance(8);
1033
+ i0.ɵɵtextInterpolate1(" ", ctx.FormatTime(ctx.DefaultDurationSeconds), " ");
1034
+ i0.ɵɵadvance();
1035
+ i0.ɵɵproperty("Min", 1)("Max", 600)("Step", 1)("Disabled", ctx.IsSaving)("ngModel", ctx.DefaultDurationSeconds);
1036
+ i0.ɵɵadvance(6);
1037
+ i0.ɵɵtextInterpolate1(" ", ctx.FormatTime(ctx.MinDurationSeconds), " ");
1038
+ i0.ɵɵadvance();
1039
+ i0.ɵɵproperty("Min", 1)("Max", 600)("Step", 1)("Disabled", ctx.IsSaving)("ngModel", ctx.MinDurationSeconds);
1040
+ i0.ɵɵadvance(6);
1041
+ i0.ɵɵtextInterpolate1(" ", ctx.FormatTime(ctx.MaxDurationSeconds), " ");
1042
+ i0.ɵɵadvance();
1043
+ i0.ɵɵproperty("Min", 1)("Max", 600)("Step", 1)("Disabled", ctx.IsSaving)("ngModel", ctx.MaxDurationSeconds);
1044
+ i0.ɵɵadvance(5);
1045
+ i0.ɵɵrepeater(ctx.AvailableFormats);
1046
+ i0.ɵɵadvance(5);
1047
+ i0.ɵɵtextInterpolate1(" Beats (", ctx.Beats.length, ") ");
1048
+ i0.ɵɵadvance(2);
1049
+ i0.ɵɵtextInterpolate1(" ", ctx.FormatTime(ctx.BeatsTotalSeconds), " total ");
1050
+ i0.ɵɵadvance();
1051
+ i0.ɵɵproperty("Beats", ctx.LiveBeatStripItems);
1052
+ i0.ɵɵadvance();
1053
+ i0.ɵɵconditional(ctx.HasBeatsDurationMismatch ? 66 : -1);
1054
+ i0.ɵɵadvance(2);
1055
+ i0.ɵɵrepeater(ctx.Beats);
1056
+ i0.ɵɵadvance(3);
1057
+ i0.ɵɵproperty("disabled", ctx.IsSaving);
1058
+ i0.ɵɵadvance(5);
1059
+ i0.ɵɵattribute("aria-expanded", ctx.IsAdvancedOpen);
1060
+ i0.ɵɵadvance();
1061
+ i0.ɵɵclassProp("fa-chevron-right", !ctx.IsAdvancedOpen)("fa-chevron-down", ctx.IsAdvancedOpen);
1062
+ i0.ɵɵadvance(3);
1063
+ i0.ɵɵconditional(ctx.IsAdvancedOpen ? 80 : -1);
1064
+ i0.ɵɵadvance(2);
1065
+ i0.ɵɵproperty("disabled", ctx.IsSaving);
1066
+ i0.ɵɵadvance(2);
1067
+ i0.ɵɵtextInterpolate(ctx.IsSaving ? "Saving..." : "Save");
1068
+ i0.ɵɵadvance();
1069
+ i0.ɵɵproperty("disabled", ctx.IsSaving);
1070
+ } }, dependencies: [CommonModule,
1071
+ FormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, ArtifactsModule, i2.MJVideoFormatGlyphComponent, i2.MJVideoBeatStripComponent, MJButtonDirective,
1072
+ MJDropdownComponent,
1073
+ MJNumericInputComponent,
1074
+ MJSwitchComponent], styles: ["[_nghost-%COMP%] {\n display: block;\n width: 100%;\n}\n\n.vs-arch-editor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n}\n\n.vs-arch-editor__body[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n max-height: 70vh;\n overflow-y: auto;\n padding-right: var(--mj-space-1);\n}\n\n.vs-arch-editor__error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2-5) var(--mj-space-3);\n border-radius: var(--mj-radius-md);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n color: var(--mj-status-error-text);\n font-size: var(--mj-text-xs);\n}\n\n.vs-arch-editor__field[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n min-width: 0;\n}\n\n.vs-arch-editor__label-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--mj-space-2);\n flex-wrap: wrap;\n}\n\n.vs-arch-editor__label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.vs-arch-editor__hint[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.vs-arch-editor__time-readout[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n}\n\n.vs-arch-editor__row-3[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(180px, 1.4fr) minmax(140px, 1fr) minmax(150px, 1fr);\n gap: var(--mj-space-3);\n}\n\n.vs-arch-editor__length-formats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 1.5fr 1fr;\n gap: var(--mj-space-4);\n align-items: end;\n}\n\n.vs-arch-editor__length-group[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--mj-space-2-5);\n}\n\n.vs-arch-editor__format-toggles[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__input[_ngcontent-%COMP%], \n.vs-arch-editor__textarea[_ngcontent-%COMP%] {\n width: 100%;\n box-sizing: border-box;\n padding: var(--mj-space-2) var(--mj-space-2-5);\n border-radius: var(--mj-radius-md);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-family: inherit;\n font-size: var(--mj-text-sm);\n transition: var(--mj-transition-fast);\n}\n\n.vs-arch-editor__textarea[_ngcontent-%COMP%] {\n resize: vertical;\n line-height: var(--mj-leading-normal);\n}\n\n.vs-arch-editor__input[_ngcontent-%COMP%]:focus-visible, \n.vs-arch-editor__textarea[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: var(--mj-focus-ring);\n}\n\n.vs-arch-editor__beats-section[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2-5);\n padding: var(--mj-space-3-5);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.vs-arch-editor__beats-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__mismatch[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-3);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-radius: var(--mj-radius-md);\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n color: var(--mj-status-warning-text);\n font-size: var(--mj-text-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.vs-arch-editor__mismatch-text[_ngcontent-%COMP%] {\n font-weight: var(--mj-font-medium);\n}\n\n.vs-arch-editor__beat-rows[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__beat-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: auto minmax(148px, 1.25fr) minmax(160px, 1.75fr) auto auto;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n}\n\n.vs-arch-editor__beat-index[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--mj-space-5);\n height: var(--mj-space-5);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n font-variant-numeric: tabular-nums;\n}\n\n.vs-arch-editor__beat-seconds-wrap[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n width: 6.5rem;\n}\n\n.vs-arch-editor__beat-time-readout[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.vs-arch-editor__beat-actions[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1);\n}\n\n.vs-arch-editor__beats-footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n}\n\n.vs-arch-editor__advanced[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3);\n border-top: 1px solid var(--mj-border-subtle);\n padding-top: var(--mj-space-3);\n}\n\n.vs-arch-editor__advanced-toggle[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-1-5);\n border: none;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n align-self: flex-start;\n transition: var(--mj-transition-fast);\n}\n\n.vs-arch-editor__advanced-toggle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.vs-arch-editor__advanced-toggle[_ngcontent-%COMP%]:focus-visible {\n outline: none;\n box-shadow: var(--mj-focus-ring);\n}\n\n.vs-arch-editor__advanced-body[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3);\n padding: var(--mj-space-3);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.vs-arch-editor__pacing-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(140px, 0.7fr) 1.3fr;\n gap: var(--mj-space-3);\n}\n\n.vs-arch-editor__advanced-beats[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__advanced-beat-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: minmax(120px, 0.8fr) auto 1.2fr;\n align-items: center;\n gap: var(--mj-space-2-5);\n}\n\n.vs-arch-editor__advanced-beat-name[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vs-arch-editor__advanced-beat-switch[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n}\n\n.vs-arch-editor__footer[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-3);\n padding-top: var(--mj-space-3);\n border-top: 1px solid var(--mj-border-default);\n}\n\n@media (max-width: 768px) {\n .vs-arch-editor__row-3[_ngcontent-%COMP%], \n .vs-arch-editor__length-formats[_ngcontent-%COMP%], \n .vs-arch-editor__pacing-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n\n .vs-arch-editor__beat-row[_ngcontent-%COMP%] {\n grid-template-columns: auto 1fr;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .vs-arch-editor__input[_ngcontent-%COMP%], \n .vs-arch-editor__textarea[_ngcontent-%COMP%], \n .vs-arch-editor__advanced-toggle[_ngcontent-%COMP%] {\n transition: none;\n }\n}"], changeDetection: 0 });
1075
+ }
1076
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(VSArchetypeEditorComponent, [{
1077
+ type: Component,
1078
+ args: [{ standalone: true, selector: 'vs-archetype-editor', imports: [
1079
+ CommonModule,
1080
+ FormsModule,
1081
+ ArtifactsModule,
1082
+ MJButtonDirective,
1083
+ MJDropdownComponent,
1084
+ MJNumericInputComponent,
1085
+ MJSwitchComponent,
1086
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"vs-arch-editor\" data-testid=\"vs-archetype-editor\">\n <div class=\"vs-arch-editor__body\">\n @if (SaveError) {\n <div\n class=\"vs-arch-editor__error\"\n role=\"alert\"\n data-testid=\"vs-arch-editor-error\"\n >\n <i class=\"fa-solid fa-circle-exclamation\" aria-hidden=\"true\"></i>\n <span>{{ SaveError }}</span>\n </div>\n }\n\n <!-- Start from -->\n <div class=\"vs-arch-editor__field\">\n <div class=\"vs-arch-editor__label-row\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-start-from-label\">\n Start from\n </span>\n <span class=\"vs-arch-editor__hint\">\n Copies fields into this form without changing the original\n </span>\n </div>\n <mj-dropdown\n data-testid=\"vs-arch-editor-start-from\"\n AriaLabelledBy=\"vs-arch-editor-start-from-label\"\n Placeholder=\"Choose an archetype to copy from...\"\n [Data]=\"StartFromOptions\"\n TextField=\"Label\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [ngModel]=\"SelectedSourceId\"\n (ngModelChange)=\"OnStartFromChange($event)\"\n ></mj-dropdown>\n </div>\n\n <!-- Name, Category, Company -->\n <div class=\"vs-arch-editor__row-3\">\n <label class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\">Name</span>\n <input\n type=\"text\"\n class=\"vs-arch-editor__input\"\n data-testid=\"vs-arch-editor-name\"\n placeholder=\"e.g. Quarterly Member Update\"\n [(ngModel)]=\"Name\"\n [disabled]=\"IsSaving\"\n />\n </label>\n\n <div class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-category-label\">\n Category\n </span>\n <mj-dropdown\n data-testid=\"vs-arch-editor-category\"\n AriaLabelledBy=\"vs-arch-editor-category-label\"\n [Data]=\"CategoryOptions\"\n TextField=\"Text\"\n ValueField=\"Value\"\n [ValuePrimitive]=\"true\"\n [(ngModel)]=\"Category\"\n ></mj-dropdown>\n </div>\n\n <div class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-company-label\">\n Company\n </span>\n <mj-dropdown\n data-testid=\"vs-arch-editor-company\"\n AriaLabelledBy=\"vs-arch-editor-company-label\"\n Placeholder=\"Select a company...\"\n [Data]=\"AvailableCompanies\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [(ngModel)]=\"CompanyID\"\n ></mj-dropdown>\n </div>\n </div>\n\n <!-- Description -->\n <label class=\"vs-arch-editor__field\">\n <div class=\"vs-arch-editor__label-row\">\n <span class=\"vs-arch-editor__label\">Description</span>\n <span class=\"vs-arch-editor__hint\">\n One short paragraph \u2014 the Director reads it to choose and shape this archetype\n </span>\n </div>\n <textarea\n class=\"vs-arch-editor__textarea\"\n data-testid=\"vs-arch-editor-description\"\n rows=\"2\"\n placeholder=\"Describe what this archetype is for and the story arc it follows...\"\n [(ngModel)]=\"Description\"\n [disabled]=\"IsSaving\"\n ></textarea>\n </label>\n\n <!-- Length & Formats -->\n <div class=\"vs-arch-editor__length-formats\">\n <div class=\"vs-arch-editor__length-group\">\n <div class=\"vs-arch-editor__field\">\n <div class=\"vs-arch-editor__label-row\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-default-dur-label\">\n Default length (s)\n </span>\n <span\n class=\"vs-arch-editor__time-readout\"\n data-testid=\"vs-arch-editor-default-readout\"\n >\n {{ FormatTime(DefaultDurationSeconds) }}\n </span>\n </div>\n <mj-numeric-input\n data-testid=\"vs-arch-editor-default-duration\"\n AriaLabelledBy=\"vs-arch-editor-default-dur-label\"\n [Min]=\"1\"\n [Max]=\"600\"\n [Step]=\"1\"\n [Disabled]=\"IsSaving\"\n [ngModel]=\"DefaultDurationSeconds\"\n (ngModelChange)=\"OnDefaultDurationChange($event)\"\n ></mj-numeric-input>\n </div>\n\n <div class=\"vs-arch-editor__field\">\n <div class=\"vs-arch-editor__label-row\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-min-dur-label\">\n Shortest (s)\n </span>\n <span\n class=\"vs-arch-editor__time-readout\"\n data-testid=\"vs-arch-editor-min-readout\"\n >\n {{ FormatTime(MinDurationSeconds) }}\n </span>\n </div>\n <mj-numeric-input\n data-testid=\"vs-arch-editor-min-duration\"\n AriaLabelledBy=\"vs-arch-editor-min-dur-label\"\n [Min]=\"1\"\n [Max]=\"600\"\n [Step]=\"1\"\n [Disabled]=\"IsSaving\"\n [ngModel]=\"MinDurationSeconds\"\n (ngModelChange)=\"OnMinDurationChange($event)\"\n ></mj-numeric-input>\n </div>\n\n <div class=\"vs-arch-editor__field\">\n <div class=\"vs-arch-editor__label-row\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-max-dur-label\">\n Longest (s)\n </span>\n <span\n class=\"vs-arch-editor__time-readout\"\n data-testid=\"vs-arch-editor-max-readout\"\n >\n {{ FormatTime(MaxDurationSeconds) }}\n </span>\n </div>\n <mj-numeric-input\n data-testid=\"vs-arch-editor-max-duration\"\n AriaLabelledBy=\"vs-arch-editor-max-dur-label\"\n [Min]=\"1\"\n [Max]=\"600\"\n [Step]=\"1\"\n [Disabled]=\"IsSaving\"\n [ngModel]=\"MaxDurationSeconds\"\n (ngModelChange)=\"OnMaxDurationChange($event)\"\n ></mj-numeric-input>\n </div>\n </div>\n\n <div class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\">Formats</span>\n <div\n class=\"vs-arch-editor__format-toggles\"\n role=\"group\"\n aria-label=\"Default video formats\"\n >\n @for (format of AvailableFormats; track format) {\n <button\n type=\"button\"\n mjButton\n Variant=\"outline\"\n Size=\"sm\"\n [Toggleable]=\"true\"\n [Selected]=\"IsFormatSelected(format)\"\n [attr.data-testid]=\"'vs-arch-editor-format-' + format\"\n [disabled]=\"IsSaving\"\n (click)=\"ToggleFormat(format)\"\n >\n <mj-video-format-glyph [Format]=\"format\" Size=\"sm\"></mj-video-format-glyph>\n </button>\n }\n </div>\n </div>\n </div>\n\n <!-- Beats -->\n <section class=\"vs-arch-editor__beats-section\" data-testid=\"vs-arch-editor-beats-section\">\n <div class=\"vs-arch-editor__beats-header\">\n <span class=\"vs-arch-editor__label\">\n Beats ({{ Beats.length }})\n </span>\n <span class=\"vs-arch-editor__time-readout\" data-testid=\"vs-arch-editor-beats-sum\">\n {{ FormatTime(BeatsTotalSeconds) }} total\n </span>\n </div>\n\n <mj-video-beat-strip\n data-testid=\"vs-arch-editor-beat-strip\"\n [Beats]=\"LiveBeatStripItems\"\n ></mj-video-beat-strip>\n\n @if (HasBeatsDurationMismatch) {\n <div\n class=\"vs-arch-editor__mismatch\"\n data-testid=\"vs-arch-editor-beats-mismatch\"\n >\n <span class=\"vs-arch-editor__mismatch-text\">\n Beats add up to {{ FormatTime(BeatsTotalSeconds) }} of {{ FormatTime(DefaultDurationSeconds) }}\n </span>\n <button\n type=\"button\"\n mjButton\n Variant=\"flat\"\n Size=\"sm\"\n data-testid=\"vs-arch-editor-fit-to-length\"\n [disabled]=\"IsSaving\"\n (click)=\"FitBeatsToLength()\"\n >\n <span>Fit to length</span>\n </button>\n </div>\n }\n\n <div class=\"vs-arch-editor__beat-rows\">\n @for (beat of Beats; track beat.TrackId; let idx = $index) {\n <div\n class=\"vs-arch-editor__beat-row\"\n [attr.data-testid]=\"'vs-arch-editor-beat-row-' + idx\"\n >\n <span class=\"vs-arch-editor__beat-index\" aria-hidden=\"true\">\n {{ idx + 1 }}\n </span>\n\n <input\n type=\"text\"\n class=\"vs-arch-editor__input vs-arch-editor__beat-label-input\"\n [attr.data-testid]=\"'vs-arch-editor-beat-label-' + idx\"\n [attr.aria-label]=\"'Beat ' + (idx + 1) + ' label'\"\n placeholder=\"Beat label\"\n [ngModel]=\"beat.Label\"\n (ngModelChange)=\"OnBeatLabelChange(idx, $event)\"\n [disabled]=\"IsSaving\"\n />\n\n <input\n type=\"text\"\n class=\"vs-arch-editor__input vs-arch-editor__beat-purpose-input\"\n [attr.data-testid]=\"'vs-arch-editor-beat-purpose-' + idx\"\n [attr.aria-label]=\"'Beat ' + (idx + 1) + ' purpose'\"\n placeholder=\"What this beat accomplishes\"\n [ngModel]=\"beat.Purpose\"\n (ngModelChange)=\"OnBeatPurposeChange(idx, $event)\"\n [disabled]=\"IsSaving\"\n />\n\n <div class=\"vs-arch-editor__beat-seconds-wrap\">\n <mj-numeric-input\n [attr.data-testid]=\"'vs-arch-editor-beat-seconds-' + idx\"\n [AriaLabel]=\"'Beat ' + (idx + 1) + ' seconds'\"\n [Min]=\"1\"\n [Max]=\"600\"\n [Step]=\"1\"\n [Disabled]=\"IsSaving\"\n [ngModel]=\"beat.Seconds\"\n (ngModelChange)=\"OnBeatSecondsChange(idx, $event)\"\n ></mj-numeric-input>\n <span class=\"vs-arch-editor__beat-time-readout\">\n {{ FormatTime(beat.Seconds) }}\n </span>\n </div>\n\n <div class=\"vs-arch-editor__beat-actions\">\n <button\n type=\"button\"\n mjButton\n Variant=\"icon\"\n Size=\"sm\"\n [AriaLabel]=\"'Move beat ' + (idx + 1) + ' up'\"\n [attr.data-testid]=\"'vs-arch-editor-beat-up-' + idx\"\n [disabled]=\"IsSaving || idx === 0\"\n (click)=\"MoveBeatUp(idx)\"\n >\n <i class=\"fa-solid fa-arrow-up\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n mjButton\n Variant=\"icon\"\n Size=\"sm\"\n [AriaLabel]=\"'Move beat ' + (idx + 1) + ' down'\"\n [attr.data-testid]=\"'vs-arch-editor-beat-down-' + idx\"\n [disabled]=\"IsSaving || idx === Beats.length - 1\"\n (click)=\"MoveBeatDown(idx)\"\n >\n <i class=\"fa-solid fa-arrow-down\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n mjButton\n Variant=\"icon\"\n Size=\"sm\"\n [AriaLabel]=\"'Remove beat ' + (idx + 1)\"\n [attr.data-testid]=\"'vs-arch-editor-beat-remove-' + idx\"\n [disabled]=\"IsSaving || Beats.length <= 1\"\n (click)=\"RemoveBeat(idx)\"\n >\n <i class=\"fa-solid fa-trash-can\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n }\n </div>\n\n <div class=\"vs-arch-editor__beats-footer\">\n <button\n type=\"button\"\n mjButton\n Variant=\"outline\"\n Size=\"sm\"\n data-testid=\"vs-arch-editor-add-beat\"\n [disabled]=\"IsSaving\"\n (click)=\"AddBeat()\"\n >\n <i class=\"fa-solid fa-plus\" aria-hidden=\"true\"></i>\n <span>Add beat</span>\n </button>\n </div>\n </section>\n\n <!-- Advanced (collapsed) -->\n <section class=\"vs-arch-editor__advanced\">\n <button\n type=\"button\"\n class=\"vs-arch-editor__advanced-toggle\"\n data-testid=\"vs-arch-editor-advanced-toggle\"\n [attr.aria-expanded]=\"IsAdvancedOpen\"\n (click)=\"ToggleAdvanced()\"\n >\n <i\n class=\"fa-solid\"\n [class.fa-chevron-right]=\"!IsAdvancedOpen\"\n [class.fa-chevron-down]=\"IsAdvancedOpen\"\n aria-hidden=\"true\"\n ></i>\n <span>Advanced (guidance, pacing, data binding)</span>\n </button>\n\n @if (IsAdvancedOpen) {\n <div\n class=\"vs-arch-editor__advanced-body\"\n data-testid=\"vs-arch-editor-advanced-body\"\n >\n <label class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\">Guidance (markdown)</span>\n <textarea\n class=\"vs-arch-editor__textarea\"\n data-testid=\"vs-arch-editor-guidance\"\n rows=\"3\"\n placeholder=\"Markdown guidance for the Director and Storyboard...\"\n [(ngModel)]=\"Guidance\"\n [disabled]=\"IsSaving\"\n ></textarea>\n </label>\n\n <div class=\"vs-arch-editor__pacing-grid\">\n <div class=\"vs-arch-editor__field\">\n <div class=\"vs-arch-editor__label-row\">\n <span class=\"vs-arch-editor__label\" id=\"vs-arch-editor-pacing-avg-label\">\n Average cut cadence (s)\n </span>\n <span class=\"vs-arch-editor__time-readout\">\n {{ FormatTime(PacingAvgSeconds) }}\n </span>\n </div>\n <mj-numeric-input\n data-testid=\"vs-arch-editor-pacing-avg\"\n AriaLabelledBy=\"vs-arch-editor-pacing-avg-label\"\n [Min]=\"0.5\"\n [Max]=\"60\"\n [Step]=\"0.5\"\n [Disabled]=\"IsSaving\"\n [(ngModel)]=\"PacingAvgSeconds\"\n ></mj-numeric-input>\n </div>\n\n <label class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\">Hold rules</span>\n <input\n type=\"text\"\n class=\"vs-arch-editor__input\"\n data-testid=\"vs-arch-editor-pacing-hold-rules\"\n placeholder=\"e.g. Hold key numbers and charts for at least 3 seconds\"\n [(ngModel)]=\"PacingHoldRules\"\n [disabled]=\"IsSaving\"\n />\n </label>\n </div>\n\n <div class=\"vs-arch-editor__field\">\n <span class=\"vs-arch-editor__label\">Beat data binding &amp; guidance</span>\n <div class=\"vs-arch-editor__advanced-beats\">\n @for (beat of Beats; track beat.TrackId; let idx = $index) {\n <div class=\"vs-arch-editor__advanced-beat-row\">\n <span class=\"vs-arch-editor__advanced-beat-name\">\n {{ idx + 1 }}. {{ beat.Label || 'Beat ' + (idx + 1) }}\n </span>\n <div class=\"vs-arch-editor__advanced-beat-switch\">\n <mj-switch\n [attr.data-testid]=\"'vs-arch-editor-beat-databinding-' + idx\"\n [AriaLabel]=\"'Requires data binding for ' + (beat.Label || 'Beat ' + (idx + 1))\"\n [Disabled]=\"IsSaving\"\n [(ngModel)]=\"beat.RequiresDataBinding\"\n ></mj-switch>\n <span class=\"vs-arch-editor__hint\">Data bound</span>\n </div>\n <input\n type=\"text\"\n class=\"vs-arch-editor__input\"\n [attr.data-testid]=\"'vs-arch-editor-beat-guidance-' + idx\"\n [attr.aria-label]=\"'Guidance for ' + (beat.Label || 'Beat ' + (idx + 1))\"\n placeholder=\"Optional beat guidance...\"\n [(ngModel)]=\"beat.Guidance\"\n [disabled]=\"IsSaving\"\n />\n </div>\n }\n </div>\n </div>\n </div>\n }\n </section>\n </div>\n\n <footer class=\"vs-arch-editor__footer\">\n <button\n type=\"button\"\n mjButton\n Variant=\"primary\"\n Size=\"md\"\n data-testid=\"vs-arch-editor-save\"\n [disabled]=\"IsSaving\"\n (click)=\"Save()\"\n >\n <span>{{ IsSaving ? 'Saving...' : 'Save' }}</span>\n </button>\n <button\n type=\"button\"\n mjButton\n Variant=\"secondary\"\n Size=\"md\"\n data-testid=\"vs-arch-editor-cancel\"\n [disabled]=\"IsSaving\"\n (click)=\"Cancel()\"\n >\n <span>Cancel</span>\n </button>\n </footer>\n</div>\n", styles: [":host {\n display: block;\n width: 100%;\n}\n\n.vs-arch-editor {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n}\n\n.vs-arch-editor__body {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-4);\n max-height: 70vh;\n overflow-y: auto;\n padding-right: var(--mj-space-1);\n}\n\n.vs-arch-editor__error {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2-5) var(--mj-space-3);\n border-radius: var(--mj-radius-md);\n background: var(--mj-status-error-bg);\n border: 1px solid var(--mj-status-error-border);\n color: var(--mj-status-error-text);\n font-size: var(--mj-text-xs);\n}\n\n.vs-arch-editor__field {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-1-5);\n min-width: 0;\n}\n\n.vs-arch-editor__label-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--mj-space-2);\n flex-wrap: wrap;\n}\n\n.vs-arch-editor__label {\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n color: var(--mj-text-primary);\n}\n\n.vs-arch-editor__hint {\n font-size: var(--mj-text-xs);\n color: var(--mj-text-muted);\n}\n\n.vs-arch-editor__time-readout {\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n}\n\n.vs-arch-editor__row-3 {\n display: grid;\n grid-template-columns: minmax(180px, 1.4fr) minmax(140px, 1fr) minmax(150px, 1fr);\n gap: var(--mj-space-3);\n}\n\n.vs-arch-editor__length-formats {\n display: grid;\n grid-template-columns: 1.5fr 1fr;\n gap: var(--mj-space-4);\n align-items: end;\n}\n\n.vs-arch-editor__length-group {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--mj-space-2-5);\n}\n\n.vs-arch-editor__format-toggles {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__input,\n.vs-arch-editor__textarea {\n width: 100%;\n box-sizing: border-box;\n padding: var(--mj-space-2) var(--mj-space-2-5);\n border-radius: var(--mj-radius-md);\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n font-family: inherit;\n font-size: var(--mj-text-sm);\n transition: var(--mj-transition-fast);\n}\n\n.vs-arch-editor__textarea {\n resize: vertical;\n line-height: var(--mj-leading-normal);\n}\n\n.vs-arch-editor__input:focus-visible,\n.vs-arch-editor__textarea:focus-visible {\n outline: none;\n border-color: var(--mj-border-focus);\n box-shadow: var(--mj-focus-ring);\n}\n\n.vs-arch-editor__beats-section {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2-5);\n padding: var(--mj-space-3-5);\n border-radius: var(--mj-radius-lg);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.vs-arch-editor__beats-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__mismatch {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-3);\n padding: var(--mj-space-2) var(--mj-space-3);\n border-radius: var(--mj-radius-md);\n background: var(--mj-status-warning-bg);\n border: 1px solid var(--mj-status-warning-border);\n color: var(--mj-status-warning-text);\n font-size: var(--mj-text-xs);\n font-variant-numeric: tabular-nums;\n}\n\n.vs-arch-editor__mismatch-text {\n font-weight: var(--mj-font-medium);\n}\n\n.vs-arch-editor__beat-rows {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__beat-row {\n display: grid;\n grid-template-columns: auto minmax(148px, 1.25fr) minmax(160px, 1.75fr) auto auto;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-2);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n}\n\n.vs-arch-editor__beat-index {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--mj-space-5);\n height: var(--mj-space-5);\n border-radius: var(--mj-radius-full);\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n font-variant-numeric: tabular-nums;\n}\n\n.vs-arch-editor__beat-seconds-wrap {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n width: 6.5rem;\n}\n\n.vs-arch-editor__beat-time-readout {\n font-size: var(--mj-text-xs);\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-muted);\n white-space: nowrap;\n}\n\n.vs-arch-editor__beat-actions {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1);\n}\n\n.vs-arch-editor__beats-footer {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n}\n\n.vs-arch-editor__advanced {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3);\n border-top: 1px solid var(--mj-border-subtle);\n padding-top: var(--mj-space-3);\n}\n\n.vs-arch-editor__advanced-toggle {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-1) var(--mj-space-1-5);\n border: none;\n border-radius: var(--mj-radius-sm);\n background: transparent;\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-semibold);\n cursor: pointer;\n align-self: flex-start;\n transition: var(--mj-transition-fast);\n}\n\n.vs-arch-editor__advanced-toggle:hover {\n color: var(--mj-text-primary);\n}\n\n.vs-arch-editor__advanced-toggle:focus-visible {\n outline: none;\n box-shadow: var(--mj-focus-ring);\n}\n\n.vs-arch-editor__advanced-body {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-3);\n padding: var(--mj-space-3);\n border-radius: var(--mj-radius-md);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-subtle);\n}\n\n.vs-arch-editor__pacing-grid {\n display: grid;\n grid-template-columns: minmax(140px, 0.7fr) 1.3fr;\n gap: var(--mj-space-3);\n}\n\n.vs-arch-editor__advanced-beats {\n display: flex;\n flex-direction: column;\n gap: var(--mj-space-2);\n}\n\n.vs-arch-editor__advanced-beat-row {\n display: grid;\n grid-template-columns: minmax(120px, 0.8fr) auto 1.2fr;\n align-items: center;\n gap: var(--mj-space-2-5);\n}\n\n.vs-arch-editor__advanced-beat-name {\n font-size: var(--mj-text-xs);\n font-weight: var(--mj-font-medium);\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.vs-arch-editor__advanced-beat-switch {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n}\n\n.vs-arch-editor__footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--mj-space-3);\n padding-top: var(--mj-space-3);\n border-top: 1px solid var(--mj-border-default);\n}\n\n@media (max-width: 768px) {\n .vs-arch-editor__row-3,\n .vs-arch-editor__length-formats,\n .vs-arch-editor__pacing-grid {\n grid-template-columns: 1fr;\n }\n\n .vs-arch-editor__beat-row {\n grid-template-columns: auto 1fr;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .vs-arch-editor__input,\n .vs-arch-editor__textarea,\n .vs-arch-editor__advanced-toggle {\n transition: none;\n }\n}\n"] }]
1087
+ }], null, { Mode: [{
1088
+ type: Input
1089
+ }], SourceArchetypeId: [{
1090
+ type: Input
1091
+ }], EditingArchetypeId: [{
1092
+ type: Input
1093
+ }], Archetypes: [{
1094
+ type: Input
1095
+ }], Companies: [{
1096
+ type: Input
1097
+ }], InitialCompanyId: [{
1098
+ type: Input
1099
+ }], Saved: [{
1100
+ type: Output
1101
+ }], Cancelled: [{
1102
+ type: Output
1103
+ }] }); })();
1104
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(VSArchetypeEditorComponent, { className: "VSArchetypeEditorComponent", filePath: "src/VideoStudio/components/vs-archetype-editor.component.ts", lineNumber: 144 }); })();
1105
+ //# sourceMappingURL=vs-archetype-editor.component.js.map