@agent-native/creative-context 0.0.0-beta-20260820202238

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 (695) hide show
  1. package/README.md +154 -0
  2. package/agent-native.eject.json +41 -0
  3. package/agent-native.package.json +119 -0
  4. package/dist/actions/confirm-canonical-logo.d.ts +6 -0
  5. package/dist/actions/confirm-canonical-logo.d.ts.map +1 -0
  6. package/dist/actions/confirm-canonical-logo.js +19 -0
  7. package/dist/actions/confirm-canonical-logo.js.map +1 -0
  8. package/dist/actions/continue-context-import.d.ts +22 -0
  9. package/dist/actions/continue-context-import.d.ts.map +1 -0
  10. package/dist/actions/continue-context-import.js +13 -0
  11. package/dist/actions/continue-context-import.js.map +1 -0
  12. package/dist/actions/creative-context-a2a.d.ts +10 -0
  13. package/dist/actions/creative-context-a2a.d.ts.map +1 -0
  14. package/dist/actions/creative-context-a2a.js +66 -0
  15. package/dist/actions/creative-context-a2a.js.map +1 -0
  16. package/dist/actions/get-brand-profile.d.ts +33 -0
  17. package/dist/actions/get-brand-profile.d.ts.map +1 -0
  18. package/dist/actions/get-brand-profile.js +13 -0
  19. package/dist/actions/get-brand-profile.js.map +1 -0
  20. package/dist/actions/get-context-import-status.d.ts +22 -0
  21. package/dist/actions/get-context-import-status.d.ts.map +1 -0
  22. package/dist/actions/get-context-import-status.js +12 -0
  23. package/dist/actions/get-context-import-status.js.map +1 -0
  24. package/dist/actions/get-context-item.d.ts +2 -0
  25. package/dist/actions/get-context-item.d.ts.map +1 -0
  26. package/dist/actions/get-context-item.js +2 -0
  27. package/dist/actions/get-context-item.js.map +1 -0
  28. package/dist/actions/get-context-pack.d.ts +7 -0
  29. package/dist/actions/get-context-pack.d.ts.map +1 -0
  30. package/dist/actions/get-context-pack.js +12 -0
  31. package/dist/actions/get-context-pack.js.map +1 -0
  32. package/dist/actions/get-creative-context.d.ts +157 -0
  33. package/dist/actions/get-creative-context.d.ts.map +1 -0
  34. package/dist/actions/get-creative-context.js +148 -0
  35. package/dist/actions/get-creative-context.js.map +1 -0
  36. package/dist/actions/get-google-picker-session.d.ts +10 -0
  37. package/dist/actions/get-google-picker-session.d.ts.map +1 -0
  38. package/dist/actions/get-google-picker-session.js +38 -0
  39. package/dist/actions/get-google-picker-session.js.map +1 -0
  40. package/dist/actions/index.d.ts +3 -0
  41. package/dist/actions/index.d.ts.map +1 -0
  42. package/dist/actions/index.js +73 -0
  43. package/dist/actions/index.js.map +1 -0
  44. package/dist/actions/infer-brand-dna.d.ts +52 -0
  45. package/dist/actions/infer-brand-dna.d.ts.map +1 -0
  46. package/dist/actions/infer-brand-dna.js +13 -0
  47. package/dist/actions/infer-brand-dna.js.map +1 -0
  48. package/dist/actions/list-canonical-logo-candidates.d.ts +9 -0
  49. package/dist/actions/list-canonical-logo-candidates.d.ts.map +1 -0
  50. package/dist/actions/list-canonical-logo-candidates.js +82 -0
  51. package/dist/actions/list-canonical-logo-candidates.js.map +1 -0
  52. package/dist/actions/list-context-connections.d.ts +22 -0
  53. package/dist/actions/list-context-connections.d.ts.map +1 -0
  54. package/dist/actions/list-context-connections.js +43 -0
  55. package/dist/actions/list-context-connections.js.map +1 -0
  56. package/dist/actions/list-context-memberships.d.ts +11 -0
  57. package/dist/actions/list-context-memberships.d.ts.map +1 -0
  58. package/dist/actions/list-context-memberships.js +47 -0
  59. package/dist/actions/list-context-memberships.js.map +1 -0
  60. package/dist/actions/list-context-packs.d.ts +10 -0
  61. package/dist/actions/list-context-packs.d.ts.map +1 -0
  62. package/dist/actions/list-context-packs.js +16 -0
  63. package/dist/actions/list-context-packs.js.map +1 -0
  64. package/dist/actions/list-context-sources.d.ts +12 -0
  65. package/dist/actions/list-context-sources.d.ts.map +1 -0
  66. package/dist/actions/list-context-sources.js +20 -0
  67. package/dist/actions/list-context-sources.js.map +1 -0
  68. package/dist/actions/list-context-suggestions.d.ts +13 -0
  69. package/dist/actions/list-context-suggestions.d.ts.map +1 -0
  70. package/dist/actions/list-context-suggestions.js +28 -0
  71. package/dist/actions/list-context-suggestions.js.map +1 -0
  72. package/dist/actions/list-creative-contexts.d.ts +12 -0
  73. package/dist/actions/list-creative-contexts.d.ts.map +1 -0
  74. package/dist/actions/list-creative-contexts.js +28 -0
  75. package/dist/actions/list-creative-contexts.js.map +1 -0
  76. package/dist/actions/manage-brand-profile.d.ts +28 -0
  77. package/dist/actions/manage-brand-profile.d.ts.map +1 -0
  78. package/dist/actions/manage-brand-profile.js +47 -0
  79. package/dist/actions/manage-brand-profile.js.map +1 -0
  80. package/dist/actions/manage-context-membership.d.ts +64 -0
  81. package/dist/actions/manage-context-membership.d.ts.map +1 -0
  82. package/dist/actions/manage-context-membership.js +70 -0
  83. package/dist/actions/manage-context-membership.js.map +1 -0
  84. package/dist/actions/manage-context-pack.d.ts +36 -0
  85. package/dist/actions/manage-context-pack.d.ts.map +1 -0
  86. package/dist/actions/manage-context-pack.js +71 -0
  87. package/dist/actions/manage-context-pack.js.map +1 -0
  88. package/dist/actions/manage-context-source.d.ts +51 -0
  89. package/dist/actions/manage-context-source.d.ts.map +1 -0
  90. package/dist/actions/manage-context-source.js +130 -0
  91. package/dist/actions/manage-context-source.js.map +1 -0
  92. package/dist/actions/manage-creative-context.d.ts +28 -0
  93. package/dist/actions/manage-creative-context.d.ts.map +1 -0
  94. package/dist/actions/manage-creative-context.js +65 -0
  95. package/dist/actions/manage-creative-context.js.map +1 -0
  96. package/dist/actions/manage-layout-template.d.ts +13 -0
  97. package/dist/actions/manage-layout-template.d.ts.map +1 -0
  98. package/dist/actions/manage-layout-template.js +43 -0
  99. package/dist/actions/manage-layout-template.js.map +1 -0
  100. package/dist/actions/preview-context-import.d.ts +23 -0
  101. package/dist/actions/preview-context-import.d.ts.map +1 -0
  102. package/dist/actions/preview-context-import.js +57 -0
  103. package/dist/actions/preview-context-import.js.map +1 -0
  104. package/dist/actions/process-context-purge.d.ts +37 -0
  105. package/dist/actions/process-context-purge.d.ts.map +1 -0
  106. package/dist/actions/process-context-purge.js +20 -0
  107. package/dist/actions/process-context-purge.js.map +1 -0
  108. package/dist/actions/propose-brand-dna.d.ts +15 -0
  109. package/dist/actions/propose-brand-dna.d.ts.map +1 -0
  110. package/dist/actions/propose-brand-dna.js +19 -0
  111. package/dist/actions/propose-brand-dna.js.map +1 -0
  112. package/dist/actions/propose-canonical-logo.d.ts +9 -0
  113. package/dist/actions/propose-canonical-logo.d.ts.map +1 -0
  114. package/dist/actions/propose-canonical-logo.js +16 -0
  115. package/dist/actions/propose-canonical-logo.js.map +1 -0
  116. package/dist/actions/publish-brand-dna.d.ts +13 -0
  117. package/dist/actions/publish-brand-dna.d.ts.map +1 -0
  118. package/dist/actions/publish-brand-dna.js +23 -0
  119. package/dist/actions/publish-brand-dna.js.map +1 -0
  120. package/dist/actions/recommend-context-roots.d.ts +14 -0
  121. package/dist/actions/recommend-context-roots.d.ts.map +1 -0
  122. package/dist/actions/recommend-context-roots.js +22 -0
  123. package/dist/actions/recommend-context-roots.js.map +1 -0
  124. package/dist/actions/record-context-feedback.d.ts +10 -0
  125. package/dist/actions/record-context-feedback.d.ts.map +1 -0
  126. package/dist/actions/record-context-feedback.js +14 -0
  127. package/dist/actions/record-context-feedback.js.map +1 -0
  128. package/dist/actions/review-context-items.d.ts +35 -0
  129. package/dist/actions/review-context-items.d.ts.map +1 -0
  130. package/dist/actions/review-context-items.js +65 -0
  131. package/dist/actions/review-context-items.js.map +1 -0
  132. package/dist/actions/run-embedding-bakeoff.d.ts +15 -0
  133. package/dist/actions/run-embedding-bakeoff.d.ts.map +1 -0
  134. package/dist/actions/run-embedding-bakeoff.js +72 -0
  135. package/dist/actions/run-embedding-bakeoff.js.map +1 -0
  136. package/dist/actions/search-creative-context.d.ts +80 -0
  137. package/dist/actions/search-creative-context.d.ts.map +1 -0
  138. package/dist/actions/search-creative-context.js +42 -0
  139. package/dist/actions/search-creative-context.js.map +1 -0
  140. package/dist/actions/set-brand-dna.d.ts +15 -0
  141. package/dist/actions/set-brand-dna.d.ts.map +1 -0
  142. package/dist/actions/set-brand-dna.js +19 -0
  143. package/dist/actions/set-brand-dna.js.map +1 -0
  144. package/dist/actions/start-context-enrichment.d.ts +25 -0
  145. package/dist/actions/start-context-enrichment.d.ts.map +1 -0
  146. package/dist/actions/start-context-enrichment.js +48 -0
  147. package/dist/actions/start-context-enrichment.js.map +1 -0
  148. package/dist/actions/start-context-import.d.ts +24 -0
  149. package/dist/actions/start-context-import.d.ts.map +1 -0
  150. package/dist/actions/start-context-import.js +37 -0
  151. package/dist/actions/start-context-import.js.map +1 -0
  152. package/dist/client/CreativeContextChip.d.ts +18 -0
  153. package/dist/client/CreativeContextChip.d.ts.map +1 -0
  154. package/dist/client/CreativeContextChip.js +80 -0
  155. package/dist/client/CreativeContextChip.js.map +1 -0
  156. package/dist/client/CreativeContextPanel.d.ts +73 -0
  157. package/dist/client/CreativeContextPanel.d.ts.map +1 -0
  158. package/dist/client/CreativeContextPanel.js +1171 -0
  159. package/dist/client/CreativeContextPanel.js.map +1 -0
  160. package/dist/client/CreativeContextSettingsLink.d.ts +4 -0
  161. package/dist/client/CreativeContextSettingsLink.d.ts.map +1 -0
  162. package/dist/client/CreativeContextSettingsLink.js +8 -0
  163. package/dist/client/CreativeContextSettingsLink.js.map +1 -0
  164. package/dist/client/CreativeContextShareTab.d.ts +56 -0
  165. package/dist/client/CreativeContextShareTab.d.ts.map +1 -0
  166. package/dist/client/CreativeContextShareTab.js +213 -0
  167. package/dist/client/CreativeContextShareTab.js.map +1 -0
  168. package/dist/client/actions.d.ts +474 -0
  169. package/dist/client/actions.d.ts.map +1 -0
  170. package/dist/client/actions.js +411 -0
  171. package/dist/client/actions.js.map +1 -0
  172. package/dist/client/agent-tab.d.ts +10 -0
  173. package/dist/client/agent-tab.d.ts.map +1 -0
  174. package/dist/client/agent-tab.js +32 -0
  175. package/dist/client/agent-tab.js.map +1 -0
  176. package/dist/client/application-state.d.ts +24 -0
  177. package/dist/client/application-state.d.ts.map +1 -0
  178. package/dist/client/application-state.js +111 -0
  179. package/dist/client/application-state.js.map +1 -0
  180. package/dist/client/google-slides-picker.d.ts +19 -0
  181. package/dist/client/google-slides-picker.d.ts.map +1 -0
  182. package/dist/client/google-slides-picker.js +106 -0
  183. package/dist/client/google-slides-picker.js.map +1 -0
  184. package/dist/client/index.d.ts +10 -0
  185. package/dist/client/index.d.ts.map +1 -0
  186. package/dist/client/index.js +10 -0
  187. package/dist/client/index.js.map +1 -0
  188. package/dist/client/messages.d.ts +5 -0
  189. package/dist/client/messages.d.ts.map +1 -0
  190. package/dist/client/messages.js +1158 -0
  191. package/dist/client/messages.js.map +1 -0
  192. package/dist/connectors/context.d.ts +9 -0
  193. package/dist/connectors/context.d.ts.map +1 -0
  194. package/dist/connectors/context.js +59 -0
  195. package/dist/connectors/context.js.map +1 -0
  196. package/dist/connectors/document-parser.d.ts +2 -0
  197. package/dist/connectors/document-parser.d.ts.map +1 -0
  198. package/dist/connectors/document-parser.js +2 -0
  199. package/dist/connectors/document-parser.js.map +1 -0
  200. package/dist/connectors/figma-native.d.ts +18 -0
  201. package/dist/connectors/figma-native.d.ts.map +1 -0
  202. package/dist/connectors/figma-native.js +883 -0
  203. package/dist/connectors/figma-native.js.map +1 -0
  204. package/dist/connectors/figma.d.ts +10 -0
  205. package/dist/connectors/figma.d.ts.map +1 -0
  206. package/dist/connectors/figma.js +166 -0
  207. package/dist/connectors/figma.js.map +1 -0
  208. package/dist/connectors/google-slides-native.d.ts +58 -0
  209. package/dist/connectors/google-slides-native.d.ts.map +1 -0
  210. package/dist/connectors/google-slides-native.js +1118 -0
  211. package/dist/connectors/google-slides-native.js.map +1 -0
  212. package/dist/connectors/google-slides.d.ts +15 -0
  213. package/dist/connectors/google-slides.d.ts.map +1 -0
  214. package/dist/connectors/google-slides.js +895 -0
  215. package/dist/connectors/google-slides.js.map +1 -0
  216. package/dist/connectors/index.d.ts +21 -0
  217. package/dist/connectors/index.d.ts.map +1 -0
  218. package/dist/connectors/index.js +45 -0
  219. package/dist/connectors/index.js.map +1 -0
  220. package/dist/connectors/manual.d.ts +9 -0
  221. package/dist/connectors/manual.d.ts.map +1 -0
  222. package/dist/connectors/manual.js +91 -0
  223. package/dist/connectors/manual.js.map +1 -0
  224. package/dist/connectors/normalize.d.ts +42 -0
  225. package/dist/connectors/normalize.d.ts.map +1 -0
  226. package/dist/connectors/normalize.js +335 -0
  227. package/dist/connectors/normalize.js.map +1 -0
  228. package/dist/connectors/notion.d.ts +10 -0
  229. package/dist/connectors/notion.d.ts.map +1 -0
  230. package/dist/connectors/notion.js +393 -0
  231. package/dist/connectors/notion.js.map +1 -0
  232. package/dist/connectors/private-artifacts.d.ts +39 -0
  233. package/dist/connectors/private-artifacts.d.ts.map +1 -0
  234. package/dist/connectors/private-artifacts.js +175 -0
  235. package/dist/connectors/private-artifacts.js.map +1 -0
  236. package/dist/connectors/provider-response.d.ts +20 -0
  237. package/dist/connectors/provider-response.d.ts.map +1 -0
  238. package/dist/connectors/provider-response.js +98 -0
  239. package/dist/connectors/provider-response.js.map +1 -0
  240. package/dist/connectors/recommendations.d.ts +25 -0
  241. package/dist/connectors/recommendations.d.ts.map +1 -0
  242. package/dist/connectors/recommendations.js +172 -0
  243. package/dist/connectors/recommendations.js.map +1 -0
  244. package/dist/connectors/registry.d.ts +10 -0
  245. package/dist/connectors/registry.d.ts.map +1 -0
  246. package/dist/connectors/registry.js +34 -0
  247. package/dist/connectors/registry.js.map +1 -0
  248. package/dist/connectors/rendered-design.d.ts +68 -0
  249. package/dist/connectors/rendered-design.d.ts.map +1 -0
  250. package/dist/connectors/rendered-design.js +362 -0
  251. package/dist/connectors/rendered-design.js.map +1 -0
  252. package/dist/connectors/rendered-page.d.ts +115 -0
  253. package/dist/connectors/rendered-page.d.ts.map +1 -0
  254. package/dist/connectors/rendered-page.js +1036 -0
  255. package/dist/connectors/rendered-page.js.map +1 -0
  256. package/dist/connectors/smart-defaults.d.ts +9 -0
  257. package/dist/connectors/smart-defaults.d.ts.map +1 -0
  258. package/dist/connectors/smart-defaults.js +72 -0
  259. package/dist/connectors/smart-defaults.js.map +1 -0
  260. package/dist/connectors/types.d.ts +79 -0
  261. package/dist/connectors/types.d.ts.map +1 -0
  262. package/dist/connectors/types.js +2 -0
  263. package/dist/connectors/types.js.map +1 -0
  264. package/dist/connectors/upload.d.ts +9 -0
  265. package/dist/connectors/upload.d.ts.map +1 -0
  266. package/dist/connectors/upload.js +440 -0
  267. package/dist/connectors/upload.js.map +1 -0
  268. package/dist/connectors/website.d.ts +20 -0
  269. package/dist/connectors/website.d.ts.map +1 -0
  270. package/dist/connectors/website.js +616 -0
  271. package/dist/connectors/website.js.map +1 -0
  272. package/dist/embeddings/index.d.ts +3 -0
  273. package/dist/embeddings/index.d.ts.map +1 -0
  274. package/dist/embeddings/index.js +3 -0
  275. package/dist/embeddings/index.js.map +1 -0
  276. package/dist/embeddings/providers.d.ts +2 -0
  277. package/dist/embeddings/providers.d.ts.map +1 -0
  278. package/dist/embeddings/providers.js +2 -0
  279. package/dist/embeddings/providers.js.map +1 -0
  280. package/dist/embeddings/types.d.ts +2 -0
  281. package/dist/embeddings/types.d.ts.map +1 -0
  282. package/dist/embeddings/types.js +2 -0
  283. package/dist/embeddings/types.js.map +1 -0
  284. package/dist/eval/acceptance-fixtures.d.ts +3 -0
  285. package/dist/eval/acceptance-fixtures.d.ts.map +1 -0
  286. package/dist/eval/acceptance-fixtures.js +84 -0
  287. package/dist/eval/acceptance-fixtures.js.map +1 -0
  288. package/dist/eval/acceptance.d.ts +114 -0
  289. package/dist/eval/acceptance.d.ts.map +1 -0
  290. package/dist/eval/acceptance.js +260 -0
  291. package/dist/eval/acceptance.js.map +1 -0
  292. package/dist/eval/fixtures.d.ts +16 -0
  293. package/dist/eval/fixtures.d.ts.map +1 -0
  294. package/dist/eval/fixtures.js +119 -0
  295. package/dist/eval/fixtures.js.map +1 -0
  296. package/dist/eval/index.d.ts +63 -0
  297. package/dist/eval/index.d.ts.map +1 -0
  298. package/dist/eval/index.js +174 -0
  299. package/dist/eval/index.js.map +1 -0
  300. package/dist/index.d.ts +5 -0
  301. package/dist/index.d.ts.map +1 -0
  302. package/dist/index.js +5 -0
  303. package/dist/index.js.map +1 -0
  304. package/dist/jobs/background-worker.d.ts +31 -0
  305. package/dist/jobs/background-worker.d.ts.map +1 -0
  306. package/dist/jobs/background-worker.js +315 -0
  307. package/dist/jobs/background-worker.js.map +1 -0
  308. package/dist/jobs/import-runner.d.ts +3 -0
  309. package/dist/jobs/import-runner.d.ts.map +1 -0
  310. package/dist/jobs/import-runner.js +613 -0
  311. package/dist/jobs/import-runner.js.map +1 -0
  312. package/dist/jobs/index.d.ts +9 -0
  313. package/dist/jobs/index.d.ts.map +1 -0
  314. package/dist/jobs/index.js +8 -0
  315. package/dist/jobs/index.js.map +1 -0
  316. package/dist/jobs/progress.d.ts +3 -0
  317. package/dist/jobs/progress.d.ts.map +1 -0
  318. package/dist/jobs/progress.js +30 -0
  319. package/dist/jobs/progress.js.map +1 -0
  320. package/dist/jobs/rebuild.d.ts +13 -0
  321. package/dist/jobs/rebuild.d.ts.map +1 -0
  322. package/dist/jobs/rebuild.js +178 -0
  323. package/dist/jobs/rebuild.js.map +1 -0
  324. package/dist/jobs/server-worker.d.ts +16 -0
  325. package/dist/jobs/server-worker.d.ts.map +1 -0
  326. package/dist/jobs/server-worker.js +262 -0
  327. package/dist/jobs/server-worker.js.map +1 -0
  328. package/dist/jobs/store-adapter.d.ts +3 -0
  329. package/dist/jobs/store-adapter.d.ts.map +1 -0
  330. package/dist/jobs/store-adapter.js +37 -0
  331. package/dist/jobs/store-adapter.js.map +1 -0
  332. package/dist/jobs/types.d.ts +138 -0
  333. package/dist/jobs/types.d.ts.map +1 -0
  334. package/dist/jobs/types.js +2 -0
  335. package/dist/jobs/types.js.map +1 -0
  336. package/dist/jobs/worker.d.ts +27 -0
  337. package/dist/jobs/worker.d.ts.map +1 -0
  338. package/dist/jobs/worker.js +90 -0
  339. package/dist/jobs/worker.js.map +1 -0
  340. package/dist/media-url.d.ts +7 -0
  341. package/dist/media-url.d.ts.map +1 -0
  342. package/dist/media-url.js +15 -0
  343. package/dist/media-url.js.map +1 -0
  344. package/dist/native-artifact-reassembly.d.ts +25 -0
  345. package/dist/native-artifact-reassembly.d.ts.map +1 -0
  346. package/dist/native-artifact-reassembly.js +262 -0
  347. package/dist/native-artifact-reassembly.js.map +1 -0
  348. package/dist/native-artifact.d.ts +88 -0
  349. package/dist/native-artifact.d.ts.map +1 -0
  350. package/dist/native-artifact.js +86 -0
  351. package/dist/native-artifact.js.map +1 -0
  352. package/dist/schema/index.d.ts +7111 -0
  353. package/dist/schema/index.d.ts.map +1 -0
  354. package/dist/schema/index.js +469 -0
  355. package/dist/schema/index.js.map +1 -0
  356. package/dist/schema/migrations.d.ts +10 -0
  357. package/dist/schema/migrations.d.ts.map +1 -0
  358. package/dist/schema/migrations.js +333 -0
  359. package/dist/schema/migrations.js.map +1 -0
  360. package/dist/search/fusion.d.ts +2 -0
  361. package/dist/search/fusion.d.ts.map +1 -0
  362. package/dist/search/fusion.js +2 -0
  363. package/dist/search/fusion.js.map +1 -0
  364. package/dist/search/mode.d.ts +4 -0
  365. package/dist/search/mode.d.ts.map +1 -0
  366. package/dist/search/mode.js +13 -0
  367. package/dist/search/mode.js.map +1 -0
  368. package/dist/search/postgres-fts.d.ts +2 -0
  369. package/dist/search/postgres-fts.d.ts.map +1 -0
  370. package/dist/search/postgres-fts.js +2 -0
  371. package/dist/search/postgres-fts.js.map +1 -0
  372. package/dist/server/brand-context.d.ts +15 -0
  373. package/dist/server/brand-context.d.ts.map +1 -0
  374. package/dist/server/brand-context.js +149 -0
  375. package/dist/server/brand-context.js.map +1 -0
  376. package/dist/server/context.d.ts +77 -0
  377. package/dist/server/context.d.ts.map +1 -0
  378. package/dist/server/context.js +63 -0
  379. package/dist/server/context.js.map +1 -0
  380. package/dist/server/enrichment.d.ts +24 -0
  381. package/dist/server/enrichment.d.ts.map +1 -0
  382. package/dist/server/enrichment.js +138 -0
  383. package/dist/server/enrichment.js.map +1 -0
  384. package/dist/server/generation-artifact-access.d.ts +21 -0
  385. package/dist/server/generation-artifact-access.d.ts.map +1 -0
  386. package/dist/server/generation-artifact-access.js +113 -0
  387. package/dist/server/generation-artifact-access.js.map +1 -0
  388. package/dist/server/generation-context.d.ts +220 -0
  389. package/dist/server/generation-context.d.ts.map +1 -0
  390. package/dist/server/generation-context.js +432 -0
  391. package/dist/server/generation-context.js.map +1 -0
  392. package/dist/server/index.d.ts +27 -0
  393. package/dist/server/index.d.ts.map +1 -0
  394. package/dist/server/index.js +115 -0
  395. package/dist/server/index.js.map +1 -0
  396. package/dist/server/isolated-a2a.d.ts +175 -0
  397. package/dist/server/isolated-a2a.d.ts.map +1 -0
  398. package/dist/server/isolated-a2a.js +312 -0
  399. package/dist/server/isolated-a2a.js.map +1 -0
  400. package/dist/server/media.d.ts +15 -0
  401. package/dist/server/media.d.ts.map +1 -0
  402. package/dist/server/media.js +108 -0
  403. package/dist/server/media.js.map +1 -0
  404. package/dist/server/native-resource-capture.d.ts +78 -0
  405. package/dist/server/native-resource-capture.d.ts.map +1 -0
  406. package/dist/server/native-resource-capture.js +94 -0
  407. package/dist/server/native-resource-capture.js.map +1 -0
  408. package/dist/server/prompt-provider.d.ts +5 -0
  409. package/dist/server/prompt-provider.d.ts.map +1 -0
  410. package/dist/server/prompt-provider.js +59 -0
  411. package/dist/server/prompt-provider.js.map +1 -0
  412. package/dist/server/public-serialization.d.ts +160 -0
  413. package/dist/server/public-serialization.d.ts.map +1 -0
  414. package/dist/server/public-serialization.js +108 -0
  415. package/dist/server/public-serialization.js.map +1 -0
  416. package/dist/server/resource-paths.d.ts +3 -0
  417. package/dist/server/resource-paths.d.ts.map +1 -0
  418. package/dist/server/resource-paths.js +5 -0
  419. package/dist/server/resource-paths.js.map +1 -0
  420. package/dist/server/retrieval.d.ts +83 -0
  421. package/dist/server/retrieval.d.ts.map +1 -0
  422. package/dist/server/retrieval.js +445 -0
  423. package/dist/server/retrieval.js.map +1 -0
  424. package/dist/server/safe-native-preview.d.ts +15 -0
  425. package/dist/server/safe-native-preview.d.ts.map +1 -0
  426. package/dist/server/safe-native-preview.js +148 -0
  427. package/dist/server/safe-native-preview.js.map +1 -0
  428. package/dist/store/brand.d.ts +47 -0
  429. package/dist/store/brand.d.ts.map +1 -0
  430. package/dist/store/brand.js +346 -0
  431. package/dist/store/brand.js.map +1 -0
  432. package/dist/store/content.d.ts +134 -0
  433. package/dist/store/content.d.ts.map +1 -0
  434. package/dist/store/content.js +1677 -0
  435. package/dist/store/content.js.map +1 -0
  436. package/dist/store/contexts.d.ts +216 -0
  437. package/dist/store/contexts.d.ts.map +1 -0
  438. package/dist/store/contexts.js +1346 -0
  439. package/dist/store/contexts.js.map +1 -0
  440. package/dist/store/generation.d.ts +28 -0
  441. package/dist/store/generation.d.ts.map +1 -0
  442. package/dist/store/generation.js +140 -0
  443. package/dist/store/generation.js.map +1 -0
  444. package/dist/store/helpers.d.ts +12 -0
  445. package/dist/store/helpers.d.ts.map +1 -0
  446. package/dist/store/helpers.js +41 -0
  447. package/dist/store/helpers.js.map +1 -0
  448. package/dist/store/index.d.ts +11 -0
  449. package/dist/store/index.d.ts.map +1 -0
  450. package/dist/store/index.js +11 -0
  451. package/dist/store/index.js.map +1 -0
  452. package/dist/store/inference.d.ts +57 -0
  453. package/dist/store/inference.d.ts.map +1 -0
  454. package/dist/store/inference.js +279 -0
  455. package/dist/store/inference.js.map +1 -0
  456. package/dist/store/jobs.d.ts +80 -0
  457. package/dist/store/jobs.d.ts.map +1 -0
  458. package/dist/store/jobs.js +428 -0
  459. package/dist/store/jobs.js.map +1 -0
  460. package/dist/store/native-artifact-summary.d.ts +7 -0
  461. package/dist/store/native-artifact-summary.d.ts.map +1 -0
  462. package/dist/store/native-artifact-summary.js +10 -0
  463. package/dist/store/native-artifact-summary.js.map +1 -0
  464. package/dist/store/packs.d.ts +36 -0
  465. package/dist/store/packs.d.ts.map +1 -0
  466. package/dist/store/packs.js +438 -0
  467. package/dist/store/packs.js.map +1 -0
  468. package/dist/store/purge.d.ts +16 -0
  469. package/dist/store/purge.d.ts.map +1 -0
  470. package/dist/store/purge.js +354 -0
  471. package/dist/store/purge.js.map +1 -0
  472. package/dist/store/sources.d.ts +76 -0
  473. package/dist/store/sources.d.ts.map +1 -0
  474. package/dist/store/sources.js +525 -0
  475. package/dist/store/sources.js.map +1 -0
  476. package/dist/store/suggestions.d.ts +29 -0
  477. package/dist/store/suggestions.d.ts.map +1 -0
  478. package/dist/store/suggestions.js +270 -0
  479. package/dist/store/suggestions.js.map +1 -0
  480. package/dist/types.d.ts +578 -0
  481. package/dist/types.d.ts.map +1 -0
  482. package/dist/types.js +10 -0
  483. package/dist/types.js.map +1 -0
  484. package/dist/untrusted-reference.d.ts +8 -0
  485. package/dist/untrusted-reference.d.ts.map +1 -0
  486. package/dist/untrusted-reference.js +19 -0
  487. package/dist/untrusted-reference.js.map +1 -0
  488. package/dist/vector/index.d.ts +2 -0
  489. package/dist/vector/index.d.ts.map +1 -0
  490. package/dist/vector/index.js +2 -0
  491. package/dist/vector/index.js.map +1 -0
  492. package/dist/vector/pgvector.d.ts +2 -0
  493. package/dist/vector/pgvector.d.ts.map +1 -0
  494. package/dist/vector/pgvector.js +2 -0
  495. package/dist/vector/pgvector.js.map +1 -0
  496. package/docs/evaluation.md +92 -0
  497. package/docs/llms-full.txt +168 -0
  498. package/docs/llms.txt +76 -0
  499. package/docs/skills/creative-context/SKILL.md +90 -0
  500. package/package.json +100 -0
  501. package/src/actions/agent-input-schemas.spec.ts +46 -0
  502. package/src/actions/confirm-canonical-logo.ts +20 -0
  503. package/src/actions/continue-context-import.ts +15 -0
  504. package/src/actions/creative-context-a2a.spec.ts +162 -0
  505. package/src/actions/creative-context-a2a.ts +88 -0
  506. package/src/actions/get-brand-profile.ts +16 -0
  507. package/src/actions/get-context-import-status.ts +13 -0
  508. package/src/actions/get-context-item.ts +1 -0
  509. package/src/actions/get-context-pack.ts +14 -0
  510. package/src/actions/get-creative-context.spec.ts +435 -0
  511. package/src/actions/get-creative-context.ts +197 -0
  512. package/src/actions/get-google-picker-session.spec.ts +62 -0
  513. package/src/actions/get-google-picker-session.ts +45 -0
  514. package/src/actions/index.ts +75 -0
  515. package/src/actions/infer-brand-dna.ts +15 -0
  516. package/src/actions/job-public-serialization.spec.ts +143 -0
  517. package/src/actions/list-canonical-logo-candidates.ts +121 -0
  518. package/src/actions/list-context-connections.spec.ts +23 -0
  519. package/src/actions/list-context-connections.ts +51 -0
  520. package/src/actions/list-context-memberships.ts +56 -0
  521. package/src/actions/list-context-packs.ts +17 -0
  522. package/src/actions/list-context-sources.ts +21 -0
  523. package/src/actions/list-context-suggestions.ts +30 -0
  524. package/src/actions/list-creative-contexts.spec.ts +38 -0
  525. package/src/actions/list-creative-contexts.ts +32 -0
  526. package/src/actions/manage-brand-profile.ts +58 -0
  527. package/src/actions/manage-context-membership.ts +80 -0
  528. package/src/actions/manage-context-pack.ts +81 -0
  529. package/src/actions/manage-context-source.ts +151 -0
  530. package/src/actions/manage-creative-context.ts +73 -0
  531. package/src/actions/manage-layout-template.ts +51 -0
  532. package/src/actions/preview-context-import.spec.ts +64 -0
  533. package/src/actions/preview-context-import.ts +61 -0
  534. package/src/actions/process-context-purge.ts +28 -0
  535. package/src/actions/propose-brand-dna.ts +22 -0
  536. package/src/actions/propose-canonical-logo.ts +19 -0
  537. package/src/actions/publish-brand-dna.ts +25 -0
  538. package/src/actions/recommend-context-roots.ts +24 -0
  539. package/src/actions/record-context-feedback.ts +16 -0
  540. package/src/actions/review-context-items.ts +69 -0
  541. package/src/actions/run-embedding-bakeoff.ts +90 -0
  542. package/src/actions/search-creative-context.ts +48 -0
  543. package/src/actions/set-brand-dna.ts +22 -0
  544. package/src/actions/start-context-enrichment.ts +52 -0
  545. package/src/actions/start-context-import.ts +38 -0
  546. package/src/client/CreativeContextChip.spec.ts +59 -0
  547. package/src/client/CreativeContextChip.tsx +243 -0
  548. package/src/client/CreativeContextPanel.tsx +3600 -0
  549. package/src/client/CreativeContextSettingsLink.tsx +30 -0
  550. package/src/client/CreativeContextShareTab.spec.ts +70 -0
  551. package/src/client/CreativeContextShareTab.tsx +666 -0
  552. package/src/client/actions.spec.ts +177 -0
  553. package/src/client/actions.ts +1024 -0
  554. package/src/client/agent-tab.tsx +56 -0
  555. package/src/client/application-state.spec.ts +46 -0
  556. package/src/client/application-state.ts +158 -0
  557. package/src/client/google-slides-picker.spec.ts +36 -0
  558. package/src/client/google-slides-picker.ts +146 -0
  559. package/src/client/index.ts +102 -0
  560. package/src/client/messages.ts +1370 -0
  561. package/src/client/source-config.spec.ts +166 -0
  562. package/src/connectors/connectors.spec.ts +778 -0
  563. package/src/connectors/context.ts +83 -0
  564. package/src/connectors/document-parser.ts +5 -0
  565. package/src/connectors/figma-native.ts +1192 -0
  566. package/src/connectors/figma-native.visual.spec.ts +221 -0
  567. package/src/connectors/figma.spec.ts +812 -0
  568. package/src/connectors/figma.ts +257 -0
  569. package/src/connectors/fixtures/google-slides-native.json +353 -0
  570. package/src/connectors/google-slides-native.spec.ts +804 -0
  571. package/src/connectors/google-slides-native.ts +1656 -0
  572. package/src/connectors/google-slides-native.visual.spec.ts +119 -0
  573. package/src/connectors/google-slides.ts +1171 -0
  574. package/src/connectors/index.ts +112 -0
  575. package/src/connectors/manual.ts +132 -0
  576. package/src/connectors/normalize.spec.ts +144 -0
  577. package/src/connectors/normalize.ts +475 -0
  578. package/src/connectors/notion.ts +529 -0
  579. package/src/connectors/private-artifacts.spec.ts +95 -0
  580. package/src/connectors/private-artifacts.ts +248 -0
  581. package/src/connectors/provider-response.ts +144 -0
  582. package/src/connectors/recommendations.ts +237 -0
  583. package/src/connectors/registry.ts +48 -0
  584. package/src/connectors/rendered-design.spec.ts +171 -0
  585. package/src/connectors/rendered-design.ts +495 -0
  586. package/src/connectors/rendered-page.spec.ts +388 -0
  587. package/src/connectors/rendered-page.ts +1387 -0
  588. package/src/connectors/smart-defaults.spec.ts +135 -0
  589. package/src/connectors/smart-defaults.ts +87 -0
  590. package/src/connectors/types.ts +113 -0
  591. package/src/connectors/upload.spec.ts +175 -0
  592. package/src/connectors/upload.ts +548 -0
  593. package/src/connectors/website.spec.ts +465 -0
  594. package/src/connectors/website.ts +777 -0
  595. package/src/embeddings/index.ts +2 -0
  596. package/src/embeddings/providers.spec.ts +73 -0
  597. package/src/embeddings/providers.ts +1 -0
  598. package/src/embeddings/types.ts +6 -0
  599. package/src/eval/acceptance-fixtures.ts +97 -0
  600. package/src/eval/acceptance.spec.ts +92 -0
  601. package/src/eval/acceptance.ts +371 -0
  602. package/src/eval/connectors-golden.spec.ts +421 -0
  603. package/src/eval/eval.spec.ts +166 -0
  604. package/src/eval/fixtures/README.md +17 -0
  605. package/src/eval/fixtures/figma-brand-system-v1.json +140 -0
  606. package/src/eval/fixtures/figma-brand-system-v2.json +127 -0
  607. package/src/eval/fixtures/launch-hero.png +0 -0
  608. package/src/eval/fixtures/launch-system-v1.pptx +0 -0
  609. package/src/eval/fixtures/launch-system-v2.pptx +0 -0
  610. package/src/eval/fixtures/notion-brand-root.json +218 -0
  611. package/src/eval/fixtures/pricing-hero.png +0 -0
  612. package/src/eval/fixtures/rendered-brand-page.html +76 -0
  613. package/src/eval/fixtures.spec.ts +43 -0
  614. package/src/eval/fixtures.ts +136 -0
  615. package/src/eval/index.ts +291 -0
  616. package/src/eval/library-flow.acceptance.spec.tsx +145 -0
  617. package/src/index.ts +4 -0
  618. package/src/jobs/background-worker.ts +423 -0
  619. package/src/jobs/import-runner.spec.ts +582 -0
  620. package/src/jobs/import-runner.ts +791 -0
  621. package/src/jobs/index.ts +40 -0
  622. package/src/jobs/progress.ts +37 -0
  623. package/src/jobs/rebuild.ts +245 -0
  624. package/src/jobs/server-worker.spec.ts +181 -0
  625. package/src/jobs/server-worker.ts +354 -0
  626. package/src/jobs/store-adapter.ts +52 -0
  627. package/src/jobs/types.ts +147 -0
  628. package/src/jobs/worker.ts +152 -0
  629. package/src/manifest.spec.ts +26 -0
  630. package/src/media-url.ts +17 -0
  631. package/src/native-artifact-reassembly.spec.ts +386 -0
  632. package/src/native-artifact-reassembly.ts +406 -0
  633. package/src/native-artifact.ts +102 -0
  634. package/src/schema/index.ts +527 -0
  635. package/src/schema/migrations.spec.ts +41 -0
  636. package/src/schema/migrations.ts +338 -0
  637. package/src/search/fusion.spec.ts +21 -0
  638. package/src/search/fusion.ts +1 -0
  639. package/src/search/mode.spec.ts +28 -0
  640. package/src/search/mode.ts +21 -0
  641. package/src/search/postgres-fts.spec.ts +63 -0
  642. package/src/search/postgres-fts.ts +1 -0
  643. package/src/server/brand-context.spec.ts +43 -0
  644. package/src/server/brand-context.ts +160 -0
  645. package/src/server/context.ts +162 -0
  646. package/src/server/enrichment.spec.ts +94 -0
  647. package/src/server/enrichment.ts +166 -0
  648. package/src/server/generation-artifact-access.spec.ts +104 -0
  649. package/src/server/generation-artifact-access.ts +217 -0
  650. package/src/server/generation-context-a2a.spec.ts +282 -0
  651. package/src/server/generation-context-off.spec.ts +213 -0
  652. package/src/server/generation-context.spec.ts +124 -0
  653. package/src/server/generation-context.ts +639 -0
  654. package/src/server/index.spec.ts +30 -0
  655. package/src/server/index.ts +163 -0
  656. package/src/server/isolated-a2a.spec.ts +184 -0
  657. package/src/server/isolated-a2a.ts +416 -0
  658. package/src/server/media.spec.ts +120 -0
  659. package/src/server/media.ts +136 -0
  660. package/src/server/native-resource-capture.spec.ts +121 -0
  661. package/src/server/native-resource-capture.ts +198 -0
  662. package/src/server/prompt-provider.spec.ts +78 -0
  663. package/src/server/prompt-provider.ts +73 -0
  664. package/src/server/public-serialization.spec.ts +150 -0
  665. package/src/server/public-serialization.ts +130 -0
  666. package/src/server/resource-paths.spec.ts +9 -0
  667. package/src/server/resource-paths.ts +5 -0
  668. package/src/server/retrieval-vector.spec.ts +180 -0
  669. package/src/server/retrieval.ts +590 -0
  670. package/src/server/safe-native-preview.spec.ts +29 -0
  671. package/src/server/safe-native-preview.ts +199 -0
  672. package/src/store/access.integration.spec.ts +3523 -0
  673. package/src/store/brand.ts +458 -0
  674. package/src/store/content.ts +2317 -0
  675. package/src/store/contexts.ts +1840 -0
  676. package/src/store/generation.ts +226 -0
  677. package/src/store/helpers.ts +53 -0
  678. package/src/store/index.ts +10 -0
  679. package/src/store/inference.spec.ts +84 -0
  680. package/src/store/inference.ts +339 -0
  681. package/src/store/invariants.spec.ts +119 -0
  682. package/src/store/jobs.ts +674 -0
  683. package/src/store/native-artifact-summary.ts +13 -0
  684. package/src/store/packs.ts +721 -0
  685. package/src/store/purge.ts +463 -0
  686. package/src/store/sources.spec.ts +102 -0
  687. package/src/store/sources.ts +692 -0
  688. package/src/store/suggestions.ts +361 -0
  689. package/src/types.ts +671 -0
  690. package/src/untrusted-reference.spec.ts +22 -0
  691. package/src/untrusted-reference.ts +24 -0
  692. package/src/vector/index.ts +1 -0
  693. package/src/vector/pgvector.spec.ts +115 -0
  694. package/src/vector/pgvector.ts +1 -0
  695. package/tsconfig.json +31 -0
