@agent-native/creative-context 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +51 -9
  2. package/agent-native.package.json +4 -0
  3. package/dist/actions/index.d.ts.map +1 -1
  4. package/dist/actions/index.js +8 -0
  5. package/dist/actions/index.js.map +1 -1
  6. package/dist/actions/list-context-memberships.d.ts +11 -0
  7. package/dist/actions/list-context-memberships.d.ts.map +1 -0
  8. package/dist/actions/list-context-memberships.js +47 -0
  9. package/dist/actions/list-context-memberships.js.map +1 -0
  10. package/dist/actions/list-creative-contexts.d.ts +12 -0
  11. package/dist/actions/list-creative-contexts.d.ts.map +1 -0
  12. package/dist/actions/list-creative-contexts.js +28 -0
  13. package/dist/actions/list-creative-contexts.js.map +1 -0
  14. package/dist/actions/manage-context-membership.d.ts +64 -0
  15. package/dist/actions/manage-context-membership.d.ts.map +1 -0
  16. package/dist/actions/manage-context-membership.js +70 -0
  17. package/dist/actions/manage-context-membership.js.map +1 -0
  18. package/dist/actions/manage-context-pack.d.ts +3 -0
  19. package/dist/actions/manage-context-pack.js +6 -0
  20. package/dist/actions/manage-context-pack.js.map +1 -1
  21. package/dist/actions/manage-context-source.js +4 -11
  22. package/dist/actions/manage-context-source.js.map +1 -1
  23. package/dist/actions/manage-creative-context.d.ts +28 -0
  24. package/dist/actions/manage-creative-context.d.ts.map +1 -0
  25. package/dist/actions/manage-creative-context.js +65 -0
  26. package/dist/actions/manage-creative-context.js.map +1 -0
  27. package/dist/actions/process-context-purge.d.ts +16 -1
  28. package/dist/actions/process-context-purge.js +2 -1
  29. package/dist/actions/process-context-purge.js.map +1 -1
  30. package/dist/actions/search-creative-context.d.ts +1 -0
  31. package/dist/actions/search-creative-context.js +2 -1
  32. package/dist/actions/search-creative-context.js.map +1 -1
  33. package/dist/client/CreativeContextChip.d.ts +5 -1
  34. package/dist/client/CreativeContextChip.d.ts.map +1 -1
  35. package/dist/client/CreativeContextChip.js +36 -7
  36. package/dist/client/CreativeContextChip.js.map +1 -1
  37. package/dist/client/CreativeContextPanel.d.ts.map +1 -1
  38. package/dist/client/CreativeContextPanel.js +406 -89
  39. package/dist/client/CreativeContextPanel.js.map +1 -1
  40. package/dist/client/CreativeContextShareTab.d.ts +56 -0
  41. package/dist/client/CreativeContextShareTab.d.ts.map +1 -0
  42. package/dist/client/CreativeContextShareTab.js +213 -0
  43. package/dist/client/CreativeContextShareTab.js.map +1 -0
  44. package/dist/client/actions.d.ts +210 -0
  45. package/dist/client/actions.d.ts.map +1 -1
  46. package/dist/client/actions.js +318 -0
  47. package/dist/client/actions.js.map +1 -1
  48. package/dist/client/application-state.d.ts +2 -0
  49. package/dist/client/application-state.d.ts.map +1 -1
  50. package/dist/client/application-state.js +25 -2
  51. package/dist/client/application-state.js.map +1 -1
  52. package/dist/client/index.d.ts +4 -3
  53. package/dist/client/index.d.ts.map +1 -1
  54. package/dist/client/index.js +4 -3
  55. package/dist/client/index.js.map +1 -1
  56. package/dist/client/messages.d.ts +1 -1
  57. package/dist/client/messages.d.ts.map +1 -1
  58. package/dist/client/messages.js +77 -0
  59. package/dist/client/messages.js.map +1 -1
  60. package/dist/connectors/types.d.ts +2 -2
  61. package/dist/connectors/types.d.ts.map +1 -1
  62. package/dist/schema/index.d.ts +1592 -0
  63. package/dist/schema/index.d.ts.map +1 -1
  64. package/dist/schema/index.js +95 -0
  65. package/dist/schema/index.js.map +1 -1
  66. package/dist/schema/migrations.d.ts.map +1 -1
  67. package/dist/schema/migrations.js +80 -0
  68. package/dist/schema/migrations.js.map +1 -1
  69. package/dist/server/generation-artifact-access.js +2 -0
  70. package/dist/server/generation-artifact-access.js.map +1 -1
  71. package/dist/server/generation-context.d.ts +12 -4
  72. package/dist/server/generation-context.d.ts.map +1 -1
  73. package/dist/server/generation-context.js +129 -7
  74. package/dist/server/generation-context.js.map +1 -1
  75. package/dist/server/index.d.ts +4 -0
  76. package/dist/server/index.d.ts.map +1 -1
  77. package/dist/server/index.js +16 -0
  78. package/dist/server/index.js.map +1 -1
  79. package/dist/server/isolated-a2a.d.ts +3 -0
  80. package/dist/server/isolated-a2a.d.ts.map +1 -1
  81. package/dist/server/isolated-a2a.js +3 -1
  82. package/dist/server/isolated-a2a.js.map +1 -1
  83. package/dist/server/media.d.ts +1 -1
  84. package/dist/server/media.d.ts.map +1 -1
  85. package/dist/server/media.js +24 -9
  86. package/dist/server/media.js.map +1 -1
  87. package/dist/server/native-resource-capture.d.ts +78 -0
  88. package/dist/server/native-resource-capture.d.ts.map +1 -0
  89. package/dist/server/native-resource-capture.js +94 -0
  90. package/dist/server/native-resource-capture.js.map +1 -0
  91. package/dist/server/public-serialization.js +1 -1
  92. package/dist/server/public-serialization.js.map +1 -1
  93. package/dist/server/retrieval.d.ts +1 -0
  94. package/dist/server/retrieval.d.ts.map +1 -1
  95. package/dist/server/retrieval.js +2 -0
  96. package/dist/server/retrieval.js.map +1 -1
  97. package/dist/server/safe-native-preview.d.ts +15 -0
  98. package/dist/server/safe-native-preview.d.ts.map +1 -0
  99. package/dist/server/safe-native-preview.js +149 -0
  100. package/dist/server/safe-native-preview.js.map +1 -0
  101. package/dist/store/brand.d.ts.map +1 -1
  102. package/dist/store/brand.js +2 -16
  103. package/dist/store/brand.js.map +1 -1
  104. package/dist/store/content.d.ts +1 -0
  105. package/dist/store/content.d.ts.map +1 -1
  106. package/dist/store/content.js +84 -20
  107. package/dist/store/content.js.map +1 -1
  108. package/dist/store/contexts.d.ts +216 -0
  109. package/dist/store/contexts.d.ts.map +1 -0
  110. package/dist/store/contexts.js +1341 -0
  111. package/dist/store/contexts.js.map +1 -0
  112. package/dist/store/index.d.ts +1 -0
  113. package/dist/store/index.d.ts.map +1 -1
  114. package/dist/store/index.js +1 -0
  115. package/dist/store/index.js.map +1 -1
  116. package/dist/store/packs.d.ts +3 -0
  117. package/dist/store/packs.d.ts.map +1 -1
  118. package/dist/store/packs.js +126 -9
  119. package/dist/store/packs.js.map +1 -1
  120. package/dist/store/purge.d.ts.map +1 -1
  121. package/dist/store/purge.js +103 -6
  122. package/dist/store/purge.js.map +1 -1
  123. package/dist/store/sources.d.ts.map +1 -1
  124. package/dist/store/sources.js +2 -15
  125. package/dist/store/sources.js.map +1 -1
  126. package/dist/store/suggestions.d.ts.map +1 -1
  127. package/dist/store/suggestions.js +3 -1
  128. package/dist/store/suggestions.js.map +1 -1
  129. package/dist/types.d.ts +77 -0
  130. package/dist/types.d.ts.map +1 -1
  131. package/dist/types.js +9 -1
  132. package/dist/types.js.map +1 -1
  133. package/docs/skills/creative-context/SKILL.md +13 -5
  134. package/package.json +3 -3
  135. package/src/actions/index.ts +8 -0
  136. package/src/actions/job-public-serialization.spec.ts +21 -0
  137. package/src/actions/list-context-memberships.ts +56 -0
  138. package/src/actions/list-creative-contexts.spec.ts +38 -0
  139. package/src/actions/list-creative-contexts.ts +32 -0
  140. package/src/actions/manage-context-membership.ts +80 -0
  141. package/src/actions/manage-context-pack.ts +6 -0
  142. package/src/actions/manage-context-source.ts +8 -11
  143. package/src/actions/manage-creative-context.ts +73 -0
  144. package/src/actions/process-context-purge.ts +4 -1
  145. package/src/actions/search-creative-context.ts +2 -1
  146. package/src/client/CreativeContextChip.spec.ts +32 -0
  147. package/src/client/CreativeContextChip.tsx +83 -14
  148. package/src/client/CreativeContextPanel.tsx +1947 -885
  149. package/src/client/CreativeContextShareTab.spec.ts +70 -0
  150. package/src/client/CreativeContextShareTab.tsx +657 -0
  151. package/src/client/actions.spec.ts +177 -0
  152. package/src/client/actions.ts +566 -0
  153. package/src/client/application-state.spec.ts +5 -0
  154. package/src/client/application-state.ts +30 -2
  155. package/src/client/index.ts +33 -0
  156. package/src/client/messages.ts +95 -0
  157. package/src/connectors/types.ts +6 -8
  158. package/src/eval/library-flow.acceptance.spec.tsx +1 -0
  159. package/src/schema/index.ts +116 -0
  160. package/src/schema/migrations.ts +80 -0
  161. package/src/server/generation-artifact-access.ts +1 -0
  162. package/src/server/generation-context-a2a.spec.ts +133 -0
  163. package/src/server/generation-context.ts +153 -7
  164. package/src/server/index.spec.ts +15 -0
  165. package/src/server/index.ts +16 -0
  166. package/src/server/isolated-a2a.ts +4 -1
  167. package/src/server/media.spec.ts +30 -2
  168. package/src/server/media.ts +31 -12
  169. package/src/server/native-resource-capture.spec.ts +121 -0
  170. package/src/server/native-resource-capture.ts +198 -0
  171. package/src/server/public-serialization.spec.ts +1 -0
  172. package/src/server/public-serialization.ts +1 -1
  173. package/src/server/retrieval.ts +3 -0
  174. package/src/server/safe-native-preview.spec.ts +29 -0
  175. package/src/server/safe-native-preview.ts +200 -0
  176. package/src/store/access.integration.spec.ts +1116 -0
  177. package/src/store/brand.ts +2 -21
  178. package/src/store/content.ts +217 -17
  179. package/src/store/contexts.ts +1826 -0
  180. package/src/store/index.ts +1 -0
  181. package/src/store/packs.ts +279 -24
  182. package/src/store/purge.ts +139 -6
  183. package/src/store/sources.ts +2 -18
  184. package/src/store/suggestions.ts +3 -1
  185. package/src/types.ts +95 -0
