@knkcs/mediahub-ui 0.4.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.
- package/README.md +62 -0
- package/dist/index.d.ts +338 -0
- package/dist/index.js +2966 -2385
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/lib/rpc-errors.ts","../src/lib/slugify.ts","../src/lib/mime-type-list.ts","../src/connect-clients.ts","../src/provider.tsx","../src/statushub.ts","../src/lib/sas-upload.ts","../src/hooks/use-add-version.ts","../src/hooks/use-assets.ts","../src/hooks/use-authz.ts","../src/hooks/use-folders.ts","../src/hooks/use-grants.ts","../src/hooks/use-collections.ts","../src/hooks/use-tags.ts","../src/hooks/use-asset-types.ts","../src/hooks/use-users.ts","../src/hooks/use-dashboard.ts","../src/hooks/use-ai-connections.ts","../src/hooks/use-ai-processes.ts","../src/hooks/use-ai-process-runs.ts","../src/stores/selection-store.ts","../src/stores/preferences-store.ts","../src/stores/upload-store.ts","../src/components/ai-process-form-dialog.tsx","../src/lib/metadata-field-count.ts","../src/components/ai-processes-tab.tsx","../src/components/asset-status-badge.tsx","../src/components/asset-grid.tsx","../src/components/asset-preview.tsx","../src/components/asset-status-control.tsx","../src/components/bulk-action-bar.tsx","../src/components/collection-chip-field.tsx","../src/components/collection-panel.tsx","../src/components/folder-breadcrumbs.tsx","../src/components/leak-guard-refusal-dialog.tsx","../src/lib/move-guard.ts","../src/components/manage-access-dialog.tsx","../src/components/move-dialog.tsx","../src/components/restricted.tsx","../src/components/restricted-folder-dialog.tsx","../src/components/folder-tree.tsx","../src/components/inline-edit-field.tsx","../src/components/metadata-schema-editor.tsx","../src/components/tag-chip-field.tsx","../src/components/tag-panel.tsx","../src/components/upload/upload-dialog.tsx","../src/components/upload/upload-drop-zone.tsx","../src/components/upload/upload-toast-stack.tsx","../src/asset-library-resolve.ts","../src/asset-library.tsx","../src/lib/asset-metadata-form.ts","../src/asset-detail.tsx","../src/asset-type-detail.tsx","../src/asset-type-create.tsx","../src/asset-type-index.tsx","../src/components/picker/picker-asset-card.tsx","../src/components/picker/picker-footer.tsx","../src/components/picker/use-picker-selection.ts","../src/asset-picker.tsx","../src/collection-picker.tsx","../src/i18n/resources.ts","../src/index.ts"],"sourcesContent":["import { toaster } from \"@knkcs/anker/primitives\";\n\n/**\n * Transport-level error mapping (guardian#50): permission denials and\n * leak-guard conflicts become human-readable descriptions; every other error\n * keeps the server's message, which for validation failures is deliberate\n * guidance.\n *\n * The mapping is structural on purpose — mediahub-ui takes no dependency on\n * `@connectrpc/connect` or generated proto types. A ConnectError is\n * recognized by its numeric `code`; a leak-guard conflict by an error detail\n * of type `mediahub.v1.LeakGuardViolation`, whose `debug` field carries the\n * server's protoJSON (Connect JSON protocol) naming the refusing rule and\n * the asset→collection exposures involved.\n */\n\n/** Connect/gRPC wire codes (subset we map). */\nconst CODE_PERMISSION_DENIED = 7;\nconst CODE_FAILED_PRECONDITION = 9;\nconst CODE_UNAVAILABLE = 14;\n\nconst LEAK_GUARD_DETAIL_TYPE = \"mediahub.v1.LeakGuardViolation\";\n\n/** One offending asset→collection pair behind a leak-guard refusal. */\nexport interface LeakGuardExposure {\n\tassetId: string;\n\tassetName: string;\n\tcollectionId: string;\n\tcollectionName: string;\n}\n\nexport interface RpcErrorDescription {\n\tkind: \"permission-denied\" | \"leak-guard\" | \"other\";\n\ttitle: string;\n\tdescription: string;\n\t/** Present for leak-guard conflicts: the items the refusal involves. */\n\texposures?: LeakGuardExposure[];\n\t/** Present for leak-guard conflicts: the refusing rule's explanation\n\t * without the joined item list — for surfaces that render `exposures`\n\t * themselves (e.g. the refusal dialog). */\n\truleText?: string;\n}\n\nconst PERMISSION_DENIED_TITLE = \"You don't have access\";\nconst PERMISSION_DENIED_BODY =\n\t\"You don't have permission to do this. The item's Owner or a workspace admin can grant you access.\";\n\nconst LEAK_GUARD_TITLE = \"Blocked to prevent a leak\";\nconst LEAK_GUARD_GENERIC =\n\t\"This change would expose Restricted material, so it was refused.\";\n\n/** Explanations per refusing rule, keyed by the wire enum's protoJSON name. */\nconst LEAK_GUARD_RULES: Record<string, string> = {\n\tLEAK_GUARD_RULE_RESTRICTED_ASSET_INTO_OPEN_COLLECTION:\n\t\t\"These assets live in a Restricted folder. An open collection is visible to the whole workspace, so adding them would leak Restricted material.\",\n\tLEAK_GUARD_RULE_ASSET_INTO_RESTRICTED_CHAIN_WHILE_EXPOSED:\n\t\t\"An open collection still exposes this asset, so moving it into a Restricted folder would leak Restricted material. Remove it from the collection first.\",\n\tLEAK_GUARD_RULE_FOLDER_INTO_RESTRICTED_CHAIN_WHILE_EXPOSED:\n\t\t\"An open collection still exposes assets inside this folder, so moving it under a Restricted folder would leak Restricted material. Remove those assets from their collections first.\",\n};\n\nfunction connectCode(err: unknown): number | undefined {\n\tif (typeof err !== \"object\" || err === null) return undefined;\n\tconst code = (err as { code?: unknown }).code;\n\treturn typeof code === \"number\" ? code : undefined;\n}\n\n/** Whether an RPC failure is a Connect permission denial. Callers that probe\n * for authority (a denial means \"not an authority\", not \"broken\") branch on\n * this instead of re-implementing the structural code check. */\nexport function isPermissionDenied(err: unknown): boolean {\n\treturn connectCode(err) === CODE_PERMISSION_DENIED;\n}\n\n/**\n * Whether an RPC failure is \"try again in a moment\" rather than a verdict.\n *\n * The server refuses a status change, and a behavior-filtered listing, with\n * Unavailable while statushub cannot be reached (statushub integration\n * standard §6, knkCS/mediahub#120) — the one code that means the same request,\n * unchanged, will work once the service answers again. mediahub being\n * unreachable itself arrives as the same code and means the same thing to the\n * reader, so the two are deliberately not told apart.\n */\nexport function isRetryableUnavailable(err: unknown): boolean {\n\treturn connectCode(err) === CODE_UNAVAILABLE;\n}\n\nfunction isLeakGuardDetailType(type: unknown): boolean {\n\treturn (\n\t\ttypeof type === \"string\" &&\n\t\t(type === LEAK_GUARD_DETAIL_TYPE ||\n\t\t\ttype.endsWith(`/${LEAK_GUARD_DETAIL_TYPE}`))\n\t);\n}\n\ninterface LeakGuardViolation {\n\trule?: string;\n\texposures: LeakGuardExposure[];\n}\n\nfunction asExposure(raw: unknown): LeakGuardExposure {\n\tconst r = (raw ?? {}) as Record<string, unknown>;\n\tconst str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n\treturn {\n\t\tassetId: str(r.assetId),\n\t\tassetName: str(r.assetName),\n\t\tcollectionId: str(r.collectionId),\n\t\tcollectionName: str(r.collectionName),\n\t};\n}\n\n/** Reads the violation from a detail's protoJSON `debug` (or from a decoded\n * message carrying `$typeName`). `rule` stays a protoJSON enum name. */\nfunction violationFrom(raw: unknown): LeakGuardViolation {\n\tif (typeof raw !== \"object\" || raw === null) return { exposures: [] };\n\tconst v = raw as Record<string, unknown>;\n\tconst exposures = Array.isArray(v.exposures)\n\t\t? v.exposures.map(asExposure)\n\t\t: [];\n\treturn { rule: typeof v.rule === \"string\" ? v.rule : undefined, exposures };\n}\n\nfunction findLeakGuardViolation(err: unknown): LeakGuardViolation | undefined {\n\tconst details = (err as { details?: unknown }).details;\n\tif (!Array.isArray(details)) return undefined;\n\tfor (const d of details) {\n\t\tif (typeof d !== \"object\" || d === null) continue;\n\t\tconst entry = d as Record<string, unknown>;\n\t\t// Wire shape from the Connect JSON protocol: { type, value, debug? }.\n\t\tif (isLeakGuardDetailType(entry.type)) {\n\t\t\treturn violationFrom(entry.debug);\n\t\t}\n\t\t// Already-decoded message (e.g. via findDetails with a registry).\n\t\tif (isLeakGuardDetailType(entry.$typeName)) {\n\t\t\treturn violationFrom(entry);\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Describes an RPC failure for the user. Permission denials and leak-guard\n * conflicts get mapped copy (never the raw server string); anything else\n * keeps the server's message under the caller's title, matching the previous\n * toast behavior.\n */\nexport function describeRpcError(\n\terr: unknown,\n\tfallbackTitle: string,\n): RpcErrorDescription {\n\tconst code = connectCode(err);\n\n\tif (code === CODE_PERMISSION_DENIED) {\n\t\treturn {\n\t\t\tkind: \"permission-denied\",\n\t\t\ttitle: PERMISSION_DENIED_TITLE,\n\t\t\tdescription: PERMISSION_DENIED_BODY,\n\t\t};\n\t}\n\n\tif (code === CODE_FAILED_PRECONDITION) {\n\t\tconst violation = findLeakGuardViolation(err);\n\t\tif (violation) {\n\t\t\tconst rule =\n\t\t\t\t(violation.rule && LEAK_GUARD_RULES[violation.rule]) ??\n\t\t\t\tLEAK_GUARD_GENERIC;\n\t\t\t// Single-line join: toast descriptions render as HTML text, where\n\t\t\t// newlines collapse to spaces.\n\t\t\tconst items = violation.exposures\n\t\t\t\t.map((e) => `${e.assetName} — in collection “${e.collectionName}”`)\n\t\t\t\t.join(\" • \");\n\t\t\treturn {\n\t\t\t\tkind: \"leak-guard\",\n\t\t\t\ttitle: LEAK_GUARD_TITLE,\n\t\t\t\tdescription: items ? `${rule} Involved: ${items}` : rule,\n\t\t\t\texposures: violation.exposures,\n\t\t\t\truleText: rule,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn {\n\t\tkind: \"other\",\n\t\ttitle: fallbackTitle,\n\t\tdescription:\n\t\t\terr instanceof Error ? err.message : \"An unexpected error occurred\",\n\t};\n}\n\n/**\n * The app-wide error toast: maps the failure with describeRpcError and shows\n * it. `fallbackTitle` is used only for errors outside the two mapped\n * families, preserving each call site's existing title.\n */\nexport function showRpcErrorToast(err: unknown, fallbackTitle: string): void {\n\tconst d = describeRpcError(err, fallbackTitle);\n\ttoaster.error({ title: d.title, description: d.description });\n}\n","/**\n * Convert a display name into a slug mediahub accepts: lowercase alphanumeric\n * with hyphens.\n *\n * Non-ASCII is a separator, not transliterated — \"Bürgerdaten\" becomes\n * \"b-rgerdaten\" — because the server's rule is the ASCII one and a\n * transliteration would produce a slug the user never saw derived.\n *\n * Both hosts carried their own copy of this (knkCS/mediahub#137); the package\n * owns it now so the asset-type screens share one derivation.\n */\nexport function slugify(name: string): string {\n\treturn name\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.replace(/-{2,}/g, \"-\");\n}\n","/**\n * A comma-separated MIME type field, both directions: the asset-type create and\n * detail screens edit `AssetTypeInfo.allowedMimeTypes` (a `string[]`) as one\n * plain-text input, so both parse the same way back into the array the mutation\n * sends.\n */\nexport const parseMimeTypeList = (value: string): string[] =>\n\tvalue\n\t\t.split(\",\")\n\t\t.map((v) => v.trim())\n\t\t.filter(Boolean);\n\n/**\n * Takes `string[] | undefined` although `AssetTypeInfo.allowedMimeTypes` is\n * declared `string[]`, because a host client may return the wire object\n * unmapped under that type. Connect omits an empty repeated field from the\n * JSON, so an asset type with no MIME types arrives without the key at all and\n * the declared type is a lie. The package's own client maps through\n * `mapAssetType`, which defaults it; core's did not, and the detail page went\n * down on \"Cannot read properties of undefined (reading 'join')\"\n * (knkcms/core#863). Tolerating the absent list here is the fix, kept in one\n * place for every host.\n */\nexport const formatMimeTypeList = (value: string[] | undefined): string =>\n\t(value ?? []).join(\", \");\n","// Structural shapes of the generated Connect service clients we depend on —\n// defined here rather than imported from web/src/gen so this package keeps\n// ZERO @connectrpc/proto peerDeps (odon pattern). Hosts pass their generated\n// clients (createClient(Service, transport)) which satisfy these structurally.\nimport type {\n\tAIConnectionClient,\n\tAIProcessClient,\n\tAssetClient,\n\tAssetTypeClient,\n\tAuthzClient,\n\tCollectionClient,\n\tDashboardClient,\n\tDirectoryClient,\n\tFolderClient,\n\tGrantClient,\n\tMediahubClients,\n\tTagClient,\n} from \"./clients\";\nimport { isPermissionDenied } from \"./lib/rpc-errors\";\nimport type {\n\tAIConnectionInfo,\n\tAIProcessInfo,\n\tAIProcessRunInfo,\n\tAssetInfo,\n\tAssetTypeInfo,\n\tAssetVersionInfo,\n\tCollectionInfo,\n\tCollectionType,\n\tFolderInfo,\n\tGrantEntry,\n\tGrantLevel,\n\tGrantResourceType,\n\tTagInfo,\n\tUserInfo,\n\tWorkspaceStats,\n} from \"./types\";\n\ntype Ts = { seconds: bigint; nanos: number } | undefined;\nconst mapTs = (t: Ts): Date | undefined =>\n\tt\n\t\t? new Date(Number(t.seconds) * 1000 + Math.floor(t.nanos / 1e6))\n\t\t: undefined;\n\nconst COLLTYPE_TO_NUM: Record<CollectionType, number> = {\n\tunspecified: 0,\n\tstatic: 1,\n\tsmart: 2,\n};\nconst NUM_TO_COLLTYPE: CollectionType[] = [\"unspecified\", \"static\", \"smart\"];\n\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapVersion = (v: any): AssetVersionInfo => ({\n\tid: v.id,\n\tversionNumber: v.versionNumber,\n\toriginalFilename: v.originalFilename,\n\tstorageKey: v.storageKey,\n\tfileSize: Number(v.fileSize),\n\tmimeType: v.mimeType,\n\tcreatedBy: v.createdBy,\n\tcomment: v.comment,\n\tcreatedAt: mapTs(v.createdAt),\n});\n/** Wire → domain: metadata travels as a JSON document (see asset.proto).\n * Malformed input degrades to {} — reads must never throw. */\nfunction parseAssetMetadata(raw: string | undefined): Record<string, unknown> {\n\tif (!raw) return {};\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\treturn typeof parsed === \"object\" &&\n\t\t\tparsed !== null &&\n\t\t\t!Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAsset = (a: any): AssetInfo => ({\n\tid: a.id,\n\tworkspaceId: a.workspaceId,\n\tname: a.name,\n\tdescription: a.description,\n\tstatusSlug: a.statusSlug ?? \"\",\n\tcurrentVersion: a.currentVersion,\n\tmetadata: parseAssetMetadata(a.metadata),\n\tassetTypeId: a.assetTypeId,\n\tfolderId: a.folderId,\n\tcreatedBy: a.createdBy,\n\tupdatedBy: a.updatedBy,\n\tcreatedAt: mapTs(a.createdAt),\n\tupdatedAt: mapTs(a.updatedAt),\n\tversions: (a.versions ?? []).map(mapVersion),\n\ttagIds: a.tagIds ?? [],\n\tcollectionIds: a.collectionIds ?? [],\n\tanalyzeWithAi: a.analyzeWithAi ?? false,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapFolder = (f: any): FolderInfo => ({\n\tid: f.id,\n\tworkspaceId: f.workspaceId,\n\tname: f.name,\n\tslug: f.slug,\n\tparentId: f.parentId,\n\trestricted: f.restricted ?? false,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapCollection = (c: any): CollectionInfo => ({\n\tid: c.id,\n\tworkspaceId: c.workspaceId,\n\tname: c.name,\n\tslug: c.slug,\n\tdescription: c.description,\n\ttype: NUM_TO_COLLTYPE[c.type] ?? \"unspecified\",\n\trules: c.rules,\n\trestricted: c.restricted ?? false,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapTag = (t: any): TagInfo => ({\n\tid: t.id,\n\tworkspaceId: t.workspaceId,\n\tname: t.name,\n\tslug: t.slug,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAssetType = (t: any): AssetTypeInfo => ({\n\tid: t.id,\n\tworkspaceId: t.workspaceId,\n\tname: t.name,\n\tslug: t.slug,\n\tdescription: t.description,\n\tallowedMimeTypes: t.allowedMimeTypes ?? [],\n\tmetadataSchema: t.metadataSchema,\n\tactive: t.active,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAIConnection = (c: any): AIConnectionInfo => ({\n\tid: c.id,\n\tworkspaceId: c.workspaceId,\n\tname: c.name,\n\tprovider: c.provider,\n\tendpoint: c.endpoint ?? \"\",\n\tdeployment: c.deployment ?? \"\",\n\tapiVersion: c.apiVersion ?? \"\",\n\tbaseUrl: c.baseUrl ?? \"\",\n\tmodel: c.model ?? \"\",\n\tdescription: c.description ?? \"\",\n\tactive: c.active,\n\thasApiKey: c.hasApiKey,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAIProcess = (p: any): AIProcessInfo => ({\n\tid: p.id,\n\tworkspaceId: p.workspaceId,\n\tassetTypeId: p.assetTypeId,\n\tconnectionId: p.connectionId,\n\tname: p.name,\n\tprompt: p.prompt,\n\toutputs: (p.outputs ?? []).map(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\t\t(o: any) => ({\n\t\t\tkey: o.key,\n\t\t\ttarget: o.target,\n\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t}),\n\t),\n\tposition: p.position ?? 0,\n\tactive: p.active,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAIProcessRun = (r: any): AIProcessRunInfo => ({\n\tid: r.id,\n\taiProcessId: r.aiProcessId,\n\tprocessName: r.processName ?? \"\",\n\tstatus: r.status ?? \"\",\n\terror: r.error ?? \"\",\n\tstartedAt: mapTs(r.startedAt),\n\tfinishedAt: mapTs(r.finishedAt),\n});\n\n// ─── Asset ────────────────────────────────────────────────────────────────────\n\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\ntype ProtoResponse = { [key: string]: any };\n\nexport interface ConnectAssetServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tlistAssets(req: any): Promise<{\n\t\tassets: ProtoResponse[];\n\t\tpagination?: {\n\t\t\ttotal: number;\n\t\t\tpage: number;\n\t\t\tpageSize: number;\n\t\t\ttotalPages: number;\n\t\t};\n\t}>;\n\tgetAsset(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAsset(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAsset(req: any): Promise<ProtoResponse>;\n\tdeleteAsset(req: { id: string }): Promise<unknown>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tgetUploadURL(req: any): Promise<{ uploadUrl: string; versionId: string }>;\n\tfinalizeUpload(req: { versionId: string }): Promise<ProtoResponse>;\n\tgetDownloadURL(req: { assetId: string; versionId: string }): Promise<{\n\t\tdownloadUrl: string;\n\t}>;\n\tmoveAsset(req: { id: string; folderId: string }): Promise<ProtoResponse>;\n\ttransitionAssetStatus(req: {\n\t\tid: string;\n\t\tfromStatusSlug: string;\n\t\ttoStatusSlug: string;\n\t}): Promise<ProtoResponse>;\n\tenhanceAssetMetadata(req: { assetId: string }): Promise<ProtoResponse>;\n\tlistAIProcessRuns(req: { assetId: string }): Promise<{\n\t\truns: ProtoResponse[];\n\t}>;\n}\n\nexport function createConnectAssetClient(\n\tc: ConnectAssetServiceClient,\n): AssetClient {\n\treturn {\n\t\tasync list(workspaceId, f) {\n\t\t\tconst res = await c.listAssets({\n\t\t\t\tworkspaceId,\n\t\t\t\tfolderId: f.folderId ?? \"\",\n\t\t\t\tassetTypeId: f.assetTypeId ?? \"\",\n\t\t\t\tstatusSlug: f.statusSlug ?? \"\",\n\t\t\t\tsearch: f.search ?? \"\",\n\t\t\t\tbehavior: f.behavior && f.behavior !== \"unspecified\" ? f.behavior : \"\",\n\t\t\t\ttagIds: f.tagIds ?? [],\n\t\t\t\tcollectionIds: f.collectionIds ?? [],\n\t\t\t});\n\t\t\tconst p = res.pagination;\n\t\t\treturn {\n\t\t\t\titems: res.assets.map(mapAsset),\n\t\t\t\ttotal: p?.total ?? res.assets.length,\n\t\t\t\tpage: p?.page ?? 1,\n\t\t\t\tpageSize: p?.pageSize ?? res.assets.length,\n\t\t\t\ttotalPages: p?.totalPages ?? 1,\n\t\t\t};\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAsset((await c.getAsset({ id })).asset);\n\t\t},\n\t\tasync create(workspaceId, params) {\n\t\t\treturn mapAsset(\n\t\t\t\t(\n\t\t\t\t\tawait c.createAsset({\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tdescription: params.description ?? \"\",\n\t\t\t\t\t\tassetTypeId: params.assetTypeId,\n\t\t\t\t\t\tfolderId: params.folderId ?? \"\",\n\t\t\t\t\t\tmetadata: JSON.stringify(params.metadata ?? {}),\n\t\t\t\t\t\tanalyzeWithAi: params.analyzeWithAi,\n\t\t\t\t\t})\n\t\t\t\t).asset,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapAsset(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAsset({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tdescription: patch.description ?? \"\",\n\t\t\t\t\t\tmetadata: JSON.stringify(patch.metadata ?? {}),\n\t\t\t\t\t})\n\t\t\t\t).asset,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAsset({ id });\n\t\t},\n\t\tasync getUploadUrl(p) {\n\t\t\tconst r = await c.getUploadURL({\n\t\t\t\tassetId: p.assetId,\n\t\t\t\tfilename: p.filename,\n\t\t\t\tcontentType: p.contentType,\n\t\t\t\tfileSize: BigInt(p.fileSize),\n\t\t\t\tcomment: p.comment ?? \"\",\n\t\t\t});\n\t\t\treturn { uploadUrl: r.uploadUrl, versionId: r.versionId };\n\t\t},\n\t\tasync finalizeUpload(versionId) {\n\t\t\treturn mapAsset((await c.finalizeUpload({ versionId })).asset);\n\t\t},\n\t\tasync getDownloadUrl(assetId, versionId) {\n\t\t\treturn (await c.getDownloadURL({ assetId, versionId })).downloadUrl;\n\t\t},\n\t\tasync move(id, folderId) {\n\t\t\treturn mapAsset((await c.moveAsset({ id, folderId })).asset);\n\t\t},\n\t\tasync transitionStatus(id, fromStatusSlug, toStatusSlug) {\n\t\t\treturn mapAsset(\n\t\t\t\t(await c.transitionAssetStatus({ id, fromStatusSlug, toStatusSlug }))\n\t\t\t\t\t.asset,\n\t\t\t);\n\t\t},\n\t\tasync enhanceMetadata(id) {\n\t\t\treturn mapAsset((await c.enhanceAssetMetadata({ assetId: id })).asset);\n\t\t},\n\t\tasync listProcessRuns(assetId) {\n\t\t\tconst res = await c.listAIProcessRuns({ assetId });\n\t\t\treturn res.runs.map(mapAIProcessRun);\n\t\t},\n\t};\n}\n\n// ─── Folder ───────────────────────────────────────────────────────────────────\n\nexport interface ConnectFolderServiceClient {\n\tlistFolders(req: { workspaceId: string; parentId: string }): Promise<{\n\t\tfolders: ProtoResponse[];\n\t}>;\n\tgetFolder(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateFolder(req: any): Promise<ProtoResponse>;\n\tupdateFolder(req: { id: string; name: string }): Promise<ProtoResponse>;\n\tdeleteFolder(req: { id: string }): Promise<unknown>;\n\tmoveFolder(req: { id: string; parentId: string }): Promise<ProtoResponse>;\n\t/** Restricted toggles — land with guardian#53; optional so the package\n\t * keeps accepting pre-#53 generated clients. */\n\trestrictFolder?(req: { id: string }): Promise<ProtoResponse>;\n\tunrestrictFolder?(req: { id: string }): Promise<ProtoResponse>;\n}\n\nexport function createConnectFolderClient(\n\tc: ConnectFolderServiceClient,\n): FolderClient {\n\treturn {\n\t\tasync list(workspaceId, parentId) {\n\t\t\tconst res = await c.listFolders({ workspaceId, parentId });\n\t\t\treturn res.folders.map(mapFolder);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapFolder((await c.getFolder({ id })).folder);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapFolder(\n\t\t\t\t(\n\t\t\t\t\tawait c.createFolder({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t\tparentId: params.parentId,\n\t\t\t\t\t\trestricted: params.restricted ?? false,\n\t\t\t\t\t})\n\t\t\t\t).folder,\n\t\t\t);\n\t\t},\n\t\tasync update(id, name) {\n\t\t\treturn mapFolder((await c.updateFolder({ id, name })).folder);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteFolder({ id });\n\t\t},\n\t\tasync move(id, parentId) {\n\t\t\treturn mapFolder((await c.moveFolder({ id, parentId })).folder);\n\t\t},\n\t\tasync setRestricted(id, restricted) {\n\t\t\tconst call = restricted ? c.restrictFolder : c.unrestrictFolder;\n\t\t\tif (typeof call !== \"function\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"This server can't toggle Restricted yet (RestrictFolder/UnrestrictFolder, guardian#53).\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn mapFolder((await call({ id })).folder);\n\t\t},\n\t};\n}\n\n// ─── Collection ───────────────────────────────────────────────────────────────\n\nexport interface ConnectCollectionServiceClient {\n\tlistCollections(req: { workspaceId: string }): Promise<{\n\t\tcollections: ProtoResponse[];\n\t}>;\n\tgetCollection(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateCollection(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateCollection(req: any): Promise<ProtoResponse>;\n\tdeleteCollection(req: { id: string }): Promise<unknown>;\n\taddAssets(req: {\n\t\tcollectionId: string;\n\t\tassetIds: string[];\n\t}): Promise<unknown>;\n\tremoveAssets(req: {\n\t\tcollectionId: string;\n\t\tassetIds: string[];\n\t}): Promise<unknown>;\n\t/** Restricted toggles — land with guardian#53; optional so the package\n\t * keeps accepting pre-#53 generated clients. */\n\trestrictCollection?(req: { id: string }): Promise<ProtoResponse>;\n\tunrestrictCollection?(req: { id: string }): Promise<ProtoResponse>;\n}\n\nexport function createConnectCollectionClient(\n\tc: ConnectCollectionServiceClient,\n): CollectionClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\tconst res = await c.listCollections({ workspaceId });\n\t\t\treturn res.collections.map(mapCollection);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapCollection((await c.getCollection({ id })).collection);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapCollection(\n\t\t\t\t(\n\t\t\t\t\tawait c.createCollection({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t\tdescription: params.description,\n\t\t\t\t\t\ttype: COLLTYPE_TO_NUM[params.type],\n\t\t\t\t\t\trules: params.rules,\n\t\t\t\t\t\trestricted: params.restricted ?? false,\n\t\t\t\t\t})\n\t\t\t\t).collection,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapCollection(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateCollection({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tdescription: patch.description ?? \"\",\n\t\t\t\t\t\trules: patch.rules ?? \"\",\n\t\t\t\t\t})\n\t\t\t\t).collection,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteCollection({ id });\n\t\t},\n\t\tasync addAssets(collectionId, assetIds) {\n\t\t\tawait c.addAssets({ collectionId, assetIds });\n\t\t},\n\t\tasync removeAssets(collectionId, assetIds) {\n\t\t\tawait c.removeAssets({ collectionId, assetIds });\n\t\t},\n\t\tasync setRestricted(id, restricted) {\n\t\t\tconst call = restricted ? c.restrictCollection : c.unrestrictCollection;\n\t\t\tif (typeof call !== \"function\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"This server can't toggle Restricted yet (RestrictCollection/UnrestrictCollection, guardian#53).\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn mapCollection((await call({ id })).collection);\n\t\t},\n\t};\n}\n\n// ─── Tag ──────────────────────────────────────────────────────────────────────\n\nexport interface ConnectTagServiceClient {\n\tlistTags(req: { workspaceId: string }): Promise<{ tags: ProtoResponse[] }>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateTag(req: any): Promise<ProtoResponse>;\n\tupdateTag(req: { id: string; name: string }): Promise<ProtoResponse>;\n\tdeleteTag(req: { id: string }): Promise<unknown>;\n\ttagAssets(req: { tagId: string; assetIds: string[] }): Promise<unknown>;\n\tuntagAssets(req: { tagId: string; assetIds: string[] }): Promise<unknown>;\n}\n\nexport function createConnectTagClient(c: ConnectTagServiceClient): TagClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\tconst res = await c.listTags({ workspaceId });\n\t\t\treturn res.tags.map(mapTag);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapTag(\n\t\t\t\t(\n\t\t\t\t\tawait c.createTag({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t})\n\t\t\t\t).tag,\n\t\t\t);\n\t\t},\n\t\tasync update(id, name) {\n\t\t\treturn mapTag((await c.updateTag({ id, name })).tag);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteTag({ id });\n\t\t},\n\t\tasync tagAssets(tagId, assetIds) {\n\t\t\tawait c.tagAssets({ tagId, assetIds });\n\t\t},\n\t\tasync untagAssets(tagId, assetIds) {\n\t\t\tawait c.untagAssets({ tagId, assetIds });\n\t\t},\n\t};\n}\n\n// ─── Asset Type ───────────────────────────────────────────────────────────────\n\nexport interface ConnectAssetTypeServiceClient {\n\tlistAssetTypes(req: { workspaceId: string }): Promise<{\n\t\tassetTypes: ProtoResponse[];\n\t}>;\n\tgetAssetType(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAssetType(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAssetType(req: any): Promise<ProtoResponse>;\n\tdeleteAssetType(req: { id: string }): Promise<unknown>;\n}\n\nexport function createConnectAssetTypeClient(\n\tc: ConnectAssetTypeServiceClient,\n): AssetTypeClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\tconst res = await c.listAssetTypes({ workspaceId });\n\t\t\treturn res.assetTypes.map(mapAssetType);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAssetType((await c.getAssetType({ id })).assetType);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapAssetType(\n\t\t\t\t(\n\t\t\t\t\tawait c.createAssetType({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t\tdescription: params.description,\n\t\t\t\t\t\tallowedMimeTypes: params.allowedMimeTypes,\n\t\t\t\t\t\tmetadataSchema: params.metadataSchema,\n\t\t\t\t\t})\n\t\t\t\t).assetType,\n\t\t\t);\n\t\t},\n\t\t/**\n\t\t * Read-modify-write: `UpdateAssetTypeRequest` carries plain proto3\n\t\t * scalars — no `optional`, no field mask — so the server cannot tell\n\t\t * \"not supplied\" from \"set to empty\", and its handler passes every\n\t\t * field through. Sending a patch alone therefore wipes `description`\n\t\t * and `allowedMimeTypes` and re-activates a deactivated type\n\t\t * (knkCS/mediahub#159; the `bool` half is the trap of\n\t\t * knkcms/core#863/#864). So fetch the current record and send the\n\t\t * union.\n\t\t *\n\t\t * Supplied-ness is the presence of the KEY, not truthiness: an\n\t\t * explicit `\"\"`/`[]`/`false` is a deliberate clear and is applied,\n\t\t * while an absent key — or one present but `undefined`, which cannot\n\t\t * travel on the wire anyway — keeps the current value.\n\t\t *\n\t\t * This opens a read-modify-write window; concurrent edits are last\n\t\t * writer wins, as core's now-deleted client also was.\n\t\t */\n\t\tasync update(id, patch) {\n\t\t\tconst cur = mapAssetType((await c.getAssetType({ id })).assetType);\n\t\t\tconst merged = <K extends keyof typeof patch>(\n\t\t\t\tkey: K,\n\t\t\t\tfallback: NonNullable<(typeof patch)[K]>,\n\t\t\t): NonNullable<(typeof patch)[K]> =>\n\t\t\t\tkey in patch && patch[key] !== undefined\n\t\t\t\t\t? (patch[key] as NonNullable<(typeof patch)[K]>)\n\t\t\t\t\t: fallback;\n\t\t\treturn mapAssetType(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAssetType({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: merged(\"name\", cur.name ?? \"\"),\n\t\t\t\t\t\tdescription: merged(\"description\", cur.description ?? \"\"),\n\t\t\t\t\t\tallowedMimeTypes: merged(\n\t\t\t\t\t\t\t\"allowedMimeTypes\",\n\t\t\t\t\t\t\tcur.allowedMimeTypes ?? [],\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmetadataSchema: merged(\"metadataSchema\", cur.metadataSchema ?? \"\"),\n\t\t\t\t\t\tactive: merged(\"active\", cur.active ?? false),\n\t\t\t\t\t})\n\t\t\t\t).assetType,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAssetType({ id });\n\t\t},\n\t};\n}\n\n// ─── User / Directory ─────────────────────────────────────────────────────────\n\nexport interface ConnectUserServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tresolveUsers(req: { userIds: string[] }): Promise<{ users: any[] }>;\n\tlistWorkspaceMembers(req: {\n\t\tworkspaceId: string;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\t}): Promise<{ members: any[] }>;\n}\n\nexport function createConnectDirectoryClient(\n\tc: ConnectUserServiceClient,\n): DirectoryClient {\n\treturn {\n\t\tasync resolveUsers(ids) {\n\t\t\tconst res = await c.resolveUsers({ userIds: ids });\n\t\t\t// The wire type is any-erased at the client boundary (interface\n\t\t\t// above); type the two fields we actually consume.\n\t\t\treturn (res.users ?? []).map(\n\t\t\t\t(u: { id: string; displayName: string }): UserInfo => ({\n\t\t\t\t\tid: u.id,\n\t\t\t\t\tdisplayName: u.displayName,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\tasync listWorkspaceMembers(workspaceId) {\n\t\t\tconst res = await c.listWorkspaceMembers({ workspaceId });\n\t\t\treturn (res.members ?? []).map(\n\t\t\t\t(m: { userId: string; displayName: string }): UserInfo => ({\n\t\t\t\t\tid: m.userId,\n\t\t\t\t\tdisplayName: m.displayName,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t};\n}\n\n// ─── Grants ───────────────────────────────────────────────────────────────────\n\nconst GRANT_RESOURCE_TO_NUM: Record<GrantResourceType, number> = {\n\tasset: 1,\n\tfolder: 2,\n\tcollection: 3,\n};\n/** Wire → domain levels; anything unknown maps to undefined and is dropped\n * rather than invented (same distrust as the service's tuple reads). */\nconst NUM_TO_GRANT_LEVEL: Record<number, GrantLevel | undefined> = {\n\t1: \"viewer\",\n\t2: \"editor\",\n};\nconst GRANT_LEVEL_TO_NUM: Record<GrantLevel, number> = {\n\tviewer: 1,\n\teditor: 2,\n};\n\nexport interface ConnectGrantServiceClient {\n\tgrantAccess(req: {\n\t\tresourceType: number;\n\t\tresourceId: string;\n\t\tuserId: string;\n\t\tlevel: number;\n\t}): Promise<unknown>;\n\trevokeAccess(req: {\n\t\tresourceType: number;\n\t\tresourceId: string;\n\t\tuserId: string;\n\t}): Promise<unknown>;\n\tlistGrants(req: { resourceType: number; resourceId: string }): Promise<{\n\t\townerUserId: string;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\t\tgrants: any[];\n\t}>;\n}\n\nexport function createConnectGrantClient(\n\tc: ConnectGrantServiceClient,\n): GrantClient {\n\treturn {\n\t\tasync list(resourceType, resourceId) {\n\t\t\tconst res = await c.listGrants({\n\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\tresourceId,\n\t\t\t});\n\t\t\tconst grants: GrantEntry[] = [];\n\t\t\tfor (const g of res.grants ?? []) {\n\t\t\t\tconst level = NUM_TO_GRANT_LEVEL[g.level as number];\n\t\t\t\tif (level) grants.push({ userId: g.userId as string, level });\n\t\t\t}\n\t\t\treturn { ownerUserId: res.ownerUserId ?? \"\", grants };\n\t\t},\n\t\tasync grant(resourceType, resourceId, userId, level) {\n\t\t\tawait c.grantAccess({\n\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t\tlevel: GRANT_LEVEL_TO_NUM[level],\n\t\t\t});\n\t\t},\n\t\tasync revoke(resourceType, resourceId, userId) {\n\t\t\tawait c.revokeAccess({\n\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t});\n\t\t},\n\t};\n}\n\n/**\n * Authority probe (guardian#55): GrantService gates every call — ListGrants\n * included — on exactly the toggle/grant authority (Owner of the resource or\n * admin of its workspace, mediahub ADR-0001), so a roster read doubles as the\n * check. A denial means \"not an authority\"; other failures reject unchanged.\n */\nexport function createConnectAuthzClient(\n\tc: ConnectGrantServiceClient,\n): AuthzClient {\n\treturn {\n\t\tasync canManage(resourceType, resourceId) {\n\t\t\ttry {\n\t\t\t\tawait c.listGrants({\n\t\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\t\tresourceId,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t} catch (err) {\n\t\t\t\tif (isPermissionDenied(err)) return false;\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// ─── Dashboard ────────────────────────────────────────────────────────────────\n\nexport interface ConnectDashboardServiceClient {\n\tgetWorkspaceStats(req: { workspaceId: string }): Promise<{\n\t\ttotalAssets: bigint;\n\t\ttotalStorageBytes: bigint;\n\t\tstatusCounts: Array<{\n\t\t\tstatusSlug: string;\n\t\t\tname: string;\n\t\t\tcolor: string;\n\t\t\tbehavior: string;\n\t\t\tcount: bigint;\n\t\t}>;\n\t\trecentUploads: Array<{\n\t\t\tid: string;\n\t\t\tname: string;\n\t\t\tassetTypeName: string;\n\t\t\tstatusName: string;\n\t\t\tstatusColor: string;\n\t\t\tcreatedAt?: { seconds: bigint; nanos: number } | undefined;\n\t\t}>;\n\t}>;\n\tgetDashboardLayout(req: { workspaceId: string }): Promise<{\n\t\tlayoutJson: string;\n\t}>;\n\tsaveDashboardLayout(req: {\n\t\tworkspaceId: string;\n\t\tlayoutJson: string;\n\t}): Promise<unknown>;\n}\n\nexport function createConnectDashboardClient(\n\tc: ConnectDashboardServiceClient,\n): DashboardClient {\n\treturn {\n\t\tasync getWorkspaceStats(workspaceId): Promise<WorkspaceStats> {\n\t\t\tconst res = await c.getWorkspaceStats({ workspaceId });\n\t\t\treturn {\n\t\t\t\ttotalAssets: Number(res.totalAssets),\n\t\t\t\ttotalStorageBytes: Number(res.totalStorageBytes),\n\t\t\t\tstatusCounts: res.statusCounts.map((s) => ({\n\t\t\t\t\tstatusSlug: s.statusSlug,\n\t\t\t\t\tname: s.name,\n\t\t\t\t\tcolor: s.color,\n\t\t\t\t\tbehavior: s.behavior,\n\t\t\t\t\tcount: Number(s.count),\n\t\t\t\t})),\n\t\t\t\trecentUploads: res.recentUploads.map((r) => ({\n\t\t\t\t\tid: r.id,\n\t\t\t\t\tname: r.name,\n\t\t\t\t\tassetTypeName: r.assetTypeName,\n\t\t\t\t\tstatusName: r.statusName,\n\t\t\t\t\tstatusColor: r.statusColor,\n\t\t\t\t\tcreatedAt: mapTs(r.createdAt),\n\t\t\t\t})),\n\t\t\t};\n\t\t},\n\t\tasync getDashboardLayout(workspaceId) {\n\t\t\tconst res = await c.getDashboardLayout({ workspaceId });\n\t\t\treturn res.layoutJson;\n\t\t},\n\t\tasync saveDashboardLayout(workspaceId, layoutJson) {\n\t\t\tawait c.saveDashboardLayout({ workspaceId, layoutJson });\n\t\t},\n\t};\n}\n\n// ─── AI Connection ────────────────────────────────────────────────────────────\n\nexport interface ConnectAIConnectionServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tlistAIConnections(req: any): Promise<{ connections: ProtoResponse[] }>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tgetAIConnection(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAIConnection(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAIConnection(req: any): Promise<ProtoResponse>;\n\tdeleteAIConnection(req: { id: string }): Promise<unknown>;\n}\n\nexport function createConnectAIConnectionClient(\n\tc: ConnectAIConnectionServiceClient,\n): AIConnectionClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\treturn (\n\t\t\t\tawait c.listAIConnections({\n\t\t\t\t\tworkspaceId,\n\t\t\t\t\tpagination: { page: 1, pageSize: 1000 },\n\t\t\t\t})\n\t\t\t).connections.map(mapAIConnection);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAIConnection((await c.getAIConnection({ id })).connection);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapAIConnection(\n\t\t\t\t(await c.createAIConnection({ ...params })).connection,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapAIConnection(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAIConnection({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tendpoint: patch.endpoint ?? \"\",\n\t\t\t\t\t\tdeployment: patch.deployment ?? \"\",\n\t\t\t\t\t\tapiVersion: patch.apiVersion ?? \"\",\n\t\t\t\t\t\tbaseUrl: patch.baseUrl ?? \"\",\n\t\t\t\t\t\tmodel: patch.model ?? \"\",\n\t\t\t\t\t\tapiKey: patch.apiKey ?? \"\",\n\t\t\t\t\t\tdescription: patch.description ?? \"\",\n\t\t\t\t\t\tactive: patch.active ?? true,\n\t\t\t\t\t})\n\t\t\t\t).connection,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAIConnection({ id });\n\t\t},\n\t};\n}\n\n// ─── AI Process ───────────────────────────────────────────────────────────────\n\nexport interface ConnectAIProcessServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tlistAIProcesses(req: any): Promise<{ processes: ProtoResponse[] }>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tgetAIProcess(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAIProcess(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAIProcess(req: any): Promise<ProtoResponse>;\n\tdeleteAIProcess(req: { id: string }): Promise<unknown>;\n}\n\nexport function createConnectAIProcessClient(\n\tc: ConnectAIProcessServiceClient,\n): AIProcessClient {\n\treturn {\n\t\tasync list(assetTypeId) {\n\t\t\treturn (await c.listAIProcesses({ assetTypeId })).processes.map(\n\t\t\t\tmapAIProcess,\n\t\t\t);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAIProcess((await c.getAIProcess({ id })).process);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapAIProcess(\n\t\t\t\t(\n\t\t\t\t\tawait c.createAIProcess({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tassetTypeId: params.assetTypeId,\n\t\t\t\t\t\tconnectionId: params.connectionId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\toutputs: params.outputs,\n\t\t\t\t\t\tposition: params.position,\n\t\t\t\t\t})\n\t\t\t\t).process,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapAIProcess(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAIProcess({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tconnectionId: patch.connectionId ?? \"\",\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tprompt: patch.prompt ?? \"\",\n\t\t\t\t\t\toutputs: patch.outputs ?? [],\n\t\t\t\t\t\tposition: patch.position ?? 0,\n\t\t\t\t\t\tactive: patch.active ?? true,\n\t\t\t\t\t})\n\t\t\t\t).process,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAIProcess({ id });\n\t\t},\n\t};\n}\n\n// ─── Bundle ───────────────────────────────────────────────────────────────────\n\nexport function createConnectMediahubClients(gen: {\n\tasset: ConnectAssetServiceClient;\n\tfolder: ConnectFolderServiceClient;\n\tcollection: ConnectCollectionServiceClient;\n\ttag: ConnectTagServiceClient;\n\tassetType: ConnectAssetTypeServiceClient;\n\tuser: ConnectUserServiceClient;\n\tgrant: ConnectGrantServiceClient;\n\tdashboard: ConnectDashboardServiceClient;\n\taiConnection: ConnectAIConnectionServiceClient;\n\taiProcess: ConnectAIProcessServiceClient;\n}): MediahubClients {\n\treturn {\n\t\tassets: createConnectAssetClient(gen.asset),\n\t\tfolders: createConnectFolderClient(gen.folder),\n\t\tcollections: createConnectCollectionClient(gen.collection),\n\t\ttags: createConnectTagClient(gen.tag),\n\t\tassetTypes: createConnectAssetTypeClient(gen.assetType),\n\t\tdirectory: createConnectDirectoryClient(gen.user),\n\t\tgrants: createConnectGrantClient(gen.grant),\n\t\tdashboard: createConnectDashboardClient(gen.dashboard),\n\t\taiConnection: createConnectAIConnectionClient(gen.aiConnection),\n\t\taiProcess: createConnectAIProcessClient(gen.aiProcess),\n\t\tauthz: createConnectAuthzClient(gen.grant),\n\t};\n}\n","import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { MediahubClients } from \"./clients\";\n\n/** Host-app routes for the places this package can only point at, never\n * navigate to itself (it has no router dependency). Rendered as plain\n * anchors; hosts include any basename in the returned href. */\nexport interface MediahubLinks {\n\t/** Route to an asset's detail view. */\n\tassetHref?: (assetId: string) => string;\n\t/** Route to a collection's view. */\n\tcollectionHref?: (collectionId: string) => string;\n}\n\ninterface MediahubContextValue {\n\tclients: MediahubClients;\n\tworkspaceId: string;\n\tlinks: MediahubLinks;\n}\n\nconst MediahubContext = createContext<MediahubContextValue | null>(null);\n\nconst EMPTY_LINKS: MediahubLinks = {};\n\nexport interface MediahubProviderProps {\n\tclients: MediahubClients;\n\t/** Ambient workspace scope — every hook reads it. */\n\tworkspaceId: string;\n\t/** Host routes for cross-surface references (e.g. the leak-guard refusal\n\t * dialog's pair links). Omitted routes render as plain text. */\n\tlinks?: MediahubLinks;\n\tchildren: ReactNode;\n}\n\nexport function MediahubProvider({\n\tclients,\n\tworkspaceId,\n\tlinks,\n\tchildren,\n}: MediahubProviderProps) {\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tclients,\n\t\t\tworkspaceId,\n\t\t\tlinks: links ?? EMPTY_LINKS,\n\t\t}),\n\t\t[clients, workspaceId, links],\n\t);\n\treturn (\n\t\t<MediahubContext.Provider value={value}>\n\t\t\t{children}\n\t\t</MediahubContext.Provider>\n\t);\n}\nMediahubProvider.displayName = \"MediahubProvider\";\n\nfunction useMediahubContext(): MediahubContextValue {\n\tconst ctx = useContext(MediahubContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useMediahubClients/useWorkspaceId must be used within <MediahubProvider>\",\n\t\t);\n\t}\n\treturn ctx;\n}\n\nexport function useMediahubClients(): MediahubClients {\n\treturn useMediahubContext().clients;\n}\n\nexport function useWorkspaceId(): string {\n\treturn useMediahubContext().workspaceId;\n}\n\n/** Host-supplied routes. Empty object when the host didn't pass `links` to\n * `<MediahubProvider>` — consumers degrade to plain text. */\nexport function useMediahubLinks(): MediahubLinks {\n\treturn useMediahubContext().links;\n}\n","import { useStatuses } from \"@knkcs/statushub-ui\";\nimport type { StatusInfo } from \"@knkcs/statushub-ui\";\n\n/**\n * The catalogue an asset's status belongs to: mediahub's `asset` entity type,\n * as registered with statushub at startup (integration standard §1).\n *\n * Every statushub-ui component and hook this package uses is pinned to it, so\n * a host never names it and can never point a mediahub surface at another\n * service's statuses. Exported because a host's settings screen embeds\n * `StatusSettings` pinned to the same catalogue (§10) — `<StatusSettings\n * {...ASSET_STATUS_CATALOGUE} />` — and one constant is how the two cannot\n * come to disagree.\n */\nexport const ASSET_STATUS_CATALOGUE = {\n\tserviceSlug: \"mediahub\",\n\tentityTypeSlug: \"asset\",\n} as const;\n\n/** The asset catalogue's statuses in the viewer's workspace. */\nexport function useAssetStatuses() {\n\treturn useStatuses(ASSET_STATUS_CATALOGUE);\n}\n\n/**\n * The status a slug names.\n *\n * `isLoading` is reported separately on purpose: \"not answered yet\" and\n * \"answered, and this slug is not in the catalogue\" look the same in the data\n * and mean opposite things. Collapsing them makes every list paint its raw\n * slugs for one frame before the names arrive.\n *\n * Once the catalogue has answered, a missing status is an **unknown status** —\n * the slug was deleted, or statushub had never answered at birth (§5) — and\n * callers render the raw slug rather than nothing: the asset still has a\n * status, mediahub just cannot name it.\n */\nexport function useAssetStatus(slug: string): {\n\tstatus: StatusInfo | undefined;\n\tisLoading: boolean;\n} {\n\tconst { data, isLoading } = useAssetStatuses();\n\treturn {\n\t\tstatus: slug ? data?.find((s) => s.slug === slug) : undefined,\n\t\tisLoading,\n\t};\n}\n","/** Direct-to-Azure SAS upload via XHR PUT (x-ms-blob-type: BlockBlob). */\nexport async function uploadFileToSAS(\n\turl: string,\n\tfile: File,\n\tcontentType: string,\n\tonProgress: (progress: number) => void,\n): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst xhr = new XMLHttpRequest();\n\t\txhr.open(\"PUT\", url);\n\t\txhr.setRequestHeader(\"x-ms-blob-type\", \"BlockBlob\");\n\t\txhr.setRequestHeader(\"Content-Type\", contentType);\n\t\txhr.upload.onprogress = (e) => {\n\t\t\tif (e.lengthComputable) {\n\t\t\t\tonProgress(Math.round((e.loaded / e.total) * 100));\n\t\t\t}\n\t\t};\n\t\txhr.onload = () => {\n\t\t\tif (xhr.status >= 200 && xhr.status < 300) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));\n\t\t\t}\n\t\t};\n\t\txhr.onerror = () => reject(new Error(\"Network error during upload\"));\n\t\txhr.send(file);\n\t});\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useState } from \"react\";\nimport { uploadFileToSAS } from \"../lib/sas-upload\";\nimport { useMediahubClients } from \"../provider\";\n\nexport interface AddVersionVars {\n\tassetId: string;\n\tfile: File;\n\tcomment?: string;\n}\n\nexport function useAddVersion() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\tconst [progress, setProgress] = useState(0);\n\n\tconst mutation = useMutation({\n\t\tmutationFn: async ({ assetId, file, comment }: AddVersionVars) => {\n\t\t\tsetProgress(0);\n\t\t\tconst contentType = file.type || \"application/octet-stream\";\n\t\t\tconst { uploadUrl, versionId } = await assets.getUploadUrl({\n\t\t\t\tassetId,\n\t\t\t\tfilename: file.name,\n\t\t\t\tcontentType,\n\t\t\t\tfileSize: file.size,\n\t\t\t\tcomment: comment ?? \"\",\n\t\t\t});\n\t\t\tif (!uploadUrl || !versionId) {\n\t\t\t\tthrow new Error(\"getUploadUrl returned an incomplete response\");\n\t\t\t}\n\t\t\tawait uploadFileToSAS(uploadUrl, file, contentType, setProgress);\n\t\t\treturn assets.finalizeUpload(versionId);\n\t\t},\n\t\tonSuccess: (_data, vars) => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"assets\", \"detail\", vars.assetId],\n\t\t\t});\n\t\t},\n\t});\n\n\treturn { ...mutation, progress };\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { AssetFilters, CreateAssetParams } from \"../types\";\n\nexport function useAssets(filters: AssetFilters = {}) {\n\tconst { assets } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assets\", workspaceId, filters],\n\t\tqueryFn: () => assets.list(workspaceId, filters),\n\t});\n}\n\nexport function useAsset(id: string) {\n\tconst { assets } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assets\", \"detail\", id],\n\t\tqueryFn: () => assets.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (params: CreateAssetParams) =>\n\t\t\tassets.create(workspaceId, params),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useUpdateAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tname?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tmetadata?: Record<string, unknown>;\n\t\t\t};\n\t\t}) => assets.update(vars.id, vars.patch),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useDeleteAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => assets.delete(id),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useMoveAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; folderId: string }) =>\n\t\t\tassets.move(vars.id, vars.folderId),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useTransitionAssetStatus() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\t/** The slug the caller last saw — the change is made against it. */\n\t\t\tfromStatusSlug: string;\n\t\t\ttoStatusSlug: string;\n\t\t}) =>\n\t\t\tassets.transitionStatus(vars.id, vars.fromStatusSlug, vars.toStatusSlug),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useEnhanceAssetMetadata() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => assets.enhanceMetadata(id),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function usePreviewURL(assetId: string, versionId: string) {\n\tconst { assets } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assets\", \"preview-url\", assetId, versionId],\n\t\tqueryFn: () => assets.getDownloadUrl(assetId, versionId),\n\t\tenabled: !!assetId && !!versionId,\n\t\tstaleTime: 15 * 60 * 1000,\n\t});\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useMediahubClients } from \"../provider\";\nimport type { GrantResourceType } from \"../types\";\n\n/**\n * Whether the current user may manage a resource — toggle its Restricted\n * flag, grant or revoke access (Owner of the resource or admin of its\n * workspace, mediahub ADR-0001). Consumers read `data === true`; a pending or\n * failed probe hides authority-only actions (fail closed).\n */\nexport function useCanManage(\n\tresourceType: GrantResourceType,\n\tresourceId: string,\n) {\n\tconst { authz } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"can-manage\", resourceType, resourceId],\n\t\tqueryFn: () => authz.canManage(resourceType, resourceId),\n\t\tenabled: !!resourceId,\n\t\t// Authority rarely changes mid-session; don't re-probe on every menu open.\n\t\tstaleTime: 5 * 60_000,\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useFolders(parentId = \"\", opts?: { enabled?: boolean }) {\n\tconst { folders } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"folders\", workspaceId, parentId],\n\t\tqueryFn: () => folders.list(workspaceId, parentId),\n\t\tenabled: opts?.enabled ?? true,\n\t});\n}\n\nexport function useFolder(id: string) {\n\tconst { folders } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"folder\", id],\n\t\tqueryFn: () => folders.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tslug: string;\n\t\t\tparentId: string;\n\t\t\trestricted?: boolean;\n\t\t}) => folders.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] }),\n\t});\n}\n\nexport function useUpdateFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; name: string }) =>\n\t\t\tfolders.update(vars.id, vars.name),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folder\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => folders.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] }),\n\t});\n}\n\nexport function useMoveFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; parentId: string }) =>\n\t\t\tfolders.move(vars.id, vars.parentId),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folder\"] });\n\t\t},\n\t});\n}\n\nexport function useSetFolderRestricted() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; restricted: boolean }) =>\n\t\t\tfolders.setRestricted(vars.id, vars.restricted),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folder\"] });\n\t\t\t// The toggle moves the subtree in/out of the open-content counts and\n\t\t\t// unscoped listings (#49) — asset pages must refetch.\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { describeRpcError } from \"../lib/rpc-errors\";\nimport { useMediahubClients } from \"../provider\";\nimport type { GrantLevel, GrantResourceType } from \"../types\";\n\n/**\n * The roster read doubles as the sharing panel's authority gate: the server\n * answers PermissionDenied for everyone but the resource's Owner and\n * workspace admins, and that denial is a final answer — never retried.\n */\nexport function useGrants(\n\tresourceType: GrantResourceType,\n\tresourceId: string,\n\topts?: { enabled?: boolean },\n) {\n\tconst { grants } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"grants\", resourceType, resourceId],\n\t\tqueryFn: () => grants.list(resourceType, resourceId),\n\t\tenabled: opts?.enabled ?? true,\n\t\tretry: (failureCount, error) =>\n\t\t\tdescribeRpcError(error, \"\").kind !== \"permission-denied\" &&\n\t\t\tfailureCount < 3,\n\t});\n}\n\nexport function useGrantAccess() {\n\tconst { grants } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tresourceType: GrantResourceType;\n\t\t\tresourceId: string;\n\t\t\tuserId: string;\n\t\t\tlevel: GrantLevel;\n\t\t}) =>\n\t\t\tgrants.grant(vars.resourceType, vars.resourceId, vars.userId, vars.level),\n\t\t// Settled, not success: the server's upsert is delete-then-write, so a\n\t\t// mid-failure can leave the grantee revoked — the roster must re-assert\n\t\t// server truth after a failure too.\n\t\tonSettled: (_data, _err, vars) =>\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"grants\", vars.resourceType, vars.resourceId],\n\t\t\t}),\n\t});\n}\n\nexport function useRevokeAccess() {\n\tconst { grants } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tresourceType: GrantResourceType;\n\t\t\tresourceId: string;\n\t\t\tuserId: string;\n\t\t}) => grants.revoke(vars.resourceType, vars.resourceId, vars.userId),\n\t\tonSettled: (_data, _err, vars) =>\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"grants\", vars.resourceType, vars.resourceId],\n\t\t\t}),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { CollectionType } from \"../types\";\n\nexport function useCollections() {\n\tconst { collections } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"collections\", workspaceId],\n\t\tqueryFn: () => collections.list(workspaceId),\n\t});\n}\n\nexport function useCollection(id: string) {\n\tconst { collections } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"collection\", id],\n\t\tqueryFn: () => collections.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tslug: string;\n\t\t\tdescription: string;\n\t\t\ttype: CollectionType;\n\t\t\trules: string;\n\t\t\trestricted?: boolean;\n\t\t}) => collections.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] }),\n\t});\n}\n\nexport function useUpdateCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: { name?: string; description?: string; rules?: string };\n\t\t}) => collections.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => collections.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] }),\n\t});\n}\n\nexport function useAddAssetsToCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { collectionId: string; assetIds: string[] }) =>\n\t\t\tcollections.addAssets(vars.collectionId, vars.assetIds),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n\nexport function useSetCollectionRestricted() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; restricted: boolean }) =>\n\t\t\tcollections.setRestricted(vars.id, vars.restricted),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n\nexport function useRemoveAssetsFromCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { collectionId: string; assetIds: string[] }) =>\n\t\t\tcollections.removeAssets(vars.collectionId, vars.assetIds),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useTags() {\n\tconst { tags } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"tags\", workspaceId],\n\t\tqueryFn: () => tags.list(workspaceId),\n\t});\n}\n\nexport function useCreateTag() {\n\tconst { tags } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { name: string; slug: string }) =>\n\t\t\ttags.create({ workspaceId, ...vars }),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"tags\"] }),\n\t});\n}\n\nexport function useUpdateTag() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; name: string }) =>\n\t\t\ttags.update(vars.id, vars.name),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"tags\"] }),\n\t});\n}\n\nexport function useDeleteTag() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => tags.delete(id),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"tags\"] }),\n\t});\n}\n\nexport function useTagAssets() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { tagId: string; assetIds: string[] }) =>\n\t\t\ttags.tagAssets(vars.tagId, vars.assetIds),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useUntagAssets() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { tagId: string; assetIds: string[] }) =>\n\t\t\ttags.untagAssets(vars.tagId, vars.assetIds),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useAssetTypes() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assetTypes\", workspaceId],\n\t\tqueryFn: () => assetTypes.list(workspaceId),\n\t});\n}\n\nexport function useAssetType(id: string) {\n\tconst { assetTypes } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assetType\", id],\n\t\tqueryFn: () => assetTypes.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAssetType() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tslug: string;\n\t\t\tdescription: string;\n\t\t\tallowedMimeTypes: string[];\n\t\t\tmetadataSchema: string;\n\t\t}) => assetTypes.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetTypes\"] }),\n\t});\n}\n\nexport function useUpdateAssetType() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tname?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tallowedMimeTypes?: string[];\n\t\t\t\tmetadataSchema?: string;\n\t\t\t\tactive?: boolean;\n\t\t\t};\n\t\t}) => assetTypes.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetTypes\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetType\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteAssetType() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => assetTypes.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetTypes\"] }),\n\t});\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useUsers(ids: string[]) {\n\tconst { directory } = useMediahubClients();\n\tconst sorted = [...ids].filter(Boolean).sort();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"users\", sorted],\n\t\tqueryFn: () => directory.resolveUsers(sorted),\n\t\tenabled: sorted.length > 0,\n\t\tstaleTime: 1000 * 60 * 10,\n\t\tselect: (data): Record<string, string> =>\n\t\t\tObject.fromEntries(data.map((u) => [u.id, u.displayName])),\n\t});\n}\n\n/** The active workspace's member listing — backs the grant picker\n * (guardian#52). Server-sorted by display name; unpaginated by design. */\nexport function useWorkspaceMembers(opts?: { enabled?: boolean }) {\n\tconst { directory } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"members\", workspaceId],\n\t\tqueryFn: () => directory.listWorkspaceMembers(workspaceId),\n\t\tenabled: opts?.enabled ?? true,\n\t\tstaleTime: 1000 * 60 * 5,\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useWorkspaceStats() {\n\tconst { dashboard } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"workspace-stats\", workspaceId],\n\t\tqueryFn: () => dashboard.getWorkspaceStats(workspaceId),\n\t\tstaleTime: 30_000,\n\t});\n}\n\nexport function useGetDashboardLayout() {\n\tconst { dashboard } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"dashboard-layout\", workspaceId],\n\t\tqueryFn: () => dashboard.getDashboardLayout(workspaceId),\n\t});\n}\n\nexport function useSaveDashboardLayout() {\n\tconst { dashboard } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (layoutJson: string) =>\n\t\t\tdashboard.saveDashboardLayout(workspaceId, layoutJson),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"dashboard-layout\", workspaceId],\n\t\t\t}),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useAIConnections() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-connections\", workspaceId],\n\t\tqueryFn: () => aiConnection.list(workspaceId),\n\t});\n}\n\nexport function useAIConnection(id: string) {\n\tconst { aiConnection } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-connection\", id],\n\t\tqueryFn: () => aiConnection.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAIConnection() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tprovider: string;\n\t\t\tendpoint: string;\n\t\t\tdeployment: string;\n\t\t\tapiVersion: string;\n\t\t\tbaseUrl: string;\n\t\t\tmodel: string;\n\t\t\tapiKey: string;\n\t\t\tdescription: string;\n\t\t}) => aiConnection.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connections\"] }),\n\t});\n}\n\nexport function useUpdateAIConnection() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tname?: string;\n\t\t\t\tendpoint?: string;\n\t\t\t\tdeployment?: string;\n\t\t\t\tapiVersion?: string;\n\t\t\t\tbaseUrl?: string;\n\t\t\t\tmodel?: string;\n\t\t\t\tapiKey?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tactive?: boolean;\n\t\t\t};\n\t\t}) => aiConnection.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connections\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connection\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteAIConnection() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => aiConnection.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connections\"] }),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients } from \"../provider\";\n\nexport function useAIProcesses(assetTypeId: string) {\n\tconst { aiProcess } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-processes\", assetTypeId],\n\t\tqueryFn: () => aiProcess.list(assetTypeId),\n\t\tenabled: !!assetTypeId,\n\t});\n}\n\nexport function useAIProcess(id: string) {\n\tconst { aiProcess } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-process\", id],\n\t\tqueryFn: () => aiProcess.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAIProcess() {\n\tconst { aiProcess } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tassetTypeId: string;\n\t\t\tconnectionId: string;\n\t\t\tname: string;\n\t\t\tprompt: string;\n\t\t\toutputs: { key: string; target: string; metadataAccessor: string }[];\n\t\t\tposition: number;\n\t\t\tworkspaceId: string;\n\t\t}) => aiProcess.create(vars),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-processes\"] }),\n\t});\n}\n\nexport function useUpdateAIProcess() {\n\tconst { aiProcess } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tconnectionId?: string;\n\t\t\t\tname?: string;\n\t\t\t\tprompt?: string;\n\t\t\t\toutputs?: { key: string; target: string; metadataAccessor: string }[];\n\t\t\t\tposition?: number;\n\t\t\t\tactive?: boolean;\n\t\t\t};\n\t\t}) => aiProcess.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-processes\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-process\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteAIProcess() {\n\tconst { aiProcess } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => aiProcess.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-processes\"] }),\n\t});\n}\n","import { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect, useRef } from \"react\";\nimport { useMediahubClients } from \"../provider\";\nimport type { AIProcessRunInfo } from \"../types\";\n\nexport const isActive = (runs: AIProcessRunInfo[] | undefined): boolean =>\n\t(runs ?? []).some((r) => r.status === \"queued\" || r.status === \"running\");\n\nexport function useAIProcessRuns(assetId: string) {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\tconst wasActive = useRef(false);\n\n\tconst query = useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-process-runs\", assetId],\n\t\tqueryFn: () => assets.listProcessRuns(assetId),\n\t\tenabled: !!assetId,\n\t\trefetchInterval: (q) =>\n\t\t\tisActive(q.state.data as AIProcessRunInfo[] | undefined) ? 2000 : false,\n\t});\n\n\t// Reset wasActive when assetId changes so switching to a new asset doesn't\n\t// fire a spurious completion-invalidate on the previous asset's state.\n\t// (assetId is read inside the effect body — a dep the body never mentions\n\t// is what biome flagged in #74; deleting the dep would kill the reset.)\n\tconst seenAssetId = useRef(assetId);\n\tuseEffect(() => {\n\t\tif (seenAssetId.current !== assetId) {\n\t\t\tseenAssetId.current = assetId;\n\t\t\twasActive.current = false;\n\t\t}\n\t}, [assetId]);\n\n\t// When runs transition from active → all-terminal, refresh the asset so the\n\t// AI-applied description/tags/metadata appear.\n\tuseEffect(() => {\n\t\tconst active = isActive(query.data);\n\t\tif (wasActive.current && !active) {\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"assets\", \"detail\", assetId],\n\t\t\t});\n\t\t}\n\t\twasActive.current = active;\n\t}, [query.data, assetId, qc]);\n\n\treturn query;\n}\n","import { create } from \"zustand\";\n\ninterface SelectionState {\n\tselectedIds: string[];\n\tlastClickedId: string | null;\n}\n\ninterface SelectionActions {\n\ttoggle: (id: string) => void;\n\tselectAll: (ids: string[]) => void;\n\tsetSelection: (ids: string[]) => void;\n\tselectRange: (targetId: string, orderedIds: string[]) => void;\n\tclearSelection: () => void;\n}\n\n// Note: To check if an item is selected in React components, use:\n// useSelectionStore((s) => s.selectedIds.includes(id))\n// Do NOT add an isSelected method to the store — it won't trigger re-renders\n// when used as a Zustand selector.\n\ntype SelectionStore = SelectionState & SelectionActions;\n\nexport const useSelectionStore = create<SelectionStore>((set, get) => ({\n\tselectedIds: [],\n\tlastClickedId: null,\n\n\ttoggle: (id) => {\n\t\tset((state) => {\n\t\t\tconst exists = state.selectedIds.includes(id);\n\t\t\treturn {\n\t\t\t\tselectedIds: exists\n\t\t\t\t\t? state.selectedIds.filter((i) => i !== id)\n\t\t\t\t\t: [...state.selectedIds, id],\n\t\t\t\tlastClickedId: id,\n\t\t\t};\n\t\t});\n\t},\n\n\tselectAll: (ids) => set({ selectedIds: [...ids], lastClickedId: null }),\n\n\tsetSelection: (ids) => set({ selectedIds: ids, lastClickedId: null }),\n\n\tselectRange: (targetId, orderedIds) => {\n\t\tconst { lastClickedId, selectedIds } = get();\n\t\tif (!lastClickedId) {\n\t\t\tset({ selectedIds: [targetId], lastClickedId: targetId });\n\t\t\treturn;\n\t\t}\n\t\tconst startIdx = orderedIds.indexOf(lastClickedId);\n\t\tconst endIdx = orderedIds.indexOf(targetId);\n\t\tif (startIdx === -1 || endIdx === -1) return;\n\t\tconst low = Math.min(startIdx, endIdx);\n\t\tconst high = Math.max(startIdx, endIdx);\n\t\tconst rangeIds = orderedIds.slice(low, high + 1);\n\t\tconst merged = new Set([...selectedIds, ...rangeIds]);\n\t\tset({ selectedIds: [...merged], lastClickedId: targetId });\n\t},\n\n\tclearSelection: () => set({ selectedIds: [], lastClickedId: null }),\n}));\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\n\ninterface PreferencesState {\n\tsidebarCollapsed: boolean;\n\tviewMode: \"list\" | \"grid\";\n}\n\ninterface PreferencesActions {\n\ttoggleSidebar: () => void;\n\tsetViewMode: (mode: \"list\" | \"grid\") => void;\n}\n\ntype PreferencesStore = PreferencesState & PreferencesActions;\n\nexport const usePreferencesStore = create<PreferencesStore>()(\n\tpersist(\n\t\t(set) => ({\n\t\t\tsidebarCollapsed: false,\n\t\t\tviewMode: \"list\",\n\n\t\t\ttoggleSidebar: () =>\n\t\t\t\tset((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),\n\n\t\t\tsetViewMode: (mode) => set({ viewMode: mode }),\n\t\t}),\n\t\t{\n\t\t\tname: \"mediahub-preferences\",\n\t\t},\n\t),\n);\n","import type { QueryClient } from \"@tanstack/react-query\";\nimport { create } from \"zustand\";\nimport type { AssetClient } from \"../clients\";\nimport { describeRpcError } from \"../lib/rpc-errors\";\nimport { uploadFileToSAS } from \"../lib/sas-upload\";\n\nexport interface UploadFile {\n\tclientId: string;\n\tfile: File;\n\tassetTypeId: string;\n\tstatus:\n\t\t| \"pending\"\n\t\t| \"creating\"\n\t\t| \"uploading\"\n\t\t| \"finalizing\"\n\t\t| \"done\"\n\t\t| \"error\";\n\tprogress: number;\n\terror?: string;\n\tassetId?: string;\n\tversionId?: string;\n}\n\ninterface UploadState {\n\tfiles: UploadFile[];\n\tvisible: boolean;\n\texpanded: boolean;\n\tanalyzeWithAi: boolean;\n\tqueryClient: QueryClient | null;\n\tassetClient: AssetClient | null;\n}\n\ninterface UploadActions {\n\taddFiles: (files: File[]) => void;\n\tsetAssetType: (clientId: string, assetTypeId: string) => void;\n\tsetBatchAssetType: (assetTypeId: string) => void;\n\tsetAnalyzeWithAi: (v: boolean) => void;\n\tstartUpload: (workspaceId: string, folderId?: string) => void;\n\tsetQueryClient: (qc: QueryClient) => void;\n\tsetAssetClient: (client: AssetClient) => void;\n\tclearPending: () => void;\n\tdismiss: () => void;\n\ttoggleExpanded: () => void;\n}\n\ntype UploadStore = UploadState & UploadActions;\n\nfunction updateFile(\n\tfiles: UploadFile[],\n\tclientId: string,\n\tpatch: Partial<UploadFile>,\n): UploadFile[] {\n\treturn files.map((f) => (f.clientId === clientId ? { ...f, ...patch } : f));\n}\n\nexport const useUploadStore = create<UploadStore>((set, get) => ({\n\tfiles: [],\n\tvisible: false,\n\texpanded: true,\n\tanalyzeWithAi: true,\n\tqueryClient: null,\n\tassetClient: null,\n\n\taddFiles: (newFiles) => {\n\t\tconst entries: UploadFile[] = newFiles.map((file) => ({\n\t\t\t// Client-only tracking ID; KSUID convention applies to server-persisted IDs\n\t\t\tclientId: crypto.randomUUID(),\n\t\t\tfile,\n\t\t\tassetTypeId: \"\",\n\t\t\tstatus: \"pending\" as const,\n\t\t\tprogress: 0,\n\t\t}));\n\t\tset((state) => ({ files: [...state.files, ...entries] }));\n\t},\n\n\tsetAssetType: (clientId, assetTypeId) => {\n\t\tset((state) => ({\n\t\t\tfiles: updateFile(state.files, clientId, { assetTypeId }),\n\t\t}));\n\t},\n\n\tsetBatchAssetType: (assetTypeId) => {\n\t\tset((state) => ({\n\t\t\tfiles: state.files.map((f) =>\n\t\t\t\tf.status === \"pending\" ? { ...f, assetTypeId } : f,\n\t\t\t),\n\t\t}));\n\t},\n\n\tsetAnalyzeWithAi: (v) => set({ analyzeWithAi: v }),\n\n\tstartUpload: async (workspaceId, folderId) => {\n\t\tconst client = get().assetClient;\n\t\tif (!client) throw new Error(\"upload-store: assetClient not set\");\n\n\t\tset({ visible: true, expanded: true });\n\n\t\tconst pending = get().files.filter((f) => f.status === \"pending\");\n\n\t\tfor (const entry of pending) {\n\t\t\tconst { clientId, file, assetTypeId } = entry;\n\n\t\t\ttry {\n\t\t\t\t// Step 1: Create asset\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, { status: \"creating\" }),\n\t\t\t\t}));\n\n\t\t\t\tconst asset = await client.create(workspaceId, {\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tassetTypeId,\n\t\t\t\t\tfolderId: folderId ?? \"\",\n\t\t\t\t\tmetadata: {},\n\t\t\t\t\tanalyzeWithAi: get().analyzeWithAi,\n\t\t\t\t});\n\t\t\t\tconst assetId = asset.id;\n\t\t\t\tif (!assetId) throw new Error(\"create returned no asset ID\");\n\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, { assetId }),\n\t\t\t\t}));\n\n\t\t\t\t// Step 2: Get upload URL\n\t\t\t\tconst { uploadUrl, versionId } = await client.getUploadUrl({\n\t\t\t\t\tassetId,\n\t\t\t\t\tfilename: file.name,\n\t\t\t\t\tcontentType: file.type || \"application/octet-stream\",\n\t\t\t\t\tfileSize: file.size,\n\t\t\t\t\tcomment: \"\",\n\t\t\t\t});\n\t\t\t\tif (!uploadUrl || !versionId) {\n\t\t\t\t\tthrow new Error(\"getUploadUrl returned incomplete response\");\n\t\t\t\t}\n\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, {\n\t\t\t\t\t\tversionId,\n\t\t\t\t\t\tstatus: \"uploading\",\n\t\t\t\t\t}),\n\t\t\t\t}));\n\n\t\t\t\t// Step 3: PUT to SAS URL via XHR\n\t\t\t\tawait uploadFileToSAS(\n\t\t\t\t\tuploadUrl,\n\t\t\t\t\tfile,\n\t\t\t\t\tfile.type || \"application/octet-stream\",\n\t\t\t\t\t(progress) => {\n\t\t\t\t\t\tset((state) => ({\n\t\t\t\t\t\t\tfiles: updateFile(state.files, clientId, { progress }),\n\t\t\t\t\t\t}));\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\t// Step 4: Finalize upload\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, { status: \"finalizing\" }),\n\t\t\t\t}));\n\t\t\t\tawait client.finalizeUpload(versionId);\n\n\t\t\t\t// Step 5: Mark done + invalidate cache\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, {\n\t\t\t\t\t\tstatus: \"done\",\n\t\t\t\t\t\tprogress: 100,\n\t\t\t\t\t}),\n\t\t\t\t}));\n\n\t\t\t\tconst qc = get().queryClient;\n\t\t\t\tif (qc) {\n\t\t\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Denials and leak-guard conflicts render mapped copy in the\n\t\t\t\t// upload stack; anything else keeps the raw message as before.\n\t\t\t\tconst described = describeRpcError(err, \"Upload failed\");\n\t\t\t\tconst message =\n\t\t\t\t\tdescribed.kind === \"other\"\n\t\t\t\t\t\t? err instanceof Error\n\t\t\t\t\t\t\t? err.message\n\t\t\t\t\t\t\t: String(err)\n\t\t\t\t\t\t: described.description;\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, {\n\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t}),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t},\n\n\tsetQueryClient: (qc) => set({ queryClient: qc }),\n\n\tsetAssetClient: (client) => set({ assetClient: client }),\n\n\tclearPending: () =>\n\t\tset((state) => ({\n\t\t\tfiles: state.files.filter((f) => f.status !== \"pending\"),\n\t\t})),\n\n\tdismiss: () =>\n\t\tset({ visible: false, files: [], expanded: true, analyzeWithAi: true }),\n\n\ttoggleExpanded: () => set((state) => ({ expanded: !state.expanded })),\n}));\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport {\n\ttype FormMarkers,\n\tFormMarkersProvider,\n\tInputField,\n\tSelectField,\n\tTextareaField,\n} from \"@knkcs/anker/forms\";\nimport { Box, Flex, toaster } from \"@knkcs/anker/primitives\";\nimport type { TFunction } from \"i18next\";\nimport { Plus, X } from \"lucide-react\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport {\n\tFormProvider,\n\tuseFieldArray,\n\tuseForm,\n\tuseFormContext,\n\tuseWatch,\n} from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { useAIConnections } from \"../hooks/use-ai-connections\";\nimport {\n\tuseCreateAIProcess,\n\tuseUpdateAIProcess,\n} from \"../hooks/use-ai-processes\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useWorkspaceId } from \"../provider\";\nimport type { AIProcessInfo } from \"../types\";\n\n// --- Types ---\n\ntype OutputTarget = \"description\" | \"tags\" | \"metadata\";\n\nexport interface MetadataAccessorOption {\n\tlabel: string;\n\tvalue: string;\n}\n\n/**\n * anker §10: a form whose fields are all required marks nothing at all —\n * neither asterisks nor \"(optional)\". Module-level so the context value's\n * identity is stable across renders.\n */\nconst ALL_REQUIRED_MARKERS: FormMarkers = {\n\tshowRequiredIndicator: false,\n\toptionalText: \"(optional)\",\n};\n\n// --- Zod schema ---\n\nfunction processFormSchema(t: TFunction) {\n\treturn z\n\t\t.object({\n\t\t\tname: z.string().min(1, t(\"aiProcessDialog.nameRequired\")),\n\t\t\tconnectionId: z.string().min(1, t(\"aiProcessDialog.connectionRequired\")),\n\t\t\tprompt: z.string().min(1, t(\"aiProcessDialog.promptRequired\")),\n\t\t\toutputs: z\n\t\t\t\t.array(\n\t\t\t\t\tz.object({\n\t\t\t\t\t\tkey: z.string().min(1, t(\"aiProcessDialog.outputKeyRequired\")),\n\t\t\t\t\t\ttarget: z.enum([\"description\", \"tags\", \"metadata\"] as const),\n\t\t\t\t\t\tmetadataAccessor: z.string().optional(),\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.min(1, t(\"aiProcessDialog.outputRequired\")),\n\t\t})\n\t\t.superRefine((v, ctx) => {\n\t\t\tv.outputs.forEach((o, i) => {\n\t\t\t\tif (o.target === \"metadata\" && !o.metadataAccessor) {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\tpath: [\"outputs\", i, \"metadataAccessor\"],\n\t\t\t\t\t\tmessage: t(\"aiProcessDialog.metadataFieldRequired\"),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n}\n\ninterface ProcessForm {\n\tname: string;\n\tconnectionId: string;\n\tprompt: string;\n\toutputs: { key: string; target: OutputTarget; metadataAccessor?: string }[];\n}\n\nconst EMPTY_OUTPUT = {\n\tkey: \"\",\n\ttarget: \"description\" as OutputTarget,\n\tmetadataAccessor: \"\",\n};\n\n/**\n * The process's outputs as form rows. Correct against the wire, not the\n * declared type: Connect omits an empty repeated field, so a process with no\n * outputs arrives without the key — hence the guarded read, and one blank row\n * so the form is never output-less (the schema requires at least one).\n */\nfunction buildProcessOutputs(proc: AIProcessInfo): ProcessForm[\"outputs\"] {\n\tconst outputs = proc.outputs ?? [];\n\tif (outputs.length === 0) return [{ ...EMPTY_OUTPUT }];\n\treturn outputs.map((o) => ({\n\t\tkey: o.key ?? \"\",\n\t\ttarget: (o.target as OutputTarget) || \"description\",\n\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t}));\n}\n\n// --- Output row ---\n\ninterface OutputRowProps {\n\tindex: number;\n\tonRemove: () => void;\n\tmetadataAccessors: MetadataAccessorOption[];\n\tcanRemove: boolean;\n}\n\nfunction OutputRow({\n\tindex,\n\tonRemove,\n\tmetadataAccessors,\n\tcanRemove,\n}: OutputRowProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { control } = useFormContext<ProcessForm>();\n\tconst target = useWatch({ control, name: `outputs.${index}.target` });\n\n\treturn (\n\t\t<Flex gap={2} align=\"flex-end\">\n\t\t\t<Box flex={1}>\n\t\t\t\t<InputField\n\t\t\t\t\tname={`outputs.${index}.key`}\n\t\t\t\t\tlabel={t(\"aiProcessDialog.outputKeyLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t\tplaceholder={t(\"aiProcessDialog.outputKeyPlaceholder\")}\n\t\t\t\t/>\n\t\t\t</Box>\n\t\t\t<Box flex={1}>\n\t\t\t\t<SelectField\n\t\t\t\t\tname={`outputs.${index}.target`}\n\t\t\t\t\tlabel={t(\"aiProcessDialog.targetLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t>\n\t\t\t\t\t<option value=\"description\">\n\t\t\t\t\t\t{t(\"aiProcessDialog.targetDescription\")}\n\t\t\t\t\t</option>\n\t\t\t\t\t<option value=\"tags\">{t(\"aiProcessDialog.targetTags\")}</option>\n\t\t\t\t\t<option value=\"metadata\">\n\t\t\t\t\t\t{t(\"aiProcessDialog.targetMetadata\")}\n\t\t\t\t\t</option>\n\t\t\t\t</SelectField>\n\t\t\t</Box>\n\t\t\t{target === \"metadata\" && (\n\t\t\t\t<Box flex={1}>\n\t\t\t\t\t<SelectField\n\t\t\t\t\t\tname={`outputs.${index}.metadataAccessor`}\n\t\t\t\t\t\tlabel={t(\"aiProcessDialog.metadataFieldLabel\")}\n\t\t\t\t\t\trequired\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"\">\n\t\t\t\t\t\t\t{t(\"aiProcessDialog.metadataFieldPlaceholder\")}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t\t{metadataAccessors.map((a) => (\n\t\t\t\t\t\t\t<option key={a.value} value={a.value}>\n\t\t\t\t\t\t\t\t{a.label}\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</SelectField>\n\t\t\t\t</Box>\n\t\t\t)}\n\t\t\t<Box pb={1}>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\tdisabled={!canRemove}\n\t\t\t\t\taria-label={t(\"aiProcessDialog.removeOutputAria\")}\n\t\t\t\t>\n\t\t\t\t\t<X size={16} />\n\t\t\t\t</Button>\n\t\t\t</Box>\n\t\t</Flex>\n\t);\n}\nOutputRow.displayName = \"OutputRow\";\n\n// --- Process form fields (shared between create and edit) ---\n\nfunction ProcessFormFields({\n\tmetadataAccessors,\n}: {\n\tmetadataAccessors: MetadataAccessorOption[];\n}): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { data: connections = [] } = useAIConnections();\n\tconst { control } = useFormContext<ProcessForm>();\n\tconst { fields, append, remove } = useFieldArray({\n\t\tcontrol,\n\t\tname: \"outputs\",\n\t});\n\n\treturn (\n\t\t<FormMarkersProvider value={ALL_REQUIRED_MARKERS}>\n\t\t\t{/* Every field here is required, so under the §10 optional-text\n\t\t\t convention this form intentionally shows NO markers at all —\n\t\t\t nothing is the exception. Don't \"fix\" by removing the provider\n\t\t\t or re-enabling asterisks. */}\n\t\t\t<Flex direction=\"column\" gap={4}>\n\t\t\t\t<InputField\n\t\t\t\t\tname=\"name\"\n\t\t\t\t\tlabel={t(\"aiProcessDialog.nameLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t\tplaceholder={t(\"aiProcessDialog.namePlaceholder\")}\n\t\t\t\t/>\n\n\t\t\t\t<SelectField\n\t\t\t\t\tname=\"connectionId\"\n\t\t\t\t\tlabel={t(\"aiProcessDialog.connectionLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">{t(\"aiProcessDialog.connectionPlaceholder\")}</option>\n\t\t\t\t\t{connections.map((c) => (\n\t\t\t\t\t\t<option key={c.id} value={c.id}>\n\t\t\t\t\t\t\t{c.name}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</SelectField>\n\n\t\t\t\t<TextareaField\n\t\t\t\t\tname=\"prompt\"\n\t\t\t\t\tlabel={t(\"aiProcessDialog.promptLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t\tplaceholder={t(\"aiProcessDialog.promptPlaceholder\")}\n\t\t\t\t/>\n\n\t\t\t\t<Box>\n\t\t\t\t\t<Box fontSize=\"sm\" fontWeight=\"medium\" mb={2}>\n\t\t\t\t\t\t{t(\"aiProcessDialog.outputsLabel\")}\n\t\t\t\t\t</Box>\n\t\t\t\t\t<Flex direction=\"column\" gap={3}>\n\t\t\t\t\t\t{fields.map((field, index) => (\n\t\t\t\t\t\t\t<OutputRow\n\t\t\t\t\t\t\t\tkey={field.id}\n\t\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t\t\tonRemove={() => remove(index)}\n\t\t\t\t\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\t\t\t\t\tcanRemove={fields.length > 1}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Flex>\n\t\t\t\t\t<Box mt={3}>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={() => append({ ...EMPTY_OUTPUT })}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Plus size={16} /> {t(\"aiProcessDialog.addOutput\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</Box>\n\t\t\t\t</Box>\n\t\t\t</Flex>\n\t\t</FormMarkersProvider>\n\t);\n}\nProcessFormFields.displayName = \"ProcessFormFields\";\n\n// --- Create form ---\n\nfunction CreateFormContent({\n\topen,\n\tassetTypeId,\n\tmetadataAccessors,\n\tonClose,\n}: {\n\topen: boolean;\n\tassetTypeId: string;\n\tmetadataAccessors: MetadataAccessorOption[];\n\tonClose: () => void;\n}): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst createMutation = useCreateAIProcess();\n\tconst resolver = useMemo(() => zodResolver(processFormSchema(t)), [t]);\n\tconst methods = useForm<ProcessForm>({\n\t\tresolver,\n\t\tdefaultValues: {\n\t\t\tname: \"\",\n\t\t\tconnectionId: \"\",\n\t\t\tprompt: \"\",\n\t\t\toutputs: [{ ...EMPTY_OUTPUT }],\n\t\t},\n\t});\n\n\t// Fallback: zag presence skips onExitComplete when a reopen interrupts the\n\t// exit animation — reset again on open so a fast close-then-reopen can't\n\t// reopen with a stale, unsaved name/connection/prompt/outputs.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tmethods.reset();\n\t}, [open, methods]);\n\n\tasync function onSubmit(data: ProcessForm) {\n\t\ttry {\n\t\t\tawait createMutation.mutateAsync({\n\t\t\t\tassetTypeId,\n\t\t\t\tconnectionId: data.connectionId,\n\t\t\t\tname: data.name,\n\t\t\t\tprompt: data.prompt,\n\t\t\t\toutputs: data.outputs.map((o) => ({\n\t\t\t\t\tkey: o.key,\n\t\t\t\t\ttarget: o.target,\n\t\t\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t\t\t})),\n\t\t\t\tposition: 0,\n\t\t\t\tworkspaceId,\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"aiProcessDialog.createdToast\") });\n\t\t\tonClose();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcessDialog.createFailedToast\"));\n\t\t}\n\t}\n\n\t// Do NOT unmount when `open` flips false: unmounting the open dialog\n\t// machine under StrictMode orphans its scroll-lock/aria-hidden cleanup and\n\t// wedges the whole app (mediahub#66). Keep the Modal mounted; lazyMount/\n\t// unmountOnExit keep the fresh-content-per-open semantics, and form state\n\t// is scrubbed in onExitComplete (not immediately on close) so the content\n\t// doesn't visibly blank mid-exit-animation.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={() => methods.reset()}\n\t\t\tonClose={onClose}\n\t\t\theader={t(\"aiProcessDialog.createHeader\")}\n\t\t\tonSave={methods.handleSubmit(onSubmit)}\n\t\t\tsaveLabel={t(\"aiProcessDialog.createLabel\")}\n\t\t\tloading={createMutation.isPending}\n\t\t>\n\t\t\t<FormProvider {...methods}>\n\t\t\t\t<ProcessFormFields metadataAccessors={metadataAccessors} />\n\t\t\t</FormProvider>\n\t\t</Modal>\n\t);\n}\nCreateFormContent.displayName = \"CreateFormContent\";\n\n// --- Edit form ---\n\nfunction EditFormContent({\n\topen,\n\teditProcess,\n\tmetadataAccessors,\n\tonClose,\n}: {\n\topen: boolean;\n\teditProcess: AIProcessInfo | undefined;\n\tmetadataAccessors: MetadataAccessorOption[];\n\tonClose: () => void;\n}): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\t// Latch the last non-undefined entity: the wrapper keeps this component\n\t// mounted permanently (both create and edit machines stay mounted so\n\t// neither ever tears down while open, mediahub#73). The edit call site\n\t// couples `open` to `!!editProcess`, so closing clears `editProcess` in the\n\t// very same commit that flips `open` false. Render from the latch so the\n\t// Modal has stable data to finish its exit animation with, instead of\n\t// crashing/blanking mid-exit.\n\tconst latchedProcessRef = useRef<AIProcessInfo | undefined>(editProcess);\n\tif (editProcess) {\n\t\tlatchedProcessRef.current = editProcess;\n\t}\n\tconst process = editProcess ?? latchedProcessRef.current;\n\n\tconst updateMutation = useUpdateAIProcess();\n\tconst resolver = useMemo(() => zodResolver(processFormSchema(t)), [t]);\n\tconst methods = useForm<ProcessForm>({\n\t\tresolver,\n\t\tdefaultValues: {\n\t\t\tname: process?.name ?? \"\",\n\t\t\tconnectionId: process?.connectionId ?? \"\",\n\t\t\tprompt: process?.prompt ?? \"\",\n\t\t\toutputs: process ? buildProcessOutputs(process) : [{ ...EMPTY_OUTPUT }],\n\t\t},\n\t});\n\n\t// Reset when the opening entity changes. Guarded on `editProcess` (not the\n\t// latched `process`) so clearing it on the way to close doesn't clobber the\n\t// values still on screen during the exit animation. Also gated on `open`:\n\t// this doubles as the fallback for zag presence skipping onExitComplete on\n\t// an interrupted exit — reopening onto the SAME editProcess wouldn't\n\t// otherwise re-run this effect (its identity is unchanged), so `open`\n\t// flipping true is what re-seeds a fast close-then-reopen instead of\n\t// showing stale edits.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tif (editProcess) {\n\t\t\tmethods.reset({\n\t\t\t\tname: editProcess.name ?? \"\",\n\t\t\t\tconnectionId: editProcess.connectionId ?? \"\",\n\t\t\t\tprompt: editProcess.prompt ?? \"\",\n\t\t\t\toutputs: buildProcessOutputs(editProcess),\n\t\t\t});\n\t\t}\n\t}, [open, editProcess, methods]);\n\n\tasync function onSubmit(data: ProcessForm) {\n\t\tif (!process) return;\n\t\ttry {\n\t\t\tawait updateMutation.mutateAsync({\n\t\t\t\tid: process.id,\n\t\t\t\tpatch: {\n\t\t\t\t\tconnectionId: data.connectionId,\n\t\t\t\t\tname: data.name,\n\t\t\t\t\tprompt: data.prompt,\n\t\t\t\t\toutputs: data.outputs.map((o) => ({\n\t\t\t\t\t\tkey: o.key,\n\t\t\t\t\t\ttarget: o.target,\n\t\t\t\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t\t\t\t})),\n\t\t\t\t\tposition: process.position,\n\t\t\t\t\tactive: process.active,\n\t\t\t\t},\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"aiProcessDialog.updatedToast\") });\n\t\t\tonClose();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcessDialog.updateFailedToast\"));\n\t\t}\n\t}\n\n\t// Kept mounted for the same reason as the create form above (mediahub#66,\n\t// #73) — including across the wrapper's create/edit branch.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={() => methods.reset()}\n\t\t\tonClose={onClose}\n\t\t\theader={t(\"aiProcessDialog.editHeader\")}\n\t\t\tonSave={methods.handleSubmit(onSubmit)}\n\t\t\tsaveLabel={t(\"aiProcessDialog.saveLabel\")}\n\t\t\tloading={updateMutation.isPending}\n\t\t>\n\t\t\t<FormProvider {...methods}>\n\t\t\t\t<ProcessFormFields metadataAccessors={metadataAccessors} />\n\t\t\t</FormProvider>\n\t\t</Modal>\n\t);\n}\nEditFormContent.displayName = \"EditFormContent\";\n\n// --- Main component ---\n\nexport interface AIProcessFormDialogProps {\n\topen: boolean;\n\tonClose: () => void;\n\tassetTypeId: string;\n\tmetadataAccessors: MetadataAccessorOption[];\n\t/** If provided, the dialog opens in edit mode for this process. */\n\teditProcess?: AIProcessInfo;\n}\n\n/**\n * Create or edit one AI process for an asset type. Packaged from the\n * standalone's host-local dialog (knkCS/mediahub#157) — same behaviour, same\n * mount semantics, strings under the package's i18n namespace.\n */\nexport function AIProcessFormDialog({\n\topen,\n\tonClose,\n\tassetTypeId,\n\tmetadataAccessors,\n\teditProcess,\n}: AIProcessFormDialogProps): React.JSX.Element {\n\t// Both inner Modals stay mounted permanently: a `if (!open) return null`\n\t// plus this component's own create/edit mode branch were each a mount gate\n\t// in their own right, and switching branches while a machine was open\n\t// reproduced the StrictMode teardown bug of mediahub#66 (#73).\n\t// `lazyMount`/`unmountOnExit` inside each inner component mean a machine\n\t// that's never been opened renders nothing.\n\treturn (\n\t\t<>\n\t\t\t<CreateFormContent\n\t\t\t\topen={open && !editProcess}\n\t\t\t\tassetTypeId={assetTypeId}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\tonClose={onClose}\n\t\t\t/>\n\t\t\t<EditFormContent\n\t\t\t\topen={open && !!editProcess}\n\t\t\t\teditProcess={editProcess}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\tonClose={onClose}\n\t\t\t/>\n\t\t</>\n\t);\n}\nAIProcessFormDialog.displayName = \"AIProcessFormDialog\";\n","/**\n * Reading the custom fields an asset type's metadata schema declares — the\n * \"Fields\" column of the asset-type index, and the metadata targets an AI\n * process can write into.\n *\n * The schema is a fieldkit `Field[]` serialized to a string (the stored default\n * is `\"{}\"`, which is not an array at all). Structural layout markers carry no\n * value — `section` tab markers and, since fieldkit 0.8.0, `card` group markers\n * — so they must never be counted as fields (mediahub#75); system fields live\n * on the asset's own columns and are likewise excluded.\n *\n * These are display guards, never validators: malformed or non-array JSON\n * degrades to \"no fields\" rather than throwing under a table cell.\n */\n\ninterface SchemaEntry {\n\tfield_type?: string;\n\tsystem?: boolean;\n\tconfig?: { name?: string; api_accessor?: string };\n}\n\nconst STRUCTURAL_MARKERS = new Set([\"section\", \"card\"]);\n\nfunction customFieldEntries(metadataSchema: string | undefined): SchemaEntry[] {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(metadataSchema || \"[]\");\n\t\tif (!Array.isArray(parsed)) return [];\n\t\treturn (parsed as SchemaEntry[]).filter(\n\t\t\t(entry) =>\n\t\t\t\t!entry.system && !STRUCTURAL_MARKERS.has(entry.field_type ?? \"\"),\n\t\t);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/** Custom value-field count for the asset-type index's \"Fields\" column. */\nexport function countCustomFields(metadataSchema: string | undefined): number {\n\treturn customFieldEntries(metadataSchema).length;\n}\n\n/** AI-process metadata-target options: custom value fields only. */\nexport function metadataAccessorOptions(\n\tmetadataSchema: string | undefined,\n): { label: string; value: string }[] {\n\treturn customFieldEntries(metadataSchema).map((entry) => ({\n\t\tlabel: entry.config?.name ?? \"\",\n\t\tvalue: entry.config?.api_accessor ?? \"\",\n\t}));\n}\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBox,\n\tFlex,\n\tSpinner,\n\tStack,\n\tSwitch,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { ChevronDown, ChevronUp, Pencil, Trash2 } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useAIConnections } from \"../hooks/use-ai-connections\";\nimport {\n\tuseAIProcesses,\n\tuseDeleteAIProcess,\n\tuseUpdateAIProcess,\n} from \"../hooks/use-ai-processes\";\nimport { metadataAccessorOptions } from \"../lib/metadata-field-count\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { AIProcessInfo } from \"../types\";\nimport { AIProcessFormDialog } from \"./ai-process-form-dialog\";\n\nexport interface AIProcessesTabProps {\n\t/** The asset type whose processes are listed. */\n\ttypeId: string;\n\t/** The asset type's metadata schema, source of the metadata output targets. */\n\tmetadataSchema: string | undefined;\n}\n\n/**\n * Every field the server needs on an update. `UpdateAIProcess` replaces the\n * record rather than merging, so a toggle or a reorder has to send the whole\n * process back — sending only the changed field blanks the rest.\n *\n * Read against the wire, not the declared type: Connect omits empty strings\n * and empty repeated fields from its JSON (knkcms/core#863), so every value is\n * defaulted here at the one place it is read.\n */\nfunction fullPatch(p: AIProcessInfo) {\n\treturn {\n\t\tconnectionId: p.connectionId ?? \"\",\n\t\tname: p.name ?? \"\",\n\t\tprompt: p.prompt ?? \"\",\n\t\toutputs: (p.outputs ?? []).map((o) => ({\n\t\t\tkey: o.key ?? \"\",\n\t\t\ttarget: o.target ?? \"\",\n\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t})),\n\t\tposition: p.position ?? 0,\n\t\tactive: p.active ?? false,\n\t};\n}\n\n/**\n * The AI-Processes tab of the packaged asset-type detail screen: the processes\n * an asset type runs when an asset is analyzed, in order — listed, reordered,\n * enabled/disabled, deleted, created and edited (knkCS/mediahub#157).\n *\n * No routing of its own: where a host's AI-connection settings live is the\n * host's URL, so the \"no connections\" hint is text, not a link.\n */\nexport function AIProcessesTab({\n\ttypeId,\n\tmetadataSchema,\n}: AIProcessesTabProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { confirm } = useConfirmModal();\n\n\tconst processesQuery = useAIProcesses(typeId);\n\tconst processes = processesQuery.data ?? [];\n\tconst connections = useAIConnections().data ?? [];\n\tconst deleteProcess = useDeleteAIProcess();\n\tconst updateProcess = useUpdateAIProcess();\n\n\tconst [createOpen, setCreateOpen] = useState(false);\n\tconst [editProcess, setEditProcess] = useState<AIProcessInfo | undefined>(\n\t\tundefined,\n\t);\n\n\tconst metadataAccessors = useMemo(\n\t\t() => metadataAccessorOptions(metadataSchema),\n\t\t[metadataSchema],\n\t);\n\n\tconst connectionMap = useMemo(\n\t\t() => new Map(connections.map((c) => [c.id, c.name])),\n\t\t[connections],\n\t);\n\n\t// The server's `position` is authoritative but need not be dense; the list\n\t// is shown — and reordered — in ascending position order.\n\tconst sorted = useMemo(\n\t\t() => [...processes].sort((a, b) => (a.position ?? 0) - (b.position ?? 0)),\n\t\t[processes],\n\t);\n\n\tasync function handleDelete(proc: AIProcessInfo) {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"aiProcesses.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"aiProcesses.deleteConfirmMessage\", {\n\t\t\t\tprocessName: proc.name ?? \"\",\n\t\t\t}),\n\t\t\tconfirmLabel: t(\"aiProcesses.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteProcess.mutateAsync(proc.id);\n\t\t\ttoaster.success({ title: t(\"aiProcesses.deletedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcesses.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleToggle(proc: AIProcessInfo, active: boolean) {\n\t\ttry {\n\t\t\tawait updateProcess.mutateAsync({\n\t\t\t\tid: proc.id,\n\t\t\t\tpatch: { ...fullPatch(proc), active },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcesses.updateFailedToast\"));\n\t\t}\n\t}\n\n\t/** Swap a process with its neighbour `delta` places away. */\n\tasync function handleMove(index: number, delta: -1 | 1) {\n\t\tconst proc = sorted[index];\n\t\tconst neighbour = sorted[index + delta];\n\t\tif (!proc || !neighbour) return;\n\t\ttry {\n\t\t\tawait updateProcess.mutateAsync({\n\t\t\t\tid: proc.id,\n\t\t\t\tpatch: { ...fullPatch(proc), position: index + delta },\n\t\t\t});\n\t\t\tawait updateProcess.mutateAsync({\n\t\t\t\tid: neighbour.id,\n\t\t\t\tpatch: { ...fullPatch(neighbour), position: index },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcesses.reorderFailedToast\"));\n\t\t}\n\t}\n\n\tconst noConnections = connections.length === 0;\n\n\treturn (\n\t\t<>\n\t\t\t<Stack gap={4}>\n\t\t\t\t<Flex justify=\"space-between\" align=\"center\">\n\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t{t(\"aiProcesses.intro\")}\n\t\t\t\t\t</Text>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={() => setCreateOpen(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"aiProcesses.newProcess\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</Flex>\n\n\t\t\t\t{noConnections && (\n\t\t\t\t\t<Box\n\t\t\t\t\t\tp={4}\n\t\t\t\t\t\tborderRadius=\"md\"\n\t\t\t\t\t\tborderWidth=\"1px\"\n\t\t\t\t\t\tborderColor=\"border.default\"\n\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"aiProcesses.noConnectionsHint\")}\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\n\t\t\t\t{processesQuery.isLoading ? (\n\t\t\t\t\t<Box display=\"flex\" justifyContent=\"center\" p={4}>\n\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t</Box>\n\t\t\t\t) : sorted.length === 0 ? (\n\t\t\t\t\tnoConnections ? null : (\n\t\t\t\t\t\t<EmptyState header={t(\"aiProcesses.empty\")} />\n\t\t\t\t\t)\n\t\t\t\t) : (\n\t\t\t\t\t<Stack gap={2}>\n\t\t\t\t\t\t{sorted.map((proc, i) => (\n\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\tkey={proc.id}\n\t\t\t\t\t\t\t\tp={4}\n\t\t\t\t\t\t\t\tborderRadius=\"md\"\n\t\t\t\t\t\t\t\tborderWidth=\"1px\"\n\t\t\t\t\t\t\t\tborderColor=\"border.default\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Flex justify=\"space-between\" align=\"center\">\n\t\t\t\t\t\t\t\t\t<Stack gap={1}>\n\t\t\t\t\t\t\t\t\t\t<Text fontWeight=\"medium\">{proc.name}</Text>\n\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t\t\t\t{connectionMap.get(proc.connectionId) ??\n\t\t\t\t\t\t\t\t\t\t\t\tproc.connectionId}{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t·{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t{t(\"aiProcesses.outputCount\", {\n\t\t\t\t\t\t\t\t\t\t\t\tcount: (proc.outputs ?? []).length,\n\t\t\t\t\t\t\t\t\t\t\t})}{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t·{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t{proc.active\n\t\t\t\t\t\t\t\t\t\t\t\t? t(\"aiProcesses.active\")\n\t\t\t\t\t\t\t\t\t\t\t\t: t(\"aiProcesses.inactive\")}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t\t\t<Flex gap={2} align=\"center\">\n\t\t\t\t\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\t\t\t\t\tchecked={proc.active ?? false}\n\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\tproc.active\n\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"aiProcesses.disableAria\")\n\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"aiProcesses.enableAria\")\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={(details) => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleToggle(proc, details.checked);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={i === 0}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleMove(i, -1);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.moveUpAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ChevronUp size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={i === sorted.length - 1}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleMove(i, 1);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.moveDownAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ChevronDown size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setEditProcess(proc)}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.editAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Pencil size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleDelete(proc);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.deleteAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Trash2 size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Stack>\n\t\t\t\t)}\n\t\t\t</Stack>\n\n\t\t\t{/* Two permanently-mounted dialog instances, `open` toggled — never\n\t\t\t mounted/unmounted while open (mediahub#66/#73). */}\n\t\t\t<AIProcessFormDialog\n\t\t\t\topen={createOpen}\n\t\t\t\tonClose={() => setCreateOpen(false)}\n\t\t\t\tassetTypeId={typeId}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t/>\n\t\t\t<AIProcessFormDialog\n\t\t\t\topen={!!editProcess}\n\t\t\t\tonClose={() => setEditProcess(undefined)}\n\t\t\t\tassetTypeId={typeId}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\teditProcess={editProcess}\n\t\t\t/>\n\t\t</>\n\t);\n}\nAIProcessesTab.displayName = \"AIProcessesTab\";\n","import { Text } from \"@knkcs/anker/primitives\";\nimport { StatusBadge } from \"@knkcs/statushub-ui\";\nimport { useAssetStatus } from \"../statushub\";\n\nexport interface AssetStatusBadgeProps {\n\t/** The asset's stored status slug. Empty renders nothing. */\n\tslug: string;\n}\n\n/**\n * An asset's status, named and coloured from statushub's catalogue.\n *\n * This is the one place mediahub turns a stored slug into something readable\n * (statushub's integration standard §10: the consumer renders statuses itself,\n * with statushub-ui's components — no host slot). A slug the catalogue does\n * not carry — an **unknown status**, deleted or never answered for (§5) —\n * prints as itself, because the asset has a status either way and saying\n * nothing would read as having none.\n */\nexport function AssetStatusBadge({ slug }: AssetStatusBadgeProps) {\n\tconst { status, isLoading } = useAssetStatus(slug);\n\tif (!slug) return null;\n\t// Nothing rather than the slug while the catalogue is in flight: the slug\n\t// is what an unknown status looks like, and showing it here would flash a\n\t// raw `in-review` across every row of every list on each mount.\n\tif (isLoading) return null;\n\tif (!status) {\n\t\treturn (\n\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t{slug}\n\t\t\t</Text>\n\t\t);\n\t}\n\treturn <StatusBadge status={status} />;\n}\nAssetStatusBadge.displayName = \"AssetStatusBadge\";\n","import { SelectableCard } from \"@knkcs/anker/components\";\nimport { Grid, Skeleton, Text } from \"@knkcs/anker/primitives\";\nimport { FileText, Film, Image, Music } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { usePreviewURL } from \"../hooks/use-preview-url\";\nimport { useSelectionStore } from \"../stores/selection-store\";\nimport type { AssetInfo } from \"../types\";\nimport { AssetStatusBadge } from \"./asset-status-badge\";\n\nfunction getMimeCategory(asset: AssetInfo): string {\n\tconst version = asset.versions[asset.versions.length - 1];\n\tif (!version) return \"unknown\";\n\tconst mime = version.mimeType;\n\tif (mime.startsWith(\"image/\")) return \"image\";\n\tif (mime.startsWith(\"video/\")) return \"video\";\n\tif (mime.startsWith(\"audio/\")) return \"audio\";\n\tif (mime === \"application/pdf\") return \"pdf\";\n\treturn \"unknown\";\n}\n\nfunction TypeIcon({ category }: { category: string }) {\n\tswitch (category) {\n\t\tcase \"image\":\n\t\t\treturn <Image size={32} opacity={0.3} />;\n\t\tcase \"video\":\n\t\t\treturn <Film size={32} opacity={0.3} />;\n\t\tcase \"audio\":\n\t\t\treturn <Music size={32} opacity={0.3} />;\n\t\tdefault:\n\t\t\treturn <FileText size={32} opacity={0.3} />;\n\t}\n}\nTypeIcon.displayName = \"TypeIcon\";\n\n/** Maps the internal MIME category slug to its display label. */\nfunction useCategoryLabel(category: string): string {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tswitch (category) {\n\t\tcase \"image\":\n\t\t\treturn t(\"assetGrid.categoryImage\");\n\t\tcase \"video\":\n\t\t\treturn t(\"assetGrid.categoryVideo\");\n\t\tcase \"audio\":\n\t\t\treturn t(\"assetGrid.categoryAudio\");\n\t\tcase \"pdf\":\n\t\t\treturn t(\"assetGrid.categoryPdf\");\n\t\tdefault:\n\t\t\treturn t(\"assetGrid.categoryUnknown\");\n\t}\n}\n\ninterface AssetCardProps {\n\tasset: AssetInfo;\n\tonOpen: (asset: AssetInfo) => void;\n}\n\nconst AssetCard: React.FC<AssetCardProps> = ({ asset, onOpen }) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst isSelected = useSelectionStore((s) => s.selectedIds.includes(asset.id));\n\tconst anySelected = useSelectionStore((s) => s.selectedIds.length > 0);\n\tconst toggle = useSelectionStore((s) => s.toggle);\n\tconst category = getMimeCategory(asset);\n\tconst categoryLabel = useCategoryLabel(category);\n\tconst latestVersion = asset.versions[asset.versions.length - 1];\n\tconst previewQuery = usePreviewURL(\n\t\tcategory === \"image\" && latestVersion ? asset.id : \"\",\n\t\tlatestVersion?.id ?? \"\",\n\t);\n\tconst previewUrl = previewQuery.data;\n\tconst [imgError, setImgError] = useState(false);\n\n\treturn (\n\t\t<SelectableCard\n\t\t\tselected={isSelected}\n\t\t\tselectionVisible={anySelected}\n\t\t\tonSelect={() => toggle(asset.id)}\n\t\t\tonClick={() => onOpen(asset)}\n\t\t>\n\t\t\t<SelectableCard.Thumbnail height=\"160px\">\n\t\t\t\t{category === \"image\" && previewUrl && !imgError ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\talt={asset.name || t(\"assetGrid.previewAlt\")}\n\t\t\t\t\t\tonError={() => setImgError(true)}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\t\t\theight: \"100%\",\n\t\t\t\t\t\t\tobjectFit: \"cover\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : category === \"image\" && previewQuery.isLoading ? (\n\t\t\t\t\t<Skeleton w=\"full\" h=\"full\" />\n\t\t\t\t) : (\n\t\t\t\t\t<TypeIcon category={category} />\n\t\t\t\t)}\n\t\t\t</SelectableCard.Thumbnail>\n\t\t\t<SelectableCard.Body>\n\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" truncate>\n\t\t\t\t\t{asset.name}\n\t\t\t\t</Text>\n\t\t\t</SelectableCard.Body>\n\t\t\t<SelectableCard.Footer>\n\t\t\t\t<AssetStatusBadge slug={asset.statusSlug} />\n\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t{categoryLabel}\n\t\t\t\t</Text>\n\t\t\t</SelectableCard.Footer>\n\t\t</SelectableCard>\n\t);\n};\nAssetCard.displayName = \"AssetCard\";\n\nexport interface AssetGridProps {\n\tassets: AssetInfo[];\n\tonOpen: (asset: AssetInfo) => void;\n}\n\nexport const AssetGrid: React.FC<AssetGridProps> = ({ assets, onOpen }) => {\n\treturn (\n\t\t<Grid templateColumns=\"repeat(auto-fill, minmax(200px, 1fr))\" gap={4}>\n\t\t\t{assets.map((asset) => (\n\t\t\t\t<AssetCard key={asset.id} asset={asset} onOpen={onOpen} />\n\t\t\t))}\n\t\t</Grid>\n\t);\n};\nAssetGrid.displayName = \"AssetGrid\";\n","import { Button } from \"@knkcs/anker/atoms\";\nimport { Box, Flex, Skeleton, Text } from \"@knkcs/anker/primitives\";\nimport { Download, FileText, Film, Image, Music } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { usePreviewURL } from \"../hooks/use-preview-url\";\n\ninterface AssetPreviewProps {\n\tassetId: string;\n\tversionId: string;\n\tmimeType: string;\n\tfileName: string;\n}\n\nfunction TypeIcon({ mimeType }: { mimeType: string }) {\n\tif (mimeType.startsWith(\"image/\")) return <Image size={48} opacity={0.3} />;\n\tif (mimeType.startsWith(\"video/\")) return <Film size={48} opacity={0.3} />;\n\tif (mimeType.startsWith(\"audio/\")) return <Music size={48} opacity={0.3} />;\n\treturn <FileText size={48} opacity={0.3} />;\n}\nTypeIcon.displayName = \"TypeIcon\";\n\nexport const AssetPreview: React.FC<AssetPreviewProps> = ({\n\tassetId,\n\tversionId,\n\tmimeType,\n\tfileName,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst previewQuery = usePreviewURL(assetId, versionId);\n\tconst url = previewQuery.data;\n\tconst [error, setError] = useState(false);\n\n\tif (previewQuery.isLoading) {\n\t\treturn <Skeleton w=\"full\" h=\"full\" minH=\"200px\" />;\n\t}\n\n\tif (!url || error) {\n\t\treturn (\n\t\t\t<Flex\n\t\t\t\tdirection=\"column\"\n\t\t\t\talign=\"center\"\n\t\t\t\tjustify=\"center\"\n\t\t\t\tgap={3}\n\t\t\t\tp={6}\n\t\t\t\th=\"full\"\n\t\t\t\tminH=\"200px\"\n\t\t\t>\n\t\t\t\t<TypeIcon mimeType={mimeType} />\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t{t(\"assetPreview.previewNotAvailable\")}\n\t\t\t\t</Text>\n\t\t\t\t{url && (\n\t\t\t\t\t<Button asChild size=\"sm\" variant=\"outline\">\n\t\t\t\t\t\t<a href={url} download={fileName}>\n\t\t\t\t\t\t\t<Download size={14} />\n\t\t\t\t\t\t\t{t(\"assetPreview.download\")}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\t// Image\n\tif (mimeType.startsWith(\"image/\")) {\n\t\treturn (\n\t\t\t<Box\n\t\t\t\th=\"full\"\n\t\t\t\tminH=\"200px\"\n\t\t\t\tdisplay=\"flex\"\n\t\t\t\talignItems=\"center\"\n\t\t\t\tjustifyContent=\"center\"\n\t\t\t\tp={2}\n\t\t\t>\n\t\t\t\t<img\n\t\t\t\t\tsrc={url}\n\t\t\t\t\talt={fileName}\n\t\t\t\t\tonError={() => setError(true)}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmaxWidth: \"100%\",\n\t\t\t\t\t\tmaxHeight: \"100%\",\n\t\t\t\t\t\tobjectFit: \"contain\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Video\n\tif (mimeType.startsWith(\"video/\")) {\n\t\treturn (\n\t\t\t<Box h=\"full\" minH=\"200px\" p={2}>\n\t\t\t\t<video\n\t\t\t\t\tsrc={url}\n\t\t\t\t\tcontrols\n\t\t\t\t\tonError={() => setError(true)}\n\t\t\t\t\tstyle={{ width: \"100%\", maxHeight: \"100%\" }}\n\t\t\t\t>\n\t\t\t\t\t<track kind=\"captions\" />\n\t\t\t\t</video>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Audio\n\tif (mimeType.startsWith(\"audio/\")) {\n\t\treturn (\n\t\t\t<Flex\n\t\t\t\tdirection=\"column\"\n\t\t\t\talign=\"center\"\n\t\t\t\tjustify=\"center\"\n\t\t\t\tgap={4}\n\t\t\t\tp={6}\n\t\t\t\th=\"full\"\n\t\t\t\tminH=\"200px\"\n\t\t\t>\n\t\t\t\t<Music size={48} opacity={0.3} />\n\t\t\t\t<audio\n\t\t\t\t\tsrc={url}\n\t\t\t\t\tcontrols\n\t\t\t\t\tonError={() => setError(true)}\n\t\t\t\t\tstyle={{ width: \"100%\" }}\n\t\t\t\t>\n\t\t\t\t\t<track kind=\"captions\" />\n\t\t\t\t</audio>\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\t// PDF\n\tif (mimeType === \"application/pdf\") {\n\t\treturn (\n\t\t\t<Box h=\"full\" minH=\"400px\">\n\t\t\t\t<iframe\n\t\t\t\t\tsrc={url}\n\t\t\t\t\ttitle={fileName}\n\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\theight=\"100%\"\n\t\t\t\t\tstyle={{ border: \"none\" }}\n\t\t\t\t/>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Fallback\n\treturn (\n\t\t<Flex\n\t\t\tdirection=\"column\"\n\t\t\talign=\"center\"\n\t\t\tjustify=\"center\"\n\t\t\tgap={3}\n\t\t\tp={6}\n\t\t\th=\"full\"\n\t\t\tminH=\"200px\"\n\t\t>\n\t\t\t<TypeIcon mimeType={mimeType} />\n\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t{t(\"assetPreview.previewNotAvailable\")}\n\t\t\t</Text>\n\t\t\t<Button asChild size=\"sm\" variant=\"outline\">\n\t\t\t\t<a href={url} download={fileName}>\n\t\t\t\t\t<Download size={14} />\n\t\t\t\t\t{t(\"assetPreview.download\")}\n\t\t\t\t</a>\n\t\t\t</Button>\n\t\t</Flex>\n\t);\n};\nAssetPreview.displayName = \"AssetPreview\";\n","import { StatusTransitionControl } from \"@knkcs/statushub-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { useTransitionAssetStatus } from \"../hooks/use-assets\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { ASSET_STATUS_CATALOGUE } from \"../statushub\";\n\nexport interface AssetStatusControlProps {\n\tassetId: string;\n\t/** The asset's stored status slug — what the viewer is looking at. */\n\tstatusSlug: string;\n}\n\n/**\n * An asset's status, and the moves statushub allows away from it.\n *\n * statushub-ui offers the moves; mediahub's own `TransitionAssetStatus` makes\n * them (integration standard §3) — the browser never writes to statushub. The\n * slug being shown travels with the change, so a screen drawn before somebody\n * else moved this asset on is refused as a conflict instead of overwriting\n * them.\n *\n * Guarded moves are shown (`canRevert`) and statushub decides them: its answer\n * is per-caller, and mediahub keeps no who-may-revert rule of its own. The\n * control swallows what `onTransition` throws — error handling is the\n * consumer's — so the refusal is toasted here.\n */\nexport function AssetStatusControl({\n\tassetId,\n\tstatusSlug,\n}: AssetStatusControlProps) {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst transition = useTransitionAssetStatus();\n\treturn (\n\t\t<StatusTransitionControl\n\t\t\t{...ASSET_STATUS_CATALOGUE}\n\t\t\tcurrentStatusSlug={statusSlug}\n\t\t\tquickAdvance={false}\n\t\t\tcanRevert\n\t\t\tonTransition={async (to) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait transition.mutateAsync({\n\t\t\t\t\t\tid: assetId,\n\t\t\t\t\t\tfromStatusSlug: statusSlug,\n\t\t\t\t\t\ttoStatusSlug: to.slug,\n\t\t\t\t\t});\n\t\t\t\t} catch (err) {\n\t\t\t\t\tshowRpcErrorToast(err, t(\"assetStatusControl.transitionFailedToast\"));\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t);\n}\nAssetStatusControl.displayName = \"AssetStatusControl\";\n","import { BulkActionBar as AnkerBulkActionBar } from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { Box, Flex, Text, toaster } from \"@knkcs/anker/primitives\";\nimport { FolderOpen, Tag, Trash2 } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useDeleteAsset } from \"../hooks/use-assets\";\nimport {\n\tuseAddAssetsToCollection,\n\tuseCollections,\n} from \"../hooks/use-collections\";\nimport { useTagAssets, useTags } from \"../hooks/use-tags\";\nimport { describeRpcError, showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useSelectionStore } from \"../stores/selection-store\";\n\nexport const BulkActionBar: React.FC = () => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst selectedIds = useSelectionStore((s) => s.selectedIds);\n\tconst clearSelection = useSelectionStore((s) => s.clearSelection);\n\tconst count = selectedIds.length;\n\n\tconst deleteAsset = useDeleteAsset();\n\tconst { confirm } = useConfirmModal();\n\tconst tagAssets = useTagAssets();\n\tconst addToCollection = useAddAssetsToCollection();\n\tconst tagsQuery = useTags();\n\tconst collectionsQuery = useCollections();\n\tconst tags = tagsQuery.data ?? [];\n\tconst collections = collectionsQuery.data ?? [];\n\n\tasync function handleBulkDelete() {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"bulkActionBar.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"bulkActionBar.deleteConfirmMessage\", { count }),\n\t\t\tconfirmLabel: t(\"bulkActionBar.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\tconst ids = useSelectionStore.getState().selectedIds;\n\t\tconst n = ids.length;\n\t\tif (n === 0) return;\n\t\tlet failed = 0;\n\t\tlet firstErr: unknown;\n\t\tfor (const id of ids) {\n\t\t\ttry {\n\t\t\t\tawait deleteAsset.mutateAsync(id);\n\t\t\t} catch (err) {\n\t\t\t\tfailed++;\n\t\t\t\tfirstErr ??= err;\n\t\t\t}\n\t\t}\n\t\tif (failed === 0) {\n\t\t\ttoaster.success({\n\t\t\t\ttitle: t(\"bulkActionBar.deleteSuccessToast\", { count: n }),\n\t\t\t});\n\t\t\tuseSelectionStore.getState().clearSelection();\n\t\t} else {\n\t\t\t// Mapped families explain themselves; other errors keep the bare\n\t\t\t// count so raw server strings never enter the toast.\n\t\t\tconst fallback = t(\"bulkActionBar.deletePartialFailureToast\", {\n\t\t\t\tdeleted: n - failed,\n\t\t\t\tfailed,\n\t\t\t});\n\t\t\tconst described = describeRpcError(firstErr, fallback);\n\t\t\ttoaster.error(\n\t\t\t\tdescribed.kind === \"other\"\n\t\t\t\t\t? { title: fallback }\n\t\t\t\t\t: { title: described.title, description: described.description },\n\t\t\t);\n\t\t}\n\t}\n\n\tasync function handleBulkTag(tagId: string) {\n\t\ttry {\n\t\t\tawait tagAssets.mutateAsync({ tagId, assetIds: [...selectedIds] });\n\t\t\ttoaster.success({ title: t(\"bulkActionBar.tagsUpdatedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"bulkActionBar.errorToast\"));\n\t\t}\n\t}\n\n\tasync function handleBulkAddToCollection(collectionId: string) {\n\t\ttry {\n\t\t\tawait addToCollection.mutateAsync({\n\t\t\t\tcollectionId,\n\t\t\t\tassetIds: [...selectedIds],\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"bulkActionBar.addedToCollectionToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"bulkActionBar.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<AnkerBulkActionBar\n\t\t\tselectedCount={count}\n\t\t\tonClear={clearSelection}\n\t\t\tcountLabel={(n: number) => t(\"bulkActionBar.countSelected\", { count: n })}\n\t\t>\n\t\t\t<AnkerBulkActionBar.PopoverAction\n\t\t\t\tlabel={t(\"bulkActionBar.addTagsAction\")}\n\t\t\t\ticon={<Tag size={14} />}\n\t\t\t>\n\t\t\t\t<Flex direction=\"column\" gap={1} p={2}>\n\t\t\t\t\t{tags.map((tag) => (\n\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\tkey={tag.id}\n\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\tpx={2}\n\t\t\t\t\t\t\tpy={1}\n\t\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\t\ttextAlign=\"left\"\n\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t_hover={{ bg: \"bg.muted\" }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button type=\"button\" onClick={() => handleBulkTag(tag.id)}>\n\t\t\t\t\t\t\t\t{tag.name}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t))}\n\t\t\t\t\t{tags.length === 0 && (\n\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" p={2}>\n\t\t\t\t\t\t\t{t(\"bulkActionBar.noTagsAvailable\")}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Flex>\n\t\t\t</AnkerBulkActionBar.PopoverAction>\n\n\t\t\t<AnkerBulkActionBar.PopoverAction\n\t\t\t\tlabel={t(\"bulkActionBar.addToCollectionAction\")}\n\t\t\t\ticon={<FolderOpen size={14} />}\n\t\t\t>\n\t\t\t\t<Flex direction=\"column\" gap={1} p={2}>\n\t\t\t\t\t{collections.map((col) => (\n\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\tkey={col.id}\n\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\tpx={2}\n\t\t\t\t\t\t\tpy={1}\n\t\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\t\ttextAlign=\"left\"\n\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t_hover={{ bg: \"bg.muted\" }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => handleBulkAddToCollection(col.id)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{col.name}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t))}\n\t\t\t\t\t{collections.length === 0 && (\n\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" p={2}>\n\t\t\t\t\t\t\t{t(\"bulkActionBar.noCollectionsAvailable\")}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Flex>\n\t\t\t</AnkerBulkActionBar.PopoverAction>\n\n\t\t\t<AnkerBulkActionBar.Action\n\t\t\t\tlabel={t(\"bulkActionBar.deleteAction\")}\n\t\t\t\ticon={<Trash2 size={14} />}\n\t\t\t\tcolorPalette=\"red\"\n\t\t\t\tonClick={handleBulkDelete}\n\t\t\t/>\n\t\t</AnkerBulkActionBar>\n\t);\n};\nBulkActionBar.displayName = \"BulkActionBar\";\n","import { ChipPicker } from \"@knkcs/anker/components\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n\tuseAddAssetsToCollection,\n\tuseCollections,\n\tuseRemoveAssetsFromCollection,\n} from \"../hooks/use-collections\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { CollectionInfo } from \"../types\";\n\ninterface CollectionChipFieldProps {\n\tassetId: string;\n\tassignedCollectionIds: string[];\n}\n\nexport const CollectionChipField: React.FC<CollectionChipFieldProps> = ({\n\tassetId,\n\tassignedCollectionIds,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst collectionsQuery = useCollections();\n\tconst allCollections: CollectionInfo[] = collectionsQuery.data ?? [];\n\tconst addToCollection = useAddAssetsToCollection();\n\tconst removeFromCollection = useRemoveAssetsFromCollection();\n\tconst qc = useQueryClient();\n\n\tconst assigned = allCollections.filter((c) =>\n\t\tassignedCollectionIds.includes(c.id),\n\t);\n\tconst unassigned = allCollections.filter(\n\t\t(c) => !assignedCollectionIds.includes(c.id),\n\t);\n\n\tasync function handleAdd(collection: CollectionInfo) {\n\t\ttry {\n\t\t\tawait addToCollection.mutateAsync({\n\t\t\t\tcollectionId: collection.id,\n\t\t\t\tassetIds: [assetId],\n\t\t\t});\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionChipField.errorToast\"));\n\t\t}\n\t}\n\n\tasync function handleRemove(collection: CollectionInfo) {\n\t\ttry {\n\t\t\tawait removeFromCollection.mutateAsync({\n\t\t\t\tcollectionId: collection.id,\n\t\t\t\tassetIds: [assetId],\n\t\t\t});\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionChipField.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<ChipPicker<CollectionInfo>\n\t\t\tassigned={assigned}\n\t\t\tavailable={unassigned}\n\t\t\tgetItemId={(c) => c.id}\n\t\t\tgetItemLabel={(c) => c.name}\n\t\t\tonAdd={handleAdd}\n\t\t\tonRemove={handleRemove}\n\t\t\taddLabel={t(\"collectionChipField.addLabel\")}\n\t\t\temptyLabel={t(\"collectionChipField.emptyLabel\")}\n\t\t\tsearchable\n\t\t\tloading={collectionsQuery.isLoading}\n\t\t/>\n\t);\n};\nCollectionChipField.displayName = \"CollectionChipField\";\n","import { InlineCreatableList } from \"@knkcs/anker/components\";\nimport { toaster } from \"@knkcs/anker/primitives\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCollections, useCreateCollection } from \"../hooks/use-collections\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { CollectionInfo } from \"../types\";\n\ninterface CollectionPanelProps {\n\tactiveCollectionId: string;\n\tonSelectCollection: (collectionId: string) => void;\n}\n\nexport const CollectionPanel: React.FC<CollectionPanelProps> = ({\n\tactiveCollectionId,\n\tonSelectCollection,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst collectionsQuery = useCollections();\n\tconst collections: CollectionInfo[] = collectionsQuery.data ?? [];\n\tconst createCollection = useCreateCollection();\n\n\tasync function handleCreate(name: string) {\n\t\ttry {\n\t\t\tawait createCollection.mutateAsync({\n\t\t\t\tname,\n\t\t\t\tslug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tdescription: \"\",\n\t\t\t\ttype: \"static\",\n\t\t\t\trules: \"\",\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"collectionPanel.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionPanel.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<InlineCreatableList<CollectionInfo>\n\t\t\titems={collections}\n\t\t\tactiveIds={activeCollectionId ? [activeCollectionId] : []}\n\t\t\tonToggle={onSelectCollection}\n\t\t\tonCreate={handleCreate}\n\t\t\tgetItemId={(c) => c.id}\n\t\t\tgetItemLabel={(c) => c.name}\n\t\t\tvariant=\"list\"\n\t\t\tcreatePlaceholder={t(\"collectionPanel.createPlaceholder\")}\n\t\t\tcreateLabel={t(\"collectionPanel.createLabel\")}\n\t\t\temptyText={t(\"collectionPanel.emptyText\")}\n\t\t/>\n\t);\n};\nCollectionPanel.displayName = \"CollectionPanel\";\n","import {\n\tBreadcrumbCurrentLink,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbList,\n\tBreadcrumbRoot,\n\tBreadcrumbSeparator,\n} from \"@knkcs/anker/primitives\";\nimport { useMemo } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useFolder } from \"../hooks/use-folders\";\n\ninterface FolderBreadcrumbsProps {\n\tfolderId: string;\n\tonNavigate: (folderId: string) => void;\n}\n\n/**\n * Build ancestor chain by walking parent_id up to 3 levels.\n * Uses useFolder for each level. Since tree browsing caches folders,\n * most calls will resolve from TanStack Query cache.\n *\n * Limitation: Shows at most 3 breadcrumb segments (grandparent/parent/current).\n * For deeper nesting, the earliest ancestors are truncated. This is acceptable\n * for v1 — folder structures deeper than 3 levels are rare. If needed later,\n * add a GetFolderAncestors RPC to the backend for a single-call solution.\n */\nfunction useAncestorChain(folderId: string) {\n\tconst folderQuery = useFolder(folderId);\n\tconst folder = folderQuery.data;\n\n\tconst parentQuery = useFolder(folder?.parentId ?? \"\");\n\tconst parent = parentQuery.data;\n\n\tconst grandparentQuery = useFolder(parent?.parentId ?? \"\");\n\tconst grandparent = grandparentQuery.data;\n\n\treturn useMemo(() => {\n\t\tconst chain: Array<{ id: string; name: string }> = [];\n\t\tif (grandparent) chain.push({ id: grandparent.id, name: grandparent.name });\n\t\tif (parent) chain.push({ id: parent.id, name: parent.name });\n\t\tif (folder) chain.push({ id: folder.id, name: folder.name });\n\t\treturn chain;\n\t}, [folder, parent, grandparent]);\n}\n\nexport const FolderBreadcrumbs: React.FC<FolderBreadcrumbsProps> = ({\n\tfolderId,\n\tonNavigate,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst ancestors = useAncestorChain(folderId);\n\n\tif (!folderId || ancestors.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<BreadcrumbRoot>\n\t\t\t<BreadcrumbList>\n\t\t\t\t<BreadcrumbItem>\n\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\thref=\"#\"\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tonNavigate(\"\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"folderBreadcrumbs.rootLabel\")}\n\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t</BreadcrumbItem>\n\t\t\t\t{ancestors.slice(0, -1).map((item) => (\n\t\t\t\t\t<BreadcrumbItem key={item.id}>\n\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\thref=\"#\"\n\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tonNavigate(item.id);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{item.name}\n\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t))}\n\t\t\t\t{ancestors.length > 0 && (\n\t\t\t\t\t<BreadcrumbItem>\n\t\t\t\t\t\t<BreadcrumbCurrentLink>\n\t\t\t\t\t\t\t{ancestors[ancestors.length - 1].name}\n\t\t\t\t\t\t</BreadcrumbCurrentLink>\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t)}\n\t\t\t</BreadcrumbList>\n\t\t</BreadcrumbRoot>\n\t);\n};\nFolderBreadcrumbs.displayName = \"FolderBreadcrumbs\";\n","import { Button } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport { Box, Flex, HStack, Link, Text } from \"@knkcs/anker/primitives\";\nimport type { ReactNode } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type { RpcErrorDescription } from \"../lib/rpc-errors\";\nimport { useMediahubLinks } from \"../provider\";\n\nexport interface LeakGuardRefusalDialogProps {\n\t/** The mapped leak-guard failure to explain. Callers keep the last refusal\n\t * mounted while the dialog animates closed (same #66 semantics as the\n\t * other dialogs) — `null` renders nothing. */\n\trefusal: RpcErrorDescription | null;\n\topen: boolean;\n\tonClose: () => void;\n}\n\nfunction MaybeLink({\n\thref,\n\tchildren,\n}: {\n\thref?: string;\n\tchildren: ReactNode;\n}): React.JSX.Element {\n\tif (!href) {\n\t\treturn (\n\t\t\t<Text as=\"span\" fontWeight=\"medium\">\n\t\t\t\t{children}\n\t\t\t</Text>\n\t\t);\n\t}\n\treturn (\n\t\t<Link\n\t\t\thref={href}\n\t\t\tfontWeight=\"medium\"\n\t\t\tcolor=\"colorPalette.fg\"\n\t\t\tcolorPalette=\"primary\"\n\t\t\ttextDecoration=\"underline\"\n\t\t>\n\t\t\t{children}\n\t\t</Link>\n\t);\n}\n\n/**\n * Explains a refused Restricted toggle (guardian#55): the refusing rule in\n * human copy plus every offending asset→collection pair, each side linked to\n * its surface when the host registered routes — never a raw error.\n */\nexport const LeakGuardRefusalDialog: React.FC<LeakGuardRefusalDialogProps> = ({\n\trefusal,\n\topen,\n\tonClose,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst links = useMediahubLinks();\n\tif (!refusal) return null;\n\n\tconst exposures = refusal.exposures ?? [];\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonClose={onClose}\n\t\t\tsize=\"md\"\n\t\t\theader={refusal.title}\n\t\t\tfooter={\n\t\t\t\t<HStack gap=\"2\" justify=\"flex-end\">\n\t\t\t\t\t<Button variant=\"outline\" onClick={onClose}>\n\t\t\t\t\t\t{t(\"leakGuardRefusalDialog.closeLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap={3}>\n\t\t\t\t<Text fontSize=\"sm\">{refusal.ruleText ?? refusal.description}</Text>\n\t\t\t\t{exposures.length > 0 && (\n\t\t\t\t\t<Box as=\"ul\" pl={4} display=\"flex\" flexDirection=\"column\" gap={1}>\n\t\t\t\t\t\t{exposures.map((e) => (\n\t\t\t\t\t\t\t<Box as=\"li\" key={`${e.assetId}:${e.collectionId}`} fontSize=\"sm\">\n\t\t\t\t\t\t\t\t<MaybeLink href={links.assetHref?.(e.assetId)}>\n\t\t\t\t\t\t\t\t\t{e.assetName}\n\t\t\t\t\t\t\t\t</MaybeLink>\n\t\t\t\t\t\t\t\t<Text as=\"span\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t\t{\" — in collection \"}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t<MaybeLink href={links.collectionHref?.(e.collectionId)}>\n\t\t\t\t\t\t\t\t\t{e.collectionName}\n\t\t\t\t\t\t\t\t</MaybeLink>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t{t(\"leakGuardRefusalDialog.resolveHint\")}\n\t\t\t\t</Text>\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n};\nLeakGuardRefusalDialog.displayName = \"LeakGuardRefusalDialog\";\n","import type { AssetClient, FolderClient } from \"../clients\";\nimport type { AssetInfo, CollectionInfo, FolderInfo } from \"../types\";\n\n/**\n * Client-side mirror of the service move guards (asset-move and folder-move\n * into a Restricted chain, guardian ADR 0003): the move picker uses these to\n * disable leak-guarded destinations up front with the reason inline. The\n * server re-checks every move — a stale answer here degrades to the server's\n * refusal, never to a leak.\n */\n\n/** Bounds every chain walk, mirroring the service's maxFolderDepth: a chain\n * deeper than this is treated as invalid rather than walked forever. */\nconst maxFolderDepth = 100;\n\nexport function openCollectionIds(collections: CollectionInfo[]): string[] {\n\treturn collections.filter((c) => !c.restricted).map((c) => c.id);\n}\n\n/** Whether an open collection exposes the asset — the condition under which\n * moving it into a Restricted chain is refused. Collections the caller\n * cannot see are Restricted by definition and never count. */\nexport function assetExposedByOpenCollection(\n\tasset: AssetInfo,\n\tcollections: CollectionInfo[],\n): boolean {\n\tconst open = new Set(openCollectionIds(collections));\n\treturn asset.collectionIds.some((id) => open.has(id));\n}\n\n/** Whether the folder or any ancestor is Restricted. Fails closed at the\n * depth bound: an unwalkable chain is treated as confined. */\nexport async function folderChainRestricted(\n\tfolders: FolderClient,\n\tfolder: FolderInfo,\n): Promise<boolean> {\n\tlet f = folder;\n\tfor (let i = 0; i < maxFolderDepth; i++) {\n\t\tif (f.restricted) return true;\n\t\tif (!f.parentId) return false;\n\t\tf = await folders.get(f.parentId);\n\t}\n\treturn true;\n}\n\n/** Whether any asset filed under folderId (transitively) belongs to an open\n * collection — the condition under which moving the folder into a Restricted\n * chain is refused. Restricted sub-branches are pruned: their assets are\n * confined already, so a move changes nothing for them. */\nexport async function folderSubtreeExposed(\n\tclients: { folders: FolderClient; assets: AssetClient },\n\tworkspaceId: string,\n\tfolderId: string,\n\topenIds: string[],\n): Promise<boolean> {\n\tif (openIds.length === 0) return false;\n\tlet frontier = [folderId];\n\tfor (let depth = 0; frontier.length > 0 && depth < maxFolderDepth; depth++) {\n\t\tfor (const id of frontier) {\n\t\t\tconst page = await clients.assets.list(workspaceId, {\n\t\t\t\tfolderId: id,\n\t\t\t\tcollectionIds: openIds,\n\t\t\t});\n\t\t\tif (page.total > 0) return true;\n\t\t}\n\t\tconst next: string[] = [];\n\t\tfor (const id of frontier) {\n\t\t\tconst children = await clients.folders.list(workspaceId, id);\n\t\t\tnext.push(...children.filter((c) => !c.restricted).map((c) => c.id));\n\t\t}\n\t\tfrontier = next;\n\t}\n\treturn false;\n}\n","import { Button, IconButton, Persona } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport {\n\tBadge,\n\tBox,\n\tFlex,\n\tHStack,\n\tNativeSelect,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Lock, X } from \"lucide-react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n\tuseGrantAccess,\n\tuseGrants,\n\tuseRevokeAccess,\n} from \"../hooks/use-grants\";\nimport { useUsers, useWorkspaceMembers } from \"../hooks/use-users\";\nimport { folderChainRestricted } from \"../lib/move-guard\";\nimport { describeRpcError, showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useMediahubClients } from \"../provider\";\nimport type {\n\tAssetInfo,\n\tCollectionInfo,\n\tFolderInfo,\n\tGrantLevel,\n} from \"../types\";\n\n/** What the panel manages access to: the full record is carried so the\n * Derived-Access note can reason about Restricted chains without refetching\n * what the mount site already holds. */\nexport type ManageAccessSubject =\n\t| { kind: \"asset\"; asset: AssetInfo }\n\t| { kind: \"folder\"; folder: FolderInfo }\n\t| { kind: \"collection\"; collection: CollectionInfo };\n\nexport interface ManageAccessDialogProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tsubject: ManageAccessSubject;\n}\n\nfunction subjectId(subject: ManageAccessSubject): string {\n\tswitch (subject.kind) {\n\t\tcase \"asset\":\n\t\t\treturn subject.asset.id;\n\t\tcase \"folder\":\n\t\t\treturn subject.folder.id;\n\t\tcase \"collection\":\n\t\t\treturn subject.collection.id;\n\t}\n}\n\nfunction subjectName(subject: ManageAccessSubject): string {\n\tswitch (subject.kind) {\n\t\tcase \"asset\":\n\t\t\treturn subject.asset.name;\n\t\tcase \"folder\":\n\t\t\treturn subject.folder.name;\n\t\tcase \"collection\":\n\t\t\treturn subject.collection.name;\n\t}\n}\n\n/**\n * \"Manage access\" panel for assets, folders, and collections (guardian#52):\n * a pinned Owner row, the roster of Grants with level dropdowns and revoke,\n * a member picker, and a Derived-Access note. The roster read doubles as the\n * authority gate — the server answers PermissionDenied to everyone but the\n * Owner and workspace admins, and those callers get the denial copy instead\n * of a roster (grantees see content, never who else was granted).\n */\nexport function ManageAccessDialog(\n\tprops: ManageAccessDialogProps,\n): React.JSX.Element {\n\tconst { open, onOpenChange, subject } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst clients = useMediahubClients();\n\tconst kind = subject.kind;\n\tconst resourceId = subjectId(subject);\n\n\t// \"\" = nobody picked yet.\n\tconst [pickedUserId, setPickedUserId] = useState(\"\");\n\tconst [pickLevel, setPickLevel] = useState<GrantLevel>(\"viewer\");\n\n\tconst rosterQuery = useGrants(kind, resourceId, { enabled: open });\n\tconst roster = rosterQuery.data;\n\tconst denied =\n\t\trosterQuery.isError &&\n\t\tdescribeRpcError(rosterQuery.error, \"\").kind === \"permission-denied\";\n\n\t// Fetched only once the caller has proven authority via the roster read —\n\t// non-authorities get the denial copy and nothing else.\n\tconst membersQuery = useWorkspaceMembers({\n\t\tenabled: open && rosterQuery.isSuccess,\n\t});\n\n\tconst rosterUserIds = useMemo(() => {\n\t\tif (!roster) return [];\n\t\tconst ids = roster.grants.map((g) => g.userId);\n\t\tif (roster.ownerUserId) ids.push(roster.ownerUserId);\n\t\treturn ids;\n\t}, [roster]);\n\t// Resolved through the directory rather than the member listing so users\n\t// who since left the workspace still render by name where possible.\n\tconst namesQuery = useUsers(rosterUserIds);\n\tconst nameOf = (userId: string) => namesQuery.data?.[userId] ?? userId;\n\n\t// Whether Derived Access is severed: collections answer from their own\n\t// flag; folders and assets need their chain walked. An unwalkable chain\n\t// counts as Restricted (fail closed), matching the move-guard idiom.\n\tconst scopeQuery = useQuery({\n\t\tqueryKey: [\"mediahub\", \"access-scope\", kind, resourceId],\n\t\tenabled: open && subject.kind !== \"collection\" && rosterQuery.isSuccess,\n\t\tqueryFn: async () => {\n\t\t\tif (subject.kind === \"folder\") {\n\t\t\t\treturn folderChainRestricted(clients.folders, subject.folder);\n\t\t\t}\n\t\t\tif (subject.kind === \"asset\") {\n\t\t\t\tif (!subject.asset.folderId) return false;\n\t\t\t\tconst parent = await clients.folders.get(subject.asset.folderId);\n\t\t\t\treturn folderChainRestricted(clients.folders, parent);\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t});\n\tconst restricted =\n\t\tsubject.kind === \"collection\"\n\t\t\t? subject.collection.restricted\n\t\t\t: scopeQuery.isError\n\t\t\t\t? true\n\t\t\t\t: scopeQuery.data;\n\n\tconst grantAccess = useGrantAccess();\n\tconst revokeAccess = useRevokeAccess();\n\tconst mutating = grantAccess.isPending || revokeAccess.isPending;\n\n\t// Same mount semantics as MoveDialog: keep the Modal mounted, reset\n\t// ephemeral state on reopen.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tsetPickedUserId(\"\");\n\t\tsetPickLevel(\"viewer\");\n\t}, [open]);\n\n\tconst granteeIds = useMemo(\n\t\t() => new Set(roster?.grants.map((g) => g.userId)),\n\t\t[roster],\n\t);\n\t// Candidates: workspace members who are neither the Owner (structural,\n\t// never grantable) nor already on the roster (managed via their row).\n\tconst candidates = useMemo(\n\t\t() =>\n\t\t\t(membersQuery.data ?? []).filter(\n\t\t\t\t(m) => m.id !== roster?.ownerUserId && !granteeIds.has(m.id),\n\t\t\t),\n\t\t[membersQuery.data, roster, granteeIds],\n\t);\n\n\tconst names = namesQuery.data;\n\tconst sortedGrants = useMemo(() => {\n\t\tconst nm = (id: string) => names?.[id] ?? id;\n\t\treturn [...(roster?.grants ?? [])].sort((a, b) =>\n\t\t\tnm(a.userId).localeCompare(nm(b.userId)),\n\t\t);\n\t}, [roster, names]);\n\n\tasync function handleGrant() {\n\t\tif (!pickedUserId) return;\n\t\ttry {\n\t\t\tawait grantAccess.mutateAsync({\n\t\t\t\tresourceType: kind,\n\t\t\t\tresourceId,\n\t\t\t\tuserId: pickedUserId,\n\t\t\t\tlevel: pickLevel,\n\t\t\t});\n\t\t\tsetPickedUserId(\"\");\n\t\t\tsetPickLevel(\"viewer\");\n\t\t\ttoaster.success({ title: t(\"manageAccessDialog.accessGrantedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"manageAccessDialog.grantFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleLevelChange(userId: string, level: GrantLevel) {\n\t\ttry {\n\t\t\tawait grantAccess.mutateAsync({\n\t\t\t\tresourceType: kind,\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t\tlevel,\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"manageAccessDialog.accessUpdatedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"manageAccessDialog.updateFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleRevoke(userId: string) {\n\t\ttry {\n\t\t\tawait revokeAccess.mutateAsync({\n\t\t\t\tresourceType: kind,\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"manageAccessDialog.accessRevokedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"manageAccessDialog.revokeFailedToast\"));\n\t\t}\n\t}\n\n\tconst viewerLabel = t(\"manageAccessDialog.viewerLabel\");\n\tconst editorLabel = t(\"manageAccessDialog.editorLabel\");\n\n\tfunction renderBody() {\n\t\tif (rosterQuery.isLoading) {\n\t\t\treturn (\n\t\t\t\t<Flex justify=\"center\" py=\"8\">\n\t\t\t\t\t<Spinner />\n\t\t\t\t</Flex>\n\t\t\t);\n\t\t}\n\t\tif (denied) {\n\t\t\tconst d = describeRpcError(rosterQuery.error, \"\");\n\t\t\treturn (\n\t\t\t\t<Box py=\"4\">\n\t\t\t\t\t<Text fontWeight=\"medium\">{d.title}</Text>\n\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" mt=\"1\">\n\t\t\t\t\t\t{d.description}\n\t\t\t\t\t</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\t\tif (rosterQuery.isError) {\n\t\t\treturn (\n\t\t\t\t<Box py=\"4\">\n\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.error\">\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescribeRpcError(\n\t\t\t\t\t\t\t\trosterQuery.error,\n\t\t\t\t\t\t\t\tt(\"manageAccessDialog.couldntLoadAccess\"),\n\t\t\t\t\t\t\t).description\n\t\t\t\t\t\t}\n\t\t\t\t\t</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\t\tif (!roster) return null;\n\n\t\treturn (\n\t\t\t<Flex direction=\"column\" gap=\"4\">\n\t\t\t\t{restricted !== undefined && (\n\t\t\t\t\t<HStack\n\t\t\t\t\t\tgap=\"2\"\n\t\t\t\t\t\talign=\"flex-start\"\n\t\t\t\t\t\tpx=\"3\"\n\t\t\t\t\t\tpy=\"2\"\n\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\tbg=\"bg.muted\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{restricted && <Lock size={14} style={{ marginTop: 2 }} />}\n\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t\t{restricted\n\t\t\t\t\t\t\t\t? t(`manageAccessDialog.restrictedAccessNote.${kind}`)\n\t\t\t\t\t\t\t\t: t(`manageAccessDialog.openAccessNote.${kind}`)}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</HStack>\n\t\t\t\t)}\n\n\t\t\t\t<Flex direction=\"column\" gap=\"2\">\n\t\t\t\t\t{roster.ownerUserId && (\n\t\t\t\t\t\t<Flex align=\"center\" gap=\"2\">\n\t\t\t\t\t\t\t<Box flex=\"1\" minW=\"0\">\n\t\t\t\t\t\t\t\t<Persona size=\"sm\" name={nameOf(roster.ownerUserId)} />\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t<Badge variant=\"subtle\">\n\t\t\t\t\t\t\t\t{t(\"manageAccessDialog.ownerBadgeLabel\")}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t</Flex>\n\t\t\t\t\t)}\n\t\t\t\t\t{sortedGrants.map((g) => {\n\t\t\t\t\t\tconst name = nameOf(g.userId);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Flex key={g.userId} align=\"center\" gap=\"2\">\n\t\t\t\t\t\t\t\t<Box flex=\"1\" minW=\"0\">\n\t\t\t\t\t\t\t\t\t<Persona size=\"sm\" name={name} />\n\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\twidth=\"auto\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"manageAccessDialog.accessLevelForAria\", {\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tvalue={g.level}\n\t\t\t\t\t\t\t\t\tdisabled={mutating}\n\t\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\t\thandleLevelChange(g.userId, e.target.value as GrantLevel)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<option value=\"viewer\">{viewerLabel}</option>\n\t\t\t\t\t\t\t\t\t<option value=\"editor\">{editorLabel}</option>\n\t\t\t\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t\t\t\t<IconButton\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"manageAccessDialog.revokeAccessForAria\", {\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tdisabled={mutating}\n\t\t\t\t\t\t\t\t\tonClick={() => handleRevoke(g.userId)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X size={14} />\n\t\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</Flex>\n\n\t\t\t\t<HStack gap=\"2\" align=\"center\">\n\t\t\t\t\t<Box flex=\"1\" minW=\"0\">\n\t\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\taria-label={t(\"manageAccessDialog.addPersonAria\")}\n\t\t\t\t\t\t\tplaceholder={t(\"manageAccessDialog.addPersonLabel\")}\n\t\t\t\t\t\t\tvalue={pickedUserId}\n\t\t\t\t\t\t\tdisabled={membersQuery.isLoading}\n\t\t\t\t\t\t\tonChange={(e) => setPickedUserId(e.target.value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{candidates.map((m) => (\n\t\t\t\t\t\t\t\t<option key={m.id} value={m.id}>\n\t\t\t\t\t\t\t\t\t{m.displayName}\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t</Box>\n\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\twidth=\"auto\"\n\t\t\t\t\t\taria-label={t(\"manageAccessDialog.accessLevelAria\")}\n\t\t\t\t\t\tvalue={pickLevel}\n\t\t\t\t\t\tonChange={(e) => setPickLevel(e.target.value as GrantLevel)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"viewer\">{viewerLabel}</option>\n\t\t\t\t\t\t<option value=\"editor\">{editorLabel}</option>\n\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!pickedUserId}\n\t\t\t\t\t\tloading={grantAccess.isPending}\n\t\t\t\t\t\tonClick={handleGrant}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"manageAccessDialog.grantLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\tsize=\"md\"\n\t\t\theader={t(\"manageAccessDialog.header\", {\n\t\t\t\tsubjectName: subjectName(subject),\n\t\t\t})}\n\t\t\tfooter={\n\t\t\t\t<HStack gap=\"2\" justify=\"flex-end\">\n\t\t\t\t\t<Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n\t\t\t\t\t\t{t(\"manageAccessDialog.doneLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t{renderBody()}\n\t\t</Modal>\n\t);\n}\nManageAccessDialog.displayName = \"ManageAccessDialog\";\n","import { Button, IconButton } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport {\n\tBox,\n\tFlex,\n\tHStack,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { TFunction } from \"i18next\";\nimport { ChevronDown, ChevronRight, Folder, Lock } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useMoveAsset } from \"../hooks/use-assets\";\nimport { useCollections } from \"../hooks/use-collections\";\nimport { useFolders, useMoveFolder } from \"../hooks/use-folders\";\nimport {\n\tassetExposedByOpenCollection,\n\tfolderChainRestricted,\n\tfolderSubtreeExposed,\n\topenCollectionIds,\n} from \"../lib/move-guard\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { AssetInfo, FolderInfo } from \"../types\";\n\n/** What the dialog moves: a folder (from the tree's context menu) or an\n * asset (from its detail view). */\nexport type MoveSubject =\n\t| { kind: \"folder\"; folder: FolderInfo }\n\t| { kind: \"asset\"; asset: AssetInfo };\n\nexport interface MoveDialogProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tsubject: MoveSubject;\n\t/** Called after a successful move with the destination folder id\n\t * (\"\" = workspace root). */\n\tonMoved?: (destinationId: string) => void;\n}\n\nfunction subjectName(subject: MoveSubject): string {\n\treturn subject.kind === \"folder\" ? subject.folder.name : subject.asset.name;\n}\n\n/** The destination the subject currently sits in (\"\" = workspace root). */\nfunction currentParentId(subject: MoveSubject): string {\n\treturn subject.kind === \"folder\"\n\t\t? subject.folder.parentId\n\t\t: subject.asset.folderId;\n}\n\ninterface RowContext {\n\tsubject: MoveSubject;\n\t/** The subject is exposed through an open collection, so Restricted\n\t * destinations would trip the server's leak guard. */\n\tguardActive: boolean;\n\tselectedId: string | null;\n\tonSelect: (id: string) => void;\n\t/** Drops the selection iff it still points at this id — rows call it\n\t * when they become disabled under an already-made selection. */\n\tonDeselect: (id: string) => void;\n\tcurrentLocationLabel: string;\n\tselfLocationLabel: string;\n\tblockedLabel: string;\n\tt: TFunction;\n}\n\n/** Why a destination row is disabled, or null when it is selectable. */\nfunction rowDisabledReason(\n\tctx: RowContext,\n\tfolder: FolderInfo,\n\tchainRestricted: boolean,\n): string | null {\n\tif (ctx.subject.kind === \"folder\" && folder.id === ctx.subject.folder.id) {\n\t\treturn ctx.selfLocationLabel;\n\t}\n\tif (folder.id === currentParentId(ctx.subject)) {\n\t\treturn ctx.currentLocationLabel;\n\t}\n\tif (ctx.guardActive && chainRestricted) {\n\t\treturn ctx.blockedLabel;\n\t}\n\treturn null;\n}\n\ninterface DestinationRowButtonProps {\n\tname: string;\n\t/** Disabled-with-reason when set; selectable when null. */\n\treason: string | null;\n\tselected: boolean;\n\trestricted?: boolean;\n\temphasized?: boolean;\n\tonClick: () => void;\n}\n\n/** The selectable body shared by every destination row, root included. */\nfunction DestinationRowButton({\n\tname,\n\treason,\n\tselected,\n\trestricted,\n\temphasized,\n\tonClick,\n}: DestinationRowButtonProps): React.JSX.Element {\n\treturn (\n\t\t<Box\n\t\t\tasChild\n\t\t\tflex=\"1\"\n\t\t\tpx=\"2\"\n\t\t\tpy=\"1\"\n\t\t\trounded=\"md\"\n\t\t\ttextAlign=\"left\"\n\t\t\tcursor={reason ? \"not-allowed\" : \"pointer\"}\n\t\t\topacity={reason ? 0.5 : 1}\n\t\t\tbg={selected ? \"colorPalette.subtle\" : \"transparent\"}\n\t\t\tcolor={selected ? \"colorPalette.fg\" : \"fg.default\"}\n\t\t\tcolorPalette=\"primary\"\n\t\t\t_hover={{ bg: selected ? \"colorPalette.subtle\" : \"bg.muted\" }}\n\t\t>\n\t\t\t<button type=\"button\" disabled={!!reason} onClick={onClick}>\n\t\t\t\t<HStack gap=\"2\" align=\"center\">\n\t\t\t\t\t{restricted ? <Lock size={13} /> : <Folder size={13} />}\n\t\t\t\t\t<Text fontSize=\"sm\" fontWeight={emphasized ? \"medium\" : \"normal\"}>\n\t\t\t\t\t\t{name}\n\t\t\t\t\t</Text>\n\t\t\t\t</HStack>\n\t\t\t\t{reason && (\n\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t\t{reason}\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t</button>\n\t\t</Box>\n\t);\n}\n\ninterface DestinationRowProps {\n\tctx: RowContext;\n\tfolder: FolderInfo;\n\t/** Whether any ancestor in the picker walk is Restricted. */\n\tancestorRestricted: boolean;\n\tlevel: number;\n}\n\nfunction DestinationRow({\n\tctx,\n\tfolder,\n\tancestorRestricted,\n\tlevel,\n}: DestinationRowProps): React.JSX.Element {\n\tconst [expanded, setExpanded] = useState(false);\n\tconst childrenQuery = useFolders(folder.id, { enabled: expanded });\n\n\tconst chainRestricted = ancestorRestricted || folder.restricted;\n\tconst reason = rowDisabledReason(ctx, folder, chainRestricted);\n\tconst isSelf =\n\t\tctx.subject.kind === \"folder\" && folder.id === ctx.subject.folder.id;\n\tconst selected = ctx.selectedId === folder.id;\n\n\t// A selection must not survive its own disabling: the exposure probe can\n\t// resolve after the user already picked a Restricted destination.\n\tconst { onDeselect } = ctx;\n\tuseEffect(() => {\n\t\tif (selected && reason) onDeselect(folder.id);\n\t}, [selected, reason, folder.id, onDeselect]);\n\n\treturn (\n\t\t<>\n\t\t\t<Flex align=\"center\" gap=\"1\" pl={level * 4}>\n\t\t\t\t{/* The subject folder's subtree moves with it — never expandable. */}\n\t\t\t\t{isSelf ? (\n\t\t\t\t\t<Box w=\"6\" />\n\t\t\t\t) : (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\texpanded\n\t\t\t\t\t\t\t\t? ctx.t(\"moveDialog.collapseAria\", { folderName: folder.name })\n\t\t\t\t\t\t\t\t: ctx.t(\"moveDialog.expandAria\", { folderName: folder.name })\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonClick={() => setExpanded((e) => !e)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n\t\t\t\t\t</IconButton>\n\t\t\t\t)}\n\t\t\t\t<DestinationRowButton\n\t\t\t\t\tname={folder.name}\n\t\t\t\t\treason={reason}\n\t\t\t\t\tselected={selected}\n\t\t\t\t\trestricted={folder.restricted}\n\t\t\t\t\tonClick={() => ctx.onSelect(folder.id)}\n\t\t\t\t/>\n\t\t\t</Flex>\n\t\t\t{expanded && childrenQuery.isLoading && (\n\t\t\t\t<Flex justify=\"center\" py=\"1\">\n\t\t\t\t\t<Spinner size=\"xs\" />\n\t\t\t\t</Flex>\n\t\t\t)}\n\t\t\t{expanded &&\n\t\t\t\tchildrenQuery.data?.map((child) => (\n\t\t\t\t\t<DestinationRow\n\t\t\t\t\t\tkey={child.id}\n\t\t\t\t\t\tctx={ctx}\n\t\t\t\t\t\tfolder={child}\n\t\t\t\t\t\tancestorRestricted={chainRestricted}\n\t\t\t\t\t\tlevel={level + 1}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t</>\n\t);\n}\n\n/**\n * Destination folder picker for moving a folder or an asset. Destinations\n * that would trip the server's leak guard (moving exposed content into a\n * Restricted chain, guardian ADR 0003) render disabled with the reason\n * inline; the server remains authoritative and re-checks every move.\n */\nexport function MoveDialog(props: MoveDialogProps): React.JSX.Element {\n\tconst { open, onOpenChange, subject, onMoved } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst clients = useMediahubClients();\n\tconst [selectedId, setSelectedId] = useState<string | null>(null);\n\n\tconst rootQuery = useFolders(\"\");\n\tconst collectionsQuery = useCollections();\n\tconst collections = collectionsQuery.data ?? [];\n\tconst openIds = useMemo(() => openCollectionIds(collections), [collections]);\n\n\tconst moveFolder = useMoveFolder();\n\tconst moveAsset = useMoveAsset();\n\n\t// Whether moving the subject into a Restricted chain would trip the\n\t// server's leak guard. Assets carry their collection memberships, so the\n\t// answer is synchronous; folders need the subtree probed.\n\tconst subjectFolderId = subject.kind === \"folder\" ? subject.folder.id : \"\";\n\tconst folderGuardQuery = useQuery({\n\t\tqueryKey: [\"mediahub\", \"move-guard\", subjectFolderId, openIds],\n\t\tqueryFn: async () => {\n\t\t\tif (subject.kind !== \"folder\") return false;\n\t\t\t// A subject already confined by a Restricted chain can move\n\t\t\t// anywhere — the move changes nothing for its audience.\n\t\t\tif (await folderChainRestricted(clients.folders, subject.folder)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn folderSubtreeExposed(\n\t\t\t\t{ folders: clients.folders, assets: clients.assets },\n\t\t\t\tworkspaceId,\n\t\t\t\tsubject.folder.id,\n\t\t\t\topenIds,\n\t\t\t);\n\t\t},\n\t\tenabled: open && subject.kind === \"folder\" && collectionsQuery.isSuccess,\n\t});\n\tconst guardActive =\n\t\tsubject.kind === \"asset\"\n\t\t\t? assetExposedByOpenCollection(subject.asset, collections)\n\t\t\t: folderGuardQuery.data === true;\n\n\t// Same mount semantics as CollectionPicker (#66): keep the Modal mounted,\n\t// reset ephemeral state on exit *and* on reopen.\n\tfunction resetEphemeralState() {\n\t\tsetSelectedId(null);\n\t}\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: reset only on open→true\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tresetEphemeralState();\n\t}, [open]);\n\n\tasync function handleConfirm() {\n\t\tif (selectedId === null) return;\n\t\ttry {\n\t\t\tif (subject.kind === \"folder\") {\n\t\t\t\tawait moveFolder.mutateAsync({\n\t\t\t\t\tid: subject.folder.id,\n\t\t\t\t\tparentId: selectedId,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait moveAsset.mutateAsync({\n\t\t\t\t\tid: subject.asset.id,\n\t\t\t\t\tfolderId: selectedId,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttoaster.success({\n\t\t\t\ttitle:\n\t\t\t\t\tsubject.kind === \"folder\"\n\t\t\t\t\t\t? t(\"moveDialog.folderMovedToast\")\n\t\t\t\t\t\t: t(\"moveDialog.assetMovedToast\"),\n\t\t\t});\n\t\t\tonMoved?.(selectedId);\n\t\t\tonOpenChange(false);\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"moveDialog.moveFailedToast\"));\n\t\t}\n\t}\n\n\tconst handleDeselect = useCallback((id: string) => {\n\t\tsetSelectedId((current) => (current === id ? null : current));\n\t}, []);\n\n\tconst ctx: RowContext = {\n\t\tsubject,\n\t\tguardActive,\n\t\tselectedId,\n\t\tonSelect: setSelectedId,\n\t\tonDeselect: handleDeselect,\n\t\tcurrentLocationLabel: t(\"moveDialog.currentLocationLabel\"),\n\t\tselfLocationLabel: t(\"moveDialog.selfLocationLabel\"),\n\t\tblockedLabel:\n\t\t\tsubject.kind === \"asset\"\n\t\t\t\t? t(\"moveDialog.blockedAssetLabel\")\n\t\t\t\t: t(\"moveDialog.blockedFolderLabel\", {\n\t\t\t\t\t\tfolderName: subject.folder.name,\n\t\t\t\t\t}),\n\t\tt,\n\t};\n\n\tconst rootReason =\n\t\tcurrentParentId(subject) === \"\" ? ctx.currentLocationLabel : null;\n\tconst moving = moveFolder.isPending || moveAsset.isPending;\n\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={resetEphemeralState}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\tsize=\"md\"\n\t\t\theader={t(\"moveDialog.header\", { subjectName: subjectName(subject) })}\n\t\t\tfooter={\n\t\t\t\t<HStack gap=\"2\" justify=\"flex-end\">\n\t\t\t\t\t<Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n\t\t\t\t\t\t{t(\"moveDialog.cancelLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={selectedId === null}\n\t\t\t\t\t\tloading={moving}\n\t\t\t\t\t\tonClick={handleConfirm}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"moveDialog.confirmLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap=\"0.5\" minH=\"240px\">\n\t\t\t\t<Flex align=\"center\" gap=\"1\">\n\t\t\t\t\t<Box w=\"6\" />\n\t\t\t\t\t<DestinationRowButton\n\t\t\t\t\t\tname={t(\"moveDialog.rootLabel\")}\n\t\t\t\t\t\treason={rootReason}\n\t\t\t\t\t\tselected={selectedId === \"\"}\n\t\t\t\t\t\temphasized\n\t\t\t\t\t\tonClick={() => setSelectedId(\"\")}\n\t\t\t\t\t/>\n\t\t\t\t</Flex>\n\t\t\t\t{rootQuery.isLoading ? (\n\t\t\t\t\t<Flex justify=\"center\" py=\"6\">\n\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t</Flex>\n\t\t\t\t) : (\n\t\t\t\t\t(rootQuery.data ?? []).map((folder) => (\n\t\t\t\t\t\t<DestinationRow\n\t\t\t\t\t\t\tkey={folder.id}\n\t\t\t\t\t\t\tctx={ctx}\n\t\t\t\t\t\t\tfolder={folder}\n\t\t\t\t\t\t\tancestorRestricted={false}\n\t\t\t\t\t\t\tlevel={0}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n}\nMoveDialog.displayName = \"MoveDialog\";\n","import { Box, Flex, Text } from \"@knkcs/anker/primitives\";\nimport type { TFunction } from \"i18next\";\nimport { Lock } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\n\n/** The shared Restricted-container warning (guardian#48): shown when creating\n * a Restricted folder and, with the other noun, on the collection dialog's\n * Restricted switch. Takes `t` explicitly (rather than calling\n * `useTranslation` itself) so it stays callable from non-component code. */\nexport function restrictedContainerWarning(\n\tkind: \"folder\" | \"collection\",\n\tt: TFunction,\n): string {\n\treturn t(`restricted.containerWarning.${kind}`);\n}\n\n/** The explicit unrestrict disclosure (guardian#55): spelled out before the\n * toggle because it widens the audience to the whole workspace. */\nexport function unrestrictDisclosure(\n\tkind: \"folder\" | \"collection\",\n\tname: string,\n\tt: TFunction,\n): string {\n\treturn t(`restricted.unrestrictDisclosure.${kind}`, { name });\n}\n\nexport interface RestrictedLockBadgeProps {\n\t/** Icon size in px. @default 12 */\n\tsize?: number;\n\t/** Optional left margin (spacing token) for sites without a gap parent. */\n\tml?: number;\n}\n\n/** Lock marker rendered wherever a Restricted container appears. The\n * `aria-label=\"Restricted\"` is the contract tests target — keep it stable. */\nexport const RestrictedLockBadge: React.FC<RestrictedLockBadgeProps> = ({\n\tsize = 12,\n\tml,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\treturn (\n\t\t<Box\n\t\t\trole=\"img\"\n\t\t\taria-label={t(\"restricted.lockBadgeAria\")}\n\t\t\tcolor=\"fg.muted\"\n\t\t\tflexShrink={0}\n\t\t\tml={ml}\n\t\t>\n\t\t\t<Lock size={size} />\n\t\t</Box>\n\t);\n};\nRestrictedLockBadge.displayName = \"RestrictedLockBadge\";\n\nexport interface RestrictedWarningNoticeProps {\n\tkind: \"folder\" | \"collection\";\n}\n\n/** Warning banner for the deliberate create-Restricted paths. */\nexport const RestrictedWarningNotice: React.FC<\n\tRestrictedWarningNoticeProps\n> = ({ kind }) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\treturn (\n\t\t<Flex\n\t\t\tgap={2}\n\t\t\tp={3}\n\t\t\trounded=\"md\"\n\t\t\tbg=\"bg.muted\"\n\t\t\tcolor=\"fg.muted\"\n\t\t\tfontSize=\"sm\"\n\t\t\talign=\"flex-start\"\n\t\t>\n\t\t\t<Box flexShrink={0} mt={0.5}>\n\t\t\t\t<Lock size={14} />\n\t\t\t</Box>\n\t\t\t<Text>{restrictedContainerWarning(kind, t)}</Text>\n\t\t</Flex>\n\t);\n};\nRestrictedWarningNotice.displayName = \"RestrictedWarningNotice\";\n","import { TextInput } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport { Flex, toaster } from \"@knkcs/anker/primitives\";\nimport { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCreateFolder } from \"../hooks/use-folders\";\nimport { RestrictedWarningNotice } from \"./restricted\";\n\nexport interface RestrictedFolderDialogProps {\n\topen: boolean;\n\tonClose: () => void;\n\t/** Parent folder to create under; \"\" creates at the root. */\n\tparentId: string;\n\t/** Called after a successful create (e.g. to refresh the tree). */\n\tonCreated?: () => void;\n}\n\n/** Deliberate-path dialog for creating a Restricted folder. The everyday\n * inline \"New Folder\" input stays the fast path for ordinary folders. */\nexport const RestrictedFolderDialog: React.FC<RestrictedFolderDialogProps> = ({\n\topen,\n\tonClose,\n\tparentId,\n\tonCreated,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst [name, setName] = useState(\"\");\n\tconst createFolder = useCreateFolder();\n\n\t// Re-arm on open rather than clearing on close: zag presence can skip\n\t// onExitComplete when a reopen interrupts the exit animation (#73), and\n\t// clearing on the close transition would blank the field mid-fade.\n\tuseEffect(() => {\n\t\tif (open) setName(\"\");\n\t}, [open]);\n\n\tasync function handleCreate() {\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) return;\n\t\ttry {\n\t\t\tawait createFolder.mutateAsync({\n\t\t\t\tname: trimmed,\n\t\t\t\tslug: trimmed.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tparentId,\n\t\t\t\trestricted: true,\n\t\t\t});\n\t\t\ttoaster.success({\n\t\t\t\ttitle: t(\"restrictedFolderDialog.createSuccessToast\"),\n\t\t\t});\n\t\t\tonCreated?.();\n\t\t\tonClose();\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\ttoaster.error({\n\t\t\t\ttitle: t(\"restrictedFolderDialog.createFailedToast\"),\n\t\t\t\tdescription: msg,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Do NOT `return null` when closed: unmounting the open dialog machine\n\t// under StrictMode orphans its scroll-lock/aria-hidden cleanup and wedges\n\t// the whole app (#66). Keep Modal mounted; lazyMount/unmountOnExit keep\n\t// the fresh-content-per-open semantics.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonClose={onClose}\n\t\t\theader={t(\"restrictedFolderDialog.header\")}\n\t\t\tonSave={handleCreate}\n\t\t\tsaveLabel={t(\"restrictedFolderDialog.createLabel\")}\n\t\t\tsaveDisabled={!name.trim()}\n\t\t\tloading={createFolder.isPending}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap={3}>\n\t\t\t\t<RestrictedWarningNotice kind=\"folder\" />\n\t\t\t\t<TextInput\n\t\t\t\t\tvalue={name}\n\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\tif (e.key === \"Enter\") handleCreate();\n\t\t\t\t\t}}\n\t\t\t\t\tautoFocus\n\t\t\t\t\tplaceholder={t(\"restrictedFolderDialog.namePlaceholder\")}\n\t\t\t\t/>\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n};\nRestrictedFolderDialog.displayName = \"RestrictedFolderDialog\";\n","import { TextInput } from \"@knkcs/anker/atoms\";\nimport {\n\tTreeViewBranchControl,\n\tTreeViewBranchIndicator,\n\tTreeViewBranchText,\n\tTreeViewNode,\n\tTreeViewRoot,\n\tTreeViewTree,\n\tcreateTreeCollection,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBox,\n\tFlex,\n\tMenuContent,\n\tMenuItem,\n\tMenuRoot,\n\tMenuTrigger,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { Ellipsis, FolderPlus } from \"lucide-react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCanManage } from \"../hooks/use-authz\";\nimport {\n\tuseCreateFolder,\n\tuseDeleteFolder,\n\tuseFolders,\n\tuseSetFolderRestricted,\n\tuseUpdateFolder,\n} from \"../hooks/use-folders\";\nimport {\n\ttype RpcErrorDescription,\n\tdescribeRpcError,\n\tshowRpcErrorToast,\n} from \"../lib/rpc-errors\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { FolderInfo } from \"../types\";\nimport { LeakGuardRefusalDialog } from \"./leak-guard-refusal-dialog\";\nimport { ManageAccessDialog } from \"./manage-access-dialog\";\nimport { MoveDialog } from \"./move-dialog\";\nimport { RestrictedLockBadge } from \"./restricted\";\nimport { RestrictedFolderDialog } from \"./restricted-folder-dialog\";\n\ninterface FolderTreeProps {\n\tactiveFolderId: string;\n\tonFolderSelect: (folderId: string) => void;\n}\n\ninterface FolderNode {\n\tid: string;\n\tname: string;\n\trestricted: boolean;\n\tchildren: FolderNode[];\n\t/** The full folder record, for actions that need more than id/name\n\t * (Move… hands it to the destination picker). Absent only on the\n\t * synthetic collection root, which never renders a row. */\n\tinfo?: FolderInfo;\n}\n\nexport const FolderTree: React.FC<FolderTreeProps> = ({\n\tactiveFolderId,\n\tonFolderSelect,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst rootQuery = useFolders(\"\");\n\tconst rootFolders: FolderInfo[] = rootQuery.data ?? [];\n\tconst [treeKey, setTreeKey] = useState(0);\n\tconst [isCreating, setIsCreating] = useState(false);\n\tconst [newName, setNewName] = useState(\"\");\n\tconst [renamingId, setRenamingId] = useState<string | null>(null);\n\tconst [renameValue, setRenameValue] = useState(\"\");\n\tconst [moveSubject, setMoveSubject] = useState<FolderInfo | null>(null);\n\tconst [moveOpen, setMoveOpen] = useState(false);\n\tconst [accessSubject, setAccessSubject] = useState<FolderInfo | null>(null);\n\tconst [accessOpen, setAccessOpen] = useState(false);\n\t// Parent for the \"New Restricted folder…\" dialog; null = closed.\n\tconst [restrictedParentId, setRestrictedParentId] = useState<string | null>(\n\t\tnull,\n\t);\n\t// The node whose context menu was last opened — the authority probe runs\n\t// for it lazily, so the tree never probes every visible row.\n\tconst [menuNodeId, setMenuNodeId] = useState(\"\");\n\t// Kept mounted while a refusal exists (dialog machines must not unmount\n\t// mid-exit, see collection-picker / #66).\n\tconst [toggleRefusal, setToggleRefusal] =\n\t\tuseState<RpcErrorDescription | null>(null);\n\tconst [refusalOpen, setRefusalOpen] = useState(false);\n\tconst createFolder = useCreateFolder();\n\tconst updateFolder = useUpdateFolder();\n\tconst deleteFolder = useDeleteFolder();\n\tconst setFolderRestricted = useSetFolderRestricted();\n\tconst canManage = useCanManage(\"folder\", menuNodeId);\n\tconst { confirm } = useConfirmModal();\n\tconst creatingRef = useRef(false);\n\tconst renamingRef = useRef(false);\n\tconst { folders } = useMediahubClients();\n\n\tconst collection = useMemo(() => {\n\t\tconst rootChildren: FolderNode[] = rootFolders.map((f) => ({\n\t\t\tid: f.id,\n\t\t\tname: f.name,\n\t\t\trestricted: f.restricted,\n\t\t\tchildren: [],\n\t\t\tinfo: f,\n\t\t}));\n\t\treturn createTreeCollection<FolderNode>({\n\t\t\trootNode: {\n\t\t\t\tid: \"root\",\n\t\t\t\tname: \"Root\",\n\t\t\t\trestricted: false,\n\t\t\t\tchildren: rootChildren,\n\t\t\t},\n\t\t\tnodeToValue: (node) => node.id,\n\t\t\tnodeToString: (node) => node.name,\n\t\t\t// Return 1 for empty children so all folders are treated as branches\n\t\t\t// (expandable) even before their children are lazy-loaded.\n\t\t\tnodeToChildrenCount: (node) =>\n\t\t\t\tnode.children.length > 0 ? node.children.length : 1,\n\t\t});\n\t}, [rootFolders]);\n\n\tconst handleLoadChildren = useCallback(\n\t\tasync ({ node }: { node: FolderNode }) => {\n\t\t\tconst res = await folders.list(workspaceId, node.id);\n\t\t\treturn res.map(\n\t\t\t\t(f): FolderNode => ({\n\t\t\t\t\tid: f.id,\n\t\t\t\t\tname: f.name,\n\t\t\t\t\trestricted: f.restricted,\n\t\t\t\t\tchildren: [],\n\t\t\t\t\tinfo: f,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t[folders, workspaceId],\n\t);\n\n\tasync function handleDelete(folderId: string, folderName: string) {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"folderTree.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"folderTree.deleteConfirmMessage\", { folderName }),\n\t\t\tconfirmLabel: t(\"folderTree.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteFolder.mutateAsync(folderId);\n\t\t\tif (activeFolderId === folderId) onFolderSelect(\"\");\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({ title: t(\"folderTree.deleteSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"folderTree.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleRenameSubmit(node: FolderNode) {\n\t\tif (renamingRef.current) return;\n\t\tconst trimmed = renameValue.trim();\n\t\tif (!trimmed || trimmed === node.name) {\n\t\t\tsetRenamingId(null);\n\t\t\treturn;\n\t\t}\n\t\trenamingRef.current = true;\n\t\ttry {\n\t\t\tawait updateFolder.mutateAsync({ id: node.id, name: trimmed });\n\t\t\tsetRenamingId(null);\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({ title: t(\"folderTree.renameSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"folderTree.renameFailedToast\"));\n\t\t} finally {\n\t\t\trenamingRef.current = false;\n\t\t}\n\t}\n\n\tasync function handleToggleRestricted(node: FolderNode) {\n\t\tconst restricting = !node.restricted;\n\t\tif (!restricting) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"folderTree.unrestrictConfirmTitle\"),\n\t\t\t\tmessage: t(\"folderTree.unrestrictConfirmMessage\", {\n\t\t\t\t\tfolderName: node.name,\n\t\t\t\t}),\n\t\t\t\tconfirmLabel: t(\"folderTree.unrestrictConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\ttry {\n\t\t\tawait setFolderRestricted.mutateAsync({\n\t\t\t\tid: node.id,\n\t\t\t\trestricted: restricting,\n\t\t\t});\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({\n\t\t\t\ttitle: restricting\n\t\t\t\t\t? t(\"folderTree.folderRestrictedToast\")\n\t\t\t\t\t: t(\"folderTree.folderUnrestrictedToast\"),\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconst fallback = restricting\n\t\t\t\t? t(\"folderTree.restrictFailedToast\")\n\t\t\t\t: t(\"folderTree.unrestrictFailedToast\");\n\t\t\tconst described = describeRpcError(err, fallback);\n\t\t\t// A guard refusal gets the explanation dialog with the offending\n\t\t\t// pairs — never a raw error (guardian#55).\n\t\t\tif (described.kind === \"leak-guard\") {\n\t\t\t\tsetToggleRefusal(described);\n\t\t\t\tsetRefusalOpen(true);\n\t\t\t} else {\n\t\t\t\tshowRpcErrorToast(err, fallback);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function handleCreate() {\n\t\tif (creatingRef.current) return;\n\t\tconst trimmed = newName.trim();\n\t\tif (!trimmed) {\n\t\t\tsetIsCreating(false);\n\t\t\treturn;\n\t\t}\n\t\tcreatingRef.current = true;\n\t\ttry {\n\t\t\tawait createFolder.mutateAsync({\n\t\t\t\tname: trimmed,\n\t\t\t\tslug: trimmed.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tparentId: activeFolderId || \"\",\n\t\t\t});\n\t\t\tsetNewName(\"\");\n\t\t\tsetIsCreating(false);\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({ title: t(\"folderTree.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"folderTree.createFailedToast\"));\n\t\t} finally {\n\t\t\tcreatingRef.current = false;\n\t\t}\n\t}\n\n\treturn (\n\t\t<Flex direction=\"column\" flex={1} gap={0.5}>\n\t\t\t<Flex\n\t\t\t\talign=\"center\"\n\t\t\t\tpx={2}\n\t\t\t\tpy={1}\n\t\t\t\trounded=\"md\"\n\t\t\t\tcursor=\"pointer\"\n\t\t\t\tbg={!activeFolderId ? \"colorPalette.subtle\" : \"transparent\"}\n\t\t\t\tcolor={!activeFolderId ? \"colorPalette.fg\" : \"fg.default\"}\n\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t_hover={{\n\t\t\t\t\tbg: !activeFolderId ? \"colorPalette.subtle\" : \"bg.muted\",\n\t\t\t\t}}\n\t\t\t\tonClick={() => onFolderSelect(\"\")}\n\t\t\t\tfontSize=\"sm\"\n\t\t\t\tfontWeight=\"medium\"\n\t\t\t\tcss={{\n\t\t\t\t\t\"& > [data-folder-menu]\": { opacity: 0 },\n\t\t\t\t\t\"&:hover > [data-folder-menu]\": { opacity: 1 },\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{t(\"folderTree.allAssets\")}\n\t\t\t\t<Box data-folder-menu=\"\" transition=\"opacity 0.1s\" ml=\"auto\">\n\t\t\t\t\t<MenuRoot>\n\t\t\t\t\t\t<MenuTrigger asChild>\n\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t\t\t\t_hover={{ color: \"fg.default\" }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"folderTree.allAssetsMenuAria\")}\n\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Ellipsis size={12} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t</MenuTrigger>\n\t\t\t\t\t\t<MenuContent>\n\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\tvalue=\"new-restricted\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tsetRestrictedParentId(\"\");\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"folderTree.newRestrictedFolder\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t</MenuContent>\n\t\t\t\t\t</MenuRoot>\n\t\t\t\t</Box>\n\t\t\t</Flex>\n\n\t\t\t{rootFolders.length > 0 && (\n\t\t\t\t<TreeViewRoot\n\t\t\t\t\tkey={treeKey}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\tselectedValue={activeFolderId ? [activeFolderId] : []}\n\t\t\t\t\tonSelectionChange={(details) => {\n\t\t\t\t\t\tconst selected = details.selectedValue[0];\n\t\t\t\t\t\tif (selected) onFolderSelect(selected);\n\t\t\t\t\t}}\n\t\t\t\t\tloadChildren={handleLoadChildren}\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t>\n\t\t\t\t\t<TreeViewTree>\n\t\t\t\t\t\t<TreeViewNode<FolderNode>\n\t\t\t\t\t\t\trender={({ node }) =>\n\t\t\t\t\t\t\t\trenamingId === node.id ? (\n\t\t\t\t\t\t\t\t\t<TreeViewBranchControl>\n\t\t\t\t\t\t\t\t\t\t<TreeViewBranchIndicator />\n\t\t\t\t\t\t\t\t\t\t{/* Keep clicks and keystrokes out of the tree's\n\t\t\t\t\t\t\t\t\t\t selection/typeahead machinery. */}\n\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\tflex=\"1\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={renameValue}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => setRenameValue(e.target.value)}\n\t\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (e.key === \"Enter\") handleRenameSubmit(node);\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (e.key === \"Escape\") setRenamingId(null);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tonBlur={() => handleRenameSubmit(node)}\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</TreeViewBranchControl>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<TreeViewBranchControl\n\t\t\t\t\t\t\t\t\t\tcss={{\n\t\t\t\t\t\t\t\t\t\t\t\"& > [data-folder-menu]\": {\n\t\t\t\t\t\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"&:hover > [data-folder-menu]\": {\n\t\t\t\t\t\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<TreeViewBranchIndicator />\n\t\t\t\t\t\t\t\t\t\t<TreeViewBranchText>{node.name}</TreeViewBranchText>\n\t\t\t\t\t\t\t\t\t\t{node.restricted && <RestrictedLockBadge ml={1} />}\n\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\tdata-folder-menu=\"\"\n\t\t\t\t\t\t\t\t\t\t\ttransition=\"opacity 0.1s\"\n\t\t\t\t\t\t\t\t\t\t\tml=\"auto\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<MenuRoot\n\t\t\t\t\t\t\t\t\t\t\t\tonOpenChange={({ open }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (open) setMenuNodeId(node.id);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<MenuTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_hover={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"fg.default\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"folderTree.folderMenuAria\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfolderName: node.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Ellipsis size={12} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t\t\t\t</MenuTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<MenuContent>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"rename\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetRenameValue(node.name);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetRenamingId(node.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.rename\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"move\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!node.info) return;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMoveSubject(node.info);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMoveOpen(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.move\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"manage-access\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!node.info) return;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetAccessSubject(node.info);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetAccessOpen(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.manageAccess\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"new-restricted\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetRestrictedParentId(node.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.newRestrictedFolder\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Authority-only (Owner or workspace admin):\n\t\t\t\t\t\t\t\t\t\t\t\t\t appears once the lazy probe confirms. */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{menuNodeId === node.id &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcanManage.data === true && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"toggle-restricted\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleToggleRestricted(node);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{node.restricted\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"folderTree.unrestrict\")\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"folderTree.restrict\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"delete\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"fg.error\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleDelete(node.id, node.name);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.delete\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t</MenuContent>\n\t\t\t\t\t\t\t\t\t\t\t</MenuRoot>\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</TreeViewBranchControl>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</TreeViewTree>\n\t\t\t\t</TreeViewRoot>\n\t\t\t)}\n\n\t\t\t<Box flex={1} />\n\n\t\t\t{isCreating ? (\n\t\t\t\t<Box px={2} py={1}>\n\t\t\t\t\t<TextInput\n\t\t\t\t\t\tvalue={newName}\n\t\t\t\t\t\tonChange={(e) => setNewName(e.target.value)}\n\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\tif (e.key === \"Enter\") handleCreate();\n\t\t\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\t\t\tsetIsCreating(false);\n\t\t\t\t\t\t\t\tsetNewName(\"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonBlur={handleCreate}\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\tplaceholder={t(\"folderTree.newFolderPlaceholder\")}\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t) : (\n\t\t\t\t<Flex\n\t\t\t\t\talign=\"center\"\n\t\t\t\t\tgap={1}\n\t\t\t\t\tpx={2}\n\t\t\t\t\tpy={1}\n\t\t\t\t\trounded=\"md\"\n\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t_hover={{ bg: \"bg.muted\" }}\n\t\t\t\t\tonClick={() => setIsCreating(true)}\n\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t>\n\t\t\t\t\t<FolderPlus size={14} />\n\t\t\t\t\t<Text>{t(\"folderTree.newFolder\")}</Text>\n\t\t\t\t</Flex>\n\t\t\t)}\n\n\t\t\t{/* Kept mounted while a subject exists (dialog machines must not\n\t\t\t unmount mid-exit, see collection-picker / #66). */}\n\t\t\t{moveSubject && (\n\t\t\t\t<MoveDialog\n\t\t\t\t\topen={moveOpen}\n\t\t\t\t\tonOpenChange={setMoveOpen}\n\t\t\t\t\tsubject={{ kind: \"folder\", folder: moveSubject }}\n\t\t\t\t\tonMoved={() => setTreeKey((k) => k + 1)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{accessSubject && (\n\t\t\t\t<ManageAccessDialog\n\t\t\t\t\topen={accessOpen}\n\t\t\t\t\tonOpenChange={setAccessOpen}\n\t\t\t\t\tsubject={{ kind: \"folder\", folder: accessSubject }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<RestrictedFolderDialog\n\t\t\t\topen={restrictedParentId !== null}\n\t\t\t\tparentId={restrictedParentId ?? \"\"}\n\t\t\t\tonClose={() => setRestrictedParentId(null)}\n\t\t\t\tonCreated={() => setTreeKey((k) => k + 1)}\n\t\t\t/>\n\t\t\t<LeakGuardRefusalDialog\n\t\t\t\trefusal={toggleRefusal}\n\t\t\t\topen={refusalOpen}\n\t\t\t\tonClose={() => setRefusalOpen(false)}\n\t\t\t/>\n\t\t</Flex>\n\t);\n};\nFolderTree.displayName = \"FolderTree\";\n","import { InlineEdit } from \"@knkcs/anker/forms\";\nimport { useState } from \"react\";\n\ninterface InlineEditFieldProps {\n\tvalue: string;\n\tonSave: (newValue: string) => Promise<void>;\n\tas?: \"input\" | \"textarea\";\n\tplaceholder?: string;\n}\n\n/**\n * Thin wrapper around anker's InlineEdit that adds async save with error handling.\n * On error, the value reverts to the previous value automatically.\n */\nexport const InlineEditField: React.FC<InlineEditFieldProps> = ({\n\tvalue,\n\tonSave,\n\tas = \"input\",\n\tplaceholder,\n}) => {\n\tconst [disabled, setDisabled] = useState(false);\n\n\tasync function handleSubmit(nextValue: string) {\n\t\tconst trimmed = nextValue.trim();\n\t\tif (trimmed === value) return;\n\t\tsetDisabled(true);\n\t\ttry {\n\t\t\tawait onSave(trimmed);\n\t\t} catch {\n\t\t\t// Error handling done by caller (toast); InlineEdit reverts on its own\n\t\t} finally {\n\t\t\tsetDisabled(false);\n\t\t}\n\t}\n\n\treturn (\n\t\t<InlineEdit\n\t\t\tvalue={value}\n\t\t\tonSubmit={handleSubmit}\n\t\t\tvariant={as}\n\t\t\tplaceholder={placeholder}\n\t\t\tdisabled={disabled}\n\t\t\tfontSize=\"sm\"\n\t\t/>\n\t);\n};\nInlineEditField.displayName = \"InlineEditField\";\n","import { toaster } from \"@knkcs/anker/primitives\";\nimport { SpecEditor } from \"@knkcs/fieldkit/editor\";\nimport { FieldKitProvider } from \"@knkcs/fieldkit/renderer\";\nimport { type Schema, builtInFieldTypes } from \"@knkcs/fieldkit/schema\";\nimport type React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useUpdateAssetType } from \"../hooks/use-asset-types\";\n\nexport interface MetadataSchemaEditorProps {\n\ttypeId: string;\n\t/**\n\t * The committed schema — SpecEditor's baseline. Content-equal re-parses on\n\t * background refetches are ignored by the editor's stability contract.\n\t */\n\tinitialSchema: Schema;\n\t/** Wire into the screen's unsaved-changes tab guard. */\n\tonDirtyChange?: (dirty: boolean) => void;\n}\n\n/**\n * The asset type's fieldkit metadata schema, edited on a page with room for it\n * (spec knkCS/mediahub#138, story 7) rather than as a JSON textarea.\n */\nexport const MetadataSchemaEditor: React.FC<MetadataSchemaEditorProps> = ({\n\ttypeId,\n\tinitialSchema,\n\tonDirtyChange,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst updateAssetType = useUpdateAssetType();\n\n\tasync function handleCommit(schema: Schema) {\n\t\t// No try/catch: a rejection must propagate to SpecEditor, which keeps\n\t\t// the draft dirty and shows its own saveFailed toast.\n\t\tawait updateAssetType.mutateAsync({\n\t\t\tid: typeId,\n\t\t\tpatch: { metadataSchema: JSON.stringify(schema) },\n\t\t});\n\t\ttoaster.success({ title: t(\"assetTypeDetail.schemaSavedToast\") });\n\t}\n\n\treturn (\n\t\t<FieldKitProvider plugins={builtInFieldTypes}>\n\t\t\t<SpecEditor\n\t\t\t\tschema={initialSchema}\n\t\t\t\tonCommit={handleCommit}\n\t\t\t\tonDirtyChange={onDirtyChange}\n\t\t\t\tplugins={builtInFieldTypes}\n\t\t\t/>\n\t\t</FieldKitProvider>\n\t);\n};\nMetadataSchemaEditor.displayName = \"MetadataSchemaEditor\";\n","import { ChipPicker } from \"@knkcs/anker/components\";\nimport { useTranslation } from \"react-i18next\";\nimport { useTagAssets, useTags, useUntagAssets } from \"../hooks/use-tags\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { TagInfo } from \"../types\";\n\ninterface TagChipFieldProps {\n\tassetId: string;\n\tassignedTagIds: string[];\n}\n\nexport const TagChipField: React.FC<TagChipFieldProps> = ({\n\tassetId,\n\tassignedTagIds,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst tagsQuery = useTags();\n\tconst allTags: TagInfo[] = tagsQuery.data ?? [];\n\tconst tagAssets = useTagAssets();\n\tconst untagAssets = useUntagAssets();\n\n\tconst assignedTags = allTags.filter((tag) => assignedTagIds.includes(tag.id));\n\tconst unassignedTags = allTags.filter(\n\t\t(tag) => !assignedTagIds.includes(tag.id),\n\t);\n\n\tasync function handleAdd(tag: TagInfo) {\n\t\ttry {\n\t\t\tawait tagAssets.mutateAsync({ tagId: tag.id, assetIds: [assetId] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"tagChipField.errorToast\"));\n\t\t}\n\t}\n\n\tasync function handleRemove(tag: TagInfo) {\n\t\ttry {\n\t\t\tawait untagAssets.mutateAsync({ tagId: tag.id, assetIds: [assetId] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"tagChipField.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<ChipPicker<TagInfo>\n\t\t\tassigned={assignedTags}\n\t\t\tavailable={unassignedTags}\n\t\t\tgetItemId={(tag) => tag.id}\n\t\t\tgetItemLabel={(tag) => tag.name}\n\t\t\tonAdd={handleAdd}\n\t\t\tonRemove={handleRemove}\n\t\t\taddLabel={t(\"tagChipField.addLabel\")}\n\t\t\temptyLabel={t(\"tagChipField.emptyLabel\")}\n\t\t\tsearchable\n\t\t\tloading={tagsQuery.isLoading}\n\t\t/>\n\t);\n};\nTagChipField.displayName = \"TagChipField\";\n","import { InlineCreatableList } from \"@knkcs/anker/components\";\nimport { toaster } from \"@knkcs/anker/primitives\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCreateTag, useTags } from \"../hooks/use-tags\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { TagInfo } from \"../types\";\n\ninterface TagPanelProps {\n\tactiveTags: string[];\n\tonToggleTag: (tagId: string) => void;\n}\n\nexport const TagPanel: React.FC<TagPanelProps> = ({\n\tactiveTags,\n\tonToggleTag,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst tagsQuery = useTags();\n\tconst tags: TagInfo[] = tagsQuery.data ?? [];\n\tconst createTag = useCreateTag();\n\n\tasync function handleCreate(name: string) {\n\t\ttry {\n\t\t\tawait createTag.mutateAsync({\n\t\t\t\tname,\n\t\t\t\tslug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"tagPanel.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"tagPanel.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<InlineCreatableList<TagInfo>\n\t\t\titems={tags}\n\t\t\tactiveIds={activeTags}\n\t\t\tonToggle={onToggleTag}\n\t\t\tonCreate={handleCreate}\n\t\t\tgetItemId={(tag) => tag.id}\n\t\t\tgetItemLabel={(tag) => tag.name}\n\t\t\tvariant=\"wrap\"\n\t\t\tcreatePlaceholder={t(\"tagPanel.createPlaceholder\")}\n\t\t\tcreateLabel={t(\"tagPanel.createLabel\")}\n\t\t\temptyText={t(\"tagPanel.emptyText\")}\n\t\t/>\n\t);\n};\nTagPanel.displayName = \"TagPanel\";\n","import { Modal } from \"@knkcs/anker/components\";\nimport {\n\tBox,\n\tCheckbox,\n\tFlex,\n\tNativeSelect,\n\tText,\n} from \"@knkcs/anker/primitives\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useAssetTypes } from \"../../hooks/use-asset-types\";\nimport { useWorkspaceId } from \"../../provider\";\nimport type { UploadFile } from \"../../stores/upload-store\";\nimport { useUploadStore } from \"../../stores/upload-store\";\n\ninterface UploadDialogProps {\n\topen: boolean;\n\tonClose: () => void;\n\tfolderId?: string;\n}\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nconst FileRow: React.FC<{\n\tentry: UploadFile;\n\tshowOverride: boolean;\n\tonToggleOverride: () => void;\n\tassetTypes: { id: string; name: string }[];\n}> = ({ entry, showOverride, onToggleOverride, assetTypes }) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst setAssetType = useUploadStore((s) => s.setAssetType);\n\n\treturn (\n\t\t<Flex\n\t\t\tpy={2.5}\n\t\t\tpx={3}\n\t\t\talign=\"center\"\n\t\t\tborderBottomWidth=\"1px\"\n\t\t\tborderColor=\"border\"\n\t\t\t_last={{ borderBottomWidth: 0 }}\n\t\t\tgap={3}\n\t\t>\n\t\t\t<Box flex={1} minW={0}>\n\t\t\t\t<Text fontSize=\"sm\" truncate>\n\t\t\t\t\t{entry.file.name}\n\t\t\t\t</Text>\n\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t{formatFileSize(entry.file.size)}\n\t\t\t\t</Text>\n\t\t\t</Box>\n\n\t\t\t{showOverride ? (\n\t\t\t\t<NativeSelect\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tvalue={entry.assetTypeId}\n\t\t\t\t\tonChange={(e) => setAssetType(entry.clientId, e.target.value)}\n\t\t\t\t\tw=\"160px\"\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">{t(\"uploadDialog.selectType\")}</option>\n\t\t\t\t\t{assetTypes.map((type) => (\n\t\t\t\t\t\t<option key={type.id} value={type.id}>\n\t\t\t\t\t\t\t{type.name}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</NativeSelect>\n\t\t\t) : (\n\t\t\t\t<Text\n\t\t\t\t\tfontSize=\"xs\"\n\t\t\t\t\tcolor=\"colorPalette.fg\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t_hover={{ textDecoration: \"underline\" }}\n\t\t\t\t\tonClick={onToggleOverride}\n\t\t\t\t>\n\t\t\t\t\t{t(\"uploadDialog.changeType\")}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</Flex>\n\t);\n};\nFileRow.displayName = \"FileRow\";\n\nexport const UploadDialog: React.FC<UploadDialogProps> = ({\n\topen,\n\tonClose,\n\tfolderId,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst files = useUploadStore((s) => s.files);\n\tconst setBatchAssetType = useUploadStore((s) => s.setBatchAssetType);\n\tconst startUpload = useUploadStore((s) => s.startUpload);\n\tconst clearPending = useUploadStore((s) => s.clearPending);\n\tconst analyzeWithAi = useUploadStore((s) => s.analyzeWithAi);\n\tconst setAnalyzeWithAi = useUploadStore((s) => s.setAnalyzeWithAi);\n\tconst assetTypesQuery = useAssetTypes();\n\tconst assetTypes = assetTypesQuery.data ?? [];\n\tconst [batchType, setBatchType] = useState(\"\");\n\tconst [overrides, setOverrides] = useState<Set<string>>(new Set());\n\n\tconst pendingFiles = files.filter((f) => f.status === \"pending\");\n\n\tfunction handleBatchTypeChange(value: string) {\n\t\tsetBatchType(value);\n\t\tsetBatchAssetType(value);\n\t}\n\n\tfunction toggleOverride(clientId: string) {\n\t\tsetOverrides((prev) => {\n\t\t\tconst next = new Set(prev);\n\t\t\tif (next.has(clientId)) {\n\t\t\t\tnext.delete(clientId);\n\t\t\t} else {\n\t\t\t\tnext.add(clientId);\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}\n\n\tconst canUpload =\n\t\tpendingFiles.length > 0 && pendingFiles.every((f) => f.assetTypeId !== \"\");\n\n\tfunction handleUpload() {\n\t\tstartUpload(workspaceId, folderId);\n\t\tonClose();\n\t\tsetBatchType(\"\");\n\t\tsetOverrides(new Set());\n\t}\n\n\tfunction handleCancel() {\n\t\tclearPending();\n\t\tonClose();\n\t}\n\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tonClose={handleCancel}\n\t\t\theader={t(\"uploadDialog.header\", { count: pendingFiles.length })}\n\t\t\tsaveLabel={t(\"uploadDialog.uploadButton\")}\n\t\t\tonSave={handleUpload}\n\t\t\tsaveDisabled={!canUpload}\n\t\t>\n\t\t\t{/* Batch asset type selector */}\n\t\t\t<Box mb={4}>\n\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" mb={2}>\n\t\t\t\t\t{t(\"uploadDialog.assetTypeLabel\")}\n\t\t\t\t</Text>\n\t\t\t\t<NativeSelect\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tvalue={batchType}\n\t\t\t\t\tonChange={(e) => handleBatchTypeChange(e.target.value)}\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">{t(\"uploadDialog.selectAssetType\")}</option>\n\t\t\t\t\t{assetTypes.map((type) => (\n\t\t\t\t\t\t<option key={type.id} value={type.id}>\n\t\t\t\t\t\t\t{type.name}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</NativeSelect>\n\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\" mt={1}>\n\t\t\t\t\t{t(\"uploadDialog.assetTypeHint\")}\n\t\t\t\t</Text>\n\t\t\t</Box>\n\n\t\t\t{/* AI analysis toggle */}\n\t\t\t<Box mb={4}>\n\t\t\t\t<Checkbox\n\t\t\t\t\tchecked={analyzeWithAi}\n\t\t\t\t\tonCheckedChange={(e) => setAnalyzeWithAi(!!e.checked)}\n\t\t\t\t>\n\t\t\t\t\t{t(\"uploadDialog.analyzeWithAi\")}\n\t\t\t\t</Checkbox>\n\t\t\t</Box>\n\n\t\t\t{/* File list */}\n\t\t\t<Box\n\t\t\t\tborderWidth=\"1px\"\n\t\t\t\tborderColor=\"border\"\n\t\t\t\trounded=\"md\"\n\t\t\t\tmaxH=\"300px\"\n\t\t\t\toverflowY=\"auto\"\n\t\t\t>\n\t\t\t\t{pendingFiles.map((entry) => (\n\t\t\t\t\t<FileRow\n\t\t\t\t\t\tkey={entry.clientId}\n\t\t\t\t\t\tentry={entry}\n\t\t\t\t\t\tshowOverride={overrides.has(entry.clientId)}\n\t\t\t\t\t\tonToggleOverride={() => toggleOverride(entry.clientId)}\n\t\t\t\t\t\tassetTypes={assetTypes}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</Box>\n\t\t</Modal>\n\t);\n};\nUploadDialog.displayName = \"UploadDialog\";\n","import { UploadDropZone as AnkerUploadDropZone } from \"@knkcs/anker/components\";\n\ninterface UploadDropZoneProps {\n\tonFilesSelected: (files: File[]) => void;\n\tcompact?: boolean;\n}\n\nexport const UploadDropZone: React.FC<UploadDropZoneProps> = ({\n\tonFilesSelected,\n\tcompact,\n}) => {\n\treturn (\n\t\t<AnkerUploadDropZone onFiles={onFilesSelected} compact={compact} multiple />\n\t);\n};\nUploadDropZone.displayName = \"UploadDropZone\";\n","import type { UploadFileStatus } from \"@knkcs/anker/feedback\";\nimport { UploadToastStack as AnkerUploadToastStack } from \"@knkcs/anker/feedback\";\nimport { useUploadStore } from \"../../stores/upload-store\";\n\n/** Map Zustand upload store statuses to anker's UploadFileStatus format. */\nfunction mapStatus(status: string): UploadFileStatus[\"status\"] {\n\tswitch (status) {\n\t\tcase \"done\":\n\t\t\treturn \"done\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"uploading\":\n\t\t\treturn \"uploading\";\n\t\tcase \"creating\":\n\t\tcase \"finalizing\":\n\t\t\treturn \"processing\";\n\t\tdefault:\n\t\t\treturn \"pending\";\n\t}\n}\n\nexport const UploadToastStack: React.FC = () => {\n\tconst storeFiles = useUploadStore((s) => s.files);\n\tconst visible = useUploadStore((s) => s.visible);\n\tconst dismiss = useUploadStore((s) => s.dismiss);\n\n\tconst files: UploadFileStatus[] = storeFiles.map((f) => ({\n\t\tid: f.clientId,\n\t\tfilename: f.file.name,\n\t\tstatus: mapStatus(f.status),\n\t\tprogress: f.progress,\n\t\terror: f.error,\n\t}));\n\n\tif (!visible || files.length === 0) return null;\n\n\treturn (\n\t\t<AnkerUploadToastStack\n\t\t\tfiles={files}\n\t\t\tonDismiss={dismiss}\n\t\t\tautoDismissMs={5000}\n\t\t\tdefaultExpanded\n\t\t/>\n\t);\n};\nUploadToastStack.displayName = \"UploadToastStack\";\n","import type { AssetInfo, AssetTypeInfo } from \"./types\";\n\n/** Build an asset-type id -> display name map from the workspace's types. */\nexport function buildAssetTypeNameMap(\n\ttypes: AssetTypeInfo[],\n): Map<string, string> {\n\treturn new Map(types.map((t) => [t.id, t.name]));\n}\n\n/** Collect the unique, non-empty `updatedBy` user ids across the given assets. */\nexport function collectUpdatedByIds(assets: AssetInfo[]): string[] {\n\treturn [...new Set(assets.map((a) => a.updatedBy).filter(Boolean))];\n}\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport {\n\tActionCell,\n\tContextRail,\n\tDataTable,\n\tDateCell,\n\tToolbar,\n\tTruncatedTextCell,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBox,\n\tFlex,\n\tNativeSelect,\n\tSegmentedControl,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport {\n\tIndexPageTemplate,\n\tSubNavLayout,\n\tusePageRail,\n} from \"@knkcs/anker/templates\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport type {\n\tColumnDef,\n\tOnChangeFn,\n\tRowSelectionState,\n} from \"@tanstack/react-table\";\nimport type { TFunction } from \"i18next\";\nimport { Download, Trash2, Upload } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport {\n\tbuildAssetTypeNameMap,\n\tcollectUpdatedByIds,\n} from \"./asset-library-resolve\";\nimport { AssetGrid } from \"./components/asset-grid\";\nimport { AssetStatusBadge } from \"./components/asset-status-badge\";\nimport { BulkActionBar } from \"./components/bulk-action-bar\";\nimport { CollectionPanel } from \"./components/collection-panel\";\nimport { FolderBreadcrumbs } from \"./components/folder-breadcrumbs\";\nimport { FolderTree } from \"./components/folder-tree\";\nimport { TagPanel } from \"./components/tag-panel\";\nimport { UploadDialog } from \"./components/upload/upload-dialog\";\nimport { UploadDropZone } from \"./components/upload/upload-drop-zone\";\nimport { useAssetTypes } from \"./hooks/use-asset-types\";\nimport { useAssets, useDeleteAsset } from \"./hooks/use-assets\";\nimport { useUsers } from \"./hooks/use-users\";\nimport {\n\tdescribeRpcError,\n\tisRetryableUnavailable,\n\tshowRpcErrorToast,\n} from \"./lib/rpc-errors\";\nimport { useAssetStatuses } from \"./statushub\";\nimport { usePreferencesStore } from \"./stores/preferences-store\";\nimport { useSelectionStore } from \"./stores/selection-store\";\nimport { useUploadStore } from \"./stores/upload-store\";\nimport type { AssetFilters, AssetInfo, AssetStatusBehavior } from \"./types\";\n\n// The behavior list is mediahub's own — the words it registers with statushub\n// (integration standard §1, statushub ADR 0002), which the server validates\n// this filter against. It stays local rather than coming from\n// statushub-ui's `useEntityType` because that hook reads\n// ServiceRegistryService, which the standalone shell's proxy deliberately does\n// NOT forward: the registry is unauthenticated by design and stays in-cluster.\n// Keep it in step with `AssetBehaviors()` in internal/service/statushub.go.\nfunction behaviorOptions(\n\tt: TFunction,\n): { label: string; value: AssetStatusBehavior | \"\" }[] {\n\treturn [\n\t\t{ label: t(\"assetLibrary.behaviorAll\"), value: \"\" },\n\t\t{ label: t(\"assetLibrary.behaviorActive\"), value: \"active\" },\n\t\t{ label: t(\"assetLibrary.behaviorArchived\"), value: \"archived\" },\n\t\t{ label: t(\"assetLibrary.behaviorInactive\"), value: \"inactive\" },\n\t\t{ label: t(\"assetLibrary.behaviorDeleted\"), value: \"deleted\" },\n\t];\n}\n\nfunction viewModeOptions(t: TFunction) {\n\treturn [\n\t\t{ label: t(\"assetLibrary.viewModeList\"), value: \"list\" },\n\t\t{ label: t(\"assetLibrary.viewModeGrid\"), value: \"grid\" },\n\t];\n}\n\n// Stable identity for \"no tag filter\": `filters.tagIds ?? []` would mint a\n// fresh array every render, invalidating the rail memo (and every callback\n// keyed on activeTags) even when nothing changed.\nconst NO_ACTIVE_TAGS: string[] = [];\n\nexport interface AssetLibraryProps {\n\tonAssetOpen?: (asset: AssetInfo) => void;\n\tinitialFilters?: AssetFilters;\n\tonFiltersChange?: (filters: AssetFilters) => void;\n}\n\nexport function AssetLibrary(props: AssetLibraryProps): React.JSX.Element {\n\tconst { onAssetOpen, initialFilters, onFiltersChange } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst [filters, setFilters] = useState<AssetFilters>(initialFilters ?? {});\n\tconst [uploadDialogOpen, setUploadDialogOpen] = useState(false);\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\n\t// Derived filter shorthands for convenience\n\tconst statusSlug = filters.statusSlug ?? \"\";\n\tconst behaviorFilter: AssetStatusBehavior | \"\" = filters.behavior ?? \"\";\n\tconst folderId = filters.folderId ?? \"\";\n\tconst activeTags = filters.tagIds ?? NO_ACTIVE_TAGS;\n\tconst activeCollectionId = filters.collectionIds?.[0] ?? \"\";\n\n\tconst updateFilter = useCallback(\n\t\t<K extends keyof AssetFilters>(key: K, value: AssetFilters[K]) => {\n\t\t\tsetFilters((prev) => {\n\t\t\t\tconst next: AssetFilters = { ...prev };\n\t\t\t\tif (\n\t\t\t\t\tvalue === undefined ||\n\t\t\t\t\tvalue === \"\" ||\n\t\t\t\t\t(Array.isArray(value) && value.length === 0)\n\t\t\t\t) {\n\t\t\t\t\tdelete next[key];\n\t\t\t\t} else {\n\t\t\t\t\tnext[key] = value;\n\t\t\t\t}\n\t\t\t\tonFiltersChange?.(next);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\t[onFiltersChange],\n\t);\n\n\t// Local search text kept controlled for immediate input feedback, debounced\n\t// into the filter (and therefore the useAssets query) so we don't refetch on\n\t// every keystroke — preserves the old SearchInput debounce behaviour.\n\tconst [searchText, setSearchText] = useState(initialFilters?.search ?? \"\");\n\tconst searchPrimed = useRef(false);\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: debounce on searchText only\n\tuseEffect(() => {\n\t\tif (!searchPrimed.current) {\n\t\t\tsearchPrimed.current = true;\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(\n\t\t\t() => updateFilter(\"search\", searchText || undefined),\n\t\t\t300,\n\t\t);\n\t\treturn () => clearTimeout(timer);\n\t}, [searchText]);\n\n\tconst handleToggleTag = useCallback(\n\t\t(tagId: string) => {\n\t\t\tconst next = activeTags.includes(tagId)\n\t\t\t\t? activeTags.filter((id) => id !== tagId)\n\t\t\t\t: [...activeTags, tagId];\n\t\t\tupdateFilter(\"tagIds\", next.length > 0 ? next : undefined);\n\t\t},\n\t\t[activeTags, updateFilter],\n\t);\n\n\tconst handleSelectCollection = useCallback(\n\t\t(collectionId: string) => {\n\t\t\tupdateFilter(\"collectionIds\", collectionId ? [collectionId] : undefined);\n\t\t},\n\t\t[updateFilter],\n\t);\n\n\tfunction setStatusSlug(value: string) {\n\t\tupdateFilter(\"statusSlug\", value || undefined);\n\t}\n\n\tfunction setBehaviorFilter(value: string) {\n\t\tupdateFilter(\n\t\t\t\"behavior\",\n\t\t\tvalue ? (value as AssetStatusBehavior) : undefined,\n\t\t);\n\t}\n\n\tconst addFiles = useUploadStore((s) => s.addFiles);\n\tconst viewMode = usePreferencesStore((s) => s.viewMode);\n\tconst setViewMode = usePreferencesStore((s) => s.setViewMode);\n\n\tconst handleFilesSelected = useCallback(\n\t\t(files: File[]) => {\n\t\t\taddFiles(files);\n\t\t\tsetUploadDialogOpen(true);\n\t\t},\n\t\t[addFiles],\n\t);\n\n\tconst deleteAsset = useDeleteAsset();\n\tconst { confirm } = useConfirmModal();\n\n\tasync function handleDelete(assetId: string, assetName: string) {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"assetLibrary.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"assetLibrary.deleteConfirmMessage\", { assetName }),\n\t\t\tconfirmLabel: t(\"assetLibrary.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteAsset.mutateAsync(assetId);\n\t\t\ttoaster.success({ title: t(\"assetLibrary.deleteSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetLibrary.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tconst assetsQuery = useAssets({\n\t\tfolderId: folderId || undefined,\n\t\tstatusSlug: statusSlug || undefined,\n\t\tbehavior: behaviorFilter || undefined,\n\t\tsearch: filters.search || undefined,\n\t\ttagIds: activeTags.length > 0 ? activeTags : undefined,\n\t\tcollectionIds: activeCollectionId ? [activeCollectionId] : undefined,\n\t});\n\n\t// The filter's options are the workspace's own catalogue, read from\n\t// statushub (integration standard §10) — the order statushub answers in.\n\tconst statusOptions = useAssetStatuses().data ?? [];\n\tconst assets: AssetInfo[] = assetsQuery.data?.items ?? [];\n\n\t// A failed listing must SAY so. `assetsQuery.data?.items ?? []` alone would\n\t// render \"No assets found\" over a refusal — which is the false answer the\n\t// server refused to give, arriving through the UI's door instead\n\t// (knkCS/mediahub#120). The behavior filter is the one read the server\n\t// refuses while statushub is unreachable, and the reader clears it by\n\t// dropping the filter, so that is the action offered.\n\tconst listFailure = assetsQuery.isError ? assetsQuery.error : undefined;\n\tconst listFailureState = listFailure ? (\n\t\tisRetryableUnavailable(listFailure) && behaviorFilter ? (\n\t\t\t<EmptyState\n\t\t\t\theader={t(\"assetLibrary.statusesUnavailableHeader\")}\n\t\t\t\tdescription={t(\"assetLibrary.statusesUnavailableDescription\")}\n\t\t\t\tactions={\n\t\t\t\t\t<Button size=\"sm\" onClick={() => setBehaviorFilter(\"\")}>\n\t\t\t\t\t\t{t(\"assetLibrary.clearStatusGroup\")}\n\t\t\t\t\t</Button>\n\t\t\t\t}\n\t\t\t/>\n\t\t) : (\n\t\t\t<EmptyState\n\t\t\t\theader={t(\"assetLibrary.assetsLoadFailedHeader\")}\n\t\t\t\tdescription={\n\t\t\t\t\tdescribeRpcError(\n\t\t\t\t\t\tlistFailure,\n\t\t\t\t\t\tt(\"assetLibrary.assetsLoadFailedHeader\"),\n\t\t\t\t\t).description\n\t\t\t\t}\n\t\t\t/>\n\t\t)\n\t) : undefined;\n\n\tconst assetTypesQuery = useAssetTypes();\n\tconst typeNames = useMemo(\n\t\t() => buildAssetTypeNameMap(assetTypesQuery.data ?? []),\n\t\t[assetTypesQuery.data],\n\t);\n\tconst updatedByIds = useMemo(() => collectUpdatedByIds(assets), [assets]);\n\tconst { data: userNames } = useUsers(updatedByIds);\n\n\tconst selectedIds = useSelectionStore((s) => s.selectedIds);\n\tconst setSelection = useSelectionStore((s) => s.setSelection);\n\n\t// Bridge Zustand selection <-> DataTable rowSelection\n\tconst rowSelection = useMemo(() => {\n\t\tconst sel: RowSelectionState = {};\n\t\tfor (const id of selectedIds) sel[id] = true;\n\t\treturn sel;\n\t}, [selectedIds]);\n\n\tconst handleRowSelectionChange: OnChangeFn<RowSelectionState> = useCallback(\n\t\t(updater) => {\n\t\t\tconst current: RowSelectionState = {};\n\t\t\tfor (const id of useSelectionStore.getState().selectedIds)\n\t\t\t\tcurrent[id] = true;\n\t\t\tconst next = typeof updater === \"function\" ? updater(current) : updater;\n\t\t\tsetSelection(Object.keys(next).filter((k) => next[k]));\n\t\t},\n\t\t[setSelection],\n\t);\n\n\t// Clear selection when filters change\n\tconst filtersKey = JSON.stringify(filters);\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: trigger on filters change\n\tuseEffect(() => {\n\t\tuseSelectionStore.getState().clearSelection();\n\t}, [filtersKey]);\n\n\t// DataTable columns for list view\n\tconst columnHelper = createColumnHelper<AssetInfo>();\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: columnHelper is stable, handleDelete is intentionally excluded\n\tconst listColumns = useMemo(\n\t\t() =>\n\t\t\t[\n\t\t\t\tcolumnHelper.accessor(\"name\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnName\"),\n\t\t\t\t\tcell: (info) => <TruncatedTextCell value={info.getValue()} />,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"assetTypeId\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnType\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<Text color=\"fg.muted\">\n\t\t\t\t\t\t\t{typeNames.get(info.getValue()) ?? info.getValue()}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"statusSlug\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnStatus\"),\n\t\t\t\t\tcell: (info) => <AssetStatusBadge slug={info.getValue()} />,\n\t\t\t\t\tenableSorting: false,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"updatedAt\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnUpdated\"),\n\t\t\t\t\tcell: (info) => {\n\t\t\t\t\t\tconst date = info.getValue();\n\t\t\t\t\t\treturn <DateCell value={date ?? null} showRelative />;\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"updatedBy\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnUpdatedBy\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<Text color=\"fg.muted\">\n\t\t\t\t\t\t\t{userNames?.[info.getValue()] ?? info.getValue()}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: \"actions\",\n\t\t\t\t\tcell: (info) => {\n\t\t\t\t\t\tconst asset = info.row.original;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ActionCell\n\t\t\t\t\t\t\t\tactions={[\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ticon: Download,\n\t\t\t\t\t\t\t\t\t\tlabel: t(\"assetLibrary.actionDownload\"),\n\t\t\t\t\t\t\t\t\t\tonClick: () => {},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ticon: Trash2,\n\t\t\t\t\t\t\t\t\t\tlabel: t(\"assetLibrary.actionDelete\"),\n\t\t\t\t\t\t\t\t\t\tonClick: () => handleDelete(asset.id, asset.name),\n\t\t\t\t\t\t\t\t\t\tcolorPalette: \"red\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t] as ColumnDef<AssetInfo, unknown>[],\n\t\t[typeNames, userNames, t],\n\t);\n\n\t// Right rail — independently-collapsible upload / tags / collections sections.\n\t// Memoised so search/filter keystrokes don't re-push the slot and bounce an\n\t// extra AppShell render; recomputes only when the rail's own inputs change.\n\tconst rail = useMemo(\n\t\t() => (\n\t\t\t<ContextRail storageKey=\"asset-library-rail\">\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"upload\"\n\t\t\t\t\tlabel={t(\"assetLibrary.uploadSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<UploadDropZone onFilesSelected={handleFilesSelected} compact />\n\t\t\t\t</ContextRail.Section>\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"tags\"\n\t\t\t\t\tlabel={t(\"assetLibrary.tagsSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<TagPanel activeTags={activeTags} onToggleTag={handleToggleTag} />\n\t\t\t\t</ContextRail.Section>\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"collections\"\n\t\t\t\t\tlabel={t(\"assetLibrary.collectionsSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<CollectionPanel\n\t\t\t\t\t\tactiveCollectionId={activeCollectionId}\n\t\t\t\t\t\tonSelectCollection={handleSelectCollection}\n\t\t\t\t\t/>\n\t\t\t\t</ContextRail.Section>\n\t\t\t</ContextRail>\n\t\t),\n\t\t[\n\t\t\tactiveTags,\n\t\t\tactiveCollectionId,\n\t\t\thandleFilesSelected,\n\t\t\thandleToggleTag,\n\t\t\thandleSelectCollection,\n\t\t\tt,\n\t\t],\n\t);\n\tusePageRail(rail);\n\n\t// Toolbar swaps for the BulkActionBar while rows are selected.\n\tconst toolbar =\n\t\tselectedIds.length > 0 ? (\n\t\t\t<BulkActionBar />\n\t\t) : (\n\t\t\t<Toolbar>\n\t\t\t\t<Toolbar.Search\n\t\t\t\t\tplaceholder={t(\"assetLibrary.searchPlaceholder\")}\n\t\t\t\t\tvalue={searchText}\n\t\t\t\t\tonChange={setSearchText}\n\t\t\t\t/>\n\t\t\t\t<Toolbar.Filters>\n\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvalue={statusSlug}\n\t\t\t\t\t\tonChange={(e) => setStatusSlug(e.target.value ?? \"\")}\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"\">{t(\"assetLibrary.statusFilterAll\")}</option>\n\t\t\t\t\t\t{statusOptions.map((s) => (\n\t\t\t\t\t\t\t<option key={s.id} value={s.slug}>\n\t\t\t\t\t\t\t\t{s.name}\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t<SegmentedControl\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvalue={behaviorFilter}\n\t\t\t\t\t\tonValueChange={(details) => setBehaviorFilter(details.value ?? \"\")}\n\t\t\t\t\t\titems={behaviorOptions(t)}\n\t\t\t\t\t/>\n\t\t\t\t</Toolbar.Filters>\n\t\t\t\t<Toolbar.Right>\n\t\t\t\t\t<SegmentedControl\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvalue={viewMode}\n\t\t\t\t\t\tonValueChange={(details) =>\n\t\t\t\t\t\t\tsetViewMode(details.value as \"list\" | \"grid\")\n\t\t\t\t\t\t}\n\t\t\t\t\t\titems={viewModeOptions(t)}\n\t\t\t\t\t/>\n\t\t\t\t\t{/* A count is a claim about the whole set, so a failed\n\t\t\t\t\t listing has none to make: \"0 assets\" beside \"statuses\n\t\t\t\t\t are unavailable\" would be the same false answer in\n\t\t\t\t\t miniature. */}\n\t\t\t\t\t{listFailure ? null : (\n\t\t\t\t\t\t<Toolbar.Count>\n\t\t\t\t\t\t\t{t(\"assetLibrary.assetsCount\", { count: assets.length })}\n\t\t\t\t\t\t</Toolbar.Count>\n\t\t\t\t\t)}\n\t\t\t\t</Toolbar.Right>\n\t\t\t</Toolbar>\n\t\t);\n\n\treturn (\n\t\t<IndexPageTemplate\n\t\t\tbreadcrumbs={[{ label: t(\"assetLibrary.pageTitle\") }]}\n\t\t\ttitle={t(\"assetLibrary.pageTitle\")}\n\t\t\tactions={\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tonClick={() => fileInputRef.current?.click()}\n\t\t\t\t>\n\t\t\t\t\t<Upload size={14} /> {t(\"assetLibrary.uploadButton\")}\n\t\t\t\t</Button>\n\t\t\t}\n\t\t\ttoolbar={toolbar}\n\t\t>\n\t\t\t<SubNavLayout storageKey=\"mediahub-assets-subnav\">\n\t\t\t\t<SubNavLayout.Nav aria-label=\"Folders\">\n\t\t\t\t\t<Box overflow=\"hidden\">\n\t\t\t\t\t\t<FolderTree\n\t\t\t\t\t\t\tactiveFolderId={folderId}\n\t\t\t\t\t\t\tonFolderSelect={(id) => updateFilter(\"folderId\", id || undefined)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</Box>\n\t\t\t\t</SubNavLayout.Nav>\n\t\t\t\t<SubNavLayout.Detail>\n\t\t\t\t\t<SubNavLayout.Toolbar>\n\t\t\t\t\t\t{folderId ? (\n\t\t\t\t\t\t\t<FolderBreadcrumbs\n\t\t\t\t\t\t\t\tfolderId={folderId}\n\t\t\t\t\t\t\t\tonNavigate={(id) => updateFilter(\"folderId\", id || undefined)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\">\n\t\t\t\t\t\t\t\t{t(\"assetLibrary.allAssets\")}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</SubNavLayout.Toolbar>\n\t\t\t\t\t<Box flex=\"1\" overflow=\"auto\" p={4}>\n\t\t\t\t\t\t{/* Above the rows, not instead of them. A refused refetch\n\t\t\t\t\t\t leaves TanStack Query's previous `data` in place, so\n\t\t\t\t\t\t an error does NOT imply an empty list — hanging this\n\t\t\t\t\t\t on the table's `emptyState` would show stale rows\n\t\t\t\t\t\t under no notice at all, which is the silently-wrong\n\t\t\t\t\t\t listing the server refusal exists to prevent. */}\n\t\t\t\t\t\t{listFailureState}\n\t\t\t\t\t\t{listFailureState && assets.length === 0 ? null : viewMode ===\n\t\t\t\t\t\t\t\"grid\" ? (\n\t\t\t\t\t\t\tassetsQuery.isLoading ? (\n\t\t\t\t\t\t\t\t<Flex justify=\"center\" py={10}>\n\t\t\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t) : assets.length === 0 ? (\n\t\t\t\t\t\t\t\t<EmptyState header={t(\"assetLibrary.noAssetsFound\")} />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<AssetGrid\n\t\t\t\t\t\t\t\t\tassets={assets}\n\t\t\t\t\t\t\t\t\tonOpen={(asset) => onAssetOpen?.(asset)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<DataTable\n\t\t\t\t\t\t\t\tcolumns={\n\t\t\t\t\t\t\t\t\tlistColumns as ColumnDef<Record<string, unknown>, unknown>[]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdata={assets as unknown as Record<string, unknown>[]}\n\t\t\t\t\t\t\t\tselectable\n\t\t\t\t\t\t\t\trowSelection={rowSelection}\n\t\t\t\t\t\t\t\tonRowSelectionChange={handleRowSelectionChange}\n\t\t\t\t\t\t\t\tgetRowId={(asset) => (asset as unknown as AssetInfo).id}\n\t\t\t\t\t\t\t\tonRowClick={(asset) =>\n\t\t\t\t\t\t\t\t\tonAssetOpen?.(asset as unknown as AssetInfo)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tloading={assetsQuery.isLoading}\n\t\t\t\t\t\t\t\temptyState={\n\t\t\t\t\t\t\t\t\t<EmptyState header={t(\"assetLibrary.noAssetsFound\")} />\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tvariant=\"line\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Box>\n\t\t\t\t</SubNavLayout.Detail>\n\t\t\t</SubNavLayout>\n\n\t\t\t<input\n\t\t\t\tref={fileInputRef}\n\t\t\t\ttype=\"file\"\n\t\t\t\tmultiple\n\t\t\t\thidden\n\t\t\t\tonChange={(e) => {\n\t\t\t\t\tconst files = e.target.files;\n\t\t\t\t\tif (files && files.length > 0) {\n\t\t\t\t\t\thandleFilesSelected(Array.from(files));\n\t\t\t\t\t}\n\t\t\t\t\te.target.value = \"\";\n\t\t\t\t}}\n\t\t\t/>\n\n\t\t\t<UploadDialog\n\t\t\t\topen={uploadDialogOpen}\n\t\t\t\tonClose={() => setUploadDialogOpen(false)}\n\t\t\t\tfolderId={folderId || undefined}\n\t\t\t/>\n\t\t</IndexPageTemplate>\n\t);\n}\nAssetLibrary.displayName = \"AssetLibrary\";\n","import {\n\ttype FieldTypePlugin,\n\ttype Schema,\n\tgetDefaultValues,\n} from \"@knkcs/fieldkit/schema\";\nimport type { AssetInfo } from \"../types\";\n\n/** Structural field types carry no value — never composed or decomposed.\n * `card` (fieldkit 0.8.0) is a layout marker exactly like `section`, one\n * level down: a value squatting under a marker accessor must neither mount\n * into the form nor be written back by a save. */\nconst STRUCTURAL = new Set([\"section\", \"card\"]);\n\n/**\n * Compose the RHF form values for the spec-driven asset body. Schema-driven,\n * never hardcoded: the schema's own `system` flags decide whether a value\n * comes from an asset column or from the metadata document. Hidden fields\n * are included so their stored values survive the full-document round-trip.\n * Custom fields with no stored value fall back to fieldkit's defaults\n * (explicit `config.default_value`, then — when `plugins` is passed — the\n * plugin's per-type `defaultValue`, fieldkit ≥0.7.0). Types that declare no\n * `defaultValue` (radio, date, time, color, rich_text, toc_reference) have\n * their key omitted entirely so the field mounts undefined — never seed a\n * stand-in value fieldkit's own registry wouldn't produce.\n */\nexport function composeFormValues(\n\tschema: Schema,\n\tasset: AssetInfo,\n\tplugins?: FieldTypePlugin[],\n): Record<string, unknown> {\n\tconst assetRecord = asset as unknown as Record<string, unknown>;\n\tconst defaults = getDefaultValues(schema, plugins);\n\tconst values: Record<string, unknown> = {};\n\tfor (const f of schema) {\n\t\tif (STRUCTURAL.has(f.field_type)) continue;\n\t\tconst acc = f.config.api_accessor;\n\t\tconst stored = f.system ? assetRecord[acc] : asset.metadata[acc];\n\t\tif (stored !== undefined) {\n\t\t\tvalues[acc] = stored;\n\t\t} else if (acc in defaults) {\n\t\t\tvalues[acc] = defaults[acc];\n\t\t}\n\t\t// else: the type declares no defaultValue — omit the key so the field\n\t\t// mounts undefined instead of a zod-invalid stand-in.\n\t}\n\treturn values;\n}\n\n/**\n * Decompose submitted form values into the update patch: system accessors →\n * asset columns; everything else → the metadata document. Starts from the\n * asset's CURRENT metadata so orphaned keys (values of since-deleted fields)\n * are preserved by a full-document save.\n */\nexport function decomposePatch(\n\tschema: Schema,\n\tasset: AssetInfo,\n\tvalues: Record<string, unknown>,\n\t// NOTE: adding a future system field means extending this return shape and the proto patch — not just the Go canonical list.\n): { name: string; description: string; metadata: Record<string, unknown> } {\n\tconst metadata: Record<string, unknown> = { ...asset.metadata };\n\tconst columns: Record<string, unknown> = {};\n\tfor (const f of schema) {\n\t\tif (STRUCTURAL.has(f.field_type)) continue;\n\t\tconst acc = f.config.api_accessor;\n\t\tif (!(acc in values)) continue;\n\t\tif (f.system) {\n\t\t\tcolumns[acc] = values[acc];\n\t\t} else {\n\t\t\tmetadata[acc] = values[acc];\n\t\t}\n\t}\n\treturn {\n\t\tname: String(columns.name ?? asset.name),\n\t\tdescription: String(columns.description ?? asset.description),\n\t\tmetadata,\n\t};\n}\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, EmptyState, IconButton } from \"@knkcs/anker/atoms\";\nimport {\n\tActionCell,\n\tContextRail,\n\tDataTable,\n\tDateCell,\n\tDescriptionList,\n\tStatusBadgeCell,\n\tTruncatedTextCell,\n\tUploadDropZone,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBadge,\n\tBox,\n\tFlex,\n\tHStack,\n\tMenuContent,\n\tMenuItem,\n\tMenuRoot,\n\tMenuTrigger,\n\tSpinner,\n\tStack,\n\tTabs,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { DetailPageTemplate, usePageRail } from \"@knkcs/anker/templates\";\nimport { FieldKitProvider, SpecForm } from \"@knkcs/fieldkit/renderer\";\nimport {\n\ttype Schema,\n\tbuiltInFieldTypes,\n\tspecToZodSchema,\n} from \"@knkcs/fieldkit/schema\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { ColumnDef } from \"@tanstack/react-table\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport type { TFunction } from \"i18next\";\nimport { ArrowLeft, Download, Ellipsis, Sparkles } from \"lucide-react\";\nimport type React from \"react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { AssetPreview } from \"./components/asset-preview\";\nimport { AssetStatusBadge } from \"./components/asset-status-badge\";\nimport { AssetStatusControl } from \"./components/asset-status-control\";\nimport { CollectionChipField } from \"./components/collection-chip-field\";\nimport { ManageAccessDialog } from \"./components/manage-access-dialog\";\nimport { MoveDialog } from \"./components/move-dialog\";\nimport { TagChipField } from \"./components/tag-chip-field\";\nimport { useAddVersion } from \"./hooks/use-add-version\";\nimport { useAIProcessRuns } from \"./hooks/use-ai-process-runs\";\nimport { useAssetType } from \"./hooks/use-asset-types\";\nimport {\n\tuseAsset,\n\tuseDeleteAsset,\n\tuseEnhanceAssetMetadata,\n\tuseUpdateAsset,\n} from \"./hooks/use-assets\";\nimport { useUsers } from \"./hooks/use-users\";\nimport { composeFormValues, decomposePatch } from \"./lib/asset-metadata-form\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport { useMediahubClients } from \"./provider\";\nimport type { AIProcessRunInfo, AssetVersionInfo } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nconst versionColumnHelper = createColumnHelper<AssetVersionInfo>();\n\nfunction aiRunColorPalette(status: AIProcessRunInfo[\"status\"]): string {\n\tswitch (status) {\n\t\tcase \"running\":\n\t\t\treturn \"blue\";\n\t\tcase \"succeeded\":\n\t\t\treturn \"green\";\n\t\tcase \"failed\":\n\t\t\treturn \"red\";\n\t\tdefault:\n\t\t\treturn \"gray\"; // queued + unknown\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// AssetDetailRail\n// ---------------------------------------------------------------------------\n\ninterface AssetDetailRailProps {\n\tassetId: string;\n\tassetName: string;\n\tcurrentVersionId: string | undefined;\n\tcurrentMimeType: string | undefined;\n\tcurrentFilename: string | undefined;\n\tcurrentFileSize: number | undefined;\n\tcurrentVersion: number;\n\tassetTypeId: string;\n\tcreatedBy: string;\n\tcreatedByName?: string;\n\tfolderId: string;\n\ttagIds: string[];\n\tcollectionIds: string[];\n\tstatusSlug: string;\n\tt: TFunction;\n}\n\nexport function AssetDetailRail({\n\tassetId,\n\tassetName,\n\tcurrentVersionId,\n\tcurrentMimeType,\n\tcurrentFilename,\n\tcurrentFileSize,\n\tcurrentVersion,\n\tassetTypeId,\n\tcreatedBy,\n\tcreatedByName,\n\tfolderId,\n\ttagIds,\n\tcollectionIds,\n\tstatusSlug,\n\tt,\n}: AssetDetailRailProps): React.JSX.Element {\n\tconst addVersion = useAddVersion();\n\tconst assetType = useAssetType(assetTypeId);\n\tconst aiRuns = useAIProcessRuns(assetId);\n\tconst runs = aiRuns.data ?? [];\n\tconst unknownValue = t(\"assetDetail.rail.unknownValue\");\n\n\treturn (\n\t\t<ContextRail storageKey=\"asset-detail-rail\">\n\t\t\t<ContextRail.Header\n\t\t\t\teyebrow={t(\"assetDetail.rail.assetEyebrow\")}\n\t\t\t\ttitle={assetName}\n\t\t\t/>\n\n\t\t\t{/* Preview */}\n\t\t\t{currentVersionId && currentMimeType ? (\n\t\t\t\t<Box mx={4} mt={3}>\n\t\t\t\t\t<AssetPreview\n\t\t\t\t\t\tassetId={assetId}\n\t\t\t\t\t\tversionId={currentVersionId}\n\t\t\t\t\t\tmimeType={currentMimeType}\n\t\t\t\t\t\tfileName={currentFilename ?? assetName}\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t) : null}\n\n\t\t\t{/* Status — omitted entirely when the asset has no status slug; the\n\t\t\t title-bar badge already conveys it. The catalogue and the moves\n\t\t\t away from the current status are statushub's; the change itself\n\t\t\t goes through mediahub's own RPC (integration standard §3). */}\n\t\t\t{statusSlug ? (\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"status\"\n\t\t\t\t\tlabel={t(\"assetDetail.rail.statusSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<AssetStatusControl assetId={assetId} statusSlug={statusSlug} />\n\t\t\t\t</ContextRail.Section>\n\t\t\t) : null}\n\n\t\t\t{/* New version — drop-to-version zone */}\n\t\t\t{/* usePageRail is a no-op without an <AppShell> ancestor — this rail\n\t\t\t renders inline when mounted directly. A future railMode:\"inline\"\n\t\t\t escape hatch is out of scope for now. */}\n\t\t\t<ContextRail.Section\n\t\t\t\tid=\"new-version\"\n\t\t\t\tlabel={t(\"assetDetail.rail.newVersionSection\")}\n\t\t\t\tdefaultOpen\n\t\t\t>\n\t\t\t\t<UploadDropZone\n\t\t\t\t\tcompact\n\t\t\t\t\tdropHintText={t(\"assetDetail.rail.dropHint\")}\n\t\t\t\t\tdisabled={addVersion.isPending}\n\t\t\t\t\tonFiles={(files) => {\n\t\t\t\t\t\tconst f = files[0];\n\t\t\t\t\t\tif (f) {\n\t\t\t\t\t\t\taddVersion.mutate({ assetId, file: f });\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t{addVersion.isPending && (\n\t\t\t\t\t<Flex align=\"center\" gap={2} mt={2}>\n\t\t\t\t\t\t<Spinner size=\"xs\" />\n\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t\t\t{t(\"assetDetail.rail.uploading\", {\n\t\t\t\t\t\t\t\tpercent: addVersion.progress,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Flex>\n\t\t\t\t)}\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* Details */}\n\t\t\t<ContextRail.Section\n\t\t\t\tid=\"details\"\n\t\t\t\tlabel={t(\"assetDetail.rail.detailsSection\")}\n\t\t\t>\n\t\t\t\t<DescriptionList orientation=\"horizontal\" gap=\"2\">\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.typeLabel\")}>\n\t\t\t\t\t\t{assetType.data?.name ?? assetTypeId}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.formatLabel\")}>\n\t\t\t\t\t\t{currentMimeType ?? unknownValue}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.sizeLabel\")}>\n\t\t\t\t\t\t{currentFileSize !== undefined\n\t\t\t\t\t\t\t? formatFileSize(currentFileSize)\n\t\t\t\t\t\t\t: unknownValue}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.versionLabel\")}>\n\t\t\t\t\t\tv{currentVersion}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.createdByLabel\")}>\n\t\t\t\t\t\t{createdByName ?? createdBy}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.folderLabel\")}>\n\t\t\t\t\t\t{folderId || unknownValue}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t</DescriptionList>\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* Tags */}\n\t\t\t<ContextRail.Section id=\"tags\" label={t(\"assetDetail.rail.tagsSection\")}>\n\t\t\t\t<TagChipField assetId={assetId} assignedTagIds={tagIds} />\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* Collections */}\n\t\t\t<ContextRail.Section\n\t\t\t\tid=\"collections\"\n\t\t\t\tlabel={t(\"assetDetail.rail.collectionsSection\")}\n\t\t\t>\n\t\t\t\t<CollectionChipField\n\t\t\t\t\tassetId={assetId}\n\t\t\t\t\tassignedCollectionIds={collectionIds}\n\t\t\t\t/>\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* AI Processing — only shown when there are runs */}\n\t\t\t{runs.length > 0 ? (\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"ai-processing\"\n\t\t\t\t\tlabel={t(\"assetDetail.rail.aiProcessingSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<Stack gap=\"2\">\n\t\t\t\t\t\t{runs.map((run) => (\n\t\t\t\t\t\t\t<Stack key={run.id} gap=\"1\">\n\t\t\t\t\t\t\t\t<HStack gap=\"2\" justify=\"space-between\">\n\t\t\t\t\t\t\t\t\t<Text fontSize=\"sm\" flexShrink={1} truncate>\n\t\t\t\t\t\t\t\t\t\t{run.processName}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\t\tcolorPalette={aiRunColorPalette(run.status)}\n\t\t\t\t\t\t\t\t\t\tvariant=\"subtle\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tflexShrink={0}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{run.status}\n\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t{run.status === \"failed\" && run.error ? (\n\t\t\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.error\">\n\t\t\t\t\t\t\t\t\t\t{run.error}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Stack>\n\t\t\t\t</ContextRail.Section>\n\t\t\t) : null}\n\t\t</ContextRail>\n\t);\n}\nAssetDetailRail.displayName = \"AssetDetailRail\";\n\n// ---------------------------------------------------------------------------\n// AssetDetail\n// ---------------------------------------------------------------------------\n\nexport interface AssetDetailProps {\n\tassetId: string;\n\t/** Navigate back to the asset list. */\n\tonBack?: () => void;\n\t/** Called after a successful delete. */\n\tonDeleted?: () => void;\n}\n\nexport function AssetDetail({\n\tassetId,\n\tonBack,\n\tonDeleted,\n}: AssetDetailProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst assetQuery = useAsset(assetId);\n\tconst asset = assetQuery.data;\n\n\tconst { assets: assetsClient } = useMediahubClients();\n\n\tconst updateAsset = useUpdateAsset();\n\tconst deleteAsset = useDeleteAsset();\n\tconst enhanceMetadata = useEnhanceAssetMetadata();\n\tconst qc = useQueryClient();\n\tconst { confirm } = useConfirmModal();\n\n\tconst assetTypeQuery = useAssetType(asset?.assetTypeId ?? \"\");\n\n\tconst schema = useMemo<Schema>(() => {\n\t\ttry {\n\t\t\treturn JSON.parse(assetTypeQuery.data?.metadataSchema || \"[]\") as Schema;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}, [assetTypeQuery.data?.metadataSchema]);\n\n\tconst composedValues = useMemo(\n\t\t() => (asset ? composeFormValues(schema, asset, builtInFieldTypes) : {}),\n\t\t[schema, asset],\n\t);\n\n\tconst zodSchema = useMemo(\n\t\t() => specToZodSchema(schema, builtInFieldTypes),\n\t\t[schema],\n\t);\n\n\t// Always-edit body form. `values` + keepDirtyValues: background refetches\n\t// update clean fields but never clobber in-progress edits.\n\tconst form = useForm({\n\t\tresolver: zodResolver(zodSchema),\n\t\tvalues: composedValues,\n\t\tresetOptions: { keepDirtyValues: true },\n\t});\n\n\tasync function handleSaveBody(values: Record<string, unknown>) {\n\t\tif (!asset) return;\n\t\tconst patch = decomposePatch(schema, asset, values);\n\t\ttry {\n\t\t\tawait updateAsset.mutateAsync({ id: asset.id, patch });\n\t\t\ttoaster.success({ title: t(\"assetDetail.saveSuccessToast\") });\n\t\t\tform.reset(values); // re-baseline: the submitted values are committed\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.saveFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleBack() {\n\t\tif (form.formState.isDirty) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetDetail.discardConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetDetail.discardConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"assetDetail.discardConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\tonBack?.();\n\t}\n\n\tconst [activeTab, setActiveTab] = useState<\"overview\" | \"versions\">(\n\t\t\"overview\",\n\t);\n\tconst [moveOpen, setMoveOpen] = useState(false);\n\tconst [accessOpen, setAccessOpen] = useState(false);\n\n\t// Current version object\n\tconst currentVersion = useMemo(() => {\n\t\tif (!asset) return undefined;\n\t\treturn (\n\t\t\tasset.versions.find((v) => v.versionNumber === asset.currentVersion) ??\n\t\t\tasset.versions.at(-1)\n\t\t);\n\t}, [asset]);\n\n\t// Collect all user IDs referenced in this asset for a single batch lookup.\n\tconst allUserIds = useMemo(() => {\n\t\tif (!asset) return [];\n\t\tconst ids = new Set<string>();\n\t\tif (asset.createdBy) ids.add(asset.createdBy);\n\t\tfor (const v of asset.versions) {\n\t\t\tif (v.createdBy) ids.add(v.createdBy);\n\t\t}\n\t\treturn [...ids];\n\t}, [asset]);\n\n\tconst { data: userNames } = useUsers(allUserIds);\n\n\t// Download a specific version via its SAS URL.\n\tconst handleDownloadVersion = useCallback(\n\t\tasync (versionId: string) => {\n\t\t\tif (!asset) return;\n\t\t\ttry {\n\t\t\t\tconst url = await assetsClient.getDownloadUrl(asset.id, versionId);\n\t\t\t\twindow.open(url, \"_blank\");\n\t\t\t} catch (err) {\n\t\t\t\tshowRpcErrorToast(err, t(\"assetDetail.downloadFailedToast\"));\n\t\t\t}\n\t\t},\n\t\t[asset, assetsClient, t],\n\t);\n\n\t// Versions table columns — every cell delegates to a provided anker *Cell\n\t// component (no inline JSX renderers).\n\tconst versionColumns = useMemo(() => {\n\t\tconst currentBadge: Record<string, string> = asset\n\t\t\t? { [`v${asset.currentVersion}`]: \"green\" }\n\t\t\t: {};\n\t\treturn [\n\t\t\tversionColumnHelper.accessor(\"versionNumber\", {\n\t\t\t\theader: t(\"assetDetail.versionColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<StatusBadgeCell\n\t\t\t\t\t\tvalue={`v${info.getValue()}`}\n\t\t\t\t\t\tcolorMap={currentBadge}\n\t\t\t\t\t\ttooltip={\n\t\t\t\t\t\t\tinfo.getValue() === asset?.currentVersion\n\t\t\t\t\t\t\t\t? t(\"assetDetail.currentVersionTooltip\")\n\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"originalFilename\", {\n\t\t\t\theader: t(\"assetDetail.fileColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<TruncatedTextCell\n\t\t\t\t\t\tvalue={info.getValue()}\n\t\t\t\t\t\tmaxLength={48}\n\t\t\t\t\t\tsubText={info.row.original.comment || info.row.original.mimeType}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"fileSize\", {\n\t\t\t\theader: t(\"assetDetail.sizeColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<TruncatedTextCell value={formatFileSize(info.getValue())} />\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"createdBy\", {\n\t\t\t\theader: t(\"assetDetail.authorColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<TruncatedTextCell\n\t\t\t\t\t\tvalue={userNames?.[info.getValue()] ?? info.getValue()}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"createdAt\", {\n\t\t\t\theader: t(\"assetDetail.dateColumn\"),\n\t\t\t\tcell: (info) => <DateCell value={info.getValue()} showRelative />,\n\t\t\t}),\n\t\t\tversionColumnHelper.display({\n\t\t\t\tid: \"actions\",\n\t\t\t\theader: \"\",\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<ActionCell\n\t\t\t\t\t\tactions={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticon: Download,\n\t\t\t\t\t\t\t\tlabel: t(\"assetDetail.downloadVersion\", {\n\t\t\t\t\t\t\t\t\tversionNumber: info.row.original.versionNumber,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\thandleDownloadVersion(info.row.original.id);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t] as ColumnDef<AssetVersionInfo, unknown>[];\n\t}, [asset, handleDownloadVersion, userNames, t]);\n\n\t// Register rail (Overview tab only) — no-op outside <AppShell>\n\tusePageRail(\n\t\tasset && activeTab === \"overview\" ? (\n\t\t\t<AssetDetailRail\n\t\t\t\tassetId={asset.id}\n\t\t\t\tassetName={asset.name}\n\t\t\t\tcurrentVersionId={currentVersion?.id}\n\t\t\t\tcurrentMimeType={currentVersion?.mimeType}\n\t\t\t\tcurrentFilename={currentVersion?.originalFilename}\n\t\t\t\tcurrentFileSize={currentVersion?.fileSize}\n\t\t\t\tcurrentVersion={asset.currentVersion}\n\t\t\t\tassetTypeId={asset.assetTypeId}\n\t\t\t\tcreatedBy={asset.createdBy}\n\t\t\t\tcreatedByName={userNames?.[asset.createdBy]}\n\t\t\t\tfolderId={asset.folderId}\n\t\t\t\ttagIds={asset.tagIds}\n\t\t\t\tcollectionIds={asset.collectionIds}\n\t\t\t\tstatusSlug={asset.statusSlug}\n\t\t\t\tt={t}\n\t\t\t/>\n\t\t) : null,\n\t);\n\n\t// -------------- handlers -----------------------------------------------\n\n\tasync function handleDownloadCurrent() {\n\t\tif (!asset || !currentVersion) return;\n\t\ttry {\n\t\t\tconst url = await assetsClient.getDownloadUrl(\n\t\t\t\tasset.id,\n\t\t\t\tcurrentVersion.id,\n\t\t\t);\n\t\t\twindow.open(url, \"_blank\");\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.downloadFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleEnhance() {\n\t\tif (!asset) return;\n\t\ttry {\n\t\t\tawait enhanceMetadata.mutateAsync(asset.id);\n\t\t\t// Kick off polling for the newly-queued process runs.\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"ai-process-runs\", asset.id],\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"assetDetail.metadataEnhancedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.enhanceFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleDelete() {\n\t\tif (!asset) return;\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"assetDetail.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"assetDetail.deleteConfirmMessage\", { assetName: asset.name }),\n\t\t\tconfirmLabel: t(\"assetDetail.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteAsset.mutateAsync(asset.id);\n\t\t\ttoaster.success({ title: t(\"assetDetail.deleteSuccessToast\") });\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.deleteFailedToast\"));\n\t\t}\n\t}\n\n\t// -------------- loading / not found ------------------------------------\n\n\tif (assetQuery.isLoading) {\n\t\treturn (\n\t\t\t<Flex justify=\"center\" align=\"center\" minH=\"400px\">\n\t\t\t\t<Spinner />\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\tif (!asset) {\n\t\treturn <EmptyState header={t(\"assetDetail.notFound\")} />;\n\t}\n\n\t// Sorted versions newest-first\n\tconst sortedVersions = [...asset.versions].sort(\n\t\t(a, b) => b.versionNumber - a.versionNumber,\n\t);\n\n\treturn (\n\t\t<DetailPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{ label: t(\"assetDetail.breadcrumbAssets\") },\n\t\t\t\t{ label: asset.name },\n\t\t\t]}\n\t\t\tavatar={\n\t\t\t\tonBack ? (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\taria-label={t(\"assetDetail.backButtonAria\")}\n\t\t\t\t\t\tonClick={handleBack}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowLeft size={18} />\n\t\t\t\t\t</IconButton>\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\ttitle={asset.name}\n\t\t\tbadges={\n\t\t\t\tasset.statusSlug ? (\n\t\t\t\t\t<AssetStatusBadge slug={asset.statusSlug} />\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\tmeta={\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\tv{asset.currentVersion}\n\t\t\t\t\t{asset.updatedAt ? ` · ${asset.updatedAt.toLocaleDateString()}` : \"\"}\n\t\t\t\t</Text>\n\t\t\t}\n\t\t\tactions={\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tloading={enhanceMetadata.isPending}\n\t\t\t\t\t\tonClick={handleEnhance}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Sparkles size={16} /> {t(\"assetDetail.enhanceWithAi\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tonClick={handleDownloadCurrent}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetDetail.download\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t// Override the form's global keepDirtyValues:true (which exists\n\t\t\t\t\t\t\t// to protect in-progress edits from background refetches) —\n\t\t\t\t\t\t\t// Discard must revert every field, dirty or not.\n\t\t\t\t\t\t\tform.reset(composedValues, { keepDirtyValues: false })\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetDetail.discard\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tloading={updateAsset.isPending}\n\t\t\t\t\t\tonClick={form.handleSubmit(handleSaveBody)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetDetail.save\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<MenuRoot>\n\t\t\t\t\t\t<MenuTrigger asChild>\n\t\t\t\t\t\t\t<IconButton\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\taria-label={t(\"assetDetail.moreActionsAria\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Ellipsis size={16} />\n\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t</MenuTrigger>\n\t\t\t\t\t\t<MenuContent>\n\t\t\t\t\t\t\t<MenuItem value=\"move\" onClick={() => setMoveOpen(true)}>\n\t\t\t\t\t\t\t\t{t(\"assetDetail.moveAction\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\tvalue=\"manage-access\"\n\t\t\t\t\t\t\t\tonClick={() => setAccessOpen(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"assetDetail.manageAccessAction\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t<MenuItem value=\"delete\" color=\"fg.error\" onClick={handleDelete}>\n\t\t\t\t\t\t\t\t{t(\"assetDetail.deleteAction\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t</MenuContent>\n\t\t\t\t\t</MenuRoot>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t\ttabs={\n\t\t\t\t<Tabs.Root\n\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\tonValueChange={(e) =>\n\t\t\t\t\t\tsetActiveTab(e.value as \"overview\" | \"versions\")\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<Tabs.List>\n\t\t\t\t\t\t<Tabs.Trigger value=\"overview\">\n\t\t\t\t\t\t\t{t(\"assetDetail.overviewTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t\t<Tabs.Trigger value=\"versions\">\n\t\t\t\t\t\t\t{t(\"assetDetail.versionsTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t</Tabs.List>\n\t\t\t\t</Tabs.Root>\n\t\t\t}\n\t\t>\n\t\t\t<Stack gap=\"4\" px=\"8\" py=\"6\">\n\t\t\t\t{/* Renders into a portal; parked here so it stays mounted with\n\t\t\t\t the loaded asset (dialog machines must not unmount mid-exit,\n\t\t\t\t see collection-picker / #66). */}\n\t\t\t\t<MoveDialog\n\t\t\t\t\topen={moveOpen}\n\t\t\t\t\tonOpenChange={setMoveOpen}\n\t\t\t\t\tsubject={{ kind: \"asset\", asset }}\n\t\t\t\t/>\n\t\t\t\t<ManageAccessDialog\n\t\t\t\t\topen={accessOpen}\n\t\t\t\t\tonOpenChange={setAccessOpen}\n\t\t\t\t\tsubject={{ kind: \"asset\", asset }}\n\t\t\t\t/>\n\t\t\t\t{activeTab === \"overview\" ? (\n\t\t\t\t\t<FieldKitProvider plugins={builtInFieldTypes}>\n\t\t\t\t\t\t<FormProvider {...form}>\n\t\t\t\t\t\t\t<SpecForm schema={schema} loading={assetTypeQuery.isLoading} />\n\t\t\t\t\t\t</FormProvider>\n\t\t\t\t\t</FieldKitProvider>\n\t\t\t\t) : (\n\t\t\t\t\t<DataTable\n\t\t\t\t\t\tcolumns={\n\t\t\t\t\t\t\tversionColumns as ColumnDef<Record<string, unknown>, unknown>[]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata={sortedVersions as unknown as Record<string, unknown>[]}\n\t\t\t\t\t\tgetRowId={(r) => (r as unknown as AssetVersionInfo).id}\n\t\t\t\t\t\temptyState={<EmptyState header={t(\"assetDetail.noVersions\")} />}\n\t\t\t\t\t\tvariant=\"line\"\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t</DetailPageTemplate>\n\t);\n}\nAssetDetail.displayName = \"AssetDetail\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, EmptyState, IconButton } from \"@knkcs/anker/atoms\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { InputField, SwitchField, TextareaField } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tHStack,\n\tSpinner,\n\tStack,\n\tTabs,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { DetailPageTemplate } from \"@knkcs/anker/templates\";\nimport type { Schema } from \"@knkcs/fieldkit/schema\";\nimport { ArrowLeft } from \"lucide-react\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { AIProcessesTab } from \"./components/ai-processes-tab\";\nimport { MetadataSchemaEditor } from \"./components/metadata-schema-editor\";\nimport {\n\tuseAssetType,\n\tuseDeleteAssetType,\n\tuseUpdateAssetType,\n} from \"./hooks/use-asset-types\";\nimport { formatMimeTypeList, parseMimeTypeList } from \"./lib/mime-type-list\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\n\ntype TabValue = \"general\" | \"metadata\" | \"ai\";\n\ntype GeneralForm = {\n\tname: string;\n\tdescription: string;\n\tallowedMimeTypesText: string;\n\tactive: boolean;\n};\n\nexport interface AssetTypeDetailProps {\n\t/** The asset type to show. */\n\ttypeId: string;\n\t/**\n\t * Typed path of the host's asset-type index, used for the breadcrumb back\n\t * link. The screen never routes itself — the host owns its URLs\n\t * (core's `docs/service-integration.md`).\n\t */\n\tassetTypesPath?: string;\n\t/**\n\t * Navigate back to the asset-type index. Given one, the screen renders a\n\t * back affordance that confirms before discarding unsaved edits — the\n\t * breadcrumb link above is the host's own navigation and the screen cannot\n\t * intercept it.\n\t */\n\tonBack?: () => void;\n\t/** Called after a successful delete; the host decides where to go next. */\n\tonDeleted?: () => void;\n}\n\n/**\n * The packaged asset-type detail screen: view, edit and delete one asset type,\n * with its fieldkit metadata schema on a second tab.\n *\n * **Correct against the wire, not against the declared type.** Connect omits\n * empty repeated fields and empty strings from its JSON, and a host client that\n * returns the wire object unmapped therefore delivers `undefined` where\n * `AssetTypeInfo` promises `string` or `string[]`. Reading one of those\n * unguarded is what took core's detail page down (knkcms/core#862, #863).\n * Every field below is defaulted at the one place it is read, so an absent\n * value renders as empty rather than throwing — and never flips a controlled\n * input to uncontrolled, which is the quieter version of the same bug.\n */\nexport function AssetTypeDetail({\n\ttypeId,\n\tassetTypesPath,\n\tonBack,\n\tonDeleted,\n}: AssetTypeDetailProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { confirm } = useConfirmModal();\n\n\tconst assetTypeQuery = useAssetType(typeId);\n\tconst assetType = assetTypeQuery.data;\n\tconst updateAssetType = useUpdateAssetType();\n\tconst deleteAssetType = useDeleteAssetType();\n\n\tconst [activeTab, setActiveTab] = useState<TabValue>(\"general\");\n\tconst [metadataDirty, setMetadataDirty] = useState(false);\n\n\tconst zodSchema = useMemo(\n\t\t() =>\n\t\t\tz.object({\n\t\t\t\tname: z.string().min(1, t(\"assetTypeDetail.nameRequired\")),\n\t\t\t\tdescription: z.string(),\n\t\t\t\tallowedMimeTypesText: z.string(),\n\t\t\t\tactive: z.boolean(),\n\t\t\t}),\n\t\t[t],\n\t);\n\n\t// Memoized on the query data, which TanStack Query keeps referentially\n\t// stable across no-op background refetches (structural sharing) — so\n\t// `values` below re-baselines only when the record actually changes.\n\tconst values = useMemo<GeneralForm>(\n\t\t() => ({\n\t\t\tname: assetType?.name ?? \"\",\n\t\t\tdescription: assetType?.description ?? \"\",\n\t\t\tallowedMimeTypesText: formatMimeTypeList(assetType?.allowedMimeTypes),\n\t\t\t// `false`, NOT `true`. `AssetType.active` is a plain proto3 bool, so\n\t\t\t// its zero value is omitted from the wire exactly as an empty string\n\t\t\t// or an empty list is — an *inactive* asset type is the one that\n\t\t\t// arrives without the key. Defaulting it to `true` would render the\n\t\t\t// switch on for a deactivated type and, on the next Save, write that\n\t\t\t// flip back. The same reason every field above is defaulted, one\n\t\t\t// value further on.\n\t\t\tactive: assetType?.active ?? false,\n\t\t}),\n\t\t[assetType],\n\t);\n\n\t// `values` + keepDirtyValues: a background refetch updates clean fields but\n\t// never clobbers an edit in progress (same contract as <AssetDetail>).\n\tconst form = useForm<GeneralForm>({\n\t\tresolver: zodResolver(zodSchema),\n\t\tvalues,\n\t\tresetOptions: { keepDirtyValues: true },\n\t});\n\n\tconst parsedSchema = useMemo<Schema>(() => {\n\t\ttry {\n\t\t\treturn JSON.parse(assetType?.metadataSchema || \"[]\") as Schema;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}, [assetType]);\n\n\tasync function handleSave(data: GeneralForm) {\n\t\ttry {\n\t\t\tawait updateAssetType.mutateAsync({\n\t\t\t\tid: typeId,\n\t\t\t\tpatch: {\n\t\t\t\t\tname: data.name,\n\t\t\t\t\tdescription: data.description,\n\t\t\t\t\tallowedMimeTypes: parseMimeTypeList(data.allowedMimeTypesText),\n\t\t\t\t\tactive: data.active,\n\t\t\t\t},\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"assetTypeDetail.saveSuccessToast\") });\n\t\t\tform.reset(data); // re-baseline: the submitted values are committed\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetTypeDetail.saveFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleDelete() {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"assetTypeDetail.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"assetTypeDetail.deleteConfirmMessage\", {\n\t\t\t\ttypeName: assetType?.name ?? \"\",\n\t\t\t}),\n\t\t\tconfirmLabel: t(\"assetTypeDetail.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteAssetType.mutateAsync(typeId);\n\t\t\ttoaster.success({ title: t(\"assetTypeDetail.deleteSuccessToast\") });\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetTypeDetail.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleBack() {\n\t\tif (form.formState.isDirty || metadataDirty) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetTypeDetail.discardConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetTypeDetail.discardConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"assetTypeDetail.discardConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\tonBack?.();\n\t}\n\n\tasync function handleTabChange(next: string) {\n\t\tif (activeTab === \"metadata\" && metadataDirty && next !== \"metadata\") {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetTypeDetail.discardSchemaConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetTypeDetail.discardSchemaConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"assetTypeDetail.discardSchemaConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return; // stay on the metadata tab\n\t\t\t// The editor unmounts with the discarded draft; its onDirtyChange\n\t\t\t// can no longer fire, so reset here.\n\t\t\tsetMetadataDirty(false);\n\t\t}\n\t\tsetActiveTab(next as TabValue);\n\t}\n\n\tif (assetTypeQuery.isLoading) {\n\t\treturn (\n\t\t\t<Flex justify=\"center\" align=\"center\" minH=\"400px\">\n\t\t\t\t<Spinner />\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\tif (!assetType) {\n\t\treturn <EmptyState header={t(\"assetTypeDetail.notFound\")} />;\n\t}\n\n\tconst title = assetType.name || t(\"assetTypeDetail.untitled\");\n\n\treturn (\n\t\t<DetailPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{\n\t\t\t\t\tlabel: t(\"assetTypeDetail.breadcrumbAssetTypes\"),\n\t\t\t\t\tto: assetTypesPath,\n\t\t\t\t},\n\t\t\t\t{ label: title },\n\t\t\t]}\n\t\t\ttitle={title}\n\t\t\tavatar={\n\t\t\t\tonBack ? (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\taria-label={t(\"assetTypeDetail.backButtonAria\")}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid handleBack();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowLeft size={18} />\n\t\t\t\t\t</IconButton>\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\tactions={\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tloading={updateAssetType.isPending}\n\t\t\t\t\t\tonClick={form.handleSubmit(handleSave)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetTypeDetail.save\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\t\tloading={deleteAssetType.isPending}\n\t\t\t\t\t\tonClick={handleDelete}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetTypeDetail.delete\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t\ttabs={\n\t\t\t\t<Tabs.Root\n\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\tonValueChange={(e) => {\n\t\t\t\t\t\tvoid handleTabChange(e.value);\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<Tabs.List>\n\t\t\t\t\t\t<Tabs.Trigger value=\"general\">\n\t\t\t\t\t\t\t{t(\"assetTypeDetail.generalTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t\t<Tabs.Trigger value=\"metadata\">\n\t\t\t\t\t\t\t{t(\"assetTypeDetail.metadataTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t\t<Tabs.Trigger value=\"ai\">\n\t\t\t\t\t\t\t{t(\"assetTypeDetail.aiProcessesTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t</Tabs.List>\n\t\t\t\t</Tabs.Root>\n\t\t\t}\n\t\t>\n\t\t\t<Stack gap=\"4\" px=\"8\" py=\"6\">\n\t\t\t\t{activeTab === \"general\" ? (\n\t\t\t\t\t<FormProvider {...form}>\n\t\t\t\t\t\t<Stack gap={4} maxW=\"lg\">\n\t\t\t\t\t\t\t<InputField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.nameLabel\")}\n\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Box>\n\t\t\t\t\t\t\t\t<Text color=\"fg.muted\" fontSize=\"sm\">\n\t\t\t\t\t\t\t\t\t{t(\"assetTypeDetail.slugLabel\")}: {assetType.slug ?? \"\"}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t<TextareaField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"description\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.descriptionLabel\")}\n\t\t\t\t\t\t\t\tplaceholder={t(\"assetTypeDetail.descriptionPlaceholder\")}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<InputField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"allowedMimeTypesText\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.allowedMimeTypesLabel\")}\n\t\t\t\t\t\t\t\tdescription={t(\"assetTypeDetail.allowedMimeTypesDescription\")}\n\t\t\t\t\t\t\t\tplaceholder=\"image/jpeg, image/png, application/pdf\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<SwitchField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"active\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.activeLabel\")}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t</FormProvider>\n\t\t\t\t) : activeTab === \"metadata\" ? (\n\t\t\t\t\t<MetadataSchemaEditor\n\t\t\t\t\t\ttypeId={typeId}\n\t\t\t\t\t\tinitialSchema={parsedSchema}\n\t\t\t\t\t\tonDirtyChange={setMetadataDirty}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<AIProcessesTab\n\t\t\t\t\t\ttypeId={typeId}\n\t\t\t\t\t\tmetadataSchema={assetType.metadataSchema}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t</DetailPageTemplate>\n\t);\n}\nAssetTypeDetail.displayName = \"AssetTypeDetail\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, TextInput } from \"@knkcs/anker/atoms\";\nimport { FormField, InputField, TextareaField } from \"@knkcs/anker/forms\";\nimport { HStack, Stack, toaster } from \"@knkcs/anker/primitives\";\nimport { SettingsPageTemplate } from \"@knkcs/anker/templates\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { useCreateAssetType } from \"./hooks/use-asset-types\";\nimport { parseMimeTypeList } from \"./lib/mime-type-list\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport { slugify } from \"./lib/slugify\";\nimport type { AssetTypeInfo } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface AssetTypeCreateProps {\n\t/**\n\t * The host's asset-type index path — used as the breadcrumb's target. A\n\t * path, not a route: the screen never navigates, it only says where the\n\t * list it belongs to lives (core's `docs/service-integration.md`).\n\t */\n\tassetTypesPath: string;\n\t/** Called with the created asset type; the host decides where to go. */\n\tonCreated?: (assetType: AssetTypeInfo) => void;\n\t/** Called when the administrator abandons the form. */\n\tonCancel?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// AssetTypeCreate\n// ---------------------------------------------------------------------------\n\n/**\n * Create an asset type. The screen the package owns, replacing the\n * standalone's create dialog and core's create page (knkCS/mediahub#137/#140).\n *\n * The slug follows the name until it is edited by hand and then stops — the\n * unconditional overwrite the standalone had silently discarded a slug someone\n * typed on purpose. The server's rule (lowercase alphanumeric with hyphens, at\n * least two characters) is stated on the form and enforced before submit,\n * because without both a name like `Bild Anhang` produced a bare 400\n * (knkcms/core#861).\n */\nexport function AssetTypeCreate({\n\tassetTypesPath,\n\tonCreated,\n\tonCancel,\n}: AssetTypeCreateProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst createAssetType = useCreateAssetType();\n\n\t// Once the slug has been typed into, it stops following the name. A flag\n\t// rather than react-hook-form's dirty state: clearing a hand-typed slug\n\t// back to empty would make the field clean again and silently resume the\n\t// autofill the administrator just opted out of.\n\tconst [slugEdited, setSlugEdited] = useState(false);\n\n\tconst schema = useMemo(\n\t\t() =>\n\t\t\tz.object({\n\t\t\t\tname: z.string().min(1, t(\"assetTypeCreate.nameRequired\")),\n\t\t\t\tslug: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(2, t(\"assetTypeCreate.slugInvalid\"))\n\t\t\t\t\t.regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, t(\"assetTypeCreate.slugInvalid\")),\n\t\t\t\tdescription: z.string(),\n\t\t\t\tallowedMimeTypes: z.string(),\n\t\t\t\tmetadataSchema: z.string(),\n\t\t\t}),\n\t\t[t],\n\t);\n\n\ttype FormValues = z.infer<typeof schema>;\n\n\tconst form = useForm<FormValues>({\n\t\tresolver: zodResolver(schema),\n\t\tdefaultValues: {\n\t\t\tname: \"\",\n\t\t\tslug: \"\",\n\t\t\tdescription: \"\",\n\t\t\tallowedMimeTypes: \"\",\n\t\t\tmetadataSchema: \"\",\n\t\t},\n\t});\n\n\tasync function onSubmit(values: FormValues) {\n\t\ttry {\n\t\t\tconst created = await createAssetType.mutateAsync({\n\t\t\t\tname: values.name,\n\t\t\t\tslug: values.slug,\n\t\t\t\tdescription: values.description,\n\t\t\t\tallowedMimeTypes: parseMimeTypeList(values.allowedMimeTypes),\n\t\t\t\t// An empty schema field means \"no custom metadata\", which the\n\t\t\t\t// service spells as an empty JSON array, not an empty string.\n\t\t\t\tmetadataSchema: values.metadataSchema.trim() || \"[]\",\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"assetTypeCreate.createdToast\") });\n\t\t\tonCreated?.(created);\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetTypeCreate.createFailedToast\"));\n\t\t}\n\t}\n\n\tconst title = t(\"assetTypeCreate.title\");\n\n\treturn (\n\t\t<SettingsPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{\n\t\t\t\t\tlabel: t(\"assetTypeCreate.breadcrumbAssetTypes\"),\n\t\t\t\t\tto: assetTypesPath,\n\t\t\t\t},\n\t\t\t\t{ label: title },\n\t\t\t]}\n\t\t\ttitle={title}\n\t\t>\n\t\t\t<FormProvider {...form}>\n\t\t\t\t<form onSubmit={form.handleSubmit(onSubmit)} noValidate>\n\t\t\t\t\t<Stack gap=\"4\">\n\t\t\t\t\t\t<FormField<FormValues>\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.nameLabel\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{(field) => (\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"assetTypeCreate.namePlaceholder\")}\n\t\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\tfield.onChange(e);\n\t\t\t\t\t\t\t\t\t\tif (!slugEdited) {\n\t\t\t\t\t\t\t\t\t\t\tform.setValue(\"slug\", slugify(e.target.value), {\n\t\t\t\t\t\t\t\t\t\t\t\tshouldValidate: form.formState.isSubmitted,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</FormField>\n\n\t\t\t\t\t\t<FormField<FormValues>\n\t\t\t\t\t\t\tname=\"slug\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.slugLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"assetTypeCreate.slugHint\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{(field) => (\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\t\t\t\tfontFamily=\"mono\"\n\t\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\tsetSlugEdited(true);\n\t\t\t\t\t\t\t\t\t\tfield.onChange(e);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</FormField>\n\n\t\t\t\t\t\t<TextareaField<FormValues>\n\t\t\t\t\t\t\tname=\"description\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.descriptionLabel\")}\n\t\t\t\t\t\t\tplaceholder={t(\"assetTypeCreate.descriptionPlaceholder\")}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<InputField<FormValues>\n\t\t\t\t\t\t\tname=\"allowedMimeTypes\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.allowedMimeTypesLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"assetTypeCreate.allowedMimeTypesHint\")}\n\t\t\t\t\t\t\tplaceholder={t(\"assetTypeCreate.allowedMimeTypesPlaceholder\")}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<TextareaField<FormValues>\n\t\t\t\t\t\t\tname=\"metadataSchema\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.metadataSchemaLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"assetTypeCreate.metadataSchemaHint\")}\n\t\t\t\t\t\t\ttextareaProps={{ fontFamily: \"mono\", rows: 8 }}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<HStack gap=\"2\" justifyContent=\"flex-start\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\t\t\tloading={createAssetType.isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"assetTypeCreate.submit\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t{onCancel ? (\n\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"outline\" onClick={onCancel}>\n\t\t\t\t\t\t\t\t\t{t(\"assetTypeCreate.cancel\")}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t</Stack>\n\t\t\t\t</form>\n\t\t\t</FormProvider>\n\t\t</SettingsPageTemplate>\n\t);\n}\nAssetTypeCreate.displayName = \"AssetTypeCreate\";\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport {\n\tBooleanCell,\n\tDataTable,\n\tMenuCell,\n\tSlugCell,\n\tToolbar,\n\tTruncatedTextCell,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { Text, toaster } from \"@knkcs/anker/primitives\";\nimport { IndexPageTemplate } from \"@knkcs/anker/templates\";\nimport { type ColumnDef, createColumnHelper } from \"@tanstack/react-table\";\nimport { Trash2 } from \"lucide-react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useAssetTypes, useDeleteAssetType } from \"./hooks/use-asset-types\";\nimport { countCustomFields } from \"./lib/metadata-field-count\";\nimport { formatMimeTypeList } from \"./lib/mime-type-list\";\nimport { describeRpcError, showRpcErrorToast } from \"./lib/rpc-errors\";\nimport type { AssetTypeInfo } from \"./types\";\n\nconst columnHelper = createColumnHelper<AssetTypeInfo>();\n\nexport interface AssetTypeIndexProps {\n\t/**\n\t * An asset type was opened. The host decides what that means — it receives\n\t * the id and nothing else, because this package must not know either host's\n\t * URL structure (core's `docs/service-integration.md`; spec #138). Screens,\n\t * not routes: nothing here navigates and nothing here builds a path.\n\t */\n\tonOpen?: (assetTypeId: string) => void;\n\t/** The reader asked for a new asset type. Same contract as `onOpen`. */\n\tonCreate?: () => void;\n}\n\n/**\n * The workspace's asset types, listed. The package owns the screen; both hosts\n * compose it and keep their own routing to themselves (#142, parent #138).\n */\nexport function AssetTypeIndex(props: AssetTypeIndexProps): React.JSX.Element {\n\tconst { onOpen, onCreate } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst assetTypesQuery = useAssetTypes();\n\tconst deleteAssetType = useDeleteAssetType();\n\tconst { confirm } = useConfirmModal();\n\n\tconst [search, setSearch] = useState(\"\");\n\n\tconst assetTypes = useMemo(\n\t\t() => assetTypesQuery.data ?? [],\n\t\t[assetTypesQuery.data],\n\t);\n\n\tconst filtered = useMemo(() => {\n\t\tconst query = search.trim().toLowerCase();\n\t\tif (!query) return assetTypes;\n\t\treturn assetTypes.filter(\n\t\t\t(type) =>\n\t\t\t\ttype.name.toLowerCase().includes(query) ||\n\t\t\t\ttype.slug.toLowerCase().includes(query),\n\t\t);\n\t}, [assetTypes, search]);\n\n\tconst handleDelete = useCallback(\n\t\tasync (assetType: AssetTypeInfo) => {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetTypeIndex.deleteConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetTypeIndex.deleteConfirmMessage\", {\n\t\t\t\t\ttypeName: assetType.name,\n\t\t\t\t}),\n\t\t\t\tconfirmLabel: t(\"assetTypeIndex.deleteConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t\ttry {\n\t\t\t\tawait deleteAssetType.mutateAsync(assetType.id);\n\t\t\t\ttoaster.success({ title: t(\"assetTypeIndex.deleteSuccessToast\") });\n\t\t\t} catch (err) {\n\t\t\t\tshowRpcErrorToast(err, t(\"assetTypeIndex.deleteFailedToast\"));\n\t\t\t}\n\t\t},\n\t\t[confirm, deleteAssetType, t],\n\t);\n\n\tconst columns = useMemo(\n\t\t() =>\n\t\t\t[\n\t\t\t\tcolumnHelper.accessor(\"name\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnName\"),\n\t\t\t\t\tcell: (info) => <TruncatedTextCell value={info.getValue()} />,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"slug\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnSlug\"),\n\t\t\t\t\tcell: (info) => <SlugCell value={info.getValue()} />,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"allowedMimeTypes\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnMimeTypes\"),\n\t\t\t\t\tenableSorting: false,\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t// `formatMimeTypeList` tolerates the key being absent\n\t\t\t\t\t\t// altogether, which is how Connect delivers an empty\n\t\t\t\t\t\t// repeated field to a host that maps the wire object\n\t\t\t\t\t\t// straight onto `AssetTypeInfo` (knkcms/core#863).\n\t\t\t\t\t\t<TruncatedTextCell value={formatMimeTypeList(info.getValue())} />\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: \"fields\",\n\t\t\t\t\theader: t(\"assetTypeIndex.columnFields\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<Text color=\"fg.muted\">\n\t\t\t\t\t\t\t{countCustomFields(info.row.original.metadataSchema)}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"active\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnStatus\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<BooleanCell\n\t\t\t\t\t\t\tvalue={info.getValue()}\n\t\t\t\t\t\t\ttrueLabel={t(\"assetTypeIndex.statusActive\")}\n\t\t\t\t\t\t\tfalseLabel={t(\"assetTypeIndex.statusInactive\")}\n\t\t\t\t\t\t/>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: \"actions\",\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<MenuCell\n\t\t\t\t\t\t\tactions={[\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlabel: t(\"assetTypeIndex.actionDelete\"),\n\t\t\t\t\t\t\t\t\ticon: Trash2,\n\t\t\t\t\t\t\t\t\tcolorPalette: \"red\",\n\t\t\t\t\t\t\t\t\tonClick: () => handleDelete(info.row.original),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t/>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t] as ColumnDef<AssetTypeInfo, unknown>[],\n\t\t[handleDelete, t],\n\t);\n\n\t// A failed listing must SAY so rather than render as \"no asset types\" —\n\t// the same rule the asset library follows for a refused listing\n\t// (knkCS/mediahub#120): an empty area over a refusal is the false answer\n\t// the server declined to give, arriving through the UI's door instead.\n\tconst listFailure = assetTypesQuery.isError ? assetTypesQuery.error : null;\n\n\tconst toolbar = (\n\t\t<Toolbar>\n\t\t\t<Toolbar.Search\n\t\t\t\tvalue={search}\n\t\t\t\tonChange={setSearch}\n\t\t\t\tplaceholder={t(\"assetTypeIndex.searchPlaceholder\")}\n\t\t\t/>\n\t\t\t{listFailure ? null : (\n\t\t\t\t<Toolbar.Right>\n\t\t\t\t\t<Toolbar.Count>\n\t\t\t\t\t\t{t(\"assetTypeIndex.typesCount\", { count: filtered.length })}\n\t\t\t\t\t</Toolbar.Count>\n\t\t\t\t</Toolbar.Right>\n\t\t\t)}\n\t\t</Toolbar>\n\t);\n\n\treturn (\n\t\t<IndexPageTemplate\n\t\t\tbreadcrumbs={[{ label: t(\"assetTypeIndex.pageTitle\") }]}\n\t\t\ttitle={t(\"assetTypeIndex.pageTitle\")}\n\t\t\tsubtitle={t(\"assetTypeIndex.pageSubtitle\")}\n\t\t\tactions={\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tonClick={() => onCreate?.()}\n\t\t\t\t>\n\t\t\t\t\t{t(\"assetTypeIndex.newButton\")}\n\t\t\t\t</Button>\n\t\t\t}\n\t\t\ttoolbar={toolbar}\n\t\t>\n\t\t\t{listFailure ? (\n\t\t\t\t<EmptyState\n\t\t\t\t\theader={t(\"assetTypeIndex.loadFailedHeader\")}\n\t\t\t\t\tdescription={\n\t\t\t\t\t\tdescribeRpcError(listFailure, t(\"assetTypeIndex.loadFailedHeader\"))\n\t\t\t\t\t\t\t.description\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<DataTable\n\t\t\t\t\tcolumns={columns as ColumnDef<Record<string, unknown>, unknown>[]}\n\t\t\t\t\tdata={filtered as unknown as Record<string, unknown>[]}\n\t\t\t\t\tgetRowId={(row) => (row as unknown as AssetTypeInfo).id}\n\t\t\t\t\tonRowClick={(row) => onOpen?.((row as unknown as AssetTypeInfo).id)}\n\t\t\t\t\tloading={assetTypesQuery.isLoading}\n\t\t\t\t\temptyState={\n\t\t\t\t\t\t<EmptyState\n\t\t\t\t\t\t\theader={\n\t\t\t\t\t\t\t\tsearch.trim()\n\t\t\t\t\t\t\t\t\t? t(\"assetTypeIndex.noMatchesHeader\")\n\t\t\t\t\t\t\t\t\t: t(\"assetTypeIndex.noAssetTypesHeader\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdescription={\n\t\t\t\t\t\t\t\tsearch.trim()\n\t\t\t\t\t\t\t\t\t? t(\"assetTypeIndex.noMatchesDescription\")\n\t\t\t\t\t\t\t\t\t: t(\"assetTypeIndex.noAssetTypesDescription\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tactions={\n\t\t\t\t\t\t\t\tsearch.trim() ? undefined : (\n\t\t\t\t\t\t\t\t\t<Button size=\"sm\" onClick={() => onCreate?.()}>\n\t\t\t\t\t\t\t\t\t\t{t(\"assetTypeIndex.newButton\")}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t\tvariant=\"line\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</IndexPageTemplate>\n\t);\n}\nAssetTypeIndex.displayName = \"AssetTypeIndex\";\n","// components/picker/picker-asset-card.tsx\nimport { SelectableCard } from \"@knkcs/anker/components\";\nimport { Skeleton, Text } from \"@knkcs/anker/primitives\";\nimport { FileText, Film, Image as ImageIcon, Music } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { usePreviewURL } from \"../../hooks/use-preview-url\";\nimport type { AssetInfo } from \"../../types\";\nimport { AssetStatusBadge } from \"../asset-status-badge\";\n\n/** Latest-version MIME category. Mirrors asset-grid.tsx. */\nexport function getMimeCategory(asset: AssetInfo): string {\n\tconst version = asset.versions[asset.versions.length - 1];\n\tif (!version) return \"unknown\";\n\tconst mime = version.mimeType;\n\tif (mime.startsWith(\"image/\")) return \"image\";\n\tif (mime.startsWith(\"video/\")) return \"video\";\n\tif (mime.startsWith(\"audio/\")) return \"audio\";\n\tif (mime === \"application/pdf\") return \"pdf\";\n\treturn \"unknown\";\n}\n\nfunction TypeIcon({ category }: { category: string }) {\n\tswitch (category) {\n\t\tcase \"image\":\n\t\t\treturn <ImageIcon size={32} opacity={0.3} />;\n\t\tcase \"video\":\n\t\t\treturn <Film size={32} opacity={0.3} />;\n\t\tcase \"audio\":\n\t\t\treturn <Music size={32} opacity={0.3} />;\n\t\tdefault:\n\t\t\treturn <FileText size={32} opacity={0.3} />;\n\t}\n}\nTypeIcon.displayName = \"TypeIcon\";\n\nexport interface PickerAssetCardProps {\n\tasset: AssetInfo;\n\tselected: boolean;\n\tselectionVisible: boolean;\n\tonToggle: (asset: AssetInfo) => void;\n}\n\nexport const PickerAssetCard: React.FC<PickerAssetCardProps> = ({\n\tasset,\n\tselected,\n\tselectionVisible,\n\tonToggle,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst category = getMimeCategory(asset);\n\tconst latestVersion = asset.versions[asset.versions.length - 1];\n\tconst previewQuery = usePreviewURL(\n\t\tcategory === \"image\" && latestVersion ? asset.id : \"\",\n\t\tlatestVersion?.id ?? \"\",\n\t);\n\tconst previewUrl = previewQuery.data;\n\tconst [imgError, setImgError] = useState(false);\n\n\treturn (\n\t\t<SelectableCard\n\t\t\tselected={selected}\n\t\t\tselectionVisible={selectionVisible}\n\t\t\tonSelect={() => onToggle(asset)}\n\t\t\tonClick={() => onToggle(asset)}\n\t\t>\n\t\t\t<SelectableCard.Thumbnail height=\"120px\">\n\t\t\t\t{category === \"image\" && previewUrl && !imgError ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\talt={asset.name || t(\"common.assetPreviewAlt\")}\n\t\t\t\t\t\tonError={() => setImgError(true)}\n\t\t\t\t\t\tstyle={{ width: \"100%\", height: \"100%\", objectFit: \"cover\" }}\n\t\t\t\t\t/>\n\t\t\t\t) : category === \"image\" && previewQuery.isLoading ? (\n\t\t\t\t\t<Skeleton w=\"full\" h=\"full\" />\n\t\t\t\t) : (\n\t\t\t\t\t<TypeIcon category={category} />\n\t\t\t\t)}\n\t\t\t</SelectableCard.Thumbnail>\n\t\t\t<SelectableCard.Body>\n\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" truncate>\n\t\t\t\t\t{asset.name}\n\t\t\t\t</Text>\n\t\t\t</SelectableCard.Body>\n\t\t\t<SelectableCard.Footer>\n\t\t\t\t<AssetStatusBadge slug={asset.statusSlug} />\n\t\t\t</SelectableCard.Footer>\n\t\t</SelectableCard>\n\t);\n};\nPickerAssetCard.displayName = \"PickerAssetCard\";\n","// components/picker/picker-footer.tsx\nimport { Button } from \"@knkcs/anker/atoms\";\nimport { Box, Flex, HStack, Text } from \"@knkcs/anker/primitives\";\nimport { useTranslation } from \"react-i18next\";\n\nexport interface PickerFooterProps {\n\tcount: number;\n\tconfirmLabel: string;\n\tcancelLabel: string;\n\tonConfirm: () => void;\n\tonCancel: () => void;\n\t/** Optional selection-strip content rendered on the left. */\n\tchildren?: React.ReactNode;\n}\n\nexport const PickerFooter: React.FC<PickerFooterProps> = ({\n\tcount,\n\tconfirmLabel,\n\tcancelLabel,\n\tonConfirm,\n\tonCancel,\n\tchildren,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\treturn (\n\t\t<Flex align=\"center\" gap=\"3\" w=\"full\">\n\t\t\t<HStack gap=\"2\" minW=\"0\" flex=\"1\">\n\t\t\t\t{children}\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" flexShrink={0}>\n\t\t\t\t\t{t(\"common.selectedCount\", { count })}\n\t\t\t\t</Text>\n\t\t\t</HStack>\n\t\t\t<Box flexShrink={0}>\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button variant=\"ghost\" onClick={onCancel}>\n\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={count === 0}\n\t\t\t\t\t\tonClick={onConfirm}\n\t\t\t\t\t>\n\t\t\t\t\t\t{confirmLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t</Box>\n\t\t</Flex>\n\t);\n};\nPickerFooter.displayName = \"PickerFooter\";\n","import { useCallback, useState } from \"react\";\n\nexport interface PickerSelection<T extends { id: string }> {\n\t/** Currently-selected full objects, in selection order. */\n\titems: T[];\n\tisSelected: (id: string) => boolean;\n\t/** Toggle an item. In single mode, selecting replaces any prior selection. */\n\ttoggle: (item: T) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n}\n\nexport function usePickerSelection<T extends { id: string }>(\n\tmode: \"single\" | \"multi\",\n): PickerSelection<T> {\n\tconst [items, setItems] = useState<T[]>([]);\n\n\tconst toggle = useCallback(\n\t\t(item: T) => {\n\t\t\tsetItems((prev) => {\n\t\t\t\tconst exists = prev.some((i) => i.id === item.id);\n\t\t\t\tif (mode === \"single\") return exists ? [] : [item];\n\t\t\t\treturn exists ? prev.filter((i) => i.id !== item.id) : [...prev, item];\n\t\t\t});\n\t\t},\n\t\t[mode],\n\t);\n\n\tconst remove = useCallback(\n\t\t(id: string) => setItems((prev) => prev.filter((i) => i.id !== id)),\n\t\t[],\n\t);\n\tconst clear = useCallback(() => setItems([]), []);\n\tconst isSelected = useCallback(\n\t\t(id: string) => items.some((i) => i.id === id),\n\t\t[items],\n\t);\n\n\treturn { items, isSelected, toggle, remove, clear };\n}\n","// asset-picker.tsx\nimport { EmptyState } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport { SearchInput } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tGrid,\n\tHStack,\n\tNativeSelect,\n\tSpinner,\n\tText,\n} from \"@knkcs/anker/primitives\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { FolderTree } from \"./components/folder-tree\";\nimport {\n\tPickerAssetCard,\n\tgetMimeCategory,\n} from \"./components/picker/picker-asset-card\";\nimport { PickerFooter } from \"./components/picker/picker-footer\";\nimport { usePickerSelection } from \"./components/picker/use-picker-selection\";\nimport { UploadDialog } from \"./components/upload/upload-dialog\";\nimport { UploadDropZone } from \"./components/upload/upload-drop-zone\";\nimport { useAssets } from \"./hooks/use-assets\";\nimport { usePreviewURL } from \"./hooks/use-preview-url\";\nimport { useAssetStatuses } from \"./statushub\";\nimport { useUploadStore } from \"./stores/upload-store\";\nimport type { AssetFilters, AssetInfo, AssetSelection } from \"./types\";\n\nexport interface AssetPickerProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\t/** @default \"single\" */\n\tmode?: \"single\" | \"multi\";\n\tonSelect: (selection: AssetSelection) => void;\n\t/** Enable upload-then-select (wired in Task 5). */\n\tallowUpload?: boolean;\n\t/** Client-side MIME filter, e.g. [\"image/*\"] or [\"application/pdf\"]. */\n\taccept?: string[];\n\t/** Initial/locked filters (e.g. a fixed assetTypeId). */\n\tinitialFilters?: AssetFilters;\n}\n\nfunction matchesAccept(asset: AssetInfo, accept: string[]): boolean {\n\tconst v = asset.versions[asset.versions.length - 1];\n\tif (!v) return false;\n\tconst mime = v.mimeType;\n\treturn accept.some((a) =>\n\t\ta.endsWith(\"/*\")\n\t\t\t? mime.startsWith(a.slice(0, a.indexOf(\"/\") + 1))\n\t\t\t: mime === a,\n\t);\n}\n\nexport function AssetPicker(props: AssetPickerProps): React.JSX.Element {\n\tconst { open, onOpenChange, onSelect, accept, initialFilters } = props;\n\tconst mode = props.mode ?? \"single\";\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst [filters, setFilters] = useState<AssetFilters>(initialFilters ?? {});\n\tconst folderId = filters.folderId ?? \"\";\n\tconst statusSlug = filters.statusSlug ?? \"\";\n\n\tconst selection = usePickerSelection<AssetInfo>(mode);\n\n\tfunction updateFilter<K extends keyof AssetFilters>(\n\t\tkey: K,\n\t\tvalue: AssetFilters[K],\n\t) {\n\t\tsetFilters((prev) => {\n\t\t\tconst next: AssetFilters = { ...prev };\n\t\t\tif (value === undefined || value === \"\") delete next[key];\n\t\t\telse next[key] = value;\n\t\t\treturn next;\n\t\t});\n\t}\n\n\tconst assetsQuery = useAssets(filters);\n\t// The workspace's own catalogue, read from statushub (§10).\n\tconst statusOptions = useAssetStatuses().data ?? [];\n\tconst allItems = assetsQuery.data?.items ?? [];\n\tconst items = useMemo(\n\t\t() =>\n\t\t\taccept?.length\n\t\t\t\t? allItems.filter((a) => matchesAccept(a, accept))\n\t\t\t\t: allItems,\n\t\t[allItems, accept],\n\t);\n\n\tconst allowUpload = props.allowUpload ?? false;\n\tconst addFiles = useUploadStore((s) => s.addFiles);\n\tconst uploadFiles = useUploadStore((s) => s.files);\n\tconst [uploadDialogOpen, setUploadDialogOpen] = useState(false);\n\t// assetIds already bridged this session — keeps the effect idempotent.\n\t// Not cleared on deselect, so re-uploading the same asset in one session\n\t// won't re-select it (acceptable for v1).\n\tconst bridgedRef = useRef<Set<string>>(new Set());\n\n\tfunction handleFilesSelected(files: File[]) {\n\t\taddFiles(files);\n\t\tsetUploadDialogOpen(true);\n\t}\n\n\t// Ephemeral picker state (selection/filters/upload dialog) is scrubbed in\n\t// the Modal's onExitComplete (not on `open` flipping false): the grid stays\n\t// visible through the exit animation, and an immediate reset would visibly\n\t// clear it mid-fade.\n\tfunction resetEphemeralState() {\n\t\tselection.clear();\n\t\tsetFilters(initialFilters ?? {});\n\t\tsetUploadDialogOpen(false);\n\t\tbridgedRef.current.clear();\n\t}\n\n\t// Fallback: zag presence skips onExitComplete when a reopen interrupts the\n\t// exit animation (fires only on the mounted→unmounted transition, not on\n\t// unmountSuspended→mounted) — reset again on open so a fast close-then-\n\t// reopen can't reopen with stale filters/selection/upload-dialog state.\n\t// Declared BEFORE the upload auto-select effect below: both run on the\n\t// same open-flip commit, and effects run in declaration order. This one\n\t// must go first — verified empirically, not just by inspection, because\n\t// the interaction is subtler than plain effect order: `bridgedRef` is a\n\t// ref (mutations are visible immediately to code in the same flush), but\n\t// `selection.isSelected` is a closure over the PRE-reset render, so\n\t// whichever effect runs second still sees the OLD selection value in that\n\t// same commit. What actually resolves it fresh is the cascade this reset\n\t// triggers: `selection.clear()` changes `usePickerSelection`'s `items`\n\t// state, which gives `isSelected` a new identity, which re-fires the\n\t// auto-select effect (it's in that effect's own deps) on the FOLLOWING\n\t// render — now with both `bridgedRef` and `selection.isSelected`\n\t// reflecting the real post-reset state. Swapping the order the other way\n\t// (auto-select first) was verified BY TEST to leave a stale bridge\n\t// re-selected after reopen instead of cleared — see the picker test file.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: reset only on open→true\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tresetEphemeralState();\n\t}, [open]);\n\n\t// Auto-select assets that finish uploading while the picker is open.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tconst byId = new Map(items.map((a) => [a.id, a]));\n\t\tfor (const f of uploadFiles) {\n\t\t\tif (\n\t\t\t\tf.status === \"done\" &&\n\t\t\t\tf.assetId &&\n\t\t\t\t!bridgedRef.current.has(f.assetId)\n\t\t\t) {\n\t\t\t\tconst a = byId.get(f.assetId);\n\t\t\t\tif (a) {\n\t\t\t\t\t// Process each finalized upload once. Select it unless the user\n\t\t\t\t\t// already has it selected (don't deselect a manual pick).\n\t\t\t\t\tbridgedRef.current.add(f.assetId);\n\t\t\t\t\tif (!selection.isSelected(a.id)) {\n\t\t\t\t\t\tselection.toggle(a);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [open, items, uploadFiles, selection.toggle, selection.isSelected]);\n\n\tfunction handleConfirm() {\n\t\tif (selection.items.length === 0) return;\n\t\tonSelect(\n\t\t\tmode === \"single\"\n\t\t\t\t? { mode: \"single\", asset: selection.items[0] }\n\t\t\t\t: { mode: \"multi\", assets: selection.items },\n\t\t);\n\t\tonOpenChange(false);\n\t}\n\n\tconst count = selection.items.length;\n\tconst confirmLabel =\n\t\tmode === \"multi\" && count > 0\n\t\t\t? t(\"assetPicker.insertCount\", { count })\n\t\t\t: t(\"assetPicker.insert\");\n\n\t// Do NOT `return null` when closed: unmounting the open dialog machine\n\t// under StrictMode orphans its scroll-lock/aria-hidden cleanup and wedges\n\t// the whole app (#66). Keep Modal mounted; lazyMount/unmountOnExit keep\n\t// the fresh-content-per-open semantics.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={resetEphemeralState}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\t// Widest typed Modal size — the picker needs room for the folder rail\n\t\t\t// + multi-column grid. (anker's recipe-only \"7xl\" isn't in the type union.)\n\t\t\tsize=\"cover\"\n\t\t\theader={\n\t\t\t\tmode === \"single\"\n\t\t\t\t\t? t(\"assetPicker.headerSingle\")\n\t\t\t\t\t: t(\"assetPicker.headerMulti\")\n\t\t\t}\n\t\t\tfooter={\n\t\t\t\t<PickerFooter\n\t\t\t\t\tcount={count}\n\t\t\t\t\tconfirmLabel={confirmLabel}\n\t\t\t\t\tcancelLabel={t(\"assetPicker.cancel\")}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tonCancel={() => onOpenChange(false)}\n\t\t\t\t>\n\t\t\t\t\t<HStack gap=\"1\" minW=\"0\">\n\t\t\t\t\t\t{selection.items.slice(0, 8).map((a) => {\n\t\t\t\t\t\t\tconst v = a.versions[a.versions.length - 1];\n\t\t\t\t\t\t\tconst isImage = getMimeCategory(a) === \"image\";\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\t\tposition=\"relative\"\n\t\t\t\t\t\t\t\t\tw=\"30px\"\n\t\t\t\t\t\t\t\t\th=\"30px\"\n\t\t\t\t\t\t\t\t\tborderRadius=\"md\"\n\t\t\t\t\t\t\t\t\toverflow=\"hidden\"\n\t\t\t\t\t\t\t\t\tborderWidth=\"1px\"\n\t\t\t\t\t\t\t\t\tborderColor=\"border\"\n\t\t\t\t\t\t\t\t\tflexShrink={0}\n\t\t\t\t\t\t\t\t\ttitle={a.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isImage && v ? (\n\t\t\t\t\t\t\t\t\t\t<PickerStripThumb\n\t\t\t\t\t\t\t\t\t\t\tassetId={a.id}\n\t\t\t\t\t\t\t\t\t\t\tversionId={v.id}\n\t\t\t\t\t\t\t\t\t\t\tname={a.name}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<Flex\n\t\t\t\t\t\t\t\t\t\t\tw=\"full\"\n\t\t\t\t\t\t\t\t\t\t\th=\"full\"\n\t\t\t\t\t\t\t\t\t\t\talign=\"center\"\n\t\t\t\t\t\t\t\t\t\t\tjustify=\"center\"\n\t\t\t\t\t\t\t\t\t\t\tbg=\"bg.muted\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"2xs\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t\t\t\t\t{a.name.slice(0, 2)}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{count > 8 && (\n\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\" flexShrink={0}>\n\t\t\t\t\t\t\t\t{t(\"assetPicker.moreCount\", { count: count - 8 })}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</HStack>\n\t\t\t\t</PickerFooter>\n\t\t\t}\n\t\t>\n\t\t\t<Flex h=\"full\" minH=\"0\">\n\t\t\t\t<Box\n\t\t\t\t\tw=\"188px\"\n\t\t\t\t\tflexShrink={0}\n\t\t\t\t\tborderRightWidth=\"1px\"\n\t\t\t\t\tborderColor=\"border\"\n\t\t\t\t\tbg=\"bg.subtle\"\n\t\t\t\t\toverflowY=\"auto\"\n\t\t\t\t\tp=\"2\"\n\t\t\t\t>\n\t\t\t\t\t<FolderTree\n\t\t\t\t\t\tactiveFolderId={folderId}\n\t\t\t\t\t\tonFolderSelect={(id) => updateFilter(\"folderId\", id || undefined)}\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t\t<Flex direction=\"column\" flex=\"1\" minW=\"0\">\n\t\t\t\t\t<Flex\n\t\t\t\t\t\tgap=\"3\"\n\t\t\t\t\t\talign=\"center\"\n\t\t\t\t\t\tpx=\"4\"\n\t\t\t\t\t\tpy=\"2\"\n\t\t\t\t\t\tborderBottomWidth=\"1px\"\n\t\t\t\t\t\tborderColor=\"border\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\tonSearch={(value) => updateFilter(\"search\", value || undefined)}\n\t\t\t\t\t\t\tdefaultValue={filters.search ?? \"\"}\n\t\t\t\t\t\t\tplaceholder={t(\"assetPicker.searchPlaceholder\")}\n\t\t\t\t\t\t\tmaxWidth=\"260px\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<HStack gap=\"1\">\n\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t{t(\"assetPicker.statusLabel\")}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tvalue={statusSlug}\n\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(\"statusSlug\", e.target.value || undefined)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<option value=\"\">{t(\"assetPicker.statusFilterAll\")}</option>\n\t\t\t\t\t\t\t\t{statusOptions.map((s) => (\n\t\t\t\t\t\t\t\t\t<option key={s.id} value={s.slug}>\n\t\t\t\t\t\t\t\t\t\t{s.name}\n\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t</Flex>\n\t\t\t\t\t{allowUpload && (\n\t\t\t\t\t\t<Box px=\"4\" py=\"2\" borderBottomWidth=\"1px\" borderColor=\"border\">\n\t\t\t\t\t\t\t<UploadDropZone onFilesSelected={handleFilesSelected} compact />\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t)}\n\t\t\t\t\t<Box flex=\"1\" overflow=\"auto\" p=\"4\">\n\t\t\t\t\t\t{assetsQuery.isLoading ? (\n\t\t\t\t\t\t\t<Flex justify=\"center\" py=\"10\">\n\t\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t) : items.length === 0 ? (\n\t\t\t\t\t\t\t<EmptyState header={t(\"assetPicker.emptyLabel\")} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Grid\n\t\t\t\t\t\t\t\ttemplateColumns=\"repeat(auto-fill, minmax(150px, 1fr))\"\n\t\t\t\t\t\t\t\tgap=\"3\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{items.map((a) => (\n\t\t\t\t\t\t\t\t\t<PickerAssetCard\n\t\t\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\t\t\tasset={a}\n\t\t\t\t\t\t\t\t\t\tselected={selection.isSelected(a.id)}\n\t\t\t\t\t\t\t\t\t\tselectionVisible={count > 0}\n\t\t\t\t\t\t\t\t\t\tonToggle={selection.toggle}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Box>\n\t\t\t\t</Flex>\n\t\t\t</Flex>\n\t\t\t{allowUpload && (\n\t\t\t\t<UploadDialog\n\t\t\t\t\topen={uploadDialogOpen}\n\t\t\t\t\tonClose={() => setUploadDialogOpen(false)}\n\t\t\t\t\tfolderId={folderId || undefined}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Modal>\n\t);\n}\nAssetPicker.displayName = \"AssetPicker\";\n\n/** Footer thumbnail — fetches a preview URL for one selected image. */\nfunction PickerStripThumb({\n\tassetId,\n\tversionId,\n\tname,\n}: { assetId: string; versionId: string; name: string }) {\n\tconst { data } = usePreviewURL(assetId, versionId);\n\tif (!data) return <Box w=\"full\" h=\"full\" bg=\"bg.muted\" />;\n\treturn (\n\t\t<img\n\t\t\tsrc={data}\n\t\t\talt={name}\n\t\t\tstyle={{ width: \"100%\", height: \"100%\", objectFit: \"cover\" }}\n\t\t/>\n\t);\n}\nPickerStripThumb.displayName = \"PickerStripThumb\";\n","// collection-picker.tsx\nimport { Button, EmptyState, TextInput } from \"@knkcs/anker/atoms\";\nimport { Modal, SelectableCard } from \"@knkcs/anker/components\";\nimport { SearchInput } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tGrid,\n\tHStack,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { FolderOpen } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { PickerFooter } from \"./components/picker/picker-footer\";\nimport { usePickerSelection } from \"./components/picker/use-picker-selection\";\nimport { RestrictedLockBadge } from \"./components/restricted\";\nimport { useCollections, useCreateCollection } from \"./hooks/use-collections\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport type { CollectionInfo, CollectionSelection } from \"./types\";\n\nexport interface CollectionPickerProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\t/** @default \"single\" */\n\tmode?: \"single\" | \"multi\";\n\tonSelect: (selection: CollectionSelection) => void;\n\t/** Show the inline \"New collection\" affordance. @default false */\n\tallowCreate?: boolean;\n}\n\nexport function CollectionPicker(\n\tprops: CollectionPickerProps,\n): React.JSX.Element {\n\tconst { open, onOpenChange, onSelect, allowCreate } = props;\n\tconst mode = props.mode ?? \"single\";\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst [search, setSearch] = useState(\"\");\n\tconst [newName, setNewName] = useState(\"\");\n\tconst selection = usePickerSelection<CollectionInfo>(mode);\n\n\tconst collectionsQuery = useCollections();\n\tconst createCollection = useCreateCollection();\n\tconst all = collectionsQuery.data ?? [];\n\tconst items = search\n\t\t? all.filter((c) => c.name.toLowerCase().includes(search.toLowerCase()))\n\t\t: all;\n\n\t// Ephemeral picker state (selection/search/inline-create name) is scrubbed\n\t// in the Modal's onExitComplete (not on `open` flipping false): the grid\n\t// stays visible through the exit animation, and an immediate reset would\n\t// visibly clear it mid-fade.\n\tfunction resetEphemeralState() {\n\t\tselection.clear();\n\t\tsetSearch(\"\");\n\t\tsetNewName(\"\");\n\t}\n\n\t// Fallback: zag presence skips onExitComplete when a reopen interrupts the\n\t// exit animation (fires only on the mounted→unmounted transition, not on\n\t// unmountSuspended→mounted) — reset again on open so a fast close-then-\n\t// reopen can't reopen with stale search/selection/newName.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: reset only on open→true\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tresetEphemeralState();\n\t}, [open]);\n\n\tfunction handleConfirm() {\n\t\tif (selection.items.length === 0) return;\n\t\tonSelect(\n\t\t\tmode === \"single\"\n\t\t\t\t? { mode: \"single\", collection: selection.items[0] }\n\t\t\t\t: { mode: \"multi\", collections: selection.items },\n\t\t);\n\t\tonOpenChange(false);\n\t}\n\n\tasync function handleCreate() {\n\t\tconst name = newName.trim();\n\t\tif (!name) return;\n\t\ttry {\n\t\t\tawait createCollection.mutateAsync({\n\t\t\t\tname,\n\t\t\t\tslug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tdescription: \"\",\n\t\t\t\ttype: \"static\",\n\t\t\t\trules: \"\",\n\t\t\t});\n\t\t\tsetNewName(\"\");\n\t\t\ttoaster.success({ title: t(\"collectionPicker.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionPicker.createFailedToast\"));\n\t\t}\n\t}\n\n\tconst count = selection.items.length;\n\tconst confirmLabel =\n\t\tcount > 0\n\t\t\t? t(\"collectionPicker.confirmCount\", { count })\n\t\t\t: t(\"collectionPicker.confirm\");\n\n\t// Do NOT `return null` when closed: unmounting the open dialog machine\n\t// under StrictMode orphans its scroll-lock/aria-hidden cleanup and wedges\n\t// the whole app (#66). Keep Modal mounted; lazyMount/unmountOnExit keep\n\t// the fresh-content-per-open semantics.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={resetEphemeralState}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\tsize=\"lg\"\n\t\t\theader={\n\t\t\t\tmode === \"single\"\n\t\t\t\t\t? t(\"collectionPicker.headerSingle\")\n\t\t\t\t\t: t(\"collectionPicker.headerMulti\")\n\t\t\t}\n\t\t\tfooter={\n\t\t\t\t<PickerFooter\n\t\t\t\t\tcount={count}\n\t\t\t\t\tconfirmLabel={confirmLabel}\n\t\t\t\t\tcancelLabel={t(\"collectionPicker.cancel\")}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tonCancel={() => onOpenChange(false)}\n\t\t\t\t/>\n\t\t\t}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap=\"3\" minH=\"280px\">\n\t\t\t\t<Flex gap=\"2\" align=\"center\">\n\t\t\t\t\t<SearchInput\n\t\t\t\t\t\tonSearch={setSearch}\n\t\t\t\t\t\tplaceholder={t(\"collectionPicker.searchPlaceholder\")}\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tmaxWidth=\"full\"\n\t\t\t\t\t/>\n\t\t\t\t\t{allowCreate && (\n\t\t\t\t\t\t<HStack gap=\"2\" flexShrink={0}>\n\t\t\t\t\t\t\t<Box w=\"160px\">\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\tvalue={newName}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setNewName(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"collectionPicker.createPlaceholder\")}\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tonClick={handleCreate}\n\t\t\t\t\t\t\t\tloading={createCollection.isPending}\n\t\t\t\t\t\t\t\tdisabled={!newName.trim()}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"collectionPicker.createButton\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t)}\n\t\t\t\t</Flex>\n\n\t\t\t\t{collectionsQuery.isLoading ? (\n\t\t\t\t\t<Flex justify=\"center\" py=\"10\">\n\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t</Flex>\n\t\t\t\t) : items.length === 0 ? (\n\t\t\t\t\t<EmptyState header={t(\"collectionPicker.emptyLabel\")} />\n\t\t\t\t) : (\n\t\t\t\t\t<Grid templateColumns=\"repeat(2, 1fr)\" gap=\"3\">\n\t\t\t\t\t\t{items.map((c) => (\n\t\t\t\t\t\t\t<SelectableCard\n\t\t\t\t\t\t\t\tkey={c.id}\n\t\t\t\t\t\t\t\tselected={selection.isSelected(c.id)}\n\t\t\t\t\t\t\t\tselectionVisible={count > 0}\n\t\t\t\t\t\t\t\tonSelect={() => selection.toggle(c)}\n\t\t\t\t\t\t\t\tonClick={() => selection.toggle(c)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectableCard.Body>\n\t\t\t\t\t\t\t\t\t<HStack gap=\"2\" align=\"center\">\n\t\t\t\t\t\t\t\t\t\t<FolderOpen size={16} />\n\t\t\t\t\t\t\t\t\t\t<Box minW=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t<HStack gap=\"1\" align=\"center\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" truncate>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{c.name}\n\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t{c.restricted && <RestrictedLockBadge />}\n\t\t\t\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize=\"xs\"\n\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t\t\t\t\t\t\t\ttextTransform=\"capitalize\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{c.type}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t</SelectableCard.Body>\n\t\t\t\t\t\t\t</SelectableCard>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Grid>\n\t\t\t\t)}\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n}\nCollectionPicker.displayName = \"CollectionPicker\";\n","import de from \"./de.json\";\nimport en from \"./en.json\";\n\n/**\n * The i18next namespace every string in this package is looked up under. A\n * host merges `i18nResources` and lists this constant among its namespaces —\n * never the literal, so a rename here fails the host's compile rather than\n * rendering raw keys (knkcms/core ADR 0005's provider checklist; #807). The\n * package's own `useTranslation` calls name the same string, which\n * `resources.test.ts` holds them to.\n */\nexport const MEDIAHUB_UI_NS = \"mediahub-ui\";\n\n/** The package's bundled translations, keyed by language, then by\n * `MEDIAHUB_UI_NS`. */\nexport const i18nResources = {\n\ten: { [MEDIAHUB_UI_NS]: en },\n\tde: { [MEDIAHUB_UI_NS]: de },\n};\n","/**\n * @knkcs/mediahub-ui — reusable mediahub asset-management surfaces.\n *\n * Transport-agnostic clients + provider + TanStack Query hooks + stores,\n * plus the UI surfaces themselves (<AssetLibrary>, <AssetPicker>,\n * <CollectionPicker>, <AssetDetail>, …). A host's own tests reach the\n * `./testing` subpath instead of this one — see `src/testing`.\n */\nexport const MEDIAHUB_UI_VERSION = \"0.1.0\";\n\nexport * from \"./types\";\nexport * from \"./lib/rpc-errors\";\nexport * from \"./lib/slugify\";\nexport * from \"./lib/mime-type-list\";\nexport * from \"./clients\";\nexport * from \"./connect-clients\";\nexport * from \"./provider\";\nexport * from \"./statushub\";\nexport * from \"./hooks\";\nexport * from \"./stores\";\nexport * from \"./components\";\nexport * from \"./asset-library\";\nexport * from \"./asset-detail\";\nexport * from \"./asset-type-detail\";\nexport * from \"./asset-type-create\";\nexport * from \"./asset-type-index\";\nexport * from \"./asset-picker\";\nexport * from \"./collection-picker\";\nexport { i18nResources, MEDIAHUB_UI_NS } from \"./i18n/resources\";\n"],"names":["CODE_PERMISSION_DENIED","CODE_FAILED_PRECONDITION","CODE_UNAVAILABLE","LEAK_GUARD_DETAIL_TYPE","PERMISSION_DENIED_TITLE","PERMISSION_DENIED_BODY","LEAK_GUARD_TITLE","LEAK_GUARD_GENERIC","LEAK_GUARD_RULES","connectCode","err","code","isPermissionDenied","isRetryableUnavailable","isLeakGuardDetailType","type","asExposure","raw","r","str","v","violationFrom","exposures","findLeakGuardViolation","details","d","entry","describeRpcError","fallbackTitle","violation","rule","items","e","showRpcErrorToast","toaster","slugify","name","parseMimeTypeList","value","formatMimeTypeList","mapTs","t","COLLTYPE_TO_NUM","NUM_TO_COLLTYPE","mapVersion","parseAssetMetadata","parsed","mapAsset","a","mapFolder","f","mapCollection","c","mapTag","mapAssetType","mapAIConnection","mapAIProcess","p","o","mapAIProcessRun","createConnectAssetClient","workspaceId","res","id","params","patch","versionId","assetId","folderId","fromStatusSlug","toStatusSlug","createConnectFolderClient","parentId","restricted","call","createConnectCollectionClient","collectionId","assetIds","createConnectTagClient","tagId","createConnectAssetTypeClient","cur","merged","key","fallback","createConnectDirectoryClient","ids","u","m","GRANT_RESOURCE_TO_NUM","NUM_TO_GRANT_LEVEL","GRANT_LEVEL_TO_NUM","createConnectGrantClient","resourceType","resourceId","grants","g","level","userId","createConnectAuthzClient","createConnectDashboardClient","s","layoutJson","createConnectAIConnectionClient","createConnectAIProcessClient","assetTypeId","createConnectMediahubClients","gen","MediahubContext","createContext","EMPTY_LINKS","MediahubProvider","clients","links","children","useMemo","jsx","useMediahubContext","ctx","useContext","useMediahubClients","useWorkspaceId","useMediahubLinks","ASSET_STATUS_CATALOGUE","useAssetStatuses","useStatuses","useAssetStatus","slug","data","isLoading","uploadFileToSAS","url","file","contentType","onProgress","resolve","reject","xhr","useAddVersion","assets","qc","useQueryClient","progress","setProgress","useState","useMutation","comment","uploadUrl","_data","vars","useAssets","filters","useQuery","useAsset","useCreateAsset","useUpdateAsset","useDeleteAsset","useMoveAsset","useTransitionAssetStatus","useEnhanceAssetMetadata","usePreviewURL","useCanManage","authz","useFolders","opts","folders","useFolder","useCreateFolder","useUpdateFolder","useDeleteFolder","useMoveFolder","useSetFolderRestricted","useGrants","failureCount","error","useGrantAccess","_err","useRevokeAccess","useCollections","collections","useCollection","useCreateCollection","useUpdateCollection","useDeleteCollection","useAddAssetsToCollection","useSetCollectionRestricted","useRemoveAssetsFromCollection","useTags","tags","useCreateTag","useUpdateTag","useDeleteTag","useTagAssets","useUntagAssets","useAssetTypes","assetTypes","useAssetType","useCreateAssetType","useUpdateAssetType","useDeleteAssetType","useUsers","directory","sorted","useWorkspaceMembers","useWorkspaceStats","dashboard","useGetDashboardLayout","useSaveDashboardLayout","useAIConnections","aiConnection","useAIConnection","useCreateAIConnection","useUpdateAIConnection","useDeleteAIConnection","useAIProcesses","aiProcess","useAIProcess","useCreateAIProcess","useUpdateAIProcess","useDeleteAIProcess","isActive","runs","useAIProcessRuns","wasActive","useRef","query","q","seenAssetId","useEffect","active","useSelectionStore","create","set","get","state","i","targetId","orderedIds","lastClickedId","selectedIds","startIdx","endIdx","low","high","rangeIds","usePreferencesStore","persist","mode","updateFile","files","clientId","useUploadStore","newFiles","entries","client","pending","described","message","ALL_REQUIRED_MARKERS","processFormSchema","z","EMPTY_OUTPUT","buildProcessOutputs","proc","outputs","OutputRow","index","onRemove","metadataAccessors","canRemove","useTranslation","control","useFormContext","target","useWatch","jsxs","Flex","Box","InputField","SelectField","Button","X","ProcessFormFields","connections","fields","append","remove","useFieldArray","FormMarkersProvider","TextareaField","field","Plus","CreateFormContent","open","onClose","createMutation","resolver","zodResolver","methods","useForm","onSubmit","Modal","FormProvider","EditFormContent","editProcess","latchedProcessRef","process","updateMutation","AIProcessFormDialog","Fragment","STRUCTURAL_MARKERS","customFieldEntries","metadataSchema","countCustomFields","metadataAccessorOptions","_a","_b","fullPatch","AIProcessesTab","typeId","confirm","useConfirmModal","processesQuery","processes","deleteProcess","updateProcess","createOpen","setCreateOpen","setEditProcess","connectionMap","b","handleDelete","handleToggle","handleMove","delta","neighbour","noConnections","Stack","Text","Spinner","EmptyState","Switch","ChevronUp","ChevronDown","Pencil","Trash2","AssetStatusBadge","status","StatusBadge","getMimeCategory","asset","version","mime","TypeIcon","category","Image","Film","Music","FileText","useCategoryLabel","AssetCard","onOpen","isSelected","anySelected","toggle","categoryLabel","latestVersion","previewQuery","previewUrl","imgError","setImgError","SelectableCard","Skeleton","AssetGrid","Grid","mimeType","AssetPreview","fileName","setError","Download","AssetStatusControl","statusSlug","transition","StatusTransitionControl","to","BulkActionBar","clearSelection","count","deleteAsset","tagAssets","addToCollection","tagsQuery","collectionsQuery","handleBulkDelete","n","failed","firstErr","handleBulkTag","handleBulkAddToCollection","AnkerBulkActionBar","Tag","tag","FolderOpen","col","CollectionChipField","assignedCollectionIds","allCollections","removeFromCollection","assigned","unassigned","handleAdd","collection","handleRemove","ChipPicker","CollectionPanel","activeCollectionId","onSelectCollection","createCollection","handleCreate","InlineCreatableList","useAncestorChain","folder","parent","grandparent","chain","FolderBreadcrumbs","onNavigate","ancestors","BreadcrumbRoot","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","item","BreadcrumbCurrentLink","MaybeLink","href","Link","LeakGuardRefusalDialog","refusal","HStack","maxFolderDepth","openCollectionIds","assetExposedByOpenCollection","folderChainRestricted","folderSubtreeExposed","openIds","frontier","depth","next","subjectId","subject","subjectName","ManageAccessDialog","props","onOpenChange","kind","pickedUserId","setPickedUserId","pickLevel","setPickLevel","rosterQuery","roster","denied","membersQuery","rosterUserIds","namesQuery","nameOf","scopeQuery","grantAccess","revokeAccess","mutating","granteeIds","candidates","names","sortedGrants","nm","handleGrant","handleLevelChange","handleRevoke","viewerLabel","editorLabel","renderBody","Lock","Persona","Badge","NativeSelect","IconButton","currentParentId","rowDisabledReason","chainRestricted","DestinationRowButton","reason","selected","emphasized","onClick","Folder","DestinationRow","ancestorRestricted","expanded","setExpanded","childrenQuery","isSelf","onDeselect","ChevronRight","child","MoveDialog","onMoved","selectedId","setSelectedId","rootQuery","moveFolder","moveAsset","subjectFolderId","folderGuardQuery","guardActive","resetEphemeralState","handleConfirm","handleDeselect","useCallback","current","rootReason","moving","restrictedContainerWarning","unrestrictDisclosure","RestrictedLockBadge","size","ml","RestrictedWarningNotice","RestrictedFolderDialog","onCreated","setName","createFolder","trimmed","msg","TextInput","FolderTree","activeFolderId","onFolderSelect","rootFolders","treeKey","setTreeKey","isCreating","setIsCreating","newName","setNewName","renamingId","setRenamingId","renameValue","setRenameValue","moveSubject","setMoveSubject","moveOpen","setMoveOpen","accessSubject","setAccessSubject","accessOpen","setAccessOpen","restrictedParentId","setRestrictedParentId","menuNodeId","setMenuNodeId","toggleRefusal","setToggleRefusal","refusalOpen","setRefusalOpen","updateFolder","deleteFolder","setFolderRestricted","canManage","creatingRef","renamingRef","rootChildren","createTreeCollection","node","handleLoadChildren","folderName","k","handleRenameSubmit","handleToggleRestricted","restricting","MenuRoot","MenuTrigger","Ellipsis","MenuContent","MenuItem","TreeViewRoot","TreeViewTree","TreeViewNode","TreeViewBranchControl","TreeViewBranchIndicator","TreeViewBranchText","FolderPlus","InlineEditField","onSave","as","placeholder","disabled","setDisabled","handleSubmit","nextValue","InlineEdit","MetadataSchemaEditor","initialSchema","onDirtyChange","updateAssetType","handleCommit","schema","FieldKitProvider","builtInFieldTypes","SpecEditor","TagChipField","assignedTagIds","allTags","untagAssets","assignedTags","unassignedTags","TagPanel","activeTags","onToggleTag","createTag","formatFileSize","bytes","FileRow","showOverride","onToggleOverride","setAssetType","UploadDialog","setBatchAssetType","startUpload","clearPending","analyzeWithAi","setAnalyzeWithAi","batchType","setBatchType","overrides","setOverrides","pendingFiles","handleBatchTypeChange","toggleOverride","prev","canUpload","handleUpload","handleCancel","Checkbox","UploadDropZone","onFilesSelected","compact","AnkerUploadDropZone","mapStatus","UploadToastStack","storeFiles","visible","dismiss","AnkerUploadToastStack","buildAssetTypeNameMap","types","collectUpdatedByIds","behaviorOptions","viewModeOptions","NO_ACTIVE_TAGS","AssetLibrary","onAssetOpen","initialFilters","onFiltersChange","setFilters","uploadDialogOpen","setUploadDialogOpen","fileInputRef","behaviorFilter","updateFilter","searchText","setSearchText","searchPrimed","timer","handleToggleTag","handleSelectCollection","setStatusSlug","setBehaviorFilter","addFiles","viewMode","setViewMode","handleFilesSelected","assetName","assetsQuery","statusOptions","listFailure","listFailureState","assetTypesQuery","typeNames","updatedByIds","userNames","setSelection","rowSelection","sel","handleRowSelectionChange","updater","filtersKey","columnHelper","createColumnHelper","listColumns","info","TruncatedTextCell","date","DateCell","ActionCell","rail","ContextRail","usePageRail","toolbar","Toolbar","SegmentedControl","IndexPageTemplate","Upload","SubNavLayout","DataTable","STRUCTURAL","composeFormValues","plugins","assetRecord","defaults","getDefaultValues","values","acc","stored","decomposePatch","metadata","columns","versionColumnHelper","aiRunColorPalette","AssetDetailRail","currentVersionId","currentMimeType","currentFilename","currentFileSize","currentVersion","createdBy","createdByName","tagIds","collectionIds","addVersion","assetType","unknownValue","DescriptionList","run","AssetDetail","onBack","onDeleted","assetQuery","assetsClient","updateAsset","enhanceMetadata","assetTypeQuery","composedValues","zodSchema","specToZodSchema","form","handleSaveBody","handleBack","activeTab","setActiveTab","allUserIds","handleDownloadVersion","versionColumns","currentBadge","StatusBadgeCell","handleDownloadCurrent","handleEnhance","sortedVersions","DetailPageTemplate","ArrowLeft","Sparkles","Tabs","SpecForm","AssetTypeDetail","assetTypesPath","deleteAssetType","metadataDirty","setMetadataDirty","parsedSchema","handleSave","handleTabChange","title","SwitchField","AssetTypeCreate","onCancel","createAssetType","slugEdited","setSlugEdited","created","SettingsPageTemplate","FormField","AssetTypeIndex","onCreate","search","setSearch","filtered","SlugCell","BooleanCell","MenuCell","row","ImageIcon","PickerAssetCard","selectionVisible","onToggle","PickerFooter","confirmLabel","cancelLabel","onConfirm","usePickerSelection","setItems","exists","clear","matchesAccept","accept","AssetPicker","onSelect","selection","allItems","allowUpload","uploadFiles","bridgedRef","byId","isImage","PickerStripThumb","SearchInput","CollectionPicker","allowCreate","all","MEDIAHUB_UI_NS","i18nResources","en","de","MEDIAHUB_UI_VERSION"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/lib/rpc-errors.ts","../src/lib/slugify.ts","../src/lib/mime-type-list.ts","../src/connect-clients.ts","../src/provider.tsx","../src/statushub.ts","../src/lib/sas-upload.ts","../src/hooks/use-add-version.ts","../src/hooks/use-assets.ts","../src/hooks/use-authz.ts","../src/hooks/use-folders.ts","../src/hooks/use-grants.ts","../src/hooks/use-collections.ts","../src/hooks/use-tags.ts","../src/hooks/use-asset-types.ts","../src/hooks/use-users.ts","../src/hooks/use-dashboard.ts","../src/hooks/use-ai-connections.ts","../src/hooks/use-ai-processes.ts","../src/hooks/use-ai-process-runs.ts","../src/stores/selection-store.ts","../src/stores/preferences-store.ts","../src/stores/upload-store.ts","../src/components/active-filter-chips.tsx","../src/components/ai-process-form-dialog.tsx","../src/lib/metadata-field-count.ts","../src/components/ai-processes-tab.tsx","../src/components/asset-status-badge.tsx","../src/components/asset-grid.tsx","../src/components/asset-preview.tsx","../src/components/asset-status-control.tsx","../src/components/bulk-action-bar.tsx","../src/components/collection-chip-field.tsx","../src/components/collection-panel.tsx","../src/components/folder-breadcrumbs.tsx","../src/components/leak-guard-refusal-dialog.tsx","../src/lib/move-guard.ts","../src/components/manage-access-dialog.tsx","../src/components/move-dialog.tsx","../src/components/restricted.tsx","../src/components/restricted-folder-dialog.tsx","../src/components/folder-tree.tsx","../src/components/inline-edit-field.tsx","../src/components/metadata-schema-editor.tsx","../src/components/tag-chip-field.tsx","../src/components/tag-panel.tsx","../src/components/upload/upload-dialog.tsx","../src/components/upload/upload-drop-zone.tsx","../src/components/upload/upload-toast-stack.tsx","../src/asset-library-resolve.ts","../src/asset-library.tsx","../src/lib/asset-metadata-form.ts","../src/asset-detail.tsx","../src/asset-type-detail.tsx","../src/asset-type-create.tsx","../src/asset-type-index.tsx","../src/collection-detail.tsx","../src/components/picker/picker-asset-card.tsx","../src/components/picker/picker-footer.tsx","../src/components/picker/use-picker-selection.ts","../src/asset-picker.tsx","../src/collection-create.tsx","../src/collection-index.tsx","../src/collection-picker.tsx","../src/i18n/resources.ts","../src/index.ts"],"sourcesContent":["import { toaster } from \"@knkcs/anker/primitives\";\n\n/**\n * Transport-level error mapping (guardian#50): permission denials and\n * leak-guard conflicts become human-readable descriptions; every other error\n * keeps the server's message, which for validation failures is deliberate\n * guidance.\n *\n * The mapping is structural on purpose — mediahub-ui takes no dependency on\n * `@connectrpc/connect` or generated proto types. A ConnectError is\n * recognized by its numeric `code`; a leak-guard conflict by an error detail\n * of type `mediahub.v1.LeakGuardViolation`, whose `debug` field carries the\n * server's protoJSON (Connect JSON protocol) naming the refusing rule and\n * the asset→collection exposures involved.\n */\n\n/** Connect/gRPC wire codes (subset we map). */\nconst CODE_PERMISSION_DENIED = 7;\nconst CODE_FAILED_PRECONDITION = 9;\nconst CODE_UNAVAILABLE = 14;\n\nconst LEAK_GUARD_DETAIL_TYPE = \"mediahub.v1.LeakGuardViolation\";\n\n/** One offending asset→collection pair behind a leak-guard refusal. */\nexport interface LeakGuardExposure {\n\tassetId: string;\n\tassetName: string;\n\tcollectionId: string;\n\tcollectionName: string;\n}\n\nexport interface RpcErrorDescription {\n\tkind: \"permission-denied\" | \"leak-guard\" | \"other\";\n\ttitle: string;\n\tdescription: string;\n\t/** Present for leak-guard conflicts: the items the refusal involves. */\n\texposures?: LeakGuardExposure[];\n\t/** Present for leak-guard conflicts: the refusing rule's explanation\n\t * without the joined item list — for surfaces that render `exposures`\n\t * themselves (e.g. the refusal dialog). */\n\truleText?: string;\n}\n\nconst PERMISSION_DENIED_TITLE = \"You don't have access\";\nconst PERMISSION_DENIED_BODY =\n\t\"You don't have permission to do this. The item's Owner or a workspace admin can grant you access.\";\n\nconst LEAK_GUARD_TITLE = \"Blocked to prevent a leak\";\nconst LEAK_GUARD_GENERIC =\n\t\"This change would expose Restricted material, so it was refused.\";\n\n/** Explanations per refusing rule, keyed by the wire enum's protoJSON name. */\nconst LEAK_GUARD_RULES: Record<string, string> = {\n\tLEAK_GUARD_RULE_RESTRICTED_ASSET_INTO_OPEN_COLLECTION:\n\t\t\"These assets live in a Restricted folder. An open collection is visible to the whole workspace, so adding them would leak Restricted material.\",\n\tLEAK_GUARD_RULE_ASSET_INTO_RESTRICTED_CHAIN_WHILE_EXPOSED:\n\t\t\"An open collection still exposes this asset, so moving it into a Restricted folder would leak Restricted material. Remove it from the collection first.\",\n\tLEAK_GUARD_RULE_FOLDER_INTO_RESTRICTED_CHAIN_WHILE_EXPOSED:\n\t\t\"An open collection still exposes assets inside this folder, so moving it under a Restricted folder would leak Restricted material. Remove those assets from their collections first.\",\n};\n\nfunction connectCode(err: unknown): number | undefined {\n\tif (typeof err !== \"object\" || err === null) return undefined;\n\tconst code = (err as { code?: unknown }).code;\n\treturn typeof code === \"number\" ? code : undefined;\n}\n\n/** Whether an RPC failure is a Connect permission denial. Callers that probe\n * for authority (a denial means \"not an authority\", not \"broken\") branch on\n * this instead of re-implementing the structural code check. */\nexport function isPermissionDenied(err: unknown): boolean {\n\treturn connectCode(err) === CODE_PERMISSION_DENIED;\n}\n\n/**\n * Whether an RPC failure is \"try again in a moment\" rather than a verdict.\n *\n * The server refuses a status change, and a behavior-filtered listing, with\n * Unavailable while statushub cannot be reached (statushub integration\n * standard §6, knkCS/mediahub#120) — the one code that means the same request,\n * unchanged, will work once the service answers again. mediahub being\n * unreachable itself arrives as the same code and means the same thing to the\n * reader, so the two are deliberately not told apart.\n */\nexport function isRetryableUnavailable(err: unknown): boolean {\n\treturn connectCode(err) === CODE_UNAVAILABLE;\n}\n\nfunction isLeakGuardDetailType(type: unknown): boolean {\n\treturn (\n\t\ttypeof type === \"string\" &&\n\t\t(type === LEAK_GUARD_DETAIL_TYPE ||\n\t\t\ttype.endsWith(`/${LEAK_GUARD_DETAIL_TYPE}`))\n\t);\n}\n\ninterface LeakGuardViolation {\n\trule?: string;\n\texposures: LeakGuardExposure[];\n}\n\nfunction asExposure(raw: unknown): LeakGuardExposure {\n\tconst r = (raw ?? {}) as Record<string, unknown>;\n\tconst str = (v: unknown) => (typeof v === \"string\" ? v : \"\");\n\treturn {\n\t\tassetId: str(r.assetId),\n\t\tassetName: str(r.assetName),\n\t\tcollectionId: str(r.collectionId),\n\t\tcollectionName: str(r.collectionName),\n\t};\n}\n\n/** Reads the violation from a detail's protoJSON `debug` (or from a decoded\n * message carrying `$typeName`). `rule` stays a protoJSON enum name. */\nfunction violationFrom(raw: unknown): LeakGuardViolation {\n\tif (typeof raw !== \"object\" || raw === null) return { exposures: [] };\n\tconst v = raw as Record<string, unknown>;\n\tconst exposures = Array.isArray(v.exposures)\n\t\t? v.exposures.map(asExposure)\n\t\t: [];\n\treturn { rule: typeof v.rule === \"string\" ? v.rule : undefined, exposures };\n}\n\nfunction findLeakGuardViolation(err: unknown): LeakGuardViolation | undefined {\n\tconst details = (err as { details?: unknown }).details;\n\tif (!Array.isArray(details)) return undefined;\n\tfor (const d of details) {\n\t\tif (typeof d !== \"object\" || d === null) continue;\n\t\tconst entry = d as Record<string, unknown>;\n\t\t// Wire shape from the Connect JSON protocol: { type, value, debug? }.\n\t\tif (isLeakGuardDetailType(entry.type)) {\n\t\t\treturn violationFrom(entry.debug);\n\t\t}\n\t\t// Already-decoded message (e.g. via findDetails with a registry).\n\t\tif (isLeakGuardDetailType(entry.$typeName)) {\n\t\t\treturn violationFrom(entry);\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Describes an RPC failure for the user. Permission denials and leak-guard\n * conflicts get mapped copy (never the raw server string); anything else\n * keeps the server's message under the caller's title, matching the previous\n * toast behavior.\n */\nexport function describeRpcError(\n\terr: unknown,\n\tfallbackTitle: string,\n): RpcErrorDescription {\n\tconst code = connectCode(err);\n\n\tif (code === CODE_PERMISSION_DENIED) {\n\t\treturn {\n\t\t\tkind: \"permission-denied\",\n\t\t\ttitle: PERMISSION_DENIED_TITLE,\n\t\t\tdescription: PERMISSION_DENIED_BODY,\n\t\t};\n\t}\n\n\tif (code === CODE_FAILED_PRECONDITION) {\n\t\tconst violation = findLeakGuardViolation(err);\n\t\tif (violation) {\n\t\t\tconst rule =\n\t\t\t\t(violation.rule && LEAK_GUARD_RULES[violation.rule]) ??\n\t\t\t\tLEAK_GUARD_GENERIC;\n\t\t\t// Single-line join: toast descriptions render as HTML text, where\n\t\t\t// newlines collapse to spaces.\n\t\t\tconst items = violation.exposures\n\t\t\t\t.map((e) => `${e.assetName} — in collection “${e.collectionName}”`)\n\t\t\t\t.join(\" • \");\n\t\t\treturn {\n\t\t\t\tkind: \"leak-guard\",\n\t\t\t\ttitle: LEAK_GUARD_TITLE,\n\t\t\t\tdescription: items ? `${rule} Involved: ${items}` : rule,\n\t\t\t\texposures: violation.exposures,\n\t\t\t\truleText: rule,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn {\n\t\tkind: \"other\",\n\t\ttitle: fallbackTitle,\n\t\tdescription:\n\t\t\terr instanceof Error ? err.message : \"An unexpected error occurred\",\n\t};\n}\n\n/**\n * The app-wide error toast: maps the failure with describeRpcError and shows\n * it. `fallbackTitle` is used only for errors outside the two mapped\n * families, preserving each call site's existing title.\n */\nexport function showRpcErrorToast(err: unknown, fallbackTitle: string): void {\n\tconst d = describeRpcError(err, fallbackTitle);\n\ttoaster.error({ title: d.title, description: d.description });\n}\n","/**\n * Convert a display name into a slug mediahub accepts: lowercase alphanumeric\n * with hyphens.\n *\n * Non-ASCII is a separator, not transliterated — \"Bürgerdaten\" becomes\n * \"b-rgerdaten\" — because the server's rule is the ASCII one and a\n * transliteration would produce a slug the user never saw derived.\n *\n * Both hosts carried their own copy of this (knkCS/mediahub#137); the package\n * owns it now so the asset-type screens share one derivation.\n */\nexport function slugify(name: string): string {\n\treturn name\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.replace(/-{2,}/g, \"-\");\n}\n","/**\n * A comma-separated MIME type field, both directions: the asset-type create and\n * detail screens edit `AssetTypeInfo.allowedMimeTypes` (a `string[]`) as one\n * plain-text input, so both parse the same way back into the array the mutation\n * sends.\n */\nexport const parseMimeTypeList = (value: string): string[] =>\n\tvalue\n\t\t.split(\",\")\n\t\t.map((v) => v.trim())\n\t\t.filter(Boolean);\n\n/**\n * Takes `string[] | undefined` although `AssetTypeInfo.allowedMimeTypes` is\n * declared `string[]`, because a host client may return the wire object\n * unmapped under that type. Connect omits an empty repeated field from the\n * JSON, so an asset type with no MIME types arrives without the key at all and\n * the declared type is a lie. The package's own client maps through\n * `mapAssetType`, which defaults it; core's did not, and the detail page went\n * down on \"Cannot read properties of undefined (reading 'join')\"\n * (knkcms/core#863). Tolerating the absent list here is the fix, kept in one\n * place for every host.\n */\nexport const formatMimeTypeList = (value: string[] | undefined): string =>\n\t(value ?? []).join(\", \");\n","// Structural shapes of the generated Connect service clients we depend on —\n// defined here rather than imported from web/src/gen so this package keeps\n// ZERO @connectrpc/proto peerDeps (odon pattern). Hosts pass their generated\n// clients (createClient(Service, transport)) which satisfy these structurally.\nimport type {\n\tAIConnectionClient,\n\tAIProcessClient,\n\tAssetClient,\n\tAssetTypeClient,\n\tAuthzClient,\n\tCollectionClient,\n\tDashboardClient,\n\tDirectoryClient,\n\tFolderClient,\n\tGrantClient,\n\tMediahubClients,\n\tTagClient,\n} from \"./clients\";\nimport { isPermissionDenied } from \"./lib/rpc-errors\";\nimport type {\n\tAIConnectionInfo,\n\tAIProcessInfo,\n\tAIProcessRunInfo,\n\tAssetInfo,\n\tAssetTypeInfo,\n\tAssetVersionInfo,\n\tCollectionInfo,\n\tCollectionType,\n\tFolderInfo,\n\tGrantEntry,\n\tGrantLevel,\n\tGrantResourceType,\n\tTagInfo,\n\tUserInfo,\n\tWorkspaceStats,\n} from \"./types\";\n\ntype Ts = { seconds: bigint; nanos: number } | undefined;\nconst mapTs = (t: Ts): Date | undefined =>\n\tt\n\t\t? new Date(Number(t.seconds) * 1000 + Math.floor(t.nanos / 1e6))\n\t\t: undefined;\n\nconst COLLTYPE_TO_NUM: Record<CollectionType, number> = {\n\tunspecified: 0,\n\tstatic: 1,\n\tsmart: 2,\n};\nconst NUM_TO_COLLTYPE: CollectionType[] = [\"unspecified\", \"static\", \"smart\"];\n\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapVersion = (v: any): AssetVersionInfo => ({\n\tid: v.id,\n\tversionNumber: v.versionNumber,\n\toriginalFilename: v.originalFilename,\n\tstorageKey: v.storageKey,\n\tfileSize: Number(v.fileSize),\n\tmimeType: v.mimeType,\n\tcreatedBy: v.createdBy,\n\tcomment: v.comment,\n\tcreatedAt: mapTs(v.createdAt),\n});\n/** Wire → domain: metadata travels as a JSON document (see asset.proto).\n * Malformed input degrades to {} — reads must never throw. */\nfunction parseAssetMetadata(raw: string | undefined): Record<string, unknown> {\n\tif (!raw) return {};\n\ttry {\n\t\tconst parsed = JSON.parse(raw) as unknown;\n\t\treturn typeof parsed === \"object\" &&\n\t\t\tparsed !== null &&\n\t\t\t!Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAsset = (a: any): AssetInfo => ({\n\tid: a.id,\n\tworkspaceId: a.workspaceId,\n\tname: a.name,\n\tdescription: a.description,\n\tstatusSlug: a.statusSlug ?? \"\",\n\tcurrentVersion: a.currentVersion,\n\tmetadata: parseAssetMetadata(a.metadata),\n\tassetTypeId: a.assetTypeId,\n\tfolderId: a.folderId,\n\tcreatedBy: a.createdBy,\n\tupdatedBy: a.updatedBy,\n\tcreatedAt: mapTs(a.createdAt),\n\tupdatedAt: mapTs(a.updatedAt),\n\tversions: (a.versions ?? []).map(mapVersion),\n\ttagIds: a.tagIds ?? [],\n\tcollectionIds: a.collectionIds ?? [],\n\tanalyzeWithAi: a.analyzeWithAi ?? false,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapFolder = (f: any): FolderInfo => ({\n\tid: f.id,\n\tworkspaceId: f.workspaceId,\n\tname: f.name,\n\tslug: f.slug,\n\tparentId: f.parentId,\n\trestricted: f.restricted ?? false,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapCollection = (c: any): CollectionInfo => ({\n\tid: c.id,\n\tworkspaceId: c.workspaceId,\n\tname: c.name,\n\tslug: c.slug,\n\tdescription: c.description,\n\ttype: NUM_TO_COLLTYPE[c.type] ?? \"unspecified\",\n\trules: c.rules,\n\trestricted: c.restricted ?? false,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapTag = (t: any): TagInfo => ({\n\tid: t.id,\n\tworkspaceId: t.workspaceId,\n\tname: t.name,\n\tslug: t.slug,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAssetType = (t: any): AssetTypeInfo => ({\n\tid: t.id,\n\tworkspaceId: t.workspaceId,\n\tname: t.name,\n\tslug: t.slug,\n\tdescription: t.description,\n\tallowedMimeTypes: t.allowedMimeTypes ?? [],\n\tmetadataSchema: t.metadataSchema,\n\tactive: t.active,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAIConnection = (c: any): AIConnectionInfo => ({\n\tid: c.id,\n\tworkspaceId: c.workspaceId,\n\tname: c.name,\n\tprovider: c.provider,\n\tendpoint: c.endpoint ?? \"\",\n\tdeployment: c.deployment ?? \"\",\n\tapiVersion: c.apiVersion ?? \"\",\n\tbaseUrl: c.baseUrl ?? \"\",\n\tmodel: c.model ?? \"\",\n\tdescription: c.description ?? \"\",\n\tactive: c.active,\n\thasApiKey: c.hasApiKey,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAIProcess = (p: any): AIProcessInfo => ({\n\tid: p.id,\n\tworkspaceId: p.workspaceId,\n\tassetTypeId: p.assetTypeId,\n\tconnectionId: p.connectionId,\n\tname: p.name,\n\tprompt: p.prompt,\n\toutputs: (p.outputs ?? []).map(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\t\t(o: any) => ({\n\t\t\tkey: o.key,\n\t\t\ttarget: o.target,\n\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t}),\n\t),\n\tposition: p.position ?? 0,\n\tactive: p.active,\n});\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\nconst mapAIProcessRun = (r: any): AIProcessRunInfo => ({\n\tid: r.id,\n\taiProcessId: r.aiProcessId,\n\tprocessName: r.processName ?? \"\",\n\tstatus: r.status ?? \"\",\n\terror: r.error ?? \"\",\n\tstartedAt: mapTs(r.startedAt),\n\tfinishedAt: mapTs(r.finishedAt),\n});\n\n// ─── Asset ────────────────────────────────────────────────────────────────────\n\n// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\ntype ProtoResponse = { [key: string]: any };\n\nexport interface ConnectAssetServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tlistAssets(req: any): Promise<{\n\t\tassets: ProtoResponse[];\n\t\tpagination?: {\n\t\t\ttotal: number;\n\t\t\tpage: number;\n\t\t\tpageSize: number;\n\t\t\ttotalPages: number;\n\t\t};\n\t}>;\n\tgetAsset(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAsset(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAsset(req: any): Promise<ProtoResponse>;\n\tdeleteAsset(req: { id: string }): Promise<unknown>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tgetUploadURL(req: any): Promise<{ uploadUrl: string; versionId: string }>;\n\tfinalizeUpload(req: { versionId: string }): Promise<ProtoResponse>;\n\tgetDownloadURL(req: { assetId: string; versionId: string }): Promise<{\n\t\tdownloadUrl: string;\n\t}>;\n\tmoveAsset(req: { id: string; folderId: string }): Promise<ProtoResponse>;\n\ttransitionAssetStatus(req: {\n\t\tid: string;\n\t\tfromStatusSlug: string;\n\t\ttoStatusSlug: string;\n\t}): Promise<ProtoResponse>;\n\tenhanceAssetMetadata(req: { assetId: string }): Promise<ProtoResponse>;\n\tlistAIProcessRuns(req: { assetId: string }): Promise<{\n\t\truns: ProtoResponse[];\n\t}>;\n}\n\nexport function createConnectAssetClient(\n\tc: ConnectAssetServiceClient,\n): AssetClient {\n\treturn {\n\t\tasync list(workspaceId, f) {\n\t\t\tconst res = await c.listAssets({\n\t\t\t\tworkspaceId,\n\t\t\t\tfolderId: f.folderId ?? \"\",\n\t\t\t\tassetTypeId: f.assetTypeId ?? \"\",\n\t\t\t\tstatusSlug: f.statusSlug ?? \"\",\n\t\t\t\tsearch: f.search ?? \"\",\n\t\t\t\tbehavior: f.behavior && f.behavior !== \"unspecified\" ? f.behavior : \"\",\n\t\t\t\ttagIds: f.tagIds ?? [],\n\t\t\t\tcollectionIds: f.collectionIds ?? [],\n\t\t\t});\n\t\t\tconst p = res.pagination;\n\t\t\treturn {\n\t\t\t\titems: res.assets.map(mapAsset),\n\t\t\t\ttotal: p?.total ?? res.assets.length,\n\t\t\t\tpage: p?.page ?? 1,\n\t\t\t\tpageSize: p?.pageSize ?? res.assets.length,\n\t\t\t\ttotalPages: p?.totalPages ?? 1,\n\t\t\t};\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAsset((await c.getAsset({ id })).asset);\n\t\t},\n\t\tasync create(workspaceId, params) {\n\t\t\treturn mapAsset(\n\t\t\t\t(\n\t\t\t\t\tawait c.createAsset({\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tdescription: params.description ?? \"\",\n\t\t\t\t\t\tassetTypeId: params.assetTypeId,\n\t\t\t\t\t\tfolderId: params.folderId ?? \"\",\n\t\t\t\t\t\tmetadata: JSON.stringify(params.metadata ?? {}),\n\t\t\t\t\t\tanalyzeWithAi: params.analyzeWithAi,\n\t\t\t\t\t})\n\t\t\t\t).asset,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapAsset(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAsset({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tdescription: patch.description ?? \"\",\n\t\t\t\t\t\tmetadata: JSON.stringify(patch.metadata ?? {}),\n\t\t\t\t\t})\n\t\t\t\t).asset,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAsset({ id });\n\t\t},\n\t\tasync getUploadUrl(p) {\n\t\t\tconst r = await c.getUploadURL({\n\t\t\t\tassetId: p.assetId,\n\t\t\t\tfilename: p.filename,\n\t\t\t\tcontentType: p.contentType,\n\t\t\t\tfileSize: BigInt(p.fileSize),\n\t\t\t\tcomment: p.comment ?? \"\",\n\t\t\t});\n\t\t\treturn { uploadUrl: r.uploadUrl, versionId: r.versionId };\n\t\t},\n\t\tasync finalizeUpload(versionId) {\n\t\t\treturn mapAsset((await c.finalizeUpload({ versionId })).asset);\n\t\t},\n\t\tasync getDownloadUrl(assetId, versionId) {\n\t\t\treturn (await c.getDownloadURL({ assetId, versionId })).downloadUrl;\n\t\t},\n\t\tasync move(id, folderId) {\n\t\t\treturn mapAsset((await c.moveAsset({ id, folderId })).asset);\n\t\t},\n\t\tasync transitionStatus(id, fromStatusSlug, toStatusSlug) {\n\t\t\treturn mapAsset(\n\t\t\t\t(await c.transitionAssetStatus({ id, fromStatusSlug, toStatusSlug }))\n\t\t\t\t\t.asset,\n\t\t\t);\n\t\t},\n\t\tasync enhanceMetadata(id) {\n\t\t\treturn mapAsset((await c.enhanceAssetMetadata({ assetId: id })).asset);\n\t\t},\n\t\tasync listProcessRuns(assetId) {\n\t\t\tconst res = await c.listAIProcessRuns({ assetId });\n\t\t\treturn res.runs.map(mapAIProcessRun);\n\t\t},\n\t};\n}\n\n// ─── Folder ───────────────────────────────────────────────────────────────────\n\nexport interface ConnectFolderServiceClient {\n\tlistFolders(req: { workspaceId: string; parentId: string }): Promise<{\n\t\tfolders: ProtoResponse[];\n\t}>;\n\tgetFolder(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateFolder(req: any): Promise<ProtoResponse>;\n\tupdateFolder(req: { id: string; name: string }): Promise<ProtoResponse>;\n\tdeleteFolder(req: { id: string }): Promise<unknown>;\n\tmoveFolder(req: { id: string; parentId: string }): Promise<ProtoResponse>;\n\t/** Restricted toggles — land with guardian#53; optional so the package\n\t * keeps accepting pre-#53 generated clients. */\n\trestrictFolder?(req: { id: string }): Promise<ProtoResponse>;\n\tunrestrictFolder?(req: { id: string }): Promise<ProtoResponse>;\n}\n\nexport function createConnectFolderClient(\n\tc: ConnectFolderServiceClient,\n): FolderClient {\n\treturn {\n\t\tasync list(workspaceId, parentId) {\n\t\t\tconst res = await c.listFolders({ workspaceId, parentId });\n\t\t\treturn res.folders.map(mapFolder);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapFolder((await c.getFolder({ id })).folder);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapFolder(\n\t\t\t\t(\n\t\t\t\t\tawait c.createFolder({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t\tparentId: params.parentId,\n\t\t\t\t\t\trestricted: params.restricted ?? false,\n\t\t\t\t\t})\n\t\t\t\t).folder,\n\t\t\t);\n\t\t},\n\t\tasync update(id, name) {\n\t\t\treturn mapFolder((await c.updateFolder({ id, name })).folder);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteFolder({ id });\n\t\t},\n\t\tasync move(id, parentId) {\n\t\t\treturn mapFolder((await c.moveFolder({ id, parentId })).folder);\n\t\t},\n\t\tasync setRestricted(id, restricted) {\n\t\t\tconst call = restricted ? c.restrictFolder : c.unrestrictFolder;\n\t\t\tif (typeof call !== \"function\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"This server can't toggle Restricted yet (RestrictFolder/UnrestrictFolder, guardian#53).\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn mapFolder((await call({ id })).folder);\n\t\t},\n\t};\n}\n\n// ─── Collection ───────────────────────────────────────────────────────────────\n\nexport interface ConnectCollectionServiceClient {\n\tlistCollections(req: { workspaceId: string }): Promise<{\n\t\tcollections: ProtoResponse[];\n\t}>;\n\tgetCollection(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateCollection(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateCollection(req: any): Promise<ProtoResponse>;\n\tdeleteCollection(req: { id: string }): Promise<unknown>;\n\taddAssets(req: {\n\t\tcollectionId: string;\n\t\tassetIds: string[];\n\t}): Promise<unknown>;\n\tremoveAssets(req: {\n\t\tcollectionId: string;\n\t\tassetIds: string[];\n\t}): Promise<unknown>;\n\t/** Restricted toggles — land with guardian#53; optional so the package\n\t * keeps accepting pre-#53 generated clients. */\n\trestrictCollection?(req: { id: string }): Promise<ProtoResponse>;\n\tunrestrictCollection?(req: { id: string }): Promise<ProtoResponse>;\n}\n\nexport function createConnectCollectionClient(\n\tc: ConnectCollectionServiceClient,\n): CollectionClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\tconst res = await c.listCollections({ workspaceId });\n\t\t\treturn res.collections.map(mapCollection);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapCollection((await c.getCollection({ id })).collection);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapCollection(\n\t\t\t\t(\n\t\t\t\t\tawait c.createCollection({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t\tdescription: params.description,\n\t\t\t\t\t\ttype: COLLTYPE_TO_NUM[params.type],\n\t\t\t\t\t\trules: params.rules,\n\t\t\t\t\t\trestricted: params.restricted ?? false,\n\t\t\t\t\t})\n\t\t\t\t).collection,\n\t\t\t);\n\t\t},\n\t\t/**\n\t\t * Read-modify-write, exactly as the asset-type client does and for the\n\t\t * same reason (knkCS/mediahub#159). `UpdateCollectionRequest` carries\n\t\t * plain proto3 scalars — no `optional`, no field mask — and the service\n\t\t * applies `description` unconditionally, so a patch naming only `name`\n\t\t * would arrive as `description: \"\"` and wipe it. So fetch the current\n\t\t * record and send the union.\n\t\t *\n\t\t * Supplied-ness is the presence of the KEY, not truthiness: an explicit\n\t\t * `\"\"` is a deliberate clear and is applied, while an absent key — or\n\t\t * one present but `undefined`, which cannot travel on the wire anyway —\n\t\t * keeps the current value. That is what lets a screen with no rules\n\t\t * editor (knkCS/mediahub#173) leave `rules` alone by simply not naming\n\t\t * it.\n\t\t *\n\t\t * This opens a read-modify-write window; concurrent edits are last\n\t\t * writer wins.\n\t\t */\n\t\tasync update(id, patch) {\n\t\t\tconst cur = mapCollection((await c.getCollection({ id })).collection);\n\t\t\tconst merged = <K extends keyof typeof patch>(\n\t\t\t\tkey: K,\n\t\t\t\tfallback: NonNullable<(typeof patch)[K]>,\n\t\t\t): NonNullable<(typeof patch)[K]> =>\n\t\t\t\tkey in patch && patch[key] !== undefined\n\t\t\t\t\t? (patch[key] as NonNullable<(typeof patch)[K]>)\n\t\t\t\t\t: fallback;\n\t\t\treturn mapCollection(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateCollection({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: merged(\"name\", cur.name ?? \"\"),\n\t\t\t\t\t\tdescription: merged(\"description\", cur.description ?? \"\"),\n\t\t\t\t\t\trules: merged(\"rules\", cur.rules ?? \"\"),\n\t\t\t\t\t})\n\t\t\t\t).collection,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteCollection({ id });\n\t\t},\n\t\tasync addAssets(collectionId, assetIds) {\n\t\t\tawait c.addAssets({ collectionId, assetIds });\n\t\t},\n\t\tasync removeAssets(collectionId, assetIds) {\n\t\t\tawait c.removeAssets({ collectionId, assetIds });\n\t\t},\n\t\tasync setRestricted(id, restricted) {\n\t\t\tconst call = restricted ? c.restrictCollection : c.unrestrictCollection;\n\t\t\tif (typeof call !== \"function\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"This server can't toggle Restricted yet (RestrictCollection/UnrestrictCollection, guardian#53).\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn mapCollection((await call({ id })).collection);\n\t\t},\n\t};\n}\n\n// ─── Tag ──────────────────────────────────────────────────────────────────────\n\nexport interface ConnectTagServiceClient {\n\tlistTags(req: { workspaceId: string }): Promise<{ tags: ProtoResponse[] }>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateTag(req: any): Promise<ProtoResponse>;\n\tupdateTag(req: { id: string; name: string }): Promise<ProtoResponse>;\n\tdeleteTag(req: { id: string }): Promise<unknown>;\n\ttagAssets(req: { tagId: string; assetIds: string[] }): Promise<unknown>;\n\tuntagAssets(req: { tagId: string; assetIds: string[] }): Promise<unknown>;\n}\n\nexport function createConnectTagClient(c: ConnectTagServiceClient): TagClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\tconst res = await c.listTags({ workspaceId });\n\t\t\treturn res.tags.map(mapTag);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapTag(\n\t\t\t\t(\n\t\t\t\t\tawait c.createTag({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t})\n\t\t\t\t).tag,\n\t\t\t);\n\t\t},\n\t\tasync update(id, name) {\n\t\t\treturn mapTag((await c.updateTag({ id, name })).tag);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteTag({ id });\n\t\t},\n\t\tasync tagAssets(tagId, assetIds) {\n\t\t\tawait c.tagAssets({ tagId, assetIds });\n\t\t},\n\t\tasync untagAssets(tagId, assetIds) {\n\t\t\tawait c.untagAssets({ tagId, assetIds });\n\t\t},\n\t};\n}\n\n// ─── Asset Type ───────────────────────────────────────────────────────────────\n\nexport interface ConnectAssetTypeServiceClient {\n\tlistAssetTypes(req: { workspaceId: string }): Promise<{\n\t\tassetTypes: ProtoResponse[];\n\t}>;\n\tgetAssetType(req: { id: string }): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAssetType(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAssetType(req: any): Promise<ProtoResponse>;\n\tdeleteAssetType(req: { id: string }): Promise<unknown>;\n}\n\nexport function createConnectAssetTypeClient(\n\tc: ConnectAssetTypeServiceClient,\n): AssetTypeClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\tconst res = await c.listAssetTypes({ workspaceId });\n\t\t\treturn res.assetTypes.map(mapAssetType);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAssetType((await c.getAssetType({ id })).assetType);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapAssetType(\n\t\t\t\t(\n\t\t\t\t\tawait c.createAssetType({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tslug: params.slug,\n\t\t\t\t\t\tdescription: params.description,\n\t\t\t\t\t\tallowedMimeTypes: params.allowedMimeTypes,\n\t\t\t\t\t\tmetadataSchema: params.metadataSchema,\n\t\t\t\t\t})\n\t\t\t\t).assetType,\n\t\t\t);\n\t\t},\n\t\t/**\n\t\t * Read-modify-write: `UpdateAssetTypeRequest` carries plain proto3\n\t\t * scalars — no `optional`, no field mask — so the server cannot tell\n\t\t * \"not supplied\" from \"set to empty\", and its handler passes every\n\t\t * field through. Sending a patch alone therefore wipes `description`\n\t\t * and `allowedMimeTypes` and re-activates a deactivated type\n\t\t * (knkCS/mediahub#159; the `bool` half is the trap of\n\t\t * knkcms/core#863/#864). So fetch the current record and send the\n\t\t * union.\n\t\t *\n\t\t * Supplied-ness is the presence of the KEY, not truthiness: an\n\t\t * explicit `\"\"`/`[]`/`false` is a deliberate clear and is applied,\n\t\t * while an absent key — or one present but `undefined`, which cannot\n\t\t * travel on the wire anyway — keeps the current value.\n\t\t *\n\t\t * This opens a read-modify-write window; concurrent edits are last\n\t\t * writer wins, as core's now-deleted client also was.\n\t\t */\n\t\tasync update(id, patch) {\n\t\t\tconst cur = mapAssetType((await c.getAssetType({ id })).assetType);\n\t\t\tconst merged = <K extends keyof typeof patch>(\n\t\t\t\tkey: K,\n\t\t\t\tfallback: NonNullable<(typeof patch)[K]>,\n\t\t\t): NonNullable<(typeof patch)[K]> =>\n\t\t\t\tkey in patch && patch[key] !== undefined\n\t\t\t\t\t? (patch[key] as NonNullable<(typeof patch)[K]>)\n\t\t\t\t\t: fallback;\n\t\t\treturn mapAssetType(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAssetType({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: merged(\"name\", cur.name ?? \"\"),\n\t\t\t\t\t\tdescription: merged(\"description\", cur.description ?? \"\"),\n\t\t\t\t\t\tallowedMimeTypes: merged(\n\t\t\t\t\t\t\t\"allowedMimeTypes\",\n\t\t\t\t\t\t\tcur.allowedMimeTypes ?? [],\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmetadataSchema: merged(\"metadataSchema\", cur.metadataSchema ?? \"\"),\n\t\t\t\t\t\tactive: merged(\"active\", cur.active ?? false),\n\t\t\t\t\t})\n\t\t\t\t).assetType,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAssetType({ id });\n\t\t},\n\t};\n}\n\n// ─── User / Directory ─────────────────────────────────────────────────────────\n\nexport interface ConnectUserServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tresolveUsers(req: { userIds: string[] }): Promise<{ users: any[] }>;\n\tlistWorkspaceMembers(req: {\n\t\tworkspaceId: string;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\t}): Promise<{ members: any[] }>;\n}\n\nexport function createConnectDirectoryClient(\n\tc: ConnectUserServiceClient,\n): DirectoryClient {\n\treturn {\n\t\tasync resolveUsers(ids) {\n\t\t\tconst res = await c.resolveUsers({ userIds: ids });\n\t\t\t// The wire type is any-erased at the client boundary (interface\n\t\t\t// above); type the two fields we actually consume.\n\t\t\treturn (res.users ?? []).map(\n\t\t\t\t(u: { id: string; displayName: string }): UserInfo => ({\n\t\t\t\t\tid: u.id,\n\t\t\t\t\tdisplayName: u.displayName,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\tasync listWorkspaceMembers(workspaceId) {\n\t\t\tconst res = await c.listWorkspaceMembers({ workspaceId });\n\t\t\treturn (res.members ?? []).map(\n\t\t\t\t(m: { userId: string; displayName: string }): UserInfo => ({\n\t\t\t\t\tid: m.userId,\n\t\t\t\t\tdisplayName: m.displayName,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t};\n}\n\n// ─── Grants ───────────────────────────────────────────────────────────────────\n\nconst GRANT_RESOURCE_TO_NUM: Record<GrantResourceType, number> = {\n\tasset: 1,\n\tfolder: 2,\n\tcollection: 3,\n};\n/** Wire → domain levels; anything unknown maps to undefined and is dropped\n * rather than invented (same distrust as the service's tuple reads). */\nconst NUM_TO_GRANT_LEVEL: Record<number, GrantLevel | undefined> = {\n\t1: \"viewer\",\n\t2: \"editor\",\n};\nconst GRANT_LEVEL_TO_NUM: Record<GrantLevel, number> = {\n\tviewer: 1,\n\teditor: 2,\n};\n\nexport interface ConnectGrantServiceClient {\n\tgrantAccess(req: {\n\t\tresourceType: number;\n\t\tresourceId: string;\n\t\tuserId: string;\n\t\tlevel: number;\n\t}): Promise<unknown>;\n\trevokeAccess(req: {\n\t\tresourceType: number;\n\t\tresourceId: string;\n\t\tuserId: string;\n\t}): Promise<unknown>;\n\tlistGrants(req: { resourceType: number; resourceId: string }): Promise<{\n\t\townerUserId: string;\n\t\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\t\tgrants: any[];\n\t}>;\n}\n\nexport function createConnectGrantClient(\n\tc: ConnectGrantServiceClient,\n): GrantClient {\n\treturn {\n\t\tasync list(resourceType, resourceId) {\n\t\t\tconst res = await c.listGrants({\n\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\tresourceId,\n\t\t\t});\n\t\t\tconst grants: GrantEntry[] = [];\n\t\t\tfor (const g of res.grants ?? []) {\n\t\t\t\tconst level = NUM_TO_GRANT_LEVEL[g.level as number];\n\t\t\t\tif (level) grants.push({ userId: g.userId as string, level });\n\t\t\t}\n\t\t\treturn { ownerUserId: res.ownerUserId ?? \"\", grants };\n\t\t},\n\t\tasync grant(resourceType, resourceId, userId, level) {\n\t\t\tawait c.grantAccess({\n\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t\tlevel: GRANT_LEVEL_TO_NUM[level],\n\t\t\t});\n\t\t},\n\t\tasync revoke(resourceType, resourceId, userId) {\n\t\t\tawait c.revokeAccess({\n\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t});\n\t\t},\n\t};\n}\n\n/**\n * Authority probe (guardian#55): GrantService gates every call — ListGrants\n * included — on exactly the toggle/grant authority (Owner of the resource or\n * admin of its workspace, mediahub ADR-0001), so a roster read doubles as the\n * check. A denial means \"not an authority\"; other failures reject unchanged.\n */\nexport function createConnectAuthzClient(\n\tc: ConnectGrantServiceClient,\n): AuthzClient {\n\treturn {\n\t\tasync canManage(resourceType, resourceId) {\n\t\t\ttry {\n\t\t\t\tawait c.listGrants({\n\t\t\t\t\tresourceType: GRANT_RESOURCE_TO_NUM[resourceType],\n\t\t\t\t\tresourceId,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t} catch (err) {\n\t\t\t\tif (isPermissionDenied(err)) return false;\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t};\n}\n\n// ─── Dashboard ────────────────────────────────────────────────────────────────\n\nexport interface ConnectDashboardServiceClient {\n\tgetWorkspaceStats(req: { workspaceId: string }): Promise<{\n\t\ttotalAssets: bigint;\n\t\ttotalStorageBytes: bigint;\n\t\tstatusCounts: Array<{\n\t\t\tstatusSlug: string;\n\t\t\tname: string;\n\t\t\tcolor: string;\n\t\t\tbehavior: string;\n\t\t\tcount: bigint;\n\t\t}>;\n\t\trecentUploads: Array<{\n\t\t\tid: string;\n\t\t\tname: string;\n\t\t\tassetTypeName: string;\n\t\t\tstatusName: string;\n\t\t\tstatusColor: string;\n\t\t\tcreatedAt?: { seconds: bigint; nanos: number } | undefined;\n\t\t}>;\n\t}>;\n\tgetDashboardLayout(req: { workspaceId: string }): Promise<{\n\t\tlayoutJson: string;\n\t}>;\n\tsaveDashboardLayout(req: {\n\t\tworkspaceId: string;\n\t\tlayoutJson: string;\n\t}): Promise<unknown>;\n}\n\nexport function createConnectDashboardClient(\n\tc: ConnectDashboardServiceClient,\n): DashboardClient {\n\treturn {\n\t\tasync getWorkspaceStats(workspaceId): Promise<WorkspaceStats> {\n\t\t\tconst res = await c.getWorkspaceStats({ workspaceId });\n\t\t\treturn {\n\t\t\t\ttotalAssets: Number(res.totalAssets),\n\t\t\t\ttotalStorageBytes: Number(res.totalStorageBytes),\n\t\t\t\tstatusCounts: res.statusCounts.map((s) => ({\n\t\t\t\t\tstatusSlug: s.statusSlug,\n\t\t\t\t\tname: s.name,\n\t\t\t\t\tcolor: s.color,\n\t\t\t\t\tbehavior: s.behavior,\n\t\t\t\t\tcount: Number(s.count),\n\t\t\t\t})),\n\t\t\t\trecentUploads: res.recentUploads.map((r) => ({\n\t\t\t\t\tid: r.id,\n\t\t\t\t\tname: r.name,\n\t\t\t\t\tassetTypeName: r.assetTypeName,\n\t\t\t\t\tstatusName: r.statusName,\n\t\t\t\t\tstatusColor: r.statusColor,\n\t\t\t\t\tcreatedAt: mapTs(r.createdAt),\n\t\t\t\t})),\n\t\t\t};\n\t\t},\n\t\tasync getDashboardLayout(workspaceId) {\n\t\t\tconst res = await c.getDashboardLayout({ workspaceId });\n\t\t\treturn res.layoutJson;\n\t\t},\n\t\tasync saveDashboardLayout(workspaceId, layoutJson) {\n\t\t\tawait c.saveDashboardLayout({ workspaceId, layoutJson });\n\t\t},\n\t};\n}\n\n// ─── AI Connection ────────────────────────────────────────────────────────────\n\nexport interface ConnectAIConnectionServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tlistAIConnections(req: any): Promise<{ connections: ProtoResponse[] }>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tgetAIConnection(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAIConnection(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAIConnection(req: any): Promise<ProtoResponse>;\n\tdeleteAIConnection(req: { id: string }): Promise<unknown>;\n}\n\nexport function createConnectAIConnectionClient(\n\tc: ConnectAIConnectionServiceClient,\n): AIConnectionClient {\n\treturn {\n\t\tasync list(workspaceId) {\n\t\t\treturn (\n\t\t\t\tawait c.listAIConnections({\n\t\t\t\t\tworkspaceId,\n\t\t\t\t\tpagination: { page: 1, pageSize: 1000 },\n\t\t\t\t})\n\t\t\t).connections.map(mapAIConnection);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAIConnection((await c.getAIConnection({ id })).connection);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapAIConnection(\n\t\t\t\t(await c.createAIConnection({ ...params })).connection,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapAIConnection(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAIConnection({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tendpoint: patch.endpoint ?? \"\",\n\t\t\t\t\t\tdeployment: patch.deployment ?? \"\",\n\t\t\t\t\t\tapiVersion: patch.apiVersion ?? \"\",\n\t\t\t\t\t\tbaseUrl: patch.baseUrl ?? \"\",\n\t\t\t\t\t\tmodel: patch.model ?? \"\",\n\t\t\t\t\t\tapiKey: patch.apiKey ?? \"\",\n\t\t\t\t\t\tdescription: patch.description ?? \"\",\n\t\t\t\t\t\tactive: patch.active ?? true,\n\t\t\t\t\t})\n\t\t\t\t).connection,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAIConnection({ id });\n\t\t},\n\t};\n}\n\n// ─── AI Process ───────────────────────────────────────────────────────────────\n\nexport interface ConnectAIProcessServiceClient {\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tlistAIProcesses(req: any): Promise<{ processes: ProtoResponse[] }>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tgetAIProcess(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tcreateAIProcess(req: any): Promise<ProtoResponse>;\n\t// biome-ignore lint/suspicious/noExplicitAny: structural Connect shape\n\tupdateAIProcess(req: any): Promise<ProtoResponse>;\n\tdeleteAIProcess(req: { id: string }): Promise<unknown>;\n}\n\nexport function createConnectAIProcessClient(\n\tc: ConnectAIProcessServiceClient,\n): AIProcessClient {\n\treturn {\n\t\tasync list(assetTypeId) {\n\t\t\treturn (await c.listAIProcesses({ assetTypeId })).processes.map(\n\t\t\t\tmapAIProcess,\n\t\t\t);\n\t\t},\n\t\tasync get(id) {\n\t\t\treturn mapAIProcess((await c.getAIProcess({ id })).process);\n\t\t},\n\t\tasync create(params) {\n\t\t\treturn mapAIProcess(\n\t\t\t\t(\n\t\t\t\t\tawait c.createAIProcess({\n\t\t\t\t\t\tworkspaceId: params.workspaceId,\n\t\t\t\t\t\tassetTypeId: params.assetTypeId,\n\t\t\t\t\t\tconnectionId: params.connectionId,\n\t\t\t\t\t\tname: params.name,\n\t\t\t\t\t\tprompt: params.prompt,\n\t\t\t\t\t\toutputs: params.outputs,\n\t\t\t\t\t\tposition: params.position,\n\t\t\t\t\t})\n\t\t\t\t).process,\n\t\t\t);\n\t\t},\n\t\tasync update(id, patch) {\n\t\t\treturn mapAIProcess(\n\t\t\t\t(\n\t\t\t\t\tawait c.updateAIProcess({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tconnectionId: patch.connectionId ?? \"\",\n\t\t\t\t\t\tname: patch.name ?? \"\",\n\t\t\t\t\t\tprompt: patch.prompt ?? \"\",\n\t\t\t\t\t\toutputs: patch.outputs ?? [],\n\t\t\t\t\t\tposition: patch.position ?? 0,\n\t\t\t\t\t\tactive: patch.active ?? true,\n\t\t\t\t\t})\n\t\t\t\t).process,\n\t\t\t);\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait c.deleteAIProcess({ id });\n\t\t},\n\t};\n}\n\n// ─── Bundle ───────────────────────────────────────────────────────────────────\n\nexport function createConnectMediahubClients(gen: {\n\tasset: ConnectAssetServiceClient;\n\tfolder: ConnectFolderServiceClient;\n\tcollection: ConnectCollectionServiceClient;\n\ttag: ConnectTagServiceClient;\n\tassetType: ConnectAssetTypeServiceClient;\n\tuser: ConnectUserServiceClient;\n\tgrant: ConnectGrantServiceClient;\n\tdashboard: ConnectDashboardServiceClient;\n\taiConnection: ConnectAIConnectionServiceClient;\n\taiProcess: ConnectAIProcessServiceClient;\n}): MediahubClients {\n\treturn {\n\t\tassets: createConnectAssetClient(gen.asset),\n\t\tfolders: createConnectFolderClient(gen.folder),\n\t\tcollections: createConnectCollectionClient(gen.collection),\n\t\ttags: createConnectTagClient(gen.tag),\n\t\tassetTypes: createConnectAssetTypeClient(gen.assetType),\n\t\tdirectory: createConnectDirectoryClient(gen.user),\n\t\tgrants: createConnectGrantClient(gen.grant),\n\t\tdashboard: createConnectDashboardClient(gen.dashboard),\n\t\taiConnection: createConnectAIConnectionClient(gen.aiConnection),\n\t\taiProcess: createConnectAIProcessClient(gen.aiProcess),\n\t\tauthz: createConnectAuthzClient(gen.grant),\n\t};\n}\n","import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { MediahubClients } from \"./clients\";\n\n/** Host-app routes for the places this package can only point at, never\n * navigate to itself (it has no router dependency). Rendered as plain\n * anchors; hosts include any basename in the returned href. */\nexport interface MediahubLinks {\n\t/** Route to an asset's detail view. */\n\tassetHref?: (assetId: string) => string;\n\t/** Route to a collection's view. */\n\tcollectionHref?: (collectionId: string) => string;\n}\n\ninterface MediahubContextValue {\n\tclients: MediahubClients;\n\tworkspaceId: string;\n\tlinks: MediahubLinks;\n}\n\nconst MediahubContext = createContext<MediahubContextValue | null>(null);\n\nconst EMPTY_LINKS: MediahubLinks = {};\n\nexport interface MediahubProviderProps {\n\tclients: MediahubClients;\n\t/** Ambient workspace scope — every hook reads it. */\n\tworkspaceId: string;\n\t/** Host routes for cross-surface references (e.g. the leak-guard refusal\n\t * dialog's pair links). Omitted routes render as plain text. */\n\tlinks?: MediahubLinks;\n\tchildren: ReactNode;\n}\n\nexport function MediahubProvider({\n\tclients,\n\tworkspaceId,\n\tlinks,\n\tchildren,\n}: MediahubProviderProps) {\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tclients,\n\t\t\tworkspaceId,\n\t\t\tlinks: links ?? EMPTY_LINKS,\n\t\t}),\n\t\t[clients, workspaceId, links],\n\t);\n\treturn (\n\t\t<MediahubContext.Provider value={value}>\n\t\t\t{children}\n\t\t</MediahubContext.Provider>\n\t);\n}\nMediahubProvider.displayName = \"MediahubProvider\";\n\nfunction useMediahubContext(): MediahubContextValue {\n\tconst ctx = useContext(MediahubContext);\n\tif (!ctx) {\n\t\tthrow new Error(\n\t\t\t\"useMediahubClients/useWorkspaceId must be used within <MediahubProvider>\",\n\t\t);\n\t}\n\treturn ctx;\n}\n\nexport function useMediahubClients(): MediahubClients {\n\treturn useMediahubContext().clients;\n}\n\nexport function useWorkspaceId(): string {\n\treturn useMediahubContext().workspaceId;\n}\n\n/** Host-supplied routes. Empty object when the host didn't pass `links` to\n * `<MediahubProvider>` — consumers degrade to plain text. */\nexport function useMediahubLinks(): MediahubLinks {\n\treturn useMediahubContext().links;\n}\n","import { useStatuses } from \"@knkcs/statushub-ui\";\nimport type { StatusInfo } from \"@knkcs/statushub-ui\";\n\n/**\n * The catalogue an asset's status belongs to: mediahub's `asset` entity type,\n * as registered with statushub at startup (integration standard §1).\n *\n * Every statushub-ui component and hook this package uses is pinned to it, so\n * a host never names it and can never point a mediahub surface at another\n * service's statuses. Exported because a host's settings screen embeds\n * `StatusSettings` pinned to the same catalogue (§10) — `<StatusSettings\n * {...ASSET_STATUS_CATALOGUE} />` — and one constant is how the two cannot\n * come to disagree.\n */\nexport const ASSET_STATUS_CATALOGUE = {\n\tserviceSlug: \"mediahub\",\n\tentityTypeSlug: \"asset\",\n} as const;\n\n/** The asset catalogue's statuses in the viewer's workspace. */\nexport function useAssetStatuses() {\n\treturn useStatuses(ASSET_STATUS_CATALOGUE);\n}\n\n/**\n * The status a slug names.\n *\n * `isLoading` is reported separately on purpose: \"not answered yet\" and\n * \"answered, and this slug is not in the catalogue\" look the same in the data\n * and mean opposite things. Collapsing them makes every list paint its raw\n * slugs for one frame before the names arrive.\n *\n * Once the catalogue has answered, a missing status is an **unknown status** —\n * the slug was deleted, or statushub had never answered at birth (§5) — and\n * callers render the raw slug rather than nothing: the asset still has a\n * status, mediahub just cannot name it.\n */\nexport function useAssetStatus(slug: string): {\n\tstatus: StatusInfo | undefined;\n\tisLoading: boolean;\n} {\n\tconst { data, isLoading } = useAssetStatuses();\n\treturn {\n\t\tstatus: slug ? data?.find((s) => s.slug === slug) : undefined,\n\t\tisLoading,\n\t};\n}\n","/** Direct-to-Azure SAS upload via XHR PUT (x-ms-blob-type: BlockBlob). */\nexport async function uploadFileToSAS(\n\turl: string,\n\tfile: File,\n\tcontentType: string,\n\tonProgress: (progress: number) => void,\n): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst xhr = new XMLHttpRequest();\n\t\txhr.open(\"PUT\", url);\n\t\txhr.setRequestHeader(\"x-ms-blob-type\", \"BlockBlob\");\n\t\txhr.setRequestHeader(\"Content-Type\", contentType);\n\t\txhr.upload.onprogress = (e) => {\n\t\t\tif (e.lengthComputable) {\n\t\t\t\tonProgress(Math.round((e.loaded / e.total) * 100));\n\t\t\t}\n\t\t};\n\t\txhr.onload = () => {\n\t\t\tif (xhr.status >= 200 && xhr.status < 300) {\n\t\t\t\tresolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`Upload failed: ${xhr.status} ${xhr.statusText}`));\n\t\t\t}\n\t\t};\n\t\txhr.onerror = () => reject(new Error(\"Network error during upload\"));\n\t\txhr.send(file);\n\t});\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport { useState } from \"react\";\nimport { uploadFileToSAS } from \"../lib/sas-upload\";\nimport { useMediahubClients } from \"../provider\";\n\nexport interface AddVersionVars {\n\tassetId: string;\n\tfile: File;\n\tcomment?: string;\n}\n\nexport function useAddVersion() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\tconst [progress, setProgress] = useState(0);\n\n\tconst mutation = useMutation({\n\t\tmutationFn: async ({ assetId, file, comment }: AddVersionVars) => {\n\t\t\tsetProgress(0);\n\t\t\tconst contentType = file.type || \"application/octet-stream\";\n\t\t\tconst { uploadUrl, versionId } = await assets.getUploadUrl({\n\t\t\t\tassetId,\n\t\t\t\tfilename: file.name,\n\t\t\t\tcontentType,\n\t\t\t\tfileSize: file.size,\n\t\t\t\tcomment: comment ?? \"\",\n\t\t\t});\n\t\t\tif (!uploadUrl || !versionId) {\n\t\t\t\tthrow new Error(\"getUploadUrl returned an incomplete response\");\n\t\t\t}\n\t\t\tawait uploadFileToSAS(uploadUrl, file, contentType, setProgress);\n\t\t\treturn assets.finalizeUpload(versionId);\n\t\t},\n\t\tonSuccess: (_data, vars) => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"assets\", \"detail\", vars.assetId],\n\t\t\t});\n\t\t},\n\t});\n\n\treturn { ...mutation, progress };\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { AssetFilters, CreateAssetParams } from \"../types\";\n\nexport function useAssets(filters: AssetFilters = {}) {\n\tconst { assets } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assets\", workspaceId, filters],\n\t\tqueryFn: () => assets.list(workspaceId, filters),\n\t});\n}\n\nexport function useAsset(id: string) {\n\tconst { assets } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assets\", \"detail\", id],\n\t\tqueryFn: () => assets.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (params: CreateAssetParams) =>\n\t\t\tassets.create(workspaceId, params),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useUpdateAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tname?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tmetadata?: Record<string, unknown>;\n\t\t\t};\n\t\t}) => assets.update(vars.id, vars.patch),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useDeleteAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => assets.delete(id),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useMoveAsset() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; folderId: string }) =>\n\t\t\tassets.move(vars.id, vars.folderId),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useTransitionAssetStatus() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\t/** The slug the caller last saw — the change is made against it. */\n\t\t\tfromStatusSlug: string;\n\t\t\ttoStatusSlug: string;\n\t\t}) =>\n\t\t\tassets.transitionStatus(vars.id, vars.fromStatusSlug, vars.toStatusSlug),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useEnhanceAssetMetadata() {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => assets.enhanceMetadata(id),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function usePreviewURL(assetId: string, versionId: string) {\n\tconst { assets } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assets\", \"preview-url\", assetId, versionId],\n\t\tqueryFn: () => assets.getDownloadUrl(assetId, versionId),\n\t\tenabled: !!assetId && !!versionId,\n\t\tstaleTime: 15 * 60 * 1000,\n\t});\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useMediahubClients } from \"../provider\";\nimport type { GrantResourceType } from \"../types\";\n\n/**\n * Whether the current user may manage a resource — toggle its Restricted\n * flag, grant or revoke access (Owner of the resource or admin of its\n * workspace, mediahub ADR-0001). Consumers read `data === true`; a pending or\n * failed probe hides authority-only actions (fail closed).\n */\nexport function useCanManage(\n\tresourceType: GrantResourceType,\n\tresourceId: string,\n) {\n\tconst { authz } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"can-manage\", resourceType, resourceId],\n\t\tqueryFn: () => authz.canManage(resourceType, resourceId),\n\t\tenabled: !!resourceId,\n\t\t// Authority rarely changes mid-session; don't re-probe on every menu open.\n\t\tstaleTime: 5 * 60_000,\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useFolders(parentId = \"\", opts?: { enabled?: boolean }) {\n\tconst { folders } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"folders\", workspaceId, parentId],\n\t\tqueryFn: () => folders.list(workspaceId, parentId),\n\t\tenabled: opts?.enabled ?? true,\n\t});\n}\n\nexport function useFolder(id: string) {\n\tconst { folders } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"folder\", id],\n\t\tqueryFn: () => folders.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tslug: string;\n\t\t\tparentId: string;\n\t\t\trestricted?: boolean;\n\t\t}) => folders.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] }),\n\t});\n}\n\nexport function useUpdateFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; name: string }) =>\n\t\t\tfolders.update(vars.id, vars.name),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folder\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => folders.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] }),\n\t});\n}\n\nexport function useMoveFolder() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; parentId: string }) =>\n\t\t\tfolders.move(vars.id, vars.parentId),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folder\"] });\n\t\t},\n\t});\n}\n\nexport function useSetFolderRestricted() {\n\tconst { folders } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; restricted: boolean }) =>\n\t\t\tfolders.setRestricted(vars.id, vars.restricted),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folders\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"folder\"] });\n\t\t\t// The toggle moves the subtree in/out of the open-content counts and\n\t\t\t// unscoped listings (#49) — asset pages must refetch.\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { describeRpcError } from \"../lib/rpc-errors\";\nimport { useMediahubClients } from \"../provider\";\nimport type { GrantLevel, GrantResourceType } from \"../types\";\n\n/**\n * The roster read doubles as the sharing panel's authority gate: the server\n * answers PermissionDenied for everyone but the resource's Owner and\n * workspace admins, and that denial is a final answer — never retried.\n */\nexport function useGrants(\n\tresourceType: GrantResourceType,\n\tresourceId: string,\n\topts?: { enabled?: boolean },\n) {\n\tconst { grants } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"grants\", resourceType, resourceId],\n\t\tqueryFn: () => grants.list(resourceType, resourceId),\n\t\tenabled: opts?.enabled ?? true,\n\t\tretry: (failureCount, error) =>\n\t\t\tdescribeRpcError(error, \"\").kind !== \"permission-denied\" &&\n\t\t\tfailureCount < 3,\n\t});\n}\n\nexport function useGrantAccess() {\n\tconst { grants } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tresourceType: GrantResourceType;\n\t\t\tresourceId: string;\n\t\t\tuserId: string;\n\t\t\tlevel: GrantLevel;\n\t\t}) =>\n\t\t\tgrants.grant(vars.resourceType, vars.resourceId, vars.userId, vars.level),\n\t\t// Settled, not success: the server's upsert is delete-then-write, so a\n\t\t// mid-failure can leave the grantee revoked — the roster must re-assert\n\t\t// server truth after a failure too.\n\t\tonSettled: (_data, _err, vars) =>\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"grants\", vars.resourceType, vars.resourceId],\n\t\t\t}),\n\t});\n}\n\nexport function useRevokeAccess() {\n\tconst { grants } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tresourceType: GrantResourceType;\n\t\t\tresourceId: string;\n\t\t\tuserId: string;\n\t\t}) => grants.revoke(vars.resourceType, vars.resourceId, vars.userId),\n\t\tonSettled: (_data, _err, vars) =>\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"grants\", vars.resourceType, vars.resourceId],\n\t\t\t}),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { CollectionType } from \"../types\";\n\nexport function useCollections() {\n\tconst { collections } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"collections\", workspaceId],\n\t\tqueryFn: () => collections.list(workspaceId),\n\t});\n}\n\nexport function useCollection(id: string) {\n\tconst { collections } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"collection\", id],\n\t\tqueryFn: () => collections.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tslug: string;\n\t\t\tdescription: string;\n\t\t\ttype: CollectionType;\n\t\t\trules: string;\n\t\t\trestricted?: boolean;\n\t\t}) => collections.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] }),\n\t});\n}\n\nexport function useUpdateCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: { name?: string; description?: string; rules?: string };\n\t\t}) => collections.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => collections.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] }),\n\t});\n}\n\nexport function useAddAssetsToCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { collectionId: string; assetIds: string[] }) =>\n\t\t\tcollections.addAssets(vars.collectionId, vars.assetIds),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n\nexport function useSetCollectionRestricted() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; restricted: boolean }) =>\n\t\t\tcollections.setRestricted(vars.id, vars.restricted),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n\nexport function useRemoveAssetsFromCollection() {\n\tconst { collections } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { collectionId: string; assetIds: string[] }) =>\n\t\t\tcollections.removeAssets(vars.collectionId, vars.assetIds),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collection\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t},\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useTags() {\n\tconst { tags } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"tags\", workspaceId],\n\t\tqueryFn: () => tags.list(workspaceId),\n\t});\n}\n\nexport function useCreateTag() {\n\tconst { tags } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { name: string; slug: string }) =>\n\t\t\ttags.create({ workspaceId, ...vars }),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"tags\"] }),\n\t});\n}\n\nexport function useUpdateTag() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { id: string; name: string }) =>\n\t\t\ttags.update(vars.id, vars.name),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"tags\"] }),\n\t});\n}\n\nexport function useDeleteTag() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => tags.delete(id),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"tags\"] }),\n\t});\n}\n\nexport function useTagAssets() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { tagId: string; assetIds: string[] }) =>\n\t\t\ttags.tagAssets(vars.tagId, vars.assetIds),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n\nexport function useUntagAssets() {\n\tconst { tags } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: { tagId: string; assetIds: string[] }) =>\n\t\t\ttags.untagAssets(vars.tagId, vars.assetIds),\n\t\tonSuccess: () => qc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] }),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useAssetTypes() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assetTypes\", workspaceId],\n\t\tqueryFn: () => assetTypes.list(workspaceId),\n\t});\n}\n\nexport function useAssetType(id: string) {\n\tconst { assetTypes } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"assetType\", id],\n\t\tqueryFn: () => assetTypes.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAssetType() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tslug: string;\n\t\t\tdescription: string;\n\t\t\tallowedMimeTypes: string[];\n\t\t\tmetadataSchema: string;\n\t\t}) => assetTypes.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetTypes\"] }),\n\t});\n}\n\nexport function useUpdateAssetType() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tname?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tallowedMimeTypes?: string[];\n\t\t\t\tmetadataSchema?: string;\n\t\t\t\tactive?: boolean;\n\t\t\t};\n\t\t}) => assetTypes.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetTypes\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetType\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteAssetType() {\n\tconst { assetTypes } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => assetTypes.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assetTypes\"] }),\n\t});\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useUsers(ids: string[]) {\n\tconst { directory } = useMediahubClients();\n\tconst sorted = [...ids].filter(Boolean).sort();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"users\", sorted],\n\t\tqueryFn: () => directory.resolveUsers(sorted),\n\t\tenabled: sorted.length > 0,\n\t\tstaleTime: 1000 * 60 * 10,\n\t\tselect: (data): Record<string, string> =>\n\t\t\tObject.fromEntries(data.map((u) => [u.id, u.displayName])),\n\t});\n}\n\n/** The active workspace's member listing — backs the grant picker\n * (guardian#52). Server-sorted by display name; unpaginated by design. */\nexport function useWorkspaceMembers(opts?: { enabled?: boolean }) {\n\tconst { directory } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"members\", workspaceId],\n\t\tqueryFn: () => directory.listWorkspaceMembers(workspaceId),\n\t\tenabled: opts?.enabled ?? true,\n\t\tstaleTime: 1000 * 60 * 5,\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useWorkspaceStats() {\n\tconst { dashboard } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"workspace-stats\", workspaceId],\n\t\tqueryFn: () => dashboard.getWorkspaceStats(workspaceId),\n\t\tstaleTime: 30_000,\n\t});\n}\n\nexport function useGetDashboardLayout() {\n\tconst { dashboard } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"dashboard-layout\", workspaceId],\n\t\tqueryFn: () => dashboard.getDashboardLayout(workspaceId),\n\t});\n}\n\nexport function useSaveDashboardLayout() {\n\tconst { dashboard } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (layoutJson: string) =>\n\t\t\tdashboard.saveDashboardLayout(workspaceId, layoutJson),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"dashboard-layout\", workspaceId],\n\t\t\t}),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\n\nexport function useAIConnections() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-connections\", workspaceId],\n\t\tqueryFn: () => aiConnection.list(workspaceId),\n\t});\n}\n\nexport function useAIConnection(id: string) {\n\tconst { aiConnection } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-connection\", id],\n\t\tqueryFn: () => aiConnection.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAIConnection() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst workspaceId = useWorkspaceId();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tname: string;\n\t\t\tprovider: string;\n\t\t\tendpoint: string;\n\t\t\tdeployment: string;\n\t\t\tapiVersion: string;\n\t\t\tbaseUrl: string;\n\t\t\tmodel: string;\n\t\t\tapiKey: string;\n\t\t\tdescription: string;\n\t\t}) => aiConnection.create({ workspaceId, ...vars }),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connections\"] }),\n\t});\n}\n\nexport function useUpdateAIConnection() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tname?: string;\n\t\t\t\tendpoint?: string;\n\t\t\t\tdeployment?: string;\n\t\t\t\tapiVersion?: string;\n\t\t\t\tbaseUrl?: string;\n\t\t\t\tmodel?: string;\n\t\t\t\tapiKey?: string;\n\t\t\t\tdescription?: string;\n\t\t\t\tactive?: boolean;\n\t\t\t};\n\t\t}) => aiConnection.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connections\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connection\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteAIConnection() {\n\tconst { aiConnection } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => aiConnection.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-connections\"] }),\n\t});\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useMediahubClients } from \"../provider\";\n\nexport function useAIProcesses(assetTypeId: string) {\n\tconst { aiProcess } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-processes\", assetTypeId],\n\t\tqueryFn: () => aiProcess.list(assetTypeId),\n\t\tenabled: !!assetTypeId,\n\t});\n}\n\nexport function useAIProcess(id: string) {\n\tconst { aiProcess } = useMediahubClients();\n\treturn useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-process\", id],\n\t\tqueryFn: () => aiProcess.get(id),\n\t\tenabled: !!id,\n\t});\n}\n\nexport function useCreateAIProcess() {\n\tconst { aiProcess } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tassetTypeId: string;\n\t\t\tconnectionId: string;\n\t\t\tname: string;\n\t\t\tprompt: string;\n\t\t\toutputs: { key: string; target: string; metadataAccessor: string }[];\n\t\t\tposition: number;\n\t\t\tworkspaceId: string;\n\t\t}) => aiProcess.create(vars),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-processes\"] }),\n\t});\n}\n\nexport function useUpdateAIProcess() {\n\tconst { aiProcess } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (vars: {\n\t\t\tid: string;\n\t\t\tpatch: {\n\t\t\t\tconnectionId?: string;\n\t\t\t\tname?: string;\n\t\t\t\tprompt?: string;\n\t\t\t\toutputs?: { key: string; target: string; metadataAccessor: string }[];\n\t\t\t\tposition?: number;\n\t\t\t\tactive?: boolean;\n\t\t\t};\n\t\t}) => aiProcess.update(vars.id, vars.patch),\n\t\tonSuccess: () => {\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-processes\"] });\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-process\"] });\n\t\t},\n\t});\n}\n\nexport function useDeleteAIProcess() {\n\tconst { aiProcess } = useMediahubClients();\n\tconst qc = useQueryClient();\n\treturn useMutation({\n\t\tmutationFn: (id: string) => aiProcess.delete(id),\n\t\tonSuccess: () =>\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"ai-processes\"] }),\n\t});\n}\n","import { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useEffect, useRef } from \"react\";\nimport { useMediahubClients } from \"../provider\";\nimport type { AIProcessRunInfo } from \"../types\";\n\nexport const isActive = (runs: AIProcessRunInfo[] | undefined): boolean =>\n\t(runs ?? []).some((r) => r.status === \"queued\" || r.status === \"running\");\n\nexport function useAIProcessRuns(assetId: string) {\n\tconst { assets } = useMediahubClients();\n\tconst qc = useQueryClient();\n\tconst wasActive = useRef(false);\n\n\tconst query = useQuery({\n\t\tqueryKey: [\"mediahub\", \"ai-process-runs\", assetId],\n\t\tqueryFn: () => assets.listProcessRuns(assetId),\n\t\tenabled: !!assetId,\n\t\trefetchInterval: (q) =>\n\t\t\tisActive(q.state.data as AIProcessRunInfo[] | undefined) ? 2000 : false,\n\t});\n\n\t// Reset wasActive when assetId changes so switching to a new asset doesn't\n\t// fire a spurious completion-invalidate on the previous asset's state.\n\t// (assetId is read inside the effect body — a dep the body never mentions\n\t// is what biome flagged in #74; deleting the dep would kill the reset.)\n\tconst seenAssetId = useRef(assetId);\n\tuseEffect(() => {\n\t\tif (seenAssetId.current !== assetId) {\n\t\t\tseenAssetId.current = assetId;\n\t\t\twasActive.current = false;\n\t\t}\n\t}, [assetId]);\n\n\t// When runs transition from active → all-terminal, refresh the asset so the\n\t// AI-applied description/tags/metadata appear.\n\tuseEffect(() => {\n\t\tconst active = isActive(query.data);\n\t\tif (wasActive.current && !active) {\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"assets\", \"detail\", assetId],\n\t\t\t});\n\t\t}\n\t\twasActive.current = active;\n\t}, [query.data, assetId, qc]);\n\n\treturn query;\n}\n","import { create } from \"zustand\";\n\ninterface SelectionState {\n\tselectedIds: string[];\n\tlastClickedId: string | null;\n}\n\ninterface SelectionActions {\n\ttoggle: (id: string) => void;\n\tselectAll: (ids: string[]) => void;\n\tsetSelection: (ids: string[]) => void;\n\tselectRange: (targetId: string, orderedIds: string[]) => void;\n\tclearSelection: () => void;\n}\n\n// Note: To check if an item is selected in React components, use:\n// useSelectionStore((s) => s.selectedIds.includes(id))\n// Do NOT add an isSelected method to the store — it won't trigger re-renders\n// when used as a Zustand selector.\n\ntype SelectionStore = SelectionState & SelectionActions;\n\nexport const useSelectionStore = create<SelectionStore>((set, get) => ({\n\tselectedIds: [],\n\tlastClickedId: null,\n\n\ttoggle: (id) => {\n\t\tset((state) => {\n\t\t\tconst exists = state.selectedIds.includes(id);\n\t\t\treturn {\n\t\t\t\tselectedIds: exists\n\t\t\t\t\t? state.selectedIds.filter((i) => i !== id)\n\t\t\t\t\t: [...state.selectedIds, id],\n\t\t\t\tlastClickedId: id,\n\t\t\t};\n\t\t});\n\t},\n\n\tselectAll: (ids) => set({ selectedIds: [...ids], lastClickedId: null }),\n\n\tsetSelection: (ids) => set({ selectedIds: ids, lastClickedId: null }),\n\n\tselectRange: (targetId, orderedIds) => {\n\t\tconst { lastClickedId, selectedIds } = get();\n\t\tif (!lastClickedId) {\n\t\t\tset({ selectedIds: [targetId], lastClickedId: targetId });\n\t\t\treturn;\n\t\t}\n\t\tconst startIdx = orderedIds.indexOf(lastClickedId);\n\t\tconst endIdx = orderedIds.indexOf(targetId);\n\t\tif (startIdx === -1 || endIdx === -1) return;\n\t\tconst low = Math.min(startIdx, endIdx);\n\t\tconst high = Math.max(startIdx, endIdx);\n\t\tconst rangeIds = orderedIds.slice(low, high + 1);\n\t\tconst merged = new Set([...selectedIds, ...rangeIds]);\n\t\tset({ selectedIds: [...merged], lastClickedId: targetId });\n\t},\n\n\tclearSelection: () => set({ selectedIds: [], lastClickedId: null }),\n}));\n","import { create } from \"zustand\";\nimport { persist } from \"zustand/middleware\";\n\ninterface PreferencesState {\n\tsidebarCollapsed: boolean;\n\tviewMode: \"list\" | \"grid\";\n}\n\ninterface PreferencesActions {\n\ttoggleSidebar: () => void;\n\tsetViewMode: (mode: \"list\" | \"grid\") => void;\n}\n\ntype PreferencesStore = PreferencesState & PreferencesActions;\n\nexport const usePreferencesStore = create<PreferencesStore>()(\n\tpersist(\n\t\t(set) => ({\n\t\t\tsidebarCollapsed: false,\n\t\t\tviewMode: \"list\",\n\n\t\t\ttoggleSidebar: () =>\n\t\t\t\tset((state) => ({ sidebarCollapsed: !state.sidebarCollapsed })),\n\n\t\t\tsetViewMode: (mode) => set({ viewMode: mode }),\n\t\t}),\n\t\t{\n\t\t\tname: \"mediahub-preferences\",\n\t\t},\n\t),\n);\n","import type { QueryClient } from \"@tanstack/react-query\";\nimport { create } from \"zustand\";\nimport type { AssetClient } from \"../clients\";\nimport { describeRpcError } from \"../lib/rpc-errors\";\nimport { uploadFileToSAS } from \"../lib/sas-upload\";\n\nexport interface UploadFile {\n\tclientId: string;\n\tfile: File;\n\tassetTypeId: string;\n\tstatus:\n\t\t| \"pending\"\n\t\t| \"creating\"\n\t\t| \"uploading\"\n\t\t| \"finalizing\"\n\t\t| \"done\"\n\t\t| \"error\";\n\tprogress: number;\n\terror?: string;\n\tassetId?: string;\n\tversionId?: string;\n}\n\ninterface UploadState {\n\tfiles: UploadFile[];\n\tvisible: boolean;\n\texpanded: boolean;\n\tanalyzeWithAi: boolean;\n\tqueryClient: QueryClient | null;\n\tassetClient: AssetClient | null;\n}\n\ninterface UploadActions {\n\taddFiles: (files: File[]) => void;\n\tsetAssetType: (clientId: string, assetTypeId: string) => void;\n\tsetBatchAssetType: (assetTypeId: string) => void;\n\tsetAnalyzeWithAi: (v: boolean) => void;\n\tstartUpload: (workspaceId: string, folderId?: string) => void;\n\tsetQueryClient: (qc: QueryClient) => void;\n\tsetAssetClient: (client: AssetClient) => void;\n\tclearPending: () => void;\n\tdismiss: () => void;\n\ttoggleExpanded: () => void;\n}\n\ntype UploadStore = UploadState & UploadActions;\n\nfunction updateFile(\n\tfiles: UploadFile[],\n\tclientId: string,\n\tpatch: Partial<UploadFile>,\n): UploadFile[] {\n\treturn files.map((f) => (f.clientId === clientId ? { ...f, ...patch } : f));\n}\n\nexport const useUploadStore = create<UploadStore>((set, get) => ({\n\tfiles: [],\n\tvisible: false,\n\texpanded: true,\n\tanalyzeWithAi: true,\n\tqueryClient: null,\n\tassetClient: null,\n\n\taddFiles: (newFiles) => {\n\t\tconst entries: UploadFile[] = newFiles.map((file) => ({\n\t\t\t// Client-only tracking ID; KSUID convention applies to server-persisted IDs\n\t\t\tclientId: crypto.randomUUID(),\n\t\t\tfile,\n\t\t\tassetTypeId: \"\",\n\t\t\tstatus: \"pending\" as const,\n\t\t\tprogress: 0,\n\t\t}));\n\t\tset((state) => ({ files: [...state.files, ...entries] }));\n\t},\n\n\tsetAssetType: (clientId, assetTypeId) => {\n\t\tset((state) => ({\n\t\t\tfiles: updateFile(state.files, clientId, { assetTypeId }),\n\t\t}));\n\t},\n\n\tsetBatchAssetType: (assetTypeId) => {\n\t\tset((state) => ({\n\t\t\tfiles: state.files.map((f) =>\n\t\t\t\tf.status === \"pending\" ? { ...f, assetTypeId } : f,\n\t\t\t),\n\t\t}));\n\t},\n\n\tsetAnalyzeWithAi: (v) => set({ analyzeWithAi: v }),\n\n\tstartUpload: async (workspaceId, folderId) => {\n\t\tconst client = get().assetClient;\n\t\tif (!client) throw new Error(\"upload-store: assetClient not set\");\n\n\t\tset({ visible: true, expanded: true });\n\n\t\tconst pending = get().files.filter((f) => f.status === \"pending\");\n\n\t\tfor (const entry of pending) {\n\t\t\tconst { clientId, file, assetTypeId } = entry;\n\n\t\t\ttry {\n\t\t\t\t// Step 1: Create asset\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, { status: \"creating\" }),\n\t\t\t\t}));\n\n\t\t\t\tconst asset = await client.create(workspaceId, {\n\t\t\t\t\tname: file.name,\n\t\t\t\t\tassetTypeId,\n\t\t\t\t\tfolderId: folderId ?? \"\",\n\t\t\t\t\tmetadata: {},\n\t\t\t\t\tanalyzeWithAi: get().analyzeWithAi,\n\t\t\t\t});\n\t\t\t\tconst assetId = asset.id;\n\t\t\t\tif (!assetId) throw new Error(\"create returned no asset ID\");\n\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, { assetId }),\n\t\t\t\t}));\n\n\t\t\t\t// Step 2: Get upload URL\n\t\t\t\tconst { uploadUrl, versionId } = await client.getUploadUrl({\n\t\t\t\t\tassetId,\n\t\t\t\t\tfilename: file.name,\n\t\t\t\t\tcontentType: file.type || \"application/octet-stream\",\n\t\t\t\t\tfileSize: file.size,\n\t\t\t\t\tcomment: \"\",\n\t\t\t\t});\n\t\t\t\tif (!uploadUrl || !versionId) {\n\t\t\t\t\tthrow new Error(\"getUploadUrl returned incomplete response\");\n\t\t\t\t}\n\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, {\n\t\t\t\t\t\tversionId,\n\t\t\t\t\t\tstatus: \"uploading\",\n\t\t\t\t\t}),\n\t\t\t\t}));\n\n\t\t\t\t// Step 3: PUT to SAS URL via XHR\n\t\t\t\tawait uploadFileToSAS(\n\t\t\t\t\tuploadUrl,\n\t\t\t\t\tfile,\n\t\t\t\t\tfile.type || \"application/octet-stream\",\n\t\t\t\t\t(progress) => {\n\t\t\t\t\t\tset((state) => ({\n\t\t\t\t\t\t\tfiles: updateFile(state.files, clientId, { progress }),\n\t\t\t\t\t\t}));\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\t// Step 4: Finalize upload\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, { status: \"finalizing\" }),\n\t\t\t\t}));\n\t\t\t\tawait client.finalizeUpload(versionId);\n\n\t\t\t\t// Step 5: Mark done + invalidate cache\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, {\n\t\t\t\t\t\tstatus: \"done\",\n\t\t\t\t\t\tprogress: 100,\n\t\t\t\t\t}),\n\t\t\t\t}));\n\n\t\t\t\tconst qc = get().queryClient;\n\t\t\t\tif (qc) {\n\t\t\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"assets\"] });\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Denials and leak-guard conflicts render mapped copy in the\n\t\t\t\t// upload stack; anything else keeps the raw message as before.\n\t\t\t\tconst described = describeRpcError(err, \"Upload failed\");\n\t\t\t\tconst message =\n\t\t\t\t\tdescribed.kind === \"other\"\n\t\t\t\t\t\t? err instanceof Error\n\t\t\t\t\t\t\t? err.message\n\t\t\t\t\t\t\t: String(err)\n\t\t\t\t\t\t: described.description;\n\t\t\t\tset((state) => ({\n\t\t\t\t\tfiles: updateFile(state.files, clientId, {\n\t\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\t\terror: message,\n\t\t\t\t\t}),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t},\n\n\tsetQueryClient: (qc) => set({ queryClient: qc }),\n\n\tsetAssetClient: (client) => set({ assetClient: client }),\n\n\tclearPending: () =>\n\t\tset((state) => ({\n\t\t\tfiles: state.files.filter((f) => f.status !== \"pending\"),\n\t\t})),\n\n\tdismiss: () =>\n\t\tset({ visible: false, files: [], expanded: true, analyzeWithAi: true }),\n\n\ttoggleExpanded: () => set((state) => ({ expanded: !state.expanded })),\n}));\n","import { Button } from \"@knkcs/anker/atoms\";\nimport { Toolbar } from \"@knkcs/anker/components\";\nimport { Box, Flex } from \"@knkcs/anker/primitives\";\nimport { X } from \"lucide-react\";\n\n/** One narrowing currently applied to the library. */\nexport interface ActiveFilterChip {\n\t/** Stable identity for the row — never rendered. */\n\tid: string;\n\t/**\n\t * What the chip says, already translated and already resolved to a name.\n\t * A chip never carries a raw id: the caller resolves Folder, Collection\n\t * and Tag through the data the panels load, and falls back to the kind's\n\t * own word when a row cannot be resolved.\n\t */\n\tlabel: string;\n\t/** Removes exactly this filter, leaving the others applied. */\n\tonRemove: () => void;\n}\n\nexport interface ActiveFilterChipsProps {\n\tchips: ActiveFilterChip[];\n\tonClearAll: () => void;\n\t/** Names the group for assistive technology, e.g. \"Active filters\". */\n\tgroupLabel: string;\n\t/** Said before each chip's label, so the button announces what it does. */\n\tremoveLabel: string;\n\tclearAllLabel: string;\n}\n\n/**\n * The library's account of what is narrowing it (ADR 0008).\n *\n * Presentation only: it owns no filter state and resolves no names — it\n * renders the chips it is handed and reports the dismissals, so the caller's\n * single filter state stays the one source the panels also write.\n *\n * With nothing applied it renders `null` rather than an empty band, so the\n * row costs no vertical space until there is something to account for.\n *\n * Each chip is anker's `Toolbar.FilterChip`, a native button — reachable by\n * Tab and activated by Enter or Space with no key handling of our own.\n */\nexport const ActiveFilterChips: React.FC<ActiveFilterChipsProps> = ({\n\tchips,\n\tonClearAll,\n\tgroupLabel,\n\tremoveLabel,\n\tclearAllLabel,\n}) => {\n\tif (chips.length === 0) return null;\n\n\t// A fieldset IS the group role, named here by `aria-label` — the chips are\n\t// announced as one labelled set rather than as loose buttons.\n\treturn (\n\t\t<Flex\n\t\t\tas=\"fieldset\"\n\t\t\taria-label={groupLabel}\n\t\t\tdata-testid=\"active-filter-chips\"\n\t\t\talign=\"center\"\n\t\t\tgap=\"2\"\n\t\t\twrap=\"wrap\"\n\t\t\tminW=\"0\"\n\t\t\tpx=\"5\"\n\t\t\tpy=\"2\"\n\t\t\tborderWidth=\"0\"\n\t\t\tborderBottomWidth=\"1px\"\n\t\t\tborderColor=\"border-muted\"\n\t\t>\n\t\t\t{chips.map((chip) => (\n\t\t\t\t<Toolbar.FilterChip key={chip.id} active onClick={chip.onRemove}>\n\t\t\t\t\t{/* The visible text names the filter; the button also has to\n\t\t\t\t\t say what pressing it does, and a bare × says that to\n\t\t\t\t\t nobody using a screen reader. */}\n\t\t\t\t\t{/* The trailing space matters: the accessible name is these\n\t\t\t\t\t two spans concatenated, and without it the button\n\t\t\t\t\t announces as \"Remove filterFolder: Press\". */}\n\t\t\t\t\t<Box as=\"span\" srOnly>{`${removeLabel} `}</Box>\n\t\t\t\t\t<Box as=\"span\">{chip.label}</Box>\n\t\t\t\t\t<X size={12} aria-hidden=\"true\" />\n\t\t\t\t</Toolbar.FilterChip>\n\t\t\t))}\n\t\t\t<Button size=\"xs\" variant=\"ghost\" onClick={onClearAll}>\n\t\t\t\t{clearAllLabel}\n\t\t\t</Button>\n\t\t</Flex>\n\t);\n};\nActiveFilterChips.displayName = \"ActiveFilterChips\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport {\n\ttype FormMarkers,\n\tFormMarkersProvider,\n\tInputField,\n\tSelectField,\n\tTextareaField,\n} from \"@knkcs/anker/forms\";\nimport { Box, Flex, toaster } from \"@knkcs/anker/primitives\";\nimport type { TFunction } from \"i18next\";\nimport { Plus, X } from \"lucide-react\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport {\n\tFormProvider,\n\tuseFieldArray,\n\tuseForm,\n\tuseFormContext,\n\tuseWatch,\n} from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { useAIConnections } from \"../hooks/use-ai-connections\";\nimport {\n\tuseCreateAIProcess,\n\tuseUpdateAIProcess,\n} from \"../hooks/use-ai-processes\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useWorkspaceId } from \"../provider\";\nimport type { AIProcessInfo } from \"../types\";\n\n// --- Types ---\n\ntype OutputTarget = \"description\" | \"tags\" | \"metadata\";\n\nexport interface MetadataAccessorOption {\n\tlabel: string;\n\tvalue: string;\n}\n\n/**\n * anker §10: a form whose fields are all required marks nothing at all —\n * neither asterisks nor \"(optional)\". Module-level so the context value's\n * identity is stable across renders.\n */\nconst ALL_REQUIRED_MARKERS: FormMarkers = {\n\tshowRequiredIndicator: false,\n\toptionalText: \"(optional)\",\n};\n\n// --- Zod schema ---\n\nfunction processFormSchema(t: TFunction) {\n\treturn z\n\t\t.object({\n\t\t\tname: z.string().min(1, t(\"aiProcessDialog.nameRequired\")),\n\t\t\tconnectionId: z.string().min(1, t(\"aiProcessDialog.connectionRequired\")),\n\t\t\tprompt: z.string().min(1, t(\"aiProcessDialog.promptRequired\")),\n\t\t\toutputs: z\n\t\t\t\t.array(\n\t\t\t\t\tz.object({\n\t\t\t\t\t\tkey: z.string().min(1, t(\"aiProcessDialog.outputKeyRequired\")),\n\t\t\t\t\t\ttarget: z.enum([\"description\", \"tags\", \"metadata\"] as const),\n\t\t\t\t\t\tmetadataAccessor: z.string().optional(),\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.min(1, t(\"aiProcessDialog.outputRequired\")),\n\t\t})\n\t\t.superRefine((v, ctx) => {\n\t\t\tv.outputs.forEach((o, i) => {\n\t\t\t\tif (o.target === \"metadata\" && !o.metadataAccessor) {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\tpath: [\"outputs\", i, \"metadataAccessor\"],\n\t\t\t\t\t\tmessage: t(\"aiProcessDialog.metadataFieldRequired\"),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n}\n\ninterface ProcessForm {\n\tname: string;\n\tconnectionId: string;\n\tprompt: string;\n\toutputs: { key: string; target: OutputTarget; metadataAccessor?: string }[];\n}\n\nconst EMPTY_OUTPUT = {\n\tkey: \"\",\n\ttarget: \"description\" as OutputTarget,\n\tmetadataAccessor: \"\",\n};\n\n/**\n * The process's outputs as form rows. Correct against the wire, not the\n * declared type: Connect omits an empty repeated field, so a process with no\n * outputs arrives without the key — hence the guarded read, and one blank row\n * so the form is never output-less (the schema requires at least one).\n */\nfunction buildProcessOutputs(proc: AIProcessInfo): ProcessForm[\"outputs\"] {\n\tconst outputs = proc.outputs ?? [];\n\tif (outputs.length === 0) return [{ ...EMPTY_OUTPUT }];\n\treturn outputs.map((o) => ({\n\t\tkey: o.key ?? \"\",\n\t\ttarget: (o.target as OutputTarget) || \"description\",\n\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t}));\n}\n\n// --- Output row ---\n\ninterface OutputRowProps {\n\tindex: number;\n\tonRemove: () => void;\n\tmetadataAccessors: MetadataAccessorOption[];\n\tcanRemove: boolean;\n}\n\nfunction OutputRow({\n\tindex,\n\tonRemove,\n\tmetadataAccessors,\n\tcanRemove,\n}: OutputRowProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { control } = useFormContext<ProcessForm>();\n\tconst target = useWatch({ control, name: `outputs.${index}.target` });\n\n\treturn (\n\t\t<Flex gap={2} align=\"flex-end\">\n\t\t\t<Box flex={1}>\n\t\t\t\t<InputField\n\t\t\t\t\tname={`outputs.${index}.key`}\n\t\t\t\t\tlabel={t(\"aiProcessDialog.outputKeyLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t\tplaceholder={t(\"aiProcessDialog.outputKeyPlaceholder\")}\n\t\t\t\t/>\n\t\t\t</Box>\n\t\t\t<Box flex={1}>\n\t\t\t\t<SelectField\n\t\t\t\t\tname={`outputs.${index}.target`}\n\t\t\t\t\tlabel={t(\"aiProcessDialog.targetLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t>\n\t\t\t\t\t<option value=\"description\">\n\t\t\t\t\t\t{t(\"aiProcessDialog.targetDescription\")}\n\t\t\t\t\t</option>\n\t\t\t\t\t<option value=\"tags\">{t(\"aiProcessDialog.targetTags\")}</option>\n\t\t\t\t\t<option value=\"metadata\">\n\t\t\t\t\t\t{t(\"aiProcessDialog.targetMetadata\")}\n\t\t\t\t\t</option>\n\t\t\t\t</SelectField>\n\t\t\t</Box>\n\t\t\t{target === \"metadata\" && (\n\t\t\t\t<Box flex={1}>\n\t\t\t\t\t<SelectField\n\t\t\t\t\t\tname={`outputs.${index}.metadataAccessor`}\n\t\t\t\t\t\tlabel={t(\"aiProcessDialog.metadataFieldLabel\")}\n\t\t\t\t\t\trequired\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"\">\n\t\t\t\t\t\t\t{t(\"aiProcessDialog.metadataFieldPlaceholder\")}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t\t{metadataAccessors.map((a) => (\n\t\t\t\t\t\t\t<option key={a.value} value={a.value}>\n\t\t\t\t\t\t\t\t{a.label}\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</SelectField>\n\t\t\t\t</Box>\n\t\t\t)}\n\t\t\t<Box pb={1}>\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\tdisabled={!canRemove}\n\t\t\t\t\taria-label={t(\"aiProcessDialog.removeOutputAria\")}\n\t\t\t\t>\n\t\t\t\t\t<X size={16} />\n\t\t\t\t</Button>\n\t\t\t</Box>\n\t\t</Flex>\n\t);\n}\nOutputRow.displayName = \"OutputRow\";\n\n// --- Process form fields (shared between create and edit) ---\n\nfunction ProcessFormFields({\n\tmetadataAccessors,\n}: {\n\tmetadataAccessors: MetadataAccessorOption[];\n}): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { data: connections = [] } = useAIConnections();\n\tconst { control } = useFormContext<ProcessForm>();\n\tconst { fields, append, remove } = useFieldArray({\n\t\tcontrol,\n\t\tname: \"outputs\",\n\t});\n\n\treturn (\n\t\t<FormMarkersProvider value={ALL_REQUIRED_MARKERS}>\n\t\t\t{/* Every field here is required, so under the §10 optional-text\n\t\t\t convention this form intentionally shows NO markers at all —\n\t\t\t nothing is the exception. Don't \"fix\" by removing the provider\n\t\t\t or re-enabling asterisks. */}\n\t\t\t<Flex direction=\"column\" gap={4}>\n\t\t\t\t<InputField\n\t\t\t\t\tname=\"name\"\n\t\t\t\t\tlabel={t(\"aiProcessDialog.nameLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t\tplaceholder={t(\"aiProcessDialog.namePlaceholder\")}\n\t\t\t\t/>\n\n\t\t\t\t<SelectField\n\t\t\t\t\tname=\"connectionId\"\n\t\t\t\t\tlabel={t(\"aiProcessDialog.connectionLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">{t(\"aiProcessDialog.connectionPlaceholder\")}</option>\n\t\t\t\t\t{connections.map((c) => (\n\t\t\t\t\t\t<option key={c.id} value={c.id}>\n\t\t\t\t\t\t\t{c.name}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</SelectField>\n\n\t\t\t\t<TextareaField\n\t\t\t\t\tname=\"prompt\"\n\t\t\t\t\tlabel={t(\"aiProcessDialog.promptLabel\")}\n\t\t\t\t\trequired\n\t\t\t\t\tplaceholder={t(\"aiProcessDialog.promptPlaceholder\")}\n\t\t\t\t/>\n\n\t\t\t\t<Box>\n\t\t\t\t\t<Box fontSize=\"sm\" fontWeight=\"medium\" mb={2}>\n\t\t\t\t\t\t{t(\"aiProcessDialog.outputsLabel\")}\n\t\t\t\t\t</Box>\n\t\t\t\t\t<Flex direction=\"column\" gap={3}>\n\t\t\t\t\t\t{fields.map((field, index) => (\n\t\t\t\t\t\t\t<OutputRow\n\t\t\t\t\t\t\t\tkey={field.id}\n\t\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t\t\tonRemove={() => remove(index)}\n\t\t\t\t\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\t\t\t\t\tcanRemove={fields.length > 1}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Flex>\n\t\t\t\t\t<Box mt={3}>\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={() => append({ ...EMPTY_OUTPUT })}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Plus size={16} /> {t(\"aiProcessDialog.addOutput\")}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</Box>\n\t\t\t\t</Box>\n\t\t\t</Flex>\n\t\t</FormMarkersProvider>\n\t);\n}\nProcessFormFields.displayName = \"ProcessFormFields\";\n\n// --- Create form ---\n\nfunction CreateFormContent({\n\topen,\n\tassetTypeId,\n\tmetadataAccessors,\n\tonClose,\n}: {\n\topen: boolean;\n\tassetTypeId: string;\n\tmetadataAccessors: MetadataAccessorOption[];\n\tonClose: () => void;\n}): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst createMutation = useCreateAIProcess();\n\tconst resolver = useMemo(() => zodResolver(processFormSchema(t)), [t]);\n\tconst methods = useForm<ProcessForm>({\n\t\tresolver,\n\t\tdefaultValues: {\n\t\t\tname: \"\",\n\t\t\tconnectionId: \"\",\n\t\t\tprompt: \"\",\n\t\t\toutputs: [{ ...EMPTY_OUTPUT }],\n\t\t},\n\t});\n\n\t// Fallback: zag presence skips onExitComplete when a reopen interrupts the\n\t// exit animation — reset again on open so a fast close-then-reopen can't\n\t// reopen with a stale, unsaved name/connection/prompt/outputs.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tmethods.reset();\n\t}, [open, methods]);\n\n\tasync function onSubmit(data: ProcessForm) {\n\t\ttry {\n\t\t\tawait createMutation.mutateAsync({\n\t\t\t\tassetTypeId,\n\t\t\t\tconnectionId: data.connectionId,\n\t\t\t\tname: data.name,\n\t\t\t\tprompt: data.prompt,\n\t\t\t\toutputs: data.outputs.map((o) => ({\n\t\t\t\t\tkey: o.key,\n\t\t\t\t\ttarget: o.target,\n\t\t\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t\t\t})),\n\t\t\t\tposition: 0,\n\t\t\t\tworkspaceId,\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"aiProcessDialog.createdToast\") });\n\t\t\tonClose();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcessDialog.createFailedToast\"));\n\t\t}\n\t}\n\n\t// Do NOT unmount when `open` flips false: unmounting the open dialog\n\t// machine under StrictMode orphans its scroll-lock/aria-hidden cleanup and\n\t// wedges the whole app (mediahub#66). Keep the Modal mounted; lazyMount/\n\t// unmountOnExit keep the fresh-content-per-open semantics, and form state\n\t// is scrubbed in onExitComplete (not immediately on close) so the content\n\t// doesn't visibly blank mid-exit-animation.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={() => methods.reset()}\n\t\t\tonClose={onClose}\n\t\t\theader={t(\"aiProcessDialog.createHeader\")}\n\t\t\tonSave={methods.handleSubmit(onSubmit)}\n\t\t\tsaveLabel={t(\"aiProcessDialog.createLabel\")}\n\t\t\tloading={createMutation.isPending}\n\t\t>\n\t\t\t<FormProvider {...methods}>\n\t\t\t\t<ProcessFormFields metadataAccessors={metadataAccessors} />\n\t\t\t</FormProvider>\n\t\t</Modal>\n\t);\n}\nCreateFormContent.displayName = \"CreateFormContent\";\n\n// --- Edit form ---\n\nfunction EditFormContent({\n\topen,\n\teditProcess,\n\tmetadataAccessors,\n\tonClose,\n}: {\n\topen: boolean;\n\teditProcess: AIProcessInfo | undefined;\n\tmetadataAccessors: MetadataAccessorOption[];\n\tonClose: () => void;\n}): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\t// Latch the last non-undefined entity: the wrapper keeps this component\n\t// mounted permanently (both create and edit machines stay mounted so\n\t// neither ever tears down while open, mediahub#73). The edit call site\n\t// couples `open` to `!!editProcess`, so closing clears `editProcess` in the\n\t// very same commit that flips `open` false. Render from the latch so the\n\t// Modal has stable data to finish its exit animation with, instead of\n\t// crashing/blanking mid-exit.\n\tconst latchedProcessRef = useRef<AIProcessInfo | undefined>(editProcess);\n\tif (editProcess) {\n\t\tlatchedProcessRef.current = editProcess;\n\t}\n\tconst process = editProcess ?? latchedProcessRef.current;\n\n\tconst updateMutation = useUpdateAIProcess();\n\tconst resolver = useMemo(() => zodResolver(processFormSchema(t)), [t]);\n\tconst methods = useForm<ProcessForm>({\n\t\tresolver,\n\t\tdefaultValues: {\n\t\t\tname: process?.name ?? \"\",\n\t\t\tconnectionId: process?.connectionId ?? \"\",\n\t\t\tprompt: process?.prompt ?? \"\",\n\t\t\toutputs: process ? buildProcessOutputs(process) : [{ ...EMPTY_OUTPUT }],\n\t\t},\n\t});\n\n\t// Reset when the opening entity changes. Guarded on `editProcess` (not the\n\t// latched `process`) so clearing it on the way to close doesn't clobber the\n\t// values still on screen during the exit animation. Also gated on `open`:\n\t// this doubles as the fallback for zag presence skipping onExitComplete on\n\t// an interrupted exit — reopening onto the SAME editProcess wouldn't\n\t// otherwise re-run this effect (its identity is unchanged), so `open`\n\t// flipping true is what re-seeds a fast close-then-reopen instead of\n\t// showing stale edits.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tif (editProcess) {\n\t\t\tmethods.reset({\n\t\t\t\tname: editProcess.name ?? \"\",\n\t\t\t\tconnectionId: editProcess.connectionId ?? \"\",\n\t\t\t\tprompt: editProcess.prompt ?? \"\",\n\t\t\t\toutputs: buildProcessOutputs(editProcess),\n\t\t\t});\n\t\t}\n\t}, [open, editProcess, methods]);\n\n\tasync function onSubmit(data: ProcessForm) {\n\t\tif (!process) return;\n\t\ttry {\n\t\t\tawait updateMutation.mutateAsync({\n\t\t\t\tid: process.id,\n\t\t\t\tpatch: {\n\t\t\t\t\tconnectionId: data.connectionId,\n\t\t\t\t\tname: data.name,\n\t\t\t\t\tprompt: data.prompt,\n\t\t\t\t\toutputs: data.outputs.map((o) => ({\n\t\t\t\t\t\tkey: o.key,\n\t\t\t\t\t\ttarget: o.target,\n\t\t\t\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t\t\t\t})),\n\t\t\t\t\tposition: process.position,\n\t\t\t\t\tactive: process.active,\n\t\t\t\t},\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"aiProcessDialog.updatedToast\") });\n\t\t\tonClose();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcessDialog.updateFailedToast\"));\n\t\t}\n\t}\n\n\t// Kept mounted for the same reason as the create form above (mediahub#66,\n\t// #73) — including across the wrapper's create/edit branch.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={() => methods.reset()}\n\t\t\tonClose={onClose}\n\t\t\theader={t(\"aiProcessDialog.editHeader\")}\n\t\t\tonSave={methods.handleSubmit(onSubmit)}\n\t\t\tsaveLabel={t(\"aiProcessDialog.saveLabel\")}\n\t\t\tloading={updateMutation.isPending}\n\t\t>\n\t\t\t<FormProvider {...methods}>\n\t\t\t\t<ProcessFormFields metadataAccessors={metadataAccessors} />\n\t\t\t</FormProvider>\n\t\t</Modal>\n\t);\n}\nEditFormContent.displayName = \"EditFormContent\";\n\n// --- Main component ---\n\nexport interface AIProcessFormDialogProps {\n\topen: boolean;\n\tonClose: () => void;\n\tassetTypeId: string;\n\tmetadataAccessors: MetadataAccessorOption[];\n\t/** If provided, the dialog opens in edit mode for this process. */\n\teditProcess?: AIProcessInfo;\n}\n\n/**\n * Create or edit one AI process for an asset type. Packaged from the\n * standalone's host-local dialog (knkCS/mediahub#157) — same behaviour, same\n * mount semantics, strings under the package's i18n namespace.\n */\nexport function AIProcessFormDialog({\n\topen,\n\tonClose,\n\tassetTypeId,\n\tmetadataAccessors,\n\teditProcess,\n}: AIProcessFormDialogProps): React.JSX.Element {\n\t// Both inner Modals stay mounted permanently: a `if (!open) return null`\n\t// plus this component's own create/edit mode branch were each a mount gate\n\t// in their own right, and switching branches while a machine was open\n\t// reproduced the StrictMode teardown bug of mediahub#66 (#73).\n\t// `lazyMount`/`unmountOnExit` inside each inner component mean a machine\n\t// that's never been opened renders nothing.\n\treturn (\n\t\t<>\n\t\t\t<CreateFormContent\n\t\t\t\topen={open && !editProcess}\n\t\t\t\tassetTypeId={assetTypeId}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\tonClose={onClose}\n\t\t\t/>\n\t\t\t<EditFormContent\n\t\t\t\topen={open && !!editProcess}\n\t\t\t\teditProcess={editProcess}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\tonClose={onClose}\n\t\t\t/>\n\t\t</>\n\t);\n}\nAIProcessFormDialog.displayName = \"AIProcessFormDialog\";\n","/**\n * Reading the custom fields an asset type's metadata schema declares — the\n * \"Fields\" column of the asset-type index, and the metadata targets an AI\n * process can write into.\n *\n * The schema is a fieldkit `Field[]` serialized to a string (the stored default\n * is `\"{}\"`, which is not an array at all). Structural layout markers carry no\n * value — `section` tab markers and, since fieldkit 0.8.0, `card` group markers\n * — so they must never be counted as fields (mediahub#75); system fields live\n * on the asset's own columns and are likewise excluded.\n *\n * These are display guards, never validators: malformed or non-array JSON\n * degrades to \"no fields\" rather than throwing under a table cell.\n */\n\ninterface SchemaEntry {\n\tfield_type?: string;\n\tsystem?: boolean;\n\tconfig?: { name?: string; api_accessor?: string };\n}\n\nconst STRUCTURAL_MARKERS = new Set([\"section\", \"card\"]);\n\nfunction customFieldEntries(metadataSchema: string | undefined): SchemaEntry[] {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(metadataSchema || \"[]\");\n\t\tif (!Array.isArray(parsed)) return [];\n\t\treturn (parsed as SchemaEntry[]).filter(\n\t\t\t(entry) =>\n\t\t\t\t!entry.system && !STRUCTURAL_MARKERS.has(entry.field_type ?? \"\"),\n\t\t);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/** Custom value-field count for the asset-type index's \"Fields\" column. */\nexport function countCustomFields(metadataSchema: string | undefined): number {\n\treturn customFieldEntries(metadataSchema).length;\n}\n\n/** AI-process metadata-target options: custom value fields only. */\nexport function metadataAccessorOptions(\n\tmetadataSchema: string | undefined,\n): { label: string; value: string }[] {\n\treturn customFieldEntries(metadataSchema).map((entry) => ({\n\t\tlabel: entry.config?.name ?? \"\",\n\t\tvalue: entry.config?.api_accessor ?? \"\",\n\t}));\n}\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBox,\n\tFlex,\n\tSpinner,\n\tStack,\n\tSwitch,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { ChevronDown, ChevronUp, Pencil, Trash2 } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useAIConnections } from \"../hooks/use-ai-connections\";\nimport {\n\tuseAIProcesses,\n\tuseDeleteAIProcess,\n\tuseUpdateAIProcess,\n} from \"../hooks/use-ai-processes\";\nimport { metadataAccessorOptions } from \"../lib/metadata-field-count\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { AIProcessInfo } from \"../types\";\nimport { AIProcessFormDialog } from \"./ai-process-form-dialog\";\n\nexport interface AIProcessesTabProps {\n\t/** The asset type whose processes are listed. */\n\ttypeId: string;\n\t/** The asset type's metadata schema, source of the metadata output targets. */\n\tmetadataSchema: string | undefined;\n}\n\n/**\n * Every field the server needs on an update. `UpdateAIProcess` replaces the\n * record rather than merging, so a toggle or a reorder has to send the whole\n * process back — sending only the changed field blanks the rest.\n *\n * Read against the wire, not the declared type: Connect omits empty strings\n * and empty repeated fields from its JSON (knkcms/core#863), so every value is\n * defaulted here at the one place it is read.\n */\nfunction fullPatch(p: AIProcessInfo) {\n\treturn {\n\t\tconnectionId: p.connectionId ?? \"\",\n\t\tname: p.name ?? \"\",\n\t\tprompt: p.prompt ?? \"\",\n\t\toutputs: (p.outputs ?? []).map((o) => ({\n\t\t\tkey: o.key ?? \"\",\n\t\t\ttarget: o.target ?? \"\",\n\t\t\tmetadataAccessor: o.metadataAccessor ?? \"\",\n\t\t})),\n\t\tposition: p.position ?? 0,\n\t\tactive: p.active ?? false,\n\t};\n}\n\n/**\n * The AI-Processes tab of the packaged asset-type detail screen: the processes\n * an asset type runs when an asset is analyzed, in order — listed, reordered,\n * enabled/disabled, deleted, created and edited (knkCS/mediahub#157).\n *\n * No routing of its own: where a host's AI-connection settings live is the\n * host's URL, so the \"no connections\" hint is text, not a link.\n */\nexport function AIProcessesTab({\n\ttypeId,\n\tmetadataSchema,\n}: AIProcessesTabProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { confirm } = useConfirmModal();\n\n\tconst processesQuery = useAIProcesses(typeId);\n\tconst processes = processesQuery.data ?? [];\n\tconst connections = useAIConnections().data ?? [];\n\tconst deleteProcess = useDeleteAIProcess();\n\tconst updateProcess = useUpdateAIProcess();\n\n\tconst [createOpen, setCreateOpen] = useState(false);\n\tconst [editProcess, setEditProcess] = useState<AIProcessInfo | undefined>(\n\t\tundefined,\n\t);\n\n\tconst metadataAccessors = useMemo(\n\t\t() => metadataAccessorOptions(metadataSchema),\n\t\t[metadataSchema],\n\t);\n\n\tconst connectionMap = useMemo(\n\t\t() => new Map(connections.map((c) => [c.id, c.name])),\n\t\t[connections],\n\t);\n\n\t// The server's `position` is authoritative but need not be dense; the list\n\t// is shown — and reordered — in ascending position order.\n\tconst sorted = useMemo(\n\t\t() => [...processes].sort((a, b) => (a.position ?? 0) - (b.position ?? 0)),\n\t\t[processes],\n\t);\n\n\tasync function handleDelete(proc: AIProcessInfo) {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"aiProcesses.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"aiProcesses.deleteConfirmMessage\", {\n\t\t\t\tprocessName: proc.name ?? \"\",\n\t\t\t}),\n\t\t\tconfirmLabel: t(\"aiProcesses.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteProcess.mutateAsync(proc.id);\n\t\t\ttoaster.success({ title: t(\"aiProcesses.deletedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcesses.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleToggle(proc: AIProcessInfo, active: boolean) {\n\t\ttry {\n\t\t\tawait updateProcess.mutateAsync({\n\t\t\t\tid: proc.id,\n\t\t\t\tpatch: { ...fullPatch(proc), active },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcesses.updateFailedToast\"));\n\t\t}\n\t}\n\n\t/** Swap a process with its neighbour `delta` places away. */\n\tasync function handleMove(index: number, delta: -1 | 1) {\n\t\tconst proc = sorted[index];\n\t\tconst neighbour = sorted[index + delta];\n\t\tif (!proc || !neighbour) return;\n\t\ttry {\n\t\t\tawait updateProcess.mutateAsync({\n\t\t\t\tid: proc.id,\n\t\t\t\tpatch: { ...fullPatch(proc), position: index + delta },\n\t\t\t});\n\t\t\tawait updateProcess.mutateAsync({\n\t\t\t\tid: neighbour.id,\n\t\t\t\tpatch: { ...fullPatch(neighbour), position: index },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"aiProcesses.reorderFailedToast\"));\n\t\t}\n\t}\n\n\tconst noConnections = connections.length === 0;\n\n\treturn (\n\t\t<>\n\t\t\t<Stack gap={4}>\n\t\t\t\t<Flex justify=\"space-between\" align=\"center\">\n\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t{t(\"aiProcesses.intro\")}\n\t\t\t\t\t</Text>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={() => setCreateOpen(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"aiProcesses.newProcess\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</Flex>\n\n\t\t\t\t{noConnections && (\n\t\t\t\t\t<Box\n\t\t\t\t\t\tp={4}\n\t\t\t\t\t\tborderRadius=\"md\"\n\t\t\t\t\t\tborderWidth=\"1px\"\n\t\t\t\t\t\tborderColor=\"border.default\"\n\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"aiProcesses.noConnectionsHint\")}\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\n\t\t\t\t{processesQuery.isLoading ? (\n\t\t\t\t\t<Box display=\"flex\" justifyContent=\"center\" p={4}>\n\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t</Box>\n\t\t\t\t) : sorted.length === 0 ? (\n\t\t\t\t\tnoConnections ? null : (\n\t\t\t\t\t\t<EmptyState header={t(\"aiProcesses.empty\")} />\n\t\t\t\t\t)\n\t\t\t\t) : (\n\t\t\t\t\t<Stack gap={2}>\n\t\t\t\t\t\t{sorted.map((proc, i) => (\n\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\tkey={proc.id}\n\t\t\t\t\t\t\t\tp={4}\n\t\t\t\t\t\t\t\tborderRadius=\"md\"\n\t\t\t\t\t\t\t\tborderWidth=\"1px\"\n\t\t\t\t\t\t\t\tborderColor=\"border.default\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Flex justify=\"space-between\" align=\"center\">\n\t\t\t\t\t\t\t\t\t<Stack gap={1}>\n\t\t\t\t\t\t\t\t\t\t<Text fontWeight=\"medium\">{proc.name}</Text>\n\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t\t\t\t{connectionMap.get(proc.connectionId) ??\n\t\t\t\t\t\t\t\t\t\t\t\tproc.connectionId}{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t·{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t{t(\"aiProcesses.outputCount\", {\n\t\t\t\t\t\t\t\t\t\t\t\tcount: (proc.outputs ?? []).length,\n\t\t\t\t\t\t\t\t\t\t\t})}{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t·{\" \"}\n\t\t\t\t\t\t\t\t\t\t\t{proc.active\n\t\t\t\t\t\t\t\t\t\t\t\t? t(\"aiProcesses.active\")\n\t\t\t\t\t\t\t\t\t\t\t\t: t(\"aiProcesses.inactive\")}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t\t\t<Flex gap={2} align=\"center\">\n\t\t\t\t\t\t\t\t\t\t<Switch\n\t\t\t\t\t\t\t\t\t\t\tchecked={proc.active ?? false}\n\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\tproc.active\n\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"aiProcesses.disableAria\")\n\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"aiProcesses.enableAria\")\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tonCheckedChange={(details) => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleToggle(proc, details.checked);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={i === 0}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleMove(i, -1);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.moveUpAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ChevronUp size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={i === sorted.length - 1}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleMove(i, 1);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.moveDownAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ChevronDown size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => setEditProcess(proc)}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.editAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Pencil size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid handleDelete(proc);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"aiProcesses.deleteAria\")}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Trash2 size={16} />\n\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Stack>\n\t\t\t\t)}\n\t\t\t</Stack>\n\n\t\t\t{/* Two permanently-mounted dialog instances, `open` toggled — never\n\t\t\t mounted/unmounted while open (mediahub#66/#73). */}\n\t\t\t<AIProcessFormDialog\n\t\t\t\topen={createOpen}\n\t\t\t\tonClose={() => setCreateOpen(false)}\n\t\t\t\tassetTypeId={typeId}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t/>\n\t\t\t<AIProcessFormDialog\n\t\t\t\topen={!!editProcess}\n\t\t\t\tonClose={() => setEditProcess(undefined)}\n\t\t\t\tassetTypeId={typeId}\n\t\t\t\tmetadataAccessors={metadataAccessors}\n\t\t\t\teditProcess={editProcess}\n\t\t\t/>\n\t\t</>\n\t);\n}\nAIProcessesTab.displayName = \"AIProcessesTab\";\n","import { Text } from \"@knkcs/anker/primitives\";\nimport { StatusBadge } from \"@knkcs/statushub-ui\";\nimport { useAssetStatus } from \"../statushub\";\n\nexport interface AssetStatusBadgeProps {\n\t/** The asset's stored status slug. Empty renders nothing. */\n\tslug: string;\n}\n\n/**\n * An asset's status, named and coloured from statushub's catalogue.\n *\n * This is the one place mediahub turns a stored slug into something readable\n * (statushub's integration standard §10: the consumer renders statuses itself,\n * with statushub-ui's components — no host slot). A slug the catalogue does\n * not carry — an **unknown status**, deleted or never answered for (§5) —\n * prints as itself, because the asset has a status either way and saying\n * nothing would read as having none.\n */\nexport function AssetStatusBadge({ slug }: AssetStatusBadgeProps) {\n\tconst { status, isLoading } = useAssetStatus(slug);\n\tif (!slug) return null;\n\t// Nothing rather than the slug while the catalogue is in flight: the slug\n\t// is what an unknown status looks like, and showing it here would flash a\n\t// raw `in-review` across every row of every list on each mount.\n\tif (isLoading) return null;\n\tif (!status) {\n\t\treturn (\n\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t{slug}\n\t\t\t</Text>\n\t\t);\n\t}\n\treturn <StatusBadge status={status} />;\n}\nAssetStatusBadge.displayName = \"AssetStatusBadge\";\n","import { SelectableCard } from \"@knkcs/anker/components\";\nimport { Grid, Skeleton, Text } from \"@knkcs/anker/primitives\";\nimport { FileText, Film, Image, Music } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { usePreviewURL } from \"../hooks/use-preview-url\";\nimport { useSelectionStore } from \"../stores/selection-store\";\nimport type { AssetInfo } from \"../types\";\nimport { AssetStatusBadge } from \"./asset-status-badge\";\n\nfunction getMimeCategory(asset: AssetInfo): string {\n\tconst version = asset.versions[asset.versions.length - 1];\n\tif (!version) return \"unknown\";\n\tconst mime = version.mimeType;\n\tif (mime.startsWith(\"image/\")) return \"image\";\n\tif (mime.startsWith(\"video/\")) return \"video\";\n\tif (mime.startsWith(\"audio/\")) return \"audio\";\n\tif (mime === \"application/pdf\") return \"pdf\";\n\treturn \"unknown\";\n}\n\nfunction TypeIcon({ category }: { category: string }) {\n\tswitch (category) {\n\t\tcase \"image\":\n\t\t\treturn <Image size={32} opacity={0.3} />;\n\t\tcase \"video\":\n\t\t\treturn <Film size={32} opacity={0.3} />;\n\t\tcase \"audio\":\n\t\t\treturn <Music size={32} opacity={0.3} />;\n\t\tdefault:\n\t\t\treturn <FileText size={32} opacity={0.3} />;\n\t}\n}\nTypeIcon.displayName = \"TypeIcon\";\n\n/** Maps the internal MIME category slug to its display label. */\nfunction useCategoryLabel(category: string): string {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tswitch (category) {\n\t\tcase \"image\":\n\t\t\treturn t(\"assetGrid.categoryImage\");\n\t\tcase \"video\":\n\t\t\treturn t(\"assetGrid.categoryVideo\");\n\t\tcase \"audio\":\n\t\t\treturn t(\"assetGrid.categoryAudio\");\n\t\tcase \"pdf\":\n\t\t\treturn t(\"assetGrid.categoryPdf\");\n\t\tdefault:\n\t\t\treturn t(\"assetGrid.categoryUnknown\");\n\t}\n}\n\ninterface AssetCardProps {\n\tasset: AssetInfo;\n\tonOpen: (asset: AssetInfo) => void;\n}\n\nconst AssetCard: React.FC<AssetCardProps> = ({ asset, onOpen }) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst isSelected = useSelectionStore((s) => s.selectedIds.includes(asset.id));\n\tconst anySelected = useSelectionStore((s) => s.selectedIds.length > 0);\n\tconst toggle = useSelectionStore((s) => s.toggle);\n\tconst category = getMimeCategory(asset);\n\tconst categoryLabel = useCategoryLabel(category);\n\tconst latestVersion = asset.versions[asset.versions.length - 1];\n\tconst previewQuery = usePreviewURL(\n\t\tcategory === \"image\" && latestVersion ? asset.id : \"\",\n\t\tlatestVersion?.id ?? \"\",\n\t);\n\tconst previewUrl = previewQuery.data;\n\tconst [imgError, setImgError] = useState(false);\n\n\treturn (\n\t\t<SelectableCard\n\t\t\tselected={isSelected}\n\t\t\tselectionVisible={anySelected}\n\t\t\tonSelect={() => toggle(asset.id)}\n\t\t\tonClick={() => onOpen(asset)}\n\t\t>\n\t\t\t<SelectableCard.Thumbnail height=\"160px\">\n\t\t\t\t{category === \"image\" && previewUrl && !imgError ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\talt={asset.name || t(\"assetGrid.previewAlt\")}\n\t\t\t\t\t\tonError={() => setImgError(true)}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\twidth: \"100%\",\n\t\t\t\t\t\t\theight: \"100%\",\n\t\t\t\t\t\t\tobjectFit: \"cover\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : category === \"image\" && previewQuery.isLoading ? (\n\t\t\t\t\t<Skeleton w=\"full\" h=\"full\" />\n\t\t\t\t) : (\n\t\t\t\t\t<TypeIcon category={category} />\n\t\t\t\t)}\n\t\t\t</SelectableCard.Thumbnail>\n\t\t\t<SelectableCard.Body>\n\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" truncate>\n\t\t\t\t\t{asset.name}\n\t\t\t\t</Text>\n\t\t\t</SelectableCard.Body>\n\t\t\t<SelectableCard.Footer>\n\t\t\t\t<AssetStatusBadge slug={asset.statusSlug} />\n\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t{categoryLabel}\n\t\t\t\t</Text>\n\t\t\t</SelectableCard.Footer>\n\t\t</SelectableCard>\n\t);\n};\nAssetCard.displayName = \"AssetCard\";\n\nexport interface AssetGridProps {\n\tassets: AssetInfo[];\n\tonOpen: (asset: AssetInfo) => void;\n}\n\nexport const AssetGrid: React.FC<AssetGridProps> = ({ assets, onOpen }) => {\n\treturn (\n\t\t<Grid templateColumns=\"repeat(auto-fill, minmax(200px, 1fr))\" gap={4}>\n\t\t\t{assets.map((asset) => (\n\t\t\t\t<AssetCard key={asset.id} asset={asset} onOpen={onOpen} />\n\t\t\t))}\n\t\t</Grid>\n\t);\n};\nAssetGrid.displayName = \"AssetGrid\";\n","import { Button } from \"@knkcs/anker/atoms\";\nimport { Box, Flex, Skeleton, Text } from \"@knkcs/anker/primitives\";\nimport { Download, FileText, Film, Image, Music } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { usePreviewURL } from \"../hooks/use-preview-url\";\n\ninterface AssetPreviewProps {\n\tassetId: string;\n\tversionId: string;\n\tmimeType: string;\n\tfileName: string;\n}\n\nfunction TypeIcon({ mimeType }: { mimeType: string }) {\n\tif (mimeType.startsWith(\"image/\")) return <Image size={48} opacity={0.3} />;\n\tif (mimeType.startsWith(\"video/\")) return <Film size={48} opacity={0.3} />;\n\tif (mimeType.startsWith(\"audio/\")) return <Music size={48} opacity={0.3} />;\n\treturn <FileText size={48} opacity={0.3} />;\n}\nTypeIcon.displayName = \"TypeIcon\";\n\nexport const AssetPreview: React.FC<AssetPreviewProps> = ({\n\tassetId,\n\tversionId,\n\tmimeType,\n\tfileName,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst previewQuery = usePreviewURL(assetId, versionId);\n\tconst url = previewQuery.data;\n\tconst [error, setError] = useState(false);\n\n\tif (previewQuery.isLoading) {\n\t\treturn <Skeleton w=\"full\" h=\"full\" minH=\"200px\" />;\n\t}\n\n\tif (!url || error) {\n\t\treturn (\n\t\t\t<Flex\n\t\t\t\tdirection=\"column\"\n\t\t\t\talign=\"center\"\n\t\t\t\tjustify=\"center\"\n\t\t\t\tgap={3}\n\t\t\t\tp={6}\n\t\t\t\th=\"full\"\n\t\t\t\tminH=\"200px\"\n\t\t\t>\n\t\t\t\t<TypeIcon mimeType={mimeType} />\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t{t(\"assetPreview.previewNotAvailable\")}\n\t\t\t\t</Text>\n\t\t\t\t{url && (\n\t\t\t\t\t<Button asChild size=\"sm\" variant=\"outline\">\n\t\t\t\t\t\t<a href={url} download={fileName}>\n\t\t\t\t\t\t\t<Download size={14} />\n\t\t\t\t\t\t\t{t(\"assetPreview.download\")}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\t// Image\n\tif (mimeType.startsWith(\"image/\")) {\n\t\treturn (\n\t\t\t<Box\n\t\t\t\th=\"full\"\n\t\t\t\tminH=\"200px\"\n\t\t\t\tdisplay=\"flex\"\n\t\t\t\talignItems=\"center\"\n\t\t\t\tjustifyContent=\"center\"\n\t\t\t\tp={2}\n\t\t\t>\n\t\t\t\t<img\n\t\t\t\t\tsrc={url}\n\t\t\t\t\talt={fileName}\n\t\t\t\t\tonError={() => setError(true)}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tmaxWidth: \"100%\",\n\t\t\t\t\t\tmaxHeight: \"100%\",\n\t\t\t\t\t\tobjectFit: \"contain\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Video\n\tif (mimeType.startsWith(\"video/\")) {\n\t\treturn (\n\t\t\t<Box h=\"full\" minH=\"200px\" p={2}>\n\t\t\t\t<video\n\t\t\t\t\tsrc={url}\n\t\t\t\t\tcontrols\n\t\t\t\t\tonError={() => setError(true)}\n\t\t\t\t\tstyle={{ width: \"100%\", maxHeight: \"100%\" }}\n\t\t\t\t>\n\t\t\t\t\t<track kind=\"captions\" />\n\t\t\t\t</video>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Audio\n\tif (mimeType.startsWith(\"audio/\")) {\n\t\treturn (\n\t\t\t<Flex\n\t\t\t\tdirection=\"column\"\n\t\t\t\talign=\"center\"\n\t\t\t\tjustify=\"center\"\n\t\t\t\tgap={4}\n\t\t\t\tp={6}\n\t\t\t\th=\"full\"\n\t\t\t\tminH=\"200px\"\n\t\t\t>\n\t\t\t\t<Music size={48} opacity={0.3} />\n\t\t\t\t<audio\n\t\t\t\t\tsrc={url}\n\t\t\t\t\tcontrols\n\t\t\t\t\tonError={() => setError(true)}\n\t\t\t\t\tstyle={{ width: \"100%\" }}\n\t\t\t\t>\n\t\t\t\t\t<track kind=\"captions\" />\n\t\t\t\t</audio>\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\t// PDF\n\tif (mimeType === \"application/pdf\") {\n\t\treturn (\n\t\t\t<Box h=\"full\" minH=\"400px\">\n\t\t\t\t<iframe\n\t\t\t\t\tsrc={url}\n\t\t\t\t\ttitle={fileName}\n\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\theight=\"100%\"\n\t\t\t\t\tstyle={{ border: \"none\" }}\n\t\t\t\t/>\n\t\t\t</Box>\n\t\t);\n\t}\n\n\t// Fallback\n\treturn (\n\t\t<Flex\n\t\t\tdirection=\"column\"\n\t\t\talign=\"center\"\n\t\t\tjustify=\"center\"\n\t\t\tgap={3}\n\t\t\tp={6}\n\t\t\th=\"full\"\n\t\t\tminH=\"200px\"\n\t\t>\n\t\t\t<TypeIcon mimeType={mimeType} />\n\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t{t(\"assetPreview.previewNotAvailable\")}\n\t\t\t</Text>\n\t\t\t<Button asChild size=\"sm\" variant=\"outline\">\n\t\t\t\t<a href={url} download={fileName}>\n\t\t\t\t\t<Download size={14} />\n\t\t\t\t\t{t(\"assetPreview.download\")}\n\t\t\t\t</a>\n\t\t\t</Button>\n\t\t</Flex>\n\t);\n};\nAssetPreview.displayName = \"AssetPreview\";\n","import { StatusTransitionControl } from \"@knkcs/statushub-ui\";\nimport { useTranslation } from \"react-i18next\";\nimport { useTransitionAssetStatus } from \"../hooks/use-assets\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { ASSET_STATUS_CATALOGUE } from \"../statushub\";\n\nexport interface AssetStatusControlProps {\n\tassetId: string;\n\t/** The asset's stored status slug — what the viewer is looking at. */\n\tstatusSlug: string;\n}\n\n/**\n * An asset's status, and the moves statushub allows away from it.\n *\n * statushub-ui offers the moves; mediahub's own `TransitionAssetStatus` makes\n * them (integration standard §3) — the browser never writes to statushub. The\n * slug being shown travels with the change, so a screen drawn before somebody\n * else moved this asset on is refused as a conflict instead of overwriting\n * them.\n *\n * Guarded moves are shown (`canRevert`) and statushub decides them: its answer\n * is per-caller, and mediahub keeps no who-may-revert rule of its own. The\n * control swallows what `onTransition` throws — error handling is the\n * consumer's — so the refusal is toasted here.\n */\nexport function AssetStatusControl({\n\tassetId,\n\tstatusSlug,\n}: AssetStatusControlProps) {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst transition = useTransitionAssetStatus();\n\treturn (\n\t\t<StatusTransitionControl\n\t\t\t{...ASSET_STATUS_CATALOGUE}\n\t\t\tcurrentStatusSlug={statusSlug}\n\t\t\tquickAdvance={false}\n\t\t\tcanRevert\n\t\t\tonTransition={async (to) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait transition.mutateAsync({\n\t\t\t\t\t\tid: assetId,\n\t\t\t\t\t\tfromStatusSlug: statusSlug,\n\t\t\t\t\t\ttoStatusSlug: to.slug,\n\t\t\t\t\t});\n\t\t\t\t} catch (err) {\n\t\t\t\t\tshowRpcErrorToast(err, t(\"assetStatusControl.transitionFailedToast\"));\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t);\n}\nAssetStatusControl.displayName = \"AssetStatusControl\";\n","import { BulkActionBar as AnkerBulkActionBar } from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { Box, Flex, Text, toaster } from \"@knkcs/anker/primitives\";\nimport { FolderOpen, Tag, Trash2 } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useDeleteAsset } from \"../hooks/use-assets\";\nimport {\n\tuseAddAssetsToCollection,\n\tuseCollections,\n} from \"../hooks/use-collections\";\nimport { useTagAssets, useTags } from \"../hooks/use-tags\";\nimport { describeRpcError, showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useSelectionStore } from \"../stores/selection-store\";\n\nexport const BulkActionBar: React.FC = () => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst selectedIds = useSelectionStore((s) => s.selectedIds);\n\tconst clearSelection = useSelectionStore((s) => s.clearSelection);\n\tconst count = selectedIds.length;\n\n\tconst deleteAsset = useDeleteAsset();\n\tconst { confirm } = useConfirmModal();\n\tconst tagAssets = useTagAssets();\n\tconst addToCollection = useAddAssetsToCollection();\n\tconst tagsQuery = useTags();\n\tconst collectionsQuery = useCollections();\n\tconst tags = tagsQuery.data ?? [];\n\tconst collections = collectionsQuery.data ?? [];\n\n\tasync function handleBulkDelete() {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"bulkActionBar.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"bulkActionBar.deleteConfirmMessage\", { count }),\n\t\t\tconfirmLabel: t(\"bulkActionBar.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\tconst ids = useSelectionStore.getState().selectedIds;\n\t\tconst n = ids.length;\n\t\tif (n === 0) return;\n\t\tlet failed = 0;\n\t\tlet firstErr: unknown;\n\t\tfor (const id of ids) {\n\t\t\ttry {\n\t\t\t\tawait deleteAsset.mutateAsync(id);\n\t\t\t} catch (err) {\n\t\t\t\tfailed++;\n\t\t\t\tfirstErr ??= err;\n\t\t\t}\n\t\t}\n\t\tif (failed === 0) {\n\t\t\ttoaster.success({\n\t\t\t\ttitle: t(\"bulkActionBar.deleteSuccessToast\", { count: n }),\n\t\t\t});\n\t\t\tuseSelectionStore.getState().clearSelection();\n\t\t} else {\n\t\t\t// Mapped families explain themselves; other errors keep the bare\n\t\t\t// count so raw server strings never enter the toast.\n\t\t\tconst fallback = t(\"bulkActionBar.deletePartialFailureToast\", {\n\t\t\t\tdeleted: n - failed,\n\t\t\t\tfailed,\n\t\t\t});\n\t\t\tconst described = describeRpcError(firstErr, fallback);\n\t\t\ttoaster.error(\n\t\t\t\tdescribed.kind === \"other\"\n\t\t\t\t\t? { title: fallback }\n\t\t\t\t\t: { title: described.title, description: described.description },\n\t\t\t);\n\t\t}\n\t}\n\n\tasync function handleBulkTag(tagId: string) {\n\t\ttry {\n\t\t\tawait tagAssets.mutateAsync({ tagId, assetIds: [...selectedIds] });\n\t\t\ttoaster.success({ title: t(\"bulkActionBar.tagsUpdatedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"bulkActionBar.errorToast\"));\n\t\t}\n\t}\n\n\tasync function handleBulkAddToCollection(collectionId: string) {\n\t\ttry {\n\t\t\tawait addToCollection.mutateAsync({\n\t\t\t\tcollectionId,\n\t\t\t\tassetIds: [...selectedIds],\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"bulkActionBar.addedToCollectionToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"bulkActionBar.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<AnkerBulkActionBar\n\t\t\tselectedCount={count}\n\t\t\tonClear={clearSelection}\n\t\t\tcountLabel={(n: number) => t(\"bulkActionBar.countSelected\", { count: n })}\n\t\t>\n\t\t\t<AnkerBulkActionBar.PopoverAction\n\t\t\t\tlabel={t(\"bulkActionBar.addTagsAction\")}\n\t\t\t\ticon={<Tag size={14} />}\n\t\t\t>\n\t\t\t\t<Flex direction=\"column\" gap={1} p={2}>\n\t\t\t\t\t{tags.map((tag) => (\n\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\tkey={tag.id}\n\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\tpx={2}\n\t\t\t\t\t\t\tpy={1}\n\t\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\t\ttextAlign=\"left\"\n\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t_hover={{ bg: \"bg.muted\" }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button type=\"button\" onClick={() => handleBulkTag(tag.id)}>\n\t\t\t\t\t\t\t\t{tag.name}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t))}\n\t\t\t\t\t{tags.length === 0 && (\n\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" p={2}>\n\t\t\t\t\t\t\t{t(\"bulkActionBar.noTagsAvailable\")}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Flex>\n\t\t\t</AnkerBulkActionBar.PopoverAction>\n\n\t\t\t<AnkerBulkActionBar.PopoverAction\n\t\t\t\tlabel={t(\"bulkActionBar.addToCollectionAction\")}\n\t\t\t\ticon={<FolderOpen size={14} />}\n\t\t\t>\n\t\t\t\t<Flex direction=\"column\" gap={1} p={2}>\n\t\t\t\t\t{collections.map((col) => (\n\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\tkey={col.id}\n\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\tpx={2}\n\t\t\t\t\t\t\tpy={1}\n\t\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t\t\t\ttextAlign=\"left\"\n\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t_hover={{ bg: \"bg.muted\" }}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={() => handleBulkAddToCollection(col.id)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{col.name}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t))}\n\t\t\t\t\t{collections.length === 0 && (\n\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" p={2}>\n\t\t\t\t\t\t\t{t(\"bulkActionBar.noCollectionsAvailable\")}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Flex>\n\t\t\t</AnkerBulkActionBar.PopoverAction>\n\n\t\t\t<AnkerBulkActionBar.Action\n\t\t\t\tlabel={t(\"bulkActionBar.deleteAction\")}\n\t\t\t\ticon={<Trash2 size={14} />}\n\t\t\t\tcolorPalette=\"red\"\n\t\t\t\tonClick={handleBulkDelete}\n\t\t\t/>\n\t\t</AnkerBulkActionBar>\n\t);\n};\nBulkActionBar.displayName = \"BulkActionBar\";\n","import { ChipPicker } from \"@knkcs/anker/components\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n\tuseAddAssetsToCollection,\n\tuseCollections,\n\tuseRemoveAssetsFromCollection,\n} from \"../hooks/use-collections\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { CollectionInfo } from \"../types\";\n\ninterface CollectionChipFieldProps {\n\tassetId: string;\n\tassignedCollectionIds: string[];\n}\n\nexport const CollectionChipField: React.FC<CollectionChipFieldProps> = ({\n\tassetId,\n\tassignedCollectionIds,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst collectionsQuery = useCollections();\n\tconst allCollections: CollectionInfo[] = collectionsQuery.data ?? [];\n\tconst addToCollection = useAddAssetsToCollection();\n\tconst removeFromCollection = useRemoveAssetsFromCollection();\n\tconst qc = useQueryClient();\n\n\tconst assigned = allCollections.filter((c) =>\n\t\tassignedCollectionIds.includes(c.id),\n\t);\n\tconst unassigned = allCollections.filter(\n\t\t(c) => !assignedCollectionIds.includes(c.id),\n\t);\n\n\tasync function handleAdd(collection: CollectionInfo) {\n\t\ttry {\n\t\t\tawait addToCollection.mutateAsync({\n\t\t\t\tcollectionId: collection.id,\n\t\t\t\tassetIds: [assetId],\n\t\t\t});\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionChipField.errorToast\"));\n\t\t}\n\t}\n\n\tasync function handleRemove(collection: CollectionInfo) {\n\t\ttry {\n\t\t\tawait removeFromCollection.mutateAsync({\n\t\t\t\tcollectionId: collection.id,\n\t\t\t\tassetIds: [assetId],\n\t\t\t});\n\t\t\tqc.invalidateQueries({ queryKey: [\"mediahub\", \"collections\"] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionChipField.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<ChipPicker<CollectionInfo>\n\t\t\tassigned={assigned}\n\t\t\tavailable={unassigned}\n\t\t\tgetItemId={(c) => c.id}\n\t\t\tgetItemLabel={(c) => c.name}\n\t\t\tonAdd={handleAdd}\n\t\t\tonRemove={handleRemove}\n\t\t\taddLabel={t(\"collectionChipField.addLabel\")}\n\t\t\temptyLabel={t(\"collectionChipField.emptyLabel\")}\n\t\t\tsearchable\n\t\t\tloading={collectionsQuery.isLoading}\n\t\t/>\n\t);\n};\nCollectionChipField.displayName = \"CollectionChipField\";\n","import { InlineCreatableList } from \"@knkcs/anker/components\";\nimport { toaster } from \"@knkcs/anker/primitives\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCollections, useCreateCollection } from \"../hooks/use-collections\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { CollectionInfo } from \"../types\";\n\ninterface CollectionPanelProps {\n\tactiveCollectionId: string;\n\tonSelectCollection: (collectionId: string) => void;\n}\n\nexport const CollectionPanel: React.FC<CollectionPanelProps> = ({\n\tactiveCollectionId,\n\tonSelectCollection,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst collectionsQuery = useCollections();\n\tconst collections: CollectionInfo[] = collectionsQuery.data ?? [];\n\tconst createCollection = useCreateCollection();\n\n\tasync function handleCreate(name: string) {\n\t\ttry {\n\t\t\tawait createCollection.mutateAsync({\n\t\t\t\tname,\n\t\t\t\tslug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tdescription: \"\",\n\t\t\t\ttype: \"static\",\n\t\t\t\trules: \"\",\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"collectionPanel.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionPanel.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<InlineCreatableList<CollectionInfo>\n\t\t\titems={collections}\n\t\t\tactiveIds={activeCollectionId ? [activeCollectionId] : []}\n\t\t\tonToggle={onSelectCollection}\n\t\t\tonCreate={handleCreate}\n\t\t\tgetItemId={(c) => c.id}\n\t\t\tgetItemLabel={(c) => c.name}\n\t\t\tvariant=\"list\"\n\t\t\tcreatePlaceholder={t(\"collectionPanel.createPlaceholder\")}\n\t\t\tcreateLabel={t(\"collectionPanel.createLabel\")}\n\t\t\temptyText={t(\"collectionPanel.emptyText\")}\n\t\t/>\n\t);\n};\nCollectionPanel.displayName = \"CollectionPanel\";\n","import {\n\tBreadcrumbCurrentLink,\n\tBreadcrumbItem,\n\tBreadcrumbLink,\n\tBreadcrumbList,\n\tBreadcrumbRoot,\n\tBreadcrumbSeparator,\n} from \"@knkcs/anker/primitives\";\nimport { useMemo } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useFolder } from \"../hooks/use-folders\";\n\ninterface FolderBreadcrumbsProps {\n\tfolderId: string;\n\tonNavigate: (folderId: string) => void;\n}\n\n/**\n * Build ancestor chain by walking parent_id up to 3 levels.\n * Uses useFolder for each level. Since tree browsing caches folders,\n * most calls will resolve from TanStack Query cache.\n *\n * Limitation: Shows at most 3 breadcrumb segments (grandparent/parent/current).\n * For deeper nesting, the earliest ancestors are truncated. This is acceptable\n * for v1 — folder structures deeper than 3 levels are rare. If needed later,\n * add a GetFolderAncestors RPC to the backend for a single-call solution.\n */\nfunction useAncestorChain(folderId: string) {\n\tconst folderQuery = useFolder(folderId);\n\tconst folder = folderQuery.data;\n\n\tconst parentQuery = useFolder(folder?.parentId ?? \"\");\n\tconst parent = parentQuery.data;\n\n\tconst grandparentQuery = useFolder(parent?.parentId ?? \"\");\n\tconst grandparent = grandparentQuery.data;\n\n\treturn useMemo(() => {\n\t\tconst chain: Array<{ id: string; name: string }> = [];\n\t\tif (grandparent) chain.push({ id: grandparent.id, name: grandparent.name });\n\t\tif (parent) chain.push({ id: parent.id, name: parent.name });\n\t\tif (folder) chain.push({ id: folder.id, name: folder.name });\n\t\treturn chain;\n\t}, [folder, parent, grandparent]);\n}\n\nexport const FolderBreadcrumbs: React.FC<FolderBreadcrumbsProps> = ({\n\tfolderId,\n\tonNavigate,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst ancestors = useAncestorChain(folderId);\n\n\tif (!folderId || ancestors.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<BreadcrumbRoot>\n\t\t\t<BreadcrumbList>\n\t\t\t\t<BreadcrumbItem>\n\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\thref=\"#\"\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tonNavigate(\"\");\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"folderBreadcrumbs.rootLabel\")}\n\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t</BreadcrumbItem>\n\t\t\t\t{ancestors.slice(0, -1).map((item) => (\n\t\t\t\t\t<BreadcrumbItem key={item.id}>\n\t\t\t\t\t\t<BreadcrumbLink\n\t\t\t\t\t\t\thref=\"#\"\n\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tonNavigate(item.id);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{item.name}\n\t\t\t\t\t\t</BreadcrumbLink>\n\t\t\t\t\t\t<BreadcrumbSeparator />\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t))}\n\t\t\t\t{ancestors.length > 0 && (\n\t\t\t\t\t<BreadcrumbItem>\n\t\t\t\t\t\t<BreadcrumbCurrentLink>\n\t\t\t\t\t\t\t{ancestors[ancestors.length - 1].name}\n\t\t\t\t\t\t</BreadcrumbCurrentLink>\n\t\t\t\t\t</BreadcrumbItem>\n\t\t\t\t)}\n\t\t\t</BreadcrumbList>\n\t\t</BreadcrumbRoot>\n\t);\n};\nFolderBreadcrumbs.displayName = \"FolderBreadcrumbs\";\n","import { Button } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport { Box, Flex, HStack, Link, Text } from \"@knkcs/anker/primitives\";\nimport type { ReactNode } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport type { RpcErrorDescription } from \"../lib/rpc-errors\";\nimport { useMediahubLinks } from \"../provider\";\n\nexport interface LeakGuardRefusalDialogProps {\n\t/** The mapped leak-guard failure to explain. Callers keep the last refusal\n\t * mounted while the dialog animates closed (same #66 semantics as the\n\t * other dialogs) — `null` renders nothing. */\n\trefusal: RpcErrorDescription | null;\n\topen: boolean;\n\tonClose: () => void;\n}\n\nfunction MaybeLink({\n\thref,\n\tchildren,\n}: {\n\thref?: string;\n\tchildren: ReactNode;\n}): React.JSX.Element {\n\tif (!href) {\n\t\treturn (\n\t\t\t<Text as=\"span\" fontWeight=\"medium\">\n\t\t\t\t{children}\n\t\t\t</Text>\n\t\t);\n\t}\n\treturn (\n\t\t<Link\n\t\t\thref={href}\n\t\t\tfontWeight=\"medium\"\n\t\t\tcolor=\"colorPalette.fg\"\n\t\t\tcolorPalette=\"primary\"\n\t\t\ttextDecoration=\"underline\"\n\t\t>\n\t\t\t{children}\n\t\t</Link>\n\t);\n}\n\n/**\n * Explains a refused Restricted toggle (guardian#55): the refusing rule in\n * human copy plus every offending asset→collection pair, each side linked to\n * its surface when the host registered routes — never a raw error.\n */\nexport const LeakGuardRefusalDialog: React.FC<LeakGuardRefusalDialogProps> = ({\n\trefusal,\n\topen,\n\tonClose,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst links = useMediahubLinks();\n\tif (!refusal) return null;\n\n\tconst exposures = refusal.exposures ?? [];\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonClose={onClose}\n\t\t\tsize=\"md\"\n\t\t\theader={refusal.title}\n\t\t\tfooter={\n\t\t\t\t<HStack gap=\"2\" justify=\"flex-end\">\n\t\t\t\t\t<Button variant=\"outline\" onClick={onClose}>\n\t\t\t\t\t\t{t(\"leakGuardRefusalDialog.closeLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap={3}>\n\t\t\t\t<Text fontSize=\"sm\">{refusal.ruleText ?? refusal.description}</Text>\n\t\t\t\t{exposures.length > 0 && (\n\t\t\t\t\t<Box as=\"ul\" pl={4} display=\"flex\" flexDirection=\"column\" gap={1}>\n\t\t\t\t\t\t{exposures.map((e) => (\n\t\t\t\t\t\t\t<Box as=\"li\" key={`${e.assetId}:${e.collectionId}`} fontSize=\"sm\">\n\t\t\t\t\t\t\t\t<MaybeLink href={links.assetHref?.(e.assetId)}>\n\t\t\t\t\t\t\t\t\t{e.assetName}\n\t\t\t\t\t\t\t\t</MaybeLink>\n\t\t\t\t\t\t\t\t<Text as=\"span\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t\t{\" — in collection \"}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t<MaybeLink href={links.collectionHref?.(e.collectionId)}>\n\t\t\t\t\t\t\t\t\t{e.collectionName}\n\t\t\t\t\t\t\t\t</MaybeLink>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Box>\n\t\t\t\t)}\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t{t(\"leakGuardRefusalDialog.resolveHint\")}\n\t\t\t\t</Text>\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n};\nLeakGuardRefusalDialog.displayName = \"LeakGuardRefusalDialog\";\n","import type { AssetClient, FolderClient } from \"../clients\";\nimport type { AssetInfo, CollectionInfo, FolderInfo } from \"../types\";\n\n/**\n * Client-side mirror of the service move guards (asset-move and folder-move\n * into a Restricted chain, guardian ADR 0003): the move picker uses these to\n * disable leak-guarded destinations up front with the reason inline. The\n * server re-checks every move — a stale answer here degrades to the server's\n * refusal, never to a leak.\n */\n\n/** Bounds every chain walk, mirroring the service's maxFolderDepth: a chain\n * deeper than this is treated as invalid rather than walked forever. */\nconst maxFolderDepth = 100;\n\nexport function openCollectionIds(collections: CollectionInfo[]): string[] {\n\treturn collections.filter((c) => !c.restricted).map((c) => c.id);\n}\n\n/** Whether an open collection exposes the asset — the condition under which\n * moving it into a Restricted chain is refused. Collections the caller\n * cannot see are Restricted by definition and never count. */\nexport function assetExposedByOpenCollection(\n\tasset: AssetInfo,\n\tcollections: CollectionInfo[],\n): boolean {\n\tconst open = new Set(openCollectionIds(collections));\n\treturn asset.collectionIds.some((id) => open.has(id));\n}\n\n/** Whether the folder or any ancestor is Restricted. Fails closed at the\n * depth bound: an unwalkable chain is treated as confined. */\nexport async function folderChainRestricted(\n\tfolders: FolderClient,\n\tfolder: FolderInfo,\n): Promise<boolean> {\n\tlet f = folder;\n\tfor (let i = 0; i < maxFolderDepth; i++) {\n\t\tif (f.restricted) return true;\n\t\tif (!f.parentId) return false;\n\t\tf = await folders.get(f.parentId);\n\t}\n\treturn true;\n}\n\n/** Whether any asset filed under folderId (transitively) belongs to an open\n * collection — the condition under which moving the folder into a Restricted\n * chain is refused. Restricted sub-branches are pruned: their assets are\n * confined already, so a move changes nothing for them. */\nexport async function folderSubtreeExposed(\n\tclients: { folders: FolderClient; assets: AssetClient },\n\tworkspaceId: string,\n\tfolderId: string,\n\topenIds: string[],\n): Promise<boolean> {\n\tif (openIds.length === 0) return false;\n\tlet frontier = [folderId];\n\tfor (let depth = 0; frontier.length > 0 && depth < maxFolderDepth; depth++) {\n\t\tfor (const id of frontier) {\n\t\t\tconst page = await clients.assets.list(workspaceId, {\n\t\t\t\tfolderId: id,\n\t\t\t\tcollectionIds: openIds,\n\t\t\t});\n\t\t\tif (page.total > 0) return true;\n\t\t}\n\t\tconst next: string[] = [];\n\t\tfor (const id of frontier) {\n\t\t\tconst children = await clients.folders.list(workspaceId, id);\n\t\t\tnext.push(...children.filter((c) => !c.restricted).map((c) => c.id));\n\t\t}\n\t\tfrontier = next;\n\t}\n\treturn false;\n}\n","import { Button, IconButton, Persona } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport {\n\tBadge,\n\tBox,\n\tFlex,\n\tHStack,\n\tNativeSelect,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Lock, X } from \"lucide-react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n\tuseGrantAccess,\n\tuseGrants,\n\tuseRevokeAccess,\n} from \"../hooks/use-grants\";\nimport { useUsers, useWorkspaceMembers } from \"../hooks/use-users\";\nimport { folderChainRestricted } from \"../lib/move-guard\";\nimport { describeRpcError, showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useMediahubClients } from \"../provider\";\nimport type {\n\tAssetInfo,\n\tCollectionInfo,\n\tFolderInfo,\n\tGrantLevel,\n} from \"../types\";\n\n/** What the panel manages access to: the full record is carried so the\n * Derived-Access note can reason about Restricted chains without refetching\n * what the mount site already holds. */\nexport type ManageAccessSubject =\n\t| { kind: \"asset\"; asset: AssetInfo }\n\t| { kind: \"folder\"; folder: FolderInfo }\n\t| { kind: \"collection\"; collection: CollectionInfo };\n\nexport interface ManageAccessDialogProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tsubject: ManageAccessSubject;\n}\n\nfunction subjectId(subject: ManageAccessSubject): string {\n\tswitch (subject.kind) {\n\t\tcase \"asset\":\n\t\t\treturn subject.asset.id;\n\t\tcase \"folder\":\n\t\t\treturn subject.folder.id;\n\t\tcase \"collection\":\n\t\t\treturn subject.collection.id;\n\t}\n}\n\nfunction subjectName(subject: ManageAccessSubject): string {\n\tswitch (subject.kind) {\n\t\tcase \"asset\":\n\t\t\treturn subject.asset.name;\n\t\tcase \"folder\":\n\t\t\treturn subject.folder.name;\n\t\tcase \"collection\":\n\t\t\treturn subject.collection.name;\n\t}\n}\n\n/**\n * \"Manage access\" panel for assets, folders, and collections (guardian#52):\n * a pinned Owner row, the roster of Grants with level dropdowns and revoke,\n * a member picker, and a Derived-Access note. The roster read doubles as the\n * authority gate — the server answers PermissionDenied to everyone but the\n * Owner and workspace admins, and those callers get the denial copy instead\n * of a roster (grantees see content, never who else was granted).\n */\nexport function ManageAccessDialog(\n\tprops: ManageAccessDialogProps,\n): React.JSX.Element {\n\tconst { open, onOpenChange, subject } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst clients = useMediahubClients();\n\tconst kind = subject.kind;\n\tconst resourceId = subjectId(subject);\n\n\t// \"\" = nobody picked yet.\n\tconst [pickedUserId, setPickedUserId] = useState(\"\");\n\tconst [pickLevel, setPickLevel] = useState<GrantLevel>(\"viewer\");\n\n\tconst rosterQuery = useGrants(kind, resourceId, { enabled: open });\n\tconst roster = rosterQuery.data;\n\tconst denied =\n\t\trosterQuery.isError &&\n\t\tdescribeRpcError(rosterQuery.error, \"\").kind === \"permission-denied\";\n\n\t// Fetched only once the caller has proven authority via the roster read —\n\t// non-authorities get the denial copy and nothing else.\n\tconst membersQuery = useWorkspaceMembers({\n\t\tenabled: open && rosterQuery.isSuccess,\n\t});\n\n\tconst rosterUserIds = useMemo(() => {\n\t\tif (!roster) return [];\n\t\tconst ids = roster.grants.map((g) => g.userId);\n\t\tif (roster.ownerUserId) ids.push(roster.ownerUserId);\n\t\treturn ids;\n\t}, [roster]);\n\t// Resolved through the directory rather than the member listing so users\n\t// who since left the workspace still render by name where possible.\n\tconst namesQuery = useUsers(rosterUserIds);\n\tconst nameOf = (userId: string) => namesQuery.data?.[userId] ?? userId;\n\n\t// Whether Derived Access is severed: collections answer from their own\n\t// flag; folders and assets need their chain walked. An unwalkable chain\n\t// counts as Restricted (fail closed), matching the move-guard idiom.\n\tconst scopeQuery = useQuery({\n\t\tqueryKey: [\"mediahub\", \"access-scope\", kind, resourceId],\n\t\tenabled: open && subject.kind !== \"collection\" && rosterQuery.isSuccess,\n\t\tqueryFn: async () => {\n\t\t\tif (subject.kind === \"folder\") {\n\t\t\t\treturn folderChainRestricted(clients.folders, subject.folder);\n\t\t\t}\n\t\t\tif (subject.kind === \"asset\") {\n\t\t\t\tif (!subject.asset.folderId) return false;\n\t\t\t\tconst parent = await clients.folders.get(subject.asset.folderId);\n\t\t\t\treturn folderChainRestricted(clients.folders, parent);\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t});\n\tconst restricted =\n\t\tsubject.kind === \"collection\"\n\t\t\t? subject.collection.restricted\n\t\t\t: scopeQuery.isError\n\t\t\t\t? true\n\t\t\t\t: scopeQuery.data;\n\n\tconst grantAccess = useGrantAccess();\n\tconst revokeAccess = useRevokeAccess();\n\tconst mutating = grantAccess.isPending || revokeAccess.isPending;\n\n\t// Same mount semantics as MoveDialog: keep the Modal mounted, reset\n\t// ephemeral state on reopen.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tsetPickedUserId(\"\");\n\t\tsetPickLevel(\"viewer\");\n\t}, [open]);\n\n\tconst granteeIds = useMemo(\n\t\t() => new Set(roster?.grants.map((g) => g.userId)),\n\t\t[roster],\n\t);\n\t// Candidates: workspace members who are neither the Owner (structural,\n\t// never grantable) nor already on the roster (managed via their row).\n\tconst candidates = useMemo(\n\t\t() =>\n\t\t\t(membersQuery.data ?? []).filter(\n\t\t\t\t(m) => m.id !== roster?.ownerUserId && !granteeIds.has(m.id),\n\t\t\t),\n\t\t[membersQuery.data, roster, granteeIds],\n\t);\n\n\tconst names = namesQuery.data;\n\tconst sortedGrants = useMemo(() => {\n\t\tconst nm = (id: string) => names?.[id] ?? id;\n\t\treturn [...(roster?.grants ?? [])].sort((a, b) =>\n\t\t\tnm(a.userId).localeCompare(nm(b.userId)),\n\t\t);\n\t}, [roster, names]);\n\n\tasync function handleGrant() {\n\t\tif (!pickedUserId) return;\n\t\ttry {\n\t\t\tawait grantAccess.mutateAsync({\n\t\t\t\tresourceType: kind,\n\t\t\t\tresourceId,\n\t\t\t\tuserId: pickedUserId,\n\t\t\t\tlevel: pickLevel,\n\t\t\t});\n\t\t\tsetPickedUserId(\"\");\n\t\t\tsetPickLevel(\"viewer\");\n\t\t\ttoaster.success({ title: t(\"manageAccessDialog.accessGrantedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"manageAccessDialog.grantFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleLevelChange(userId: string, level: GrantLevel) {\n\t\ttry {\n\t\t\tawait grantAccess.mutateAsync({\n\t\t\t\tresourceType: kind,\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t\tlevel,\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"manageAccessDialog.accessUpdatedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"manageAccessDialog.updateFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleRevoke(userId: string) {\n\t\ttry {\n\t\t\tawait revokeAccess.mutateAsync({\n\t\t\t\tresourceType: kind,\n\t\t\t\tresourceId,\n\t\t\t\tuserId,\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"manageAccessDialog.accessRevokedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"manageAccessDialog.revokeFailedToast\"));\n\t\t}\n\t}\n\n\tconst viewerLabel = t(\"manageAccessDialog.viewerLabel\");\n\tconst editorLabel = t(\"manageAccessDialog.editorLabel\");\n\n\tfunction renderBody() {\n\t\tif (rosterQuery.isLoading) {\n\t\t\treturn (\n\t\t\t\t<Flex justify=\"center\" py=\"8\">\n\t\t\t\t\t<Spinner />\n\t\t\t\t</Flex>\n\t\t\t);\n\t\t}\n\t\tif (denied) {\n\t\t\tconst d = describeRpcError(rosterQuery.error, \"\");\n\t\t\treturn (\n\t\t\t\t<Box py=\"4\">\n\t\t\t\t\t<Text fontWeight=\"medium\">{d.title}</Text>\n\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" mt=\"1\">\n\t\t\t\t\t\t{d.description}\n\t\t\t\t\t</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\t\tif (rosterQuery.isError) {\n\t\t\treturn (\n\t\t\t\t<Box py=\"4\">\n\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.error\">\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdescribeRpcError(\n\t\t\t\t\t\t\t\trosterQuery.error,\n\t\t\t\t\t\t\t\tt(\"manageAccessDialog.couldntLoadAccess\"),\n\t\t\t\t\t\t\t).description\n\t\t\t\t\t\t}\n\t\t\t\t\t</Text>\n\t\t\t\t</Box>\n\t\t\t);\n\t\t}\n\t\tif (!roster) return null;\n\n\t\treturn (\n\t\t\t<Flex direction=\"column\" gap=\"4\">\n\t\t\t\t{restricted !== undefined && (\n\t\t\t\t\t<HStack\n\t\t\t\t\t\tgap=\"2\"\n\t\t\t\t\t\talign=\"flex-start\"\n\t\t\t\t\t\tpx=\"3\"\n\t\t\t\t\t\tpy=\"2\"\n\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\tbg=\"bg.muted\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{restricted && <Lock size={14} style={{ marginTop: 2 }} />}\n\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t\t{restricted\n\t\t\t\t\t\t\t\t? t(`manageAccessDialog.restrictedAccessNote.${kind}`)\n\t\t\t\t\t\t\t\t: t(`manageAccessDialog.openAccessNote.${kind}`)}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</HStack>\n\t\t\t\t)}\n\n\t\t\t\t<Flex direction=\"column\" gap=\"2\">\n\t\t\t\t\t{roster.ownerUserId && (\n\t\t\t\t\t\t<Flex align=\"center\" gap=\"2\">\n\t\t\t\t\t\t\t<Box flex=\"1\" minW=\"0\">\n\t\t\t\t\t\t\t\t<Persona size=\"sm\" name={nameOf(roster.ownerUserId)} />\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t<Badge variant=\"subtle\">\n\t\t\t\t\t\t\t\t{t(\"manageAccessDialog.ownerBadgeLabel\")}\n\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t</Flex>\n\t\t\t\t\t)}\n\t\t\t\t\t{sortedGrants.map((g) => {\n\t\t\t\t\t\tconst name = nameOf(g.userId);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Flex key={g.userId} align=\"center\" gap=\"2\">\n\t\t\t\t\t\t\t\t<Box flex=\"1\" minW=\"0\">\n\t\t\t\t\t\t\t\t\t<Persona size=\"sm\" name={name} />\n\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\twidth=\"auto\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"manageAccessDialog.accessLevelForAria\", {\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tvalue={g.level}\n\t\t\t\t\t\t\t\t\tdisabled={mutating}\n\t\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\t\thandleLevelChange(g.userId, e.target.value as GrantLevel)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<option value=\"viewer\">{viewerLabel}</option>\n\t\t\t\t\t\t\t\t\t<option value=\"editor\">{editorLabel}</option>\n\t\t\t\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t\t\t\t<IconButton\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"manageAccessDialog.revokeAccessForAria\", {\n\t\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tdisabled={mutating}\n\t\t\t\t\t\t\t\t\tonClick={() => handleRevoke(g.userId)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X size={14} />\n\t\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</Flex>\n\n\t\t\t\t<HStack gap=\"2\" align=\"center\">\n\t\t\t\t\t<Box flex=\"1\" minW=\"0\">\n\t\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\taria-label={t(\"manageAccessDialog.addPersonAria\")}\n\t\t\t\t\t\t\tplaceholder={t(\"manageAccessDialog.addPersonLabel\")}\n\t\t\t\t\t\t\tvalue={pickedUserId}\n\t\t\t\t\t\t\tdisabled={membersQuery.isLoading}\n\t\t\t\t\t\t\tonChange={(e) => setPickedUserId(e.target.value)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{candidates.map((m) => (\n\t\t\t\t\t\t\t\t<option key={m.id} value={m.id}>\n\t\t\t\t\t\t\t\t\t{m.displayName}\n\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t</Box>\n\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\twidth=\"auto\"\n\t\t\t\t\t\taria-label={t(\"manageAccessDialog.accessLevelAria\")}\n\t\t\t\t\t\tvalue={pickLevel}\n\t\t\t\t\t\tonChange={(e) => setPickLevel(e.target.value as GrantLevel)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"viewer\">{viewerLabel}</option>\n\t\t\t\t\t\t<option value=\"editor\">{editorLabel}</option>\n\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!pickedUserId}\n\t\t\t\t\t\tloading={grantAccess.isPending}\n\t\t\t\t\t\tonClick={handleGrant}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"manageAccessDialog.grantLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\tsize=\"md\"\n\t\t\theader={t(\"manageAccessDialog.header\", {\n\t\t\t\tsubjectName: subjectName(subject),\n\t\t\t})}\n\t\t\tfooter={\n\t\t\t\t<HStack gap=\"2\" justify=\"flex-end\">\n\t\t\t\t\t<Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n\t\t\t\t\t\t{t(\"manageAccessDialog.doneLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t{renderBody()}\n\t\t</Modal>\n\t);\n}\nManageAccessDialog.displayName = \"ManageAccessDialog\";\n","import { Button, IconButton } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport {\n\tBox,\n\tFlex,\n\tHStack,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { TFunction } from \"i18next\";\nimport { ChevronDown, ChevronRight, Folder, Lock } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useMoveAsset } from \"../hooks/use-assets\";\nimport { useCollections } from \"../hooks/use-collections\";\nimport { useFolders, useMoveFolder } from \"../hooks/use-folders\";\nimport {\n\tassetExposedByOpenCollection,\n\tfolderChainRestricted,\n\tfolderSubtreeExposed,\n\topenCollectionIds,\n} from \"../lib/move-guard\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { AssetInfo, FolderInfo } from \"../types\";\n\n/** What the dialog moves: a folder (from the tree's context menu) or an\n * asset (from its detail view). */\nexport type MoveSubject =\n\t| { kind: \"folder\"; folder: FolderInfo }\n\t| { kind: \"asset\"; asset: AssetInfo };\n\nexport interface MoveDialogProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\tsubject: MoveSubject;\n\t/** Called after a successful move with the destination folder id\n\t * (\"\" = workspace root). */\n\tonMoved?: (destinationId: string) => void;\n}\n\nfunction subjectName(subject: MoveSubject): string {\n\treturn subject.kind === \"folder\" ? subject.folder.name : subject.asset.name;\n}\n\n/** The destination the subject currently sits in (\"\" = workspace root). */\nfunction currentParentId(subject: MoveSubject): string {\n\treturn subject.kind === \"folder\"\n\t\t? subject.folder.parentId\n\t\t: subject.asset.folderId;\n}\n\ninterface RowContext {\n\tsubject: MoveSubject;\n\t/** The subject is exposed through an open collection, so Restricted\n\t * destinations would trip the server's leak guard. */\n\tguardActive: boolean;\n\tselectedId: string | null;\n\tonSelect: (id: string) => void;\n\t/** Drops the selection iff it still points at this id — rows call it\n\t * when they become disabled under an already-made selection. */\n\tonDeselect: (id: string) => void;\n\tcurrentLocationLabel: string;\n\tselfLocationLabel: string;\n\tblockedLabel: string;\n\tt: TFunction;\n}\n\n/** Why a destination row is disabled, or null when it is selectable. */\nfunction rowDisabledReason(\n\tctx: RowContext,\n\tfolder: FolderInfo,\n\tchainRestricted: boolean,\n): string | null {\n\tif (ctx.subject.kind === \"folder\" && folder.id === ctx.subject.folder.id) {\n\t\treturn ctx.selfLocationLabel;\n\t}\n\tif (folder.id === currentParentId(ctx.subject)) {\n\t\treturn ctx.currentLocationLabel;\n\t}\n\tif (ctx.guardActive && chainRestricted) {\n\t\treturn ctx.blockedLabel;\n\t}\n\treturn null;\n}\n\ninterface DestinationRowButtonProps {\n\tname: string;\n\t/** Disabled-with-reason when set; selectable when null. */\n\treason: string | null;\n\tselected: boolean;\n\trestricted?: boolean;\n\temphasized?: boolean;\n\tonClick: () => void;\n}\n\n/** The selectable body shared by every destination row, root included. */\nfunction DestinationRowButton({\n\tname,\n\treason,\n\tselected,\n\trestricted,\n\temphasized,\n\tonClick,\n}: DestinationRowButtonProps): React.JSX.Element {\n\treturn (\n\t\t<Box\n\t\t\tasChild\n\t\t\tflex=\"1\"\n\t\t\tpx=\"2\"\n\t\t\tpy=\"1\"\n\t\t\trounded=\"md\"\n\t\t\ttextAlign=\"left\"\n\t\t\tcursor={reason ? \"not-allowed\" : \"pointer\"}\n\t\t\topacity={reason ? 0.5 : 1}\n\t\t\tbg={selected ? \"colorPalette.subtle\" : \"transparent\"}\n\t\t\tcolor={selected ? \"colorPalette.fg\" : \"fg.default\"}\n\t\t\tcolorPalette=\"primary\"\n\t\t\t_hover={{ bg: selected ? \"colorPalette.subtle\" : \"bg.muted\" }}\n\t\t>\n\t\t\t<button type=\"button\" disabled={!!reason} onClick={onClick}>\n\t\t\t\t<HStack gap=\"2\" align=\"center\">\n\t\t\t\t\t{restricted ? <Lock size={13} /> : <Folder size={13} />}\n\t\t\t\t\t<Text fontSize=\"sm\" fontWeight={emphasized ? \"medium\" : \"normal\"}>\n\t\t\t\t\t\t{name}\n\t\t\t\t\t</Text>\n\t\t\t\t</HStack>\n\t\t\t\t{reason && (\n\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t\t{reason}\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t</button>\n\t\t</Box>\n\t);\n}\n\ninterface DestinationRowProps {\n\tctx: RowContext;\n\tfolder: FolderInfo;\n\t/** Whether any ancestor in the picker walk is Restricted. */\n\tancestorRestricted: boolean;\n\tlevel: number;\n}\n\nfunction DestinationRow({\n\tctx,\n\tfolder,\n\tancestorRestricted,\n\tlevel,\n}: DestinationRowProps): React.JSX.Element {\n\tconst [expanded, setExpanded] = useState(false);\n\tconst childrenQuery = useFolders(folder.id, { enabled: expanded });\n\n\tconst chainRestricted = ancestorRestricted || folder.restricted;\n\tconst reason = rowDisabledReason(ctx, folder, chainRestricted);\n\tconst isSelf =\n\t\tctx.subject.kind === \"folder\" && folder.id === ctx.subject.folder.id;\n\tconst selected = ctx.selectedId === folder.id;\n\n\t// A selection must not survive its own disabling: the exposure probe can\n\t// resolve after the user already picked a Restricted destination.\n\tconst { onDeselect } = ctx;\n\tuseEffect(() => {\n\t\tif (selected && reason) onDeselect(folder.id);\n\t}, [selected, reason, folder.id, onDeselect]);\n\n\treturn (\n\t\t<>\n\t\t\t<Flex align=\"center\" gap=\"1\" pl={level * 4}>\n\t\t\t\t{/* The subject folder's subtree moves with it — never expandable. */}\n\t\t\t\t{isSelf ? (\n\t\t\t\t\t<Box w=\"6\" />\n\t\t\t\t) : (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\texpanded\n\t\t\t\t\t\t\t\t? ctx.t(\"moveDialog.collapseAria\", { folderName: folder.name })\n\t\t\t\t\t\t\t\t: ctx.t(\"moveDialog.expandAria\", { folderName: folder.name })\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonClick={() => setExpanded((e) => !e)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n\t\t\t\t\t</IconButton>\n\t\t\t\t)}\n\t\t\t\t<DestinationRowButton\n\t\t\t\t\tname={folder.name}\n\t\t\t\t\treason={reason}\n\t\t\t\t\tselected={selected}\n\t\t\t\t\trestricted={folder.restricted}\n\t\t\t\t\tonClick={() => ctx.onSelect(folder.id)}\n\t\t\t\t/>\n\t\t\t</Flex>\n\t\t\t{expanded && childrenQuery.isLoading && (\n\t\t\t\t<Flex justify=\"center\" py=\"1\">\n\t\t\t\t\t<Spinner size=\"xs\" />\n\t\t\t\t</Flex>\n\t\t\t)}\n\t\t\t{expanded &&\n\t\t\t\tchildrenQuery.data?.map((child) => (\n\t\t\t\t\t<DestinationRow\n\t\t\t\t\t\tkey={child.id}\n\t\t\t\t\t\tctx={ctx}\n\t\t\t\t\t\tfolder={child}\n\t\t\t\t\t\tancestorRestricted={chainRestricted}\n\t\t\t\t\t\tlevel={level + 1}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t</>\n\t);\n}\n\n/**\n * Destination folder picker for moving a folder or an asset. Destinations\n * that would trip the server's leak guard (moving exposed content into a\n * Restricted chain, guardian ADR 0003) render disabled with the reason\n * inline; the server remains authoritative and re-checks every move.\n */\nexport function MoveDialog(props: MoveDialogProps): React.JSX.Element {\n\tconst { open, onOpenChange, subject, onMoved } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst clients = useMediahubClients();\n\tconst [selectedId, setSelectedId] = useState<string | null>(null);\n\n\tconst rootQuery = useFolders(\"\");\n\tconst collectionsQuery = useCollections();\n\tconst collections = collectionsQuery.data ?? [];\n\tconst openIds = useMemo(() => openCollectionIds(collections), [collections]);\n\n\tconst moveFolder = useMoveFolder();\n\tconst moveAsset = useMoveAsset();\n\n\t// Whether moving the subject into a Restricted chain would trip the\n\t// server's leak guard. Assets carry their collection memberships, so the\n\t// answer is synchronous; folders need the subtree probed.\n\tconst subjectFolderId = subject.kind === \"folder\" ? subject.folder.id : \"\";\n\tconst folderGuardQuery = useQuery({\n\t\tqueryKey: [\"mediahub\", \"move-guard\", subjectFolderId, openIds],\n\t\tqueryFn: async () => {\n\t\t\tif (subject.kind !== \"folder\") return false;\n\t\t\t// A subject already confined by a Restricted chain can move\n\t\t\t// anywhere — the move changes nothing for its audience.\n\t\t\tif (await folderChainRestricted(clients.folders, subject.folder)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn folderSubtreeExposed(\n\t\t\t\t{ folders: clients.folders, assets: clients.assets },\n\t\t\t\tworkspaceId,\n\t\t\t\tsubject.folder.id,\n\t\t\t\topenIds,\n\t\t\t);\n\t\t},\n\t\tenabled: open && subject.kind === \"folder\" && collectionsQuery.isSuccess,\n\t});\n\tconst guardActive =\n\t\tsubject.kind === \"asset\"\n\t\t\t? assetExposedByOpenCollection(subject.asset, collections)\n\t\t\t: folderGuardQuery.data === true;\n\n\t// Same mount semantics as CollectionPicker (#66): keep the Modal mounted,\n\t// reset ephemeral state on exit *and* on reopen.\n\tfunction resetEphemeralState() {\n\t\tsetSelectedId(null);\n\t}\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: reset only on open→true\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tresetEphemeralState();\n\t}, [open]);\n\n\tasync function handleConfirm() {\n\t\tif (selectedId === null) return;\n\t\ttry {\n\t\t\tif (subject.kind === \"folder\") {\n\t\t\t\tawait moveFolder.mutateAsync({\n\t\t\t\t\tid: subject.folder.id,\n\t\t\t\t\tparentId: selectedId,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait moveAsset.mutateAsync({\n\t\t\t\t\tid: subject.asset.id,\n\t\t\t\t\tfolderId: selectedId,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttoaster.success({\n\t\t\t\ttitle:\n\t\t\t\t\tsubject.kind === \"folder\"\n\t\t\t\t\t\t? t(\"moveDialog.folderMovedToast\")\n\t\t\t\t\t\t: t(\"moveDialog.assetMovedToast\"),\n\t\t\t});\n\t\t\tonMoved?.(selectedId);\n\t\t\tonOpenChange(false);\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"moveDialog.moveFailedToast\"));\n\t\t}\n\t}\n\n\tconst handleDeselect = useCallback((id: string) => {\n\t\tsetSelectedId((current) => (current === id ? null : current));\n\t}, []);\n\n\tconst ctx: RowContext = {\n\t\tsubject,\n\t\tguardActive,\n\t\tselectedId,\n\t\tonSelect: setSelectedId,\n\t\tonDeselect: handleDeselect,\n\t\tcurrentLocationLabel: t(\"moveDialog.currentLocationLabel\"),\n\t\tselfLocationLabel: t(\"moveDialog.selfLocationLabel\"),\n\t\tblockedLabel:\n\t\t\tsubject.kind === \"asset\"\n\t\t\t\t? t(\"moveDialog.blockedAssetLabel\")\n\t\t\t\t: t(\"moveDialog.blockedFolderLabel\", {\n\t\t\t\t\t\tfolderName: subject.folder.name,\n\t\t\t\t\t}),\n\t\tt,\n\t};\n\n\tconst rootReason =\n\t\tcurrentParentId(subject) === \"\" ? ctx.currentLocationLabel : null;\n\tconst moving = moveFolder.isPending || moveAsset.isPending;\n\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={resetEphemeralState}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\tsize=\"md\"\n\t\t\theader={t(\"moveDialog.header\", { subjectName: subjectName(subject) })}\n\t\t\tfooter={\n\t\t\t\t<HStack gap=\"2\" justify=\"flex-end\">\n\t\t\t\t\t<Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n\t\t\t\t\t\t{t(\"moveDialog.cancelLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={selectedId === null}\n\t\t\t\t\t\tloading={moving}\n\t\t\t\t\t\tonClick={handleConfirm}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"moveDialog.confirmLabel\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap=\"0.5\" minH=\"240px\">\n\t\t\t\t<Flex align=\"center\" gap=\"1\">\n\t\t\t\t\t<Box w=\"6\" />\n\t\t\t\t\t<DestinationRowButton\n\t\t\t\t\t\tname={t(\"moveDialog.rootLabel\")}\n\t\t\t\t\t\treason={rootReason}\n\t\t\t\t\t\tselected={selectedId === \"\"}\n\t\t\t\t\t\temphasized\n\t\t\t\t\t\tonClick={() => setSelectedId(\"\")}\n\t\t\t\t\t/>\n\t\t\t\t</Flex>\n\t\t\t\t{rootQuery.isLoading ? (\n\t\t\t\t\t<Flex justify=\"center\" py=\"6\">\n\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t</Flex>\n\t\t\t\t) : (\n\t\t\t\t\t(rootQuery.data ?? []).map((folder) => (\n\t\t\t\t\t\t<DestinationRow\n\t\t\t\t\t\t\tkey={folder.id}\n\t\t\t\t\t\t\tctx={ctx}\n\t\t\t\t\t\t\tfolder={folder}\n\t\t\t\t\t\t\tancestorRestricted={false}\n\t\t\t\t\t\t\tlevel={0}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n}\nMoveDialog.displayName = \"MoveDialog\";\n","import { Box, Flex, Text } from \"@knkcs/anker/primitives\";\nimport type { TFunction } from \"i18next\";\nimport { Lock } from \"lucide-react\";\nimport { useTranslation } from \"react-i18next\";\n\n/** The shared Restricted-container warning (guardian#48): shown when creating\n * a Restricted folder and, with the other noun, on the collection dialog's\n * Restricted switch. Takes `t` explicitly (rather than calling\n * `useTranslation` itself) so it stays callable from non-component code. */\nexport function restrictedContainerWarning(\n\tkind: \"folder\" | \"collection\",\n\tt: TFunction,\n): string {\n\treturn t(`restricted.containerWarning.${kind}`);\n}\n\n/** The explicit unrestrict disclosure (guardian#55): spelled out before the\n * toggle because it widens the audience to the whole workspace. */\nexport function unrestrictDisclosure(\n\tkind: \"folder\" | \"collection\",\n\tname: string,\n\tt: TFunction,\n): string {\n\treturn t(`restricted.unrestrictDisclosure.${kind}`, { name });\n}\n\nexport interface RestrictedLockBadgeProps {\n\t/** Icon size in px. @default 12 */\n\tsize?: number;\n\t/** Optional left margin (spacing token) for sites without a gap parent. */\n\tml?: number;\n}\n\n/** Lock marker rendered wherever a Restricted container appears. The\n * `aria-label=\"Restricted\"` is the contract tests target — keep it stable. */\nexport const RestrictedLockBadge: React.FC<RestrictedLockBadgeProps> = ({\n\tsize = 12,\n\tml,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\treturn (\n\t\t<Box\n\t\t\trole=\"img\"\n\t\t\taria-label={t(\"restricted.lockBadgeAria\")}\n\t\t\tcolor=\"fg.muted\"\n\t\t\tflexShrink={0}\n\t\t\tml={ml}\n\t\t>\n\t\t\t<Lock size={size} />\n\t\t</Box>\n\t);\n};\nRestrictedLockBadge.displayName = \"RestrictedLockBadge\";\n\nexport interface RestrictedWarningNoticeProps {\n\tkind: \"folder\" | \"collection\";\n}\n\n/** Warning banner for the deliberate create-Restricted paths. */\nexport const RestrictedWarningNotice: React.FC<\n\tRestrictedWarningNoticeProps\n> = ({ kind }) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\treturn (\n\t\t<Flex\n\t\t\tgap={2}\n\t\t\tp={3}\n\t\t\trounded=\"md\"\n\t\t\tbg=\"bg.muted\"\n\t\t\tcolor=\"fg.muted\"\n\t\t\tfontSize=\"sm\"\n\t\t\talign=\"flex-start\"\n\t\t>\n\t\t\t<Box flexShrink={0} mt={0.5}>\n\t\t\t\t<Lock size={14} />\n\t\t\t</Box>\n\t\t\t<Text>{restrictedContainerWarning(kind, t)}</Text>\n\t\t</Flex>\n\t);\n};\nRestrictedWarningNotice.displayName = \"RestrictedWarningNotice\";\n","import { TextInput } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport { Flex, toaster } from \"@knkcs/anker/primitives\";\nimport { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCreateFolder } from \"../hooks/use-folders\";\nimport { RestrictedWarningNotice } from \"./restricted\";\n\nexport interface RestrictedFolderDialogProps {\n\topen: boolean;\n\tonClose: () => void;\n\t/** Parent folder to create under; \"\" creates at the root. */\n\tparentId: string;\n\t/** Called after a successful create (e.g. to refresh the tree). */\n\tonCreated?: () => void;\n}\n\n/** Deliberate-path dialog for creating a Restricted folder. The everyday\n * inline \"New Folder\" input stays the fast path for ordinary folders. */\nexport const RestrictedFolderDialog: React.FC<RestrictedFolderDialogProps> = ({\n\topen,\n\tonClose,\n\tparentId,\n\tonCreated,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst [name, setName] = useState(\"\");\n\tconst createFolder = useCreateFolder();\n\n\t// Re-arm on open rather than clearing on close: zag presence can skip\n\t// onExitComplete when a reopen interrupts the exit animation (#73), and\n\t// clearing on the close transition would blank the field mid-fade.\n\tuseEffect(() => {\n\t\tif (open) setName(\"\");\n\t}, [open]);\n\n\tasync function handleCreate() {\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) return;\n\t\ttry {\n\t\t\tawait createFolder.mutateAsync({\n\t\t\t\tname: trimmed,\n\t\t\t\tslug: trimmed.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tparentId,\n\t\t\t\trestricted: true,\n\t\t\t});\n\t\t\ttoaster.success({\n\t\t\t\ttitle: t(\"restrictedFolderDialog.createSuccessToast\"),\n\t\t\t});\n\t\t\tonCreated?.();\n\t\t\tonClose();\n\t\t} catch (err) {\n\t\t\tconst msg = err instanceof Error ? err.message : String(err);\n\t\t\ttoaster.error({\n\t\t\t\ttitle: t(\"restrictedFolderDialog.createFailedToast\"),\n\t\t\t\tdescription: msg,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Do NOT `return null` when closed: unmounting the open dialog machine\n\t// under StrictMode orphans its scroll-lock/aria-hidden cleanup and wedges\n\t// the whole app (#66). Keep Modal mounted; lazyMount/unmountOnExit keep\n\t// the fresh-content-per-open semantics.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonClose={onClose}\n\t\t\theader={t(\"restrictedFolderDialog.header\")}\n\t\t\tonSave={handleCreate}\n\t\t\tsaveLabel={t(\"restrictedFolderDialog.createLabel\")}\n\t\t\tsaveDisabled={!name.trim()}\n\t\t\tloading={createFolder.isPending}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap={3}>\n\t\t\t\t<RestrictedWarningNotice kind=\"folder\" />\n\t\t\t\t<TextInput\n\t\t\t\t\tvalue={name}\n\t\t\t\t\tonChange={(e) => setName(e.target.value)}\n\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\tif (e.key === \"Enter\") handleCreate();\n\t\t\t\t\t}}\n\t\t\t\t\tautoFocus\n\t\t\t\t\tplaceholder={t(\"restrictedFolderDialog.namePlaceholder\")}\n\t\t\t\t/>\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n};\nRestrictedFolderDialog.displayName = \"RestrictedFolderDialog\";\n","import { TextInput } from \"@knkcs/anker/atoms\";\nimport {\n\tTreeViewBranchControl,\n\tTreeViewBranchIndicator,\n\tTreeViewBranchText,\n\tTreeViewNode,\n\tTreeViewRoot,\n\tTreeViewTree,\n\tcreateTreeCollection,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBox,\n\tFlex,\n\tMenuContent,\n\tMenuItem,\n\tMenuRoot,\n\tMenuTrigger,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { Ellipsis, FolderPlus } from \"lucide-react\";\nimport { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCanManage } from \"../hooks/use-authz\";\nimport {\n\tuseCreateFolder,\n\tuseDeleteFolder,\n\tuseFolders,\n\tuseSetFolderRestricted,\n\tuseUpdateFolder,\n} from \"../hooks/use-folders\";\nimport {\n\ttype RpcErrorDescription,\n\tdescribeRpcError,\n\tshowRpcErrorToast,\n} from \"../lib/rpc-errors\";\nimport { useMediahubClients, useWorkspaceId } from \"../provider\";\nimport type { FolderInfo } from \"../types\";\nimport { LeakGuardRefusalDialog } from \"./leak-guard-refusal-dialog\";\nimport { ManageAccessDialog } from \"./manage-access-dialog\";\nimport { MoveDialog } from \"./move-dialog\";\nimport { RestrictedLockBadge } from \"./restricted\";\nimport { RestrictedFolderDialog } from \"./restricted-folder-dialog\";\n\ninterface FolderTreeProps {\n\tactiveFolderId: string;\n\tonFolderSelect: (folderId: string) => void;\n}\n\ninterface FolderNode {\n\tid: string;\n\tname: string;\n\trestricted: boolean;\n\tchildren: FolderNode[];\n\t/** The full folder record, for actions that need more than id/name\n\t * (Move… hands it to the destination picker). Absent only on the\n\t * synthetic collection root, which never renders a row. */\n\tinfo?: FolderInfo;\n}\n\nexport const FolderTree: React.FC<FolderTreeProps> = ({\n\tactiveFolderId,\n\tonFolderSelect,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst rootQuery = useFolders(\"\");\n\tconst rootFolders: FolderInfo[] = rootQuery.data ?? [];\n\tconst [treeKey, setTreeKey] = useState(0);\n\tconst [isCreating, setIsCreating] = useState(false);\n\tconst [newName, setNewName] = useState(\"\");\n\tconst [renamingId, setRenamingId] = useState<string | null>(null);\n\tconst [renameValue, setRenameValue] = useState(\"\");\n\tconst [moveSubject, setMoveSubject] = useState<FolderInfo | null>(null);\n\tconst [moveOpen, setMoveOpen] = useState(false);\n\tconst [accessSubject, setAccessSubject] = useState<FolderInfo | null>(null);\n\tconst [accessOpen, setAccessOpen] = useState(false);\n\t// Parent for the \"New Restricted folder…\" dialog; null = closed.\n\tconst [restrictedParentId, setRestrictedParentId] = useState<string | null>(\n\t\tnull,\n\t);\n\t// The node whose context menu was last opened — the authority probe runs\n\t// for it lazily, so the tree never probes every visible row.\n\tconst [menuNodeId, setMenuNodeId] = useState(\"\");\n\t// Kept mounted while a refusal exists (dialog machines must not unmount\n\t// mid-exit, see collection-picker / #66).\n\tconst [toggleRefusal, setToggleRefusal] =\n\t\tuseState<RpcErrorDescription | null>(null);\n\tconst [refusalOpen, setRefusalOpen] = useState(false);\n\tconst createFolder = useCreateFolder();\n\tconst updateFolder = useUpdateFolder();\n\tconst deleteFolder = useDeleteFolder();\n\tconst setFolderRestricted = useSetFolderRestricted();\n\tconst canManage = useCanManage(\"folder\", menuNodeId);\n\tconst { confirm } = useConfirmModal();\n\tconst creatingRef = useRef(false);\n\tconst renamingRef = useRef(false);\n\tconst { folders } = useMediahubClients();\n\n\tconst collection = useMemo(() => {\n\t\tconst rootChildren: FolderNode[] = rootFolders.map((f) => ({\n\t\t\tid: f.id,\n\t\t\tname: f.name,\n\t\t\trestricted: f.restricted,\n\t\t\tchildren: [],\n\t\t\tinfo: f,\n\t\t}));\n\t\treturn createTreeCollection<FolderNode>({\n\t\t\trootNode: {\n\t\t\t\tid: \"root\",\n\t\t\t\tname: \"Root\",\n\t\t\t\trestricted: false,\n\t\t\t\tchildren: rootChildren,\n\t\t\t},\n\t\t\tnodeToValue: (node) => node.id,\n\t\t\tnodeToString: (node) => node.name,\n\t\t\t// Return 1 for empty children so all folders are treated as branches\n\t\t\t// (expandable) even before their children are lazy-loaded.\n\t\t\tnodeToChildrenCount: (node) =>\n\t\t\t\tnode.children.length > 0 ? node.children.length : 1,\n\t\t});\n\t}, [rootFolders]);\n\n\tconst handleLoadChildren = useCallback(\n\t\tasync ({ node }: { node: FolderNode }) => {\n\t\t\tconst res = await folders.list(workspaceId, node.id);\n\t\t\treturn res.map(\n\t\t\t\t(f): FolderNode => ({\n\t\t\t\t\tid: f.id,\n\t\t\t\t\tname: f.name,\n\t\t\t\t\trestricted: f.restricted,\n\t\t\t\t\tchildren: [],\n\t\t\t\t\tinfo: f,\n\t\t\t\t}),\n\t\t\t);\n\t\t},\n\t\t[folders, workspaceId],\n\t);\n\n\tasync function handleDelete(folderId: string, folderName: string) {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"folderTree.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"folderTree.deleteConfirmMessage\", { folderName }),\n\t\t\tconfirmLabel: t(\"folderTree.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteFolder.mutateAsync(folderId);\n\t\t\tif (activeFolderId === folderId) onFolderSelect(\"\");\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({ title: t(\"folderTree.deleteSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"folderTree.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleRenameSubmit(node: FolderNode) {\n\t\tif (renamingRef.current) return;\n\t\tconst trimmed = renameValue.trim();\n\t\tif (!trimmed || trimmed === node.name) {\n\t\t\tsetRenamingId(null);\n\t\t\treturn;\n\t\t}\n\t\trenamingRef.current = true;\n\t\ttry {\n\t\t\tawait updateFolder.mutateAsync({ id: node.id, name: trimmed });\n\t\t\tsetRenamingId(null);\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({ title: t(\"folderTree.renameSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"folderTree.renameFailedToast\"));\n\t\t} finally {\n\t\t\trenamingRef.current = false;\n\t\t}\n\t}\n\n\tasync function handleToggleRestricted(node: FolderNode) {\n\t\tconst restricting = !node.restricted;\n\t\tif (!restricting) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"folderTree.unrestrictConfirmTitle\"),\n\t\t\t\tmessage: t(\"folderTree.unrestrictConfirmMessage\", {\n\t\t\t\t\tfolderName: node.name,\n\t\t\t\t}),\n\t\t\t\tconfirmLabel: t(\"folderTree.unrestrictConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\ttry {\n\t\t\tawait setFolderRestricted.mutateAsync({\n\t\t\t\tid: node.id,\n\t\t\t\trestricted: restricting,\n\t\t\t});\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({\n\t\t\t\ttitle: restricting\n\t\t\t\t\t? t(\"folderTree.folderRestrictedToast\")\n\t\t\t\t\t: t(\"folderTree.folderUnrestrictedToast\"),\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconst fallback = restricting\n\t\t\t\t? t(\"folderTree.restrictFailedToast\")\n\t\t\t\t: t(\"folderTree.unrestrictFailedToast\");\n\t\t\tconst described = describeRpcError(err, fallback);\n\t\t\t// A guard refusal gets the explanation dialog with the offending\n\t\t\t// pairs — never a raw error (guardian#55).\n\t\t\tif (described.kind === \"leak-guard\") {\n\t\t\t\tsetToggleRefusal(described);\n\t\t\t\tsetRefusalOpen(true);\n\t\t\t} else {\n\t\t\t\tshowRpcErrorToast(err, fallback);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function handleCreate() {\n\t\tif (creatingRef.current) return;\n\t\tconst trimmed = newName.trim();\n\t\tif (!trimmed) {\n\t\t\tsetIsCreating(false);\n\t\t\treturn;\n\t\t}\n\t\tcreatingRef.current = true;\n\t\ttry {\n\t\t\tawait createFolder.mutateAsync({\n\t\t\t\tname: trimmed,\n\t\t\t\tslug: trimmed.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tparentId: activeFolderId || \"\",\n\t\t\t});\n\t\t\tsetNewName(\"\");\n\t\t\tsetIsCreating(false);\n\t\t\tsetTreeKey((k) => k + 1);\n\t\t\ttoaster.success({ title: t(\"folderTree.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"folderTree.createFailedToast\"));\n\t\t} finally {\n\t\t\tcreatingRef.current = false;\n\t\t}\n\t}\n\n\treturn (\n\t\t<Flex direction=\"column\" flex={1} gap={0.5}>\n\t\t\t<Flex\n\t\t\t\talign=\"center\"\n\t\t\t\tpx={2}\n\t\t\t\tpy={1}\n\t\t\t\trounded=\"md\"\n\t\t\t\tcursor=\"pointer\"\n\t\t\t\tbg={!activeFolderId ? \"colorPalette.subtle\" : \"transparent\"}\n\t\t\t\tcolor={!activeFolderId ? \"colorPalette.fg\" : \"fg.default\"}\n\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t_hover={{\n\t\t\t\t\tbg: !activeFolderId ? \"colorPalette.subtle\" : \"bg.muted\",\n\t\t\t\t}}\n\t\t\t\tonClick={() => onFolderSelect(\"\")}\n\t\t\t\tfontSize=\"sm\"\n\t\t\t\tfontWeight=\"medium\"\n\t\t\t\tcss={{\n\t\t\t\t\t\"& > [data-folder-menu]\": { opacity: 0 },\n\t\t\t\t\t\"&:hover > [data-folder-menu]\": { opacity: 1 },\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{t(\"folderTree.allAssets\")}\n\t\t\t\t<Box data-folder-menu=\"\" transition=\"opacity 0.1s\" ml=\"auto\">\n\t\t\t\t\t<MenuRoot>\n\t\t\t\t\t\t<MenuTrigger asChild>\n\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t\t\t\t_hover={{ color: \"fg.default\" }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\taria-label={t(\"folderTree.allAssetsMenuAria\")}\n\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Ellipsis size={12} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t</MenuTrigger>\n\t\t\t\t\t\t<MenuContent>\n\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\tvalue=\"new-restricted\"\n\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\tsetRestrictedParentId(\"\");\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"folderTree.newRestrictedFolder\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t</MenuContent>\n\t\t\t\t\t</MenuRoot>\n\t\t\t\t</Box>\n\t\t\t</Flex>\n\n\t\t\t{rootFolders.length > 0 && (\n\t\t\t\t<TreeViewRoot\n\t\t\t\t\tkey={treeKey}\n\t\t\t\t\tcollection={collection}\n\t\t\t\t\tselectedValue={activeFolderId ? [activeFolderId] : []}\n\t\t\t\t\tonSelectionChange={(details) => {\n\t\t\t\t\t\tconst selected = details.selectedValue[0];\n\t\t\t\t\t\tif (selected) onFolderSelect(selected);\n\t\t\t\t\t}}\n\t\t\t\t\tloadChildren={handleLoadChildren}\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t>\n\t\t\t\t\t<TreeViewTree>\n\t\t\t\t\t\t<TreeViewNode<FolderNode>\n\t\t\t\t\t\t\trender={({ node }) =>\n\t\t\t\t\t\t\t\trenamingId === node.id ? (\n\t\t\t\t\t\t\t\t\t<TreeViewBranchControl>\n\t\t\t\t\t\t\t\t\t\t<TreeViewBranchIndicator />\n\t\t\t\t\t\t\t\t\t\t{/* Keep clicks and keystrokes out of the tree's\n\t\t\t\t\t\t\t\t\t\t selection/typeahead machinery. */}\n\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\tflex=\"1\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={renameValue}\n\t\t\t\t\t\t\t\t\t\t\t\tonChange={(e) => setRenameValue(e.target.value)}\n\t\t\t\t\t\t\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (e.key === \"Enter\") handleRenameSubmit(node);\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (e.key === \"Escape\") setRenamingId(null);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\tonBlur={() => handleRenameSubmit(node)}\n\t\t\t\t\t\t\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</TreeViewBranchControl>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<TreeViewBranchControl\n\t\t\t\t\t\t\t\t\t\tcss={{\n\t\t\t\t\t\t\t\t\t\t\t\"& > [data-folder-menu]\": {\n\t\t\t\t\t\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"&:hover > [data-folder-menu]\": {\n\t\t\t\t\t\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<TreeViewBranchIndicator />\n\t\t\t\t\t\t\t\t\t\t<TreeViewBranchText>{node.name}</TreeViewBranchText>\n\t\t\t\t\t\t\t\t\t\t{node.restricted && <RestrictedLockBadge ml={1} />}\n\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\tdata-folder-menu=\"\"\n\t\t\t\t\t\t\t\t\t\t\ttransition=\"opacity 0.1s\"\n\t\t\t\t\t\t\t\t\t\t\tml=\"auto\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<MenuRoot\n\t\t\t\t\t\t\t\t\t\t\t\tonOpenChange={({ open }) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (open) setMenuNodeId(node.id);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<MenuTrigger asChild>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tasChild\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t_hover={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor: \"fg.default\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={t(\"folderTree.folderMenuAria\", {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfolderName: node.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<Ellipsis size={12} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t\t\t\t</MenuTrigger>\n\t\t\t\t\t\t\t\t\t\t\t\t<MenuContent>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"rename\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetRenameValue(node.name);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetRenamingId(node.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.rename\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"move\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!node.info) return;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMoveSubject(node.info);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetMoveOpen(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.move\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"manage-access\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!node.info) return;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetAccessSubject(node.info);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetAccessOpen(true);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.manageAccess\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"new-restricted\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsetRestrictedParentId(node.id);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.newRestrictedFolder\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Authority-only (Owner or workspace admin):\n\t\t\t\t\t\t\t\t\t\t\t\t\t appears once the lazy probe confirms. */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{menuNodeId === node.id &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcanManage.data === true && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"toggle-restricted\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleToggleRestricted(node);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{node.restricted\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? t(\"folderTree.unrestrict\")\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: t(\"folderTree.restrict\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue=\"delete\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"fg.error\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleDelete(node.id, node.name);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{t(\"folderTree.delete\")}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t\t\t\t\t</MenuContent>\n\t\t\t\t\t\t\t\t\t\t\t</MenuRoot>\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</TreeViewBranchControl>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</TreeViewTree>\n\t\t\t\t</TreeViewRoot>\n\t\t\t)}\n\n\t\t\t<Box flex={1} />\n\n\t\t\t{isCreating ? (\n\t\t\t\t<Box px={2} py={1}>\n\t\t\t\t\t<TextInput\n\t\t\t\t\t\tvalue={newName}\n\t\t\t\t\t\tonChange={(e) => setNewName(e.target.value)}\n\t\t\t\t\t\tonKeyDown={(e) => {\n\t\t\t\t\t\t\tif (e.key === \"Enter\") handleCreate();\n\t\t\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\t\t\tsetIsCreating(false);\n\t\t\t\t\t\t\t\tsetNewName(\"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonBlur={handleCreate}\n\t\t\t\t\t\tautoFocus\n\t\t\t\t\t\tplaceholder={t(\"folderTree.newFolderPlaceholder\")}\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t) : (\n\t\t\t\t<Flex\n\t\t\t\t\talign=\"center\"\n\t\t\t\t\tgap={1}\n\t\t\t\t\tpx={2}\n\t\t\t\t\tpy={1}\n\t\t\t\t\trounded=\"md\"\n\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t_hover={{ bg: \"bg.muted\" }}\n\t\t\t\t\tonClick={() => setIsCreating(true)}\n\t\t\t\t\tfontSize=\"sm\"\n\t\t\t\t>\n\t\t\t\t\t<FolderPlus size={14} />\n\t\t\t\t\t<Text>{t(\"folderTree.newFolder\")}</Text>\n\t\t\t\t</Flex>\n\t\t\t)}\n\n\t\t\t{/* Kept mounted while a subject exists (dialog machines must not\n\t\t\t unmount mid-exit, see collection-picker / #66). */}\n\t\t\t{moveSubject && (\n\t\t\t\t<MoveDialog\n\t\t\t\t\topen={moveOpen}\n\t\t\t\t\tonOpenChange={setMoveOpen}\n\t\t\t\t\tsubject={{ kind: \"folder\", folder: moveSubject }}\n\t\t\t\t\tonMoved={() => setTreeKey((k) => k + 1)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{accessSubject && (\n\t\t\t\t<ManageAccessDialog\n\t\t\t\t\topen={accessOpen}\n\t\t\t\t\tonOpenChange={setAccessOpen}\n\t\t\t\t\tsubject={{ kind: \"folder\", folder: accessSubject }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<RestrictedFolderDialog\n\t\t\t\topen={restrictedParentId !== null}\n\t\t\t\tparentId={restrictedParentId ?? \"\"}\n\t\t\t\tonClose={() => setRestrictedParentId(null)}\n\t\t\t\tonCreated={() => setTreeKey((k) => k + 1)}\n\t\t\t/>\n\t\t\t<LeakGuardRefusalDialog\n\t\t\t\trefusal={toggleRefusal}\n\t\t\t\topen={refusalOpen}\n\t\t\t\tonClose={() => setRefusalOpen(false)}\n\t\t\t/>\n\t\t</Flex>\n\t);\n};\nFolderTree.displayName = \"FolderTree\";\n","import { InlineEdit } from \"@knkcs/anker/forms\";\nimport { useState } from \"react\";\n\ninterface InlineEditFieldProps {\n\tvalue: string;\n\tonSave: (newValue: string) => Promise<void>;\n\tas?: \"input\" | \"textarea\";\n\tplaceholder?: string;\n}\n\n/**\n * Thin wrapper around anker's InlineEdit that adds async save with error handling.\n * On error, the value reverts to the previous value automatically.\n */\nexport const InlineEditField: React.FC<InlineEditFieldProps> = ({\n\tvalue,\n\tonSave,\n\tas = \"input\",\n\tplaceholder,\n}) => {\n\tconst [disabled, setDisabled] = useState(false);\n\n\tasync function handleSubmit(nextValue: string) {\n\t\tconst trimmed = nextValue.trim();\n\t\tif (trimmed === value) return;\n\t\tsetDisabled(true);\n\t\ttry {\n\t\t\tawait onSave(trimmed);\n\t\t} catch {\n\t\t\t// Error handling done by caller (toast); InlineEdit reverts on its own\n\t\t} finally {\n\t\t\tsetDisabled(false);\n\t\t}\n\t}\n\n\treturn (\n\t\t<InlineEdit\n\t\t\tvalue={value}\n\t\t\tonSubmit={handleSubmit}\n\t\t\tvariant={as}\n\t\t\tplaceholder={placeholder}\n\t\t\tdisabled={disabled}\n\t\t\tfontSize=\"sm\"\n\t\t/>\n\t);\n};\nInlineEditField.displayName = \"InlineEditField\";\n","import { toaster } from \"@knkcs/anker/primitives\";\nimport { SpecEditor } from \"@knkcs/fieldkit/editor\";\nimport { FieldKitProvider } from \"@knkcs/fieldkit/renderer\";\nimport { type Schema, builtInFieldTypes } from \"@knkcs/fieldkit/schema\";\nimport type React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useUpdateAssetType } from \"../hooks/use-asset-types\";\n\nexport interface MetadataSchemaEditorProps {\n\ttypeId: string;\n\t/**\n\t * The committed schema — SpecEditor's baseline. Content-equal re-parses on\n\t * background refetches are ignored by the editor's stability contract.\n\t */\n\tinitialSchema: Schema;\n\t/** Wire into the screen's unsaved-changes tab guard. */\n\tonDirtyChange?: (dirty: boolean) => void;\n}\n\n/**\n * The asset type's fieldkit metadata schema, edited on a page with room for it\n * (spec knkCS/mediahub#138, story 7) rather than as a JSON textarea.\n */\nexport const MetadataSchemaEditor: React.FC<MetadataSchemaEditorProps> = ({\n\ttypeId,\n\tinitialSchema,\n\tonDirtyChange,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst updateAssetType = useUpdateAssetType();\n\n\tasync function handleCommit(schema: Schema) {\n\t\t// No try/catch: a rejection must propagate to SpecEditor, which keeps\n\t\t// the draft dirty and shows its own saveFailed toast.\n\t\tawait updateAssetType.mutateAsync({\n\t\t\tid: typeId,\n\t\t\tpatch: { metadataSchema: JSON.stringify(schema) },\n\t\t});\n\t\ttoaster.success({ title: t(\"assetTypeDetail.schemaSavedToast\") });\n\t}\n\n\treturn (\n\t\t<FieldKitProvider plugins={builtInFieldTypes}>\n\t\t\t<SpecEditor\n\t\t\t\tschema={initialSchema}\n\t\t\t\tonCommit={handleCommit}\n\t\t\t\tonDirtyChange={onDirtyChange}\n\t\t\t\tplugins={builtInFieldTypes}\n\t\t\t/>\n\t\t</FieldKitProvider>\n\t);\n};\nMetadataSchemaEditor.displayName = \"MetadataSchemaEditor\";\n","import { ChipPicker } from \"@knkcs/anker/components\";\nimport { useTranslation } from \"react-i18next\";\nimport { useTagAssets, useTags, useUntagAssets } from \"../hooks/use-tags\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { TagInfo } from \"../types\";\n\ninterface TagChipFieldProps {\n\tassetId: string;\n\tassignedTagIds: string[];\n}\n\nexport const TagChipField: React.FC<TagChipFieldProps> = ({\n\tassetId,\n\tassignedTagIds,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst tagsQuery = useTags();\n\tconst allTags: TagInfo[] = tagsQuery.data ?? [];\n\tconst tagAssets = useTagAssets();\n\tconst untagAssets = useUntagAssets();\n\n\tconst assignedTags = allTags.filter((tag) => assignedTagIds.includes(tag.id));\n\tconst unassignedTags = allTags.filter(\n\t\t(tag) => !assignedTagIds.includes(tag.id),\n\t);\n\n\tasync function handleAdd(tag: TagInfo) {\n\t\ttry {\n\t\t\tawait tagAssets.mutateAsync({ tagId: tag.id, assetIds: [assetId] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"tagChipField.errorToast\"));\n\t\t}\n\t}\n\n\tasync function handleRemove(tag: TagInfo) {\n\t\ttry {\n\t\t\tawait untagAssets.mutateAsync({ tagId: tag.id, assetIds: [assetId] });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"tagChipField.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<ChipPicker<TagInfo>\n\t\t\tassigned={assignedTags}\n\t\t\tavailable={unassignedTags}\n\t\t\tgetItemId={(tag) => tag.id}\n\t\t\tgetItemLabel={(tag) => tag.name}\n\t\t\tonAdd={handleAdd}\n\t\t\tonRemove={handleRemove}\n\t\t\taddLabel={t(\"tagChipField.addLabel\")}\n\t\t\temptyLabel={t(\"tagChipField.emptyLabel\")}\n\t\t\tsearchable\n\t\t\tloading={tagsQuery.isLoading}\n\t\t/>\n\t);\n};\nTagChipField.displayName = \"TagChipField\";\n","import { InlineCreatableList } from \"@knkcs/anker/components\";\nimport { toaster } from \"@knkcs/anker/primitives\";\nimport { useTranslation } from \"react-i18next\";\nimport { useCreateTag, useTags } from \"../hooks/use-tags\";\nimport { showRpcErrorToast } from \"../lib/rpc-errors\";\nimport type { TagInfo } from \"../types\";\n\ninterface TagPanelProps {\n\tactiveTags: string[];\n\tonToggleTag: (tagId: string) => void;\n}\n\nexport const TagPanel: React.FC<TagPanelProps> = ({\n\tactiveTags,\n\tonToggleTag,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst tagsQuery = useTags();\n\tconst tags: TagInfo[] = tagsQuery.data ?? [];\n\tconst createTag = useCreateTag();\n\n\tasync function handleCreate(name: string) {\n\t\ttry {\n\t\t\tawait createTag.mutateAsync({\n\t\t\t\tname,\n\t\t\t\tslug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"tagPanel.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"tagPanel.errorToast\"));\n\t\t}\n\t}\n\n\treturn (\n\t\t<InlineCreatableList<TagInfo>\n\t\t\titems={tags}\n\t\t\tactiveIds={activeTags}\n\t\t\tonToggle={onToggleTag}\n\t\t\tonCreate={handleCreate}\n\t\t\tgetItemId={(tag) => tag.id}\n\t\t\tgetItemLabel={(tag) => tag.name}\n\t\t\tvariant=\"wrap\"\n\t\t\tcreatePlaceholder={t(\"tagPanel.createPlaceholder\")}\n\t\t\tcreateLabel={t(\"tagPanel.createLabel\")}\n\t\t\temptyText={t(\"tagPanel.emptyText\")}\n\t\t/>\n\t);\n};\nTagPanel.displayName = \"TagPanel\";\n","import { Modal } from \"@knkcs/anker/components\";\nimport {\n\tBox,\n\tCheckbox,\n\tFlex,\n\tNativeSelect,\n\tText,\n} from \"@knkcs/anker/primitives\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useAssetTypes } from \"../../hooks/use-asset-types\";\nimport { useWorkspaceId } from \"../../provider\";\nimport type { UploadFile } from \"../../stores/upload-store\";\nimport { useUploadStore } from \"../../stores/upload-store\";\n\ninterface UploadDialogProps {\n\topen: boolean;\n\tonClose: () => void;\n\tfolderId?: string;\n}\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nconst FileRow: React.FC<{\n\tentry: UploadFile;\n\tshowOverride: boolean;\n\tonToggleOverride: () => void;\n\tassetTypes: { id: string; name: string }[];\n}> = ({ entry, showOverride, onToggleOverride, assetTypes }) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst setAssetType = useUploadStore((s) => s.setAssetType);\n\n\treturn (\n\t\t<Flex\n\t\t\tpy={2.5}\n\t\t\tpx={3}\n\t\t\talign=\"center\"\n\t\t\tborderBottomWidth=\"1px\"\n\t\t\tborderColor=\"border\"\n\t\t\t_last={{ borderBottomWidth: 0 }}\n\t\t\tgap={3}\n\t\t>\n\t\t\t<Box flex={1} minW={0}>\n\t\t\t\t<Text fontSize=\"sm\" truncate>\n\t\t\t\t\t{entry.file.name}\n\t\t\t\t</Text>\n\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t{formatFileSize(entry.file.size)}\n\t\t\t\t</Text>\n\t\t\t</Box>\n\n\t\t\t{showOverride ? (\n\t\t\t\t<NativeSelect\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tvalue={entry.assetTypeId}\n\t\t\t\t\tonChange={(e) => setAssetType(entry.clientId, e.target.value)}\n\t\t\t\t\tw=\"160px\"\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">{t(\"uploadDialog.selectType\")}</option>\n\t\t\t\t\t{assetTypes.map((type) => (\n\t\t\t\t\t\t<option key={type.id} value={type.id}>\n\t\t\t\t\t\t\t{type.name}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</NativeSelect>\n\t\t\t) : (\n\t\t\t\t<Text\n\t\t\t\t\tfontSize=\"xs\"\n\t\t\t\t\tcolor=\"colorPalette.fg\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tcursor=\"pointer\"\n\t\t\t\t\t_hover={{ textDecoration: \"underline\" }}\n\t\t\t\t\tonClick={onToggleOverride}\n\t\t\t\t>\n\t\t\t\t\t{t(\"uploadDialog.changeType\")}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</Flex>\n\t);\n};\nFileRow.displayName = \"FileRow\";\n\nexport const UploadDialog: React.FC<UploadDialogProps> = ({\n\topen,\n\tonClose,\n\tfolderId,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst workspaceId = useWorkspaceId();\n\tconst files = useUploadStore((s) => s.files);\n\tconst setBatchAssetType = useUploadStore((s) => s.setBatchAssetType);\n\tconst startUpload = useUploadStore((s) => s.startUpload);\n\tconst clearPending = useUploadStore((s) => s.clearPending);\n\tconst analyzeWithAi = useUploadStore((s) => s.analyzeWithAi);\n\tconst setAnalyzeWithAi = useUploadStore((s) => s.setAnalyzeWithAi);\n\tconst assetTypesQuery = useAssetTypes();\n\tconst assetTypes = assetTypesQuery.data ?? [];\n\tconst [batchType, setBatchType] = useState(\"\");\n\tconst [overrides, setOverrides] = useState<Set<string>>(new Set());\n\n\tconst pendingFiles = files.filter((f) => f.status === \"pending\");\n\n\tfunction handleBatchTypeChange(value: string) {\n\t\tsetBatchType(value);\n\t\tsetBatchAssetType(value);\n\t}\n\n\tfunction toggleOverride(clientId: string) {\n\t\tsetOverrides((prev) => {\n\t\t\tconst next = new Set(prev);\n\t\t\tif (next.has(clientId)) {\n\t\t\t\tnext.delete(clientId);\n\t\t\t} else {\n\t\t\t\tnext.add(clientId);\n\t\t\t}\n\t\t\treturn next;\n\t\t});\n\t}\n\n\tconst canUpload =\n\t\tpendingFiles.length > 0 && pendingFiles.every((f) => f.assetTypeId !== \"\");\n\n\tfunction handleUpload() {\n\t\tstartUpload(workspaceId, folderId);\n\t\tonClose();\n\t\tsetBatchType(\"\");\n\t\tsetOverrides(new Set());\n\t}\n\n\tfunction handleCancel() {\n\t\tclearPending();\n\t\tonClose();\n\t}\n\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tonClose={handleCancel}\n\t\t\theader={t(\"uploadDialog.header\", { count: pendingFiles.length })}\n\t\t\tsaveLabel={t(\"uploadDialog.uploadButton\")}\n\t\t\tonSave={handleUpload}\n\t\t\tsaveDisabled={!canUpload}\n\t\t>\n\t\t\t{/* Batch asset type selector */}\n\t\t\t<Box mb={4}>\n\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" mb={2}>\n\t\t\t\t\t{t(\"uploadDialog.assetTypeLabel\")}\n\t\t\t\t</Text>\n\t\t\t\t<NativeSelect\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tvalue={batchType}\n\t\t\t\t\tonChange={(e) => handleBatchTypeChange(e.target.value)}\n\t\t\t\t>\n\t\t\t\t\t<option value=\"\">{t(\"uploadDialog.selectAssetType\")}</option>\n\t\t\t\t\t{assetTypes.map((type) => (\n\t\t\t\t\t\t<option key={type.id} value={type.id}>\n\t\t\t\t\t\t\t{type.name}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</NativeSelect>\n\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\" mt={1}>\n\t\t\t\t\t{t(\"uploadDialog.assetTypeHint\")}\n\t\t\t\t</Text>\n\t\t\t</Box>\n\n\t\t\t{/* AI analysis toggle */}\n\t\t\t<Box mb={4}>\n\t\t\t\t<Checkbox\n\t\t\t\t\tchecked={analyzeWithAi}\n\t\t\t\t\tonCheckedChange={(e) => setAnalyzeWithAi(!!e.checked)}\n\t\t\t\t>\n\t\t\t\t\t{t(\"uploadDialog.analyzeWithAi\")}\n\t\t\t\t</Checkbox>\n\t\t\t</Box>\n\n\t\t\t{/* File list */}\n\t\t\t<Box\n\t\t\t\tborderWidth=\"1px\"\n\t\t\t\tborderColor=\"border\"\n\t\t\t\trounded=\"md\"\n\t\t\t\tmaxH=\"300px\"\n\t\t\t\toverflowY=\"auto\"\n\t\t\t>\n\t\t\t\t{pendingFiles.map((entry) => (\n\t\t\t\t\t<FileRow\n\t\t\t\t\t\tkey={entry.clientId}\n\t\t\t\t\t\tentry={entry}\n\t\t\t\t\t\tshowOverride={overrides.has(entry.clientId)}\n\t\t\t\t\t\tonToggleOverride={() => toggleOverride(entry.clientId)}\n\t\t\t\t\t\tassetTypes={assetTypes}\n\t\t\t\t\t/>\n\t\t\t\t))}\n\t\t\t</Box>\n\t\t</Modal>\n\t);\n};\nUploadDialog.displayName = \"UploadDialog\";\n","import { UploadDropZone as AnkerUploadDropZone } from \"@knkcs/anker/components\";\n\ninterface UploadDropZoneProps {\n\tonFilesSelected: (files: File[]) => void;\n\tcompact?: boolean;\n}\n\nexport const UploadDropZone: React.FC<UploadDropZoneProps> = ({\n\tonFilesSelected,\n\tcompact,\n}) => {\n\treturn (\n\t\t<AnkerUploadDropZone onFiles={onFilesSelected} compact={compact} multiple />\n\t);\n};\nUploadDropZone.displayName = \"UploadDropZone\";\n","import type { UploadFileStatus } from \"@knkcs/anker/feedback\";\nimport { UploadToastStack as AnkerUploadToastStack } from \"@knkcs/anker/feedback\";\nimport { useUploadStore } from \"../../stores/upload-store\";\n\n/** Map Zustand upload store statuses to anker's UploadFileStatus format. */\nfunction mapStatus(status: string): UploadFileStatus[\"status\"] {\n\tswitch (status) {\n\t\tcase \"done\":\n\t\t\treturn \"done\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tcase \"uploading\":\n\t\t\treturn \"uploading\";\n\t\tcase \"creating\":\n\t\tcase \"finalizing\":\n\t\t\treturn \"processing\";\n\t\tdefault:\n\t\t\treturn \"pending\";\n\t}\n}\n\nexport const UploadToastStack: React.FC = () => {\n\tconst storeFiles = useUploadStore((s) => s.files);\n\tconst visible = useUploadStore((s) => s.visible);\n\tconst dismiss = useUploadStore((s) => s.dismiss);\n\n\tconst files: UploadFileStatus[] = storeFiles.map((f) => ({\n\t\tid: f.clientId,\n\t\tfilename: f.file.name,\n\t\tstatus: mapStatus(f.status),\n\t\tprogress: f.progress,\n\t\terror: f.error,\n\t}));\n\n\tif (!visible || files.length === 0) return null;\n\n\treturn (\n\t\t<AnkerUploadToastStack\n\t\t\tfiles={files}\n\t\t\tonDismiss={dismiss}\n\t\t\tautoDismissMs={5000}\n\t\t\tdefaultExpanded\n\t\t/>\n\t);\n};\nUploadToastStack.displayName = \"UploadToastStack\";\n","import type { AssetInfo, AssetTypeInfo } from \"./types\";\n\n/** Build an asset-type id -> display name map from the workspace's types. */\nexport function buildAssetTypeNameMap(\n\ttypes: AssetTypeInfo[],\n): Map<string, string> {\n\treturn new Map(types.map((t) => [t.id, t.name]));\n}\n\n/** Collect the unique, non-empty `updatedBy` user ids across the given assets. */\nexport function collectUpdatedByIds(assets: AssetInfo[]): string[] {\n\treturn [...new Set(assets.map((a) => a.updatedBy).filter(Boolean))];\n}\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport {\n\tActionCell,\n\tContextRail,\n\tDataTable,\n\tDateCell,\n\tToolbar,\n\tTruncatedTextCell,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBox,\n\tFlex,\n\tNativeSelect,\n\tSegmentedControl,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport {\n\tIndexPageTemplate,\n\tSubNavLayout,\n\tusePageRail,\n} from \"@knkcs/anker/templates\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport type {\n\tColumnDef,\n\tOnChangeFn,\n\tRowSelectionState,\n} from \"@tanstack/react-table\";\nimport type { TFunction } from \"i18next\";\nimport { Download, Trash2, Upload } from \"lucide-react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport {\n\tbuildAssetTypeNameMap,\n\tcollectUpdatedByIds,\n} from \"./asset-library-resolve\";\nimport {\n\ttype ActiveFilterChip,\n\tActiveFilterChips,\n} from \"./components/active-filter-chips\";\nimport { AssetGrid } from \"./components/asset-grid\";\nimport { AssetStatusBadge } from \"./components/asset-status-badge\";\nimport { BulkActionBar } from \"./components/bulk-action-bar\";\nimport { CollectionPanel } from \"./components/collection-panel\";\nimport { FolderBreadcrumbs } from \"./components/folder-breadcrumbs\";\nimport { FolderTree } from \"./components/folder-tree\";\nimport { TagPanel } from \"./components/tag-panel\";\nimport { UploadDialog } from \"./components/upload/upload-dialog\";\nimport { UploadDropZone } from \"./components/upload/upload-drop-zone\";\nimport { useAssetTypes } from \"./hooks/use-asset-types\";\nimport { useAssets, useDeleteAsset } from \"./hooks/use-assets\";\nimport { useCollections } from \"./hooks/use-collections\";\nimport { useFolder } from \"./hooks/use-folders\";\nimport { useTags } from \"./hooks/use-tags\";\nimport { useUsers } from \"./hooks/use-users\";\nimport {\n\tdescribeRpcError,\n\tisRetryableUnavailable,\n\tshowRpcErrorToast,\n} from \"./lib/rpc-errors\";\nimport { useAssetStatuses } from \"./statushub\";\nimport { usePreferencesStore } from \"./stores/preferences-store\";\nimport { useSelectionStore } from \"./stores/selection-store\";\nimport { useUploadStore } from \"./stores/upload-store\";\nimport type { AssetFilters, AssetInfo, AssetStatusBehavior } from \"./types\";\n\n// The behavior list is mediahub's own — the words it registers with statushub\n// (integration standard §1, statushub ADR 0002), which the server validates\n// this filter against. It stays local rather than coming from\n// statushub-ui's `useEntityType` because that hook reads\n// ServiceRegistryService, which the standalone shell's proxy deliberately does\n// NOT forward: the registry is unauthenticated by design and stays in-cluster.\n// Keep it in step with `AssetBehaviors()` in internal/service/statushub.go.\nfunction behaviorOptions(\n\tt: TFunction,\n): { label: string; value: AssetStatusBehavior | \"\" }[] {\n\treturn [\n\t\t{ label: t(\"assetLibrary.behaviorAll\"), value: \"\" },\n\t\t{ label: t(\"assetLibrary.behaviorActive\"), value: \"active\" },\n\t\t{ label: t(\"assetLibrary.behaviorArchived\"), value: \"archived\" },\n\t\t{ label: t(\"assetLibrary.behaviorInactive\"), value: \"inactive\" },\n\t\t{ label: t(\"assetLibrary.behaviorDeleted\"), value: \"deleted\" },\n\t];\n}\n\nfunction viewModeOptions(t: TFunction) {\n\treturn [\n\t\t{ label: t(\"assetLibrary.viewModeList\"), value: \"list\" },\n\t\t{ label: t(\"assetLibrary.viewModeGrid\"), value: \"grid\" },\n\t];\n}\n\n// Stable identity for \"no tag filter\": `filters.tagIds ?? []` would mint a\n// fresh array every render, invalidating the rail memo (and every callback\n// keyed on activeTags) even when nothing changed.\nconst NO_ACTIVE_TAGS: string[] = [];\n\n// Same reason, for \"the status catalogue has not answered yet\": the chip row\n// memoises on it, and a fresh `[]` per render would rebuild the chips on every\n// render while statushub is still loading.\nconst NO_STATUS_OPTIONS: NonNullable<\n\tReturnType<typeof useAssetStatuses>[\"data\"]\n> = [];\n\nexport interface AssetLibraryProps {\n\tonAssetOpen?: (asset: AssetInfo) => void;\n\tinitialFilters?: AssetFilters;\n\tonFiltersChange?: (filters: AssetFilters) => void;\n}\n\nexport function AssetLibrary(props: AssetLibraryProps): React.JSX.Element {\n\tconst { onAssetOpen, initialFilters, onFiltersChange } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst [filters, setFilters] = useState<AssetFilters>(initialFilters ?? {});\n\tconst [uploadDialogOpen, setUploadDialogOpen] = useState(false);\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\n\t// Derived filter shorthands for convenience\n\tconst statusSlug = filters.statusSlug ?? \"\";\n\tconst behaviorFilter: AssetStatusBehavior | \"\" = filters.behavior ?? \"\";\n\tconst folderId = filters.folderId ?? \"\";\n\tconst activeTags = filters.tagIds ?? NO_ACTIVE_TAGS;\n\tconst activeCollectionId = filters.collectionIds?.[0] ?? \"\";\n\n\tconst updateFilter = useCallback(\n\t\t<K extends keyof AssetFilters>(key: K, value: AssetFilters[K]) => {\n\t\t\tsetFilters((prev) => {\n\t\t\t\tconst next: AssetFilters = { ...prev };\n\t\t\t\tif (\n\t\t\t\t\tvalue === undefined ||\n\t\t\t\t\tvalue === \"\" ||\n\t\t\t\t\t(Array.isArray(value) && value.length === 0)\n\t\t\t\t) {\n\t\t\t\t\tdelete next[key];\n\t\t\t\t} else {\n\t\t\t\t\tnext[key] = value;\n\t\t\t\t}\n\t\t\t\tonFiltersChange?.(next);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\t[onFiltersChange],\n\t);\n\n\t// Local search text kept controlled for immediate input feedback, debounced\n\t// into the filter (and therefore the useAssets query) so we don't refetch on\n\t// every keystroke — preserves the old SearchInput debounce behaviour.\n\tconst [searchText, setSearchText] = useState(initialFilters?.search ?? \"\");\n\tconst searchPrimed = useRef(false);\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: debounce on searchText only\n\tuseEffect(() => {\n\t\tif (!searchPrimed.current) {\n\t\t\tsearchPrimed.current = true;\n\t\t\treturn;\n\t\t}\n\t\tconst timer = setTimeout(\n\t\t\t() => updateFilter(\"search\", searchText || undefined),\n\t\t\t300,\n\t\t);\n\t\treturn () => clearTimeout(timer);\n\t}, [searchText]);\n\n\t// Clearing everything is one write to the one filter state the panels also\n\t// write — the chips can never disagree with the rail, because there is\n\t// nothing to disagree with. The search box is local to the toolbar, so it\n\t// is emptied alongside; its debounce then commits the same empty filter.\n\tconst clearAllFilters = useCallback(() => {\n\t\tsetSearchText(\"\");\n\t\tsetFilters(() => {\n\t\t\tconst next: AssetFilters = {};\n\t\t\tonFiltersChange?.(next);\n\t\t\treturn next;\n\t\t});\n\t}, [onFiltersChange]);\n\n\tconst handleToggleTag = useCallback(\n\t\t(tagId: string) => {\n\t\t\tconst next = activeTags.includes(tagId)\n\t\t\t\t? activeTags.filter((id) => id !== tagId)\n\t\t\t\t: [...activeTags, tagId];\n\t\t\tupdateFilter(\"tagIds\", next.length > 0 ? next : undefined);\n\t\t},\n\t\t[activeTags, updateFilter],\n\t);\n\n\tconst handleSelectCollection = useCallback(\n\t\t(collectionId: string) => {\n\t\t\tupdateFilter(\"collectionIds\", collectionId ? [collectionId] : undefined);\n\t\t},\n\t\t[updateFilter],\n\t);\n\n\tfunction setStatusSlug(value: string) {\n\t\tupdateFilter(\"statusSlug\", value || undefined);\n\t}\n\n\tfunction setBehaviorFilter(value: string) {\n\t\tupdateFilter(\n\t\t\t\"behavior\",\n\t\t\tvalue ? (value as AssetStatusBehavior) : undefined,\n\t\t);\n\t}\n\n\tconst addFiles = useUploadStore((s) => s.addFiles);\n\tconst viewMode = usePreferencesStore((s) => s.viewMode);\n\tconst setViewMode = usePreferencesStore((s) => s.setViewMode);\n\n\tconst handleFilesSelected = useCallback(\n\t\t(files: File[]) => {\n\t\t\taddFiles(files);\n\t\t\tsetUploadDialogOpen(true);\n\t\t},\n\t\t[addFiles],\n\t);\n\n\tconst deleteAsset = useDeleteAsset();\n\tconst { confirm } = useConfirmModal();\n\n\tasync function handleDelete(assetId: string, assetName: string) {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"assetLibrary.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"assetLibrary.deleteConfirmMessage\", { assetName }),\n\t\t\tconfirmLabel: t(\"assetLibrary.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteAsset.mutateAsync(assetId);\n\t\t\ttoaster.success({ title: t(\"assetLibrary.deleteSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetLibrary.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tconst assetsQuery = useAssets({\n\t\tfolderId: folderId || undefined,\n\t\tstatusSlug: statusSlug || undefined,\n\t\tbehavior: behaviorFilter || undefined,\n\t\tsearch: filters.search || undefined,\n\t\ttagIds: activeTags.length > 0 ? activeTags : undefined,\n\t\tcollectionIds: activeCollectionId ? [activeCollectionId] : undefined,\n\t});\n\n\t// The filter's options are the workspace's own catalogue, read from\n\t// statushub (integration standard §10) — the order statushub answers in.\n\tconst statusOptions = useAssetStatuses().data ?? NO_STATUS_OPTIONS;\n\tconst assets: AssetInfo[] = assetsQuery.data?.items ?? [];\n\n\t// The chips name what is applied, in words. Every id is resolved through\n\t// the data the panels already load — the same TanStack Query entries the\n\t// rail's `TagPanel` and `CollectionPanel` read, and the one the folder\n\t// breadcrumbs read — so nothing is fetched twice and no chip ever carries\n\t// an id. An id that resolves to nothing (a row deleted, or a host deep\n\t// link into something this workspace cannot see) still narrows the query,\n\t// so it still gets a chip: named by its kind rather than by its id.\n\tconst activeFolder = useFolder(folderId).data;\n\tconst allTags = useTags().data;\n\tconst allCollections = useCollections().data;\n\n\tconst filterChips = useMemo<ActiveFilterChip[]>(() => {\n\t\tconst chips: ActiveFilterChip[] = [];\n\t\tif (folderId) {\n\t\t\tchips.push({\n\t\t\t\tid: \"folder\",\n\t\t\t\tlabel: activeFolder\n\t\t\t\t\t? t(\"assetLibrary.chipFolder\", { name: activeFolder.name })\n\t\t\t\t\t: t(\"assetLibrary.chipFolderUnresolved\"),\n\t\t\t\tonRemove: () => updateFilter(\"folderId\", undefined),\n\t\t\t});\n\t\t}\n\t\tif (activeCollectionId) {\n\t\t\tconst collection = allCollections?.find(\n\t\t\t\t(c) => c.id === activeCollectionId,\n\t\t\t);\n\t\t\tchips.push({\n\t\t\t\tid: `collection:${activeCollectionId}`,\n\t\t\t\tlabel: collection\n\t\t\t\t\t? t(\"assetLibrary.chipCollection\", { name: collection.name })\n\t\t\t\t\t: t(\"assetLibrary.chipCollectionUnresolved\"),\n\t\t\t\tonRemove: () => handleSelectCollection(\"\"),\n\t\t\t});\n\t\t}\n\t\tfor (const tagId of activeTags) {\n\t\t\tconst tag = allTags?.find((candidate) => candidate.id === tagId);\n\t\t\tchips.push({\n\t\t\t\tid: `tag:${tagId}`,\n\t\t\t\tlabel: tag\n\t\t\t\t\t? t(\"assetLibrary.chipTag\", { name: tag.name })\n\t\t\t\t\t: t(\"assetLibrary.chipTagUnresolved\"),\n\t\t\t\tonRemove: () => handleToggleTag(tagId),\n\t\t\t});\n\t\t}\n\t\tif (statusSlug) {\n\t\t\t// A slug is the workspace's own word, not an id — so it is a\n\t\t\t// readable last resort while the catalogue is still answering.\n\t\t\tconst status = statusOptions.find((s) => s.slug === statusSlug);\n\t\t\tchips.push({\n\t\t\t\tid: \"status\",\n\t\t\t\tlabel: t(\"assetLibrary.chipStatus\", {\n\t\t\t\t\tname: status?.name ?? statusSlug,\n\t\t\t\t}),\n\t\t\t\tonRemove: () => updateFilter(\"statusSlug\", undefined),\n\t\t\t});\n\t\t}\n\t\tif (behaviorFilter) {\n\t\t\tconst option = behaviorOptions(t).find((o) => o.value === behaviorFilter);\n\t\t\tchips.push({\n\t\t\t\tid: \"behavior\",\n\t\t\t\tlabel: t(\"assetLibrary.chipStatusGroup\", {\n\t\t\t\t\tname: option?.label ?? behaviorFilter,\n\t\t\t\t}),\n\t\t\t\tonRemove: () => updateFilter(\"behavior\", undefined),\n\t\t\t});\n\t\t}\n\t\tif (filters.search) {\n\t\t\tchips.push({\n\t\t\t\tid: \"search\",\n\t\t\t\tlabel: t(\"assetLibrary.chipSearch\", { term: filters.search }),\n\t\t\t\tonRemove: () => {\n\t\t\t\t\tsetSearchText(\"\");\n\t\t\t\t\tupdateFilter(\"search\", undefined);\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t\treturn chips;\n\t}, [\n\t\tfolderId,\n\t\tactiveFolder,\n\t\tactiveCollectionId,\n\t\tallCollections,\n\t\tactiveTags,\n\t\tallTags,\n\t\tstatusSlug,\n\t\tstatusOptions,\n\t\tbehaviorFilter,\n\t\tfilters.search,\n\t\thandleSelectCollection,\n\t\thandleToggleTag,\n\t\tupdateFilter,\n\t\tt,\n\t]);\n\n\t// An empty grid under four filters is not an empty library, and saying so\n\t// is the difference between \"this is broken\" and \"widen the search\".\n\tconst noAssetsState =\n\t\tfilterChips.length > 0 ? (\n\t\t\t<EmptyState\n\t\t\t\theader={t(\"assetLibrary.noAssetsMatchFilters\")}\n\t\t\t\tdescription={t(\"assetLibrary.noAssetsMatchFiltersDescription\")}\n\t\t\t\tactions={\n\t\t\t\t\t<Button size=\"sm\" onClick={clearAllFilters}>\n\t\t\t\t\t\t{t(\"assetLibrary.clearAllFilters\")}\n\t\t\t\t\t</Button>\n\t\t\t\t}\n\t\t\t/>\n\t\t) : (\n\t\t\t<EmptyState header={t(\"assetLibrary.noAssetsFound\")} />\n\t\t);\n\n\t// A failed listing must SAY so. `assetsQuery.data?.items ?? []` alone would\n\t// render \"No assets found\" over a refusal — which is the false answer the\n\t// server refused to give, arriving through the UI's door instead\n\t// (knkCS/mediahub#120). The behavior filter is the one read the server\n\t// refuses while statushub is unreachable, and the reader clears it by\n\t// dropping the filter, so that is the action offered.\n\tconst listFailure = assetsQuery.isError ? assetsQuery.error : undefined;\n\tconst listFailureState = listFailure ? (\n\t\tisRetryableUnavailable(listFailure) && behaviorFilter ? (\n\t\t\t<EmptyState\n\t\t\t\theader={t(\"assetLibrary.statusesUnavailableHeader\")}\n\t\t\t\tdescription={t(\"assetLibrary.statusesUnavailableDescription\")}\n\t\t\t\tactions={\n\t\t\t\t\t<Button size=\"sm\" onClick={() => setBehaviorFilter(\"\")}>\n\t\t\t\t\t\t{t(\"assetLibrary.clearStatusGroup\")}\n\t\t\t\t\t</Button>\n\t\t\t\t}\n\t\t\t/>\n\t\t) : (\n\t\t\t<EmptyState\n\t\t\t\theader={t(\"assetLibrary.assetsLoadFailedHeader\")}\n\t\t\t\tdescription={\n\t\t\t\t\tdescribeRpcError(\n\t\t\t\t\t\tlistFailure,\n\t\t\t\t\t\tt(\"assetLibrary.assetsLoadFailedHeader\"),\n\t\t\t\t\t).description\n\t\t\t\t}\n\t\t\t/>\n\t\t)\n\t) : undefined;\n\n\tconst assetTypesQuery = useAssetTypes();\n\tconst typeNames = useMemo(\n\t\t() => buildAssetTypeNameMap(assetTypesQuery.data ?? []),\n\t\t[assetTypesQuery.data],\n\t);\n\tconst updatedByIds = useMemo(() => collectUpdatedByIds(assets), [assets]);\n\tconst { data: userNames } = useUsers(updatedByIds);\n\n\tconst selectedIds = useSelectionStore((s) => s.selectedIds);\n\tconst setSelection = useSelectionStore((s) => s.setSelection);\n\n\t// Bridge Zustand selection <-> DataTable rowSelection\n\tconst rowSelection = useMemo(() => {\n\t\tconst sel: RowSelectionState = {};\n\t\tfor (const id of selectedIds) sel[id] = true;\n\t\treturn sel;\n\t}, [selectedIds]);\n\n\tconst handleRowSelectionChange: OnChangeFn<RowSelectionState> = useCallback(\n\t\t(updater) => {\n\t\t\tconst current: RowSelectionState = {};\n\t\t\tfor (const id of useSelectionStore.getState().selectedIds)\n\t\t\t\tcurrent[id] = true;\n\t\t\tconst next = typeof updater === \"function\" ? updater(current) : updater;\n\t\t\tsetSelection(Object.keys(next).filter((k) => next[k]));\n\t\t},\n\t\t[setSelection],\n\t);\n\n\t// Clear selection when filters change\n\tconst filtersKey = JSON.stringify(filters);\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: trigger on filters change\n\tuseEffect(() => {\n\t\tuseSelectionStore.getState().clearSelection();\n\t}, [filtersKey]);\n\n\t// DataTable columns for list view\n\tconst columnHelper = createColumnHelper<AssetInfo>();\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: columnHelper is stable, handleDelete is intentionally excluded\n\tconst listColumns = useMemo(\n\t\t() =>\n\t\t\t[\n\t\t\t\tcolumnHelper.accessor(\"name\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnName\"),\n\t\t\t\t\tcell: (info) => <TruncatedTextCell value={info.getValue()} />,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"assetTypeId\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnType\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<Text color=\"fg.muted\">\n\t\t\t\t\t\t\t{typeNames.get(info.getValue()) ?? info.getValue()}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"statusSlug\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnStatus\"),\n\t\t\t\t\tcell: (info) => <AssetStatusBadge slug={info.getValue()} />,\n\t\t\t\t\tenableSorting: false,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"updatedAt\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnUpdated\"),\n\t\t\t\t\tcell: (info) => {\n\t\t\t\t\t\tconst date = info.getValue();\n\t\t\t\t\t\treturn <DateCell value={date ?? null} showRelative />;\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"updatedBy\", {\n\t\t\t\t\theader: t(\"assetLibrary.columnUpdatedBy\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<Text color=\"fg.muted\">\n\t\t\t\t\t\t\t{userNames?.[info.getValue()] ?? info.getValue()}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: \"actions\",\n\t\t\t\t\tcell: (info) => {\n\t\t\t\t\t\tconst asset = info.row.original;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ActionCell\n\t\t\t\t\t\t\t\tactions={[\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ticon: Download,\n\t\t\t\t\t\t\t\t\t\tlabel: t(\"assetLibrary.actionDownload\"),\n\t\t\t\t\t\t\t\t\t\tonClick: () => {},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ticon: Trash2,\n\t\t\t\t\t\t\t\t\t\tlabel: t(\"assetLibrary.actionDelete\"),\n\t\t\t\t\t\t\t\t\t\tonClick: () => handleDelete(asset.id, asset.name),\n\t\t\t\t\t\t\t\t\t\tcolorPalette: \"red\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t] as ColumnDef<AssetInfo, unknown>[],\n\t\t[typeNames, userNames, t],\n\t);\n\n\t// Right rail — independently-collapsible upload / tags / collections sections.\n\t// Memoised so search/filter keystrokes don't re-push the slot and bounce an\n\t// extra AppShell render; recomputes only when the rail's own inputs change.\n\tconst rail = useMemo(\n\t\t() => (\n\t\t\t<ContextRail storageKey=\"asset-library-rail\">\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"upload\"\n\t\t\t\t\tlabel={t(\"assetLibrary.uploadSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<UploadDropZone onFilesSelected={handleFilesSelected} compact />\n\t\t\t\t</ContextRail.Section>\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"tags\"\n\t\t\t\t\tlabel={t(\"assetLibrary.tagsSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<TagPanel activeTags={activeTags} onToggleTag={handleToggleTag} />\n\t\t\t\t</ContextRail.Section>\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"collections\"\n\t\t\t\t\tlabel={t(\"assetLibrary.collectionsSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<CollectionPanel\n\t\t\t\t\t\tactiveCollectionId={activeCollectionId}\n\t\t\t\t\t\tonSelectCollection={handleSelectCollection}\n\t\t\t\t\t/>\n\t\t\t\t</ContextRail.Section>\n\t\t\t</ContextRail>\n\t\t),\n\t\t[\n\t\t\tactiveTags,\n\t\t\tactiveCollectionId,\n\t\t\thandleFilesSelected,\n\t\t\thandleToggleTag,\n\t\t\thandleSelectCollection,\n\t\t\tt,\n\t\t],\n\t);\n\tusePageRail(rail);\n\n\t// Toolbar swaps for the BulkActionBar while rows are selected.\n\tconst toolbar =\n\t\tselectedIds.length > 0 ? (\n\t\t\t<BulkActionBar />\n\t\t) : (\n\t\t\t<Toolbar>\n\t\t\t\t<Toolbar.Search\n\t\t\t\t\tplaceholder={t(\"assetLibrary.searchPlaceholder\")}\n\t\t\t\t\tvalue={searchText}\n\t\t\t\t\tonChange={setSearchText}\n\t\t\t\t/>\n\t\t\t\t<Toolbar.Filters>\n\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvalue={statusSlug}\n\t\t\t\t\t\tonChange={(e) => setStatusSlug(e.target.value ?? \"\")}\n\t\t\t\t\t>\n\t\t\t\t\t\t<option value=\"\">{t(\"assetLibrary.statusFilterAll\")}</option>\n\t\t\t\t\t\t{statusOptions.map((s) => (\n\t\t\t\t\t\t\t<option key={s.id} value={s.slug}>\n\t\t\t\t\t\t\t\t{s.name}\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t<SegmentedControl\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvalue={behaviorFilter}\n\t\t\t\t\t\tonValueChange={(details) => setBehaviorFilter(details.value ?? \"\")}\n\t\t\t\t\t\titems={behaviorOptions(t)}\n\t\t\t\t\t/>\n\t\t\t\t</Toolbar.Filters>\n\t\t\t\t<Toolbar.Right>\n\t\t\t\t\t<SegmentedControl\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvalue={viewMode}\n\t\t\t\t\t\tonValueChange={(details) =>\n\t\t\t\t\t\t\tsetViewMode(details.value as \"list\" | \"grid\")\n\t\t\t\t\t\t}\n\t\t\t\t\t\titems={viewModeOptions(t)}\n\t\t\t\t\t/>\n\t\t\t\t\t{/* A count is a claim about the whole set, so a failed\n\t\t\t\t\t listing has none to make: \"0 assets\" beside \"statuses\n\t\t\t\t\t are unavailable\" would be the same false answer in\n\t\t\t\t\t miniature. */}\n\t\t\t\t\t{listFailure ? null : (\n\t\t\t\t\t\t<Toolbar.Count>\n\t\t\t\t\t\t\t{t(\"assetLibrary.assetsCount\", { count: assets.length })}\n\t\t\t\t\t\t</Toolbar.Count>\n\t\t\t\t\t)}\n\t\t\t\t</Toolbar.Right>\n\t\t\t</Toolbar>\n\t\t);\n\n\treturn (\n\t\t<IndexPageTemplate\n\t\t\tbreadcrumbs={[{ label: t(\"assetLibrary.pageTitle\") }]}\n\t\t\ttitle={t(\"assetLibrary.pageTitle\")}\n\t\t\tactions={\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tonClick={() => fileInputRef.current?.click()}\n\t\t\t\t>\n\t\t\t\t\t<Upload size={14} /> {t(\"assetLibrary.uploadButton\")}\n\t\t\t\t</Button>\n\t\t\t}\n\t\t\ttoolbar={toolbar}\n\t\t>\n\t\t\t<SubNavLayout storageKey=\"mediahub-assets-subnav\">\n\t\t\t\t<SubNavLayout.Nav aria-label=\"Folders\">\n\t\t\t\t\t<Box overflow=\"hidden\">\n\t\t\t\t\t\t<FolderTree\n\t\t\t\t\t\t\tactiveFolderId={folderId}\n\t\t\t\t\t\t\tonFolderSelect={(id) => updateFilter(\"folderId\", id || undefined)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</Box>\n\t\t\t\t</SubNavLayout.Nav>\n\t\t\t\t<SubNavLayout.Detail>\n\t\t\t\t\t<SubNavLayout.Toolbar>\n\t\t\t\t\t\t{folderId ? (\n\t\t\t\t\t\t\t<FolderBreadcrumbs\n\t\t\t\t\t\t\t\tfolderId={folderId}\n\t\t\t\t\t\t\t\tonNavigate={(id) => updateFilter(\"folderId\", id || undefined)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\">\n\t\t\t\t\t\t\t\t{t(\"assetLibrary.allAssets\")}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</SubNavLayout.Toolbar>\n\t\t\t\t\t{/* Above the results, and outside the scroll area: the account\n\t\t\t\t\t of what is applied has to stay on screen while the reader\n\t\t\t\t\t scrolls the little that survived it. */}\n\t\t\t\t\t<ActiveFilterChips\n\t\t\t\t\t\tchips={filterChips}\n\t\t\t\t\t\tonClearAll={clearAllFilters}\n\t\t\t\t\t\tgroupLabel={t(\"assetLibrary.activeFiltersLabel\")}\n\t\t\t\t\t\tremoveLabel={t(\"assetLibrary.removeFilter\")}\n\t\t\t\t\t\tclearAllLabel={t(\"assetLibrary.clearAllFilters\")}\n\t\t\t\t\t/>\n\t\t\t\t\t<Box flex=\"1\" overflow=\"auto\" p={4}>\n\t\t\t\t\t\t{/* Above the rows, not instead of them. A refused refetch\n\t\t\t\t\t\t leaves TanStack Query's previous `data` in place, so\n\t\t\t\t\t\t an error does NOT imply an empty list — hanging this\n\t\t\t\t\t\t on the table's `emptyState` would show stale rows\n\t\t\t\t\t\t under no notice at all, which is the silently-wrong\n\t\t\t\t\t\t listing the server refusal exists to prevent. */}\n\t\t\t\t\t\t{listFailureState}\n\t\t\t\t\t\t{listFailureState && assets.length === 0 ? null : viewMode ===\n\t\t\t\t\t\t\t\"grid\" ? (\n\t\t\t\t\t\t\tassetsQuery.isLoading ? (\n\t\t\t\t\t\t\t\t<Flex justify=\"center\" py={10}>\n\t\t\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t) : assets.length === 0 ? (\n\t\t\t\t\t\t\t\tnoAssetsState\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<AssetGrid\n\t\t\t\t\t\t\t\t\tassets={assets}\n\t\t\t\t\t\t\t\t\tonOpen={(asset) => onAssetOpen?.(asset)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<DataTable\n\t\t\t\t\t\t\t\tcolumns={\n\t\t\t\t\t\t\t\t\tlistColumns as ColumnDef<Record<string, unknown>, unknown>[]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdata={assets as unknown as Record<string, unknown>[]}\n\t\t\t\t\t\t\t\tselectable\n\t\t\t\t\t\t\t\trowSelection={rowSelection}\n\t\t\t\t\t\t\t\tonRowSelectionChange={handleRowSelectionChange}\n\t\t\t\t\t\t\t\tgetRowId={(asset) => (asset as unknown as AssetInfo).id}\n\t\t\t\t\t\t\t\tonRowClick={(asset) =>\n\t\t\t\t\t\t\t\t\tonAssetOpen?.(asset as unknown as AssetInfo)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tloading={assetsQuery.isLoading}\n\t\t\t\t\t\t\t\temptyState={noAssetsState}\n\t\t\t\t\t\t\t\tvariant=\"line\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Box>\n\t\t\t\t</SubNavLayout.Detail>\n\t\t\t</SubNavLayout>\n\n\t\t\t<input\n\t\t\t\tref={fileInputRef}\n\t\t\t\ttype=\"file\"\n\t\t\t\tmultiple\n\t\t\t\thidden\n\t\t\t\tonChange={(e) => {\n\t\t\t\t\tconst files = e.target.files;\n\t\t\t\t\tif (files && files.length > 0) {\n\t\t\t\t\t\thandleFilesSelected(Array.from(files));\n\t\t\t\t\t}\n\t\t\t\t\te.target.value = \"\";\n\t\t\t\t}}\n\t\t\t/>\n\n\t\t\t<UploadDialog\n\t\t\t\topen={uploadDialogOpen}\n\t\t\t\tonClose={() => setUploadDialogOpen(false)}\n\t\t\t\tfolderId={folderId || undefined}\n\t\t\t/>\n\t\t</IndexPageTemplate>\n\t);\n}\nAssetLibrary.displayName = \"AssetLibrary\";\n","import {\n\ttype FieldTypePlugin,\n\ttype Schema,\n\tgetDefaultValues,\n} from \"@knkcs/fieldkit/schema\";\nimport type { AssetInfo } from \"../types\";\n\n/** Structural field types carry no value — never composed or decomposed.\n * `card` (fieldkit 0.8.0) is a layout marker exactly like `section`, one\n * level down: a value squatting under a marker accessor must neither mount\n * into the form nor be written back by a save. */\nconst STRUCTURAL = new Set([\"section\", \"card\"]);\n\n/**\n * Compose the RHF form values for the spec-driven asset body. Schema-driven,\n * never hardcoded: the schema's own `system` flags decide whether a value\n * comes from an asset column or from the metadata document. Hidden fields\n * are included so their stored values survive the full-document round-trip.\n * Custom fields with no stored value fall back to fieldkit's defaults\n * (explicit `config.default_value`, then — when `plugins` is passed — the\n * plugin's per-type `defaultValue`, fieldkit ≥0.7.0). Types that declare no\n * `defaultValue` (radio, date, time, color, rich_text, toc_reference) have\n * their key omitted entirely so the field mounts undefined — never seed a\n * stand-in value fieldkit's own registry wouldn't produce.\n */\nexport function composeFormValues(\n\tschema: Schema,\n\tasset: AssetInfo,\n\tplugins?: FieldTypePlugin[],\n): Record<string, unknown> {\n\tconst assetRecord = asset as unknown as Record<string, unknown>;\n\tconst defaults = getDefaultValues(schema, plugins);\n\tconst values: Record<string, unknown> = {};\n\tfor (const f of schema) {\n\t\tif (STRUCTURAL.has(f.field_type)) continue;\n\t\tconst acc = f.config.api_accessor;\n\t\tconst stored = f.system ? assetRecord[acc] : asset.metadata[acc];\n\t\tif (stored !== undefined) {\n\t\t\tvalues[acc] = stored;\n\t\t} else if (acc in defaults) {\n\t\t\tvalues[acc] = defaults[acc];\n\t\t}\n\t\t// else: the type declares no defaultValue — omit the key so the field\n\t\t// mounts undefined instead of a zod-invalid stand-in.\n\t}\n\treturn values;\n}\n\n/**\n * Decompose submitted form values into the update patch: system accessors →\n * asset columns; everything else → the metadata document. Starts from the\n * asset's CURRENT metadata so orphaned keys (values of since-deleted fields)\n * are preserved by a full-document save.\n */\nexport function decomposePatch(\n\tschema: Schema,\n\tasset: AssetInfo,\n\tvalues: Record<string, unknown>,\n\t// NOTE: adding a future system field means extending this return shape and the proto patch — not just the Go canonical list.\n): { name: string; description: string; metadata: Record<string, unknown> } {\n\tconst metadata: Record<string, unknown> = { ...asset.metadata };\n\tconst columns: Record<string, unknown> = {};\n\tfor (const f of schema) {\n\t\tif (STRUCTURAL.has(f.field_type)) continue;\n\t\tconst acc = f.config.api_accessor;\n\t\tif (!(acc in values)) continue;\n\t\tif (f.system) {\n\t\t\tcolumns[acc] = values[acc];\n\t\t} else {\n\t\t\tmetadata[acc] = values[acc];\n\t\t}\n\t}\n\treturn {\n\t\tname: String(columns.name ?? asset.name),\n\t\tdescription: String(columns.description ?? asset.description),\n\t\tmetadata,\n\t};\n}\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, EmptyState, IconButton } from \"@knkcs/anker/atoms\";\nimport {\n\tActionCell,\n\tContextRail,\n\tDataTable,\n\tDateCell,\n\tDescriptionList,\n\tStatusBadgeCell,\n\tTruncatedTextCell,\n\tUploadDropZone,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport {\n\tBadge,\n\tBox,\n\tFlex,\n\tHStack,\n\tMenuContent,\n\tMenuItem,\n\tMenuRoot,\n\tMenuTrigger,\n\tSpinner,\n\tStack,\n\tTabs,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { DetailPageTemplate, usePageRail } from \"@knkcs/anker/templates\";\nimport { FieldKitProvider, SpecForm } from \"@knkcs/fieldkit/renderer\";\nimport {\n\ttype Schema,\n\tbuiltInFieldTypes,\n\tspecToZodSchema,\n} from \"@knkcs/fieldkit/schema\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { ColumnDef } from \"@tanstack/react-table\";\nimport { createColumnHelper } from \"@tanstack/react-table\";\nimport type { TFunction } from \"i18next\";\nimport { ArrowLeft, Download, Ellipsis, Sparkles } from \"lucide-react\";\nimport type React from \"react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { AssetPreview } from \"./components/asset-preview\";\nimport { AssetStatusBadge } from \"./components/asset-status-badge\";\nimport { AssetStatusControl } from \"./components/asset-status-control\";\nimport { CollectionChipField } from \"./components/collection-chip-field\";\nimport { ManageAccessDialog } from \"./components/manage-access-dialog\";\nimport { MoveDialog } from \"./components/move-dialog\";\nimport { TagChipField } from \"./components/tag-chip-field\";\nimport { useAddVersion } from \"./hooks/use-add-version\";\nimport { useAIProcessRuns } from \"./hooks/use-ai-process-runs\";\nimport { useAssetType } from \"./hooks/use-asset-types\";\nimport {\n\tuseAsset,\n\tuseDeleteAsset,\n\tuseEnhanceAssetMetadata,\n\tuseUpdateAsset,\n} from \"./hooks/use-assets\";\nimport { useUsers } from \"./hooks/use-users\";\nimport { composeFormValues, decomposePatch } from \"./lib/asset-metadata-form\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport { useMediahubClients } from \"./provider\";\nimport type { AIProcessRunInfo, AssetVersionInfo } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatFileSize(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nconst versionColumnHelper = createColumnHelper<AssetVersionInfo>();\n\nfunction aiRunColorPalette(status: AIProcessRunInfo[\"status\"]): string {\n\tswitch (status) {\n\t\tcase \"running\":\n\t\t\treturn \"blue\";\n\t\tcase \"succeeded\":\n\t\t\treturn \"green\";\n\t\tcase \"failed\":\n\t\t\treturn \"red\";\n\t\tdefault:\n\t\t\treturn \"gray\"; // queued + unknown\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// AssetDetailRail\n// ---------------------------------------------------------------------------\n\ninterface AssetDetailRailProps {\n\tassetId: string;\n\tassetName: string;\n\tcurrentVersionId: string | undefined;\n\tcurrentMimeType: string | undefined;\n\tcurrentFilename: string | undefined;\n\tcurrentFileSize: number | undefined;\n\tcurrentVersion: number;\n\tassetTypeId: string;\n\tcreatedBy: string;\n\tcreatedByName?: string;\n\tfolderId: string;\n\ttagIds: string[];\n\tcollectionIds: string[];\n\tstatusSlug: string;\n\tt: TFunction;\n}\n\nexport function AssetDetailRail({\n\tassetId,\n\tassetName,\n\tcurrentVersionId,\n\tcurrentMimeType,\n\tcurrentFilename,\n\tcurrentFileSize,\n\tcurrentVersion,\n\tassetTypeId,\n\tcreatedBy,\n\tcreatedByName,\n\tfolderId,\n\ttagIds,\n\tcollectionIds,\n\tstatusSlug,\n\tt,\n}: AssetDetailRailProps): React.JSX.Element {\n\tconst addVersion = useAddVersion();\n\tconst assetType = useAssetType(assetTypeId);\n\tconst aiRuns = useAIProcessRuns(assetId);\n\tconst runs = aiRuns.data ?? [];\n\tconst unknownValue = t(\"assetDetail.rail.unknownValue\");\n\n\treturn (\n\t\t<ContextRail storageKey=\"asset-detail-rail\">\n\t\t\t<ContextRail.Header\n\t\t\t\teyebrow={t(\"assetDetail.rail.assetEyebrow\")}\n\t\t\t\ttitle={assetName}\n\t\t\t/>\n\n\t\t\t{/* Preview */}\n\t\t\t{currentVersionId && currentMimeType ? (\n\t\t\t\t<Box mx={4} mt={3}>\n\t\t\t\t\t<AssetPreview\n\t\t\t\t\t\tassetId={assetId}\n\t\t\t\t\t\tversionId={currentVersionId}\n\t\t\t\t\t\tmimeType={currentMimeType}\n\t\t\t\t\t\tfileName={currentFilename ?? assetName}\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t) : null}\n\n\t\t\t{/* Status — omitted entirely when the asset has no status slug; the\n\t\t\t title-bar badge already conveys it. The catalogue and the moves\n\t\t\t away from the current status are statushub's; the change itself\n\t\t\t goes through mediahub's own RPC (integration standard §3). */}\n\t\t\t{statusSlug ? (\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"status\"\n\t\t\t\t\tlabel={t(\"assetDetail.rail.statusSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<AssetStatusControl assetId={assetId} statusSlug={statusSlug} />\n\t\t\t\t</ContextRail.Section>\n\t\t\t) : null}\n\n\t\t\t{/* New version — drop-to-version zone */}\n\t\t\t{/* usePageRail is a no-op without an <AppShell> ancestor — this rail\n\t\t\t renders inline when mounted directly. A future railMode:\"inline\"\n\t\t\t escape hatch is out of scope for now. */}\n\t\t\t<ContextRail.Section\n\t\t\t\tid=\"new-version\"\n\t\t\t\tlabel={t(\"assetDetail.rail.newVersionSection\")}\n\t\t\t\tdefaultOpen\n\t\t\t>\n\t\t\t\t<UploadDropZone\n\t\t\t\t\tcompact\n\t\t\t\t\tdropHintText={t(\"assetDetail.rail.dropHint\")}\n\t\t\t\t\tdisabled={addVersion.isPending}\n\t\t\t\t\tonFiles={(files) => {\n\t\t\t\t\t\tconst f = files[0];\n\t\t\t\t\t\tif (f) {\n\t\t\t\t\t\t\taddVersion.mutate({ assetId, file: f });\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t{addVersion.isPending && (\n\t\t\t\t\t<Flex align=\"center\" gap={2} mt={2}>\n\t\t\t\t\t\t<Spinner size=\"xs\" />\n\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t\t\t{t(\"assetDetail.rail.uploading\", {\n\t\t\t\t\t\t\t\tpercent: addVersion.progress,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Flex>\n\t\t\t\t)}\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* Details */}\n\t\t\t<ContextRail.Section\n\t\t\t\tid=\"details\"\n\t\t\t\tlabel={t(\"assetDetail.rail.detailsSection\")}\n\t\t\t>\n\t\t\t\t<DescriptionList orientation=\"horizontal\" gap=\"2\">\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.typeLabel\")}>\n\t\t\t\t\t\t{assetType.data?.name ?? assetTypeId}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.formatLabel\")}>\n\t\t\t\t\t\t{currentMimeType ?? unknownValue}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.sizeLabel\")}>\n\t\t\t\t\t\t{currentFileSize !== undefined\n\t\t\t\t\t\t\t? formatFileSize(currentFileSize)\n\t\t\t\t\t\t\t: unknownValue}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.versionLabel\")}>\n\t\t\t\t\t\tv{currentVersion}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.createdByLabel\")}>\n\t\t\t\t\t\t{createdByName ?? createdBy}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t\t<DescriptionList.Row label={t(\"assetDetail.rail.folderLabel\")}>\n\t\t\t\t\t\t{folderId || unknownValue}\n\t\t\t\t\t</DescriptionList.Row>\n\t\t\t\t</DescriptionList>\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* Tags */}\n\t\t\t<ContextRail.Section id=\"tags\" label={t(\"assetDetail.rail.tagsSection\")}>\n\t\t\t\t<TagChipField assetId={assetId} assignedTagIds={tagIds} />\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* Collections */}\n\t\t\t<ContextRail.Section\n\t\t\t\tid=\"collections\"\n\t\t\t\tlabel={t(\"assetDetail.rail.collectionsSection\")}\n\t\t\t>\n\t\t\t\t<CollectionChipField\n\t\t\t\t\tassetId={assetId}\n\t\t\t\t\tassignedCollectionIds={collectionIds}\n\t\t\t\t/>\n\t\t\t</ContextRail.Section>\n\n\t\t\t{/* AI Processing — only shown when there are runs */}\n\t\t\t{runs.length > 0 ? (\n\t\t\t\t<ContextRail.Section\n\t\t\t\t\tid=\"ai-processing\"\n\t\t\t\t\tlabel={t(\"assetDetail.rail.aiProcessingSection\")}\n\t\t\t\t\tdefaultOpen\n\t\t\t\t>\n\t\t\t\t\t<Stack gap=\"2\">\n\t\t\t\t\t\t{runs.map((run) => (\n\t\t\t\t\t\t\t<Stack key={run.id} gap=\"1\">\n\t\t\t\t\t\t\t\t<HStack gap=\"2\" justify=\"space-between\">\n\t\t\t\t\t\t\t\t\t<Text fontSize=\"sm\" flexShrink={1} truncate>\n\t\t\t\t\t\t\t\t\t\t{run.processName}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\t\t\t\tcolorPalette={aiRunColorPalette(run.status)}\n\t\t\t\t\t\t\t\t\t\tvariant=\"subtle\"\n\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\t\tflexShrink={0}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{run.status}\n\t\t\t\t\t\t\t\t\t</Badge>\n\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t{run.status === \"failed\" && run.error ? (\n\t\t\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.error\">\n\t\t\t\t\t\t\t\t\t\t{run.error}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Stack>\n\t\t\t\t</ContextRail.Section>\n\t\t\t) : null}\n\t\t</ContextRail>\n\t);\n}\nAssetDetailRail.displayName = \"AssetDetailRail\";\n\n// ---------------------------------------------------------------------------\n// AssetDetail\n// ---------------------------------------------------------------------------\n\nexport interface AssetDetailProps {\n\tassetId: string;\n\t/** Navigate back to the asset list. */\n\tonBack?: () => void;\n\t/** Called after a successful delete. */\n\tonDeleted?: () => void;\n}\n\nexport function AssetDetail({\n\tassetId,\n\tonBack,\n\tonDeleted,\n}: AssetDetailProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst assetQuery = useAsset(assetId);\n\tconst asset = assetQuery.data;\n\n\tconst { assets: assetsClient } = useMediahubClients();\n\n\tconst updateAsset = useUpdateAsset();\n\tconst deleteAsset = useDeleteAsset();\n\tconst enhanceMetadata = useEnhanceAssetMetadata();\n\tconst qc = useQueryClient();\n\tconst { confirm } = useConfirmModal();\n\n\tconst assetTypeQuery = useAssetType(asset?.assetTypeId ?? \"\");\n\n\tconst schema = useMemo<Schema>(() => {\n\t\ttry {\n\t\t\treturn JSON.parse(assetTypeQuery.data?.metadataSchema || \"[]\") as Schema;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}, [assetTypeQuery.data?.metadataSchema]);\n\n\tconst composedValues = useMemo(\n\t\t() => (asset ? composeFormValues(schema, asset, builtInFieldTypes) : {}),\n\t\t[schema, asset],\n\t);\n\n\tconst zodSchema = useMemo(\n\t\t() => specToZodSchema(schema, builtInFieldTypes),\n\t\t[schema],\n\t);\n\n\t// Always-edit body form. `values` + keepDirtyValues: background refetches\n\t// update clean fields but never clobber in-progress edits.\n\tconst form = useForm({\n\t\tresolver: zodResolver(zodSchema),\n\t\tvalues: composedValues,\n\t\tresetOptions: { keepDirtyValues: true },\n\t});\n\n\tasync function handleSaveBody(values: Record<string, unknown>) {\n\t\tif (!asset) return;\n\t\tconst patch = decomposePatch(schema, asset, values);\n\t\ttry {\n\t\t\tawait updateAsset.mutateAsync({ id: asset.id, patch });\n\t\t\ttoaster.success({ title: t(\"assetDetail.saveSuccessToast\") });\n\t\t\tform.reset(values); // re-baseline: the submitted values are committed\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.saveFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleBack() {\n\t\tif (form.formState.isDirty) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetDetail.discardConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetDetail.discardConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"assetDetail.discardConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\tonBack?.();\n\t}\n\n\tconst [activeTab, setActiveTab] = useState<\"overview\" | \"versions\">(\n\t\t\"overview\",\n\t);\n\tconst [moveOpen, setMoveOpen] = useState(false);\n\tconst [accessOpen, setAccessOpen] = useState(false);\n\n\t// Current version object\n\tconst currentVersion = useMemo(() => {\n\t\tif (!asset) return undefined;\n\t\treturn (\n\t\t\tasset.versions.find((v) => v.versionNumber === asset.currentVersion) ??\n\t\t\tasset.versions.at(-1)\n\t\t);\n\t}, [asset]);\n\n\t// Collect all user IDs referenced in this asset for a single batch lookup.\n\tconst allUserIds = useMemo(() => {\n\t\tif (!asset) return [];\n\t\tconst ids = new Set<string>();\n\t\tif (asset.createdBy) ids.add(asset.createdBy);\n\t\tfor (const v of asset.versions) {\n\t\t\tif (v.createdBy) ids.add(v.createdBy);\n\t\t}\n\t\treturn [...ids];\n\t}, [asset]);\n\n\tconst { data: userNames } = useUsers(allUserIds);\n\n\t// Download a specific version via its SAS URL.\n\tconst handleDownloadVersion = useCallback(\n\t\tasync (versionId: string) => {\n\t\t\tif (!asset) return;\n\t\t\ttry {\n\t\t\t\tconst url = await assetsClient.getDownloadUrl(asset.id, versionId);\n\t\t\t\twindow.open(url, \"_blank\");\n\t\t\t} catch (err) {\n\t\t\t\tshowRpcErrorToast(err, t(\"assetDetail.downloadFailedToast\"));\n\t\t\t}\n\t\t},\n\t\t[asset, assetsClient, t],\n\t);\n\n\t// Versions table columns — every cell delegates to a provided anker *Cell\n\t// component (no inline JSX renderers).\n\tconst versionColumns = useMemo(() => {\n\t\tconst currentBadge: Record<string, string> = asset\n\t\t\t? { [`v${asset.currentVersion}`]: \"green\" }\n\t\t\t: {};\n\t\treturn [\n\t\t\tversionColumnHelper.accessor(\"versionNumber\", {\n\t\t\t\theader: t(\"assetDetail.versionColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<StatusBadgeCell\n\t\t\t\t\t\tvalue={`v${info.getValue()}`}\n\t\t\t\t\t\tcolorMap={currentBadge}\n\t\t\t\t\t\ttooltip={\n\t\t\t\t\t\t\tinfo.getValue() === asset?.currentVersion\n\t\t\t\t\t\t\t\t? t(\"assetDetail.currentVersionTooltip\")\n\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"originalFilename\", {\n\t\t\t\theader: t(\"assetDetail.fileColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<TruncatedTextCell\n\t\t\t\t\t\tvalue={info.getValue()}\n\t\t\t\t\t\tmaxLength={48}\n\t\t\t\t\t\tsubText={info.row.original.comment || info.row.original.mimeType}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"fileSize\", {\n\t\t\t\theader: t(\"assetDetail.sizeColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<TruncatedTextCell value={formatFileSize(info.getValue())} />\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"createdBy\", {\n\t\t\t\theader: t(\"assetDetail.authorColumn\"),\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<TruncatedTextCell\n\t\t\t\t\t\tvalue={userNames?.[info.getValue()] ?? info.getValue()}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t\tversionColumnHelper.accessor(\"createdAt\", {\n\t\t\t\theader: t(\"assetDetail.dateColumn\"),\n\t\t\t\tcell: (info) => <DateCell value={info.getValue()} showRelative />,\n\t\t\t}),\n\t\t\tversionColumnHelper.display({\n\t\t\t\tid: \"actions\",\n\t\t\t\theader: \"\",\n\t\t\t\tcell: (info) => (\n\t\t\t\t\t<ActionCell\n\t\t\t\t\t\tactions={[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticon: Download,\n\t\t\t\t\t\t\t\tlabel: t(\"assetDetail.downloadVersion\", {\n\t\t\t\t\t\t\t\t\tversionNumber: info.row.original.versionNumber,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\t\t\t\thandleDownloadVersion(info.row.original.id);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\t\t\t\t),\n\t\t\t}),\n\t\t] as ColumnDef<AssetVersionInfo, unknown>[];\n\t}, [asset, handleDownloadVersion, userNames, t]);\n\n\t// Register rail (Overview tab only) — no-op outside <AppShell>\n\tusePageRail(\n\t\tasset && activeTab === \"overview\" ? (\n\t\t\t<AssetDetailRail\n\t\t\t\tassetId={asset.id}\n\t\t\t\tassetName={asset.name}\n\t\t\t\tcurrentVersionId={currentVersion?.id}\n\t\t\t\tcurrentMimeType={currentVersion?.mimeType}\n\t\t\t\tcurrentFilename={currentVersion?.originalFilename}\n\t\t\t\tcurrentFileSize={currentVersion?.fileSize}\n\t\t\t\tcurrentVersion={asset.currentVersion}\n\t\t\t\tassetTypeId={asset.assetTypeId}\n\t\t\t\tcreatedBy={asset.createdBy}\n\t\t\t\tcreatedByName={userNames?.[asset.createdBy]}\n\t\t\t\tfolderId={asset.folderId}\n\t\t\t\ttagIds={asset.tagIds}\n\t\t\t\tcollectionIds={asset.collectionIds}\n\t\t\t\tstatusSlug={asset.statusSlug}\n\t\t\t\tt={t}\n\t\t\t/>\n\t\t) : null,\n\t);\n\n\t// -------------- handlers -----------------------------------------------\n\n\tasync function handleDownloadCurrent() {\n\t\tif (!asset || !currentVersion) return;\n\t\ttry {\n\t\t\tconst url = await assetsClient.getDownloadUrl(\n\t\t\t\tasset.id,\n\t\t\t\tcurrentVersion.id,\n\t\t\t);\n\t\t\twindow.open(url, \"_blank\");\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.downloadFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleEnhance() {\n\t\tif (!asset) return;\n\t\ttry {\n\t\t\tawait enhanceMetadata.mutateAsync(asset.id);\n\t\t\t// Kick off polling for the newly-queued process runs.\n\t\t\tqc.invalidateQueries({\n\t\t\t\tqueryKey: [\"mediahub\", \"ai-process-runs\", asset.id],\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"assetDetail.metadataEnhancedToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.enhanceFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleDelete() {\n\t\tif (!asset) return;\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"assetDetail.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"assetDetail.deleteConfirmMessage\", { assetName: asset.name }),\n\t\t\tconfirmLabel: t(\"assetDetail.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteAsset.mutateAsync(asset.id);\n\t\t\ttoaster.success({ title: t(\"assetDetail.deleteSuccessToast\") });\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetDetail.deleteFailedToast\"));\n\t\t}\n\t}\n\n\t// -------------- loading / not found ------------------------------------\n\n\tif (assetQuery.isLoading) {\n\t\treturn (\n\t\t\t<Flex justify=\"center\" align=\"center\" minH=\"400px\">\n\t\t\t\t<Spinner />\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\tif (!asset) {\n\t\treturn <EmptyState header={t(\"assetDetail.notFound\")} />;\n\t}\n\n\t// Sorted versions newest-first\n\tconst sortedVersions = [...asset.versions].sort(\n\t\t(a, b) => b.versionNumber - a.versionNumber,\n\t);\n\n\treturn (\n\t\t<DetailPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{ label: t(\"assetDetail.breadcrumbAssets\") },\n\t\t\t\t{ label: asset.name },\n\t\t\t]}\n\t\t\tavatar={\n\t\t\t\tonBack ? (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\taria-label={t(\"assetDetail.backButtonAria\")}\n\t\t\t\t\t\tonClick={handleBack}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowLeft size={18} />\n\t\t\t\t\t</IconButton>\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\ttitle={asset.name}\n\t\t\tbadges={\n\t\t\t\tasset.statusSlug ? (\n\t\t\t\t\t<AssetStatusBadge slug={asset.statusSlug} />\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\tmeta={\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\tv{asset.currentVersion}\n\t\t\t\t\t{asset.updatedAt ? ` · ${asset.updatedAt.toLocaleDateString()}` : \"\"}\n\t\t\t\t</Text>\n\t\t\t}\n\t\t\tactions={\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tloading={enhanceMetadata.isPending}\n\t\t\t\t\t\tonClick={handleEnhance}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Sparkles size={16} /> {t(\"assetDetail.enhanceWithAi\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tonClick={handleDownloadCurrent}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetDetail.download\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t// Override the form's global keepDirtyValues:true (which exists\n\t\t\t\t\t\t\t// to protect in-progress edits from background refetches) —\n\t\t\t\t\t\t\t// Discard must revert every field, dirty or not.\n\t\t\t\t\t\t\tform.reset(composedValues, { keepDirtyValues: false })\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetDetail.discard\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tloading={updateAsset.isPending}\n\t\t\t\t\t\tonClick={form.handleSubmit(handleSaveBody)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetDetail.save\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<MenuRoot>\n\t\t\t\t\t\t<MenuTrigger asChild>\n\t\t\t\t\t\t\t<IconButton\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\taria-label={t(\"assetDetail.moreActionsAria\")}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Ellipsis size={16} />\n\t\t\t\t\t\t\t</IconButton>\n\t\t\t\t\t\t</MenuTrigger>\n\t\t\t\t\t\t<MenuContent>\n\t\t\t\t\t\t\t<MenuItem value=\"move\" onClick={() => setMoveOpen(true)}>\n\t\t\t\t\t\t\t\t{t(\"assetDetail.moveAction\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\tvalue=\"manage-access\"\n\t\t\t\t\t\t\t\tonClick={() => setAccessOpen(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"assetDetail.manageAccessAction\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t<MenuItem value=\"delete\" color=\"fg.error\" onClick={handleDelete}>\n\t\t\t\t\t\t\t\t{t(\"assetDetail.deleteAction\")}\n\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t</MenuContent>\n\t\t\t\t\t</MenuRoot>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t\ttabs={\n\t\t\t\t<Tabs.Root\n\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\tonValueChange={(e) =>\n\t\t\t\t\t\tsetActiveTab(e.value as \"overview\" | \"versions\")\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<Tabs.List>\n\t\t\t\t\t\t<Tabs.Trigger value=\"overview\">\n\t\t\t\t\t\t\t{t(\"assetDetail.overviewTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t\t<Tabs.Trigger value=\"versions\">\n\t\t\t\t\t\t\t{t(\"assetDetail.versionsTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t</Tabs.List>\n\t\t\t\t</Tabs.Root>\n\t\t\t}\n\t\t>\n\t\t\t<Stack gap=\"4\" px=\"8\" py=\"6\">\n\t\t\t\t{/* Renders into a portal; parked here so it stays mounted with\n\t\t\t\t the loaded asset (dialog machines must not unmount mid-exit,\n\t\t\t\t see collection-picker / #66). */}\n\t\t\t\t<MoveDialog\n\t\t\t\t\topen={moveOpen}\n\t\t\t\t\tonOpenChange={setMoveOpen}\n\t\t\t\t\tsubject={{ kind: \"asset\", asset }}\n\t\t\t\t/>\n\t\t\t\t<ManageAccessDialog\n\t\t\t\t\topen={accessOpen}\n\t\t\t\t\tonOpenChange={setAccessOpen}\n\t\t\t\t\tsubject={{ kind: \"asset\", asset }}\n\t\t\t\t/>\n\t\t\t\t{activeTab === \"overview\" ? (\n\t\t\t\t\t<FieldKitProvider plugins={builtInFieldTypes}>\n\t\t\t\t\t\t<FormProvider {...form}>\n\t\t\t\t\t\t\t<SpecForm schema={schema} loading={assetTypeQuery.isLoading} />\n\t\t\t\t\t\t</FormProvider>\n\t\t\t\t\t</FieldKitProvider>\n\t\t\t\t) : (\n\t\t\t\t\t<DataTable\n\t\t\t\t\t\tcolumns={\n\t\t\t\t\t\t\tversionColumns as ColumnDef<Record<string, unknown>, unknown>[]\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata={sortedVersions as unknown as Record<string, unknown>[]}\n\t\t\t\t\t\tgetRowId={(r) => (r as unknown as AssetVersionInfo).id}\n\t\t\t\t\t\temptyState={<EmptyState header={t(\"assetDetail.noVersions\")} />}\n\t\t\t\t\t\tvariant=\"line\"\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t</DetailPageTemplate>\n\t);\n}\nAssetDetail.displayName = \"AssetDetail\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, EmptyState, IconButton } from \"@knkcs/anker/atoms\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { InputField, SwitchField, TextareaField } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tHStack,\n\tSpinner,\n\tStack,\n\tTabs,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { DetailPageTemplate } from \"@knkcs/anker/templates\";\nimport type { Schema } from \"@knkcs/fieldkit/schema\";\nimport { ArrowLeft } from \"lucide-react\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { AIProcessesTab } from \"./components/ai-processes-tab\";\nimport { MetadataSchemaEditor } from \"./components/metadata-schema-editor\";\nimport {\n\tuseAssetType,\n\tuseDeleteAssetType,\n\tuseUpdateAssetType,\n} from \"./hooks/use-asset-types\";\nimport { formatMimeTypeList, parseMimeTypeList } from \"./lib/mime-type-list\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\n\ntype TabValue = \"general\" | \"metadata\" | \"ai\";\n\ntype GeneralForm = {\n\tname: string;\n\tdescription: string;\n\tallowedMimeTypesText: string;\n\tactive: boolean;\n};\n\nexport interface AssetTypeDetailProps {\n\t/** The asset type to show. */\n\ttypeId: string;\n\t/**\n\t * Typed path of the host's asset-type index, used for the breadcrumb back\n\t * link. The screen never routes itself — the host owns its URLs\n\t * (core's `docs/service-integration.md`).\n\t */\n\tassetTypesPath?: string;\n\t/**\n\t * Navigate back to the asset-type index. Given one, the screen renders a\n\t * back affordance that confirms before discarding unsaved edits — the\n\t * breadcrumb link above is the host's own navigation and the screen cannot\n\t * intercept it.\n\t */\n\tonBack?: () => void;\n\t/** Called after a successful delete; the host decides where to go next. */\n\tonDeleted?: () => void;\n}\n\n/**\n * The packaged asset-type detail screen: view, edit and delete one asset type,\n * with its fieldkit metadata schema on a second tab.\n *\n * **Correct against the wire, not against the declared type.** Connect omits\n * empty repeated fields and empty strings from its JSON, and a host client that\n * returns the wire object unmapped therefore delivers `undefined` where\n * `AssetTypeInfo` promises `string` or `string[]`. Reading one of those\n * unguarded is what took core's detail page down (knkcms/core#862, #863).\n * Every field below is defaulted at the one place it is read, so an absent\n * value renders as empty rather than throwing — and never flips a controlled\n * input to uncontrolled, which is the quieter version of the same bug.\n */\nexport function AssetTypeDetail({\n\ttypeId,\n\tassetTypesPath,\n\tonBack,\n\tonDeleted,\n}: AssetTypeDetailProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { confirm } = useConfirmModal();\n\n\tconst assetTypeQuery = useAssetType(typeId);\n\tconst assetType = assetTypeQuery.data;\n\tconst updateAssetType = useUpdateAssetType();\n\tconst deleteAssetType = useDeleteAssetType();\n\n\tconst [activeTab, setActiveTab] = useState<TabValue>(\"general\");\n\tconst [metadataDirty, setMetadataDirty] = useState(false);\n\n\tconst zodSchema = useMemo(\n\t\t() =>\n\t\t\tz.object({\n\t\t\t\tname: z.string().min(1, t(\"assetTypeDetail.nameRequired\")),\n\t\t\t\tdescription: z.string(),\n\t\t\t\tallowedMimeTypesText: z.string(),\n\t\t\t\tactive: z.boolean(),\n\t\t\t}),\n\t\t[t],\n\t);\n\n\t// Memoized on the query data, which TanStack Query keeps referentially\n\t// stable across no-op background refetches (structural sharing) — so\n\t// `values` below re-baselines only when the record actually changes.\n\tconst values = useMemo<GeneralForm>(\n\t\t() => ({\n\t\t\tname: assetType?.name ?? \"\",\n\t\t\tdescription: assetType?.description ?? \"\",\n\t\t\tallowedMimeTypesText: formatMimeTypeList(assetType?.allowedMimeTypes),\n\t\t\t// `false`, NOT `true`. `AssetType.active` is a plain proto3 bool, so\n\t\t\t// its zero value is omitted from the wire exactly as an empty string\n\t\t\t// or an empty list is — an *inactive* asset type is the one that\n\t\t\t// arrives without the key. Defaulting it to `true` would render the\n\t\t\t// switch on for a deactivated type and, on the next Save, write that\n\t\t\t// flip back. The same reason every field above is defaulted, one\n\t\t\t// value further on.\n\t\t\tactive: assetType?.active ?? false,\n\t\t}),\n\t\t[assetType],\n\t);\n\n\t// `values` + keepDirtyValues: a background refetch updates clean fields but\n\t// never clobbers an edit in progress (same contract as <AssetDetail>).\n\tconst form = useForm<GeneralForm>({\n\t\tresolver: zodResolver(zodSchema),\n\t\tvalues,\n\t\tresetOptions: { keepDirtyValues: true },\n\t});\n\n\tconst parsedSchema = useMemo<Schema>(() => {\n\t\ttry {\n\t\t\treturn JSON.parse(assetType?.metadataSchema || \"[]\") as Schema;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}, [assetType]);\n\n\tasync function handleSave(data: GeneralForm) {\n\t\ttry {\n\t\t\tawait updateAssetType.mutateAsync({\n\t\t\t\tid: typeId,\n\t\t\t\tpatch: {\n\t\t\t\t\tname: data.name,\n\t\t\t\t\tdescription: data.description,\n\t\t\t\t\tallowedMimeTypes: parseMimeTypeList(data.allowedMimeTypesText),\n\t\t\t\t\tactive: data.active,\n\t\t\t\t},\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"assetTypeDetail.saveSuccessToast\") });\n\t\t\tform.reset(data); // re-baseline: the submitted values are committed\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetTypeDetail.saveFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleDelete() {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"assetTypeDetail.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"assetTypeDetail.deleteConfirmMessage\", {\n\t\t\t\ttypeName: assetType?.name ?? \"\",\n\t\t\t}),\n\t\t\tconfirmLabel: t(\"assetTypeDetail.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteAssetType.mutateAsync(typeId);\n\t\t\ttoaster.success({ title: t(\"assetTypeDetail.deleteSuccessToast\") });\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetTypeDetail.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleBack() {\n\t\tif (form.formState.isDirty || metadataDirty) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetTypeDetail.discardConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetTypeDetail.discardConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"assetTypeDetail.discardConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\tonBack?.();\n\t}\n\n\tasync function handleTabChange(next: string) {\n\t\tif (activeTab === \"metadata\" && metadataDirty && next !== \"metadata\") {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetTypeDetail.discardSchemaConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetTypeDetail.discardSchemaConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"assetTypeDetail.discardSchemaConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return; // stay on the metadata tab\n\t\t\t// The editor unmounts with the discarded draft; its onDirtyChange\n\t\t\t// can no longer fire, so reset here.\n\t\t\tsetMetadataDirty(false);\n\t\t}\n\t\tsetActiveTab(next as TabValue);\n\t}\n\n\tif (assetTypeQuery.isLoading) {\n\t\treturn (\n\t\t\t<Flex justify=\"center\" align=\"center\" minH=\"400px\">\n\t\t\t\t<Spinner />\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\tif (!assetType) {\n\t\treturn <EmptyState header={t(\"assetTypeDetail.notFound\")} />;\n\t}\n\n\tconst title = assetType.name || t(\"assetTypeDetail.untitled\");\n\n\treturn (\n\t\t<DetailPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{\n\t\t\t\t\tlabel: t(\"assetTypeDetail.breadcrumbAssetTypes\"),\n\t\t\t\t\tto: assetTypesPath,\n\t\t\t\t},\n\t\t\t\t{ label: title },\n\t\t\t]}\n\t\t\ttitle={title}\n\t\t\tavatar={\n\t\t\t\tonBack ? (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\taria-label={t(\"assetTypeDetail.backButtonAria\")}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid handleBack();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowLeft size={18} />\n\t\t\t\t\t</IconButton>\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\tactions={\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tloading={updateAssetType.isPending}\n\t\t\t\t\t\tonClick={form.handleSubmit(handleSave)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetTypeDetail.save\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\t\tloading={deleteAssetType.isPending}\n\t\t\t\t\t\tonClick={handleDelete}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"assetTypeDetail.delete\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t\ttabs={\n\t\t\t\t<Tabs.Root\n\t\t\t\t\tvalue={activeTab}\n\t\t\t\t\tonValueChange={(e) => {\n\t\t\t\t\t\tvoid handleTabChange(e.value);\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<Tabs.List>\n\t\t\t\t\t\t<Tabs.Trigger value=\"general\">\n\t\t\t\t\t\t\t{t(\"assetTypeDetail.generalTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t\t<Tabs.Trigger value=\"metadata\">\n\t\t\t\t\t\t\t{t(\"assetTypeDetail.metadataTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t\t<Tabs.Trigger value=\"ai\">\n\t\t\t\t\t\t\t{t(\"assetTypeDetail.aiProcessesTab\")}\n\t\t\t\t\t\t</Tabs.Trigger>\n\t\t\t\t\t</Tabs.List>\n\t\t\t\t</Tabs.Root>\n\t\t\t}\n\t\t>\n\t\t\t<Stack gap=\"4\" px=\"8\" py=\"6\">\n\t\t\t\t{activeTab === \"general\" ? (\n\t\t\t\t\t<FormProvider {...form}>\n\t\t\t\t\t\t<Stack gap={4} maxW=\"lg\">\n\t\t\t\t\t\t\t<InputField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.nameLabel\")}\n\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Box>\n\t\t\t\t\t\t\t\t<Text color=\"fg.muted\" fontSize=\"sm\">\n\t\t\t\t\t\t\t\t\t{t(\"assetTypeDetail.slugLabel\")}: {assetType.slug ?? \"\"}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t<TextareaField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"description\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.descriptionLabel\")}\n\t\t\t\t\t\t\t\tplaceholder={t(\"assetTypeDetail.descriptionPlaceholder\")}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<InputField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"allowedMimeTypesText\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.allowedMimeTypesLabel\")}\n\t\t\t\t\t\t\t\tdescription={t(\"assetTypeDetail.allowedMimeTypesDescription\")}\n\t\t\t\t\t\t\t\tplaceholder=\"image/jpeg, image/png, application/pdf\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<SwitchField<GeneralForm>\n\t\t\t\t\t\t\t\tname=\"active\"\n\t\t\t\t\t\t\t\tlabel={t(\"assetTypeDetail.activeLabel\")}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t</FormProvider>\n\t\t\t\t) : activeTab === \"metadata\" ? (\n\t\t\t\t\t<MetadataSchemaEditor\n\t\t\t\t\t\ttypeId={typeId}\n\t\t\t\t\t\tinitialSchema={parsedSchema}\n\t\t\t\t\t\tonDirtyChange={setMetadataDirty}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<AIProcessesTab\n\t\t\t\t\t\ttypeId={typeId}\n\t\t\t\t\t\tmetadataSchema={assetType.metadataSchema}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t</DetailPageTemplate>\n\t);\n}\nAssetTypeDetail.displayName = \"AssetTypeDetail\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, TextInput } from \"@knkcs/anker/atoms\";\nimport { FormField, InputField, TextareaField } from \"@knkcs/anker/forms\";\nimport { HStack, Stack, toaster } from \"@knkcs/anker/primitives\";\nimport { SettingsPageTemplate } from \"@knkcs/anker/templates\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { useCreateAssetType } from \"./hooks/use-asset-types\";\nimport { parseMimeTypeList } from \"./lib/mime-type-list\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport { slugify } from \"./lib/slugify\";\nimport type { AssetTypeInfo } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface AssetTypeCreateProps {\n\t/**\n\t * The host's asset-type index path — used as the breadcrumb's target. A\n\t * path, not a route: the screen never navigates, it only says where the\n\t * list it belongs to lives (core's `docs/service-integration.md`).\n\t */\n\tassetTypesPath: string;\n\t/** Called with the created asset type; the host decides where to go. */\n\tonCreated?: (assetType: AssetTypeInfo) => void;\n\t/** Called when the administrator abandons the form. */\n\tonCancel?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// AssetTypeCreate\n// ---------------------------------------------------------------------------\n\n/**\n * Create an asset type. The screen the package owns, replacing the\n * standalone's create dialog and core's create page (knkCS/mediahub#137/#140).\n *\n * The slug follows the name until it is edited by hand and then stops — the\n * unconditional overwrite the standalone had silently discarded a slug someone\n * typed on purpose. The server's rule (lowercase alphanumeric with hyphens, at\n * least two characters) is stated on the form and enforced before submit,\n * because without both a name like `Bild Anhang` produced a bare 400\n * (knkcms/core#861).\n */\nexport function AssetTypeCreate({\n\tassetTypesPath,\n\tonCreated,\n\tonCancel,\n}: AssetTypeCreateProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst createAssetType = useCreateAssetType();\n\n\t// Once the slug has been typed into, it stops following the name. A flag\n\t// rather than react-hook-form's dirty state: clearing a hand-typed slug\n\t// back to empty would make the field clean again and silently resume the\n\t// autofill the administrator just opted out of.\n\tconst [slugEdited, setSlugEdited] = useState(false);\n\n\tconst schema = useMemo(\n\t\t() =>\n\t\t\tz.object({\n\t\t\t\tname: z.string().min(1, t(\"assetTypeCreate.nameRequired\")),\n\t\t\t\tslug: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(2, t(\"assetTypeCreate.slugInvalid\"))\n\t\t\t\t\t.regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, t(\"assetTypeCreate.slugInvalid\")),\n\t\t\t\tdescription: z.string(),\n\t\t\t\tallowedMimeTypes: z.string(),\n\t\t\t\tmetadataSchema: z.string(),\n\t\t\t}),\n\t\t[t],\n\t);\n\n\ttype FormValues = z.infer<typeof schema>;\n\n\tconst form = useForm<FormValues>({\n\t\tresolver: zodResolver(schema),\n\t\tdefaultValues: {\n\t\t\tname: \"\",\n\t\t\tslug: \"\",\n\t\t\tdescription: \"\",\n\t\t\tallowedMimeTypes: \"\",\n\t\t\tmetadataSchema: \"\",\n\t\t},\n\t});\n\n\tasync function onSubmit(values: FormValues) {\n\t\ttry {\n\t\t\tconst created = await createAssetType.mutateAsync({\n\t\t\t\tname: values.name,\n\t\t\t\tslug: values.slug,\n\t\t\t\tdescription: values.description,\n\t\t\t\tallowedMimeTypes: parseMimeTypeList(values.allowedMimeTypes),\n\t\t\t\t// An empty schema field means \"no custom metadata\", which the\n\t\t\t\t// service spells as an empty JSON array, not an empty string.\n\t\t\t\tmetadataSchema: values.metadataSchema.trim() || \"[]\",\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"assetTypeCreate.createdToast\") });\n\t\t\tonCreated?.(created);\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"assetTypeCreate.createFailedToast\"));\n\t\t}\n\t}\n\n\tconst title = t(\"assetTypeCreate.title\");\n\n\treturn (\n\t\t<SettingsPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{\n\t\t\t\t\tlabel: t(\"assetTypeCreate.breadcrumbAssetTypes\"),\n\t\t\t\t\tto: assetTypesPath,\n\t\t\t\t},\n\t\t\t\t{ label: title },\n\t\t\t]}\n\t\t\ttitle={title}\n\t\t>\n\t\t\t<FormProvider {...form}>\n\t\t\t\t<form onSubmit={form.handleSubmit(onSubmit)} noValidate>\n\t\t\t\t\t<Stack gap=\"4\">\n\t\t\t\t\t\t<FormField<FormValues>\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.nameLabel\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{(field) => (\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"assetTypeCreate.namePlaceholder\")}\n\t\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\tfield.onChange(e);\n\t\t\t\t\t\t\t\t\t\tif (!slugEdited) {\n\t\t\t\t\t\t\t\t\t\t\tform.setValue(\"slug\", slugify(e.target.value), {\n\t\t\t\t\t\t\t\t\t\t\t\tshouldValidate: form.formState.isSubmitted,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</FormField>\n\n\t\t\t\t\t\t<FormField<FormValues>\n\t\t\t\t\t\t\tname=\"slug\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.slugLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"assetTypeCreate.slugHint\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{(field) => (\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\t\t\t\tfontFamily=\"mono\"\n\t\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\tsetSlugEdited(true);\n\t\t\t\t\t\t\t\t\t\tfield.onChange(e);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</FormField>\n\n\t\t\t\t\t\t<TextareaField<FormValues>\n\t\t\t\t\t\t\tname=\"description\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.descriptionLabel\")}\n\t\t\t\t\t\t\tplaceholder={t(\"assetTypeCreate.descriptionPlaceholder\")}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<InputField<FormValues>\n\t\t\t\t\t\t\tname=\"allowedMimeTypes\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.allowedMimeTypesLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"assetTypeCreate.allowedMimeTypesHint\")}\n\t\t\t\t\t\t\tplaceholder={t(\"assetTypeCreate.allowedMimeTypesPlaceholder\")}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<TextareaField<FormValues>\n\t\t\t\t\t\t\tname=\"metadataSchema\"\n\t\t\t\t\t\t\tlabel={t(\"assetTypeCreate.metadataSchemaLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"assetTypeCreate.metadataSchemaHint\")}\n\t\t\t\t\t\t\ttextareaProps={{ fontFamily: \"mono\", rows: 8 }}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<HStack gap=\"2\" justifyContent=\"flex-start\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\t\t\tloading={createAssetType.isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"assetTypeCreate.submit\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t{onCancel ? (\n\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"outline\" onClick={onCancel}>\n\t\t\t\t\t\t\t\t\t{t(\"assetTypeCreate.cancel\")}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t</Stack>\n\t\t\t\t</form>\n\t\t\t</FormProvider>\n\t\t</SettingsPageTemplate>\n\t);\n}\nAssetTypeCreate.displayName = \"AssetTypeCreate\";\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport {\n\tBooleanCell,\n\tDataTable,\n\tMenuCell,\n\tSlugCell,\n\tToolbar,\n\tTruncatedTextCell,\n} from \"@knkcs/anker/components\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { Text, toaster } from \"@knkcs/anker/primitives\";\nimport { IndexPageTemplate } from \"@knkcs/anker/templates\";\nimport { type ColumnDef, createColumnHelper } from \"@tanstack/react-table\";\nimport { Trash2 } from \"lucide-react\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useAssetTypes, useDeleteAssetType } from \"./hooks/use-asset-types\";\nimport { countCustomFields } from \"./lib/metadata-field-count\";\nimport { formatMimeTypeList } from \"./lib/mime-type-list\";\nimport { describeRpcError, showRpcErrorToast } from \"./lib/rpc-errors\";\nimport type { AssetTypeInfo } from \"./types\";\n\nconst columnHelper = createColumnHelper<AssetTypeInfo>();\n\nexport interface AssetTypeIndexProps {\n\t/**\n\t * An asset type was opened. The host decides what that means — it receives\n\t * the id and nothing else, because this package must not know either host's\n\t * URL structure (core's `docs/service-integration.md`; spec #138). Screens,\n\t * not routes: nothing here navigates and nothing here builds a path.\n\t */\n\tonOpen?: (assetTypeId: string) => void;\n\t/** The reader asked for a new asset type. Same contract as `onOpen`. */\n\tonCreate?: () => void;\n}\n\n/**\n * The workspace's asset types, listed. The package owns the screen; both hosts\n * compose it and keep their own routing to themselves (#142, parent #138).\n */\nexport function AssetTypeIndex(props: AssetTypeIndexProps): React.JSX.Element {\n\tconst { onOpen, onCreate } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst assetTypesQuery = useAssetTypes();\n\tconst deleteAssetType = useDeleteAssetType();\n\tconst { confirm } = useConfirmModal();\n\n\tconst [search, setSearch] = useState(\"\");\n\n\tconst assetTypes = useMemo(\n\t\t() => assetTypesQuery.data ?? [],\n\t\t[assetTypesQuery.data],\n\t);\n\n\tconst filtered = useMemo(() => {\n\t\tconst query = search.trim().toLowerCase();\n\t\tif (!query) return assetTypes;\n\t\treturn assetTypes.filter(\n\t\t\t(type) =>\n\t\t\t\ttype.name.toLowerCase().includes(query) ||\n\t\t\t\ttype.slug.toLowerCase().includes(query),\n\t\t);\n\t}, [assetTypes, search]);\n\n\tconst handleDelete = useCallback(\n\t\tasync (assetType: AssetTypeInfo) => {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"assetTypeIndex.deleteConfirmTitle\"),\n\t\t\t\tmessage: t(\"assetTypeIndex.deleteConfirmMessage\", {\n\t\t\t\t\ttypeName: assetType.name,\n\t\t\t\t}),\n\t\t\t\tconfirmLabel: t(\"assetTypeIndex.deleteConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t\ttry {\n\t\t\t\tawait deleteAssetType.mutateAsync(assetType.id);\n\t\t\t\ttoaster.success({ title: t(\"assetTypeIndex.deleteSuccessToast\") });\n\t\t\t} catch (err) {\n\t\t\t\tshowRpcErrorToast(err, t(\"assetTypeIndex.deleteFailedToast\"));\n\t\t\t}\n\t\t},\n\t\t[confirm, deleteAssetType, t],\n\t);\n\n\tconst columns = useMemo(\n\t\t() =>\n\t\t\t[\n\t\t\t\tcolumnHelper.accessor(\"name\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnName\"),\n\t\t\t\t\tcell: (info) => <TruncatedTextCell value={info.getValue()} />,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"slug\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnSlug\"),\n\t\t\t\t\tcell: (info) => <SlugCell value={info.getValue()} />,\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"allowedMimeTypes\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnMimeTypes\"),\n\t\t\t\t\tenableSorting: false,\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t// `formatMimeTypeList` tolerates the key being absent\n\t\t\t\t\t\t// altogether, which is how Connect delivers an empty\n\t\t\t\t\t\t// repeated field to a host that maps the wire object\n\t\t\t\t\t\t// straight onto `AssetTypeInfo` (knkcms/core#863).\n\t\t\t\t\t\t<TruncatedTextCell value={formatMimeTypeList(info.getValue())} />\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: \"fields\",\n\t\t\t\t\theader: t(\"assetTypeIndex.columnFields\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<Text color=\"fg.muted\">\n\t\t\t\t\t\t\t{countCustomFields(info.row.original.metadataSchema)}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"active\", {\n\t\t\t\t\theader: t(\"assetTypeIndex.columnStatus\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<BooleanCell\n\t\t\t\t\t\t\tvalue={info.getValue()}\n\t\t\t\t\t\t\ttrueLabel={t(\"assetTypeIndex.statusActive\")}\n\t\t\t\t\t\t\tfalseLabel={t(\"assetTypeIndex.statusInactive\")}\n\t\t\t\t\t\t/>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.display({\n\t\t\t\t\tid: \"actions\",\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t<MenuCell\n\t\t\t\t\t\t\tactions={[\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tlabel: t(\"assetTypeIndex.actionDelete\"),\n\t\t\t\t\t\t\t\t\ticon: Trash2,\n\t\t\t\t\t\t\t\t\tcolorPalette: \"red\",\n\t\t\t\t\t\t\t\t\tonClick: () => handleDelete(info.row.original),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]}\n\t\t\t\t\t\t/>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t] as ColumnDef<AssetTypeInfo, unknown>[],\n\t\t[handleDelete, t],\n\t);\n\n\t// A failed listing must SAY so rather than render as \"no asset types\" —\n\t// the same rule the asset library follows for a refused listing\n\t// (knkCS/mediahub#120): an empty area over a refusal is the false answer\n\t// the server declined to give, arriving through the UI's door instead.\n\tconst listFailure = assetTypesQuery.isError ? assetTypesQuery.error : null;\n\n\tconst toolbar = (\n\t\t<Toolbar>\n\t\t\t<Toolbar.Search\n\t\t\t\tvalue={search}\n\t\t\t\tonChange={setSearch}\n\t\t\t\tplaceholder={t(\"assetTypeIndex.searchPlaceholder\")}\n\t\t\t/>\n\t\t\t{listFailure ? null : (\n\t\t\t\t<Toolbar.Right>\n\t\t\t\t\t<Toolbar.Count>\n\t\t\t\t\t\t{t(\"assetTypeIndex.typesCount\", { count: filtered.length })}\n\t\t\t\t\t</Toolbar.Count>\n\t\t\t\t</Toolbar.Right>\n\t\t\t)}\n\t\t</Toolbar>\n\t);\n\n\treturn (\n\t\t<IndexPageTemplate\n\t\t\tbreadcrumbs={[{ label: t(\"assetTypeIndex.pageTitle\") }]}\n\t\t\ttitle={t(\"assetTypeIndex.pageTitle\")}\n\t\t\tsubtitle={t(\"assetTypeIndex.pageSubtitle\")}\n\t\t\tactions={\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tonClick={() => onCreate?.()}\n\t\t\t\t>\n\t\t\t\t\t{t(\"assetTypeIndex.newButton\")}\n\t\t\t\t</Button>\n\t\t\t}\n\t\t\ttoolbar={toolbar}\n\t\t>\n\t\t\t{listFailure ? (\n\t\t\t\t<EmptyState\n\t\t\t\t\theader={t(\"assetTypeIndex.loadFailedHeader\")}\n\t\t\t\t\tdescription={\n\t\t\t\t\t\tdescribeRpcError(listFailure, t(\"assetTypeIndex.loadFailedHeader\"))\n\t\t\t\t\t\t\t.description\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<DataTable\n\t\t\t\t\tcolumns={columns as ColumnDef<Record<string, unknown>, unknown>[]}\n\t\t\t\t\tdata={filtered as unknown as Record<string, unknown>[]}\n\t\t\t\t\tgetRowId={(row) => (row as unknown as AssetTypeInfo).id}\n\t\t\t\t\tonRowClick={(row) => onOpen?.((row as unknown as AssetTypeInfo).id)}\n\t\t\t\t\tloading={assetTypesQuery.isLoading}\n\t\t\t\t\temptyState={\n\t\t\t\t\t\t<EmptyState\n\t\t\t\t\t\t\theader={\n\t\t\t\t\t\t\t\tsearch.trim()\n\t\t\t\t\t\t\t\t\t? t(\"assetTypeIndex.noMatchesHeader\")\n\t\t\t\t\t\t\t\t\t: t(\"assetTypeIndex.noAssetTypesHeader\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdescription={\n\t\t\t\t\t\t\t\tsearch.trim()\n\t\t\t\t\t\t\t\t\t? t(\"assetTypeIndex.noMatchesDescription\")\n\t\t\t\t\t\t\t\t\t: t(\"assetTypeIndex.noAssetTypesDescription\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tactions={\n\t\t\t\t\t\t\t\tsearch.trim() ? undefined : (\n\t\t\t\t\t\t\t\t\t<Button size=\"sm\" onClick={() => onCreate?.()}>\n\t\t\t\t\t\t\t\t\t\t{t(\"assetTypeIndex.newButton\")}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t\tvariant=\"line\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</IndexPageTemplate>\n\t);\n}\nAssetTypeIndex.displayName = \"AssetTypeIndex\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, EmptyState, IconButton } from \"@knkcs/anker/atoms\";\nimport { useConfirmModal } from \"@knkcs/anker/feedback\";\nimport { InputField, TextareaField } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tHStack,\n\tSpinner,\n\tStack,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { DetailPageTemplate } from \"@knkcs/anker/templates\";\nimport { ArrowLeft, Lock, LockOpen, Users } from \"lucide-react\";\nimport type React from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { LeakGuardRefusalDialog } from \"./components/leak-guard-refusal-dialog\";\nimport { ManageAccessDialog } from \"./components/manage-access-dialog\";\nimport {\n\tRestrictedLockBadge,\n\tunrestrictDisclosure,\n} from \"./components/restricted\";\nimport { useCanManage } from \"./hooks/use-authz\";\nimport {\n\tuseCollection,\n\tuseDeleteCollection,\n\tuseSetCollectionRestricted,\n\tuseUpdateCollection,\n} from \"./hooks/use-collections\";\nimport {\n\ttype RpcErrorDescription,\n\tdescribeRpcError,\n\tshowRpcErrorToast,\n} from \"./lib/rpc-errors\";\n\ntype IdentityForm = {\n\tname: string;\n\tdescription: string;\n};\n\nexport interface CollectionDetailProps {\n\t/** The collection to show. */\n\tcollectionId: string;\n\t/**\n\t * Typed path of the host's collection index, used for the breadcrumb back\n\t * link. The screen never routes itself — the host owns its URLs\n\t * (core's `docs/service-integration.md`).\n\t */\n\tcollectionsPath?: string;\n\t/**\n\t * Navigate back to the collection index. Given one, the screen renders a\n\t * back affordance that confirms before discarding unsaved edits — the\n\t * breadcrumb link above is the host's own navigation and the screen cannot\n\t * intercept it.\n\t */\n\tonBack?: () => void;\n\t/** Called after a successful delete; the host decides where to go next. */\n\tonDeleted?: () => void;\n}\n\n/**\n * The packaged collection detail screen: view one Collection, correct its name\n * and description, delete it behind a confirmation, and — for an authority —\n * decide who may see it.\n *\n * **Authority, per ADR 0001**, is owner-on-the-Collection *or* admin-on-its-\n * workspace, and the package already answers it: `useCanManage` probes it by\n * attempting the roster read the server gates on exactly that authority. Only\n * `data === true` unlocks anything — a pending probe, a denial and a failure\n * all render the same screen without management controls (fail closed).\n *\n * **A denial is an answer, not a failure.** `canManage` reads Connect's\n * *numeric* code 7 as \"not an authority\" and returns false. A host transport\n * that flattens errors to a bare message (core's did until\n * knkboor/general#814) turns that answer into a rejection — which this screen\n * survives, because a rejected probe is not `true` either, so the controls\n * stay hidden instead of the screen breaking for the users with least access.\n * Both shapes are pinned by test.\n *\n * **Grantees never see the roster** (ADR 0001 again): content access and\n * roster access are separate privileges, so a viewer gets the Collection's\n * identity and no Manage Access affordance at all — the roster is never\n * fetched for them, not merely hidden after the fact. Authority withdrawn\n * *mid-session* takes the controls away at once and closes an open dialog\n * through its `open` prop — the machine itself stays mounted, because\n * unmounting a dialog while it is open leaks the body scroll lock over the\n * whole application (CLAUDE-ANKER's Modal mount pattern). The Restricted state\n * itself is on the record they already read and is shown to everyone, as the\n * index and the folder tree show it.\n *\n * **Curation** — adding and removing assets — is not this screen's job: per\n * ADR 0003 it happens in the library, where the assets are.\n *\n * **The patch is the whole record this screen owns, every time.**\n * `UpdateCollectionRequest` carries plain proto3 scalars and the service applies\n * `description` unconditionally, so a patch naming only `name` clears the\n * description (knkCS/mediahub#159, the same trap as knkcms/core#863). Saving\n * therefore sends both fields, and deliberately does *not* name `rules` — the\n * smart-collection field this surface does not edit (knkCS/mediahub#173) — so\n * the client's read-modify-write keeps whatever is stored there.\n *\n * **Correct against the wire, not against the declared type.** Connect omits\n * empty strings from its JSON, so a description-less collection arrives with\n * the key absent. Every field is defaulted where it is read, so an absent value\n * renders as empty rather than flipping a controlled input to uncontrolled.\n */\nexport function CollectionDetail({\n\tcollectionId,\n\tcollectionsPath,\n\tonBack,\n\tonDeleted,\n}: CollectionDetailProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst { confirm } = useConfirmModal();\n\n\tconst collectionQuery = useCollection(collectionId);\n\tconst collection = collectionQuery.data;\n\tconst updateCollection = useUpdateCollection();\n\tconst deleteCollection = useDeleteCollection();\n\tconst setRestricted = useSetCollectionRestricted();\n\n\t// Fail closed: only an affirmative probe is authority. Pending, denied and\n\t// failed all read the same here — see the class comment.\n\tconst canManage = useCanManage(\"collection\", collectionId);\n\tconst isAuthority = canManage.data === true;\n\n\tconst [accessOpen, setAccessOpen] = useState(false);\n\t// The refusal stays mounted while its dialog animates closed (dialog\n\t// machines must not unmount mid-exit, #66).\n\tconst [refusal, setRefusal] = useState<RpcErrorDescription | null>(null);\n\tconst [refusalOpen, setRefusalOpen] = useState(false);\n\n\t// `isAuthority` is live: a background refetch of the probe can answer\n\t// `false` for someone whose authority was revoked mid-session. The\n\t// controls must vanish at that moment — but the dialog MACHINES must not,\n\t// because unmounting one while it is open orphans zag's cleanup and leaks\n\t// the body scroll lock over the whole app (CLAUDE-ANKER, #66). So\n\t// authority latches for the mount and is closed through `open` instead.\n\tconst [everAuthority, setEverAuthority] = useState(false);\n\tuseEffect(() => {\n\t\tif (isAuthority) {\n\t\t\tsetEverAuthority(true);\n\t\t\treturn;\n\t\t}\n\t\tsetAccessOpen(false);\n\t\tsetRefusalOpen(false);\n\t}, [isAuthority]);\n\n\tconst zodSchema = useMemo(\n\t\t() =>\n\t\t\tz.object({\n\t\t\t\tname: z.string().min(1, t(\"collectionDetail.nameRequired\")),\n\t\t\t\tdescription: z.string(),\n\t\t\t}),\n\t\t[t],\n\t);\n\n\t// Memoized on the query data, which TanStack Query keeps referentially\n\t// stable across no-op background refetches (structural sharing) — so\n\t// `values` below re-baselines only when the record actually changes.\n\tconst values = useMemo<IdentityForm>(\n\t\t() => ({\n\t\t\tname: collection?.name ?? \"\",\n\t\t\tdescription: collection?.description ?? \"\",\n\t\t}),\n\t\t[collection],\n\t);\n\n\t// `values` + keepDirtyValues: a background refetch updates clean fields but\n\t// never clobbers an edit in progress (same contract as <AssetTypeDetail>).\n\tconst form = useForm<IdentityForm>({\n\t\tresolver: zodResolver(zodSchema),\n\t\tvalues,\n\t\tresetOptions: { keepDirtyValues: true },\n\t});\n\n\tasync function handleSave(data: IdentityForm) {\n\t\ttry {\n\t\t\tawait updateCollection.mutateAsync({\n\t\t\t\tid: collectionId,\n\t\t\t\t// Both fields, always — see the #159 note above. `rules` is absent\n\t\t\t\t// on purpose: absence is what preserves it.\n\t\t\t\tpatch: { name: data.name, description: data.description },\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"collectionDetail.saveSuccessToast\") });\n\t\t\tform.reset(data); // re-baseline: the submitted values are committed\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionDetail.saveFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleDelete() {\n\t\tconst confirmed = await confirm({\n\t\t\ttitle: t(\"collectionDetail.deleteConfirmTitle\"),\n\t\t\tmessage: t(\"collectionDetail.deleteConfirmMessage\", {\n\t\t\t\tcollectionName: collection?.name ?? \"\",\n\t\t\t}),\n\t\t\tconfirmLabel: t(\"collectionDetail.deleteConfirmLabel\"),\n\t\t});\n\t\tif (!confirmed) return;\n\t\ttry {\n\t\t\tawait deleteCollection.mutateAsync(collectionId);\n\t\t\ttoaster.success({ title: t(\"collectionDetail.deleteSuccessToast\") });\n\t\t\tonDeleted?.();\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionDetail.deleteFailedToast\"));\n\t\t}\n\t}\n\n\tasync function handleToggleRestricted() {\n\t\tif (!collection) return;\n\t\tconst restricting = !collection.restricted;\n\t\t// Unrestricting widens the audience to the whole workspace, so it is\n\t\t// spelled out before it happens (guardian#55). Restricting only narrows.\n\t\tif (!restricting) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"collectionDetail.unrestrictConfirmTitle\"),\n\t\t\t\tmessage: unrestrictDisclosure(\"collection\", collection.name, t),\n\t\t\t\tconfirmLabel: t(\"collectionDetail.unrestrictConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\ttry {\n\t\t\tawait setRestricted.mutateAsync({\n\t\t\t\tid: collectionId,\n\t\t\t\trestricted: restricting,\n\t\t\t});\n\t\t\ttoaster.success({\n\t\t\t\ttitle: restricting\n\t\t\t\t\t? t(\"collectionDetail.restrictSuccessToast\")\n\t\t\t\t\t: t(\"collectionDetail.unrestrictSuccessToast\"),\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconst fallback = restricting\n\t\t\t\t? t(\"collectionDetail.restrictFailedToast\")\n\t\t\t\t: t(\"collectionDetail.unrestrictFailedToast\");\n\t\t\tconst described = describeRpcError(err, fallback);\n\t\t\t// A leak-guard refusal gets the dialog that NAMES the offending\n\t\t\t// asset→collection pairs — never a generic failure toast.\n\t\t\tif (described.kind === \"leak-guard\") {\n\t\t\t\tsetRefusal(described);\n\t\t\t\tsetRefusalOpen(true);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tshowRpcErrorToast(err, fallback);\n\t\t}\n\t}\n\n\tasync function handleBack() {\n\t\tif (form.formState.isDirty) {\n\t\t\tconst confirmed = await confirm({\n\t\t\t\ttitle: t(\"collectionDetail.discardConfirmTitle\"),\n\t\t\t\tmessage: t(\"collectionDetail.discardConfirmMessage\"),\n\t\t\t\tconfirmLabel: t(\"collectionDetail.discardConfirmLabel\"),\n\t\t\t});\n\t\t\tif (!confirmed) return;\n\t\t}\n\t\tonBack?.();\n\t}\n\n\tif (collectionQuery.isLoading) {\n\t\treturn (\n\t\t\t<Flex justify=\"center\" align=\"center\" minH=\"400px\">\n\t\t\t\t<Spinner />\n\t\t\t</Flex>\n\t\t);\n\t}\n\n\tif (!collection) {\n\t\treturn <EmptyState header={t(\"collectionDetail.notFound\")} />;\n\t}\n\n\tconst title = collection.name || t(\"collectionDetail.untitled\");\n\n\treturn (\n\t\t<DetailPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{\n\t\t\t\t\tlabel: t(\"collectionDetail.breadcrumbCollections\"),\n\t\t\t\t\tto: collectionsPath,\n\t\t\t\t},\n\t\t\t\t{ label: title },\n\t\t\t]}\n\t\t\ttitle={title}\n\t\t\t// The Restricted state is on the screen itself, not only in the\n\t\t\t// control that changes it — and it is shown to everyone who can see\n\t\t\t// the Collection, exactly as the index and the folder tree show it.\n\t\t\tbadges={\n\t\t\t\tcollection.restricted ? <RestrictedLockBadge size={14} /> : undefined\n\t\t\t}\n\t\t\tavatar={\n\t\t\t\tonBack ? (\n\t\t\t\t\t<IconButton\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\taria-label={t(\"collectionDetail.backButtonAria\")}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tvoid handleBack();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowLeft size={18} />\n\t\t\t\t\t</IconButton>\n\t\t\t\t) : undefined\n\t\t\t}\n\t\t\tactions={\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={!form.formState.isDirty}\n\t\t\t\t\t\tloading={updateCollection.isPending}\n\t\t\t\t\t\tonClick={form.handleSubmit(handleSave)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"collectionDetail.save\")}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tcolorPalette=\"red\"\n\t\t\t\t\t\tloading={deleteCollection.isPending}\n\t\t\t\t\t\tonClick={handleDelete}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t(\"collectionDetail.delete\")}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t}\n\t\t>\n\t\t\t<Stack gap=\"4\" px=\"8\" py=\"6\">\n\t\t\t\t<FormProvider {...form}>\n\t\t\t\t\t<Stack gap={4} maxW=\"lg\">\n\t\t\t\t\t\t<InputField<IdentityForm>\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\tlabel={t(\"collectionDetail.nameLabel\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<Box>\n\t\t\t\t\t\t\t<Text color=\"fg.muted\" fontSize=\"sm\">\n\t\t\t\t\t\t\t\t{t(\"collectionDetail.slugLabel\")}: {collection.slug ?? \"\"}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t<TextareaField<IdentityForm>\n\t\t\t\t\t\t\tname=\"description\"\n\t\t\t\t\t\t\tlabel={t(\"collectionDetail.descriptionLabel\")}\n\t\t\t\t\t\t\tplaceholder={t(\"collectionDetail.descriptionPlaceholder\")}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</Stack>\n\t\t\t\t</FormProvider>\n\n\t\t\t\t{/* Everything below is authority-only (ADR 0001). A non-authority\n\t\t\t\t reaches neither the controls nor the roster — the dialogs are\n\t\t\t\t not mounted at all, so nothing here asks the server for a\n\t\t\t\t roster on their behalf.\n\n\t\t\t\t The CONTROLS follow the live probe; the DIALOGS follow the\n\t\t\t\t latch, so authority withdrawn mid-session closes an open\n\t\t\t\t dialog through `open` rather than yanking its machine out\n\t\t\t\t from under it. A latch never mounts for someone the probe\n\t\t\t\t has not answered `true` for, so the roster is still never\n\t\t\t\t read on a non-authority's behalf. */}\n\t\t\t\t{everAuthority && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<ManageAccessDialog\n\t\t\t\t\t\t\topen={accessOpen}\n\t\t\t\t\t\t\tonOpenChange={setAccessOpen}\n\t\t\t\t\t\t\tsubject={{ kind: \"collection\", collection }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<LeakGuardRefusalDialog\n\t\t\t\t\t\t\trefusal={refusal}\n\t\t\t\t\t\t\topen={refusalOpen}\n\t\t\t\t\t\t\tonClose={() => setRefusalOpen(false)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t\t{isAuthority && (\n\t\t\t\t\t<Stack gap=\"3\" maxW=\"lg\">\n\t\t\t\t\t\t<Text fontWeight=\"medium\">\n\t\t\t\t\t\t\t{t(\"collectionDetail.accessHeading\")}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t<HStack\n\t\t\t\t\t\t\tgap=\"2\"\n\t\t\t\t\t\t\talign=\"flex-start\"\n\t\t\t\t\t\t\tpx=\"3\"\n\t\t\t\t\t\t\tpy=\"2\"\n\t\t\t\t\t\t\trounded=\"md\"\n\t\t\t\t\t\t\tbg=\"bg.muted\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{collection.restricted && (\n\t\t\t\t\t\t\t\t<Lock size={14} style={{ marginTop: 2 }} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t{collection.restricted\n\t\t\t\t\t\t\t\t\t? t(\"collectionDetail.accessRestrictedNote\")\n\t\t\t\t\t\t\t\t\t: t(\"collectionDetail.accessOpenNote\")}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\t\t\tloading={setRestricted.isPending}\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tvoid handleToggleRestricted();\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{collection.restricted ? (\n\t\t\t\t\t\t\t\t\t<LockOpen size={16} />\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<Lock size={16} />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t{collection.restricted\n\t\t\t\t\t\t\t\t\t? t(\"collectionDetail.unrestrict\")\n\t\t\t\t\t\t\t\t\t: t(\"collectionDetail.restrict\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\t\t\tonClick={() => setAccessOpen(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Users size={16} />\n\t\t\t\t\t\t\t\t{t(\"collectionDetail.manageAccess\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t</Stack>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t</DetailPageTemplate>\n\t);\n}\nCollectionDetail.displayName = \"CollectionDetail\";\n","// components/picker/picker-asset-card.tsx\nimport { SelectableCard } from \"@knkcs/anker/components\";\nimport { Skeleton, Text } from \"@knkcs/anker/primitives\";\nimport { FileText, Film, Image as ImageIcon, Music } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { usePreviewURL } from \"../../hooks/use-preview-url\";\nimport type { AssetInfo } from \"../../types\";\nimport { AssetStatusBadge } from \"../asset-status-badge\";\n\n/** Latest-version MIME category. Mirrors asset-grid.tsx. */\nexport function getMimeCategory(asset: AssetInfo): string {\n\tconst version = asset.versions[asset.versions.length - 1];\n\tif (!version) return \"unknown\";\n\tconst mime = version.mimeType;\n\tif (mime.startsWith(\"image/\")) return \"image\";\n\tif (mime.startsWith(\"video/\")) return \"video\";\n\tif (mime.startsWith(\"audio/\")) return \"audio\";\n\tif (mime === \"application/pdf\") return \"pdf\";\n\treturn \"unknown\";\n}\n\nfunction TypeIcon({ category }: { category: string }) {\n\tswitch (category) {\n\t\tcase \"image\":\n\t\t\treturn <ImageIcon size={32} opacity={0.3} />;\n\t\tcase \"video\":\n\t\t\treturn <Film size={32} opacity={0.3} />;\n\t\tcase \"audio\":\n\t\t\treturn <Music size={32} opacity={0.3} />;\n\t\tdefault:\n\t\t\treturn <FileText size={32} opacity={0.3} />;\n\t}\n}\nTypeIcon.displayName = \"TypeIcon\";\n\nexport interface PickerAssetCardProps {\n\tasset: AssetInfo;\n\tselected: boolean;\n\tselectionVisible: boolean;\n\tonToggle: (asset: AssetInfo) => void;\n}\n\nexport const PickerAssetCard: React.FC<PickerAssetCardProps> = ({\n\tasset,\n\tselected,\n\tselectionVisible,\n\tonToggle,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst category = getMimeCategory(asset);\n\tconst latestVersion = asset.versions[asset.versions.length - 1];\n\tconst previewQuery = usePreviewURL(\n\t\tcategory === \"image\" && latestVersion ? asset.id : \"\",\n\t\tlatestVersion?.id ?? \"\",\n\t);\n\tconst previewUrl = previewQuery.data;\n\tconst [imgError, setImgError] = useState(false);\n\n\treturn (\n\t\t<SelectableCard\n\t\t\tselected={selected}\n\t\t\tselectionVisible={selectionVisible}\n\t\t\tonSelect={() => onToggle(asset)}\n\t\t\tonClick={() => onToggle(asset)}\n\t\t>\n\t\t\t<SelectableCard.Thumbnail height=\"120px\">\n\t\t\t\t{category === \"image\" && previewUrl && !imgError ? (\n\t\t\t\t\t<img\n\t\t\t\t\t\tsrc={previewUrl}\n\t\t\t\t\t\talt={asset.name || t(\"common.assetPreviewAlt\")}\n\t\t\t\t\t\tonError={() => setImgError(true)}\n\t\t\t\t\t\tstyle={{ width: \"100%\", height: \"100%\", objectFit: \"cover\" }}\n\t\t\t\t\t/>\n\t\t\t\t) : category === \"image\" && previewQuery.isLoading ? (\n\t\t\t\t\t<Skeleton w=\"full\" h=\"full\" />\n\t\t\t\t) : (\n\t\t\t\t\t<TypeIcon category={category} />\n\t\t\t\t)}\n\t\t\t</SelectableCard.Thumbnail>\n\t\t\t<SelectableCard.Body>\n\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" truncate>\n\t\t\t\t\t{asset.name}\n\t\t\t\t</Text>\n\t\t\t</SelectableCard.Body>\n\t\t\t<SelectableCard.Footer>\n\t\t\t\t<AssetStatusBadge slug={asset.statusSlug} />\n\t\t\t</SelectableCard.Footer>\n\t\t</SelectableCard>\n\t);\n};\nPickerAssetCard.displayName = \"PickerAssetCard\";\n","// components/picker/picker-footer.tsx\nimport { Button } from \"@knkcs/anker/atoms\";\nimport { Box, Flex, HStack, Text } from \"@knkcs/anker/primitives\";\nimport { useTranslation } from \"react-i18next\";\n\nexport interface PickerFooterProps {\n\tcount: number;\n\tconfirmLabel: string;\n\tcancelLabel: string;\n\tonConfirm: () => void;\n\tonCancel: () => void;\n\t/** Optional selection-strip content rendered on the left. */\n\tchildren?: React.ReactNode;\n}\n\nexport const PickerFooter: React.FC<PickerFooterProps> = ({\n\tcount,\n\tconfirmLabel,\n\tcancelLabel,\n\tonConfirm,\n\tonCancel,\n\tchildren,\n}) => {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\treturn (\n\t\t<Flex align=\"center\" gap=\"3\" w=\"full\">\n\t\t\t<HStack gap=\"2\" minW=\"0\" flex=\"1\">\n\t\t\t\t{children}\n\t\t\t\t<Text fontSize=\"sm\" color=\"fg.muted\" flexShrink={0}>\n\t\t\t\t\t{t(\"common.selectedCount\", { count })}\n\t\t\t\t</Text>\n\t\t\t</HStack>\n\t\t\t<Box flexShrink={0}>\n\t\t\t\t<HStack gap=\"2\">\n\t\t\t\t\t<Button variant=\"ghost\" onClick={onCancel}>\n\t\t\t\t\t\t{cancelLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\tdisabled={count === 0}\n\t\t\t\t\t\tonClick={onConfirm}\n\t\t\t\t\t>\n\t\t\t\t\t\t{confirmLabel}\n\t\t\t\t\t</Button>\n\t\t\t\t</HStack>\n\t\t\t</Box>\n\t\t</Flex>\n\t);\n};\nPickerFooter.displayName = \"PickerFooter\";\n","import { useCallback, useState } from \"react\";\n\nexport interface PickerSelection<T extends { id: string }> {\n\t/** Currently-selected full objects, in selection order. */\n\titems: T[];\n\tisSelected: (id: string) => boolean;\n\t/** Toggle an item. In single mode, selecting replaces any prior selection. */\n\ttoggle: (item: T) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n}\n\nexport function usePickerSelection<T extends { id: string }>(\n\tmode: \"single\" | \"multi\",\n): PickerSelection<T> {\n\tconst [items, setItems] = useState<T[]>([]);\n\n\tconst toggle = useCallback(\n\t\t(item: T) => {\n\t\t\tsetItems((prev) => {\n\t\t\t\tconst exists = prev.some((i) => i.id === item.id);\n\t\t\t\tif (mode === \"single\") return exists ? [] : [item];\n\t\t\t\treturn exists ? prev.filter((i) => i.id !== item.id) : [...prev, item];\n\t\t\t});\n\t\t},\n\t\t[mode],\n\t);\n\n\tconst remove = useCallback(\n\t\t(id: string) => setItems((prev) => prev.filter((i) => i.id !== id)),\n\t\t[],\n\t);\n\tconst clear = useCallback(() => setItems([]), []);\n\tconst isSelected = useCallback(\n\t\t(id: string) => items.some((i) => i.id === id),\n\t\t[items],\n\t);\n\n\treturn { items, isSelected, toggle, remove, clear };\n}\n","// asset-picker.tsx\nimport { EmptyState } from \"@knkcs/anker/atoms\";\nimport { Modal } from \"@knkcs/anker/components\";\nimport { SearchInput } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tGrid,\n\tHStack,\n\tNativeSelect,\n\tSpinner,\n\tText,\n} from \"@knkcs/anker/primitives\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { FolderTree } from \"./components/folder-tree\";\nimport {\n\tPickerAssetCard,\n\tgetMimeCategory,\n} from \"./components/picker/picker-asset-card\";\nimport { PickerFooter } from \"./components/picker/picker-footer\";\nimport { usePickerSelection } from \"./components/picker/use-picker-selection\";\nimport { UploadDialog } from \"./components/upload/upload-dialog\";\nimport { UploadDropZone } from \"./components/upload/upload-drop-zone\";\nimport { useAssets } from \"./hooks/use-assets\";\nimport { usePreviewURL } from \"./hooks/use-preview-url\";\nimport { useAssetStatuses } from \"./statushub\";\nimport { useUploadStore } from \"./stores/upload-store\";\nimport type { AssetFilters, AssetInfo, AssetSelection } from \"./types\";\n\nexport interface AssetPickerProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\t/** @default \"single\" */\n\tmode?: \"single\" | \"multi\";\n\tonSelect: (selection: AssetSelection) => void;\n\t/** Enable upload-then-select (wired in Task 5). */\n\tallowUpload?: boolean;\n\t/** Client-side MIME filter, e.g. [\"image/*\"] or [\"application/pdf\"]. */\n\taccept?: string[];\n\t/** Initial/locked filters (e.g. a fixed assetTypeId). */\n\tinitialFilters?: AssetFilters;\n}\n\nfunction matchesAccept(asset: AssetInfo, accept: string[]): boolean {\n\tconst v = asset.versions[asset.versions.length - 1];\n\tif (!v) return false;\n\tconst mime = v.mimeType;\n\treturn accept.some((a) =>\n\t\ta.endsWith(\"/*\")\n\t\t\t? mime.startsWith(a.slice(0, a.indexOf(\"/\") + 1))\n\t\t\t: mime === a,\n\t);\n}\n\nexport function AssetPicker(props: AssetPickerProps): React.JSX.Element {\n\tconst { open, onOpenChange, onSelect, accept, initialFilters } = props;\n\tconst mode = props.mode ?? \"single\";\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst [filters, setFilters] = useState<AssetFilters>(initialFilters ?? {});\n\tconst folderId = filters.folderId ?? \"\";\n\tconst statusSlug = filters.statusSlug ?? \"\";\n\n\tconst selection = usePickerSelection<AssetInfo>(mode);\n\n\tfunction updateFilter<K extends keyof AssetFilters>(\n\t\tkey: K,\n\t\tvalue: AssetFilters[K],\n\t) {\n\t\tsetFilters((prev) => {\n\t\t\tconst next: AssetFilters = { ...prev };\n\t\t\tif (value === undefined || value === \"\") delete next[key];\n\t\t\telse next[key] = value;\n\t\t\treturn next;\n\t\t});\n\t}\n\n\tconst assetsQuery = useAssets(filters);\n\t// The workspace's own catalogue, read from statushub (§10).\n\tconst statusOptions = useAssetStatuses().data ?? [];\n\tconst allItems = assetsQuery.data?.items ?? [];\n\tconst items = useMemo(\n\t\t() =>\n\t\t\taccept?.length\n\t\t\t\t? allItems.filter((a) => matchesAccept(a, accept))\n\t\t\t\t: allItems,\n\t\t[allItems, accept],\n\t);\n\n\tconst allowUpload = props.allowUpload ?? false;\n\tconst addFiles = useUploadStore((s) => s.addFiles);\n\tconst uploadFiles = useUploadStore((s) => s.files);\n\tconst [uploadDialogOpen, setUploadDialogOpen] = useState(false);\n\t// assetIds already bridged this session — keeps the effect idempotent.\n\t// Not cleared on deselect, so re-uploading the same asset in one session\n\t// won't re-select it (acceptable for v1).\n\tconst bridgedRef = useRef<Set<string>>(new Set());\n\n\tfunction handleFilesSelected(files: File[]) {\n\t\taddFiles(files);\n\t\tsetUploadDialogOpen(true);\n\t}\n\n\t// Ephemeral picker state (selection/filters/upload dialog) is scrubbed in\n\t// the Modal's onExitComplete (not on `open` flipping false): the grid stays\n\t// visible through the exit animation, and an immediate reset would visibly\n\t// clear it mid-fade.\n\tfunction resetEphemeralState() {\n\t\tselection.clear();\n\t\tsetFilters(initialFilters ?? {});\n\t\tsetUploadDialogOpen(false);\n\t\tbridgedRef.current.clear();\n\t}\n\n\t// Fallback: zag presence skips onExitComplete when a reopen interrupts the\n\t// exit animation (fires only on the mounted→unmounted transition, not on\n\t// unmountSuspended→mounted) — reset again on open so a fast close-then-\n\t// reopen can't reopen with stale filters/selection/upload-dialog state.\n\t// Declared BEFORE the upload auto-select effect below: both run on the\n\t// same open-flip commit, and effects run in declaration order. This one\n\t// must go first — verified empirically, not just by inspection, because\n\t// the interaction is subtler than plain effect order: `bridgedRef` is a\n\t// ref (mutations are visible immediately to code in the same flush), but\n\t// `selection.isSelected` is a closure over the PRE-reset render, so\n\t// whichever effect runs second still sees the OLD selection value in that\n\t// same commit. What actually resolves it fresh is the cascade this reset\n\t// triggers: `selection.clear()` changes `usePickerSelection`'s `items`\n\t// state, which gives `isSelected` a new identity, which re-fires the\n\t// auto-select effect (it's in that effect's own deps) on the FOLLOWING\n\t// render — now with both `bridgedRef` and `selection.isSelected`\n\t// reflecting the real post-reset state. Swapping the order the other way\n\t// (auto-select first) was verified BY TEST to leave a stale bridge\n\t// re-selected after reopen instead of cleared — see the picker test file.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: reset only on open→true\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tresetEphemeralState();\n\t}, [open]);\n\n\t// Auto-select assets that finish uploading while the picker is open.\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tconst byId = new Map(items.map((a) => [a.id, a]));\n\t\tfor (const f of uploadFiles) {\n\t\t\tif (\n\t\t\t\tf.status === \"done\" &&\n\t\t\t\tf.assetId &&\n\t\t\t\t!bridgedRef.current.has(f.assetId)\n\t\t\t) {\n\t\t\t\tconst a = byId.get(f.assetId);\n\t\t\t\tif (a) {\n\t\t\t\t\t// Process each finalized upload once. Select it unless the user\n\t\t\t\t\t// already has it selected (don't deselect a manual pick).\n\t\t\t\t\tbridgedRef.current.add(f.assetId);\n\t\t\t\t\tif (!selection.isSelected(a.id)) {\n\t\t\t\t\t\tselection.toggle(a);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [open, items, uploadFiles, selection.toggle, selection.isSelected]);\n\n\tfunction handleConfirm() {\n\t\tif (selection.items.length === 0) return;\n\t\tonSelect(\n\t\t\tmode === \"single\"\n\t\t\t\t? { mode: \"single\", asset: selection.items[0] }\n\t\t\t\t: { mode: \"multi\", assets: selection.items },\n\t\t);\n\t\tonOpenChange(false);\n\t}\n\n\tconst count = selection.items.length;\n\tconst confirmLabel =\n\t\tmode === \"multi\" && count > 0\n\t\t\t? t(\"assetPicker.insertCount\", { count })\n\t\t\t: t(\"assetPicker.insert\");\n\n\t// Do NOT `return null` when closed: unmounting the open dialog machine\n\t// under StrictMode orphans its scroll-lock/aria-hidden cleanup and wedges\n\t// the whole app (#66). Keep Modal mounted; lazyMount/unmountOnExit keep\n\t// the fresh-content-per-open semantics.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={resetEphemeralState}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\t// Widest typed Modal size — the picker needs room for the folder rail\n\t\t\t// + multi-column grid. (anker's recipe-only \"7xl\" isn't in the type union.)\n\t\t\tsize=\"cover\"\n\t\t\theader={\n\t\t\t\tmode === \"single\"\n\t\t\t\t\t? t(\"assetPicker.headerSingle\")\n\t\t\t\t\t: t(\"assetPicker.headerMulti\")\n\t\t\t}\n\t\t\tfooter={\n\t\t\t\t<PickerFooter\n\t\t\t\t\tcount={count}\n\t\t\t\t\tconfirmLabel={confirmLabel}\n\t\t\t\t\tcancelLabel={t(\"assetPicker.cancel\")}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tonCancel={() => onOpenChange(false)}\n\t\t\t\t>\n\t\t\t\t\t<HStack gap=\"1\" minW=\"0\">\n\t\t\t\t\t\t{selection.items.slice(0, 8).map((a) => {\n\t\t\t\t\t\t\tconst v = a.versions[a.versions.length - 1];\n\t\t\t\t\t\t\tconst isImage = getMimeCategory(a) === \"image\";\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<Box\n\t\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\t\tposition=\"relative\"\n\t\t\t\t\t\t\t\t\tw=\"30px\"\n\t\t\t\t\t\t\t\t\th=\"30px\"\n\t\t\t\t\t\t\t\t\tborderRadius=\"md\"\n\t\t\t\t\t\t\t\t\toverflow=\"hidden\"\n\t\t\t\t\t\t\t\t\tborderWidth=\"1px\"\n\t\t\t\t\t\t\t\t\tborderColor=\"border\"\n\t\t\t\t\t\t\t\t\tflexShrink={0}\n\t\t\t\t\t\t\t\t\ttitle={a.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{isImage && v ? (\n\t\t\t\t\t\t\t\t\t\t<PickerStripThumb\n\t\t\t\t\t\t\t\t\t\t\tassetId={a.id}\n\t\t\t\t\t\t\t\t\t\t\tversionId={v.id}\n\t\t\t\t\t\t\t\t\t\t\tname={a.name}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<Flex\n\t\t\t\t\t\t\t\t\t\t\tw=\"full\"\n\t\t\t\t\t\t\t\t\t\t\th=\"full\"\n\t\t\t\t\t\t\t\t\t\t\talign=\"center\"\n\t\t\t\t\t\t\t\t\t\t\tjustify=\"center\"\n\t\t\t\t\t\t\t\t\t\t\tbg=\"bg.muted\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"2xs\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t\t\t\t\t{a.name.slice(0, 2)}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{count > 8 && (\n\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\" flexShrink={0}>\n\t\t\t\t\t\t\t\t{t(\"assetPicker.moreCount\", { count: count - 8 })}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</HStack>\n\t\t\t\t</PickerFooter>\n\t\t\t}\n\t\t>\n\t\t\t<Flex h=\"full\" minH=\"0\">\n\t\t\t\t<Box\n\t\t\t\t\tw=\"188px\"\n\t\t\t\t\tflexShrink={0}\n\t\t\t\t\tborderRightWidth=\"1px\"\n\t\t\t\t\tborderColor=\"border\"\n\t\t\t\t\tbg=\"bg.subtle\"\n\t\t\t\t\toverflowY=\"auto\"\n\t\t\t\t\tp=\"2\"\n\t\t\t\t>\n\t\t\t\t\t<FolderTree\n\t\t\t\t\t\tactiveFolderId={folderId}\n\t\t\t\t\t\tonFolderSelect={(id) => updateFilter(\"folderId\", id || undefined)}\n\t\t\t\t\t/>\n\t\t\t\t</Box>\n\t\t\t\t<Flex direction=\"column\" flex=\"1\" minW=\"0\">\n\t\t\t\t\t<Flex\n\t\t\t\t\t\tgap=\"3\"\n\t\t\t\t\t\talign=\"center\"\n\t\t\t\t\t\tpx=\"4\"\n\t\t\t\t\t\tpy=\"2\"\n\t\t\t\t\t\tborderBottomWidth=\"1px\"\n\t\t\t\t\t\tborderColor=\"border\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<SearchInput\n\t\t\t\t\t\t\tonSearch={(value) => updateFilter(\"search\", value || undefined)}\n\t\t\t\t\t\t\tdefaultValue={filters.search ?? \"\"}\n\t\t\t\t\t\t\tplaceholder={t(\"assetPicker.searchPlaceholder\")}\n\t\t\t\t\t\t\tmaxWidth=\"260px\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<HStack gap=\"1\">\n\t\t\t\t\t\t\t<Text fontSize=\"xs\" color=\"fg.muted\">\n\t\t\t\t\t\t\t\t{t(\"assetPicker.statusLabel\")}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t<NativeSelect\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tvalue={statusSlug}\n\t\t\t\t\t\t\t\tonChange={(e) =>\n\t\t\t\t\t\t\t\t\tupdateFilter(\"statusSlug\", e.target.value || undefined)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<option value=\"\">{t(\"assetPicker.statusFilterAll\")}</option>\n\t\t\t\t\t\t\t\t{statusOptions.map((s) => (\n\t\t\t\t\t\t\t\t\t<option key={s.id} value={s.slug}>\n\t\t\t\t\t\t\t\t\t\t{s.name}\n\t\t\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</NativeSelect>\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t</Flex>\n\t\t\t\t\t{allowUpload && (\n\t\t\t\t\t\t<Box px=\"4\" py=\"2\" borderBottomWidth=\"1px\" borderColor=\"border\">\n\t\t\t\t\t\t\t<UploadDropZone onFilesSelected={handleFilesSelected} compact />\n\t\t\t\t\t\t</Box>\n\t\t\t\t\t)}\n\t\t\t\t\t<Box flex=\"1\" overflow=\"auto\" p=\"4\">\n\t\t\t\t\t\t{assetsQuery.isLoading ? (\n\t\t\t\t\t\t\t<Flex justify=\"center\" py=\"10\">\n\t\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t\t</Flex>\n\t\t\t\t\t\t) : items.length === 0 ? (\n\t\t\t\t\t\t\t<EmptyState header={t(\"assetPicker.emptyLabel\")} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Grid\n\t\t\t\t\t\t\t\ttemplateColumns=\"repeat(auto-fill, minmax(150px, 1fr))\"\n\t\t\t\t\t\t\t\tgap=\"3\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{items.map((a) => (\n\t\t\t\t\t\t\t\t\t<PickerAssetCard\n\t\t\t\t\t\t\t\t\t\tkey={a.id}\n\t\t\t\t\t\t\t\t\t\tasset={a}\n\t\t\t\t\t\t\t\t\t\tselected={selection.isSelected(a.id)}\n\t\t\t\t\t\t\t\t\t\tselectionVisible={count > 0}\n\t\t\t\t\t\t\t\t\t\tonToggle={selection.toggle}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Box>\n\t\t\t\t</Flex>\n\t\t\t</Flex>\n\t\t\t{allowUpload && (\n\t\t\t\t<UploadDialog\n\t\t\t\t\topen={uploadDialogOpen}\n\t\t\t\t\tonClose={() => setUploadDialogOpen(false)}\n\t\t\t\t\tfolderId={folderId || undefined}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</Modal>\n\t);\n}\nAssetPicker.displayName = \"AssetPicker\";\n\n/** Footer thumbnail — fetches a preview URL for one selected image. */\nfunction PickerStripThumb({\n\tassetId,\n\tversionId,\n\tname,\n}: { assetId: string; versionId: string; name: string }) {\n\tconst { data } = usePreviewURL(assetId, versionId);\n\tif (!data) return <Box w=\"full\" h=\"full\" bg=\"bg.muted\" />;\n\treturn (\n\t\t<img\n\t\t\tsrc={data}\n\t\t\talt={name}\n\t\t\tstyle={{ width: \"100%\", height: \"100%\", objectFit: \"cover\" }}\n\t\t/>\n\t);\n}\nPickerStripThumb.displayName = \"PickerStripThumb\";\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { Button, TextInput } from \"@knkcs/anker/atoms\";\nimport { FormField, TextareaField } from \"@knkcs/anker/forms\";\nimport { HStack, Stack, toaster } from \"@knkcs/anker/primitives\";\nimport { SettingsPageTemplate } from \"@knkcs/anker/templates\";\nimport type React from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { z } from \"zod\";\n\nimport { useCreateCollection } from \"./hooks/use-collections\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport { slugify } from \"./lib/slugify\";\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface CollectionCreateProps {\n\t/**\n\t * The host's Collection index path — the breadcrumb's target. A path, not a\n\t * route: the screen never navigates, it only says where the list it belongs\n\t * to lives (core's `docs/service-integration.md`; spec #174).\n\t */\n\tcollectionsPath: string;\n\t/**\n\t * The Collection was created; the host receives its id and decides where to\n\t * go. Id only, like `CollectionIndex`'s `onOpen` — the host needs it to\n\t * build a detail URL, and nothing here knows what that URL looks like.\n\t */\n\tonCreated?: (collectionId: string) => void;\n\t/** Called when the administrator abandons the form. */\n\tonCancel?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// CollectionCreate\n// ---------------------------------------------------------------------------\n\n/**\n * Create a Collection. The package owns the screen; both hosts compose it and\n * keep their routing to themselves (#176, parent #174).\n *\n * **Static Collections only.** There is deliberately no Smart/Static selector\n * and no `rules` editor, though the standalone app's form dialog offered both.\n * A smart Collection's `rules` are validated as JSON, stored and returned —\n * and never evaluated anywhere; membership resolves exclusively through\n * explicit edges. The control would therefore do nothing at all, and this\n * project does not ship a known-inert control into a second host\n * (knkCS/mediahub#173). Every Collection created here is `static` with empty\n * rules.\n *\n * The slug follows the name until it is edited by hand and then stops, and the\n * server's rule (lowercase alphanumeric with hyphens, at least two characters)\n * is both stated on the form and enforced before submit — without both, a name\n * like `Bild Anhang` produced a bare 400 (knkcms/core#861).\n */\nexport function CollectionCreate({\n\tcollectionsPath,\n\tonCreated,\n\tonCancel,\n}: CollectionCreateProps): React.JSX.Element {\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\tconst createCollection = useCreateCollection();\n\n\t// Once the slug has been typed into it stops following the name. A flag\n\t// rather than react-hook-form's dirty state: clearing a hand-typed slug\n\t// back to empty would make the field clean again and silently resume the\n\t// autofill the administrator just opted out of.\n\tconst [slugEdited, setSlugEdited] = useState(false);\n\n\tconst schema = useMemo(\n\t\t() =>\n\t\t\tz.object({\n\t\t\t\tname: z.string().min(1, t(\"collectionCreate.nameRequired\")),\n\t\t\t\tslug: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(2, t(\"collectionCreate.slugInvalid\"))\n\t\t\t\t\t.regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, t(\"collectionCreate.slugInvalid\")),\n\t\t\t\tdescription: z.string(),\n\t\t\t}),\n\t\t[t],\n\t);\n\n\ttype FormValues = z.infer<typeof schema>;\n\n\tconst form = useForm<FormValues>({\n\t\tresolver: zodResolver(schema),\n\t\tdefaultValues: { name: \"\", slug: \"\", description: \"\" },\n\t});\n\n\tasync function onSubmit(values: FormValues) {\n\t\ttry {\n\t\t\tconst created = await createCollection.mutateAsync({\n\t\t\t\tname: values.name,\n\t\t\t\tslug: values.slug,\n\t\t\t\tdescription: values.description,\n\t\t\t\t// Static, always — see the note on this component.\n\t\t\t\ttype: \"static\",\n\t\t\t\trules: \"\",\n\t\t\t});\n\t\t\ttoaster.success({ title: t(\"collectionCreate.createdToast\") });\n\t\t\tonCreated?.(created.id);\n\t\t} catch (err) {\n\t\t\t// The server's reason, not a generic failure: a permission denial and\n\t\t\t// a validation refusal read differently to the person who caused them\n\t\t\t// (`lib/rpc-errors.ts`).\n\t\t\tshowRpcErrorToast(err, t(\"collectionCreate.createFailedToast\"));\n\t\t}\n\t}\n\n\tconst title = t(\"collectionCreate.title\");\n\n\treturn (\n\t\t<SettingsPageTemplate\n\t\t\tbreadcrumbs={[\n\t\t\t\t{\n\t\t\t\t\tlabel: t(\"collectionCreate.breadcrumbCollections\"),\n\t\t\t\t\tto: collectionsPath,\n\t\t\t\t},\n\t\t\t\t{ label: title },\n\t\t\t]}\n\t\t\ttitle={title}\n\t\t>\n\t\t\t<FormProvider {...form}>\n\t\t\t\t<form onSubmit={form.handleSubmit(onSubmit)} noValidate>\n\t\t\t\t\t<Stack gap=\"4\">\n\t\t\t\t\t\t<FormField<FormValues>\n\t\t\t\t\t\t\tname=\"name\"\n\t\t\t\t\t\t\tlabel={t(\"collectionCreate.nameLabel\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{(field) => (\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"collectionCreate.namePlaceholder\")}\n\t\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\tfield.onChange(e);\n\t\t\t\t\t\t\t\t\t\tif (!slugEdited) {\n\t\t\t\t\t\t\t\t\t\t\tform.setValue(\"slug\", slugify(e.target.value), {\n\t\t\t\t\t\t\t\t\t\t\t\tshouldValidate: form.formState.isSubmitted,\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</FormField>\n\n\t\t\t\t\t\t<FormField<FormValues>\n\t\t\t\t\t\t\tname=\"slug\"\n\t\t\t\t\t\t\tlabel={t(\"collectionCreate.slugLabel\")}\n\t\t\t\t\t\t\tdescription={t(\"collectionCreate.slugHint\")}\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{(field) => (\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\t{...field}\n\t\t\t\t\t\t\t\t\tvalue={field.value ?? \"\"}\n\t\t\t\t\t\t\t\t\tfontFamily=\"mono\"\n\t\t\t\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\t\t\t\tsetSlugEdited(true);\n\t\t\t\t\t\t\t\t\t\tfield.onChange(e);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</FormField>\n\n\t\t\t\t\t\t<TextareaField<FormValues>\n\t\t\t\t\t\t\tname=\"description\"\n\t\t\t\t\t\t\tlabel={t(\"collectionCreate.descriptionLabel\")}\n\t\t\t\t\t\t\tplaceholder={t(\"collectionCreate.descriptionPlaceholder\")}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<HStack gap=\"2\" justifyContent=\"flex-start\">\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\t\t\t\tloading={createCollection.isPending}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"collectionCreate.submit\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t{onCancel ? (\n\t\t\t\t\t\t\t\t<Button type=\"button\" variant=\"outline\" onClick={onCancel}>\n\t\t\t\t\t\t\t\t\t{t(\"collectionCreate.cancel\")}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t</Stack>\n\t\t\t\t</form>\n\t\t\t</FormProvider>\n\t\t</SettingsPageTemplate>\n\t);\n}\nCollectionCreate.displayName = \"CollectionCreate\";\n","import { Button, EmptyState } from \"@knkcs/anker/atoms\";\nimport { DataTable, Toolbar, TruncatedTextCell } from \"@knkcs/anker/components\";\nimport { Flex } from \"@knkcs/anker/primitives\";\nimport { IndexPageTemplate } from \"@knkcs/anker/templates\";\nimport { type ColumnDef, createColumnHelper } from \"@tanstack/react-table\";\nimport { useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { RestrictedLockBadge } from \"./components/restricted\";\nimport { useCollections } from \"./hooks/use-collections\";\nimport { describeRpcError } from \"./lib/rpc-errors\";\nimport type { CollectionInfo } from \"./types\";\n\nconst columnHelper = createColumnHelper<CollectionInfo>();\n\nexport interface CollectionIndexProps {\n\t/**\n\t * A collection was opened. The host decides what that means — it receives\n\t * the id and nothing else, because this package must not know either host's\n\t * URL structure (core's `docs/service-integration.md`; spec #138, #174).\n\t * Screens, not routes: nothing here navigates and nothing here builds a path.\n\t */\n\tonOpen?: (collectionId: string) => void;\n\t/** The reader asked for a new collection. Same contract as `onOpen`. */\n\tonCreate?: () => void;\n}\n\n/**\n * The workspace's Collections, listed. The package owns the screen; both hosts\n * compose it and keep their own routing to themselves (#175, parent #174).\n *\n * Listing is deliberately NOT gated by authority: a Collection the user can see\n * is listed, because per ADR 0001 seeing a Collection and managing it are\n * separate privileges. Management controls arrive in later tickets and are\n * gated there, on the can-manage probe — never here, on the listing.\n */\nexport function CollectionIndex(\n\tprops: CollectionIndexProps,\n): React.JSX.Element {\n\tconst { onOpen, onCreate } = props;\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst collectionsQuery = useCollections();\n\tconst [search, setSearch] = useState(\"\");\n\n\tconst collections = useMemo(\n\t\t() => collectionsQuery.data ?? [],\n\t\t[collectionsQuery.data],\n\t);\n\n\tconst filtered = useMemo(() => {\n\t\tconst query = search.trim().toLowerCase();\n\t\tif (!query) return collections;\n\t\treturn collections.filter((collection) =>\n\t\t\tcollection.name.toLowerCase().includes(query),\n\t\t);\n\t}, [collections, search]);\n\n\tconst columns = useMemo(\n\t\t() =>\n\t\t\t[\n\t\t\t\tcolumnHelper.accessor(\"name\", {\n\t\t\t\t\theader: t(\"collectionIndex.columnName\"),\n\t\t\t\t\tcell: (info) => (\n\t\t\t\t\t\t// The lock beside the name is how this package marks every\n\t\t\t\t\t\t// Restricted container (folder tree, collection picker); its\n\t\t\t\t\t\t// `aria-label` is the contract tests target.\n\t\t\t\t\t\t<Flex align=\"center\" gap={1}>\n\t\t\t\t\t\t\t<TruncatedTextCell value={info.getValue()} />\n\t\t\t\t\t\t\t{info.row.original.restricted ? <RestrictedLockBadge /> : null}\n\t\t\t\t\t\t</Flex>\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t\tcolumnHelper.accessor(\"description\", {\n\t\t\t\t\theader: t(\"collectionIndex.columnDescription\"),\n\t\t\t\t\tenableSorting: false,\n\t\t\t\t\tcell: (info) => <TruncatedTextCell value={info.getValue() ?? \"\"} />,\n\t\t\t\t}),\n\t\t\t] as ColumnDef<CollectionInfo, unknown>[],\n\t\t[t],\n\t);\n\n\t// A failed listing must SAY so rather than render as \"no collections\" — the\n\t// same rule the asset library follows for a refused listing\n\t// (knkCS/mediahub#120): an empty area over a refusal is the false answer the\n\t// server declined to give, arriving through the UI's door instead.\n\tconst listFailure = collectionsQuery.isError ? collectionsQuery.error : null;\n\n\tconst searching = search.trim().length > 0;\n\n\tconst toolbar = (\n\t\t<Toolbar>\n\t\t\t<Toolbar.Search\n\t\t\t\tvalue={search}\n\t\t\t\tonChange={setSearch}\n\t\t\t\tplaceholder={t(\"collectionIndex.searchPlaceholder\")}\n\t\t\t/>\n\t\t\t{listFailure ? null : (\n\t\t\t\t<Toolbar.Right>\n\t\t\t\t\t<Toolbar.Count>\n\t\t\t\t\t\t{t(\"collectionIndex.collectionsCount\", { count: filtered.length })}\n\t\t\t\t\t</Toolbar.Count>\n\t\t\t\t</Toolbar.Right>\n\t\t\t)}\n\t\t</Toolbar>\n\t);\n\n\treturn (\n\t\t<IndexPageTemplate\n\t\t\tbreadcrumbs={[{ label: t(\"collectionIndex.pageTitle\") }]}\n\t\t\ttitle={t(\"collectionIndex.pageTitle\")}\n\t\t\tsubtitle={t(\"collectionIndex.pageSubtitle\")}\n\t\t\tactions={\n\t\t\t\t<Button\n\t\t\t\t\tvariant=\"solid\"\n\t\t\t\t\tcolorPalette=\"primary\"\n\t\t\t\t\tonClick={() => onCreate?.()}\n\t\t\t\t>\n\t\t\t\t\t{t(\"collectionIndex.newButton\")}\n\t\t\t\t</Button>\n\t\t\t}\n\t\t\ttoolbar={toolbar}\n\t\t>\n\t\t\t{listFailure ? (\n\t\t\t\t<EmptyState\n\t\t\t\t\theader={t(\"collectionIndex.loadFailedHeader\")}\n\t\t\t\t\tdescription={\n\t\t\t\t\t\tdescribeRpcError(listFailure, t(\"collectionIndex.loadFailedHeader\"))\n\t\t\t\t\t\t\t.description\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<DataTable\n\t\t\t\t\tcolumns={columns as ColumnDef<Record<string, unknown>, unknown>[]}\n\t\t\t\t\tdata={filtered as unknown as Record<string, unknown>[]}\n\t\t\t\t\tgetRowId={(row) => (row as unknown as CollectionInfo).id}\n\t\t\t\t\tonRowClick={(row) => onOpen?.((row as unknown as CollectionInfo).id)}\n\t\t\t\t\tloading={collectionsQuery.isLoading}\n\t\t\t\t\temptyState={\n\t\t\t\t\t\t<EmptyState\n\t\t\t\t\t\t\theader={\n\t\t\t\t\t\t\t\tsearching\n\t\t\t\t\t\t\t\t\t? t(\"collectionIndex.noMatchesHeader\")\n\t\t\t\t\t\t\t\t\t: t(\"collectionIndex.noCollectionsHeader\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdescription={\n\t\t\t\t\t\t\t\tsearching\n\t\t\t\t\t\t\t\t\t? t(\"collectionIndex.noMatchesDescription\")\n\t\t\t\t\t\t\t\t\t: t(\"collectionIndex.noCollectionsDescription\")\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tactions={\n\t\t\t\t\t\t\t\tsearching ? undefined : (\n\t\t\t\t\t\t\t\t\t<Button size=\"sm\" onClick={() => onCreate?.()}>\n\t\t\t\t\t\t\t\t\t\t{t(\"collectionIndex.newButton\")}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t\tvariant=\"line\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t</IndexPageTemplate>\n\t);\n}\nCollectionIndex.displayName = \"CollectionIndex\";\n","// collection-picker.tsx\nimport { Button, EmptyState, TextInput } from \"@knkcs/anker/atoms\";\nimport { Modal, SelectableCard } from \"@knkcs/anker/components\";\nimport { SearchInput } from \"@knkcs/anker/forms\";\nimport {\n\tBox,\n\tFlex,\n\tGrid,\n\tHStack,\n\tSpinner,\n\tText,\n\ttoaster,\n} from \"@knkcs/anker/primitives\";\nimport { FolderOpen } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { PickerFooter } from \"./components/picker/picker-footer\";\nimport { usePickerSelection } from \"./components/picker/use-picker-selection\";\nimport { RestrictedLockBadge } from \"./components/restricted\";\nimport { useCollections, useCreateCollection } from \"./hooks/use-collections\";\nimport { showRpcErrorToast } from \"./lib/rpc-errors\";\nimport type { CollectionInfo, CollectionSelection } from \"./types\";\n\nexport interface CollectionPickerProps {\n\topen: boolean;\n\tonOpenChange: (open: boolean) => void;\n\t/** @default \"single\" */\n\tmode?: \"single\" | \"multi\";\n\tonSelect: (selection: CollectionSelection) => void;\n\t/** Show the inline \"New collection\" affordance. @default false */\n\tallowCreate?: boolean;\n}\n\nexport function CollectionPicker(\n\tprops: CollectionPickerProps,\n): React.JSX.Element {\n\tconst { open, onOpenChange, onSelect, allowCreate } = props;\n\tconst mode = props.mode ?? \"single\";\n\tconst { t } = useTranslation(\"mediahub-ui\");\n\n\tconst [search, setSearch] = useState(\"\");\n\tconst [newName, setNewName] = useState(\"\");\n\tconst selection = usePickerSelection<CollectionInfo>(mode);\n\n\tconst collectionsQuery = useCollections();\n\tconst createCollection = useCreateCollection();\n\tconst all = collectionsQuery.data ?? [];\n\tconst items = search\n\t\t? all.filter((c) => c.name.toLowerCase().includes(search.toLowerCase()))\n\t\t: all;\n\n\t// Ephemeral picker state (selection/search/inline-create name) is scrubbed\n\t// in the Modal's onExitComplete (not on `open` flipping false): the grid\n\t// stays visible through the exit animation, and an immediate reset would\n\t// visibly clear it mid-fade.\n\tfunction resetEphemeralState() {\n\t\tselection.clear();\n\t\tsetSearch(\"\");\n\t\tsetNewName(\"\");\n\t}\n\n\t// Fallback: zag presence skips onExitComplete when a reopen interrupts the\n\t// exit animation (fires only on the mounted→unmounted transition, not on\n\t// unmountSuspended→mounted) — reset again on open so a fast close-then-\n\t// reopen can't reopen with stale search/selection/newName.\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: reset only on open→true\n\tuseEffect(() => {\n\t\tif (!open) return;\n\t\tresetEphemeralState();\n\t}, [open]);\n\n\tfunction handleConfirm() {\n\t\tif (selection.items.length === 0) return;\n\t\tonSelect(\n\t\t\tmode === \"single\"\n\t\t\t\t? { mode: \"single\", collection: selection.items[0] }\n\t\t\t\t: { mode: \"multi\", collections: selection.items },\n\t\t);\n\t\tonOpenChange(false);\n\t}\n\n\tasync function handleCreate() {\n\t\tconst name = newName.trim();\n\t\tif (!name) return;\n\t\ttry {\n\t\t\tawait createCollection.mutateAsync({\n\t\t\t\tname,\n\t\t\t\tslug: name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\tdescription: \"\",\n\t\t\t\ttype: \"static\",\n\t\t\t\trules: \"\",\n\t\t\t});\n\t\t\tsetNewName(\"\");\n\t\t\ttoaster.success({ title: t(\"collectionPicker.createSuccessToast\") });\n\t\t} catch (err) {\n\t\t\tshowRpcErrorToast(err, t(\"collectionPicker.createFailedToast\"));\n\t\t}\n\t}\n\n\tconst count = selection.items.length;\n\tconst confirmLabel =\n\t\tcount > 0\n\t\t\t? t(\"collectionPicker.confirmCount\", { count })\n\t\t\t: t(\"collectionPicker.confirm\");\n\n\t// Do NOT `return null` when closed: unmounting the open dialog machine\n\t// under StrictMode orphans its scroll-lock/aria-hidden cleanup and wedges\n\t// the whole app (#66). Keep Modal mounted; lazyMount/unmountOnExit keep\n\t// the fresh-content-per-open semantics.\n\treturn (\n\t\t<Modal\n\t\t\topen={open}\n\t\t\tlazyMount\n\t\t\tunmountOnExit\n\t\t\tonExitComplete={resetEphemeralState}\n\t\t\tonClose={() => onOpenChange(false)}\n\t\t\tsize=\"lg\"\n\t\t\theader={\n\t\t\t\tmode === \"single\"\n\t\t\t\t\t? t(\"collectionPicker.headerSingle\")\n\t\t\t\t\t: t(\"collectionPicker.headerMulti\")\n\t\t\t}\n\t\t\tfooter={\n\t\t\t\t<PickerFooter\n\t\t\t\t\tcount={count}\n\t\t\t\t\tconfirmLabel={confirmLabel}\n\t\t\t\t\tcancelLabel={t(\"collectionPicker.cancel\")}\n\t\t\t\t\tonConfirm={handleConfirm}\n\t\t\t\t\tonCancel={() => onOpenChange(false)}\n\t\t\t\t/>\n\t\t\t}\n\t\t>\n\t\t\t<Flex direction=\"column\" gap=\"3\" minH=\"280px\">\n\t\t\t\t<Flex gap=\"2\" align=\"center\">\n\t\t\t\t\t<SearchInput\n\t\t\t\t\t\tonSearch={setSearch}\n\t\t\t\t\t\tplaceholder={t(\"collectionPicker.searchPlaceholder\")}\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tmaxWidth=\"full\"\n\t\t\t\t\t/>\n\t\t\t\t\t{allowCreate && (\n\t\t\t\t\t\t<HStack gap=\"2\" flexShrink={0}>\n\t\t\t\t\t\t\t<Box w=\"160px\">\n\t\t\t\t\t\t\t\t<TextInput\n\t\t\t\t\t\t\t\t\tvalue={newName}\n\t\t\t\t\t\t\t\t\tonChange={(e) => setNewName(e.target.value)}\n\t\t\t\t\t\t\t\t\tplaceholder={t(\"collectionPicker.createPlaceholder\")}\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\tonClick={handleCreate}\n\t\t\t\t\t\t\t\tloading={createCollection.isPending}\n\t\t\t\t\t\t\t\tdisabled={!newName.trim()}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t(\"collectionPicker.createButton\")}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</HStack>\n\t\t\t\t\t)}\n\t\t\t\t</Flex>\n\n\t\t\t\t{collectionsQuery.isLoading ? (\n\t\t\t\t\t<Flex justify=\"center\" py=\"10\">\n\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t</Flex>\n\t\t\t\t) : items.length === 0 ? (\n\t\t\t\t\t<EmptyState header={t(\"collectionPicker.emptyLabel\")} />\n\t\t\t\t) : (\n\t\t\t\t\t<Grid templateColumns=\"repeat(2, 1fr)\" gap=\"3\">\n\t\t\t\t\t\t{items.map((c) => (\n\t\t\t\t\t\t\t<SelectableCard\n\t\t\t\t\t\t\t\tkey={c.id}\n\t\t\t\t\t\t\t\tselected={selection.isSelected(c.id)}\n\t\t\t\t\t\t\t\tselectionVisible={count > 0}\n\t\t\t\t\t\t\t\tonSelect={() => selection.toggle(c)}\n\t\t\t\t\t\t\t\tonClick={() => selection.toggle(c)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectableCard.Body>\n\t\t\t\t\t\t\t\t\t<HStack gap=\"2\" align=\"center\">\n\t\t\t\t\t\t\t\t\t\t<FolderOpen size={16} />\n\t\t\t\t\t\t\t\t\t\t<Box minW=\"0\">\n\t\t\t\t\t\t\t\t\t\t\t<HStack gap=\"1\" align=\"center\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Text fontSize=\"sm\" fontWeight=\"medium\" truncate>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{c.name}\n\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t{c.restricted && <RestrictedLockBadge />}\n\t\t\t\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\t\tfontSize=\"xs\"\n\t\t\t\t\t\t\t\t\t\t\t\tcolor=\"fg.muted\"\n\t\t\t\t\t\t\t\t\t\t\t\ttextTransform=\"capitalize\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{c.type}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t</Box>\n\t\t\t\t\t\t\t\t\t</HStack>\n\t\t\t\t\t\t\t\t</SelectableCard.Body>\n\t\t\t\t\t\t\t</SelectableCard>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Grid>\n\t\t\t\t)}\n\t\t\t</Flex>\n\t\t</Modal>\n\t);\n}\nCollectionPicker.displayName = \"CollectionPicker\";\n","import de from \"./de.json\";\nimport en from \"./en.json\";\n\n/**\n * The i18next namespace every string in this package is looked up under. A\n * host merges `i18nResources` and lists this constant among its namespaces —\n * never the literal, so a rename here fails the host's compile rather than\n * rendering raw keys (knkcms/core ADR 0005's provider checklist; #807). The\n * package's own `useTranslation` calls name the same string, which\n * `resources.test.ts` holds them to.\n */\nexport const MEDIAHUB_UI_NS = \"mediahub-ui\";\n\n/** The package's bundled translations, keyed by language, then by\n * `MEDIAHUB_UI_NS`. */\nexport const i18nResources = {\n\ten: { [MEDIAHUB_UI_NS]: en },\n\tde: { [MEDIAHUB_UI_NS]: de },\n};\n","/**\n * @knkcs/mediahub-ui — reusable mediahub asset-management surfaces.\n *\n * Transport-agnostic clients + provider + TanStack Query hooks + stores,\n * plus the UI surfaces themselves (<AssetLibrary>, <AssetPicker>,\n * <CollectionPicker>, <AssetDetail>, …). A host's own tests reach the\n * `./testing` subpath instead of this one — see `src/testing`.\n */\nexport const MEDIAHUB_UI_VERSION = \"0.1.0\";\n\nexport * from \"./types\";\nexport * from \"./lib/rpc-errors\";\nexport * from \"./lib/slugify\";\nexport * from \"./lib/mime-type-list\";\nexport * from \"./clients\";\nexport * from \"./connect-clients\";\nexport * from \"./provider\";\nexport * from \"./statushub\";\nexport * from \"./hooks\";\nexport * from \"./stores\";\nexport * from \"./components\";\nexport * from \"./asset-library\";\nexport * from \"./asset-detail\";\nexport * from \"./asset-type-detail\";\nexport * from \"./asset-type-create\";\nexport * from \"./asset-type-index\";\nexport * from \"./collection-detail\";\nexport * from \"./asset-picker\";\nexport * from \"./collection-create\";\nexport * from \"./collection-index\";\nexport * from \"./collection-picker\";\nexport { i18nResources, MEDIAHUB_UI_NS } from \"./i18n/resources\";\n"],"names":["CODE_PERMISSION_DENIED","CODE_FAILED_PRECONDITION","CODE_UNAVAILABLE","LEAK_GUARD_DETAIL_TYPE","PERMISSION_DENIED_TITLE","PERMISSION_DENIED_BODY","LEAK_GUARD_TITLE","LEAK_GUARD_GENERIC","LEAK_GUARD_RULES","connectCode","err","code","isPermissionDenied","isRetryableUnavailable","isLeakGuardDetailType","type","asExposure","raw","r","str","v","violationFrom","exposures","findLeakGuardViolation","details","d","entry","describeRpcError","fallbackTitle","violation","rule","items","e","showRpcErrorToast","toaster","slugify","name","parseMimeTypeList","value","formatMimeTypeList","mapTs","t","COLLTYPE_TO_NUM","NUM_TO_COLLTYPE","mapVersion","parseAssetMetadata","parsed","mapAsset","a","mapFolder","f","mapCollection","c","mapTag","mapAssetType","mapAIConnection","mapAIProcess","p","o","mapAIProcessRun","createConnectAssetClient","workspaceId","res","id","params","patch","versionId","assetId","folderId","fromStatusSlug","toStatusSlug","createConnectFolderClient","parentId","restricted","call","createConnectCollectionClient","cur","merged","key","fallback","collectionId","assetIds","createConnectTagClient","tagId","createConnectAssetTypeClient","createConnectDirectoryClient","ids","u","m","GRANT_RESOURCE_TO_NUM","NUM_TO_GRANT_LEVEL","GRANT_LEVEL_TO_NUM","createConnectGrantClient","resourceType","resourceId","grants","g","level","userId","createConnectAuthzClient","createConnectDashboardClient","layoutJson","createConnectAIConnectionClient","createConnectAIProcessClient","assetTypeId","createConnectMediahubClients","gen","MediahubContext","createContext","EMPTY_LINKS","MediahubProvider","clients","links","children","useMemo","jsx","useMediahubContext","ctx","useContext","useMediahubClients","useWorkspaceId","useMediahubLinks","ASSET_STATUS_CATALOGUE","useAssetStatuses","useStatuses","useAssetStatus","slug","data","isLoading","uploadFileToSAS","url","file","contentType","onProgress","resolve","reject","xhr","useAddVersion","assets","qc","useQueryClient","progress","setProgress","useState","useMutation","comment","uploadUrl","_data","vars","useAssets","filters","useQuery","useAsset","useCreateAsset","useUpdateAsset","useDeleteAsset","useMoveAsset","useTransitionAssetStatus","useEnhanceAssetMetadata","usePreviewURL","useCanManage","authz","useFolders","opts","folders","useFolder","useCreateFolder","useUpdateFolder","useDeleteFolder","useMoveFolder","useSetFolderRestricted","useGrants","failureCount","error","useGrantAccess","_err","useRevokeAccess","useCollections","collections","useCollection","useCreateCollection","useUpdateCollection","useDeleteCollection","useAddAssetsToCollection","useSetCollectionRestricted","useRemoveAssetsFromCollection","useTags","tags","useCreateTag","useUpdateTag","useDeleteTag","useTagAssets","useUntagAssets","useAssetTypes","assetTypes","useAssetType","useCreateAssetType","useUpdateAssetType","useDeleteAssetType","useUsers","directory","sorted","useWorkspaceMembers","useWorkspaceStats","dashboard","useGetDashboardLayout","useSaveDashboardLayout","useAIConnections","aiConnection","useAIConnection","useCreateAIConnection","useUpdateAIConnection","useDeleteAIConnection","useAIProcesses","aiProcess","useAIProcess","useCreateAIProcess","useUpdateAIProcess","useDeleteAIProcess","isActive","runs","useAIProcessRuns","wasActive","useRef","query","q","seenAssetId","useEffect","active","useSelectionStore","create","set","get","state","i","targetId","orderedIds","lastClickedId","selectedIds","startIdx","endIdx","low","high","rangeIds","usePreferencesStore","persist","mode","updateFile","files","clientId","useUploadStore","newFiles","entries","client","pending","described","message","ActiveFilterChips","chips","onClearAll","groupLabel","removeLabel","clearAllLabel","jsxs","Flex","chip","Toolbar","Box","X","Button","ALL_REQUIRED_MARKERS","processFormSchema","z","EMPTY_OUTPUT","buildProcessOutputs","proc","outputs","OutputRow","index","onRemove","metadataAccessors","canRemove","useTranslation","control","useFormContext","target","useWatch","InputField","SelectField","ProcessFormFields","connections","fields","append","remove","useFieldArray","FormMarkersProvider","TextareaField","field","Plus","CreateFormContent","open","onClose","createMutation","resolver","zodResolver","methods","useForm","onSubmit","Modal","FormProvider","EditFormContent","editProcess","latchedProcessRef","process","updateMutation","AIProcessFormDialog","Fragment","STRUCTURAL_MARKERS","customFieldEntries","metadataSchema","countCustomFields","metadataAccessorOptions","_a","_b","fullPatch","AIProcessesTab","typeId","confirm","useConfirmModal","processesQuery","processes","deleteProcess","updateProcess","createOpen","setCreateOpen","setEditProcess","connectionMap","b","handleDelete","handleToggle","handleMove","delta","neighbour","noConnections","Stack","Text","Spinner","EmptyState","Switch","ChevronUp","ChevronDown","Pencil","Trash2","AssetStatusBadge","status","StatusBadge","getMimeCategory","asset","version","mime","TypeIcon","category","Image","Film","Music","FileText","useCategoryLabel","AssetCard","onOpen","isSelected","s","anySelected","toggle","categoryLabel","latestVersion","previewQuery","previewUrl","imgError","setImgError","SelectableCard","Skeleton","AssetGrid","Grid","mimeType","AssetPreview","fileName","setError","Download","AssetStatusControl","statusSlug","transition","StatusTransitionControl","to","BulkActionBar","clearSelection","count","deleteAsset","tagAssets","addToCollection","tagsQuery","collectionsQuery","handleBulkDelete","n","failed","firstErr","handleBulkTag","handleBulkAddToCollection","AnkerBulkActionBar","Tag","tag","FolderOpen","col","CollectionChipField","assignedCollectionIds","allCollections","removeFromCollection","assigned","unassigned","handleAdd","collection","handleRemove","ChipPicker","CollectionPanel","activeCollectionId","onSelectCollection","createCollection","handleCreate","InlineCreatableList","useAncestorChain","folder","parent","grandparent","chain","FolderBreadcrumbs","onNavigate","ancestors","BreadcrumbRoot","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","item","BreadcrumbCurrentLink","MaybeLink","href","Link","LeakGuardRefusalDialog","refusal","HStack","maxFolderDepth","openCollectionIds","assetExposedByOpenCollection","folderChainRestricted","folderSubtreeExposed","openIds","frontier","depth","next","subjectId","subject","subjectName","ManageAccessDialog","props","onOpenChange","kind","pickedUserId","setPickedUserId","pickLevel","setPickLevel","rosterQuery","roster","denied","membersQuery","rosterUserIds","namesQuery","nameOf","scopeQuery","grantAccess","revokeAccess","mutating","granteeIds","candidates","names","sortedGrants","nm","handleGrant","handleLevelChange","handleRevoke","viewerLabel","editorLabel","renderBody","Lock","Persona","Badge","NativeSelect","IconButton","currentParentId","rowDisabledReason","chainRestricted","DestinationRowButton","reason","selected","emphasized","onClick","Folder","DestinationRow","ancestorRestricted","expanded","setExpanded","childrenQuery","isSelf","onDeselect","ChevronRight","child","MoveDialog","onMoved","selectedId","setSelectedId","rootQuery","moveFolder","moveAsset","subjectFolderId","folderGuardQuery","guardActive","resetEphemeralState","handleConfirm","handleDeselect","useCallback","current","rootReason","moving","restrictedContainerWarning","unrestrictDisclosure","RestrictedLockBadge","size","ml","RestrictedWarningNotice","RestrictedFolderDialog","onCreated","setName","createFolder","trimmed","msg","TextInput","FolderTree","activeFolderId","onFolderSelect","rootFolders","treeKey","setTreeKey","isCreating","setIsCreating","newName","setNewName","renamingId","setRenamingId","renameValue","setRenameValue","moveSubject","setMoveSubject","moveOpen","setMoveOpen","accessSubject","setAccessSubject","accessOpen","setAccessOpen","restrictedParentId","setRestrictedParentId","menuNodeId","setMenuNodeId","toggleRefusal","setToggleRefusal","refusalOpen","setRefusalOpen","updateFolder","deleteFolder","setFolderRestricted","canManage","creatingRef","renamingRef","rootChildren","createTreeCollection","node","handleLoadChildren","folderName","k","handleRenameSubmit","handleToggleRestricted","restricting","MenuRoot","MenuTrigger","Ellipsis","MenuContent","MenuItem","TreeViewRoot","TreeViewTree","TreeViewNode","TreeViewBranchControl","TreeViewBranchIndicator","TreeViewBranchText","FolderPlus","InlineEditField","onSave","as","placeholder","disabled","setDisabled","handleSubmit","nextValue","InlineEdit","MetadataSchemaEditor","initialSchema","onDirtyChange","updateAssetType","handleCommit","schema","FieldKitProvider","builtInFieldTypes","SpecEditor","TagChipField","assignedTagIds","allTags","untagAssets","assignedTags","unassignedTags","TagPanel","activeTags","onToggleTag","createTag","formatFileSize","bytes","FileRow","showOverride","onToggleOverride","setAssetType","UploadDialog","setBatchAssetType","startUpload","clearPending","analyzeWithAi","setAnalyzeWithAi","batchType","setBatchType","overrides","setOverrides","pendingFiles","handleBatchTypeChange","toggleOverride","prev","canUpload","handleUpload","handleCancel","Checkbox","UploadDropZone","onFilesSelected","compact","AnkerUploadDropZone","mapStatus","UploadToastStack","storeFiles","visible","dismiss","AnkerUploadToastStack","buildAssetTypeNameMap","types","collectUpdatedByIds","behaviorOptions","viewModeOptions","NO_ACTIVE_TAGS","NO_STATUS_OPTIONS","AssetLibrary","onAssetOpen","initialFilters","onFiltersChange","setFilters","uploadDialogOpen","setUploadDialogOpen","fileInputRef","behaviorFilter","updateFilter","searchText","setSearchText","searchPrimed","timer","clearAllFilters","handleToggleTag","handleSelectCollection","setStatusSlug","setBehaviorFilter","addFiles","viewMode","setViewMode","handleFilesSelected","assetName","assetsQuery","statusOptions","activeFolder","filterChips","candidate","option","noAssetsState","listFailure","listFailureState","assetTypesQuery","typeNames","updatedByIds","userNames","setSelection","rowSelection","sel","handleRowSelectionChange","updater","filtersKey","columnHelper","createColumnHelper","listColumns","info","TruncatedTextCell","date","DateCell","ActionCell","rail","ContextRail","usePageRail","toolbar","SegmentedControl","IndexPageTemplate","Upload","SubNavLayout","DataTable","STRUCTURAL","composeFormValues","plugins","assetRecord","defaults","getDefaultValues","values","acc","stored","decomposePatch","metadata","columns","versionColumnHelper","aiRunColorPalette","AssetDetailRail","currentVersionId","currentMimeType","currentFilename","currentFileSize","currentVersion","createdBy","createdByName","tagIds","collectionIds","addVersion","assetType","unknownValue","DescriptionList","run","AssetDetail","onBack","onDeleted","assetQuery","assetsClient","updateAsset","enhanceMetadata","assetTypeQuery","composedValues","zodSchema","specToZodSchema","form","handleSaveBody","handleBack","activeTab","setActiveTab","allUserIds","handleDownloadVersion","versionColumns","currentBadge","StatusBadgeCell","handleDownloadCurrent","handleEnhance","sortedVersions","DetailPageTemplate","ArrowLeft","Sparkles","Tabs","SpecForm","AssetTypeDetail","assetTypesPath","deleteAssetType","metadataDirty","setMetadataDirty","parsedSchema","handleSave","handleTabChange","title","SwitchField","AssetTypeCreate","onCancel","createAssetType","slugEdited","setSlugEdited","created","SettingsPageTemplate","FormField","AssetTypeIndex","onCreate","search","setSearch","filtered","SlugCell","BooleanCell","MenuCell","row","CollectionDetail","collectionsPath","collectionQuery","updateCollection","deleteCollection","setRestricted","isAuthority","setRefusal","everAuthority","setEverAuthority","LockOpen","Users","ImageIcon","PickerAssetCard","selectionVisible","onToggle","PickerFooter","confirmLabel","cancelLabel","onConfirm","usePickerSelection","setItems","exists","clear","matchesAccept","accept","AssetPicker","onSelect","selection","allItems","allowUpload","uploadFiles","bridgedRef","byId","isImage","PickerStripThumb","SearchInput","CollectionCreate","CollectionIndex","searching","CollectionPicker","allowCreate","all","MEDIAHUB_UI_NS","i18nResources","en","de","MEDIAHUB_UI_VERSION"],"mappings":"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"}
|