@@ -0,0 +1,1171 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useFormatters, useT } from "@agent-native/core/client/i18n";
3
+ import { useOrg } from "@agent-native/core/client/org";
4
+ import { useUploadResource } from "@agent-native/core/client/uploads";
5
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, Skeleton, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, } from "@agent-native/toolkit/ui";
6
+ import { IconAlertTriangle, IconArrowUpRight, IconBooks, IconChartBar, IconCheck, IconDots, IconFileImport, IconFileText, IconLayout, IconPalette, IconPhoto, IconPlayerPlay, IconPin, IconPlus, IconRefresh, IconSearch, IconSlideshow, IconSparkles, IconUpload, IconWorld, } from "@tabler/icons-react";
7
+ import { useEffect, useMemo, useRef, useState, } from "react";
8
+ import { creativeContextMediaUrl } from "../media-url.js";
9
+ import { useCreativeContextBrandProfile, useCreativeContexts, useCanonicalLogoCandidates, useCreativeContextConnections, useCreativeContextGooglePickerSession, useCreativeContextRootRecommendations, useCreativeContextImportStatus, useCreativeContextPack, useCreativeContextPacks, useContextMemberships, useManageCreativeContext, useManageContextMembership, useCreativeContextSearch, useCreativeContextSuggestions, useCreativeContextSources, useManageCreativeContextSource, useManageLayoutTemplate, usePreviewCreativeContextImport, usePublishCreativeContextBrandDna, useConfirmCanonicalLogo, useProposeCanonicalLogo, useRefreshCreativeContextSource, useReviewCreativeContextItems, useStartCreativeContextImport, parseCreativeContexts, parseContextMemberships, } from "./actions.js";
10
+ import { useCreativeContextState, } from "./application-state.js";
11
+ import { CreativeContextChip } from "./CreativeContextChip.js";
12
+ import { chooseGoogleSlidesPresentations } from "./google-slides-picker.js";
13
+ const CONNECTORS = [
14
+ {
15
+ kind: "google-slides",
16
+ label: "Google Slides",
17
+ referencePlaceholder: "Presentation URLs or IDs — one per line",
18
+ referenceRequired: false,
19
+ icon: IconSlideshow,
20
+ },
21
+ {
22
+ kind: "figma",
23
+ label: "Figma",
24
+ referencePlaceholder: "Team, project, or file URLs — one per line",
25
+ referenceRequired: false,
26
+ icon: IconPalette,
27
+ },
28
+ {
29
+ kind: "notion",
30
+ label: "Notion",
31
+ referencePlaceholder: "Page or teamspace root URLs / IDs — one per line",
32
+ referenceRequired: false,
33
+ icon: IconFileText,
34
+ },
35
+ {
36
+ kind: "website",
37
+ label: "Website",
38
+ referencePlaceholder: "https://example.com\nhttps://example.com/about",
39
+ referenceRequired: true,
40
+ icon: IconWorld,
41
+ },
42
+ {
43
+ kind: "upload",
44
+ label: "Uploaded files",
45
+ referencePlaceholder: "One hosted file URL per line",
46
+ referenceRequired: true,
47
+ icon: IconUpload,
48
+ },
49
+ ];
50
+ function isVisibleInScope(visibility, scope) {
51
+ return scope === "org" ? visibility !== "private" : visibility === "private";
52
+ }
53
+ function splitReferences(value) {
54
+ return value
55
+ .split(/\r?\n|,/)
56
+ .map((entry) => entry.trim())
57
+ .filter(Boolean);
58
+ }
59
+ function connectionProviderForConnector(kind) {
60
+ if (kind === "google-slides")
61
+ return "google_drive";
62
+ if (kind === "figma" || kind === "notion")
63
+ return kind;
64
+ return null;
65
+ }
66
+ function recommendationProviderForConnector(kind) {
67
+ if (kind === "google-slides" || kind === "figma" || kind === "notion") {
68
+ return kind;
69
+ }
70
+ return null;
71
+ }
72
+ export function parseFigmaRecommendationBoundary(reference) {
73
+ for (const value of splitReferences(reference)) {
74
+ const teamId = value.match(/\/team\/([^/?#]+)/)?.[1] ??
75
+ (value.startsWith("team:") ? value.slice("team:".length) : undefined);
76
+ if (teamId)
77
+ return { figmaTeamId: teamId };
78
+ const projectId = value.match(/\/project\/([^/?#]+)/)?.[1] ??
79
+ (value.startsWith("project:")
80
+ ? value.slice("project:".length)
81
+ : undefined);
82
+ if (projectId)
83
+ return { figmaProjectId: projectId };
84
+ }
85
+ return {};
86
+ }
87
+ export function selectRenderableLayoutThumbnails(thumbnails) {
88
+ return thumbnails.filter((thumbnail) => thumbnail.hasThumbnail).slice(0, 3);
89
+ }
90
+ export function mergeRecommendationSelection(current, available, previouslySeen) {
91
+ const next = new Set([...current].filter((externalId) => available.has(externalId)));
92
+ for (const externalId of available) {
93
+ if (!previouslySeen.has(externalId))
94
+ next.add(externalId);
95
+ }
96
+ return next;
97
+ }
98
+ export function buildCreativeContextSourceConfig(kind, reference, uploadedFiles, recommendations = []) {
99
+ const references = splitReferences(reference);
100
+ if (kind === "google-slides") {
101
+ const presentationIds = references.flatMap((value) => {
102
+ const match = value.match(/\/presentation\/d\/([^/?#]+)/);
103
+ const id = match?.[1] ?? (/^https?:\/\//.test(value) ? "" : value);
104
+ return id ? [id] : [];
105
+ });
106
+ return {
107
+ presentationIds: [
108
+ ...new Set([
109
+ ...presentationIds,
110
+ ...recommendations.map((item) => item.externalId),
111
+ ]),
112
+ ],
113
+ };
114
+ }
115
+ if (kind === "figma") {
116
+ const fileUrls = [];
117
+ const projectUrls = [];
118
+ const teamUrls = [];
119
+ for (const url of references) {
120
+ if (/\/team\//.test(url))
121
+ teamUrls.push(url);
122
+ else if (/\/project\//.test(url))
123
+ projectUrls.push(url);
124
+ else
125
+ fileUrls.push(url);
126
+ }
127
+ return {
128
+ fileUrls,
129
+ projectUrls,
130
+ teamUrls,
131
+ ...(recommendations.length
132
+ ? { fileKeys: recommendations.map((item) => item.externalId) }
133
+ : {}),
134
+ };
135
+ }
136
+ if (kind === "notion") {
137
+ const rootPageIds = [];
138
+ const rootPageUrls = [];
139
+ const teamspaceRootPageIds = [];
140
+ const teamspaceRootPageUrls = [];
141
+ for (const root of references) {
142
+ const isTeamspace = root.startsWith("teamspace:");
143
+ const value = isTeamspace ? root.slice("teamspace:".length) : root;
144
+ if (/^https?:\/\//.test(value)) {
145
+ (isTeamspace ? teamspaceRootPageUrls : rootPageUrls).push(value);
146
+ }
147
+ else {
148
+ (isTeamspace ? teamspaceRootPageIds : rootPageIds).push(value);
149
+ }
150
+ }
151
+ return {
152
+ rootPageIds: [
153
+ ...rootPageIds,
154
+ ...recommendations.map((item) => item.externalId),
155
+ ],
156
+ rootPageUrls,
157
+ teamspaceRootPageIds,
158
+ teamspaceRootPageUrls,
159
+ };
160
+ }
161
+ if (kind === "website")
162
+ return { urls: references };
163
+ return { items: uploadedFiles };
164
+ }
165
+ function ContextModeButton({ mode, activeMode, label, description, disabled, onSelect, }) {
166
+ const selected = mode === activeMode;
167
+ return (_jsxs("button", { type: "button", role: "radio", "aria-checked": selected, disabled: disabled, onClick: () => onSelect(mode), className: `min-w-0 flex-1 cursor-pointer rounded-md border px-3 py-2 text-start transition-colors disabled:cursor-not-allowed disabled:opacity-60 ${selected
168
+ ? "border-foreground/25 bg-accent/70 text-foreground"
169
+ : "border-border bg-background text-muted-foreground hover:bg-accent/40 hover:text-foreground"}`, children: [_jsx("span", { className: "block text-sm font-medium", children: label }), _jsx("span", { className: "mt-0.5 block text-xs leading-relaxed", children: description })] }));
170
+ }
171
+ function ScopeControl({ scope, onChange, }) {
172
+ const t = useT();
173
+ return (_jsx("div", { className: "inline-flex rounded-md border border-border bg-muted/30 p-0.5", children: ["user", "org"].map((value) => (_jsx("button", { type: "button", "aria-pressed": scope === value, onClick: () => onChange(value), className: `rounded px-2.5 py-1 text-xs font-medium transition-colors ${scope === value
174
+ ? "bg-background text-foreground shadow-sm"
175
+ : "text-muted-foreground hover:text-foreground"}`, children: t(value === "user"
176
+ ? "creativeContext.personal"
177
+ : "creativeContext.organization") }, value))) }));
178
+ }
179
+ function SourceRow({ source, refreshing, canReview, onRefresh, onReview, onCurate, canPromote, onPromote, onPause, onRestore, onDelete, }) {
180
+ const t = useT();
181
+ const { formatDate, formatNumber } = useFormatters();
182
+ return (_jsxs("div", { className: "flex items-start gap-3 border-t border-border/60 py-3 first:border-t-0", children: [_jsx("div", { className: "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground", children: _jsx(IconBooks, { className: "size-4" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: source.name }), _jsx(Badge, { variant: "secondary", className: "font-normal", children: source.kind }), source.status === "error" ? (_jsx(Badge, { variant: "destructive", className: "font-normal", children: t("creativeContext.sourceError") })) : source.status !== "active" ? (_jsx(Badge, { variant: "outline", className: "font-normal", children: source.status })) : null] }), _jsxs("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { children: t("creativeContext.itemsLabel", {
183
+ count: formatNumber(source.itemCount),
184
+ }) }), source.lastSyncedAt ? (_jsx("span", { children: formatDate(source.lastSyncedAt, {
185
+ month: "short",
186
+ day: "numeric",
187
+ year: "numeric",
188
+ }) })) : null] }), source.restrictedItemCount > 0 ? (_jsxs("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-xs text-amber-700 dark:text-amber-300", children: [_jsx("span", { children: t("creativeContext.restrictedItems", {
189
+ count: formatNumber(source.restrictedItemCount),
190
+ }) }), canReview ? (_jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "h-6 px-2 text-xs", onClick: () => onReview(source), children: t("creativeContext.reviewRestricted") })) : null] })) : null, source.lastError ? (_jsx("p", { className: "mt-1 line-clamp-2 text-xs text-destructive", children: source.lastError })) : null] }), source.status !== "archived" ? (_jsxs(Button, { type: "button", variant: "ghost", size: "sm", disabled: refreshing, onClick: () => onRefresh(source.id), children: [_jsx(IconRefresh, { className: refreshing ? "animate-spin" : undefined }), refreshing
191
+ ? t("creativeContext.refreshing")
192
+ : t("creativeContext.refresh")] })) : null, _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon", "aria-label": t("creativeContext.manage"), children: _jsx(IconDots, {}) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { onSelect: () => onCurate(source), children: t("creativeContext.curateItems") }), source.status === "paused" || source.status === "error" ? (_jsx(DropdownMenuItem, { onSelect: () => onRestore(source), children: t("creativeContext.restore") })) : (_jsx(DropdownMenuItem, { onSelect: () => onPause(source), children: t("creativeContext.pause") })), canPromote ? (_jsx(DropdownMenuItem, { onSelect: () => onPromote(source), children: t("creativeContext.promoteToOrganization") })) : null, _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { className: "text-destructive focus:text-destructive", onSelect: () => onDelete(source), children: t("creativeContext.delete") })] })] })] }));
193
+ }
194
+ function PackRow({ pack, pinned, disabled, onPin, onDetails, }) {
195
+ const t = useT();
196
+ const { formatNumber } = useFormatters();
197
+ return (_jsxs("div", { className: "flex items-center gap-3 border-t border-border/60 py-3 first:border-t-0", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium", children: pack.name }), pinned ? (_jsxs(Badge, { variant: "secondary", className: "font-normal", children: [_jsx(IconPin, { className: "me-1 size-3" }), t("creativeContext.pinned")] })) : null] }), pack.description ? (_jsx("p", { className: "mt-0.5 line-clamp-2 text-xs text-muted-foreground", children: pack.description })) : null, _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t("creativeContext.itemsLabel", {
198
+ count: formatNumber(pack.memberCount),
199
+ }) })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onDetails(pack.id), children: t("creativeContext.packDetails") }), _jsxs(Button, { type: "button", variant: pinned ? "secondary" : "ghost", size: "sm", disabled: disabled, onClick: () => onPin(pinned ? null : pack.id), children: [_jsx(IconPin, {}), pinned ? t("creativeContext.unpin") : t("creativeContext.pin")] })] }));
200
+ }
201
+ function AccessScopedThumbnail({ itemId, itemVersionId, className, }) {
202
+ const [failed, setFailed] = useState(false);
203
+ if (failed) {
204
+ return (_jsx("div", { className: `flex items-center justify-center bg-muted text-muted-foreground ${className}`, children: _jsx(IconFileText, { className: "size-5" }) }));
205
+ }
206
+ return (_jsx("img", { src: creativeContextMediaUrl({ itemId, itemVersionId }), alt: "", className: className, onError: () => setFailed(true) }));
207
+ }
208
+ function ItemCuration({ source, items, busy, onReview, onClose, }) {
209
+ const t = useT();
210
+ return (_jsxs("div", { className: "mt-4 rounded-md border border-border p-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold", children: t("creativeContext.curateItems") }), _jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: source.name })] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: onClose, children: t("creativeContext.cancel") })] }), _jsx("div", { className: "mt-3 grid gap-3 sm:grid-cols-2", children: items.map((item) => (_jsxs("article", { className: "overflow-hidden rounded-md border border-border/70", children: [item.thumbnailBlobRef ? (_jsx(AccessScopedThumbnail, { itemId: item.id, itemVersionId: item.currentVersionId, className: "aspect-video w-full object-cover" }, item.currentVersionId)) : (_jsx("div", { className: "flex aspect-video w-full items-center justify-center bg-muted text-muted-foreground", children: _jsx(IconFileText, { className: "size-5" }) })), _jsxs("div", { className: "p-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-sm font-medium", children: item.title }), _jsx("p", { className: "text-xs text-muted-foreground", children: item.kind })] }), _jsxs("div", { className: "flex flex-wrap justify-end gap-1", children: [item.curationRank === "exemplar" ? (_jsx(Badge, { variant: "secondary", children: t("creativeContext.exemplar") })) : null, item.status === "deprecated" ? (_jsx(Badge, { variant: "outline", children: t("creativeContext.deprecated") })) : null, item.upstreamAccess === "unknown" ? (_jsx(Badge, { variant: "outline", children: t("creativeContext.unknownAccess") })) : null] })] }), _jsxs("div", { className: "mt-3 flex flex-wrap gap-1.5", children: [_jsx(Button, { type: "button", variant: item.starred ? "secondary" : "outline", size: "sm", disabled: busy, onClick: () => onReview(item.starred ? "unstar" : "star", item.id), children: t(item.starred
211
+ ? "creativeContext.unstar"
212
+ : "creativeContext.star") }), _jsx(Button, { type: "button", variant: item.curationRank === "exemplar" ? "secondary" : "outline", size: "sm", disabled: busy, onClick: () => onReview(item.curationRank === "exemplar" ? "normal" : "exemplar", item.id), children: t("creativeContext.exemplar") }), _jsx(Button, { type: "button", variant: item.curationRank === "ignored" ? "secondary" : "outline", size: "sm", disabled: busy, onClick: () => onReview(item.curationRank === "ignored" ? "normal" : "ignore", item.id), children: t("creativeContext.ignore") }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", disabled: busy, onClick: () => onReview(item.status === "deprecated" ? "restore" : "deprecate", item.id), children: t(item.status === "deprecated"
213
+ ? "creativeContext.restore"
214
+ : "creativeContext.deprecate") })] }), item.curationStatus === "review" ? (_jsxs("div", { className: "mt-2 flex gap-1.5 border-t border-border/60 pt-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", disabled: busy, onClick: () => onReview("exclude", item.id), children: t("creativeContext.exclude") }), _jsx(Button, { type: "button", size: "sm", disabled: busy, onClick: () => onReview("approve", item.id), children: t("creativeContext.approve") })] })) : null] })] }, item.id))) })] }));
215
+ }
216
+ function StructuredPreview({ preview, compact = false, }) {
217
+ if (!preview) {
218
+ return (_jsx("div", { className: "flex h-full min-h-28 items-center justify-center bg-muted text-muted-foreground", children: _jsx(IconFileText, { className: "size-5" }) }));
219
+ }
220
+ if (preview.type === "slides") {
221
+ const visibleSlides = compact ? preview.slides.slice(0, 3) : preview.slides;
222
+ return (_jsxs("div", { className: "grid h-full grid-cols-3 gap-1.5 bg-muted/50 p-2", children: [visibleSlides.map((slide) => (_jsxs("div", { className: "min-w-0 rounded border border-border/70 bg-background p-1.5", children: [_jsx("span", { className: "text-[10px] font-medium text-muted-foreground", children: slide.index }), _jsx("p", { className: "mt-1 line-clamp-2 text-[11px] font-medium leading-tight", children: slide.title }), !compact && slide.excerpt ? (_jsx("p", { className: "mt-1 line-clamp-5 text-[10px] leading-snug text-muted-foreground", children: slide.excerpt })) : null] }, slide.index))), !visibleSlides.length ? (_jsxs("div", { className: "col-span-3 flex items-center justify-center text-xs text-muted-foreground", children: [preview.slideCount, " slides"] })) : null] }));
223
+ }
224
+ if (preview.type === "slide") {
225
+ return (_jsxs("div", { className: "flex h-full flex-col justify-between bg-muted/50 p-4", children: [_jsxs("span", { className: "text-xs text-muted-foreground", children: ["Slide ", preview.index] }), _jsx("p", { className: "line-clamp-3 text-sm font-semibold", children: preview.title }), preview.excerpt ? (_jsx("p", { className: "line-clamp-5 text-xs leading-relaxed text-muted-foreground", children: preview.excerpt })) : null] }));
226
+ }
227
+ if (preview.type === "design" || preview.type === "design-frame") {
228
+ const frames = preview.type === "design"
229
+ ? preview.frames
230
+ : [
231
+ {
232
+ title: preview.title,
233
+ fileType: preview.fileType,
234
+ excerpt: preview.excerpt,
235
+ },
236
+ ];
237
+ const visibleFrames = compact ? frames.slice(0, 4) : frames;
238
+ return (_jsx("div", { className: "grid h-full grid-cols-2 gap-1.5 bg-muted/50 p-2", children: visibleFrames.map((frame, index) => (_jsxs("div", { className: "min-w-0 rounded border border-border/70 bg-background p-2", children: [_jsxs("div", { className: "flex items-center gap-1 text-muted-foreground", children: [_jsx(IconLayout, { className: "size-3 shrink-0" }), _jsx("span", { className: "truncate text-[10px] uppercase tracking-wide", children: frame.fileType })] }), _jsx("p", { className: "mt-2 line-clamp-2 text-xs font-medium leading-tight", children: frame.title }), !compact && frame.excerpt ? (_jsx("p", { className: "mt-1 line-clamp-4 text-[10px] leading-snug text-muted-foreground", children: frame.excerpt })) : null] }, `${frame.title}-${index}`))) }));
239
+ }
240
+ if (preview.type === "document") {
241
+ const visibleBlocks = preview.blocks.slice(0, compact ? 7 : 40);
242
+ return (_jsx("article", { className: "h-full overflow-auto bg-background p-4", children: visibleBlocks.length ? (_jsx("div", { className: "space-y-2", children: visibleBlocks.map((block, index) => {
243
+ if (block.kind === "heading") {
244
+ return (_jsx("p", { className: (block.level ?? 2) <= 2
245
+ ? "text-sm font-semibold"
246
+ : "text-xs font-medium", children: block.text }, `${block.kind}-${index}`));
247
+ }
248
+ if (block.kind === "bullet") {
249
+ return (_jsx("p", { className: "flex gap-2 text-xs leading-relaxed text-muted-foreground before:content-['\u2022']", children: block.text }, `${block.kind}-${index}`));
250
+ }
251
+ if (block.kind === "quote") {
252
+ return (_jsx("blockquote", { className: "border-s-2 border-border ps-3 text-xs italic leading-relaxed text-muted-foreground", children: block.text }, `${block.kind}-${index}`));
253
+ }
254
+ if (block.kind === "code") {
255
+ return (_jsx("pre", { className: "overflow-hidden rounded bg-muted p-2 font-mono text-[10px] leading-relaxed", children: block.text }, `${block.kind}-${index}`));
256
+ }
257
+ return (_jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: block.text }, `${block.kind}-${index}`));
258
+ }) })) : preview.excerpt ? (_jsx("p", { className: "mt-3 line-clamp-6 whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground", children: preview.excerpt })) : null }));
259
+ }
260
+ if (preview.type === "asset") {
261
+ return (_jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-muted text-muted-foreground", children: [preview.mediaType === "video" ? (_jsx(IconPlayerPlay, { className: "size-6" })) : (_jsx(IconPhoto, { className: "size-6" })), !compact && preview.width && preview.height ? (_jsxs("span", { className: "text-xs", children: [preview.width, " \u00D7 ", preview.height] })) : null] }));
262
+ }
263
+ return (_jsxs("div", { className: "grid h-full grid-cols-2 gap-2 bg-muted/50 p-3", children: [preview.panels.slice(0, compact ? 4 : 24).map((panel) => (_jsxs("div", { className: "rounded border border-border/70 bg-background p-2", children: [_jsxs("div", { className: "flex items-center gap-1 text-muted-foreground", children: [_jsx(IconChartBar, { className: "size-3" }), _jsx("span", { className: "truncate text-[10px] capitalize", children: panel.visualization })] }), _jsx("p", { className: "mt-2 line-clamp-2 text-xs font-medium", children: panel.title })] }, panel.id))), !preview.panels.length ? (_jsx("div", { className: "col-span-2 flex items-center justify-center text-xs text-muted-foreground", children: "Synthetic dashboard preview" })) : null] }));
264
+ }
265
+ function ContextPreviewVisual({ manifest, compact = false, }) {
266
+ if (manifest.media?.mimeType?.startsWith("video/")) {
267
+ return (_jsx("video", { controls: !compact, muted: compact, playsInline: true, preload: "metadata", src: manifest.media.url, poster: manifest.posterUrl, className: "h-full w-full bg-black object-contain" }));
268
+ }
269
+ if (manifest.media) {
270
+ return (_jsx("img", { src: manifest.media.url, alt: "", className: "h-full w-full object-contain" }));
271
+ }
272
+ return _jsx(StructuredPreview, { preview: manifest.preview, compact: compact });
273
+ }
274
+ function ContextPreviewSheet({ manifest, onOpenChange, }) {
275
+ const [selectedMediaUrl, setSelectedMediaUrl] = useState(null);
276
+ useEffect(() => setSelectedMediaUrl(null), [manifest?.itemVersionId]);
277
+ const selectedMedia = manifest?.gallery?.find((medium) => medium.url === selectedMediaUrl) ??
278
+ manifest?.media ??
279
+ null;
280
+ return (_jsx(Sheet, { open: Boolean(manifest), onOpenChange: onOpenChange, children: _jsxs(SheetContent, { side: "right", className: "w-full overflow-y-auto sm:max-w-xl", children: [_jsxs(SheetHeader, { children: [_jsx(SheetTitle, { children: manifest?.title ?? "Context preview" }), _jsx(SheetDescription, { children: manifest?.kind ?? "" })] }), manifest && (selectedMedia || manifest.preview) ? (_jsx("div", { className: "mt-5 min-h-56 overflow-hidden rounded-md border border-border", children: _jsx(ContextPreviewVisual, { manifest: { ...manifest, media: selectedMedia } }) })) : (_jsx("div", { className: "mt-5 flex min-h-44 items-center justify-center rounded-md border border-dashed border-border text-sm text-muted-foreground", children: "No safe preview is available for this item." })), manifest?.gallery && manifest.gallery.length > 1 ? (_jsx("div", { className: "mt-3 grid grid-cols-3 gap-2 sm:grid-cols-4", children: manifest.gallery.map((medium, index) => (_jsx("button", { type: "button", className: `aspect-video overflow-hidden rounded border bg-muted transition-colors ${medium.url === (selectedMedia?.url ?? manifest.media?.url)
281
+ ? "border-foreground"
282
+ : "border-border hover:border-foreground/50"}`, onClick: () => setSelectedMediaUrl(medium.url), children: _jsx("img", { src: medium.url, alt: `Preview ${index + 1}`, loading: "lazy", className: "h-full w-full object-contain" }) }, `${medium.url}-${index}`))) })) : null] }) }));
283
+ }
284
+ function ContextRail({ contexts, selectedContextId, disabled, canCreate, onSelect, onCreate, }) {
285
+ return (_jsxs("aside", { className: "border-b border-border/70 pb-5", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: "Contexts" }), _jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: "Choose the reusable context that should guide this work." })] }), _jsx(Badge, { variant: "outline", children: contexts.length })] }), _jsxs("div", { className: "mt-3 flex gap-2 overflow-x-auto pb-1", children: [contexts.map((context) => (_jsxs("button", { type: "button", disabled: disabled, "aria-pressed": selectedContextId === context.id, onClick: () => onSelect(context.id), className: `min-w-40 rounded-md border px-3 py-2 text-start transition-colors disabled:opacity-60 ${selectedContextId === context.id ? "border-foreground/25 bg-accent text-foreground" : "border-border text-muted-foreground hover:bg-accent/50 hover:text-foreground"}`, children: [_jsx("span", { className: "block truncate text-sm font-medium", children: context.name }), _jsx("span", { className: "mt-0.5 block truncate text-xs", children: context.description || `${context.memberCount} resources` })] }, context.id))), _jsxs(Button, { type: "button", variant: "outline", className: "min-w-40 justify-start", disabled: disabled || !canCreate, onClick: onCreate, children: [_jsx(IconPlus, {}), " New context"] }), !contexts.length ? (_jsx("p", { className: "py-2 text-sm text-muted-foreground", children: "Create a context from a resource\u2019s Share tab to start organizing the Library." })) : null] })] }));
286
+ }
287
+ export function CreativeContextPanel({ scope = "user", canManageOrg = false, scopeControl, connectionsHref = "/settings/integrations", }) {
288
+ const t = useT();
289
+ const { formatNumber } = useFormatters();
290
+ const { data: org } = useOrg();
291
+ const [libraryScope, setLibraryScope] = useState(scope);
292
+ const sourcesQuery = useCreativeContextSources({ limit: 100 });
293
+ const contextsQuery = useCreativeContexts();
294
+ const packsQuery = useCreativeContextPacks();
295
+ const brandProfileQuery = useCreativeContextBrandProfile();
296
+ const suggestionsQuery = useCreativeContextSuggestions();
297
+ const logoCandidatesQuery = useCanonicalLogoCandidates(brandProfileQuery.data?.profile?.id, suggestionsQuery.data?.capabilities.canonicalLogo === true);
298
+ const refreshSource = useRefreshCreativeContextSource();
299
+ const manageSource = useManageCreativeContextSource();
300
+ const uploadResource = useUploadResource();
301
+ const startImport = useStartCreativeContextImport();
302
+ const searchContext = useCreativeContextSearch();
303
+ const reviewItems = useReviewCreativeContextItems();
304
+ const publishBrandDna = usePublishCreativeContextBrandDna();
305
+ const proposeCanonicalLogo = useProposeCanonicalLogo();
306
+ const confirmCanonicalLogo = useConfirmCanonicalLogo();
307
+ const manageLayoutTemplate = useManageLayoutTemplate();
308
+ const contextState = useCreativeContextState();
309
+ const [query, setQuery] = useState("");
310
+ const [libraryView, setLibraryView] = useState("items");
311
+ const [previewManifest, setPreviewManifest] = useState(null);
312
+ const [savingState, setSavingState] = useState(false);
313
+ const [stateError, setStateError] = useState(null);
314
+ const [refreshMessage, setRefreshMessage] = useState(null);
315
+ const [searchError, setSearchError] = useState(null);
316
+ const [connectorKind, setConnectorKind] = useState(null);
317
+ const connectionProvider = connectionProviderForConnector(connectorKind);
318
+ const connectionsQuery = useCreativeContextConnections(connectionProvider);
319
+ const [selectedConnectionId, setSelectedConnectionId] = useState("");
320
+ const [sourceName, setSourceName] = useState("");
321
+ const [sourceReference, setSourceReference] = useState("");
322
+ const recommendationProvider = recommendationProviderForConnector(connectorKind);
323
+ const recommendationsQuery = useCreativeContextRootRecommendations(recommendationProvider, selectedConnectionId || null, connectorKind === "figma"
324
+ ? parseFigmaRecommendationBoundary(sourceReference)
325
+ : {});
326
+ const [selectedRecommendationIds, setSelectedRecommendationIds] = useState(() => new Set());
327
+ const seenRecommendationIdsRef = useRef(new Set());
328
+ const [pickerRecommendations, setPickerRecommendations] = useState([]);
329
+ const [openingGooglePicker, setOpeningGooglePicker] = useState(false);
330
+ const googlePickerSession = useCreativeContextGooglePickerSession(connectorKind === "google-slides" && selectedConnectionId
331
+ ? selectedConnectionId
332
+ : null);
333
+ const [uploadedFiles, setUploadedFiles] = useState([]);
334
+ const fileInputRef = useRef(null);
335
+ const folderInputRef = useRef(null);
336
+ const [setupError, setSetupError] = useState(null);
337
+ const [previewSourceId, setPreviewSourceId] = useState(null);
338
+ const [previewSourceName, setPreviewSourceName] = useState("");
339
+ const [selectedPreviewItemIds, setSelectedPreviewItemIds] = useState(() => new Set());
340
+ const initializedPreviewSelectionRef = useRef(null);
341
+ const [importJobId, setImportJobId] = useState(null);
342
+ const [importTargetScope, setImportTargetScope] = useState("user");
343
+ const [completedJobId, setCompletedJobId] = useState(null);
344
+ const [promotionPreview, setPromotionPreview] = useState(null);
345
+ const [promotionSourceId, setPromotionSourceId] = useState(null);
346
+ const [promotionMessage, setPromotionMessage] = useState(null);
347
+ const [lifecycleMessage, setLifecycleMessage] = useState(null);
348
+ const [deleteSource, setDeleteSource] = useState(null);
349
+ const [hiddenSourceIds, setHiddenSourceIds] = useState(() => new Set());
350
+ const [publishedMessage, setPublishedMessage] = useState(null);
351
+ const [reviewSource, setReviewSource] = useState(null);
352
+ const [reviewedItems, setReviewedItems] = useState([]);
353
+ const [reviewError, setReviewError] = useState(null);
354
+ const [membershipUpdateCandidate, setMembershipUpdateCandidate] = useState(null);
355
+ const [updatingMembershipId, setUpdatingMembershipId] = useState(null);
356
+ const [selectedPackId, setSelectedPackId] = useState(null);
357
+ const [suggestionError, setSuggestionError] = useState(null);
358
+ const previewQuery = usePreviewCreativeContextImport(previewSourceId);
359
+ const importStatusQuery = useCreativeContextImportStatus(importJobId);
360
+ const packQuery = useCreativeContextPack(selectedPackId);
361
+ useEffect(() => setLibraryScope(scope), [scope]);
362
+ useEffect(() => {
363
+ if (!connectionProvider) {
364
+ setSelectedConnectionId("");
365
+ return;
366
+ }
367
+ setSelectedConnectionId(connectionsQuery.data?.autoSelectedConnectionId ?? "");
368
+ }, [connectionProvider, connectionsQuery.data?.autoSelectedConnectionId]);
369
+ const availableRecommendations = useMemo(() => {
370
+ const byId = new Map();
371
+ for (const recommendation of [
372
+ ...(recommendationsQuery.data?.recommendations ?? []),
373
+ ...pickerRecommendations,
374
+ ]) {
375
+ byId.set(recommendation.externalId, recommendation);
376
+ }
377
+ return [...byId.values()];
378
+ }, [pickerRecommendations, recommendationsQuery.data?.recommendations]);
379
+ useEffect(() => {
380
+ const availableIds = new Set(availableRecommendations.map(({ externalId }) => externalId));
381
+ const previouslySeen = seenRecommendationIdsRef.current;
382
+ setSelectedRecommendationIds((current) => mergeRecommendationSelection(current, availableIds, previouslySeen));
383
+ seenRecommendationIdsRef.current = availableIds;
384
+ }, [availableRecommendations]);
385
+ const sources = useMemo(() => (sourcesQuery.data?.sources ?? []).filter((source) => source.status !== "archived" &&
386
+ !hiddenSourceIds.has(source.id) &&
387
+ isVisibleInScope(source.visibility, libraryScope)), [hiddenSourceIds, libraryScope, sourcesQuery.data?.sources]);
388
+ const packs = useMemo(() => (packsQuery.data?.packs ?? []).filter((pack) => !pack.archivedAt && isVisibleInScope(pack.visibility, libraryScope)), [libraryScope, packsQuery.data?.packs]);
389
+ const contexts = useMemo(() => parseCreativeContexts(contextsQuery.data), [contextsQuery.data]);
390
+ const selectedLibraryContextId = contextState.state.selectedContextId ?? contexts[0]?.id ?? null;
391
+ const contextMembershipsQuery = useContextMemberships(selectedLibraryContextId ? { contextId: selectedLibraryContextId } : null);
392
+ const manageContext = useManageCreativeContext();
393
+ const manageContextMembership = useManageContextMembership();
394
+ const contextMemberships = parseContextMemberships(contextMembershipsQuery.data);
395
+ const publishedContextMemberships = contextMemberships.filter((membership) => membership.publishedItem);
396
+ const pendingContextMemberships = contextMemberships.filter((membership) => membership.pendingSubmission);
397
+ const selectedLibraryContext = contexts.find((context) => context.id === selectedLibraryContextId);
398
+ const [contextSettingsName, setContextSettingsName] = useState("");
399
+ const [contextSettingsDescription, setContextSettingsDescription] = useState("");
400
+ const [contextSettingsPolicy, setContextSettingsPolicy] = useState("open");
401
+ const [newContextName, setNewContextName] = useState("");
402
+ const [newContextPolicy, setNewContextPolicy] = useState("open");
403
+ const [contextSettingsError, setContextSettingsError] = useState(null);
404
+ const activePack = packs.find((pack) => pack.id === contextState.state.currentPackId);
405
+ const selectedConnector = CONNECTORS.find((connector) => connector.kind === connectorKind);
406
+ const importJob = importStatusQuery.data?.job;
407
+ const importResult = importJob?.result;
408
+ const brandProposal = importResult?.inference?.brandDnaProposal;
409
+ const brandLayoutThumbnails = selectRenderableLayoutThumbnails(brandProposal?.layoutThumbnails ?? []);
410
+ const brandVoicePreview = brandProposal?.voiceDescriptors?.join(" · ") ?? brandProposal?.voiceLine;
411
+ const canManageScope = libraryScope === "user" || canManageOrg;
412
+ const canCreateContext = canManageScope && contexts.some((context) => context.access.canAdmin);
413
+ const activeAppId = contextsQuery.data?.appId;
414
+ const appDefaultContextId = contextsQuery.data?.appDefaultContextId ?? null;
415
+ const canSetAppDefault = Boolean(activeAppId && selectedLibraryContext?.access.canAdmin && canManageScope);
416
+ const proposalCapabilities = suggestionsQuery.data?.capabilities;
417
+ const logoCandidates = proposalCapabilities?.canonicalLogo
418
+ ? (logoCandidatesQuery.data?.candidates ?? [])
419
+ : [];
420
+ const proposedLayouts = (suggestionsQuery.data?.suggestions ?? []).filter((suggestion) => suggestion.kind === "layout-template" &&
421
+ (suggestion.status === "proposed" || suggestion.status === "promoted"));
422
+ useEffect(() => {
423
+ setContextSettingsName(selectedLibraryContext?.name ?? "");
424
+ setContextSettingsDescription(selectedLibraryContext?.description ?? "");
425
+ setContextSettingsPolicy(selectedLibraryContext?.approvalPolicy ?? "open");
426
+ setContextSettingsError(null);
427
+ }, [selectedLibraryContext]);
428
+ useEffect(() => {
429
+ if (!previewSourceId || !previewQuery.data)
430
+ return;
431
+ const defaults = previewQuery.data.smartDefaultExternalIds ?? [];
432
+ const initializationKey = `${previewSourceId}:${defaults.join("\u0000")}`;
433
+ if (initializedPreviewSelectionRef.current === initializationKey)
434
+ return;
435
+ const discoveredIds = new Set(previewQuery.data.items.map((item) => item.externalId));
436
+ setSelectedPreviewItemIds(new Set(defaults.filter((externalId) => discoveredIds.has(externalId))));
437
+ initializedPreviewSelectionRef.current = initializationKey;
438
+ }, [previewQuery.data, previewSourceId]);
439
+ useEffect(() => {
440
+ if (importJob?.status !== "completed" || completedJobId === importJob.id)
441
+ return;
442
+ setCompletedJobId(importJob.id);
443
+ void sourcesQuery.refetch();
444
+ void packsQuery.refetch();
445
+ void brandProfileQuery.refetch();
446
+ if (importTargetScope === "org" && previewSourceId) {
447
+ setPromotionSourceId(previewSourceId);
448
+ void manageSource
449
+ .mutateAsync({
450
+ operation: "preview-promotion",
451
+ sourceId: previewSourceId,
452
+ })
453
+ .then((result) => setPromotionPreview(result.promotionPreview ?? null))
454
+ .catch(() => setPromotionMessage(t("creativeContext.saveFailed")));
455
+ }
456
+ }, [
457
+ brandProfileQuery,
458
+ completedJobId,
459
+ importJob,
460
+ importTargetScope,
461
+ manageSource,
462
+ packsQuery,
463
+ previewSourceId,
464
+ sourcesQuery,
465
+ t,
466
+ ]);
467
+ async function changeMode(mode) {
468
+ if (mode === contextState.state.contextMode)
469
+ return;
470
+ setSavingState(true);
471
+ setStateError(null);
472
+ try {
473
+ await contextState.setState(mode === "off"
474
+ ? {
475
+ contextMode: "off",
476
+ selectedContextId: null,
477
+ currentPackId: null,
478
+ pinnedPackId: null,
479
+ }
480
+ : {
481
+ ...contextState.state,
482
+ contextMode: "auto",
483
+ selectedContextId: null,
484
+ pinnedPackId: null,
485
+ });
486
+ }
487
+ catch {
488
+ setStateError(t("creativeContext.stateSaveFailed"));
489
+ }
490
+ finally {
491
+ setSavingState(false);
492
+ }
493
+ }
494
+ async function changePinnedPack(packId) {
495
+ setSavingState(true);
496
+ setStateError(null);
497
+ try {
498
+ await contextState.setState({
499
+ ...contextState.state,
500
+ contextMode: "auto",
501
+ selectedContextId: null,
502
+ pinnedPackId: packId,
503
+ });
504
+ }
505
+ catch {
506
+ setStateError(t("creativeContext.stateSaveFailed"));
507
+ }
508
+ finally {
509
+ setSavingState(false);
510
+ }
511
+ }
512
+ async function selectContext(contextId) {
513
+ setSavingState(true);
514
+ setStateError(null);
515
+ try {
516
+ await contextState.setState({
517
+ ...contextState.state,
518
+ contextMode: "auto",
519
+ selectedContextId: contextId,
520
+ pinnedPackId: null,
521
+ });
522
+ }
523
+ catch {
524
+ setStateError(t("creativeContext.stateSaveFailed"));
525
+ }
526
+ finally {
527
+ setSavingState(false);
528
+ }
529
+ }
530
+ async function reviewContextMembership(membershipId, operation) {
531
+ if (!selectedLibraryContextId)
532
+ return;
533
+ try {
534
+ await manageContextMembership.mutateAsync({
535
+ operation,
536
+ contextId: selectedLibraryContextId,
537
+ membershipId,
538
+ });
539
+ await contextMembershipsQuery.refetch();
540
+ }
541
+ catch {
542
+ setReviewError(t("creativeContext.saveFailed"));
543
+ }
544
+ }
545
+ async function submitLatestContextMembershipUpdate() {
546
+ if (!selectedLibraryContextId || !membershipUpdateCandidate)
547
+ return;
548
+ setReviewError(null);
549
+ setUpdatingMembershipId(membershipUpdateCandidate.id);
550
+ try {
551
+ await manageContextMembership.mutateAsync({
552
+ operation: "submit-latest",
553
+ contextId: selectedLibraryContextId,
554
+ membershipId: membershipUpdateCandidate.id,
555
+ confirmBroaderPublication: true,
556
+ });
557
+ setMembershipUpdateCandidate(null);
558
+ await contextMembershipsQuery.refetch();
559
+ }
560
+ catch {
561
+ setReviewError(t("creativeContext.submitUpdateFailed"));
562
+ }
563
+ finally {
564
+ setUpdatingMembershipId(null);
565
+ }
566
+ }
567
+ function refresh(sourceId) {
568
+ setRefreshMessage(null);
569
+ refreshSource.mutate({ sourceId, mode: "incremental" }, {
570
+ onSuccess: () => setRefreshMessage(t("creativeContext.refreshed")),
571
+ onError: () => setRefreshMessage(t("creativeContext.refreshFailed")),
572
+ });
573
+ }
574
+ async function uploadFiles(files) {
575
+ if (!files.length)
576
+ return;
577
+ setSetupError(null);
578
+ try {
579
+ const uploaded = await Promise.all(files.map(async (file) => {
580
+ const relativePath = file
581
+ .webkitRelativePath || file.name;
582
+ const safePath = relativePath
583
+ .replace(/\.\./g, "")
584
+ .replace(/[^a-zA-Z0-9._/-]/g, "-");
585
+ const formData = new FormData();
586
+ formData.append("file", file, file.name);
587
+ formData.append("path", `/creative-context/${Date.now()}-${safePath}`);
588
+ const resource = (await uploadResource.mutateAsync(formData));
589
+ const url = resource.url ?? resource.content;
590
+ if (!url)
591
+ throw new Error("Upload returned no file handle");
592
+ return {
593
+ id: resource.id,
594
+ title: file.name,
595
+ fileName: file.name,
596
+ mimeType: file.type || "application/octet-stream",
597
+ url,
598
+ };
599
+ }));
600
+ setUploadedFiles((current) => [...current, ...uploaded]);
601
+ }
602
+ catch {
603
+ setSetupError(t("creativeContext.saveFailed"));
604
+ }
605
+ }
606
+ function chooseFiles(event) {
607
+ void uploadFiles(Array.from(event.target.files ?? []));
608
+ event.target.value = "";
609
+ }
610
+ function dropFiles(event) {
611
+ event.preventDefault();
612
+ void uploadFiles(Array.from(event.dataTransfer.files));
613
+ }
614
+ async function previewImport(event) {
615
+ event.preventDefault();
616
+ if (!selectedConnector || !sourceName.trim())
617
+ return;
618
+ setSetupError(null);
619
+ setImportJobId(null);
620
+ setCompletedJobId(null);
621
+ setPublishedMessage(null);
622
+ try {
623
+ const confirmedRecommendations = availableRecommendations.filter((recommendation) => selectedRecommendationIds.has(recommendation.externalId));
624
+ const result = await manageSource.mutateAsync({
625
+ operation: "create",
626
+ name: sourceName.trim(),
627
+ kind: selectedConnector.kind,
628
+ connectionId: selectedConnectionId || undefined,
629
+ externalRef: selectedConnector.kind === "upload"
630
+ ? `${uploadedFiles.length} files`
631
+ : sourceReference.trim() ||
632
+ (confirmedRecommendations.length
633
+ ? `${selectedConnector.kind}:${confirmedRecommendations
634
+ .map((recommendation) => recommendation.externalId)
635
+ .join(",")}`
636
+ : undefined),
637
+ config: buildCreativeContextSourceConfig(selectedConnector.kind, sourceReference, uploadedFiles, confirmedRecommendations),
638
+ });
639
+ if (!result.source)
640
+ throw new Error("Source creation returned no source");
641
+ setImportTargetScope(libraryScope);
642
+ setPreviewSourceName(result.source.name);
643
+ setPreviewSourceId(result.source.id);
644
+ setSelectedPreviewItemIds(new Set());
645
+ initializedPreviewSelectionRef.current = null;
646
+ setPromotionSourceId(null);
647
+ setPromotionPreview(null);
648
+ setPromotionMessage(null);
649
+ setConnectorKind(null);
650
+ setSourceName("");
651
+ setSourceReference("");
652
+ setPickerRecommendations([]);
653
+ seenRecommendationIdsRef.current.clear();
654
+ setUploadedFiles([]);
655
+ await sourcesQuery.refetch();
656
+ }
657
+ catch {
658
+ setSetupError(t("creativeContext.saveFailed"));
659
+ }
660
+ }
661
+ async function chooseGoogleSlides() {
662
+ setSetupError(null);
663
+ setOpeningGooglePicker(true);
664
+ try {
665
+ const session = await googlePickerSession.refetch();
666
+ if (!session.data) {
667
+ throw new Error("Google Picker session is unavailable.");
668
+ }
669
+ const selections = await chooseGoogleSlidesPresentations(session.data);
670
+ if (!selections.length)
671
+ return;
672
+ const selected = selections.map((selection) => ({
673
+ ...selection,
674
+ provider: "google-slides",
675
+ kind: "presentation",
676
+ }));
677
+ setPickerRecommendations((current) => {
678
+ const byId = new Map(current.map((recommendation) => [
679
+ recommendation.externalId,
680
+ recommendation,
681
+ ]));
682
+ for (const recommendation of selected) {
683
+ byId.set(recommendation.externalId, recommendation);
684
+ }
685
+ return [...byId.values()];
686
+ });
687
+ setSelectedRecommendationIds((current) => {
688
+ const next = new Set(current);
689
+ for (const recommendation of selected) {
690
+ next.add(recommendation.externalId);
691
+ }
692
+ return next;
693
+ });
694
+ void recommendationsQuery.refetch();
695
+ }
696
+ catch (error) {
697
+ setSetupError(error instanceof Error ? error.message : String(error));
698
+ }
699
+ finally {
700
+ setOpeningGooglePicker(false);
701
+ }
702
+ }
703
+ async function confirmPromotion() {
704
+ if (!promotionSourceId || !promotionPreview)
705
+ return;
706
+ setPromotionMessage(null);
707
+ try {
708
+ await manageSource.mutateAsync({
709
+ operation: "promote",
710
+ sourceId: promotionSourceId,
711
+ confirmation: {
712
+ containerRef: promotionPreview.containerRef,
713
+ boundaryHash: promotionPreview.boundaryHash,
714
+ itemCount: promotionPreview.itemCount,
715
+ },
716
+ });
717
+ setPromotionMessage(t("creativeContext.promotionComplete"));
718
+ setPromotionPreview(null);
719
+ setPromotionSourceId(null);
720
+ await sourcesQuery.refetch();
721
+ }
722
+ catch {
723
+ setPromotionMessage(t("creativeContext.saveFailed"));
724
+ }
725
+ }
726
+ async function pauseSource(source) {
727
+ setLifecycleMessage(null);
728
+ try {
729
+ await manageSource.mutateAsync({
730
+ operation: "update",
731
+ sourceId: source.id,
732
+ patch: { status: "paused" },
733
+ });
734
+ setLifecycleMessage(t("creativeContext.sourcePaused"));
735
+ await sourcesQuery.refetch();
736
+ }
737
+ catch {
738
+ setLifecycleMessage(t("creativeContext.saveFailed"));
739
+ }
740
+ }
741
+ async function restoreSource(source) {
742
+ setLifecycleMessage(null);
743
+ try {
744
+ await manageSource.mutateAsync({
745
+ operation: "restore",
746
+ sourceId: source.id,
747
+ });
748
+ setLifecycleMessage(t("creativeContext.sourceRestored"));
749
+ await sourcesQuery.refetch();
750
+ }
751
+ catch {
752
+ setLifecycleMessage(t("creativeContext.saveFailed"));
753
+ }
754
+ }
755
+ async function previewSourcePromotion(source) {
756
+ setPromotionMessage(null);
757
+ setPromotionPreview(null);
758
+ setPromotionSourceId(source.id);
759
+ try {
760
+ const result = await manageSource.mutateAsync({
761
+ operation: "preview-promotion",
762
+ sourceId: source.id,
763
+ });
764
+ setPromotionPreview(result.promotionPreview ?? null);
765
+ }
766
+ catch {
767
+ setPromotionSourceId(null);
768
+ setPromotionMessage(t("creativeContext.saveFailed"));
769
+ }
770
+ }
771
+ async function confirmDeleteSource() {
772
+ if (!deleteSource)
773
+ return;
774
+ const sourceId = deleteSource.id;
775
+ setLifecycleMessage(null);
776
+ setDeleteSource(null);
777
+ setHiddenSourceIds((current) => new Set(current).add(sourceId));
778
+ try {
779
+ await manageSource.mutateAsync({ operation: "delete", sourceId });
780
+ setLifecycleMessage(t("creativeContext.deletionQueued"));
781
+ void sourcesQuery.refetch();
782
+ }
783
+ catch {
784
+ setHiddenSourceIds((current) => {
785
+ const next = new Set(current);
786
+ next.delete(sourceId);
787
+ return next;
788
+ });
789
+ setLifecycleMessage(t("creativeContext.saveFailed"));
790
+ }
791
+ }
792
+ async function beginImport() {
793
+ if (!previewSourceId || !selectedPreviewItemIds.size)
794
+ return;
795
+ setSetupError(null);
796
+ try {
797
+ const result = await startImport.mutateAsync({
798
+ sourceId: previewSourceId,
799
+ mode: "incremental",
800
+ itemExternalIds: (previewQuery.data?.items ?? [])
801
+ .map((item) => item.externalId)
802
+ .filter((externalId) => selectedPreviewItemIds.has(externalId)),
803
+ });
804
+ setImportJobId(result.job.id);
805
+ }
806
+ catch {
807
+ setSetupError(t("creativeContext.importFailed"));
808
+ }
809
+ }
810
+ async function publishProposal() {
811
+ const importResult = importJob?.result;
812
+ const proposal = importResult?.inference?.brandDnaProposal;
813
+ if (!proposal)
814
+ return;
815
+ setPublishedMessage(null);
816
+ try {
817
+ const result = await publishBrandDna.mutateAsync({
818
+ profileId: proposal.profileId,
819
+ proposalVersionId: proposal.dnaVersionId,
820
+ confirmation: {
821
+ proposalVersionId: proposal.dnaVersionId,
822
+ contentHash: proposal.contentHash,
823
+ },
824
+ });
825
+ setPublishedMessage(`${t("creativeContext.brandContextPublished")} · ${result.profile.name} · v${result.dna.versionNumber}`);
826
+ await brandProfileQuery.refetch();
827
+ }
828
+ catch {
829
+ setPublishedMessage(t("creativeContext.saveFailed"));
830
+ }
831
+ }
832
+ async function openItemCuration(source, queue = "all") {
833
+ setReviewSource(source);
834
+ setReviewError(null);
835
+ try {
836
+ const result = await reviewItems.mutateAsync({
837
+ sourceId: source.id,
838
+ operation: "list",
839
+ queue,
840
+ limit: 100,
841
+ });
842
+ setReviewedItems(result.items);
843
+ }
844
+ catch {
845
+ setReviewedItems([]);
846
+ setReviewError(t("creativeContext.unavailable"));
847
+ }
848
+ }
849
+ async function reviewContextItem(operation, itemId) {
850
+ if (!reviewSource)
851
+ return;
852
+ setReviewError(null);
853
+ try {
854
+ await reviewItems.mutateAsync({
855
+ sourceId: reviewSource.id,
856
+ operation,
857
+ itemIds: [itemId],
858
+ });
859
+ const result = await reviewItems.mutateAsync({
860
+ sourceId: reviewSource.id,
861
+ operation: "list",
862
+ queue: "all",
863
+ limit: 100,
864
+ });
865
+ setReviewedItems(result.items);
866
+ await sourcesQuery.refetch();
867
+ }
868
+ catch {
869
+ setReviewError(t("creativeContext.saveFailed"));
870
+ }
871
+ }
872
+ async function chooseCanonicalLogo(candidate) {
873
+ setSuggestionError(null);
874
+ try {
875
+ const suggestion = await proposeCanonicalLogo.mutateAsync({
876
+ profileId: brandProfileQuery.data?.profile?.id,
877
+ itemId: candidate.itemId,
878
+ itemVersionId: candidate.itemVersionId,
879
+ reason: "Selected from the ranked Library review card",
880
+ payload: { mediaId: candidate.mediaId },
881
+ });
882
+ await confirmCanonicalLogo.mutateAsync({
883
+ suggestionId: suggestion.id,
884
+ decision: "confirm",
885
+ });
886
+ await suggestionsQuery.refetch();
887
+ }
888
+ catch {
889
+ setSuggestionError(t("creativeContext.saveFailed"));
890
+ }
891
+ }
892
+ async function decideLayoutSuggestion(suggestionId, operation) {
893
+ setSuggestionError(null);
894
+ try {
895
+ await manageLayoutTemplate.mutateAsync({ suggestionId, operation });
896
+ await suggestionsQuery.refetch();
897
+ }
898
+ catch {
899
+ setSuggestionError(t("creativeContext.saveFailed"));
900
+ }
901
+ }
902
+ async function saveContextSettings() {
903
+ if (!selectedLibraryContext?.access.canAdmin || !contextSettingsName.trim())
904
+ return;
905
+ setContextSettingsError(null);
906
+ try {
907
+ await manageContext.mutateAsync({
908
+ operation: "update",
909
+ contextId: selectedLibraryContext.id,
910
+ patch: {
911
+ name: contextSettingsName.trim(),
912
+ description: contextSettingsDescription.trim() || null,
913
+ approvalPolicy: contextSettingsPolicy,
914
+ },
915
+ });
916
+ await contextsQuery.refetch();
917
+ }
918
+ catch {
919
+ setContextSettingsError("Could not update this context.");
920
+ }
921
+ }
922
+ async function createSpecialtyContext() {
923
+ if (!canCreateContext || !newContextName.trim())
924
+ return;
925
+ setContextSettingsError(null);
926
+ try {
927
+ const result = await manageContext.mutateAsync({
928
+ operation: "create",
929
+ name: newContextName.trim(),
930
+ kind: "specialty",
931
+ approvalPolicy: newContextPolicy,
932
+ });
933
+ setNewContextName("");
934
+ setNewContextPolicy("open");
935
+ await contextsQuery.refetch();
936
+ if (result.context?.id)
937
+ await selectContext(result.context.id);
938
+ }
939
+ catch {
940
+ setContextSettingsError("Could not create this context.");
941
+ }
942
+ }
943
+ async function setAppDefaultContext() {
944
+ if (!activeAppId || !selectedLibraryContext || !canSetAppDefault)
945
+ return;
946
+ setContextSettingsError(null);
947
+ try {
948
+ await manageContext.mutateAsync({
949
+ operation: "set-app-default",
950
+ contextId: selectedLibraryContext.id,
951
+ appId: activeAppId,
952
+ });
953
+ await contextsQuery.refetch();
954
+ }
955
+ catch {
956
+ setContextSettingsError("Could not update the automatic context for this app.");
957
+ }
958
+ }
959
+ async function search(event) {
960
+ event.preventDefault();
961
+ const searchText = query.trim();
962
+ if (!searchText ||
963
+ (!sources.length &&
964
+ !selectedLibraryContextId &&
965
+ !contextState.state.pinnedPackId))
966
+ return;
967
+ setSearchError(null);
968
+ try {
969
+ const result = await searchContext.mutateAsync({
970
+ query: searchText,
971
+ sourceIds: selectedLibraryContextId || contextState.state.pinnedPackId
972
+ ? undefined
973
+ : sources.map((source) => source.id),
974
+ packId: contextState.state.pinnedPackId ?? undefined,
975
+ contextId: contextState.state.pinnedPackId
976
+ ? undefined
977
+ : (selectedLibraryContextId ?? undefined),
978
+ limit: 20,
979
+ snapshot: true,
980
+ });
981
+ if (result.contextPackId && contextState.state.contextMode === "auto") {
982
+ await contextState.setState({
983
+ ...contextState.state,
984
+ currentPackId: result.contextPackId,
985
+ });
986
+ }
987
+ }
988
+ catch {
989
+ setSearchError(t("creativeContext.unavailable"));
990
+ }
991
+ }
992
+ const loading = sourcesQuery.isLoading ||
993
+ packsQuery.isLoading ||
994
+ contextsQuery.isLoading ||
995
+ contextState.isLoading;
996
+ const unavailable = sourcesQuery.error || packsQuery.error || contextsQuery.error;
997
+ return (_jsxs("div", { className: "mx-auto flex w-full max-w-5xl flex-col gap-7 p-6 lg:p-10", children: [_jsxs("header", { className: "flex flex-wrap items-start justify-between gap-4 border-b border-border/70 pb-5", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: t("creativeContext.title") }), _jsx("p", { className: "mt-1 max-w-2xl text-sm text-muted-foreground", children: t("creativeContext.description") })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [scopeControl ??
998
+ (org?.orgId ? (_jsx(ScopeControl, { scope: libraryScope, onChange: setLibraryScope })) : null), _jsx(CreativeContextChip, { state: contextState.state, packs: packs, contexts: contexts })] })] }), loading ? (_jsxs("div", { className: "space-y-3", "aria-label": t("creativeContext.loading"), children: [_jsx(Skeleton, { className: "h-24 w-full" }), _jsx(Skeleton, { className: "h-40 w-full" }), _jsx(Skeleton, { className: "h-32 w-full" })] })) : unavailable ? (_jsxs("div", { className: "flex items-center gap-3 rounded-md border border-dashed border-border p-6 text-sm text-muted-foreground", children: [_jsx(IconAlertTriangle, { className: "size-5" }), t("creativeContext.unavailable")] })) : (_jsxs(_Fragment, { children: [_jsx(ContextRail, { contexts: contexts, selectedContextId: contextState.state.selectedContextId, disabled: savingState, canCreate: canCreateContext, onSelect: (contextId) => void selectContext(contextId), onCreate: () => setLibraryView("settings") }), _jsxs(Tabs, { value: libraryView, onValueChange: (value) => setLibraryView(value), children: [_jsxs(TabsList, { className: "w-full justify-start overflow-x-auto", children: [_jsx(TabsTrigger, { value: "items", children: "Items" }), _jsx(TabsTrigger, { value: "sources", children: "Sources" }), _jsx(TabsTrigger, { value: "approvals", children: "Approvals" }), _jsx(TabsTrigger, { value: "settings", children: "Settings" })] }), _jsxs(TabsContent, { value: "items", children: [_jsx("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: publishedContextMemberships.map((membership) => {
999
+ const item = membership.publishedItem;
1000
+ const imageMedium = item.media.find((medium) => medium.mimeType?.startsWith("image/"));
1001
+ const playbackMedium = item.media.find((medium) => medium.mimeType?.startsWith("video/"));
1002
+ const medium = imageMedium ?? playbackMedium ?? item.media[0];
1003
+ const sheetMedium = playbackMedium ?? medium;
1004
+ const updateAvailable = membership.nativeUpdateStatus?.state === "update-available";
1005
+ return (_jsxs("article", { className: "overflow-hidden rounded-md border border-border", children: [_jsxs("button", { type: "button", onClick: () => setPreviewManifest({
1006
+ title: item.title,
1007
+ kind: item.kind,
1008
+ itemId: item.id,
1009
+ itemVersionId: item.itemVersionId,
1010
+ preview: item.preview,
1011
+ media: sheetMedium ?? null,
1012
+ gallery: item.media.filter((candidate) => candidate.mimeType?.startsWith("image/")),
1013
+ posterUrl: playbackMedium && imageMedium
1014
+ ? imageMedium.url
1015
+ : undefined,
1016
+ }), className: "block w-full text-start transition-colors hover:bg-accent/40", children: [_jsx("span", { className: "block aspect-video overflow-hidden", children: _jsx(ContextPreviewVisual, { compact: true, manifest: {
1017
+ title: item.title,
1018
+ kind: item.kind,
1019
+ itemId: item.id,
1020
+ itemVersionId: item.itemVersionId,
1021
+ preview: item.preview,
1022
+ media: medium ?? null,
1023
+ gallery: item.media,
1024
+ } }) }), _jsxs("span", { className: "block p-3", children: [_jsx("span", { className: "block truncate text-sm font-medium", children: item.title }), _jsxs("span", { className: "mt-1 flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground", children: [_jsx("span", { children: item.kind }), _jsx("span", { children: "\u00B7" }), _jsx("span", { className: "capitalize", children: membership.rank }), _jsx(Badge, { variant: "secondary", children: "Published" }), updateAvailable ? (_jsx(Badge, { variant: "outline", children: t("creativeContext.updateAvailable") })) : null] }), _jsxs("span", { className: "mt-1 block truncate font-mono text-[10px] text-muted-foreground", children: ["Version ", item.itemVersionId.slice(0, 12)] })] })] }), updateAvailable &&
1025
+ selectedLibraryContext?.access.canSubmit ? (_jsx("div", { className: "border-t border-border/70 p-2", children: _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "w-full", disabled: updatingMembershipId === membership.id, onClick: () => setMembershipUpdateCandidate({
1026
+ id: membership.id,
1027
+ title: item.title,
1028
+ }), children: [_jsx(IconRefresh, {}), updatingMembershipId === membership.id
1029
+ ? t("creativeContext.submittingUpdate")
1030
+ : t("creativeContext.submitUpdate")] }) })) : null] }, membership.id));
1031
+ }) }), !publishedContextMemberships.length ? (_jsx("p", { className: "py-4 text-sm text-muted-foreground", children: "Approved context items appear here after publication." })) : null, reviewError ? (_jsx("p", { className: "mt-3 text-sm text-destructive", children: reviewError })) : null] }), _jsxs(TabsContent, { value: "approvals", children: [_jsx("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: pendingContextMemberships.map((membership) => {
1032
+ const submission = membership.pendingSubmission;
1033
+ const item = submission.proposedItem;
1034
+ const medium = item?.media[0];
1035
+ return (_jsxs("article", { className: "overflow-hidden rounded-md border border-border", children: [item ? (_jsx("button", { type: "button", className: "block aspect-video w-full overflow-hidden text-start", onClick: () => setPreviewManifest({
1036
+ title: item.title,
1037
+ kind: item.kind,
1038
+ itemId: item.id,
1039
+ itemVersionId: item.itemVersionId,
1040
+ preview: item.preview,
1041
+ media: medium ?? null,
1042
+ gallery: item.media.filter((candidate) => candidate.mimeType?.startsWith("image/")),
1043
+ }), children: _jsx(ContextPreviewVisual, { compact: true, manifest: {
1044
+ title: item.title,
1045
+ kind: item.kind,
1046
+ itemId: item.id,
1047
+ itemVersionId: item.itemVersionId,
1048
+ preview: item.preview,
1049
+ media: medium ?? null,
1050
+ } }) })) : null, _jsxs("div", { className: "p-3", children: [_jsx("p", { className: "truncate text-sm font-medium", children: item?.title ?? "Pending context submission" }), _jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground", children: ["Submitted by ", submission.submittedBy] }), submission.note ? (_jsx("p", { className: "mt-2 line-clamp-3 text-xs text-muted-foreground", children: submission.note })) : null, selectedLibraryContext?.access.canReview ? (_jsxs("div", { className: "mt-3 flex gap-2", children: [_jsx(Button, { size: "sm", onClick: () => void reviewContextMembership(membership.id, "approve"), children: "Approve" }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => void reviewContextMembership(membership.id, "request-changes"), children: "Request changes" })] })) : (_jsx(Badge, { variant: "outline", className: "mt-3", children: "Awaiting review" }))] })] }, membership.id));
1051
+ }) }), !pendingContextMemberships.length ? (_jsx("p", { className: "py-4 text-sm text-muted-foreground", children: "No context submissions need review." })) : null] }), _jsx(TabsContent, { value: "sources", children: _jsx("p", { className: "text-sm text-muted-foreground", children: "Sources and their review queues are managed below." }) }), _jsxs(TabsContent, { value: "settings", children: [_jsxs("div", { className: "grid gap-5 lg:grid-cols-2", children: [_jsxs("section", { className: "space-y-3 rounded-md border border-border p-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold", children: "Context settings" }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Automatic selection uses Default plus at most one matching specialty. Exact packs remain available under advanced provenance." })] }), _jsx(Input, { value: contextSettingsName, disabled: !selectedLibraryContext?.access.canAdmin, onChange: (event) => setContextSettingsName(event.target.value), placeholder: "Context name" }), _jsx(Textarea, { value: contextSettingsDescription, disabled: !selectedLibraryContext?.access.canAdmin, onChange: (event) => setContextSettingsDescription(event.target.value), placeholder: "When should agents use this context?", rows: 3 }), _jsxs(Select, { value: contextSettingsPolicy, disabled: !selectedLibraryContext?.access.canAdmin, onValueChange: (value) => setContextSettingsPolicy(value), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "open", children: "Open publishing" }), _jsx(SelectItem, { value: "review", children: "Require review" }), _jsx(SelectItem, { value: "admins-only", children: "Admins only" })] })] }), _jsx(Button, { type: "button", size: "sm", disabled: !selectedLibraryContext?.access.canAdmin ||
1052
+ !contextSettingsName.trim() ||
1053
+ manageContext.isPending, onClick: () => void saveContextSettings(), children: "Save settings" }), activeAppId ? (_jsxs("div", { className: "border-t border-border/70 pt-3", children: [_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Automatic generations use Default plus this context for", ` ${activeAppId}`, " when no context is chosen explicitly."] }), _jsx(Button, { type: "button", size: "sm", variant: "outline", className: "mt-3", disabled: !canSetAppDefault ||
1054
+ appDefaultContextId === selectedLibraryContext?.id ||
1055
+ manageContext.isPending, onClick: () => void setAppDefaultContext(), children: appDefaultContextId === selectedLibraryContext?.id
1056
+ ? `Automatic for ${activeAppId}`
1057
+ : `Use automatically for ${activeAppId}` })] })) : null] }), _jsxs("section", { className: "space-y-3 rounded-md border border-dashed border-border p-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold", children: "New specialty" }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Create a focused style such as Marketing, Product, or Sales. Contexts start open unless you choose review." })] }), _jsx(Input, { value: newContextName, disabled: !canCreateContext, onChange: (event) => setNewContextName(event.target.value), placeholder: "Marketing" }), _jsxs(Select, { value: newContextPolicy, disabled: !canCreateContext, onValueChange: (value) => setNewContextPolicy(value), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "open", children: "Open publishing" }), _jsx(SelectItem, { value: "review", children: "Require review" }), _jsx(SelectItem, { value: "admins-only", children: "Admins only" })] })] }), _jsxs(Button, { type: "button", size: "sm", variant: "outline", disabled: !canCreateContext ||
1058
+ !newContextName.trim() ||
1059
+ manageContext.isPending, onClick: () => void createSpecialtyContext(), children: [_jsx(IconPlus, {}), " Create context"] })] })] }), contextSettingsError ? (_jsx("p", { className: "mt-3 text-xs text-destructive", children: contextSettingsError })) : null] })] }), libraryView === "settings" ? (_jsxs("section", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: t("creativeContext.modeLabel") }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: activePack
1060
+ ? `${t("creativeContext.activePack")}: ${activePack.name}`
1061
+ : t("creativeContext.noActivePack") })] }), _jsxs("div", { className: "flex flex-col gap-2 sm:flex-row", role: "radiogroup", children: [_jsx(ContextModeButton, { mode: "auto", activeMode: contextState.state.contextMode, label: t("creativeContext.automatic"), description: t("creativeContext.automaticDescription"), disabled: savingState, onSelect: (mode) => void changeMode(mode) }), _jsx(ContextModeButton, { mode: "off", activeMode: contextState.state.contextMode, label: t("creativeContext.off"), description: t("creativeContext.offDescription"), disabled: savingState, onSelect: (mode) => void changeMode(mode) })] }), stateError ? (_jsx("p", { className: "text-xs text-destructive", children: stateError })) : null] })) : null, libraryView === "settings" &&
1062
+ brandProfileQuery.data?.profile &&
1063
+ brandProfileQuery.data.dna ? (_jsx("section", { className: "border-t border-border/70 pt-6", children: _jsxs("div", { className: "rounded-md border border-border p-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: t("creativeContext.publishedBrandContext") }), _jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: brandProfileQuery.data.profile.name })] }), _jsxs(Badge, { variant: "secondary", children: ["v", brandProfileQuery.data.dna.versionNumber] })] }), _jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: brandProfileQuery.data.dna.payload.summary })] }) })) : null, libraryView === "approvals" &&
1064
+ (logoCandidates.length || proposedLayouts.length) ? (_jsxs("section", { className: "border-t border-border/70 pt-6", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(IconSparkles, { className: "size-5 text-muted-foreground" }), _jsx("h2", { className: "text-lg font-semibold", children: t("creativeContext.suggestions") })] }), logoCandidates.length ? (_jsxs("div", { className: "mt-4", children: [_jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold", children: [_jsx(IconPhoto, { className: "size-4 text-muted-foreground" }), t("creativeContext.logo")] }), _jsx("div", { className: "mt-2 grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: logoCandidates.map((candidate) => (_jsxs("article", { className: "overflow-hidden rounded-md border border-border", children: [_jsx("div", { className: "flex h-28 items-center justify-center bg-muted/40 p-3", children: _jsx("img", { src: candidate.thumbnailUrl, alt: candidate.title, className: "max-h-full max-w-full object-contain" }) }), _jsxs("div", { className: "flex items-center justify-between gap-2 p-3", children: [_jsx("p", { className: "min-w-0 truncate text-sm font-medium", children: candidate.title }), _jsxs(Button, { type: "button", size: "sm", variant: "outline", disabled: proposeCanonicalLogo.isPending ||
1065
+ confirmCanonicalLogo.isPending, onClick: () => void chooseCanonicalLogo(candidate), children: [_jsx(IconCheck, {}), t("creativeContext.approve")] })] })] }, candidate.mediaId))) })] })) : null, proposedLayouts.length &&
1066
+ proposalCapabilities?.layoutTemplate ? (_jsxs("div", { className: "mt-5", children: [_jsxs("h3", { className: "flex items-center gap-2 text-sm font-semibold", children: [_jsx(IconLayout, { className: "size-4 text-muted-foreground" }), t("creativeContext.layouts")] }), _jsx("div", { className: "mt-2 divide-y divide-border/70 rounded-md border border-border", children: proposedLayouts.map((suggestion) => (_jsxs("article", { className: "flex flex-wrap items-center justify-between gap-3 p-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-sm font-medium", children: suggestion.reason ?? suggestion.itemId }), _jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: suggestion.status })] }), _jsx("div", { className: "flex items-center gap-2", children: suggestion.status === "proposed" ? (_jsxs(_Fragment, { children: [_jsxs(Button, { type: "button", size: "sm", disabled: manageLayoutTemplate.isPending, onClick: () => void decideLayoutSuggestion(suggestion.id, "promote"), children: [_jsx(IconCheck, {}), t("creativeContext.approve")] }), _jsx(Button, { type: "button", size: "sm", variant: "outline", disabled: manageLayoutTemplate.isPending, onClick: () => void decideLayoutSuggestion(suggestion.id, "reject"), children: t("creativeContext.exclude") })] })) : (_jsx(Button, { type: "button", size: "sm", variant: "outline", disabled: manageLayoutTemplate.isPending, onClick: () => void decideLayoutSuggestion(suggestion.id, "demote"), children: t("creativeContext.deprecate") })) })] }, suggestion.id))) })] })) : null, suggestionError ? (_jsx("p", { className: "mt-3 text-sm text-destructive", children: suggestionError })) : null] })) : null, libraryView === "sources" ? (_jsxs(_Fragment, { children: [_jsxs("section", { className: "border-t border-border/70 pt-6", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold", children: t("creativeContext.addSource") }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: t("creativeContext.sourcesDescription") })] }), _jsx("div", { className: "mt-4 grid gap-2 sm:grid-cols-2 lg:grid-cols-5", children: CONNECTORS.map((connector) => {
1067
+ const Icon = connector.icon;
1068
+ return (_jsxs("button", { type: "button", disabled: !canManageScope, onClick: () => {
1069
+ setConnectorKind(connector.kind);
1070
+ setSourceName(connector.label);
1071
+ setSourceReference("");
1072
+ setUploadedFiles([]);
1073
+ setPickerRecommendations([]);
1074
+ seenRecommendationIdsRef.current.clear();
1075
+ setSelectedConnectionId("");
1076
+ setSelectedRecommendationIds(new Set());
1077
+ setSetupError(null);
1078
+ }, className: "flex min-h-24 flex-col items-start justify-between rounded-md border border-border p-3 text-start transition-colors hover:bg-accent/50 disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(Icon, { className: "size-5 text-muted-foreground" }), _jsx("span", { className: "text-sm font-medium", children: connector.label })] }, connector.kind));
1079
+ }) }), selectedConnector ? (_jsxs("form", { className: "mt-4 rounded-md border border-border p-4", onSubmit: (event) => void previewImport(event), children: [connectionProvider ? (_jsx("div", { className: "mb-3", children: connectionsQuery.isLoading ? (_jsx(Skeleton, { className: "h-9 w-full" })) : connectionsQuery.data?.needsSetup ? (_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [_jsx("span", { children: t("creativeContext.setupConnection") }), _jsx(Button, { asChild: true, type: "button", variant: "outline", size: "sm", children: _jsxs("a", { href: connectionsQuery.data.connectPath ||
1080
+ connectionsQuery.data.connectionsPath ||
1081
+ connectionsHref, children: [t("creativeContext.connectProvider"), _jsx(IconArrowUpRight, {})] }) })] })) : connectionsQuery.data?.needsPicker ? (_jsxs("label", { className: "block space-y-1.5 text-xs font-medium", children: [_jsx("span", { children: t("creativeContext.chooseConnection") }), _jsxs(Select, { value: selectedConnectionId, onValueChange: setSelectedConnectionId, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: t("creativeContext.chooseConnection") }) }), _jsx(SelectContent, { children: connectionsQuery.data.connections.map((connection) => (_jsx(SelectItem, { value: connection.connectionId, children: connection.label }, connection.connectionId))) })] })] })) : null })) : null, recommendationProvider && selectedConnectionId ? (_jsxs("div", { className: "mb-3 rounded-md border border-border p-3", children: [connectorKind === "google-slides" ? (_jsxs("div", { className: "mb-3 flex flex-wrap items-center justify-between gap-3 border-b border-border/60 pb-3", children: [_jsx("p", { className: "max-w-lg text-xs text-muted-foreground", children: t("creativeContext.googlePickerDescription") }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: openingGooglePicker, onClick: () => void chooseGoogleSlides(), children: [_jsx(IconSlideshow, {}), openingGooglePicker
1082
+ ? t("creativeContext.loading")
1083
+ : t("creativeContext.choosePresentations")] })] })) : null, recommendationsQuery.isLoading &&
1084
+ !availableRecommendations.length ? (_jsx(Skeleton, { className: "h-16 w-full" })) : availableRecommendations.length ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs text-muted-foreground", children: [_jsx("span", { children: t("creativeContext.discoveredItems", {
1085
+ count: formatNumber(availableRecommendations.length),
1086
+ }) }), _jsx("span", { children: t("creativeContext.selectedItems", {
1087
+ count: formatNumber(selectedRecommendationIds.size),
1088
+ }) })] }), _jsx("div", { className: "max-h-52 divide-y divide-border/60 overflow-y-auto", children: availableRecommendations.map((recommendation) => (_jsxs("label", { className: "flex cursor-pointer items-start gap-3 py-2", children: [_jsx(Checkbox, { className: "mt-0.5", checked: selectedRecommendationIds.has(recommendation.externalId), onCheckedChange: (checked) => setSelectedRecommendationIds((current) => {
1089
+ const next = new Set(current);
1090
+ if (checked) {
1091
+ next.add(recommendation.externalId);
1092
+ }
1093
+ else {
1094
+ next.delete(recommendation.externalId);
1095
+ }
1096
+ return next;
1097
+ }) }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate text-sm", children: recommendation.title }), _jsx("span", { className: "block text-xs text-muted-foreground", children: recommendation.containerRef ??
1098
+ recommendation.kind })] })] }, recommendation.externalId))) })] })) : (_jsx("p", { className: "text-xs text-muted-foreground", children: recommendationsQuery.data?.unavailableReason ??
1099
+ t("creativeContext.unavailable") }))] })) : null, _jsxs("div", { className: "grid gap-3 sm:grid-cols-2", children: [_jsxs("label", { className: "space-y-1.5 text-xs font-medium", children: [_jsx("span", { children: t("creativeContext.sourceName") }), _jsx(Input, { value: sourceName, onChange: (event) => setSourceName(event.target.value), required: true })] }), selectedConnector.kind === "upload" ? (_jsxs("div", { className: "space-y-1.5 text-xs font-medium", children: [_jsx("span", { children: t("creativeContext.sourceReference") }), _jsx("input", { ref: fileInputRef, type: "file", multiple: true, accept: ".pptx,.docx,.pdf,.png,.jpg,.jpeg,.webp,.gif,.svg,application/pdf,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.openxmlformats-officedocument.wordprocessingml.document,image/png,image/jpeg,image/webp,image/gif,image/svg+xml", className: "hidden", onChange: chooseFiles }), _jsx("input", { ref: folderInputRef, type: "file", multiple: true, className: "hidden", onChange: chooseFiles, ...{ webkitdirectory: "", directory: "" } }), _jsxs("div", { onDragOver: (event) => event.preventDefault(), onDrop: dropFiles, className: "rounded-md border border-dashed border-border p-4", children: [_jsx("p", { className: "text-xs text-muted-foreground", children: t("creativeContext.dropFiles") }), _jsxs("div", { className: "mt-3 flex flex-wrap gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => fileInputRef.current?.click(), children: t("creativeContext.chooseFiles") }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => folderInputRef.current?.click(), children: t("creativeContext.chooseFolder") })] }), uploadedFiles.length ? (_jsx("ul", { className: "mt-3 space-y-1 text-xs text-muted-foreground", children: uploadedFiles.map((file) => (_jsx("li", { className: "truncate", children: file.fileName }, file.id))) })) : null] })] })) : (_jsxs("label", { className: "space-y-1.5 text-xs font-medium", children: [_jsx("span", { children: t("creativeContext.sourceReference") }), selectedConnector.kind === "website" ||
1100
+ selectedConnector.kind === "figma" ||
1101
+ selectedConnector.kind === "notion" ? (_jsx(Textarea, { value: sourceReference, onChange: (event) => setSourceReference(event.target.value), placeholder: selectedConnector.referencePlaceholder, required: selectedConnector.referenceRequired, rows: 3 })) : (_jsx(Input, { value: sourceReference, onChange: (event) => setSourceReference(event.target.value), placeholder: selectedConnector.referencePlaceholder, required: selectedConnector.referenceRequired }))] }))] }), _jsxs("div", { className: "mt-3 flex justify-end gap-2", children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => setConnectorKind(null), children: t("creativeContext.cancel") }), _jsxs(Button, { type: "submit", disabled: manageSource.isPending ||
1102
+ uploadResource.isPending ||
1103
+ (selectedConnector.kind === "upload" &&
1104
+ !uploadedFiles.length) ||
1105
+ (Boolean(connectionProvider) &&
1106
+ !selectedConnectionId) ||
1107
+ (selectedConnector.referenceRequired &&
1108
+ !sourceReference.trim()) ||
1109
+ (Boolean(recommendationProvider) &&
1110
+ !sourceReference.trim() &&
1111
+ !selectedRecommendationIds.size), children: [_jsx(IconFileImport, {}), t("creativeContext.preview")] })] })] })) : null, previewSourceId ? (_jsxs("div", { className: "mt-4 rounded-md border border-border p-4", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold", children: previewSourceName }), previewQuery.isLoading ? (_jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: t("creativeContext.loading") })) : (_jsxs("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [_jsx("span", { children: t("creativeContext.discoveredItems", {
1112
+ count: formatNumber(previewQuery.data?.total ??
1113
+ previewQuery.data?.items.length ??
1114
+ 0),
1115
+ }) }), _jsx("span", { children: t("creativeContext.selectedItems", {
1116
+ count: formatNumber(selectedPreviewItemIds.size),
1117
+ }) })] }))] }), _jsxs(Button, { type: "button", disabled: previewQuery.isLoading ||
1118
+ !previewQuery.data?.items.length ||
1119
+ !selectedPreviewItemIds.size ||
1120
+ startImport.isPending ||
1121
+ importJob?.status === "queued" ||
1122
+ importJob?.status === "running", onClick: () => void beginImport(), children: [_jsx(IconFileImport, {}), startImport.isPending
1123
+ ? t("creativeContext.importing")
1124
+ : t("creativeContext.startImport")] })] }), previewQuery.data?.items.length ? (_jsxs("div", { className: "mt-3", children: [_jsxs("div", { className: "flex items-center gap-2 border-y border-border/60 py-2", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setSelectedPreviewItemIds(new Set(previewQuery.data?.items.map((item) => item.externalId) ?? [])), children: t("creativeContext.selectAll") }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setSelectedPreviewItemIds(new Set()), children: t("creativeContext.clearSelection") })] }), _jsx("div", { className: "max-h-80 divide-y divide-border/60 overflow-y-auto", children: previewQuery.data.items.map((item) => (_jsxs("label", { className: "flex cursor-pointer items-start gap-3 py-2", children: [_jsx(Checkbox, { className: "mt-0.5", checked: selectedPreviewItemIds.has(item.externalId), onCheckedChange: (checked) => setSelectedPreviewItemIds((current) => {
1125
+ const next = new Set(current);
1126
+ if (checked)
1127
+ next.add(item.externalId);
1128
+ else
1129
+ next.delete(item.externalId);
1130
+ return next;
1131
+ }) }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate text-sm", children: item.title }), _jsx("span", { className: "block text-xs text-muted-foreground", children: item.kind })] })] }, item.externalId))) })] })) : null] })) : null, importJob ? (_jsxs("div", { className: "mt-4 rounded-md border border-border p-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [importJob.status === "completed" ? (_jsx(IconCheck, { className: "size-5 text-emerald-600" })) : importJob.status === "failed" ? (_jsx(IconAlertTriangle, { className: "size-5 text-destructive" })) : (_jsx(IconRefresh, { className: "size-5 animate-spin text-muted-foreground" })), _jsx("h3", { className: "text-sm font-semibold", children: importJob.status === "completed"
1132
+ ? t("creativeContext.importComplete")
1133
+ : importJob.status === "failed"
1134
+ ? t("creativeContext.importFailed")
1135
+ : t("creativeContext.importing") })] }), importJob.status === "completed" && brandProposal ? (_jsx("div", { className: "mt-4 rounded-md bg-muted/50 p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(IconSparkles, { className: "mt-0.5 size-5 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h4", { className: "text-sm font-semibold", children: t("creativeContext.brandDnaTitle") }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: brandProposal.summary }), brandProposal.colors.length ? (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "text-xs font-medium", children: t("creativeContext.colors") }), _jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: brandProposal.colors.map((color) => (_jsxs("div", { className: "flex items-center gap-1.5 rounded border border-border bg-background px-2 py-1 text-xs", children: [_jsx("span", { className: "size-4 rounded-sm border border-black/10", style: { backgroundColor: color } }), color] }, color))) })] })) : null, brandProposal.fonts.length ? (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "text-xs font-medium", children: t("creativeContext.fonts") }), _jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: brandProposal.fonts.map((font) => (_jsx(Badge, { variant: "outline", children: font }, font))) })] })) : null, brandLayoutThumbnails.length ? (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "text-xs font-medium", children: t("creativeContext.layouts") }), _jsx("div", { className: "mt-2 grid grid-cols-3 gap-2", children: brandLayoutThumbnails.map((thumbnail) => (_jsx(AccessScopedThumbnail, { itemId: thumbnail.itemId, itemVersionId: thumbnail.itemVersionId, className: "aspect-video w-full rounded border border-border object-cover" }, thumbnail.itemVersionId))) })] })) : null, brandVoicePreview ? (_jsxs("div", { className: "mt-4", children: [_jsx("p", { className: "text-xs font-medium", children: t("creativeContext.voice") }), _jsx("blockquote", { className: "mt-1 border-s-2 border-border ps-3 text-sm text-muted-foreground", children: brandVoicePreview })] })) : null, _jsxs("div", { className: "mt-4 flex flex-wrap gap-2", children: [_jsxs(Button, { type: "button", disabled: publishBrandDna.isPending, onClick: () => void publishProposal(), children: [_jsx(IconSparkles, {}), publishBrandDna.isPending
1136
+ ? t("creativeContext.applyingBrandContext")
1137
+ : t("creativeContext.applyBrandContext")] }), _jsx(Button, { asChild: true, type: "button", variant: "outline", children: _jsxs("a", { href: "/settings/agent", children: [t("creativeContext.generateWithContext"), _jsx(IconArrowUpRight, {})] }) })] }), publishedMessage ? (_jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: publishedMessage })) : null] })] }) })) : importJob.error ? (_jsx("p", { className: "mt-2 text-sm text-destructive", children: importJob.error })) : (_jsxs("p", { className: "mt-2 text-xs text-muted-foreground", children: [formatNumber(importJob.progressCurrent), " /", " ", formatNumber(importJob.progressTotal ?? 0)] }))] })) : null, promotionPreview ? (_jsxs("div", { className: "mt-4 rounded-md border border-border p-4", children: [_jsx("h3", { className: "text-sm font-semibold", children: t("creativeContext.promoteToOrganization") }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: t("creativeContext.promotionDescription") }), _jsxs("dl", { className: "mt-3 grid gap-2 text-xs sm:grid-cols-3", children: [_jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground", children: t("creativeContext.sourceReference") }), _jsx("dd", { className: "mt-0.5 truncate font-medium", children: promotionPreview.containerRef })] }), _jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground", children: t("creativeContext.itemsLabel", { count: "" }) }), _jsx("dd", { className: "mt-0.5 font-medium", children: formatNumber(promotionPreview.itemCount) })] }), _jsxs("div", { children: [_jsx("dt", { className: "text-muted-foreground", children: t("creativeContext.restrictedItems", { count: "" }) }), _jsx("dd", { className: "mt-0.5 font-medium", children: formatNumber(promotionPreview.restrictedItemCount) })] })] }), _jsx(Button, { type: "button", className: "mt-4", disabled: manageSource.isPending, onClick: () => void confirmPromotion(), children: t("creativeContext.promoteToOrganization") })] })) : null, promotionMessage ? (_jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: promotionMessage })) : null, setupError ? (_jsx("p", { className: "mt-2 text-sm text-destructive", children: setupError })) : null] }), _jsxs("section", { className: "border-t border-border/70 pt-6", children: [_jsx("h2", { className: "text-lg font-semibold", children: t("creativeContext.sourcesTitle") }), sources.length ? (_jsx("div", { className: "mt-3", children: sources.map((source) => (_jsx(SourceRow, { source: source, refreshing: refreshSource.isPending &&
1138
+ refreshSource.variables?.sourceId === source.id, canReview: canManageScope, canPromote: libraryScope === "user" &&
1139
+ Boolean(org?.orgId) &&
1140
+ canManageOrg &&
1141
+ source.visibility === "private", onRefresh: refresh, onReview: (selected) => void openItemCuration(selected, "restricted"), onCurate: (selected) => void openItemCuration(selected), onPromote: (selected) => void previewSourcePromotion(selected), onPause: (selected) => void pauseSource(selected), onRestore: (selected) => void restoreSource(selected), onDelete: setDeleteSource }, source.id))) })) : (_jsxs("div", { className: "mt-4 rounded-md border border-dashed border-border p-6 text-center", children: [_jsx(IconBooks, { className: "mx-auto size-7 text-muted-foreground" }), _jsx("h3", { className: "mt-3 text-sm font-semibold", children: t("creativeContext.noSourcesTitle") }), _jsx("p", { className: "mx-auto mt-1 max-w-md text-sm text-muted-foreground", children: t("creativeContext.noSourcesDescription") }), _jsx(Button, { asChild: true, variant: "outline", size: "sm", className: "mt-4", children: _jsxs("a", { href: connectionsHref, children: [t("creativeContext.connectSources"), _jsx(IconArrowUpRight, {})] }) })] })), reviewSource ? (_jsx(ItemCuration, { source: reviewSource, items: reviewedItems, busy: reviewItems.isPending, onReview: (operation, itemId) => void reviewContextItem(operation, itemId), onClose: () => {
1142
+ setReviewSource(null);
1143
+ setReviewedItems([]);
1144
+ } })) : null, reviewError ? (_jsx("p", { className: "mt-2 text-sm text-destructive", children: reviewError })) : null, refreshMessage ? (_jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: refreshMessage })) : null, lifecycleMessage ? (_jsx("p", { className: "mt-2 text-xs text-muted-foreground", children: lifecycleMessage })) : null] })] })) : null, libraryView === "settings" ? (_jsxs("section", { className: "border-t border-border/70 pt-6", children: [_jsx("h2", { className: "text-lg font-semibold", children: t("creativeContext.packsTitle") }), packs.length ? (_jsx("div", { className: "mt-3", children: packs.map((pack) => (_jsx(PackRow, { pack: pack, pinned: contextState.state.pinnedPackId === pack.id, disabled: savingState, onPin: (packId) => void changePinnedPack(packId), onDetails: setSelectedPackId }, pack.id))) })) : (_jsx("p", { className: "mt-3 rounded-md border border-dashed border-border p-5 text-sm text-muted-foreground", children: t("creativeContext.noPacks") })), selectedPackId ? (_jsxs("div", { className: "mt-4 rounded-md border border-border p-4", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-sm font-semibold", children: packQuery.data?.pack?.name ??
1145
+ t("creativeContext.packDetails") }), packQuery.data?.pack?.derivedFromPackId ? (_jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [t("creativeContext.influence"), ":", " ", packQuery.data.pack.derivedFromPackId] })) : null] }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setSelectedPackId(null), children: t("creativeContext.cancel") })] }), packQuery.data?.pack?.members.length ? (_jsx("div", { className: "mt-3 divide-y divide-border/60", children: packQuery.data.pack.members.map((member) => (_jsxs("div", { className: "py-2 text-xs", children: [_jsx("p", { className: "font-medium", children: member.itemId }), member.reason ? (_jsxs("p", { className: "mt-0.5 text-muted-foreground", children: [t("creativeContext.influence"), ": ", member.reason] })) : null] }, member.id))) })) : null] })) : null] })) : null, libraryView === "items" ? (_jsxs("section", { className: "border-t border-border/70 pt-6", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-lg font-semibold", children: t("creativeContext.searchTitle") }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: t("creativeContext.searchDescription") })] }), _jsxs("form", { className: "mt-4 flex gap-2", onSubmit: (event) => void search(event), children: [_jsxs("div", { className: "relative min-w-0 flex-1", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: t("creativeContext.searchPlaceholder"), "aria-label": t("creativeContext.searchPlaceholder"), className: "ps-9" })] }), _jsxs(Button, { type: "submit", variant: "outline", disabled: !query.trim() ||
1146
+ (!sources.length &&
1147
+ !selectedLibraryContextId &&
1148
+ !contextState.state.pinnedPackId) ||
1149
+ searchContext.isPending, children: [_jsx(IconSearch, {}), t("creativeContext.searchTitle")] })] }), searchError ? (_jsx("p", { className: "mt-4 text-sm text-destructive", children: searchError })) : !searchContext.data && !searchContext.isPending ? (_jsx("p", { className: "mt-4 text-sm text-muted-foreground", children: t("creativeContext.searchPrompt") })) : searchContext.isPending ? (_jsxs("div", { className: "mt-4 space-y-2", children: [_jsx(Skeleton, { className: "h-20 w-full" }), _jsx(Skeleton, { className: "h-20 w-full" })] })) : searchContext.data?.results.length ? (_jsxs("div", { className: "mt-4 space-y-2", children: [_jsx("p", { className: "text-xs text-muted-foreground", children: t("creativeContext.resultsLabel", {
1150
+ count: formatNumber(searchContext.data.results.length),
1151
+ }) }), searchContext.data.results.map((result) => (_jsxs("article", { className: "rounded-md border border-border/70 p-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "truncate text-sm font-medium", children: result.title }), _jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground", children: [result.sourceName, " \u00B7 ", result.kind] })] }), result.canonicalUrl ? (_jsx(Button, { asChild: true, variant: "ghost", size: "icon", children: _jsx("a", { href: result.canonicalUrl, target: "_blank", rel: "noreferrer", "aria-label": result.title, children: _jsx(IconArrowUpRight, {}) }) })) : null] }), _jsx("p", { className: "mt-2 line-clamp-3 text-sm leading-relaxed text-muted-foreground", children: result.excerpt })] }, `${result.itemVersionId}:${result.chunkId ?? "item"}`)))] })) : (_jsx("p", { className: "mt-4 text-sm text-muted-foreground", children: t("creativeContext.noResults") }))] })) : null] })), _jsx(ContextPreviewSheet, { manifest: previewManifest, onOpenChange: (open) => {
1152
+ if (!open)
1153
+ setPreviewManifest(null);
1154
+ } }), _jsx(AlertDialog, { open: Boolean(membershipUpdateCandidate), onOpenChange: (open) => {
1155
+ if (!open && !updatingMembershipId)
1156
+ setMembershipUpdateCandidate(null);
1157
+ }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("creativeContext.submitUpdateTitle") }), _jsx(AlertDialogDescription, { children: t("creativeContext.submitUpdateDescription", {
1158
+ name: membershipUpdateCandidate?.title ?? "",
1159
+ }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: Boolean(updatingMembershipId), children: t("creativeContext.cancel") }), _jsx(AlertDialogAction, { disabled: Boolean(updatingMembershipId), onClick: (event) => {
1160
+ event.preventDefault();
1161
+ void submitLatestContextMembershipUpdate();
1162
+ }, children: updatingMembershipId
1163
+ ? t("creativeContext.submittingUpdate")
1164
+ : t("creativeContext.submitUpdate") })] })] }) }), _jsx(AlertDialog, { open: Boolean(deleteSource), onOpenChange: (open) => {
1165
+ if (!open)
1166
+ setDeleteSource(null);
1167
+ }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("creativeContext.deleteSourceTitle") }), _jsx(AlertDialogDescription, { children: t("creativeContext.deleteSourceDescription", {
1168
+ name: deleteSource?.name ?? "",
1169
+ }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: t("creativeContext.cancel") }), _jsx(AlertDialogAction, { className: "bg-destructive text-destructive-foreground hover:bg-destructive/90", onClick: () => void confirmDeleteSource(), children: t("creativeContext.delete") })] })] }) })] }));
1170
+ }
1171
+ //# sourceMappingURL=CreativeContextPanel.js.map