@@ -1,11 +1,11 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useFormatters, useUploadResource, useT, } from "@agent-native/core/client";
3
3
  import { useOrg } from "@agent-native/core/client/org";
4
- import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Skeleton, Textarea, } from "@agent-native/toolkit/ui";
5
- import { IconAlertTriangle, IconArrowUpRight, IconBooks, IconCheck, IconDots, IconFileImport, IconFileText, IconLayout, IconPalette, IconPhoto, IconPin, IconRefresh, IconSearch, IconSlideshow, IconSparkles, IconUpload, IconWorld, } from "@tabler/icons-react";
4
+ 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";
5
+ 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";
6
6
  import { useEffect, useMemo, useRef, useState, } from "react";
7
7
  import { creativeContextMediaUrl } from "../media-url.js";
8
- import { useCreativeContextBrandProfile, useCanonicalLogoCandidates, useCreativeContextConnections, useCreativeContextGooglePickerSession, useCreativeContextRootRecommendations, useCreativeContextImportStatus, useCreativeContextPack, useCreativeContextPacks, useCreativeContextSearch, useCreativeContextSuggestions, useCreativeContextSources, useManageCreativeContextSource, useManageLayoutTemplate, usePreviewCreativeContextImport, usePublishCreativeContextBrandDna, useConfirmCanonicalLogo, useProposeCanonicalLogo, useRefreshCreativeContextSource, useReviewCreativeContextItems, useStartCreativeContextImport, } from "./actions.js";
8
+ 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";
9
9
  import { useCreativeContextState, } from "./application-state.js";
10
10
  import { CreativeContextChip } from "./CreativeContextChip.js";
11
11
  import { chooseGoogleSlidesPresentations } from "./google-slides-picker.js";
@@ -212,12 +212,84 @@ function ItemCuration({ source, items, busy, onReview, onClose, }) {
212
212
  ? "creativeContext.restore"
213
213
  : "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))) })] }));
214
214
  }
215
+ function StructuredPreview({ preview, compact = false, }) {
216
+ if (!preview) {
217
+ 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" }) }));
218
+ }
219
+ if (preview.type === "slides") {
220
+ const visibleSlides = compact ? preview.slides.slice(0, 3) : preview.slides;
221
+ 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] }));
222
+ }
223
+ if (preview.type === "slide") {
224
+ 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] }));
225
+ }
226
+ if (preview.type === "design" || preview.type === "design-frame") {
227
+ const frames = preview.type === "design"
228
+ ? preview.frames
229
+ : [
230
+ {
231
+ title: preview.title,
232
+ fileType: preview.fileType,
233
+ excerpt: preview.excerpt,
234
+ },
235
+ ];
236
+ const visibleFrames = compact ? frames.slice(0, 4) : frames;
237
+ 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}`))) }));
238
+ }
239
+ if (preview.type === "document") {
240
+ const visibleBlocks = preview.blocks.slice(0, compact ? 7 : 40);
241
+ 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) => {
242
+ if (block.kind === "heading") {
243
+ return (_jsx("p", { className: (block.level ?? 2) <= 2
244
+ ? "text-sm font-semibold"
245
+ : "text-xs font-medium", children: block.text }, `${block.kind}-${index}`));
246
+ }
247
+ if (block.kind === "bullet") {
248
+ return (_jsx("p", { className: "flex gap-2 text-xs leading-relaxed text-muted-foreground before:content-['\u2022']", children: block.text }, `${block.kind}-${index}`));
249
+ }
250
+ if (block.kind === "quote") {
251
+ 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}`));
252
+ }
253
+ if (block.kind === "code") {
254
+ return (_jsx("pre", { className: "overflow-hidden rounded bg-muted p-2 font-mono text-[10px] leading-relaxed", children: block.text }, `${block.kind}-${index}`));
255
+ }
256
+ return (_jsx("p", { className: "text-xs leading-relaxed text-muted-foreground", children: block.text }, `${block.kind}-${index}`));
257
+ }) })) : preview.excerpt ? (_jsx("p", { className: "mt-3 line-clamp-6 whitespace-pre-wrap text-xs leading-relaxed text-muted-foreground", children: preview.excerpt })) : null }));
258
+ }
259
+ if (preview.type === "asset") {
260
+ 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] }));
261
+ }
262
+ 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] }));
263
+ }
264
+ function ContextPreviewVisual({ manifest, compact = false, }) {
265
+ if (manifest.media?.mimeType?.startsWith("video/")) {
266
+ 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" }));
267
+ }
268
+ if (manifest.media) {
269
+ return (_jsx("img", { src: manifest.media.url, alt: "", className: "h-full w-full object-contain" }));
270
+ }
271
+ return _jsx(StructuredPreview, { preview: manifest.preview, compact: compact });
272
+ }
273
+ function ContextPreviewSheet({ manifest, onOpenChange, }) {
274
+ const [selectedMediaUrl, setSelectedMediaUrl] = useState(null);
275
+ useEffect(() => setSelectedMediaUrl(null), [manifest?.itemVersionId]);
276
+ const selectedMedia = manifest?.gallery?.find((medium) => medium.url === selectedMediaUrl) ??
277
+ manifest?.media ??
278
+ null;
279
+ 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)
280
+ ? "border-foreground"
281
+ : "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] }) }));
282
+ }
283
+ function ContextRail({ contexts, selectedContextId, disabled, canCreate, onSelect, onCreate, }) {
284
+ 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] })] }));
285
+ }
215
286
  export function CreativeContextPanel({ scope = "user", canManageOrg = false, scopeControl, connectionsHref = "/agent#connections", }) {
216
287
  const t = useT();
217
288
  const { formatNumber } = useFormatters();
218
289
  const { data: org } = useOrg();
219
290
  const [libraryScope, setLibraryScope] = useState(scope);
220
291
  const sourcesQuery = useCreativeContextSources({ limit: 100 });
292
+ const contextsQuery = useCreativeContexts();
221
293
  const packsQuery = useCreativeContextPacks();
222
294
  const brandProfileQuery = useCreativeContextBrandProfile();
223
295
  const suggestionsQuery = useCreativeContextSuggestions();
@@ -234,6 +306,8 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
234
306
  const manageLayoutTemplate = useManageLayoutTemplate();
235
307
  const contextState = useCreativeContextState();
236
308
  const [query, setQuery] = useState("");
309
+ const [libraryView, setLibraryView] = useState("items");
310
+ const [previewManifest, setPreviewManifest] = useState(null);
237
311
  const [savingState, setSavingState] = useState(false);
238
312
  const [stateError, setStateError] = useState(null);
239
313
  const [refreshMessage, setRefreshMessage] = useState(null);
@@ -276,6 +350,8 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
276
350
  const [reviewSource, setReviewSource] = useState(null);
277
351
  const [reviewedItems, setReviewedItems] = useState([]);
278
352
  const [reviewError, setReviewError] = useState(null);
353
+ const [membershipUpdateCandidate, setMembershipUpdateCandidate] = useState(null);
354
+ const [updatingMembershipId, setUpdatingMembershipId] = useState(null);
279
355
  const [selectedPackId, setSelectedPackId] = useState(null);
280
356
  const [suggestionError, setSuggestionError] = useState(null);
281
357
  const previewQuery = usePreviewCreativeContextImport(previewSourceId);
@@ -309,6 +385,21 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
309
385
  !hiddenSourceIds.has(source.id) &&
310
386
  isVisibleInScope(source.visibility, libraryScope)), [hiddenSourceIds, libraryScope, sourcesQuery.data?.sources]);
311
387
  const packs = useMemo(() => (packsQuery.data?.packs ?? []).filter((pack) => !pack.archivedAt && isVisibleInScope(pack.visibility, libraryScope)), [libraryScope, packsQuery.data?.packs]);
388
+ const contexts = useMemo(() => parseCreativeContexts(contextsQuery.data), [contextsQuery.data]);
389
+ const selectedLibraryContextId = contextState.state.selectedContextId ?? contexts[0]?.id ?? null;
390
+ const contextMembershipsQuery = useContextMemberships(selectedLibraryContextId ? { contextId: selectedLibraryContextId } : null);
391
+ const manageContext = useManageCreativeContext();
392
+ const manageContextMembership = useManageContextMembership();
393
+ const contextMemberships = parseContextMemberships(contextMembershipsQuery.data);
394
+ const publishedContextMemberships = contextMemberships.filter((membership) => membership.publishedItem);
395
+ const pendingContextMemberships = contextMemberships.filter((membership) => membership.pendingSubmission);
396
+ const selectedLibraryContext = contexts.find((context) => context.id === selectedLibraryContextId);
397
+ const [contextSettingsName, setContextSettingsName] = useState("");
398
+ const [contextSettingsDescription, setContextSettingsDescription] = useState("");
399
+ const [contextSettingsPolicy, setContextSettingsPolicy] = useState("open");
400
+ const [newContextName, setNewContextName] = useState("");
401
+ const [newContextPolicy, setNewContextPolicy] = useState("open");
402
+ const [contextSettingsError, setContextSettingsError] = useState(null);
312
403
  const activePack = packs.find((pack) => pack.id === contextState.state.currentPackId);
313
404
  const selectedConnector = CONNECTORS.find((connector) => connector.kind === connectorKind);
314
405
  const importJob = importStatusQuery.data?.job;
@@ -317,12 +408,22 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
317
408
  const brandLayoutThumbnails = selectRenderableLayoutThumbnails(brandProposal?.layoutThumbnails ?? []);
318
409
  const brandVoicePreview = brandProposal?.voiceDescriptors?.join(" · ") ?? brandProposal?.voiceLine;
319
410
  const canManageScope = libraryScope === "user" || canManageOrg;
411
+ const canCreateContext = canManageScope && contexts.some((context) => context.access.canAdmin);
412
+ const activeAppId = contextsQuery.data?.appId;
413
+ const appDefaultContextId = contextsQuery.data?.appDefaultContextId ?? null;
414
+ const canSetAppDefault = Boolean(activeAppId && selectedLibraryContext?.access.canAdmin && canManageScope);
320
415
  const proposalCapabilities = suggestionsQuery.data?.capabilities;
321
416
  const logoCandidates = proposalCapabilities?.canonicalLogo
322
417
  ? (logoCandidatesQuery.data?.candidates ?? [])
323
418
  : [];
324
419
  const proposedLayouts = (suggestionsQuery.data?.suggestions ?? []).filter((suggestion) => suggestion.kind === "layout-template" &&
325
420
  (suggestion.status === "proposed" || suggestion.status === "promoted"));
421
+ useEffect(() => {
422
+ setContextSettingsName(selectedLibraryContext?.name ?? "");
423
+ setContextSettingsDescription(selectedLibraryContext?.description ?? "");
424
+ setContextSettingsPolicy(selectedLibraryContext?.approvalPolicy ?? "open");
425
+ setContextSettingsError(null);
426
+ }, [selectedLibraryContext]);
326
427
  useEffect(() => {
327
428
  if (!previewSourceId || !previewQuery.data)
328
429
  return;
@@ -369,8 +470,18 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
369
470
  setStateError(null);
370
471
  try {
371
472
  await contextState.setState(mode === "off"
372
- ? { contextMode: "off", currentPackId: null, pinnedPackId: null }
373
- : { ...contextState.state, contextMode: "auto" });
473
+ ? {
474
+ contextMode: "off",
475
+ selectedContextId: null,
476
+ currentPackId: null,
477
+ pinnedPackId: null,
478
+ }
479
+ : {
480
+ ...contextState.state,
481
+ contextMode: "auto",
482
+ selectedContextId: null,
483
+ pinnedPackId: null,
484
+ });
374
485
  }
375
486
  catch {
376
487
  setStateError(t("creativeContext.stateSaveFailed"));
@@ -386,6 +497,7 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
386
497
  await contextState.setState({
387
498
  ...contextState.state,
388
499
  contextMode: "auto",
500
+ selectedContextId: null,
389
501
  pinnedPackId: packId,
390
502
  });
391
503
  }
@@ -396,6 +508,61 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
396
508
  setSavingState(false);
397
509
  }
398
510
  }
511
+ async function selectContext(contextId) {
512
+ setSavingState(true);
513
+ setStateError(null);
514
+ try {
515
+ await contextState.setState({
516
+ ...contextState.state,
517
+ contextMode: "auto",
518
+ selectedContextId: contextId,
519
+ pinnedPackId: null,
520
+ });
521
+ }
522
+ catch {
523
+ setStateError(t("creativeContext.stateSaveFailed"));
524
+ }
525
+ finally {
526
+ setSavingState(false);
527
+ }
528
+ }
529
+ async function reviewContextMembership(membershipId, operation) {
530
+ if (!selectedLibraryContextId)
531
+ return;
532
+ try {
533
+ await manageContextMembership.mutateAsync({
534
+ operation,
535
+ contextId: selectedLibraryContextId,
536
+ membershipId,
537
+ });
538
+ await contextMembershipsQuery.refetch();
539
+ }
540
+ catch {
541
+ setReviewError(t("creativeContext.saveFailed"));
542
+ }
543
+ }
544
+ async function submitLatestContextMembershipUpdate() {
545
+ if (!selectedLibraryContextId || !membershipUpdateCandidate)
546
+ return;
547
+ setReviewError(null);
548
+ setUpdatingMembershipId(membershipUpdateCandidate.id);
549
+ try {
550
+ await manageContextMembership.mutateAsync({
551
+ operation: "submit-latest",
552
+ contextId: selectedLibraryContextId,
553
+ membershipId: membershipUpdateCandidate.id,
554
+ confirmBroaderPublication: true,
555
+ });
556
+ setMembershipUpdateCandidate(null);
557
+ await contextMembershipsQuery.refetch();
558
+ }
559
+ catch {
560
+ setReviewError(t("creativeContext.submitUpdateFailed"));
561
+ }
562
+ finally {
563
+ setUpdatingMembershipId(null);
564
+ }
565
+ }
399
566
  function refresh(sourceId) {
400
567
  setRefreshMessage(null);
401
568
  refreshSource.mutate({ sourceId, mode: "incremental" }, {
@@ -731,17 +898,82 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
731
898
  setSuggestionError(t("creativeContext.saveFailed"));
732
899
  }
733
900
  }
901
+ async function saveContextSettings() {
902
+ if (!selectedLibraryContext?.access.canAdmin || !contextSettingsName.trim())
903
+ return;
904
+ setContextSettingsError(null);
905
+ try {
906
+ await manageContext.mutateAsync({
907
+ operation: "update",
908
+ contextId: selectedLibraryContext.id,
909
+ patch: {
910
+ name: contextSettingsName.trim(),
911
+ description: contextSettingsDescription.trim() || null,
912
+ approvalPolicy: contextSettingsPolicy,
913
+ },
914
+ });
915
+ await contextsQuery.refetch();
916
+ }
917
+ catch {
918
+ setContextSettingsError("Could not update this context.");
919
+ }
920
+ }
921
+ async function createSpecialtyContext() {
922
+ if (!canCreateContext || !newContextName.trim())
923
+ return;
924
+ setContextSettingsError(null);
925
+ try {
926
+ const result = await manageContext.mutateAsync({
927
+ operation: "create",
928
+ name: newContextName.trim(),
929
+ kind: "specialty",
930
+ approvalPolicy: newContextPolicy,
931
+ });
932
+ setNewContextName("");
933
+ setNewContextPolicy("open");
934
+ await contextsQuery.refetch();
935
+ if (result.context?.id)
936
+ await selectContext(result.context.id);
937
+ }
938
+ catch {
939
+ setContextSettingsError("Could not create this context.");
940
+ }
941
+ }
942
+ async function setAppDefaultContext() {
943
+ if (!activeAppId || !selectedLibraryContext || !canSetAppDefault)
944
+ return;
945
+ setContextSettingsError(null);
946
+ try {
947
+ await manageContext.mutateAsync({
948
+ operation: "set-app-default",
949
+ contextId: selectedLibraryContext.id,
950
+ appId: activeAppId,
951
+ });
952
+ await contextsQuery.refetch();
953
+ }
954
+ catch {
955
+ setContextSettingsError("Could not update the automatic context for this app.");
956
+ }
957
+ }
734
958
  async function search(event) {
735
959
  event.preventDefault();
736
960
  const searchText = query.trim();
737
- if (!searchText || !sources.length)
961
+ if (!searchText ||
962
+ (!sources.length &&
963
+ !selectedLibraryContextId &&
964
+ !contextState.state.pinnedPackId))
738
965
  return;
739
966
  setSearchError(null);
740
967
  try {
741
968
  const result = await searchContext.mutateAsync({
742
969
  query: searchText,
743
- sourceIds: sources.map((source) => source.id),
970
+ sourceIds: selectedLibraryContextId || contextState.state.pinnedPackId
971
+ ? undefined
972
+ : sources.map((source) => source.id),
744
973
  packId: contextState.state.pinnedPackId ?? undefined,
974
+ contextId: contextState.state.pinnedPackId
975
+ ? undefined
976
+ : (selectedLibraryContextId ?? undefined),
745
977
  limit: 20,
746
978
  snapshot: true,
747
979
  });
@@ -756,94 +988,179 @@ export function CreativeContextPanel({ scope = "user", canManageOrg = false, sco
756
988
  setSearchError(t("creativeContext.unavailable"));
757
989
  }
758
990
  }
759
- const loading = sourcesQuery.isLoading || packsQuery.isLoading || contextState.isLoading;
760
- const unavailable = sourcesQuery.error || packsQuery.error;
991
+ const loading = sourcesQuery.isLoading ||
992
+ packsQuery.isLoading ||
993
+ contextsQuery.isLoading ||
994
+ contextState.isLoading;
995
+ const unavailable = sourcesQuery.error || packsQuery.error || contextsQuery.error;
761
996
  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 ??
762
- (org?.orgId ? (_jsx(ScopeControl, { scope: libraryScope, onChange: setLibraryScope })) : null), _jsx(CreativeContextChip, { state: contextState.state, packs: packs })] })] }), 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: [_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
997
+ (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) => {
998
+ const item = membership.publishedItem;
999
+ const imageMedium = item.media.find((medium) => medium.mimeType?.startsWith("image/"));
1000
+ const playbackMedium = item.media.find((medium) => medium.mimeType?.startsWith("video/"));
1001
+ const medium = imageMedium ?? playbackMedium ?? item.media[0];
1002
+ const sheetMedium = playbackMedium ?? medium;
1003
+ const updateAvailable = membership.nativeUpdateStatus?.state === "update-available";
1004
+ return (_jsxs("article", { className: "overflow-hidden rounded-md border border-border", children: [_jsxs("button", { type: "button", onClick: () => setPreviewManifest({
1005
+ title: item.title,
1006
+ kind: item.kind,
1007
+ itemId: item.id,
1008
+ itemVersionId: item.itemVersionId,
1009
+ preview: item.preview,
1010
+ media: sheetMedium ?? null,
1011
+ gallery: item.media.filter((candidate) => candidate.mimeType?.startsWith("image/")),
1012
+ posterUrl: playbackMedium && imageMedium
1013
+ ? imageMedium.url
1014
+ : undefined,
1015
+ }), 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: {
1016
+ title: item.title,
1017
+ kind: item.kind,
1018
+ itemId: item.id,
1019
+ itemVersionId: item.itemVersionId,
1020
+ preview: item.preview,
1021
+ media: medium ?? null,
1022
+ gallery: item.media,
1023
+ } }) }), _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 &&
1024
+ 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({
1025
+ id: membership.id,
1026
+ title: item.title,
1027
+ }), children: [_jsx(IconRefresh, {}), updatingMembershipId === membership.id
1028
+ ? t("creativeContext.submittingUpdate")
1029
+ : t("creativeContext.submitUpdate")] }) })) : null] }, membership.id));
1030
+ }) }), !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) => {
1031
+ const submission = membership.pendingSubmission;
1032
+ const item = submission.proposedItem;
1033
+ const medium = item?.media[0];
1034
+ 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({
1035
+ title: item.title,
1036
+ kind: item.kind,
1037
+ itemId: item.id,
1038
+ itemVersionId: item.itemVersionId,
1039
+ preview: item.preview,
1040
+ media: medium ?? null,
1041
+ gallery: item.media.filter((candidate) => candidate.mimeType?.startsWith("image/")),
1042
+ }), children: _jsx(ContextPreviewVisual, { compact: true, manifest: {
1043
+ title: item.title,
1044
+ kind: item.kind,
1045
+ itemId: item.id,
1046
+ itemVersionId: item.itemVersionId,
1047
+ preview: item.preview,
1048
+ media: medium ?? null,
1049
+ } }) })) : 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));
1050
+ }) }), !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 ||
1051
+ !contextSettingsName.trim() ||
1052
+ 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 ||
1053
+ appDefaultContextId === selectedLibraryContext?.id ||
1054
+ manageContext.isPending, onClick: () => void setAppDefaultContext(), children: appDefaultContextId === selectedLibraryContext?.id
1055
+ ? `Automatic for ${activeAppId}`
1056
+ : `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 ||
1057
+ !newContextName.trim() ||
1058
+ 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
763
1059
  ? `${t("creativeContext.activePack")}: ${activePack.name}`
764
- : 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] }), brandProfileQuery.data?.profile && 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, 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 ||
1060
+ : 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" &&
1061
+ brandProfileQuery.data?.profile &&
1062
+ 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" &&
1063
+ (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 ||
765
1064
  confirmCanonicalLogo.isPending, onClick: () => void chooseCanonicalLogo(candidate), children: [_jsx(IconCheck, {}), t("creativeContext.approve")] })] })] }, candidate.mediaId))) })] })) : null, proposedLayouts.length &&
766
- 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, _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) => {
767
- const Icon = connector.icon;
768
- return (_jsxs("button", { type: "button", disabled: !canManageScope, onClick: () => {
769
- setConnectorKind(connector.kind);
770
- setSourceName(connector.label);
771
- setSourceReference("");
772
- setUploadedFiles([]);
773
- setPickerRecommendations([]);
774
- seenRecommendationIdsRef.current.clear();
775
- setSelectedConnectionId("");
776
- setSelectedRecommendationIds(new Set());
777
- setSetupError(null);
778
- }, 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));
779
- }) }), 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 ||
780
- connectionsQuery.data.connectionsPath ||
781
- 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
782
- ? t("creativeContext.loading")
783
- : t("creativeContext.choosePresentations")] })] })) : null, recommendationsQuery.isLoading &&
784
- !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", {
785
- count: formatNumber(availableRecommendations.length),
786
- }) }), _jsx("span", { children: t("creativeContext.selectedItems", {
787
- count: formatNumber(selectedRecommendationIds.size),
788
- }) })] }), _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) => {
1065
+ 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) => {
1066
+ const Icon = connector.icon;
1067
+ return (_jsxs("button", { type: "button", disabled: !canManageScope, onClick: () => {
1068
+ setConnectorKind(connector.kind);
1069
+ setSourceName(connector.label);
1070
+ setSourceReference("");
1071
+ setUploadedFiles([]);
1072
+ setPickerRecommendations([]);
1073
+ seenRecommendationIdsRef.current.clear();
1074
+ setSelectedConnectionId("");
1075
+ setSelectedRecommendationIds(new Set());
1076
+ setSetupError(null);
1077
+ }, 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));
1078
+ }) }), 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 ||
1079
+ connectionsQuery.data.connectionsPath ||
1080
+ 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
1081
+ ? t("creativeContext.loading")
1082
+ : t("creativeContext.choosePresentations")] })] })) : null, recommendationsQuery.isLoading &&
1083
+ !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", {
1084
+ count: formatNumber(availableRecommendations.length),
1085
+ }) }), _jsx("span", { children: t("creativeContext.selectedItems", {
1086
+ count: formatNumber(selectedRecommendationIds.size),
1087
+ }) })] }), _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) => {
1088
+ const next = new Set(current);
1089
+ if (checked) {
1090
+ next.add(recommendation.externalId);
1091
+ }
1092
+ else {
1093
+ next.delete(recommendation.externalId);
1094
+ }
1095
+ return next;
1096
+ }) }), _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 ??
1097
+ recommendation.kind })] })] }, recommendation.externalId))) })] })) : (_jsx("p", { className: "text-xs text-muted-foreground", children: recommendationsQuery.data?.unavailableReason ??
1098
+ 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" ||
1099
+ selectedConnector.kind === "figma" ||
1100
+ 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 ||
1101
+ uploadResource.isPending ||
1102
+ (selectedConnector.kind === "upload" &&
1103
+ !uploadedFiles.length) ||
1104
+ (Boolean(connectionProvider) &&
1105
+ !selectedConnectionId) ||
1106
+ (selectedConnector.referenceRequired &&
1107
+ !sourceReference.trim()) ||
1108
+ (Boolean(recommendationProvider) &&
1109
+ !sourceReference.trim() &&
1110
+ !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", {
1111
+ count: formatNumber(previewQuery.data?.total ??
1112
+ previewQuery.data?.items.length ??
1113
+ 0),
1114
+ }) }), _jsx("span", { children: t("creativeContext.selectedItems", {
1115
+ count: formatNumber(selectedPreviewItemIds.size),
1116
+ }) })] }))] }), _jsxs(Button, { type: "button", disabled: previewQuery.isLoading ||
1117
+ !previewQuery.data?.items.length ||
1118
+ !selectedPreviewItemIds.size ||
1119
+ startImport.isPending ||
1120
+ importJob?.status === "queued" ||
1121
+ importJob?.status === "running", onClick: () => void beginImport(), children: [_jsx(IconFileImport, {}), startImport.isPending
1122
+ ? t("creativeContext.importing")
1123
+ : 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) => {
789
1124
  const next = new Set(current);
790
- if (checked) {
791
- next.add(recommendation.externalId);
792
- }
793
- else {
794
- next.delete(recommendation.externalId);
795
- }
1125
+ if (checked)
1126
+ next.add(item.externalId);
1127
+ else
1128
+ next.delete(item.externalId);
796
1129
  return next;
797
- }) }), _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 ??
798
- recommendation.kind })] })] }, recommendation.externalId))) })] })) : (_jsx("p", { className: "text-xs text-muted-foreground", children: recommendationsQuery.data?.unavailableReason ??
799
- 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" ||
800
- selectedConnector.kind === "figma" ||
801
- 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 ||
802
- uploadResource.isPending ||
803
- (selectedConnector.kind === "upload" &&
804
- !uploadedFiles.length) ||
805
- (Boolean(connectionProvider) && !selectedConnectionId) ||
806
- (selectedConnector.referenceRequired &&
807
- !sourceReference.trim()) ||
808
- (Boolean(recommendationProvider) &&
809
- !sourceReference.trim() &&
810
- !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", {
811
- count: formatNumber(previewQuery.data?.total ??
812
- previewQuery.data?.items.length ??
813
- 0),
814
- }) }), _jsx("span", { children: t("creativeContext.selectedItems", {
815
- count: formatNumber(selectedPreviewItemIds.size),
816
- }) })] }))] }), _jsxs(Button, { type: "button", disabled: previewQuery.isLoading ||
817
- !previewQuery.data?.items.length ||
818
- !selectedPreviewItemIds.size ||
819
- startImport.isPending ||
820
- importJob?.status === "queued" ||
821
- importJob?.status === "running", onClick: () => void beginImport(), children: [_jsx(IconFileImport, {}), startImport.isPending
822
- ? t("creativeContext.importing")
823
- : 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) => {
824
- const next = new Set(current);
825
- if (checked)
826
- next.add(item.externalId);
827
- else
828
- next.delete(item.externalId);
829
- return next;
830
- }) }), _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"
831
- ? t("creativeContext.importComplete")
832
- : importJob.status === "failed"
833
- ? t("creativeContext.importFailed")
834
- : 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
835
- ? t("creativeContext.applyingBrandContext")
836
- : t("creativeContext.applyBrandContext")] }), _jsx(Button, { asChild: true, type: "button", variant: "outline", children: _jsxs("a", { href: "/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 &&
837
- refreshSource.variables?.sourceId === source.id, canReview: canManageScope, canPromote: libraryScope === "user" &&
838
- Boolean(org?.orgId) &&
839
- canManageOrg &&
840
- 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: () => {
841
- setReviewSource(null);
842
- setReviewedItems([]);
843
- } })) : 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] }), _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 ??
844
- 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] }), _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() || !sources.length || 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", {
1130
+ }) }), _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"
1131
+ ? t("creativeContext.importComplete")
1132
+ : importJob.status === "failed"
1133
+ ? t("creativeContext.importFailed")
1134
+ : 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
1135
+ ? t("creativeContext.applyingBrandContext")
1136
+ : t("creativeContext.applyBrandContext")] }), _jsx(Button, { asChild: true, type: "button", variant: "outline", children: _jsxs("a", { href: "/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 &&
1137
+ refreshSource.variables?.sourceId === source.id, canReview: canManageScope, canPromote: libraryScope === "user" &&
1138
+ Boolean(org?.orgId) &&
1139
+ canManageOrg &&
1140
+ 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: () => {
1141
+ setReviewSource(null);
1142
+ setReviewedItems([]);
1143
+ } })) : 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 ??
1144
+ 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() ||
1145
+ (!sources.length &&
1146
+ !selectedLibraryContextId &&
1147
+ !contextState.state.pinnedPackId) ||
1148
+ 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", {
845
1149
  count: formatNumber(searchContext.data.results.length),
846
- }) }), 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") }))] })] })), _jsx(AlertDialog, { open: Boolean(deleteSource), onOpenChange: (open) => {
1150
+ }) }), 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) => {
1151
+ if (!open)
1152
+ setPreviewManifest(null);
1153
+ } }), _jsx(AlertDialog, { open: Boolean(membershipUpdateCandidate), onOpenChange: (open) => {
1154
+ if (!open && !updatingMembershipId)
1155
+ setMembershipUpdateCandidate(null);
1156
+ }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("creativeContext.submitUpdateTitle") }), _jsx(AlertDialogDescription, { children: t("creativeContext.submitUpdateDescription", {
1157
+ name: membershipUpdateCandidate?.title ?? "",
1158
+ }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: Boolean(updatingMembershipId), children: t("creativeContext.cancel") }), _jsx(AlertDialogAction, { disabled: Boolean(updatingMembershipId), onClick: (event) => {
1159
+ event.preventDefault();
1160
+ void submitLatestContextMembershipUpdate();
1161
+ }, children: updatingMembershipId
1162
+ ? t("creativeContext.submittingUpdate")
1163
+ : t("creativeContext.submitUpdate") })] })] }) }), _jsx(AlertDialog, { open: Boolean(deleteSource), onOpenChange: (open) => {
847
1164
  if (!open)
848
1165
  setDeleteSource(null);
849
1166
  }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t("creativeContext.deleteSourceTitle") }), _jsx(AlertDialogDescription, { children: t("creativeContext.deleteSourceDescription", {