@fluid-app/portal-sdk 0.1.174 → 0.1.175
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/dist/{PortalContentApiProvider-DNZj3MTz.cjs → PortalContentApiProvider-CqfumtyH.cjs} +4 -4
- package/dist/PortalContentApiProvider-CqfumtyH.cjs.map +1 -0
- package/dist/{PortalContentApiProvider-D0xhS3Ge.mjs → PortalContentApiProvider-CvYJD4mj.mjs} +4 -4
- package/dist/PortalContentApiProvider-CvYJD4mj.mjs.map +1 -0
- package/dist/{ProductsScreen-fPFSKVOn.cjs → ProductsScreen-BGFL7B9Y.cjs} +2 -2
- package/dist/{ProductsScreen-fPFSKVOn.cjs.map → ProductsScreen-BGFL7B9Y.cjs.map} +1 -1
- package/dist/{ProductsScreen-DIdRGVvA.mjs → ProductsScreen-BUCzY4c8.mjs} +2 -2
- package/dist/{ProductsScreen-CeNMvU4d.mjs → ProductsScreen-CJWgYPY9.mjs} +2 -2
- package/dist/{ProductsScreen-CeNMvU4d.mjs.map → ProductsScreen-CJWgYPY9.mjs.map} +1 -1
- package/dist/{ProductsScreen-iQf4zOus.cjs → ProductsScreen-CyOr92nO.cjs} +2 -2
- package/dist/{ShareablesScreen-Bl6aT0vn.cjs → ShareablesScreen-BYySYuY1.cjs} +2 -2
- package/dist/{ShareablesScreen-Bl6aT0vn.cjs.map → ShareablesScreen-BYySYuY1.cjs.map} +1 -1
- package/dist/{ShareablesScreen-D2JbmO7a.mjs → ShareablesScreen-Ca0VOB6e.mjs} +2 -2
- package/dist/{ShareablesScreen-D2JbmO7a.mjs.map → ShareablesScreen-Ca0VOB6e.mjs.map} +1 -1
- package/dist/{ShareablesScreen-CfchbhSH.mjs → ShareablesScreen-Cr-WyfrQ.mjs} +2 -2
- package/dist/{ShareablesScreen-CtuGiQ7_.cjs → ShareablesScreen-PPfy8gtj.cjs} +2 -2
- package/dist/index.cjs +8 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -17
- package/dist/PortalContentApiProvider-D0xhS3Ge.mjs.map +0 -1
- package/dist/PortalContentApiProvider-DNZj3MTz.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortalContentApiProvider-CqfumtyH.cjs","names":["DEFAULT_IMAGE","Card","CirclePlay","Badge","PAGE_SIZE","GRID_CLASS","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbPage","Skeleton","SearchSort","Badge","Button","Maximize","X","FacebookIcon","InstagramIcon","FacebookIcon","InstagramIcon","Button","DropdownMenu","DropdownMenuTrigger","Menu","DropdownMenuContent","DropdownMenuItem","Copy","React","Button","Play","FileImage","Image","Spinner","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","BreadcrumbPage","Spinner","Button","Download","Separator","MarketingAssetsGrid","PAGE_SIZE","GRID_CLASS","Button","Plus","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbPage","keepPreviousData","Skeleton","SearchSort","List","LayoutGrid","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","BreadcrumbPage","Spinner","Button","Download","z","z","X","K","u","centerCrop","makeAspectCrop","z","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","Form","FormField","FormItem","FormLabel","FormControl","Input","FormMessage","Button","Dialog","DialogContent","DialogHeader","DialogTitle","AlertTriangleIcon","Button","ImageIcon","VideoIcon","FileIcon","cn","cn","cn","DropdownMenu","DropdownMenuTrigger","EllipsisVerticalIcon","DropdownMenuContent","DropdownMenuItem","XIcon","Trash2Icon","cn","React","useZodForm","Dialog","DialogPortal","DialogOverlay","Breadcrumb","BreadcrumbList","React","BreadcrumbItem","BreadcrumbPage","Button","cn","BreadcrumbSeparator","FolderIcon","TooltipProvider","Tooltip","TooltipTrigger","TooltipContent","LoaderIcon","ChevronDownIcon","Button","React","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Button","Input","TooltipProvider","Tooltip","TooltipTrigger","Button","MinusIcon","TooltipContent","Slider","PlusIcon","TypeIcon","LayoutGridIcon","ListIcon","DropdownMenu","DropdownMenuTrigger","FolderPlusIcon","DropdownMenuContent","DropdownMenuItem","DropdownMenuSub","DropdownMenuSubTrigger","DropdownMenuSubContent","FolderIcon","Popover","PopoverTrigger","SlidersHorizontalIcon","PopoverContent","defaultFiltersState","ArrowUpDownIcon","CheckIcon","XIcon","ImageIcon","VideoIcon","FileIcon","Dialog","DialogPortal","DialogOverlay","DialogContent","Input","SearchIcon","LoaderIcon","Button","ChevronDownIcon","DownloadIcon","UserIcon","Button","LoaderIcon","CheckIcon","AlertTriangleIcon","LinkIcon","Input","CheckIcon","AlertTriangleIcon","Button","LoaderIcon","ArrowRightIcon","FileIcon","Switch","Dialog","DialogContent","DialogTitle","DropdownMenu","DropdownMenuTrigger","ChevronDownIcon","DropdownMenuContent","DropdownMenuItem","Button","MoveHorizontalIcon","RotateCwIcon","MinusIcon","Slider","PlusIcon","ReactCrop","formatFileSize","useDropzone","Card","CardContent","ArrowUpIcon","Button","LoaderIcon","CheckIcon","AlertTriangleIcon","Switch","React","FileIcon","ImageIcon","VideoIcon","React","DropdownMenu","DropdownMenuTrigger","EllipsisVerticalIcon","DropdownMenuContent","DropdownMenuItem","CropIcon","LayersIcon","XIcon","Button","Dialog","DialogPortal","DialogOverlay","defaultDamFilters","CloudIcon","ImagesIcon","LaptopIcon","LinkIcon","Dialog","DialogContent","DialogTitle","Video","FileText","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","BreadcrumbPage","Button","Upload","Input","Spinner","DEFAULT_IMAGE","cn","Checkbox","DropdownMenu","DropdownMenuTrigger","MoreVertical","DropdownMenuContent","DropdownMenuItem","Heart","Pencil","DropdownMenuSeparator","Trash2","Badge","Button","X","PAGE_SIZE","GRID_CLASS","Button","Plus","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbPage","keepPreviousData","Skeleton","SearchSort","DEFAULT_IMAGE","ShoppingBag","ArrowUpRight","DEFAULT_IMAGE","ListMusic","Play","ArrowUpRight","DEFAULT_IMAGE","Button","Pencil","Trash2","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","BreadcrumbPage","Spinner","Separator","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter","Button","Trash2","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbLink","BreadcrumbSeparator","BreadcrumbPage","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter","useEditor","StarterKit","Placeholder","TextAlign","Underline","cn","AlignLeft","AlignCenter","AlignRight","AlignJustify","List","ListOrdered","EditorContent","Label","Input","cn","CSS","React","Video","Image","FileText","ShoppingBag","Package","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","GripVertical","DropdownMenu","DropdownMenuTrigger","Button","MoreHorizontal","DropdownMenuContent","DropdownMenuItem","Trash2","DndContext","closestCenter","SortableContext","verticalListSortingStrategy","Button","Plus","Skeleton","Breadcrumb","BreadcrumbList","BreadcrumbItem","BreadcrumbPage","Skeleton","SearchSort","Card","CirclePlay","Badge","z","usePortalTenantClient","usePortalProductsApi"],"sources":["../../../shareables/core/src/context.tsx","../../../shareables/core/src/query-keys.ts","../../../shareables/core/src/api-context.tsx","../../../shareables/core/src/hooks/use-share-link.ts","../../../shareables/core/src/hooks/use-media-mutations.ts","../../../shareables/core/src/utils.ts","../../../shareables/core/src/hooks/use-playlist-mutations.ts","../../../shareables/ui/src/context.tsx","../../../shareables/ui/src/utils/strip-tags.ts","../../../shareables/ui/src/utils/social-sharing.ts","../../../shareables/ui/src/utils/os-detection.ts","../../../products/api-client/src/namespaces/products.ts","../../../shareables/ui/src/components/MediaShare/ShareItemCard.tsx","../../../shareables/ui/src/components/MediaShare/products/ShareProductCard.tsx","../../../shareables/ui/src/components/screens/ProductsScreen.tsx","../../../shareables/ui/src/components/SharePage/SharePageImageDisplay.tsx","../../../shareables/ui/src/components/QrCodeDisplay.tsx","../../../shareables/ui/src/components/icons/social-icons.tsx","../../../shareables/ui/src/components/SharePage/ShareLinkSection.tsx","../../../shareables/ui/src/components/ShareablesModal/MarketingAssetsGrid.tsx","../../../shareables/ui/src/components/screens/ProductDetailScreen.tsx","../../../shareables/ui/src/components/screens/MediaListingScreen.tsx","../../../shareables/ui/src/components/screens/MediaDetailScreen.tsx","../../../file-picker/ui/src/context/FilePickerApiContext.tsx","../../../file-picker/ui/src/context/FilePickerContext.tsx","../../../file-picker/ui/src/utils/brand-icons.tsx","../../../file-picker/core/src/query-keys.ts","../../../file-picker/core/src/schemas/dam.ts","../../../file-picker/core/src/schemas/file-picker-config.ts","../../../file-picker/core/src/constants/filter-options.ts","../../../file-picker/core/src/utils/mime-type.ts","../../../../node_modules/.pnpm/react-image-crop@11.0.10_react@19.2.4/node_modules/react-image-crop/dist/index.js","../../../file-picker/core/src/utils/image-crop.ts","../../../file-picker/core/src/utils/dam-asset.ts","../../../file-picker/core/src/utils/dam-url.ts","../../../file-picker/core/src/utils/filename-sanitizer.ts","../../../file-picker/ui/src/hooks/use-debounced-search.ts","../../../file-picker/ui/src/hooks/use-dam-library.ts","../../../file-picker/ui/src/components/AddFolderModal.tsx","../../../file-picker/ui/src/components/AssetActions.tsx","../../../file-picker/ui/src/utils/icons.ts","../../../file-picker/ui/src/components/DamLibraryAsset/AssetThumbnail.tsx","../../../file-picker/ui/src/components/DamLibraryAsset/SelectionIndexBadge.tsx","../../../file-picker/ui/src/components/DamLibraryAsset/AssetActionsMenu.tsx","../../../file-picker/ui/src/components/LibraryAssetGrid.tsx","../../../file-picker/ui/src/components/DamLibrary.tsx","../../../file-picker/ui/src/components/FilePickerSidebar.tsx","../../../file-picker/ui/src/components/FilePickerFiltersPanel.tsx","../../../file-picker/ui/src/components/FilePickerHeader.tsx","../../../file-picker/ui/src/components/MediaTab.tsx","../../../file-picker/ui/src/hooks/use-unsplash-picker.ts","../../../file-picker/ui/src/components/UnsplashPicker.tsx","../../../file-picker/ui/src/hooks/use-url-upload.ts","../../../file-picker/ui/src/components/UrlUpload.tsx","../../../file-picker/ui/src/hooks/use-computer-upload.ts","../../../file-picker/ui/src/components/ImageCropModal.tsx","../../../file-picker/ui/src/components/ComputerUpload.tsx","../../../file-picker/ui/src/components/FilePickerContent.tsx","../../../file-picker/ui/src/components/SelectionPanel.tsx","../../../file-picker/ui/src/components/FilePicker.tsx","../../../shareables/ui/src/components/screens/MediaCreateScreen.tsx","../../../shareables/ui/src/components/playlists/PlaylistCard.tsx","../../../shareables/ui/src/components/playlists/BulkSelectionBar.tsx","../../../shareables/ui/src/components/screens/PlaylistsListingScreen.tsx","../../../shareables/ui/src/constants.ts","../../../shareables/ui/src/components/SharePage/TaggedProductsList.tsx","../../../shareables/ui/src/components/SharePage/PlaylistItemsList.tsx","../../../shareables/ui/src/components/screens/PlaylistDetailScreen.tsx","../../../shareables/ui/src/components/playlists/form/PlaylistFormProvider.tsx","../../../shareables/ui/src/components/playlists/form/PlaylistItemsContext.tsx","../../../shareables/ui/src/components/playlists/form/PlaylistFormHeader.tsx","../../../shareables/ui/src/components/playlists/RichTextEditor.tsx","../../../shareables/ui/src/components/playlists/form/PlaylistFormDetails.tsx","../../../shareables/ui/src/components/playlists/form/SortableRow.tsx","../../../shareables/ui/src/components/playlists/form/SortableTable.tsx","../../../shareables/ui/src/components/playlists/form/PlaylistItemsSection.tsx","../../../shareables/ui/src/components/playlists/form/PlaylistOpenGraphPreview.tsx","../../../shareables/ui/src/components/screens/PlaylistCreateScreen.tsx","../../../shareables/ui/src/components/screens/FilesListingScreen.tsx","../../../shareables/ui/src/components/ShareablesApp.tsx","../../../shareables/ui/src/components/ProductsApp.tsx","../../../file-picker/api-client/src/api/url-proxy.ts","../src/adapters/file-picker-api-adapter.ts","../src/adapters/content-api-adapter.ts","../src/content/PortalContentApiProvider.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\n\ninterface ShareablesCoreConfig {\n /**\n * Legacy FetchClient for direct API calls (e.g. products-api-client).\n * Optional — portal-tenant contexts use BFF adapters instead.\n */\n client?: FetchClient;\n user: { id: number } | null;\n /** When true, use rep-scoped API endpoints (e.g. /users/v2025-06/media) */\n repContext?: boolean;\n}\n\nconst ShareablesCoreContext = createContext<ShareablesCoreConfig | null>(null);\n\nexport function ShareablesCoreProvider({\n config,\n children,\n}: {\n config: ShareablesCoreConfig;\n children: React.ReactNode;\n}): React.JSX.Element {\n return (\n <ShareablesCoreContext.Provider value={config}>\n {children}\n </ShareablesCoreContext.Provider>\n );\n}\n\nexport function useShareablesClient(): FetchClient | null {\n const ctx = useContext(ShareablesCoreContext);\n if (!ctx) {\n throw new Error(\n \"useShareablesClient must be used within a ShareablesCoreProvider\",\n );\n }\n return ctx.client ?? null;\n}\n\nexport function useShareablesUser(): { id: number } | null {\n const ctx = useContext(ShareablesCoreContext);\n if (!ctx) {\n throw new Error(\n \"useShareablesUser must be used within a ShareablesCoreProvider\",\n );\n }\n return ctx.user;\n}\n\nexport function useRepContext(): boolean {\n const ctx = useContext(ShareablesCoreContext);\n return ctx?.repContext ?? false;\n}\n","export const shareablesKeys = {\n media: {\n all: [\"media\"] as const,\n list: (search?: string, sortDesc?: boolean, repContext?: boolean) =>\n [\"media\", \"list\", search, sortDesc, repContext] as const,\n detail: (id: number, repContext?: boolean) =>\n [\"media\", \"detail\", id, repContext] as const,\n grid: () => [\"media\", \"grid\"] as const,\n },\n playlists: {\n all: [\"playlists\"] as const,\n detail: (id: number) => [\"playlists\", \"detail\", id] as const,\n },\n productMedia: {\n all: [\"productMedia\"] as const,\n counts: (ids: number[]) =>\n [\"productMedia\", \"counts\", ids.toSorted()] as const,\n count: (id: number) => [\"productMedia\", \"count\", id] as const,\n },\n shareLinks: {\n all: [\"shareLinks\"] as const,\n link: (type: string, id?: number, contactId?: number, locale?: string) =>\n [\"shareLinks\", \"link\", type, id, contactId, locale] as const,\n },\n};\n","import { createContext, useContext } from \"react\";\nimport type { ContentDomainApi } from \"./content-domain-api\";\n\nconst ShareablesApiContext = createContext<ContentDomainApi | null>(null);\n\nexport function ShareablesApiProvider({\n value,\n children,\n}: {\n value: ContentDomainApi;\n children: React.ReactNode;\n}): React.JSX.Element {\n return (\n <ShareablesApiContext.Provider value={value}>\n {children}\n </ShareablesApiContext.Provider>\n );\n}\n\nexport function useShareablesApi(): ContentDomainApi {\n const ctx = useContext(ShareablesApiContext);\n if (!ctx) {\n throw new Error(\n \"useShareablesApi must be used within a ShareablesApiProvider\",\n );\n }\n return ctx;\n}\n","import { useCallback } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { shareables } from \"../types\";\nimport { useShareablesApi } from \"../api-context\";\nimport { shareablesKeys } from \"../query-keys\";\n\nexport interface ShareLinkItem {\n id?: number;\n share_link?: string;\n}\n\nexport function useShareLink(\n item: ShareLinkItem,\n shareableType: string,\n contactId?: number,\n locale = \"en\",\n) {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n\n // Check if we need an ID for this shareable type\n const isIdRequired = shareableType !== \"MySite\";\n\n // Check if the ID is a valid database ID (integer) vs a generated float ID\n const isValidDatabaseId =\n item?.id && Number.isInteger(item.id) && item.id > 1;\n\n const shouldFetch = isIdRequired ? isValidDatabaseId : true;\n\n const queryKey = shareablesKeys.shareLinks.link(\n shareableType,\n item?.id,\n contactId,\n locale,\n );\n\n const {\n data: shareLink,\n isLoading: loading,\n error,\n refetch,\n } = useQuery({\n queryKey,\n queryFn: async () => {\n // If we have an existing share_link, return it\n if (item?.share_link && !contactId) {\n return item.share_link;\n }\n\n if (isIdRequired && !item?.id) {\n throw new Error(\"Something went wrong, please try again.\");\n }\n\n if (isIdRequired && !isValidDatabaseId) {\n throw new Error(\"Share links are not available for this item.\");\n }\n\n const input: shareables.CreateShareLinkInput = {\n locale,\n relateableType: shareableType,\n ...(isIdRequired && item?.id && { relateableId: item.id }),\n ...(contactId && { contactId }),\n };\n\n const link = await api.share.createShareLink(input);\n return link;\n },\n enabled: isIdRequired ? Boolean(shouldFetch && item?.id) : true,\n staleTime: 5 * 60 * 1000,\n gcTime: 10 * 60 * 1000,\n });\n\n const getShareLink = useCallback(async () => {\n if (shareLink) return shareLink;\n const result = await refetch();\n return result.data;\n }, [shareLink, refetch]);\n\n const resetShareLink = useCallback(() => {\n queryClient.removeQueries({ queryKey });\n }, [queryClient, queryKey]);\n\n return {\n loading,\n shareLink,\n getShareLink,\n resetShareLink,\n error,\n };\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { shareables } from \"../types\";\nimport { useShareablesApi } from \"../api-context\";\nimport { useRepContext } from \"../context\";\nimport { shareablesKeys } from \"../query-keys\";\n\nexport interface UseMediaMutationsOptions {\n onDeleteSuccess?: (id: number) => void;\n onDeleteError?: (error: Error, id: number) => void;\n onDuplicateSuccess?: (newMedia: shareables.MediumResponse) => void;\n onDuplicateError?: (error: Error) => void;\n}\n\nexport const useMediaMutations = (options?: UseMediaMutationsOptions) => {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n const repContext = useRepContext();\n\n // Delete media mutation with optimistic updates\n const deleteMutation = useMutation({\n mutationFn: (id: number) => {\n return api.media.deleteMedia(id);\n },\n onMutate: async (id: number) => {\n await queryClient.cancelQueries({\n queryKey: shareablesKeys.media.all,\n });\n\n // Optimistically remove from media lists\n const previousData = queryClient.getQueriesData({\n queryKey: shareablesKeys.media.all,\n });\n\n queryClient.setQueriesData<unknown>(\n { queryKey: shareablesKeys.media.all },\n (oldData: unknown) => {\n if (!oldData) return oldData;\n\n // Handle different response formats\n if (Array.isArray(oldData)) {\n return oldData.filter((item: { id: number }) => item.id !== id);\n }\n\n const dataObj = oldData as Record<string, unknown>;\n if (dataObj.data && Array.isArray(dataObj.data)) {\n return {\n ...dataObj,\n data: dataObj.data.filter(\n (item: { id: number }) => item.id !== id,\n ),\n };\n }\n\n if (dataObj.media && Array.isArray(dataObj.media)) {\n return {\n ...dataObj,\n media: dataObj.media.filter(\n (item: { id: number }) => item.id !== id,\n ),\n };\n }\n\n return oldData;\n },\n );\n\n // Remove individual media query\n queryClient.removeQueries({\n queryKey: shareablesKeys.media.detail(id, repContext),\n });\n\n return { previousData, id };\n },\n onSuccess: async (_, id) => {\n // Invalidate all media queries to refetch fresh data\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.media.all,\n });\n options?.onDeleteSuccess?.(id);\n },\n onError: (error: Error, _id: number, context) => {\n // Rollback optimistic updates\n if (context?.previousData) {\n context.previousData.forEach(([queryKey, data]) => {\n queryClient.setQueryData(queryKey, data);\n });\n }\n\n console.error(\"Error deleting media:\", error);\n options?.onDeleteError?.(error, _id);\n },\n });\n\n // Duplicate media mutation with optimistic update\n const duplicateMutation = useMutation({\n mutationFn: (mediaData: shareables.MediumUpdate) => {\n return api.media.createMedia(mediaData);\n },\n onMutate: async (mediaData) => {\n await queryClient.cancelQueries({\n queryKey: shareablesKeys.media.all,\n });\n\n // Generate temporary ID for optimistic update\n const tempId = Date.now();\n\n // Create optimistic media object\n const optimisticMedia = {\n id: tempId,\n title: mediaData.title || \"Untitled Media\",\n description: mediaData.description || null,\n media_type: \"share\",\n media_format: null,\n image_url: mediaData.image_url || null,\n video_url: mediaData.video_url || null,\n pdf_url: mediaData.pdf_url || null,\n stripped: mediaData.description || null,\n active: mediaData.active ?? true,\n visibility: mediaData.visibility || null,\n share_link: null,\n views: 0,\n leads: 0,\n watch: null,\n video_status: null,\n duration: null,\n cta_url: mediaData.cta_url || null,\n cta_button_text: mediaData.cta_button_text || null,\n cta_enabled: mediaData.cta_enabled ?? false,\n cta_action_type: mediaData.cta_action_type || null,\n video_shopping_enabled: mediaData.video_shopping_enabled ?? false,\n prompts_enabled: mediaData.prompts_enabled ?? false,\n ranks: [],\n preview_link: null,\n attached_shareables: [],\n subtitles: {},\n user_id: null,\n created_at: new Date().toISOString(),\n };\n\n // Snapshot previous data for rollback\n const previousMediaLists = queryClient.getQueriesData({\n queryKey: shareablesKeys.media.all,\n });\n\n // Optimistically add media to list queries\n queryClient.setQueriesData<unknown>(\n { queryKey: shareablesKeys.media.all },\n (oldData: unknown) => {\n if (!oldData) return [optimisticMedia];\n\n // Handle different response formats\n if (Array.isArray(oldData)) {\n return [optimisticMedia, ...oldData];\n }\n\n const dataObj = oldData as Record<string, unknown>;\n if (dataObj.data && Array.isArray(dataObj.data)) {\n return { ...dataObj, data: [optimisticMedia, ...dataObj.data] };\n }\n\n if (dataObj.media && Array.isArray(dataObj.media)) {\n return { ...dataObj, media: [optimisticMedia, ...dataObj.media] };\n }\n\n return oldData;\n },\n );\n\n // Set optimistic individual media query\n queryClient.setQueryData(\n shareablesKeys.media.detail(tempId, repContext),\n {\n media: optimisticMedia,\n },\n );\n\n return { previousMediaLists, tempId };\n },\n onError: (_error, _mediaData, context) => {\n // Rollback optimistic updates\n if (context) {\n context.previousMediaLists.forEach(([queryKey, data]) => {\n queryClient.setQueryData(queryKey, data);\n });\n\n queryClient.removeQueries({\n queryKey: shareablesKeys.media.detail(context.tempId),\n });\n }\n\n console.error(\"Error duplicating media:\", _error);\n options?.onDuplicateError?.(_error);\n },\n onSuccess: async (data, _mediaData, context) => {\n const realMediaId = data.id;\n\n if (context) {\n // Remove optimistic data\n queryClient.removeQueries({\n queryKey: shareablesKeys.media.detail(context.tempId),\n });\n }\n\n // Set real media data\n queryClient.setQueryData(\n shareablesKeys.media.detail(realMediaId, repContext),\n {\n media: data,\n },\n );\n\n options?.onDuplicateSuccess?.(data);\n\n // Invalidate lists to get fresh data\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.media.all,\n predicate: (query) => {\n return query.queryKey.length === 1 && query.queryKey[0] === \"media\";\n },\n });\n },\n });\n\n // Handler functions\n const handleDelete = async (id: number) => {\n try {\n await deleteMutation.mutateAsync(id);\n } catch (error) {\n console.error(\"Delete failed:\", error);\n }\n };\n\n const handleDuplicate = async (mediaData: shareables.MediumUpdate) => {\n try {\n await duplicateMutation.mutateAsync(mediaData);\n } catch (error) {\n console.error(\"Duplicate failed:\", error);\n }\n };\n\n return {\n deleteMutation,\n duplicateMutation,\n handleDelete,\n handleDuplicate,\n };\n};\n\n// ---------------------------------------------------------------------------\n// useCreateMediaMutation — dedicated create (no optimistic duplication logic)\n// ---------------------------------------------------------------------------\n\nexport interface UseCreateMediaOptions {\n onSuccess?: (newMedia: shareables.MediumResponse) => void;\n onError?: (error: Error) => void;\n}\n\nexport const useCreateMediaMutation = (options?: UseCreateMediaOptions) => {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (payload: shareables.MediumUpdate) => {\n return api.media.createMedia(payload);\n },\n onSuccess: (data) => {\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.media.all,\n });\n options?.onSuccess?.(data);\n },\n onError: (error) => {\n console.error(\"Error creating media:\", error);\n options?.onError?.(error as Error);\n },\n });\n};\n","/**\n * Check if an error is a cancellation/abort error from TanStack Query or AbortController.\n */\nexport function isCancellationError(error: unknown): boolean {\n return (\n !!error &&\n typeof error === \"object\" &&\n \"name\" in error &&\n (error.name === \"CancelledError\" || error.name === \"AbortError\")\n );\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { shareables } from \"../types\";\nimport { useShareablesApi } from \"../api-context\";\nimport { shareablesKeys } from \"../query-keys\";\nimport { isCancellationError } from \"../utils\";\n\n// ---------------------------------------------------------------------------\n// Types for optimistic updates (internal)\n// ---------------------------------------------------------------------------\n\ninterface PlaylistItemLike {\n id?: number | null;\n order?: number;\n relateable_type?: string | null;\n relateable?: unknown;\n}\n\n// ---------------------------------------------------------------------------\n// useAddItemToPlaylistMutation\n// ---------------------------------------------------------------------------\n\nexport interface UseAddItemOptions {\n onSuccess?: (playlistId: number) => void;\n onError?: (error: Error, playlistId: number) => void;\n}\n\ninterface AddItemToPlaylistParams {\n playlistId: number;\n newItem: PlaylistItemLike;\n data: { relateable_type: string; relateable_id: number; order: number };\n}\n\nexport const useAddItemToPlaylistMutation = (options?: UseAddItemOptions) => {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({ playlistId, data }: AddItemToPlaylistParams) => {\n return api.playlists.addItemToPlaylist(playlistId, {\n items: [data],\n });\n },\n onMutate: async ({ playlistId, newItem }: AddItemToPlaylistParams) => {\n await queryClient.cancelQueries({\n queryKey: shareablesKeys.playlists.detail(playlistId),\n });\n\n const previousData = queryClient.getQueryData(\n shareablesKeys.playlists.detail(playlistId),\n );\n\n queryClient.setQueryData(\n shareablesKeys.playlists.detail(playlistId),\n (old: unknown) => {\n if (!old || typeof old !== \"object\" || !(\"playlist\" in old))\n return old;\n\n const playlistData = old as {\n playlist: { items?: PlaylistItemLike[] };\n };\n return {\n ...playlistData,\n playlist: {\n ...playlistData.playlist,\n items: [...(playlistData.playlist.items || []), newItem],\n },\n };\n },\n );\n\n return { previousData };\n },\n onSuccess: (_, { playlistId }) => {\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.detail(playlistId),\n });\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.all,\n });\n options?.onSuccess?.(playlistId);\n },\n onError: (error, { playlistId }, context) => {\n // Always rollback optimistic updates first\n if (context?.previousData) {\n queryClient.setQueryData(\n shareablesKeys.playlists.detail(playlistId),\n context.previousData,\n );\n }\n\n if (isCancellationError(error)) return;\n\n console.error(\"Error adding item to playlist:\", error);\n options?.onError?.(error as Error, playlistId);\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// useRemoveItemsFromPlaylistMutation\n// ---------------------------------------------------------------------------\n\nexport interface UseRemoveItemsOptions {\n onSuccess?: (playlistId: number) => void;\n onError?: (error: Error, playlistId: number) => void;\n}\n\ninterface RemoveItemsFromPlaylistParams {\n playlistId: number;\n itemIds: number[];\n}\n\nexport const useRemoveItemsFromPlaylistMutation = (\n options?: UseRemoveItemsOptions,\n) => {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({ playlistId, itemIds }: RemoveItemsFromPlaylistParams) => {\n return api.playlists.removeItemsFromPlaylist(playlistId, {\n item_ids: itemIds,\n });\n },\n onMutate: async ({\n playlistId,\n itemIds,\n }: RemoveItemsFromPlaylistParams) => {\n await queryClient.cancelQueries({\n queryKey: shareablesKeys.playlists.detail(playlistId),\n });\n\n const previousData = queryClient.getQueryData(\n shareablesKeys.playlists.detail(playlistId),\n );\n\n queryClient.setQueryData(\n shareablesKeys.playlists.detail(playlistId),\n (old: unknown) => {\n if (!old || typeof old !== \"object\" || !(\"playlist\" in old))\n return old;\n\n const playlistData = old as {\n playlist: { items?: PlaylistItemLike[] };\n };\n return {\n ...playlistData,\n playlist: {\n ...playlistData.playlist,\n items: (playlistData.playlist.items || []).filter(\n (item) => item.id != null && !itemIds.includes(item.id),\n ),\n },\n };\n },\n );\n\n return { previousData };\n },\n onSuccess: (_, { playlistId }) => {\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.detail(playlistId),\n });\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.all,\n });\n options?.onSuccess?.(playlistId);\n },\n onError: (error, { playlistId }, context) => {\n // Always rollback optimistic updates first\n if (context?.previousData) {\n queryClient.setQueryData(\n shareablesKeys.playlists.detail(playlistId),\n context.previousData,\n );\n }\n\n if (isCancellationError(error)) return;\n\n // \"No valid playlist items found\" means the last item was removed — treat as success\n const errorMessage =\n error && typeof error === \"object\" && \"message\" in error\n ? String(error.message)\n : \"\";\n\n if (errorMessage.includes(\"No valid playlist items found\")) {\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.detail(playlistId),\n });\n options?.onSuccess?.(playlistId);\n return;\n }\n\n console.error(\"Error removing item from playlist:\", error);\n options?.onError?.(error as Error, playlistId);\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// useCreatePlaylistMutation\n// ---------------------------------------------------------------------------\n\nexport interface UseCreatePlaylistOptions {\n onSuccess?: (response: shareables.GetPlaylistResponse) => void;\n onError?: (error: Error) => void;\n}\n\nexport const useCreatePlaylistMutation = (\n options?: UseCreatePlaylistOptions,\n) => {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (input: shareables.CreatePlaylistInput) => {\n return api.playlists.createPlaylist(input);\n },\n onSuccess: (createdPlaylist) => {\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.all,\n });\n options?.onSuccess?.(createdPlaylist);\n },\n onError: (error) => {\n if (isCancellationError(error)) return;\n\n console.error(\"Error creating playlist:\", error);\n options?.onError?.(error as Error);\n },\n });\n};\n\n// ---------------------------------------------------------------------------\n// useUpdatePlaylistMutation\n// ---------------------------------------------------------------------------\n\nexport interface UseUpdatePlaylistOptions {\n onSuccess?: (playlistId: number) => void;\n onError?: (error: Error) => void;\n}\n\ninterface UpdatePlaylistParams {\n playlistId: number;\n data: shareables.UpdatePlaylistInput;\n}\n\nexport const useUpdatePlaylistMutation = (\n options?: UseUpdatePlaylistOptions,\n) => {\n const api = useShareablesApi();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({ playlistId, data }: UpdatePlaylistParams) => {\n return api.playlists.updatePlaylist(playlistId, data);\n },\n onSuccess: (_, { playlistId }) => {\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.all,\n });\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.detail(playlistId),\n });\n options?.onSuccess?.(playlistId);\n },\n onError: (error) => {\n if (isCancellationError(error)) return;\n\n console.error(\"Error updating playlist:\", error);\n options?.onError?.(error as Error);\n },\n });\n};\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { FilePickerApi } from \"@fluid-app/file-picker-core\";\n\nexport type RenderImageProps = {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n fill?: boolean;\n className?: string;\n onError?: () => void;\n};\n\nexport interface ShareablesUIConfig {\n /** User info for fallback logo, etc. */\n user?: { id: number; company?: { logo_url?: string | null } | null } | null;\n /** Base path for rep links (e.g., \"/rep/123\") */\n basePath: string;\n /** Navigation callback — replaces useRouter.push */\n navigate: (path: string) => void;\n /** Toast callback — replaces fluidToast */\n showToast: (opts: {\n title: string;\n type: \"success\" | \"error\" | \"warning\";\n error?: unknown;\n }) => void;\n /** MySite share handler — admin-coupled (dynamic import).\n * The implementation is responsible for providing user-specific fields\n * (affiliate_id, country_id) from its own auth context. */\n onMySiteShare?: (params: {\n shareLink: string;\n relateable_id: number;\n relateable_type: string;\n }) => Promise<{ is_favorited: boolean }>;\n /** File download handler — replaces useFileDownload */\n onFileDownload?: (url: string, filename: string) => void;\n /** File picker API for DAM asset browsing/uploading */\n filePickerApi?: FilePickerApi;\n /** Custom image renderer — replaces next/image imports */\n renderImage?: (props: RenderImageProps) => React.ReactNode;\n /** Toggle favorite on a playlist (Library) or other entity.\n * Host app provides the implementation since the endpoint lives\n * outside the shareables API domain. */\n onToggleFavorite?: (params: {\n favoriteableId: number;\n favoriteableType: string;\n }) => Promise<{ is_favorited: boolean }>;\n /** Delete a playlist by ID. */\n onDeletePlaylist?: (playlistId: number) => Promise<void>;\n /** When true, hides create/edit/delete actions (e.g. for customer users). */\n readOnly?: boolean;\n}\n\nconst MISSING_PROVIDER = Symbol(\"missing-shareables-provider\");\n\nconst ShareablesUIContext = createContext<\n ShareablesUIConfig | typeof MISSING_PROVIDER\n>(MISSING_PROVIDER);\n\nexport function ShareablesUIProvider({\n config,\n children,\n}: {\n config: ShareablesUIConfig;\n children: React.ReactNode;\n}) {\n return (\n <ShareablesUIContext.Provider value={config}>\n {children}\n </ShareablesUIContext.Provider>\n );\n}\n\nfunction defaultRenderImage(props: RenderImageProps): React.ReactNode {\n return (\n <img\n src={props.src}\n alt={props.alt}\n width={props.width}\n height={props.height}\n className={`${props.fill ? \"absolute inset-0 h-full w-full object-cover\" : \"\"} ${props.className ?? \"\"}`}\n onError={props.onError}\n />\n );\n}\n\nexport function useRenderImage(): (props: RenderImageProps) => React.ReactNode {\n const ctx = useContext(ShareablesUIContext);\n if (ctx === MISSING_PROVIDER) {\n return defaultRenderImage;\n }\n return ctx.renderImage ?? defaultRenderImage;\n}\n\nexport function useShareablesUI(): ShareablesUIConfig {\n const ctx = useContext(ShareablesUIContext);\n if (ctx === MISSING_PROVIDER) {\n throw new Error(\n \"useShareablesUI must be used within a <ShareablesUIProvider>. \" +\n \"Wrap your component tree with <ShareablesUIProvider config={...}>.\",\n );\n }\n return ctx;\n}\n","export const stripTags = (str: string) => {\n if (!str) return \"\";\n\n if (typeof document === \"undefined\") {\n // SSR fallback: decode common HTML entities then strip tags\n return str\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/<[^>]*>/g, \"\");\n }\n\n // Decoding HTML entities since user-input description might contain them\n const temp = document.createElement(\"textarea\");\n temp.innerHTML = str;\n const decoded = temp.value;\n\n const doc = new DOMParser().parseFromString(decoded, \"text/html\");\n return doc.body.textContent || \"\";\n};\n","export interface SocialShareParams {\n url: string;\n title?: string;\n description?: string;\n hashtags?: string[];\n}\n\nexport function getFacebookShareUrl({\n url,\n title,\n description,\n}: SocialShareParams): string {\n const params = new URLSearchParams({\n u: url,\n ...(title && { quote: title }),\n ...(description && { description }),\n });\n\n return `https://www.facebook.com/sharer/sharer.php?${params.toString()}`;\n}\n\nexport function getXShareUrl({\n url,\n title,\n hashtags,\n}: SocialShareParams): string {\n const params = new URLSearchParams({\n url,\n ...(title && { text: title }),\n ...(hashtags && hashtags.length > 0 && { hashtags: hashtags.join(\",\") }),\n });\n\n return `https://twitter.com/intent/tweet?${params.toString()}`;\n}\n\nexport function getLinkedInShareUrl({\n url,\n title,\n description,\n}: SocialShareParams): string {\n const params = new URLSearchParams({\n url,\n ...(title && { title }),\n ...(description && { summary: description }),\n });\n\n return `https://www.linkedin.com/sharing/share-offsite/?${params.toString()}`;\n}\n\nexport function handleInstagramShare({\n url,\n}: SocialShareParams): Promise<void> {\n return navigator.clipboard.writeText(url).then(() => {\n setTimeout(() => {\n window.open(\"https://www.instagram.com\", \"_blank\");\n }, 2000);\n });\n}\n\nexport function handleTikTokShare({ url }: SocialShareParams): Promise<void> {\n return navigator.clipboard.writeText(url).then(() => {\n setTimeout(() => {\n window.open(\"https://www.tiktok.com\", \"_blank\");\n }, 2000);\n });\n}\n\nexport function openSocialShare(shareUrl: string): void {\n const width = 600;\n const height = 400;\n const left = (window.screen.width - width) / 2;\n const top = (window.screen.height - height) / 2;\n\n window.open(\n shareUrl,\n \"social-share\",\n `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`,\n );\n}\n\nexport async function handleSocialShare(\n platform: \"facebook\" | \"x\" | \"linkedin\" | \"instagram\" | \"tiktok\",\n params: SocialShareParams,\n onSuccess?: (message: string) => void,\n onError?: (message: string) => void,\n): Promise<void> {\n try {\n switch (platform) {\n case \"facebook\":\n openSocialShare(getFacebookShareUrl(params));\n onSuccess?.(\"Opening Facebook share dialog...\");\n break;\n\n case \"x\":\n openSocialShare(getXShareUrl(params));\n onSuccess?.(\"Opening X share dialog...\");\n break;\n\n case \"linkedin\":\n openSocialShare(getLinkedInShareUrl(params));\n onSuccess?.(\"Opening LinkedIn share dialog...\");\n break;\n\n case \"instagram\":\n await handleInstagramShare(params);\n onSuccess?.(\n \"Link copied! Opening Instagram and paste link in bio or post!.\",\n );\n break;\n\n case \"tiktok\":\n await handleTikTokShare(params);\n onSuccess?.(\"Link copied! Opening TikTok and paste in your link!\");\n break;\n\n default:\n throw new Error(`Unsupported platform: ${platform}`);\n }\n } catch (error) {\n console.error(\"Social sharing error:\", error);\n onError?.(`Failed to share on ${platform}. Please try again.`);\n }\n}\n","export type OperatingSystem =\n | \"mac\"\n | \"windows\"\n | \"linux\"\n | \"ios\"\n | \"android\"\n | \"unknown\";\n\nexport function getOperatingSystem(): OperatingSystem {\n if (typeof navigator === \"undefined\") {\n return \"unknown\";\n }\n\n const userAgent = navigator.userAgent.toLowerCase();\n const platform = navigator.platform?.toLowerCase() || \"\";\n\n if (/iphone|ipad|ipod/.test(userAgent)) {\n return \"ios\";\n }\n\n if (/android/.test(userAgent)) {\n return \"android\";\n }\n\n if (/mac/.test(platform) || /darwin/.test(userAgent)) {\n return \"mac\";\n }\n\n if (/win/.test(platform) || /windows/.test(userAgent)) {\n return \"windows\";\n }\n\n if (/linux/.test(platform) || /x11/.test(platform)) {\n return \"linux\";\n }\n\n return \"unknown\";\n}\n\nexport function isMobileDevice(): boolean {\n const os = getOperatingSystem();\n return os === \"ios\" || os === \"android\";\n}\n\nexport function isDesktopDevice(): boolean {\n const os = getOperatingSystem();\n return os === \"mac\" || os === \"windows\" || os === \"linux\";\n}\n","import type { FetchClient } from \"../lib/fetch-client\";\nimport type { products } from \"../custom/products\";\n\n// ============================================================================\n// Products - List & Get\n// ============================================================================\n\nexport async function listProducts(\n client: FetchClient,\n params?: products.ListProductsParams,\n): Promise<products.ProductsResponse> {\n const { sorting, ...rest } = params ?? {};\n return client.get(\"/company/v1/products\", {\n ...rest,\n ...(sorting && { order_by: [sorting.id, sorting.desc ? \"desc\" : \"asc\"] }),\n });\n}\n\nexport async function getProduct(\n client: FetchClient,\n id: string | number,\n options?: { lang?: string; country_code?: string },\n): Promise<products.ProductResponse> {\n return client.get(`/company/v1/products/${id}`, {\n ...(options?.lang && { lang: options.lang }),\n ...(options?.country_code && { country_code: options.country_code }),\n });\n}\n\nexport async function listProductsV2(\n client: FetchClient,\n params?: products.ListProductsV2Params,\n): Promise<products.ProductsV2Response> {\n const { sorting, ...rest } = params ?? {};\n return client.get(\"/v2025-06/products\", {\n ...rest,\n ...(sorting && { order_by: [sorting.id, sorting.desc ? \"desc\" : \"asc\"] }),\n });\n}\n\nexport async function searchProducts(\n client: FetchClient,\n searchTerm: string,\n countryCodes: readonly string[],\n): Promise<products.ProductsResponse> {\n const input: Record<string, unknown> = {\n limit: 100,\n };\n if (searchTerm) {\n input.search_query = searchTerm;\n }\n if (countryCodes && countryCodes.length > 0) {\n input.country_code = countryCodes;\n }\n return client.get(\"/company/v1/products\", input);\n}\n\n// ============================================================================\n// Products - Create, Delete, Duplicate\n// ============================================================================\n\nexport async function createProduct(\n client: FetchClient,\n product: products.CreateProduct,\n): Promise<products.ProductResponse> {\n return client.post(\"/company/v1/products\", { product });\n}\n\nexport async function deleteProduct(\n client: FetchClient,\n id: number,\n): Promise<products.DeleteProductResponse> {\n return client.delete(`/company/v1/products/${id}`);\n}\n\nexport async function duplicateProduct(\n client: FetchClient,\n id: number,\n): Promise<products.DuplicateProductResponse> {\n return client.post(`/company/v1/products/${id}/duplicate`);\n}\n\n// ============================================================================\n// Products - Status Changes\n// ============================================================================\n\nexport async function archiveProduct(\n client: FetchClient,\n product: { id: number; title: string },\n): Promise<products.ProductResponse> {\n return client.patch(`/company/v1/products/${product.id}`, {\n id: product.id.toString(),\n product: {\n title: product.title || \"\",\n status: \"archived\",\n },\n });\n}\n\nexport async function unarchiveProduct(\n client: FetchClient,\n product: { id: number; title: string },\n): Promise<products.ProductResponse> {\n return client.patch(`/company/v1/products/${product.id}`, {\n id: product.id.toString(),\n product: {\n title: product.title || \"\",\n status: \"active\",\n },\n });\n}\n\nexport async function draftProduct(\n client: FetchClient,\n product: { id: number; title: string },\n): Promise<products.ProductResponse> {\n return client.patch(`/company/v1/products/${product.id}`, {\n id: product.id.toString(),\n product: {\n title: product.title || \"\",\n status: \"draft\",\n },\n });\n}\n\nexport async function sendProductToTop(\n client: FetchClient,\n id: number,\n): Promise<products.SendToTopResponse> {\n return client.patch(`/company/v1/products/${id}/send_to_top`);\n}\n","\"use client\";\n\nimport { Card, Badge } from \"@fluid-app/ui-primitives\";\nimport { CirclePlay } from \"lucide-react\";\nimport { useShareablesUI, useRenderImage } from \"../../context\";\n\nexport interface ShareItemCardProps {\n /** Display title */\n title: string;\n /** Image URL to display */\n imageUrl?: string | null;\n /** Navigation URL when card is clicked */\n href: string;\n /** Optional badge to display (e.g., \"5 items\", \"12 assets\") */\n badge?: {\n text: string;\n isLoading?: boolean;\n };\n /** Whether this item is a video */\n isVideo?: boolean;\n /** Subtitle text below the title */\n subtitle?: string;\n}\n\nconst DEFAULT_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png\";\n\nexport default function ShareItemCard({\n title,\n imageUrl,\n href,\n badge,\n isVideo = false,\n subtitle = \"Click to find shareable assets\",\n}: ShareItemCardProps) {\n const { navigate } = useShareablesUI();\n const renderImage = useRenderImage();\n\n function handleClick() {\n navigate(href);\n }\n\n return (\n <Card\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleClick();\n }\n }}\n className=\"group hover:bg-muted cursor-pointer gap-0 overflow-hidden rounded-lg border-0 p-0 shadow-none transition-colors\"\n >\n {/* Image container */}\n <div className=\"bg-muted relative aspect-square overflow-hidden rounded-lg\">\n {renderImage({\n src: imageUrl || DEFAULT_IMAGE,\n alt: title,\n fill: true,\n className: \"object-cover transition-transform group-hover:scale-105\",\n })}\n\n {/* Video play indicator */}\n {isVideo && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-foreground/50 flex h-16 w-16 items-center justify-center rounded-full backdrop-blur-sm\">\n <CirclePlay className=\"text-background h-12 w-12\" />\n </div>\n </div>\n )}\n\n {/* Badge */}\n {badge && !isVideo && !badge.isLoading && (\n <Badge className=\"absolute top-2 right-2 shadow-lg\" variant=\"default\">\n {badge.text}\n </Badge>\n )}\n\n {/* Loading indicator for badge */}\n {badge?.isLoading && !isVideo && (\n <div className=\"bg-muted-foreground absolute top-2 right-2 h-6 w-6 animate-pulse rounded-full\" />\n )}\n </div>\n\n {/* Item info */}\n <div className=\"px-2 pt-2 pb-4\">\n <h3 className=\"text-foreground line-clamp-2 text-sm leading-tight font-bold\">\n {title || \"Untitled\"}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">{subtitle}</p>\n </div>\n </Card>\n );\n}\n","import ShareItemCard from \"../ShareItemCard\";\n\ninterface ShareProductCardProps {\n product: {\n id: number;\n title: string;\n image_url?: string | null;\n images?: Array<{ image_url: string; position?: number }> | null;\n kind?: string;\n video_url?: string;\n };\n mediaCount?: number;\n}\n\nfunction getProductImageUrl(\n product: ShareProductCardProps[\"product\"],\n): string | null {\n if (Array.isArray(product.images) && product.images.length > 0) {\n const sortedImages = [...product.images].sort(\n (a, b) => (a.position ?? 0) - (b.position ?? 0),\n );\n const primaryImage = sortedImages[0];\n if (primaryImage?.image_url) {\n return primaryImage.image_url;\n }\n }\n return product.image_url ?? null;\n}\n\nexport default function ShareProductCard({\n product,\n mediaCount,\n}: ShareProductCardProps) {\n const imageUrl = getProductImageUrl(product);\n const isVideo = product.kind === \"video\" && !!product.video_url;\n\n return (\n <ShareItemCard\n title={product.title}\n imageUrl={imageUrl}\n href={`product/${product.id}`}\n badge={\n !isVideo && mediaCount != null\n ? { text: `${mediaCount} assets` }\n : undefined\n }\n isVideo={isVideo}\n />\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { listProducts } from \"@fluid-app/products-api-client\";\nimport { useShareablesClient } from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n Skeleton,\n} from \"@fluid-app/ui-primitives\";\nimport { SearchSort } from \"@fluid-app/ui-components/components/SearchSort\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport ShareProductCard from \"../MediaShare/products/ShareProductCard\";\nimport type { PortalProductsResponse } from \"../portal-product-types\";\n\nconst PAGE_SIZE = 24;\n\nconst GRID_CLASS =\n \"grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-4\";\n\nexport interface ProductsScreenProps {\n countryCode?: string;\n fetchProducts?: (\n search: string,\n cursor?: string,\n limit?: number,\n ) => Promise<PortalProductsResponse>;\n onNavigate?: (screen: string, detailId?: string) => void;\n}\n\nexport function ProductsScreen({\n countryCode,\n fetchProducts: fetchPortalProducts,\n onNavigate,\n}: ProductsScreenProps) {\n const client = useShareablesClient();\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">Products</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n const observerTarget = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedSearch(searchTerm);\n }, 300);\n return () => clearTimeout(timer);\n }, [searchTerm]);\n\n // Portal-tenant query (cursor-based)\n const portalQuery = useInfiniteQuery({\n queryKey: [\"portal-product-catalog\", debouncedSearch || \"\", PAGE_SIZE],\n queryFn: async ({ pageParam }) => {\n return fetchPortalProducts!(debouncedSearch, pageParam, PAGE_SIZE);\n },\n getNextPageParam: (lastPage) =>\n lastPage.meta?.pagination?.next_cursor ?? undefined,\n initialPageParam: undefined as string | undefined,\n enabled: !!fetchPortalProducts,\n });\n\n // Legacy query (page-based) — used when fetchProducts prop is not provided\n const legacyQuery = useInfiniteQuery({\n queryKey: [\"shareables-products\", debouncedSearch, countryCode],\n queryFn: async ({ pageParam = 1 }) => {\n // Invariant: `enabled` guarantees `client` is non-null when this runs.\n if (!client) throw new Error(\"Unreachable: client is null\");\n const response = await listProducts(client, {\n page: pageParam,\n per_page: PAGE_SIZE,\n search_query: debouncedSearch || undefined,\n sorting: { id: \"title\", desc: false },\n status: [\"active\"],\n country_code: countryCode ? [countryCode] : [\"US\"],\n published_stores: [\"rep\"],\n });\n return response.products;\n },\n getNextPageParam: (lastPage, allPages) =>\n lastPage.length === PAGE_SIZE ? allPages.length + 1 : undefined,\n initialPageParam: 1,\n enabled: !fetchPortalProducts && !!client,\n });\n\n // When neither `fetchPortalProducts` nor `client` is available, both\n // queries are disabled and the screen renders with an empty product list.\n const usePortal = !!fetchPortalProducts;\n const activeQuery = usePortal ? portalQuery : legacyQuery;\n\n const {\n data,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n error,\n } = activeQuery;\n\n const handleIntersect = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n },\n [hasNextPage, isFetchingNextPage, fetchNextPage],\n );\n\n useEffect(() => {\n const target = observerTarget.current;\n if (!target) return;\n\n const observer = new IntersectionObserver(handleIntersect, {\n threshold: 0.1,\n rootMargin: \"200px\",\n });\n observer.observe(target);\n return () => observer.disconnect();\n }, [handleIntersect]);\n\n const products = useMemo(() => {\n if (!data) return [];\n if (usePortal) {\n const portalData = data as typeof portalQuery.data;\n return (\n portalData?.pages.flatMap((page) =>\n page.products.map((p) => ({\n id: p.id ?? 0,\n title: p.name ?? \"\",\n image_url: p.images?.[0]?.url ?? null,\n media_count: p.media_count,\n })),\n ) ?? []\n );\n }\n const legacyData = data as typeof legacyQuery.data;\n return (\n legacyData?.pages.flat().map((p) => ({\n id: p.id,\n title: p.title ?? \"\",\n image_url:\n p.image_url ??\n (\n p.images as\n | Array<{ image_url: string; position?: number }>\n | undefined\n )?.[0]?.image_url ??\n null,\n media_count: undefined as number | undefined,\n })) ?? []\n );\n }, [data, usePortal]);\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-10 flex-1\" />\n </div>\n <div className={GRID_CLASS}>\n {Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"space-y-2\">\n <Skeleton className=\"aspect-square w-full rounded-lg\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-destructive text-sm\">\n Failed to load products. Please try again.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"flex justify-end\">\n <div className=\"w-full max-w-sm\">\n <SearchSort\n searchValue={searchTerm}\n onSearchChange={setSearchTerm}\n placeholder=\"Search products...\"\n />\n </div>\n </div>\n\n {/* Products grid */}\n {products.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-muted-foreground text-sm\">\n {debouncedSearch\n ? \"No products match your search.\"\n : \"No products available.\"}\n </p>\n </div>\n ) : (\n <div className={GRID_CLASS}>\n {products.map((product) => (\n <ShareProductCard\n key={product.id}\n product={{\n id: product.id,\n title: product.title,\n image_url: product.image_url,\n }}\n mediaCount={product.media_count}\n />\n ))}\n </div>\n )}\n\n {isFetchingNextPage && (\n <div className=\"flex justify-center py-4\">\n <div className=\"border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent\" />\n </div>\n )}\n\n <div ref={observerTarget} className=\"h-1\" />\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { Button, Badge } from \"@fluid-app/ui-primitives\";\nimport { useRenderImage } from \"../../context\";\nimport { Maximize, X } from \"lucide-react\";\n\ninterface SharePageImageDisplayProps {\n displayImage: string;\n displayTitle: string;\n displayVideo?: string;\n isVideo: boolean;\n badgeLabel: string;\n}\n\nexport default function SharePageImageDisplay({\n displayImage,\n displayTitle,\n displayVideo,\n isVideo,\n badgeLabel,\n}: SharePageImageDisplayProps) {\n const [isPreviewOpen, setIsPreviewOpen] = useState(false);\n const renderImage = useRenderImage();\n\n return (\n <div className=\"relative h-full w-full overflow-hidden rounded-2xl bg-gray-100\">\n {isVideo ? (\n <video\n src={displayVideo || \"\"}\n className=\"h-full w-full object-cover\"\n autoPlay\n muted\n loop\n controls\n />\n ) : (\n renderImage({\n src: displayImage,\n alt: displayTitle,\n fill: true,\n className: \"object-cover\",\n })\n )}\n\n {/* Badge in top-right corner */}\n <Badge\n variant=\"secondary\"\n className=\"absolute top-3 right-3 z-10 bg-gray-100 text-gray-900 hover:bg-gray-100\"\n >\n {badgeLabel}\n </Badge>\n\n {/* Expand button for videos */}\n {isVideo && (\n <Button\n onClick={() => setIsPreviewOpen(true)}\n className=\"absolute top-3 left-3 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white/90 text-gray-700 backdrop-blur-sm transition-colors hover:bg-white\"\n variant=\"ghost\"\n size=\"sm\"\n >\n <Maximize className=\"h-4 w-4\" />\n </Button>\n )}\n\n {/* Fullscreen Video Preview */}\n {isPreviewOpen && isVideo && (\n <div\n className=\"fixed inset-0 z-9999 flex items-center justify-center bg-black\"\n onClick={() => setIsPreviewOpen(false)}\n >\n <Button\n onClick={() => setIsPreviewOpen(false)}\n className=\"absolute top-4 right-4 z-10000 flex h-10 w-10 items-center justify-center rounded-full bg-white/90 text-gray-900 backdrop-blur-sm transition-colors hover:bg-white\"\n variant=\"ghost\"\n size=\"sm\"\n >\n <X className=\"h-5 w-5\" />\n </Button>\n <video\n src={displayVideo || \"\"}\n className=\"max-h-screen max-w-full\"\n autoPlay\n controls\n onClick={(e) => e.stopPropagation()}\n />\n </div>\n )}\n </div>\n );\n}\n","import { useMemo } from \"react\";\n\ninterface QrCodeDisplayProps {\n url: string | null | undefined;\n alt?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n}\n\nexport function QrCodeDisplay({\n url,\n alt = \"QR Code\",\n size = \"md\",\n className = \"\",\n}: QrCodeDisplayProps) {\n const qrCodeUrl = useMemo(\n () =>\n url\n ? `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(url)}`\n : \"\",\n [url],\n );\n\n const sizeClasses = {\n sm: \"h-16 w-16\",\n md: \"h-[120px] w-[120px]\",\n lg: \"h-40 w-40\",\n };\n\n const iconSizes = {\n sm: \"h-4 w-4\",\n md: \"h-8 w-8\",\n lg: \"h-12 w-12\",\n };\n\n return (\n <div\n className={`flex ${sizeClasses[size]} items-center justify-center overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm ${className}`}\n >\n {qrCodeUrl ? (\n <img\n src={qrCodeUrl}\n alt={alt}\n className=\"h-full w-full object-cover\"\n loading=\"lazy\"\n onError={(e) => {\n e.currentTarget.style.display = \"none\";\n const parent = e.currentTarget.parentElement;\n if (parent) parent.title = \"QR code failed to load\";\n }}\n />\n ) : (\n <div className=\"flex items-center justify-center text-gray-400\">\n <svg\n className={iconSizes[size]}\n fill=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M3 3h6v6H3V3zm8 0h6v6h-6V3zm8 0h2v2h-2V3zm0 4h2v2h-2V7zM3 11h6v6H3v-6zm8 0h6v6h-6v-6zm8 0h2v2h-2v-2zm0 4h2v2h-2v-2zM3 19h6v2H3v-2zm8 0h6v2h-6v-2zm8 0h2v2h-2v-2z\" />\n </svg>\n </div>\n )}\n </div>\n );\n}\n","import type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement>;\n\nexport function FacebookIcon(props: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\" />\n </svg>\n );\n}\n\nexport function InstagramIcon(props: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z\" />\n </svg>\n );\n}\n\nexport function TikTokIcon(props: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z\" />\n </svg>\n );\n}\n\nexport function XTwitterIcon(props: IconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n {...props}\n >\n <path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n </svg>\n );\n}\n","\"use client\";\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport { QrCodeDisplay } from \"../QrCodeDisplay\";\nimport { Menu, Copy } from \"lucide-react\";\nimport {\n FacebookIcon,\n InstagramIcon,\n TikTokIcon,\n XTwitterIcon,\n} from \"../icons/social-icons\";\nimport { handleSocialShare } from \"../../utils/social-sharing\";\nimport { isMobileDevice } from \"../../utils/os-detection\";\nimport { useShareablesUI } from \"../../context\";\n\ninterface ShareLinkSectionProps {\n shareLink: string | null;\n loading: boolean;\n displayTitle: string;\n isVideo: boolean;\n relateableId: number;\n relateableType: \"Product\" | \"Medium\" | \"Page\" | \"EnrollmentPack\" | \"Library\";\n}\n\nexport default function ShareLinkSection({\n shareLink,\n loading,\n displayTitle,\n isVideo,\n relateableId,\n relateableType,\n}: ShareLinkSectionProps) {\n const { showToast, onMySiteShare } = useShareablesUI();\n\n const handleCopyLink = async () => {\n if (shareLink) {\n try {\n await navigator.clipboard.writeText(shareLink);\n showToast({\n title: \"Share link copied to clipboard!\",\n type: \"success\",\n });\n } catch (error) {\n showToast({\n title: \"Failed to copy link to clipboard\",\n type: \"error\",\n error,\n });\n }\n }\n };\n\n const handlePlatformShare = async (platform: string) => {\n if (!shareLink) {\n showToast({\n title: \"Share link not available yet. Please wait...\",\n type: \"error\",\n });\n return;\n }\n await handleSocialShare(\n platform.toLowerCase() as\n | \"facebook\"\n | \"x\"\n | \"linkedin\"\n | \"instagram\"\n | \"tiktok\",\n {\n url: shareLink,\n title: displayTitle,\n description: `Check out this ${isVideo ? \"video\" : \"image\"}: ${displayTitle}`,\n },\n (message) => showToast({ title: message, type: \"success\" }),\n (message) => showToast({ title: message, type: \"error\" }),\n );\n };\n\n const handleMySiteShareClick = async () => {\n if (!shareLink) {\n showToast({\n title: \"Share link not available yet. Please wait...\",\n type: \"error\",\n });\n return;\n }\n\n if (onMySiteShare) {\n try {\n const result = await onMySiteShare({\n shareLink,\n relateable_id: relateableId,\n relateable_type: relateableType,\n });\n showToast({\n title: result.is_favorited\n ? \"Added to MySite\"\n : \"Removed from MySite\",\n type: \"success\",\n });\n } catch (error) {\n showToast({\n title: \"Failed to share to MySite\",\n type: \"error\",\n error,\n });\n }\n }\n };\n\n const socialPlatforms = [\n { name: \"Facebook\", Icon: FacebookIcon },\n { name: \"Instagram\", Icon: InstagramIcon },\n { name: \"TikTok\", Icon: TikTokIcon },\n { name: \"X\", Icon: XTwitterIcon },\n ];\n\n return (\n <div className=\"space-y-4\">\n {/* Header with divider lines */}\n <div className=\"flex items-center gap-3\">\n <h3 className=\"text-foreground shrink-0 text-sm font-semibold\">\n Share Your Unique Link\n </h3>\n <div className=\"bg-foreground h-px flex-1\" />\n </div>\n\n <div className=\"flex items-start gap-4\">\n {/* QR Code */}\n <div className=\"bg-muted shrink-0 rounded-md p-2\">\n <QrCodeDisplay\n url={shareLink}\n alt=\"QR Code for share link\"\n size=\"sm\"\n className=\"h-[75px] w-[75px] rounded-none! border-none\"\n />\n </div>\n\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n {/* Social buttons */}\n <div className=\"scrollbar-none flex flex-nowrap items-center gap-2 overflow-x-auto\">\n <Button\n onClick={handleMySiteShareClick}\n variant=\"secondary\"\n size=\"sm\"\n className=\"border-foreground bg-background text-foreground hover:bg-muted h-8 rounded-md border px-3 text-xs font-semibold transition-colors\"\n >\n MySite\n </Button>\n {isMobileDevice() ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n className=\"border-foreground bg-background text-foreground hover:bg-muted h-8 rounded-md border px-3 text-xs font-semibold transition-colors\"\n >\n <Menu className=\"mr-1 h-3 w-3\" />\n Share\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"w-48\">\n {socialPlatforms.map((platform) => (\n <DropdownMenuItem\n key={platform.name}\n onClick={() => handlePlatformShare(platform.name)}\n className=\"flex cursor-pointer items-center gap-2\"\n >\n <platform.Icon className=\"h-4 w-4\" />\n {platform.name}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n socialPlatforms.map((platform) => (\n <Button\n key={platform.name}\n onClick={() => handlePlatformShare(platform.name)}\n variant=\"secondary\"\n size=\"sm\"\n className=\"border-foreground bg-background text-foreground hover:bg-muted h-8 rounded-md border px-3 text-xs font-semibold transition-colors\"\n >\n <platform.Icon className=\"mr-1.5 h-3 w-3\" />\n {platform.name}\n </Button>\n ))\n )}\n </div>\n\n {/* Gradient URL bar */}\n <div\n className=\"flex h-10 items-center gap-2 rounded-lg px-3\"\n style={{\n background:\n \"linear-gradient(81.27deg, #E5F7FF 0.95%, #FFDBF5 34.5%, #FFE0CF 60.44%, #EDFFFB 75.06%, #FFDBF5 99.76%)\",\n }}\n >\n <span className=\"flex-1 truncate text-sm text-[#344054]\">\n {shareLink || (loading ? \"Generating link...\" : \"Loading...\")}\n </span>\n <Button\n onClick={handleCopyLink}\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-6 w-6 shrink-0 p-0 hover:bg-transparent\"\n disabled={!shareLink}\n >\n <Copy className=\"h-4 w-4 text-[#344054]\" />\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import React, { useCallback } from \"react\";\nimport { Spinner, Button } from \"@fluid-app/ui-primitives\";\nimport { useRenderImage } from \"../../context\";\nimport { Image, Play, FileImage } from \"lucide-react\";\n\nconst PLACEHOLDER_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/placeholder.png\";\n\nconst FILTER_TABS = [\"All\", \"Images\", \"Videos\"];\n\n// Sub-components\n\ninterface FilterTabsProps {\n tabs: string[];\n activeTab: string;\n onTabChange: (tab: string) => void;\n}\n\nconst FilterTabs = React.memo(function FilterTabs({\n tabs,\n activeTab,\n onTabChange,\n}: FilterTabsProps) {\n return (\n <div className=\"mb-3 flex gap-2\">\n {tabs.map((tab) => (\n <Button\n key={tab}\n onClick={() => onTabChange(tab)}\n variant=\"secondary\"\n size=\"sm\"\n className={`inline-flex items-center gap-x-1.5 rounded-sm border-none px-2 py-1 text-xs font-medium capitalize shadow-none! transition-colors ${\n activeTab === tab\n ? \"bg-primary text-primary-foreground ring-primary hover:bg-primary hover:text-primary-foreground hover:ring-primary\"\n : \"bg-muted text-foreground hover:bg-primary hover:text-primary-foreground hover:ring-primary\"\n }`}\n >\n {tab}\n </Button>\n ))}\n </div>\n );\n});\n\ninterface MediaCardProps {\n mediaItem: MediaItem;\n onClick: (mediaItem: MediaItem) => void;\n}\n\nconst MediaCard = React.memo(function MediaCard({\n mediaItem,\n onClick,\n}: MediaCardProps) {\n const renderImage = useRenderImage();\n const isVideo = mediaItem.kind === \"video\";\n const isImage = mediaItem.kind === \"image\";\n\n const MediaIcon = isVideo ? Play : isImage ? FileImage : Image;\n\n return (\n <button\n onClick={() => onClick(mediaItem)}\n className=\"group flex w-full flex-col gap-2 text-left transition-all\"\n >\n {/* Media Image */}\n <div className=\"bg-background relative aspect-[3/4] w-full overflow-hidden rounded-lg\">\n {renderImage({\n src: mediaItem.image_url || PLACEHOLDER_IMAGE,\n alt: mediaItem.title || \"Media\",\n fill: true,\n className: \"object-cover\",\n })}\n\n {/* Media Type Icon Badge in top-right corner */}\n <div className=\"absolute top-2 right-2\">\n <div className=\"bg-background/90 flex h-8 w-8 items-center justify-center rounded-full shadow-md backdrop-blur-sm\">\n <MediaIcon className=\"h-4 w-4 text-gray-900\" />\n </div>\n </div>\n </div>\n\n {/* Title */}\n <h3 className=\"text-foreground line-clamp-2 px-1 text-[15px] leading-[1.4] font-semibold\">\n {mediaItem.title || \"Untitled\"}\n </h3>\n </button>\n );\n});\n\ninterface LoadingStateProps {\n message?: string;\n}\n\nconst LoadingState = React.memo(function LoadingState({\n message = \"Loading media...\",\n}: LoadingStateProps) {\n return (\n <div className=\"flex flex-col items-center justify-center gap-3 py-12\">\n <Spinner className=\"size-8\" />\n <div className=\"text-muted-foreground text-sm\">{message}</div>\n </div>\n );\n});\n\ninterface ErrorStateProps {\n message?: string;\n}\n\nconst ErrorState = React.memo(function ErrorState({\n message = \"Failed to load media\",\n}: ErrorStateProps) {\n return (\n <div className=\"flex items-center justify-center\">\n <div className=\"text-sm text-red-500\">{message}</div>\n </div>\n );\n});\n\ninterface EmptyStateProps {\n message: string;\n icon?: React.ReactNode;\n description?: string;\n}\n\nconst EmptyState = React.memo(function EmptyState({\n message,\n icon,\n description,\n}: EmptyStateProps) {\n return (\n <div className=\"flex items-center justify-center py-8\">\n {icon && <div className=\"mb-2 text-gray-400\">{icon}</div>}\n <div className=\"text-center\">\n <div className=\"text-sm text-gray-500\">{message}</div>\n {description && (\n <div className=\"text-xs text-gray-400\">{description}</div>\n )}\n </div>\n </div>\n );\n});\n\nconst AnalyticsPlaceholder = React.memo(function AnalyticsPlaceholder() {\n return (\n <div className=\"flex flex-1 items-center justify-center\">\n <div className=\"text-center\">\n <div className=\"mb-1 text-sm text-gray-500\">Analytics Coming Soon</div>\n <div className=\"text-xs text-gray-400\">\n View engagement metrics and performance data\n </div>\n </div>\n </div>\n );\n});\n\nconst RELATEABLE_TYPE_LABELS: Record<string, string> = {\n Product: \"product\",\n Medium: \"media\",\n EnrollmentPack: \"enrollment pack\",\n MySite: \"site\",\n Library: \"library\",\n};\n\nconst NoAssetsState = React.memo(function NoAssetsState({\n relateable_type,\n}: {\n relateable_type: string;\n}) {\n const label = RELATEABLE_TYPE_LABELS[relateable_type] ?? \"item\";\n return (\n <div className=\"flex flex-1 items-center justify-center px-6\">\n <div className=\"text-center\">\n <div className=\"mb-2 text-gray-400\">\n <Image className=\"mx-auto h-12 w-12\" />\n </div>\n <div className=\"mb-1 text-sm text-gray-500\">No Marketing Assets</div>\n <div className=\"text-xs text-gray-400\">\n This {label} does not have any associated media\n </div>\n </div>\n </div>\n );\n});\n\nexport interface MediaItem {\n id: number;\n title: string;\n image_url?: string | null;\n kind: string;\n video_url?: string | null;\n media_format?: string | null;\n}\n\ninterface MarketingAssetsGridProps {\n isLoading: boolean;\n error: Error | null;\n activeTab: string;\n onTabChange: (tab: string) => void;\n mediaItems: MediaItem[];\n onMediaItemClick: (mediaItem: MediaItem) => void;\n showEmptyState?: boolean;\n activeMainTab?: string;\n relateable_type:\n | \"Product\"\n | \"Medium\"\n | \"EnrollmentPack\"\n | \"MySite\"\n | \"Library\";\n}\n\nfunction MarketingAssetsGrid({\n isLoading,\n error,\n activeTab,\n onTabChange,\n mediaItems,\n onMediaItemClick,\n showEmptyState = false,\n activeMainTab = \"Related Sharables\",\n relateable_type,\n}: MarketingAssetsGridProps) {\n const handleMediaItemClick = useCallback(\n (mediaItem: MediaItem) => {\n onMediaItemClick(mediaItem);\n },\n [onMediaItemClick],\n );\n\n // Render content based on current state\n const renderContent = () => {\n if (showEmptyState) {\n return <NoAssetsState relateable_type={relateable_type} />;\n }\n if (activeMainTab === \"Analytics\" && relateable_type === \"Medium\") {\n return <AnalyticsPlaceholder />;\n }\n\n if (activeMainTab === \"Related Sharables\") {\n return (\n <>\n {/* Header */}\n <div className=\"mb-4 px-4 pt-4\">\n <h2 className=\"text-foreground text-[15px] leading-[1.4] font-semibold\">\n Related Sharables ({mediaItems.length})\n </h2>\n </div>\n\n {/* Content */}\n <div className=\"px-4 pb-4\">\n <FilterTabs\n tabs={FILTER_TABS}\n activeTab={activeTab}\n onTabChange={onTabChange}\n />\n\n {isLoading && <LoadingState />}\n {error && <ErrorState />}\n\n {!isLoading && !error && mediaItems.length > 0 && (\n <div className=\"grid grid-cols-2 gap-4 xl:grid-cols-3\">\n {mediaItems.map((mediaItem: MediaItem) => (\n <MediaCard\n key={mediaItem.id}\n mediaItem={mediaItem}\n onClick={handleMediaItemClick}\n />\n ))}\n </div>\n )}\n\n {!isLoading && !error && mediaItems.length === 0 && (\n <EmptyState message={`No ${activeTab.toLowerCase()} found`} />\n )}\n </div>\n </>\n );\n }\n\n return null;\n };\n\n return (\n <div\n className=\"hide-scrollbar bg-background flex min-h-0 flex-1 flex-col overflow-y-auto\"\n style={{ scrollbarWidth: \"none\", msOverflowStyle: \"none\" }}\n >\n {/* MainTabs hidden */}\n {renderContent()}\n </div>\n );\n}\n\n// Memoize the entire component to prevent unnecessary re-renders\nexport default React.memo(MarketingAssetsGrid);\n","\"use client\";\n\nimport { useState, useCallback, useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { getProduct } from \"@fluid-app/products-api-client\";\nimport {\n useShareablesApi,\n useShareablesClient,\n useShareLink,\n} from \"@fluid-app/shareables-core\";\nimport type { PortalProductResponse } from \"../portal-product-types\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n Button,\n Separator,\n Spinner,\n} from \"@fluid-app/ui-primitives\";\nimport { Download } from \"lucide-react\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport SharePageImageDisplay from \"../SharePage/SharePageImageDisplay\";\nimport ShareLinkSection from \"../SharePage/ShareLinkSection\";\nimport MarketingAssetsGrid from \"../ShareablesModal/MarketingAssetsGrid\";\nimport type { MediaItem } from \"../ShareablesModal/MarketingAssetsGrid\";\nimport { useShareablesUI } from \"../../context\";\nimport { stripTags } from \"../../utils/strip-tags\";\n\nexport interface ProductDetailScreenProps {\n productId: string;\n countryCode?: string;\n fetchProduct?: (id: string | number) => Promise<PortalProductResponse>;\n onNavigate?: (screen: string, detailId?: string) => void;\n onBack?: () => void;\n}\n\nexport function ProductDetailScreen({\n productId,\n countryCode,\n fetchProduct: fetchPortalProduct,\n onNavigate,\n onBack,\n}: ProductDetailScreenProps) {\n const api = useShareablesApi();\n const client = useShareablesClient();\n const { navigate, showToast, onFileDownload } = useShareablesUI();\n const [activeTab, setActiveTab] = useState(\"All\");\n const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false);\n\n // Portal-tenant product fetch\n const { data: portalProductResponse, isLoading: isLoadingPortalProduct } =\n useQuery({\n queryKey: [\"portal-products\", \"detail\", productId],\n queryFn: () => fetchPortalProduct!(productId),\n enabled: !!fetchPortalProduct,\n });\n\n // Legacy product fetch\n const { data: legacyProductResponse, isLoading: isLoadingLegacyProduct } =\n useQuery({\n queryKey: [\"product\", productId],\n queryFn: () => {\n // Invariant: `enabled` guarantees `client` is non-null when this runs.\n if (!client) throw new Error(\"Unreachable: client is null\");\n return getProduct(client, productId, { country_code: countryCode });\n },\n enabled: !fetchPortalProduct && !!client,\n });\n\n const isLoadingProduct = fetchPortalProduct\n ? isLoadingPortalProduct\n : isLoadingLegacyProduct;\n\n // Fetch product media\n const {\n data: productMediaResponse,\n isLoading: isLoadingMedia,\n error: mediaError,\n } = useQuery({\n queryKey: [\"media\", \"public\", productId],\n queryFn: () => api.productMedia.getProductMedia(Number(productId)),\n });\n\n // Share link\n const {\n shareLink,\n loading: shareLinkLoading,\n error: shareLinkError,\n } = useShareLink({ id: Number(productId) }, \"Product\");\n\n // Derive display values from whichever source is available\n const portalProduct = portalProductResponse?.product;\n const legacyProduct = legacyProductResponse?.product;\n const product = portalProduct || legacyProduct;\n\n const displayTitle = portalProduct?.name || legacyProduct?.title || \"\";\n const displayImage =\n portalProduct?.images?.[0]?.url || legacyProduct?.image_url || \"\";\n const displayDescription =\n portalProduct?.description ||\n legacyProduct?.description ||\n legacyProduct?.stripped ||\n \"\";\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n (onBack ?? (() => navigate(\"products\")))();\n }}\n >\n Products\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {displayTitle || \"Product\"}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [displayTitle, onBack, navigate],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n const strippedDescription = stripTags(displayDescription);\n const shouldShowReadMore = strippedDescription.length > 150;\n const displayPrice = (() => {\n if (legacyProduct?.display_price) return legacyProduct.display_price;\n const price = portalProduct?.price ?? legacyProduct?.price;\n if (!price) return undefined;\n const numericPrice = Number(price);\n if (Number.isNaN(numericPrice)) return `$${price}`;\n try {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: portalProduct?.currency || \"USD\",\n }).format(numericPrice);\n } catch {\n return `$${price}`;\n }\n })();\n\n // Filter media items\n const filteredMediaItems: MediaItem[] = (productMediaResponse?.media ?? [])\n .filter((item: { kind: string | null }) => {\n if (activeTab === \"All\") return true;\n if (activeTab === \"Images\") return item.kind === \"image\";\n if (activeTab === \"Videos\") return item.kind === \"video\";\n return true;\n })\n .map(\n (item: {\n id: number;\n title: string;\n image_url?: string | null;\n kind: string | null;\n video_url?: string | null;\n media_format?: string | null;\n }) => ({\n id: item.id,\n title: item.title,\n image_url: item.image_url,\n kind: item.kind || \"\",\n video_url: item.video_url,\n media_format: item.media_format,\n }),\n );\n\n const hasMedia = (productMediaResponse?.media?.length || 0) > 0;\n\n // Download handler\n const handleDownload = useCallback(() => {\n if (!displayImage) {\n showToast({\n title: \"No downloadable asset available\",\n type: \"error\",\n });\n return;\n }\n if (onFileDownload) {\n onFileDownload(displayImage, displayTitle || \"product\");\n } else {\n window.open(displayImage, \"_blank\");\n }\n }, [displayImage, displayTitle, onFileDownload, showToast]);\n\n // Media item click\n const handleMediaItemClick = useCallback(\n (mediaItem: MediaItem) => {\n onNavigate?.(\"media\", String(mediaItem.id));\n },\n [onNavigate],\n );\n\n // Loading state\n if (isLoadingProduct) {\n return (\n <div className=\"flex items-center justify-center py-16\">\n <Spinner className=\"size-8\" />\n </div>\n );\n }\n\n // No data state\n if (!product) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-destructive text-sm\">\n Product not found or failed to load.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-4 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"mx-auto flex w-full max-w-480 flex-col gap-6 md:h-[calc(100vh-140px)] md:flex-row\">\n {/* Left Column - Image with badge */}\n <div className=\"aspect-square w-full md:aspect-auto md:h-full\">\n <div className=\"relative h-full overflow-hidden rounded-2xl\">\n <SharePageImageDisplay\n displayImage={displayImage}\n displayTitle={displayTitle}\n isVideo={false}\n badgeLabel=\"Product\"\n />\n </div>\n </div>\n\n {/* Right Column - Details and Related Sharables */}\n <div className=\"flex w-full flex-col md:overflow-y-auto\">\n {/* Details Panel */}\n <div className=\"space-y-4\">\n {/* Title */}\n <h1 className=\"text-foreground text-[26px] leading-[1.2] font-semibold\">\n {displayTitle}\n </h1>\n\n {/* Description */}\n {strippedDescription && (\n <div className=\"text-foreground/70 text-sm leading-relaxed\">\n <div\n className={\n !isDescriptionExpanded && shouldShowReadMore\n ? \"line-clamp-3\"\n : \"\"\n }\n >\n {strippedDescription}\n </div>\n {shouldShowReadMore && (\n <Button\n onClick={() =>\n setIsDescriptionExpanded(!isDescriptionExpanded)\n }\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-foreground hover:text-foreground/80 mt-1 h-auto p-0 text-xs font-normal underline\"\n >\n {isDescriptionExpanded ? \"Read less\" : \"Read more\"}\n </Button>\n )}\n </div>\n )}\n\n {/* Price */}\n {displayPrice && (\n <div className=\"text-foreground flex items-center gap-2 text-sm\">\n <span className=\"font-semibold\">Price</span>\n <span>|</span>\n <span className=\"font-semibold\">{displayPrice}</span>\n </div>\n )}\n\n {/* Download Button */}\n {displayImage && (\n <Button\n onClick={handleDownload}\n className=\"bg-foreground text-background hover:bg-foreground/70 flex h-10 w-full items-center justify-between rounded-lg px-4 transition-all\"\n >\n <span className=\"text-sm font-medium\">Download Asset</span>\n <Download className=\"h-4 w-4\" />\n </Button>\n )}\n\n {/* Share Link Section */}\n <ShareLinkSection\n shareLink={shareLinkError ? null : shareLink || null}\n loading={shareLinkLoading}\n displayTitle={displayTitle}\n isVideo={false}\n relateableId={Number(productId)}\n relateableType=\"Product\"\n />\n </div>\n\n {/* Divider + Marketing Assets */}\n <Separator className=\"border-foreground my-4\" />\n\n <div className=\"hide-scrollbar bg-background h-full overflow-y-auto rounded-lg\">\n <MarketingAssetsGrid\n isLoading={isLoadingMedia}\n error={mediaError as Error | null}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n mediaItems={filteredMediaItems}\n onMediaItemClick={handleMediaItemClick}\n showEmptyState={!hasMedia}\n activeMainTab=\"Related Sharables\"\n relateable_type=\"Product\"\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useInfiniteQuery, keepPreviousData } from \"@tanstack/react-query\";\nimport {\n useShareablesApi,\n useRepContext,\n shareablesKeys,\n} from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n Button,\n Skeleton,\n} from \"@fluid-app/ui-primitives\";\nimport { SearchSort } from \"@fluid-app/ui-components/components/SearchSort\";\nimport { LayoutGrid, List, Plus } from \"lucide-react\";\nimport {\n useScreenHeaderActions,\n useScreenHeaderBreadcrumbs,\n} from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport ShareItemCard from \"../MediaShare/ShareItemCard\";\nimport { useShareablesUI } from \"../../context\";\n\nconst PAGE_SIZE = 24;\n\nconst GRID_CLASS =\n \"grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-4\";\n\nfunction getMediaKindLabel(kind: string | null): string {\n switch (kind) {\n case \"video\":\n return \"Video\";\n case \"pdf\":\n return \"PDF\";\n default:\n return \"Image\";\n }\n}\n\nexport interface MediaListingScreenProps {\n onNavigate?: (screen: string, detailId?: string) => void;\n}\n\ntype ViewMode = \"grid\" | \"list\";\n\nexport function MediaListingScreen({ onNavigate }: MediaListingScreenProps) {\n const api = useShareablesApi();\n const repContext = useRepContext();\n const { navigate, readOnly } = useShareablesUI();\n\n const headerActions = useMemo(\n () =>\n readOnly ? null : (\n <Button onClick={() => navigate(\"media/new\")} size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n Add Media\n </Button>\n ),\n [navigate, readOnly],\n );\n useScreenHeaderActions(headerActions);\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">Media</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n const [sortValue, setSortValue] = useState(\"title_asc\");\n const [viewMode, setViewMode] = useState<ViewMode>(\"grid\");\n const observerTarget = useRef<HTMLDivElement>(null);\n\n // Debounce search input\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedSearch(searchTerm);\n }, 300);\n return () => clearTimeout(timer);\n }, [searchTerm]);\n\n const {\n data,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n error,\n } = useInfiniteQuery({\n queryKey: shareablesKeys.media.list(\n debouncedSearch,\n sortValue === \"title_desc\",\n repContext,\n ),\n queryFn: async ({ pageParam = 1 }) => {\n const response = await api.media.getMedia({\n page: pageParam,\n per_page: PAGE_SIZE,\n search_query: debouncedSearch || undefined,\n sorted_by: sortValue,\n });\n return { media: response.media, nextPage: response.meta?.next ?? null };\n },\n getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined,\n initialPageParam: 1,\n placeholderData: keepPreviousData,\n });\n\n const handleIntersect = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n },\n [hasNextPage, isFetchingNextPage, fetchNextPage],\n );\n\n useEffect(() => {\n const target = observerTarget.current;\n if (!target) return;\n\n const observer = new IntersectionObserver(handleIntersect, {\n threshold: 0.1,\n rootMargin: \"200px\",\n });\n observer.observe(target);\n return () => observer.disconnect();\n }, [handleIntersect]);\n\n const mediaItems = data?.pages.flatMap((page) => page.media) ?? [];\n\n // Loading skeleton\n if (isLoading) {\n return (\n <div className=\"space-y-6 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-10 flex-1\" />\n <Skeleton className=\"h-10 w-10\" />\n </div>\n <div className={GRID_CLASS}>\n {Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"space-y-2\">\n <Skeleton className=\"aspect-square w-full rounded-lg\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-destructive text-sm\">\n Failed to load media. Please try again.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 px-4 py-4 md:px-10 md:py-6\">\n {/* Search, sort, and view toggle */}\n <div className=\"flex items-center justify-end gap-2\">\n <div className=\"w-full max-w-sm\">\n <SearchSort\n searchValue={searchTerm}\n onSearchChange={setSearchTerm}\n placeholder=\"Search media...\"\n sortOptions={[\n { label: \"Name (A-Z)\", value: \"title_asc\" },\n { label: \"Name (Z-A)\", value: \"title_desc\" },\n ]}\n sortValue={sortValue}\n onSortChange={setSortValue}\n />\n </div>\n\n {/* View toggle */}\n <div className=\"border-input bg-muted flex items-center rounded-lg border p-0.5\">\n <button\n type=\"button\"\n onClick={() => setViewMode(\"list\")}\n className={`flex h-8 w-8 items-center justify-center rounded-md transition-all ${\n viewMode === \"list\"\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n title=\"List view\"\n >\n <List className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode(\"grid\")}\n className={`flex h-8 w-8 items-center justify-center rounded-md transition-all ${\n viewMode === \"grid\"\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n title=\"Grid view\"\n >\n <LayoutGrid className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n {/* Media content */}\n {mediaItems.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-muted-foreground text-sm\">\n {debouncedSearch\n ? \"No media match your search.\"\n : \"No media available.\"}\n </p>\n </div>\n ) : viewMode === \"grid\" ? (\n <div className={GRID_CLASS}>\n {mediaItems.map((item) => (\n <ShareItemCard\n key={item.id}\n title={item.title ?? \"\"}\n imageUrl={item.image_url}\n href={`media/${item.id}`}\n badge={{ text: getMediaKindLabel(item.kind) }}\n isVideo={item.kind === \"video\"}\n subtitle=\"Click to view media\"\n />\n ))}\n </div>\n ) : (\n <div className=\"divide-border divide-y rounded-lg border\">\n {mediaItems.map((item) => (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => navigate(`media/${item.id}`)}\n className=\"hover:bg-muted flex w-full items-center gap-4 px-4 py-3 text-left transition-colors\"\n >\n <div className=\"bg-muted h-12 w-12 shrink-0 overflow-hidden rounded-md\">\n {item.image_url ? (\n <img\n src={item.image_url}\n alt={item.title ?? \"\"}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"bg-muted h-full w-full\" />\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate text-sm font-medium\">\n {item.title ?? \"Untitled\"}\n </p>\n <p className=\"text-muted-foreground text-xs\">\n {getMediaKindLabel(item.kind)}\n </p>\n </div>\n </button>\n ))}\n </div>\n )}\n\n {/* Loading more indicator */}\n {isFetchingNextPage && (\n <div className=\"flex justify-center py-4\">\n <div className=\"border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent\" />\n </div>\n )}\n\n {/* Intersection observer sentinel */}\n <div ref={observerTarget} className=\"h-1\" />\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback, useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport {\n useShareablesApi,\n useRepContext,\n useShareLink,\n shareablesKeys,\n} from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n Button,\n Spinner,\n} from \"@fluid-app/ui-primitives\";\nimport { Download } from \"lucide-react\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport SharePageImageDisplay from \"../SharePage/SharePageImageDisplay\";\nimport ShareLinkSection from \"../SharePage/ShareLinkSection\";\nimport { useShareablesUI } from \"../../context\";\nimport { stripTags } from \"../../utils/strip-tags\";\n\nexport interface MediaDetailScreenProps {\n mediaId: string;\n onNavigate?: (screen: string, detailId?: string) => void;\n onBack?: () => void;\n}\n\nfunction getBadgeLabel(kind: string | null): string {\n switch (kind) {\n case \"video\":\n return \"Video\";\n case \"image\":\n return \"Image\";\n case \"pdf\":\n return \"PDF\";\n default:\n return \"Media\";\n }\n}\n\nexport function MediaDetailScreen({\n mediaId,\n onNavigate: _onNavigate,\n onBack,\n}: MediaDetailScreenProps) {\n const api = useShareablesApi();\n const repContext = useRepContext();\n const { navigate, showToast, onFileDownload } = useShareablesUI();\n const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false);\n\n // Fetch media\n const { data: mediaResponse, isLoading } = useQuery({\n queryKey: shareablesKeys.media.detail(Number(mediaId), repContext),\n queryFn: () => api.media.getMediaById(Number(mediaId)),\n });\n\n // Share link — relateableType for media is \"Medium\"\n const {\n shareLink,\n loading: shareLinkLoading,\n error: shareLinkError,\n } = useShareLink({ id: Number(mediaId) }, \"Medium\");\n\n const mediaItem = mediaResponse?.media;\n\n // Derive display values\n const displayTitle = mediaItem?.title || \"\";\n const displayImage = mediaItem?.image_url || \"\";\n const displayVideo = mediaItem?.video_url || \"\";\n const isVideo = mediaItem?.kind === \"video\" && !!displayVideo;\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n (onBack ?? (() => navigate(\"media\")))();\n }}\n >\n Media\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {displayTitle || \"Media\"}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [displayTitle, onBack, navigate],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n const badgeLabel = getBadgeLabel(mediaItem?.kind ?? null);\n\n const rawDescription =\n mediaItem?.description?.body || mediaItem?.stripped || \"\";\n const strippedDescription = stripTags(rawDescription);\n const shouldShowReadMore = strippedDescription.length > 150;\n\n // Download URL: video URL for videos, image URL otherwise\n const downloadUrl = isVideo ? displayVideo : displayImage;\n\n // Download handler\n const handleDownload = useCallback(() => {\n if (!downloadUrl) {\n showToast({\n title: \"No downloadable asset available\",\n type: \"error\",\n });\n return;\n }\n if (onFileDownload) {\n onFileDownload(downloadUrl, displayTitle || \"media\");\n } else {\n window.open(downloadUrl, \"_blank\");\n }\n }, [downloadUrl, displayTitle, onFileDownload, showToast]);\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center py-16\">\n <Spinner className=\"size-8\" />\n </div>\n );\n }\n\n // No data state\n if (!mediaItem) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-destructive text-sm\">\n Media not found or failed to load.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-4 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"mx-auto flex w-full max-w-480 flex-col gap-6 md:h-[calc(100vh-140px)] md:flex-row\">\n {/* Left Column - Image/Video with badge */}\n <div className=\"aspect-square w-full md:aspect-auto md:h-full\">\n <div className=\"relative h-full overflow-hidden rounded-2xl\">\n <SharePageImageDisplay\n displayImage={displayImage}\n displayTitle={displayTitle}\n displayVideo={isVideo ? displayVideo : undefined}\n isVideo={isVideo}\n badgeLabel={badgeLabel}\n />\n </div>\n </div>\n\n {/* Right Column - Details */}\n <div className=\"flex w-full flex-col md:overflow-y-auto\">\n <div className=\"space-y-4\">\n {/* Title */}\n <h1 className=\"text-foreground text-[26px] leading-[1.2] font-semibold\">\n {displayTitle}\n </h1>\n\n {/* Description */}\n {strippedDescription && (\n <div className=\"text-foreground/70 text-sm leading-relaxed\">\n <div\n className={\n !isDescriptionExpanded && shouldShowReadMore\n ? \"line-clamp-3\"\n : \"\"\n }\n >\n {strippedDescription}\n </div>\n {shouldShowReadMore && (\n <Button\n onClick={() =>\n setIsDescriptionExpanded(!isDescriptionExpanded)\n }\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-foreground hover:text-foreground/80 mt-1 h-auto p-0 text-xs font-normal underline\"\n >\n {isDescriptionExpanded ? \"Read less\" : \"Read more\"}\n </Button>\n )}\n </div>\n )}\n\n {/* Download Button */}\n {downloadUrl && (\n <Button\n onClick={handleDownload}\n className=\"bg-foreground text-background hover:bg-foreground/70 flex h-10 w-full items-center justify-between rounded-lg px-4 transition-all\"\n >\n <span className=\"text-sm font-medium\">Download Asset</span>\n <Download className=\"h-4 w-4\" />\n </Button>\n )}\n\n {/* Share Link Section */}\n <ShareLinkSection\n shareLink={shareLinkError ? null : shareLink || null}\n loading={shareLinkLoading}\n displayTitle={displayTitle}\n isVideo={isVideo}\n relateableId={Number(mediaId)}\n relateableType=\"Medium\"\n />\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { createContext, useContext } from \"react\";\nimport type { FilePickerApi } from \"@fluid-app/file-picker-core\";\n\nconst FilePickerApiContext = createContext<FilePickerApi | null>(null);\n\nexport function FilePickerApiProvider({\n api,\n children,\n}: {\n api: FilePickerApi;\n children: React.ReactNode;\n}): React.JSX.Element {\n return (\n <FilePickerApiContext.Provider value={api}>\n {children}\n </FilePickerApiContext.Provider>\n );\n}\n\nexport function useFilePickerApi(): FilePickerApi {\n const ctx = useContext(FilePickerApiContext);\n if (!ctx) {\n throw new Error(\n \"useFilePickerApi must be used within a FilePickerApiProvider\",\n );\n }\n return ctx;\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\n\nexport interface FilePickerToast {\n success(title: string): void;\n error(title: string, error?: unknown): void;\n loading(title: string): string | number;\n dismiss(id: string | number): void;\n}\n\nexport interface FilePickerContextValue {\n companyId?: number;\n userId?: number;\n toast: FilePickerToast;\n shareablesClient?: {\n media: { list: (...args: unknown[]) => Promise<unknown> };\n };\n apiBaseUrl?: string;\n}\n\nconst FilePickerContext = createContext<FilePickerContextValue | null>(null);\n\nexport function FilePickerProvider({\n children,\n value,\n}: {\n children: React.ReactNode;\n value: FilePickerContextValue;\n}): React.JSX.Element {\n return (\n <FilePickerContext.Provider value={value}>\n {children}\n </FilePickerContext.Provider>\n );\n}\n\nexport function useFilePickerContext(): FilePickerContextValue {\n const ctx = useContext(FilePickerContext);\n if (!ctx) {\n throw new Error(\n \"useFilePickerContext must be used within a FilePickerProvider\",\n );\n }\n return ctx;\n}\n","import type React from \"react\";\n\ninterface BrandIconProps {\n className?: string;\n}\n\nexport function GoogleIcon({ className }: BrandIconProps): React.JSX.Element {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" />\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n );\n}\n\nexport function InstagramIcon({\n className,\n}: BrandIconProps): React.JSX.Element {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.406-11.845a1.44 1.44 0 1 0 0 2.881 1.44 1.44 0 0 0 0-2.881z\" />\n </svg>\n );\n}\n\nexport function FacebookIcon({ className }: BrandIconProps): React.JSX.Element {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\" />\n </svg>\n );\n}\n\nexport function TiktokIcon({ className }: BrandIconProps): React.JSX.Element {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z\" />\n </svg>\n );\n}\n\nexport function DropboxIcon({ className }: BrandIconProps): React.JSX.Element {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 6.13L6 10.13l6 4-6 4-6-4 6-4-6-4 6-4 6 4zm0 0l6-4 6 4-6 4 6 4-6 4-6-4 6-4-6-4zm0 16.74l-6-4 6-4 6 4-6 4z\" />\n </svg>\n );\n}\n\nexport function UnsplashIcon({ className }: BrandIconProps): React.JSX.Element {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M7.5 6.75V0h9v6.75h-9zm9 3.75H24V24H0V10.5h7.5v6.75h9V10.5z\" />\n </svg>\n );\n}\n","export const damQueryKeys: {\n all: readonly [\"dam\"];\n assets: () => readonly [\"dam\", \"assets\"];\n query: (params: unknown) => readonly [\"dam\", \"query\", unknown];\n} = {\n all: [\"dam\"] as const,\n assets: (): readonly [\"dam\", \"assets\"] => [\"dam\", \"assets\"] as const,\n query: (params: unknown): readonly [\"dam\", \"query\", unknown] =>\n [\"dam\", \"query\", params] as const,\n};\n","import { z } from \"zod\";\n\ntype DamVariantApi = {\n id: string;\n url: string | null;\n file_name: string;\n mime_type: string;\n content: any;\n created_at: string;\n updated_at: string;\n default: boolean;\n is_original: boolean;\n is_text: boolean;\n media_type: string;\n processing_status: string;\n tags: string[];\n};\n\nexport const damVariantSchema: z.ZodType<DamVariantApi> = z.object({\n id: z.string(),\n url: z.string().nullable(),\n file_name: z.string(),\n mime_type: z.string(),\n content: z.any().nullable(),\n created_at: z.string(),\n updated_at: z.string(),\n default: z.boolean(),\n is_original: z.boolean(),\n is_text: z.boolean(),\n media_type: z.string(),\n processing_status: z.string(),\n tags: z.array(z.string()),\n});\n\ntype DamAssetApi = {\n id: number;\n canonical_path: string;\n category: string;\n code: string;\n company: string;\n created_at: string;\n default_variant_id: string;\n default_variant_url?: string;\n description: string;\n name: string;\n updated_at: string;\n variants?: DamVariantApi[];\n};\n\nexport const damAssetSchema: z.ZodType<DamAssetApi> = z.object({\n id: z.number(),\n canonical_path: z.string(),\n category: z.string(),\n code: z.string(),\n company: z.string(),\n created_at: z.string(),\n default_variant_id: z.string(),\n default_variant_url: z.string().optional(),\n description: z.string(),\n name: z.string(),\n updated_at: z.string(),\n variants: z.array(damVariantSchema).optional(),\n});\n\ntype DamTreeFolderNode = {\n asset_code?: string | Record<string, unknown>;\n name?: string | Record<string, unknown>;\n category?: string | Record<string, unknown>;\n variants?: unknown[] | Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport const damTreeFolderNodeSchema: z.ZodType<DamTreeFolderNode> = z\n .object({\n asset_code: z\n .union([z.string(), z.record(z.string(), z.unknown())])\n .optional(),\n name: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),\n category: z\n .union([z.string(), z.record(z.string(), z.unknown())])\n .optional(),\n variants: z\n .union([z.array(z.unknown()), z.record(z.string(), z.unknown())])\n .optional(),\n })\n .passthrough();\n\nexport const damTreeSchema: z.ZodType<Record<string, any>> = z.record(\n z.string(),\n z.union([\n z.lazy(() => damTreeSchema),\n damAssetSchema,\n damTreeFolderNodeSchema,\n ]),\n);\n\ntype DamQueryResponse = {\n path: string;\n tree: Record<string, any>;\n meta?: { next_cursor?: string };\n};\n\nexport const damQueryResponseSchema: z.ZodType<DamQueryResponse> = z.object({\n path: z.string(),\n tree: damTreeSchema,\n meta: z\n .object({\n next_cursor: z.string().optional(),\n })\n .optional(),\n});\n\ntype DamAssetCreateRequest = {\n asset: {\n file: any;\n name: string;\n description?: string;\n tags?: string;\n };\n};\n\nexport const damAssetCreateRequestSchema: z.ZodType<DamAssetCreateRequest> =\n z.object({\n asset: z.object({\n file: z.any(),\n name: z.string(),\n description: z.string().optional(),\n tags: z.string().optional(),\n }),\n });\n\ntype DamAssetCreateResponse = {\n asset: DamAssetApi;\n meta: { request_id: string; timestamp: string };\n};\n\nexport const damAssetCreateResponseSchema: z.ZodType<DamAssetCreateResponse> =\n z.object({\n asset: damAssetSchema,\n meta: z.object({\n request_id: z.string(),\n timestamp: z.string(),\n }),\n });\n\n// Schema for creating asset with placeholder (for ImageKit direct upload)\ntype DamAssetCreateWithPlaceholderRequest = {\n placeholder_asset: {\n mime_type: string;\n name?: string;\n description?: string;\n };\n skip_autotagging?: boolean;\n};\n\nexport const damAssetCreateWithPlaceholderRequestSchema: z.ZodType<DamAssetCreateWithPlaceholderRequest> =\n z.object({\n placeholder_asset: z.object({\n mime_type: z.string(),\n name: z.string().optional(),\n description: z.string().optional(),\n }),\n skip_autotagging: z.boolean().optional(),\n });\n\n// Schema for creating asset path without file upload (legacy)\ntype DamAssetPathCreateRequest = {\n asset?: {\n file: any;\n name: string;\n description?: string;\n tags?: string;\n };\n text_asset?: {\n file_name: string;\n mime_type: string;\n text: string;\n name?: string;\n description?: string;\n tags?: string;\n };\n placeholder_asset?: {\n mime_type: string;\n name?: string;\n description?: string;\n };\n skip_autotagging?: boolean;\n};\n\nexport const damAssetPathCreateRequestSchema: z.ZodType<DamAssetPathCreateRequest> =\n z.object({\n asset: z\n .object({\n file: z.any(),\n name: z.string(),\n description: z.string().optional(),\n tags: z.string().optional(),\n })\n .optional(),\n text_asset: z\n .object({\n file_name: z.string(),\n mime_type: z.string(),\n text: z.string(),\n name: z.string().optional(),\n description: z.string().optional(),\n tags: z.string().optional(),\n })\n .optional(),\n placeholder_asset: z\n .object({\n mime_type: z.string(),\n name: z.string().optional(),\n description: z.string().optional(),\n })\n .optional(),\n skip_autotagging: z.boolean().optional(),\n });\n\ntype DamAssetPathCreateResponse = {\n asset: { id: number; canonical_path: string; name: string };\n meta: { request_id: string; timestamp: string };\n};\n\nexport const damAssetPathCreateResponseSchema: z.ZodType<DamAssetPathCreateResponse> =\n z.object({\n asset: z.object({\n id: z.number(),\n canonical_path: z.string(),\n name: z.string(),\n }),\n meta: z.object({\n request_id: z.string(),\n timestamp: z.string(),\n }),\n });\n\nexport type { DamVariantApi, DamAssetApi };\nexport type DamTreeApi = z.infer<typeof damTreeSchema>;\nexport type { DamQueryResponse };\nexport type { DamAssetCreateRequest };\nexport type { DamAssetCreateResponse };\nexport type { DamAssetCreateWithPlaceholderRequest };\nexport type { DamAssetPathCreateRequest };\nexport type { DamAssetPathCreateResponse };\n","import { z } from \"zod\";\n\ntype FilePickerConfigInput = {\n accept?: string[];\n maxFiles?: number;\n maxSize?: number;\n showProgress?: boolean;\n showVariants?: boolean;\n fileTypeFilter?: string[];\n allowedMethods?: (\n | \"upload\"\n | \"computer\"\n | \"dam\"\n | \"media\"\n | \"url\"\n | \"unsplash\"\n | \"google-drive\"\n | \"instagram\"\n | \"facebook\"\n | \"tiktok\"\n | \"dropbox\"\n )[];\n};\n\ntype FilePickerConfigOutput = {\n accept?: string[];\n maxFiles: number;\n maxSize?: number;\n showProgress: boolean;\n showVariants: boolean;\n fileTypeFilter?: string[];\n allowedMethods?: (\n | \"upload\"\n | \"computer\"\n | \"dam\"\n | \"media\"\n | \"url\"\n | \"unsplash\"\n | \"google-drive\"\n | \"instagram\"\n | \"facebook\"\n | \"tiktok\"\n | \"dropbox\"\n )[];\n};\n\nexport const filePickerConfigSchema: z.ZodType<FilePickerConfigOutput> =\n z.object({\n accept: z.array(z.string()).optional(),\n maxFiles: z.number().min(1).optional().default(1),\n maxSize: z.number().positive().optional(),\n showProgress: z.boolean().optional().default(true),\n showVariants: z.boolean().optional().default(false),\n fileTypeFilter: z.array(z.string()).optional(),\n allowedMethods: z\n .array(\n z.enum([\n \"upload\",\n \"computer\",\n \"dam\",\n \"media\",\n \"url\",\n \"unsplash\",\n \"google-drive\",\n \"instagram\",\n \"facebook\",\n \"tiktok\",\n \"dropbox\",\n ]),\n )\n .optional(),\n });\n\nexport type { FilePickerConfigInput, FilePickerConfigOutput };\n","export const FILTER_VALUE_ALL = \"__all__\";\n\nexport const DAM_TYPE_FILTER_OPTIONS: { value: string; label: string }[] = [\n { value: FILTER_VALUE_ALL, label: \"All types\" },\n { value: \"images\", label: \"Image\" },\n { value: \"videos\", label: \"Video\" },\n { value: \"audio\", label: \"Audio\" },\n { value: \"text\", label: \"Text\" },\n { value: \"documents\", label: \"Document\" },\n { value: \"other\", label: \"Others\" },\n];\n\nexport function getCategoryFromTypeFilter(value: string): string | undefined {\n if (!value) return undefined;\n return value;\n}\n\nexport const DATE_FILTER_OPTIONS: readonly { value: string; label: string }[] =\n [\n { value: FILTER_VALUE_ALL, label: \"Any time\" },\n { value: \"24h\", label: \"Past 24 hours\" },\n { value: \"7d\", label: \"Past 7 days\" },\n { value: \"30d\", label: \"Past 30 days\" },\n { value: \"90d\", label: \"Past 90 days\" },\n ];\n\nexport const UPLOADED_BY_OPTIONS: readonly { value: string; label: string }[] =\n [\n { value: FILTER_VALUE_ALL, label: \"Anyone\" },\n { value: \"me\", label: \"Me\" },\n ];\n\nexport const USAGE_STATUS_OPTIONS: readonly {\n value: string;\n label: string;\n}[] = [\n { value: FILTER_VALUE_ALL, label: \"Any\" },\n { value: \"used\", label: \"Used\" },\n { value: \"unused\", label: \"Unused\" },\n];\n\nexport const SOURCE_OPTIONS: readonly { value: string; label: string }[] = [\n { value: FILTER_VALUE_ALL, label: \"Any\" },\n { value: \"upload\", label: \"Upload\" },\n { value: \"dam\", label: \"DAM\" },\n];\n\n// Need to add \"newest\" and \"oldest\" options later after we have the created_at field in the API\nexport type SortOptionId = \"name_asc\" | \"name_desc\";\n\nexport const SORT_OPTIONS: Array<{\n id: SortOptionId;\n label: string;\n sortBy: string;\n sortDirection: \"asc\" | \"desc\";\n}> = [\n { id: \"name_asc\", label: \"Name A–Z\", sortBy: \"name\", sortDirection: \"asc\" },\n { id: \"name_desc\", label: \"Name Z–A\", sortBy: \"name\", sortDirection: \"desc\" },\n];\n","const EXTENSION_MIME_MAP: Record<string, string> = {\n \".heic\": \"image/heic\",\n \".heics\": \"image/heic-sequence\",\n \".heif\": \"image/heif\",\n};\n\n/**\n * Resolves MIME type from file.type, falling back to extension-based lookup\n * when the browser returns an empty type (e.g. HEIC on Chrome/Firefox).\n */\nexport function getFileMimeType(file: File): string {\n if (file.type) return file.type;\n const ext = file.name.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n return (ext && EXTENSION_MIME_MAP[ext]) || \"application/octet-stream\";\n}\n\n/**\n * Validates if a file type matches the accepted types\n */\nexport function isFileTypeAccepted(\n mimeType: string,\n fileName: string,\n acceptTypes: string[],\n): boolean {\n if (!acceptTypes || acceptTypes.length === 0) {\n return true; // No restrictions\n }\n\n return acceptTypes.some((acceptType) => {\n // Handle MIME type patterns (e.g., \"image/*\", \"video/*\")\n if (acceptType.includes(\"*\")) {\n const baseType = acceptType.split(\"/\")[0];\n const fileBaseType = mimeType.split(\"/\")[0];\n return baseType === fileBaseType;\n }\n\n // Handle exact MIME type matches (e.g., \"image/jpeg\", \"video/mp4\")\n if (acceptType.includes(\"/\") && !acceptType.startsWith(\".\")) {\n return mimeType === acceptType;\n }\n\n // Handle file extension matches (e.g., \".jpg\", \".mp4\")\n if (acceptType.startsWith(\".\")) {\n const lastDotIndex = fileName.lastIndexOf(\".\");\n if (lastDotIndex === -1) return false;\n const fileExtension = fileName.toLowerCase().substring(lastDotIndex);\n return fileExtension === acceptType.toLowerCase();\n }\n\n return false;\n });\n}\n\n/**\n * Gets a user-friendly description of accepted file types\n */\nexport function getAcceptedTypesDescription(acceptTypes: string[]): string {\n if (!acceptTypes || acceptTypes.length === 0) {\n return \"Any file type\";\n }\n\n const descriptions: string[] = [];\n const seenTypes = new Set<string>();\n\n acceptTypes.forEach((type) => {\n if (seenTypes.has(type)) return;\n seenTypes.add(type);\n\n if (type === \"image/*\") {\n descriptions.push(\"Images\");\n } else if (type === \"video/*\") {\n descriptions.push(\"Videos\");\n } else if (type === \"audio/*\") {\n descriptions.push(\"Audio\");\n } else if (type === \"application/pdf\") {\n descriptions.push(\"PDF files\");\n } else if (type.startsWith(\".\")) {\n descriptions.push(`${type.toUpperCase()} files`);\n } else if (type.includes(\"/\")) {\n descriptions.push(type);\n }\n });\n\n if (descriptions.length === 0) {\n return acceptTypes.join(\", \");\n }\n\n if (descriptions.length === 1) {\n return descriptions[0]!;\n }\n\n if (descriptions.length === 2) {\n return `${descriptions[0]!} and ${descriptions[1]!}`;\n }\n\n return `${descriptions.slice(0, -1).join(\", \")}, and ${descriptions[descriptions.length - 1]!}`;\n}\n","var _ = Object.defineProperty;\nvar $ = (a, h, e) => h in a ? _(a, h, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[h] = e;\nvar m = (a, h, e) => $(a, typeof h != \"symbol\" ? h + \"\" : h, e);\nimport u, { PureComponent as K, createRef as P } from \"react\";\nconst E = {\n x: 0,\n y: 0,\n width: 0,\n height: 0,\n unit: \"px\"\n}, b = (a, h, e) => Math.min(Math.max(a, h), e), H = (...a) => a.filter((h) => h && typeof h == \"string\").join(\" \"), X = (a, h) => a === h || a.width === h.width && a.height === h.height && a.x === h.x && a.y === h.y && a.unit === h.unit;\nfunction B(a, h, e, n) {\n const t = D(a, e, n);\n return a.width && (t.height = t.width / h), a.height && (t.width = t.height * h), t.y + t.height > n && (t.height = n - t.y, t.width = t.height * h), t.x + t.width > e && (t.width = e - t.x, t.height = t.width / h), a.unit === \"%\" ? v(t, e, n) : t;\n}\nfunction L(a, h, e) {\n const n = D(a, h, e);\n return n.x = (h - n.width) / 2, n.y = (e - n.height) / 2, a.unit === \"%\" ? v(n, h, e) : n;\n}\nfunction v(a, h, e) {\n return a.unit === \"%\" ? { ...E, ...a, unit: \"%\" } : {\n unit: \"%\",\n x: a.x ? a.x / h * 100 : 0,\n y: a.y ? a.y / e * 100 : 0,\n width: a.width ? a.width / h * 100 : 0,\n height: a.height ? a.height / e * 100 : 0\n };\n}\nfunction D(a, h, e) {\n return a.unit ? a.unit === \"px\" ? { ...E, ...a, unit: \"px\" } : {\n unit: \"px\",\n x: a.x ? a.x * h / 100 : 0,\n y: a.y ? a.y * e / 100 : 0,\n width: a.width ? a.width * h / 100 : 0,\n height: a.height ? a.height * e / 100 : 0\n } : { ...E, ...a, unit: \"px\" };\n}\nfunction k(a, h, e, n, t, d = 0, r = 0, o = n, w = t) {\n const i = { ...a };\n let s = Math.min(d, n), c = Math.min(r, t), g = Math.min(o, n), p = Math.min(w, t);\n h && (h > 1 ? (s = r ? r * h : s, c = s / h, g = o * h) : (c = d ? d / h : c, s = c * h, p = w / h)), i.y < 0 && (i.height = Math.max(i.height + i.y, c), i.y = 0), i.x < 0 && (i.width = Math.max(i.width + i.x, s), i.x = 0);\n const l = n - (i.x + i.width);\n l < 0 && (i.x = Math.min(i.x, n - s), i.width += l);\n const C = t - (i.y + i.height);\n if (C < 0 && (i.y = Math.min(i.y, t - c), i.height += C), i.width < s && ((e === \"sw\" || e == \"nw\") && (i.x -= s - i.width), i.width = s), i.height < c && ((e === \"nw\" || e == \"ne\") && (i.y -= c - i.height), i.height = c), i.width > g && ((e === \"sw\" || e == \"nw\") && (i.x -= g - i.width), i.width = g), i.height > p && ((e === \"nw\" || e == \"ne\") && (i.y -= p - i.height), i.height = p), h) {\n const y = i.width / i.height;\n if (y < h) {\n const f = Math.max(i.width / h, c);\n (e === \"nw\" || e == \"ne\") && (i.y -= f - i.height), i.height = f;\n } else if (y > h) {\n const f = Math.max(i.height * h, s);\n (e === \"sw\" || e == \"nw\") && (i.x -= f - i.width), i.width = f;\n }\n }\n return i;\n}\nfunction I(a, h, e, n) {\n const t = { ...a };\n return h === \"ArrowLeft\" ? n === \"nw\" ? (t.x -= e, t.y -= e, t.width += e, t.height += e) : n === \"w\" ? (t.x -= e, t.width += e) : n === \"sw\" ? (t.x -= e, t.width += e, t.height += e) : n === \"ne\" ? (t.y += e, t.width -= e, t.height -= e) : n === \"e\" ? t.width -= e : n === \"se\" && (t.width -= e, t.height -= e) : h === \"ArrowRight\" && (n === \"nw\" ? (t.x += e, t.y += e, t.width -= e, t.height -= e) : n === \"w\" ? (t.x += e, t.width -= e) : n === \"sw\" ? (t.x += e, t.width -= e, t.height -= e) : n === \"ne\" ? (t.y -= e, t.width += e, t.height += e) : n === \"e\" ? t.width += e : n === \"se\" && (t.width += e, t.height += e)), h === \"ArrowUp\" ? n === \"nw\" ? (t.x -= e, t.y -= e, t.width += e, t.height += e) : n === \"n\" ? (t.y -= e, t.height += e) : n === \"ne\" ? (t.y -= e, t.width += e, t.height += e) : n === \"sw\" ? (t.x += e, t.width -= e, t.height -= e) : n === \"s\" ? t.height -= e : n === \"se\" && (t.width -= e, t.height -= e) : h === \"ArrowDown\" && (n === \"nw\" ? (t.x += e, t.y += e, t.width -= e, t.height -= e) : n === \"n\" ? (t.y += e, t.height -= e) : n === \"ne\" ? (t.y += e, t.width -= e, t.height -= e) : n === \"sw\" ? (t.x -= e, t.width += e, t.height += e) : n === \"s\" ? t.height += e : n === \"se\" && (t.width += e, t.height += e)), t;\n}\nconst M = { capture: !0, passive: !1 };\nlet N = 0;\nconst x = class x extends K {\n constructor() {\n super(...arguments);\n m(this, \"docMoveBound\", !1);\n m(this, \"mouseDownOnCrop\", !1);\n m(this, \"dragStarted\", !1);\n m(this, \"evData\", {\n startClientX: 0,\n startClientY: 0,\n startCropX: 0,\n startCropY: 0,\n clientX: 0,\n clientY: 0,\n isResize: !0\n });\n m(this, \"componentRef\", P());\n m(this, \"mediaRef\", P());\n m(this, \"resizeObserver\");\n m(this, \"initChangeCalled\", !1);\n m(this, \"instanceId\", `rc-${N++}`);\n m(this, \"state\", {\n cropIsActive: !1,\n newCropIsBeingDrawn: !1\n });\n m(this, \"onCropPointerDown\", (e) => {\n const { crop: n, disabled: t } = this.props, d = this.getBox();\n if (!n)\n return;\n const r = D(n, d.width, d.height);\n if (t)\n return;\n e.cancelable && e.preventDefault(), this.bindDocMove(), this.componentRef.current.focus({ preventScroll: !0 });\n const o = e.target.dataset.ord, w = !!o;\n let i = e.clientX, s = e.clientY, c = r.x, g = r.y;\n if (o) {\n const p = e.clientX - d.x, l = e.clientY - d.y;\n let C = 0, y = 0;\n o === \"ne\" || o == \"e\" ? (C = p - (r.x + r.width), y = l - r.y, c = r.x, g = r.y + r.height) : o === \"se\" || o === \"s\" ? (C = p - (r.x + r.width), y = l - (r.y + r.height), c = r.x, g = r.y) : o === \"sw\" || o == \"w\" ? (C = p - r.x, y = l - (r.y + r.height), c = r.x + r.width, g = r.y) : (o === \"nw\" || o == \"n\") && (C = p - r.x, y = l - r.y, c = r.x + r.width, g = r.y + r.height), i = c + d.x + C, s = g + d.y + y;\n }\n this.evData = {\n startClientX: i,\n startClientY: s,\n startCropX: c,\n startCropY: g,\n clientX: e.clientX,\n clientY: e.clientY,\n isResize: w,\n ord: o\n }, this.mouseDownOnCrop = !0, this.setState({ cropIsActive: !0 });\n });\n m(this, \"onComponentPointerDown\", (e) => {\n const { crop: n, disabled: t, locked: d, keepSelection: r, onChange: o } = this.props, w = this.getBox();\n if (t || d || r && n)\n return;\n e.cancelable && e.preventDefault(), this.bindDocMove(), this.componentRef.current.focus({ preventScroll: !0 });\n const i = e.clientX - w.x, s = e.clientY - w.y, c = {\n unit: \"px\",\n x: i,\n y: s,\n width: 0,\n height: 0\n };\n this.evData = {\n startClientX: e.clientX,\n startClientY: e.clientY,\n startCropX: i,\n startCropY: s,\n clientX: e.clientX,\n clientY: e.clientY,\n isResize: !0\n }, this.mouseDownOnCrop = !0, o(D(c, w.width, w.height), v(c, w.width, w.height)), this.setState({ cropIsActive: !0, newCropIsBeingDrawn: !0 });\n });\n m(this, \"onDocPointerMove\", (e) => {\n const { crop: n, disabled: t, onChange: d, onDragStart: r } = this.props, o = this.getBox();\n if (t || !n || !this.mouseDownOnCrop)\n return;\n e.cancelable && e.preventDefault(), this.dragStarted || (this.dragStarted = !0, r && r(e));\n const { evData: w } = this;\n w.clientX = e.clientX, w.clientY = e.clientY;\n let i;\n w.isResize ? i = this.resizeCrop() : i = this.dragCrop(), X(n, i) || d(\n D(i, o.width, o.height),\n v(i, o.width, o.height)\n );\n });\n m(this, \"onComponentKeyDown\", (e) => {\n const { crop: n, disabled: t, onChange: d, onComplete: r } = this.props;\n if (t)\n return;\n const o = e.key;\n let w = !1;\n if (!n)\n return;\n const i = this.getBox(), s = this.makePixelCrop(i), g = (navigator.platform.match(\"Mac\") ? e.metaKey : e.ctrlKey) ? x.nudgeStepLarge : e.shiftKey ? x.nudgeStepMedium : x.nudgeStep;\n if (o === \"ArrowLeft\" ? (s.x -= g, w = !0) : o === \"ArrowRight\" ? (s.x += g, w = !0) : o === \"ArrowUp\" ? (s.y -= g, w = !0) : o === \"ArrowDown\" && (s.y += g, w = !0), w) {\n e.cancelable && e.preventDefault(), s.x = b(s.x, 0, i.width - s.width), s.y = b(s.y, 0, i.height - s.height);\n const p = D(s, i.width, i.height), l = v(s, i.width, i.height);\n d(p, l), r && r(p, l);\n }\n });\n m(this, \"onHandlerKeyDown\", (e, n) => {\n const {\n aspect: t = 0,\n crop: d,\n disabled: r,\n minWidth: o = 0,\n minHeight: w = 0,\n maxWidth: i,\n maxHeight: s,\n onChange: c,\n onComplete: g\n } = this.props, p = this.getBox();\n if (r || !d)\n return;\n if (e.key === \"ArrowUp\" || e.key === \"ArrowDown\" || e.key === \"ArrowLeft\" || e.key === \"ArrowRight\")\n e.stopPropagation(), e.preventDefault();\n else\n return;\n const C = (navigator.platform.match(\"Mac\") ? e.metaKey : e.ctrlKey) ? x.nudgeStepLarge : e.shiftKey ? x.nudgeStepMedium : x.nudgeStep, y = D(d, p.width, p.height), f = I(y, e.key, C, n), R = k(\n f,\n t,\n n,\n p.width,\n p.height,\n o,\n w,\n i,\n s\n );\n if (!X(d, R)) {\n const Y = v(R, p.width, p.height);\n c(R, Y), g && g(R, Y);\n }\n });\n m(this, \"onDocPointerDone\", (e) => {\n const { crop: n, disabled: t, onComplete: d, onDragEnd: r } = this.props, o = this.getBox();\n this.unbindDocMove(), !(t || !n) && this.mouseDownOnCrop && (this.mouseDownOnCrop = !1, this.dragStarted = !1, r && r(e), d && d(D(n, o.width, o.height), v(n, o.width, o.height)), this.setState({ cropIsActive: !1, newCropIsBeingDrawn: !1 }));\n });\n m(this, \"onDragFocus\", () => {\n var e;\n (e = this.componentRef.current) == null || e.scrollTo(0, 0);\n });\n }\n get document() {\n return document;\n }\n // We unfortunately get the bounding box every time as x+y changes\n // due to scrolling.\n getBox() {\n const e = this.mediaRef.current;\n if (!e)\n return { x: 0, y: 0, width: 0, height: 0 };\n const { x: n, y: t, width: d, height: r } = e.getBoundingClientRect();\n return { x: n, y: t, width: d, height: r };\n }\n componentDidUpdate(e) {\n const { crop: n, onComplete: t } = this.props;\n if (t && !e.crop && n) {\n const { width: d, height: r } = this.getBox();\n d && r && t(D(n, d, r), v(n, d, r));\n }\n }\n componentWillUnmount() {\n this.resizeObserver && this.resizeObserver.disconnect(), this.unbindDocMove();\n }\n bindDocMove() {\n this.docMoveBound || (this.document.addEventListener(\"pointermove\", this.onDocPointerMove, M), this.document.addEventListener(\"pointerup\", this.onDocPointerDone, M), this.document.addEventListener(\"pointercancel\", this.onDocPointerDone, M), this.docMoveBound = !0);\n }\n unbindDocMove() {\n this.docMoveBound && (this.document.removeEventListener(\"pointermove\", this.onDocPointerMove, M), this.document.removeEventListener(\"pointerup\", this.onDocPointerDone, M), this.document.removeEventListener(\"pointercancel\", this.onDocPointerDone, M), this.docMoveBound = !1);\n }\n getCropStyle() {\n const { crop: e } = this.props;\n if (e)\n return {\n top: `${e.y}${e.unit}`,\n left: `${e.x}${e.unit}`,\n width: `${e.width}${e.unit}`,\n height: `${e.height}${e.unit}`\n };\n }\n dragCrop() {\n const { evData: e } = this, n = this.getBox(), t = this.makePixelCrop(n), d = e.clientX - e.startClientX, r = e.clientY - e.startClientY;\n return t.x = b(e.startCropX + d, 0, n.width - t.width), t.y = b(e.startCropY + r, 0, n.height - t.height), t;\n }\n getPointRegion(e, n, t, d) {\n const { evData: r } = this, o = r.clientX - e.x, w = r.clientY - e.y;\n let i;\n d && n ? i = n === \"nw\" || n === \"n\" || n === \"ne\" : i = w < r.startCropY;\n let s;\n return t && n ? s = n === \"nw\" || n === \"w\" || n === \"sw\" : s = o < r.startCropX, s ? i ? \"nw\" : \"sw\" : i ? \"ne\" : \"se\";\n }\n resolveMinDimensions(e, n, t = 0, d = 0) {\n const r = Math.min(t, e.width), o = Math.min(d, e.height);\n return !n || !r && !o ? [r, o] : n > 1 ? r ? [r, r / n] : [o * n, o] : o ? [o * n, o] : [r, r / n];\n }\n resizeCrop() {\n const { evData: e } = this, { aspect: n = 0, maxWidth: t, maxHeight: d } = this.props, r = this.getBox(), [o, w] = this.resolveMinDimensions(r, n, this.props.minWidth, this.props.minHeight);\n let i = this.makePixelCrop(r);\n const s = this.getPointRegion(r, e.ord, o, w), c = e.ord || s;\n let g = e.clientX - e.startClientX, p = e.clientY - e.startClientY;\n (o && c === \"nw\" || c === \"w\" || c === \"sw\") && (g = Math.min(g, -o)), (w && c === \"nw\" || c === \"n\" || c === \"ne\") && (p = Math.min(p, -w));\n const l = {\n unit: \"px\",\n x: 0,\n y: 0,\n width: 0,\n height: 0\n };\n s === \"ne\" ? (l.x = e.startCropX, l.width = g, n ? (l.height = l.width / n, l.y = e.startCropY - l.height) : (l.height = Math.abs(p), l.y = e.startCropY - l.height)) : s === \"se\" ? (l.x = e.startCropX, l.y = e.startCropY, l.width = g, n ? l.height = l.width / n : l.height = p) : s === \"sw\" ? (l.x = e.startCropX + g, l.y = e.startCropY, l.width = Math.abs(g), n ? l.height = l.width / n : l.height = p) : s === \"nw\" && (l.x = e.startCropX + g, l.width = Math.abs(g), n ? (l.height = l.width / n, l.y = e.startCropY - l.height) : (l.height = Math.abs(p), l.y = e.startCropY + p));\n const C = k(\n l,\n n,\n s,\n r.width,\n r.height,\n o,\n w,\n t,\n d\n );\n return n || x.xyOrds.indexOf(c) > -1 ? i = C : x.xOrds.indexOf(c) > -1 ? (i.x = C.x, i.width = C.width) : x.yOrds.indexOf(c) > -1 && (i.y = C.y, i.height = C.height), i.x = b(i.x, 0, r.width - i.width), i.y = b(i.y, 0, r.height - i.height), i;\n }\n renderCropSelection() {\n const {\n ariaLabels: e = x.defaultProps.ariaLabels,\n disabled: n,\n locked: t,\n renderSelectionAddon: d,\n ruleOfThirds: r,\n crop: o\n } = this.props, w = this.getCropStyle();\n if (o)\n return /* @__PURE__ */ u.createElement(\n \"div\",\n {\n style: w,\n className: \"ReactCrop__crop-selection\",\n onPointerDown: this.onCropPointerDown,\n \"aria-label\": e.cropArea,\n tabIndex: 0,\n onKeyDown: this.onComponentKeyDown,\n role: \"group\"\n },\n !n && !t && /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__drag-elements\", onFocus: this.onDragFocus }, /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__drag-bar ord-n\", \"data-ord\": \"n\" }), /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__drag-bar ord-e\", \"data-ord\": \"e\" }), /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__drag-bar ord-s\", \"data-ord\": \"s\" }), /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__drag-bar ord-w\", \"data-ord\": \"w\" }), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-nw\",\n \"data-ord\": \"nw\",\n tabIndex: 0,\n \"aria-label\": e.nwDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"nw\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-n\",\n \"data-ord\": \"n\",\n tabIndex: 0,\n \"aria-label\": e.nDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"n\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-ne\",\n \"data-ord\": \"ne\",\n tabIndex: 0,\n \"aria-label\": e.neDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"ne\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-e\",\n \"data-ord\": \"e\",\n tabIndex: 0,\n \"aria-label\": e.eDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"e\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-se\",\n \"data-ord\": \"se\",\n tabIndex: 0,\n \"aria-label\": e.seDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"se\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-s\",\n \"data-ord\": \"s\",\n tabIndex: 0,\n \"aria-label\": e.sDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"s\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-sw\",\n \"data-ord\": \"sw\",\n tabIndex: 0,\n \"aria-label\": e.swDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"sw\"),\n role: \"button\"\n }\n ), /* @__PURE__ */ u.createElement(\n \"div\",\n {\n className: \"ReactCrop__drag-handle ord-w\",\n \"data-ord\": \"w\",\n tabIndex: 0,\n \"aria-label\": e.wDragHandle,\n onKeyDown: (i) => this.onHandlerKeyDown(i, \"w\"),\n role: \"button\"\n }\n )),\n d && /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__selection-addon\", onPointerDown: (i) => i.stopPropagation() }, d(this.state)),\n r && /* @__PURE__ */ u.createElement(u.Fragment, null, /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__rule-of-thirds-hz\" }), /* @__PURE__ */ u.createElement(\"div\", { className: \"ReactCrop__rule-of-thirds-vt\" }))\n );\n }\n makePixelCrop(e) {\n const n = { ...E, ...this.props.crop || {} };\n return D(n, e.width, e.height);\n }\n render() {\n const { aspect: e, children: n, circularCrop: t, className: d, crop: r, disabled: o, locked: w, style: i, ruleOfThirds: s } = this.props, { cropIsActive: c, newCropIsBeingDrawn: g } = this.state, p = r ? this.renderCropSelection() : null, l = H(\n \"ReactCrop\",\n d,\n c && \"ReactCrop--active\",\n o && \"ReactCrop--disabled\",\n w && \"ReactCrop--locked\",\n g && \"ReactCrop--new-crop\",\n r && e && \"ReactCrop--fixed-aspect\",\n r && t && \"ReactCrop--circular-crop\",\n r && s && \"ReactCrop--rule-of-thirds\",\n !this.dragStarted && r && !r.width && !r.height && \"ReactCrop--invisible-crop\",\n t && \"ReactCrop--no-animate\"\n );\n return /* @__PURE__ */ u.createElement(\"div\", { ref: this.componentRef, className: l, style: i }, /* @__PURE__ */ u.createElement(\"div\", { ref: this.mediaRef, className: \"ReactCrop__child-wrapper\", onPointerDown: this.onComponentPointerDown }, n), r ? /* @__PURE__ */ u.createElement(\"svg\", { className: \"ReactCrop__crop-mask\", width: \"100%\", height: \"100%\" }, /* @__PURE__ */ u.createElement(\"defs\", null, /* @__PURE__ */ u.createElement(\"mask\", { id: `hole-${this.instanceId}` }, /* @__PURE__ */ u.createElement(\"rect\", { width: \"100%\", height: \"100%\", fill: \"white\" }), t ? /* @__PURE__ */ u.createElement(\n \"ellipse\",\n {\n cx: `${r.x + r.width / 2}${r.unit}`,\n cy: `${r.y + r.height / 2}${r.unit}`,\n rx: `${r.width / 2}${r.unit}`,\n ry: `${r.height / 2}${r.unit}`,\n fill: \"black\"\n }\n ) : /* @__PURE__ */ u.createElement(\n \"rect\",\n {\n x: `${r.x}${r.unit}`,\n y: `${r.y}${r.unit}`,\n width: `${r.width}${r.unit}`,\n height: `${r.height}${r.unit}`,\n fill: \"black\"\n }\n ))), /* @__PURE__ */ u.createElement(\"rect\", { fill: \"black\", fillOpacity: 0.5, width: \"100%\", height: \"100%\", mask: `url(#hole-${this.instanceId})` })) : void 0, p);\n }\n};\nm(x, \"xOrds\", [\"e\", \"w\"]), m(x, \"yOrds\", [\"n\", \"s\"]), m(x, \"xyOrds\", [\"nw\", \"ne\", \"se\", \"sw\"]), m(x, \"nudgeStep\", 1), m(x, \"nudgeStepMedium\", 10), m(x, \"nudgeStepLarge\", 100), m(x, \"defaultProps\", {\n ariaLabels: {\n cropArea: \"Use the arrow keys to move the crop selection area\",\n nwDragHandle: \"Use the arrow keys to move the north west drag handle to change the crop selection area\",\n nDragHandle: \"Use the up and down arrow keys to move the north drag handle to change the crop selection area\",\n neDragHandle: \"Use the arrow keys to move the north east drag handle to change the crop selection area\",\n eDragHandle: \"Use the up and down arrow keys to move the east drag handle to change the crop selection area\",\n seDragHandle: \"Use the arrow keys to move the south east drag handle to change the crop selection area\",\n sDragHandle: \"Use the up and down arrow keys to move the south drag handle to change the crop selection area\",\n swDragHandle: \"Use the arrow keys to move the south west drag handle to change the crop selection area\",\n wDragHandle: \"Use the up and down arrow keys to move the west drag handle to change the crop selection area\"\n }\n});\nlet S = x;\nexport {\n S as Component,\n S as ReactCrop,\n X as areCropsEqual,\n L as centerCrop,\n b as clamp,\n H as cls,\n k as containCrop,\n v as convertToPercentCrop,\n D as convertToPixelCrop,\n S as default,\n E as defaultCrop,\n B as makeAspectCrop,\n I as nudgeCrop\n};\n","import {\n centerCrop,\n makeAspectCrop,\n type Crop,\n type PixelCrop,\n} from \"react-image-crop\";\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nexport const ASPECT_OPTIONS: readonly {\n label: string;\n value: \"free\" | number;\n}[] = [\n { label: \"Free\", value: \"free\" as const },\n { label: \"1:1\", value: 1 },\n { label: \"16:9\", value: 16 / 9 },\n { label: \"4:3\", value: 4 / 3 },\n];\n\nexport type AspectValue = \"free\" | number;\n\nexport const ROTATION_MIN = -180;\nexport const ROTATION_MAX = 180;\n\n// ── Crop helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Compute initial crop + completedCrop values for given container dimensions\n * and optional aspect ratio.\n *\n * Used when the image first loads, when the user resets, and when the aspect\n * ratio changes via the dropdown.\n */\nexport function computeInitialCrop(\n displayedWidth: number,\n displayedHeight: number,\n aspect?: number,\n): { crop: Crop; completedCrop: PixelCrop } {\n if (aspect) {\n const imageAspect = displayedWidth / displayedHeight;\n const seed =\n aspect > imageAspect\n ? { unit: \"%\" as const, width: 100 }\n : { unit: \"%\" as const, height: 100 };\n\n const crop = centerCrop(\n makeAspectCrop(seed, aspect, displayedWidth, displayedHeight),\n displayedWidth,\n displayedHeight,\n );\n const completedCrop: PixelCrop = {\n x: (crop.x / 100) * displayedWidth,\n y: (crop.y / 100) * displayedHeight,\n width: (crop.width / 100) * displayedWidth,\n height: (crop.height / 100) * displayedHeight,\n unit: \"px\",\n };\n return { crop, completedCrop };\n }\n\n const crop: Crop = { unit: \"%\", x: 0, y: 0, width: 100, height: 100 };\n const completedCrop: PixelCrop = {\n x: 0,\n y: 0,\n width: displayedWidth,\n height: displayedHeight,\n unit: \"px\",\n };\n return { crop, completedCrop };\n}\n\n// ── Canvas export ────────────────────────────────────────────────────────────\n\n/**\n * Render the image onto a canvas at natural (full) resolution\n * (including rotation, zoom, flip) then extract the crop rectangle as a File.\n *\n * Uses createImageBitmap() from the original file to guarantee full-resolution\n * decoding. The <img> element may have been decoded at reduced resolution by the\n * browser when displayed at a small CSS size (downsample-on-decode).\n */\nexport async function getCroppedImgFromViewport(\n image: HTMLImageElement,\n vw: number,\n vh: number,\n crop: { x: number; y: number; width: number; height: number },\n zoom: number,\n rotationDeg: number,\n flipHorizontal: boolean,\n fileName: string,\n type: string = \"image/jpeg\",\n quality: number = 0.9,\n sourceFile?: File,\n): Promise<File> {\n // Decode the image at full resolution from the original file bytes,\n // bypassing any browser downsample-on-decode optimization on the <img>.\n const bitmap = sourceFile\n ? await createImageBitmap(sourceFile)\n : await createImageBitmap(image);\n\n const nw = bitmap.width;\n const nh = bitmap.height;\n\n // Scale factor from viewport coords to natural-resolution coords.\n // Cap canvas dimensions at MAX_CANVAS_DIM to avoid exceeding browser limits\n // (most browsers cap at 16384, but we use 4096 for safe memory usage).\n const MAX_CANVAS_DIM = 4096;\n const rawUpscale = Math.max(nw / vw, nh / vh);\n const rawW = Math.round(vw * rawUpscale);\n const rawH = Math.round(vh * rawUpscale);\n const downscale = Math.min(1, MAX_CANVAS_DIM / rawW, MAX_CANVAS_DIM / rawH);\n const upscale = rawUpscale * downscale;\n const canvasW = Math.round(rawW * downscale);\n const canvasH = Math.round(rawH * downscale);\n\n const scaleFit = Math.min(canvasW / nw, canvasH / nh);\n const scale = scaleFit * zoom;\n\n const source = document.createElement(\"canvas\");\n source.width = canvasW;\n source.height = canvasH;\n const ctx = source.getContext(\"2d\");\n if (!ctx) throw new Error(\"No 2d context\");\n ctx.imageSmoothingQuality = \"high\";\n ctx.imageSmoothingEnabled = true;\n\n ctx.save();\n ctx.translate(canvasW / 2, canvasH / 2);\n ctx.rotate((rotationDeg * Math.PI) / 180);\n if (flipHorizontal) ctx.scale(-1, 1);\n ctx.scale(scale, scale);\n ctx.translate(-nw / 2, -nh / 2);\n ctx.drawImage(bitmap, 0, 0);\n ctx.restore();\n\n bitmap.close();\n\n // Scale crop coordinates to natural resolution\n const cropX = Math.max(0, Math.floor(crop.x * upscale));\n const cropY = Math.max(0, Math.floor(crop.y * upscale));\n const pw = Math.floor(crop.width * upscale);\n const ph = Math.floor(crop.height * upscale);\n\n const out = document.createElement(\"canvas\");\n out.width = pw;\n out.height = ph;\n const outCtx = out.getContext(\"2d\");\n if (!outCtx) throw new Error(\"No 2d context\");\n outCtx.imageSmoothingQuality = \"high\";\n outCtx.imageSmoothingEnabled = true;\n outCtx.drawImage(source, cropX, cropY, pw, ph, 0, 0, pw, ph);\n\n return new Promise((resolve, reject) => {\n out.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error(\"Canvas is empty\"));\n return;\n }\n const file = new File([blob], fileName, { type });\n resolve(file);\n },\n type,\n quality,\n );\n });\n}\n","import type React from \"react\";\nimport type { DamAsset } from \"../types\";\n\nexport function getAssetCardClassName(isSelected: boolean): string {\n return isSelected ? \"bg-blue-50 ring-2 ring-blue-500\" : \"bg-white\";\n}\n\nexport function createAssetClickHandlers(\n pendingClickTimeoutRef: React.MutableRefObject<ReturnType<\n typeof setTimeout\n > | null>,\n handleAssetClick: (\n e: React.MouseEvent,\n asset: DamAsset,\n index: number,\n ) => void,\n setPreviewAsset: (asset: DamAsset | null) => void,\n asset: DamAsset,\n index: number,\n): {\n onClick: (e: React.MouseEvent) => void;\n onDoubleClick: (e: React.MouseEvent) => void;\n} {\n const delayMs = 250;\n return {\n onClick: (e: React.MouseEvent) => {\n if (pendingClickTimeoutRef.current) {\n clearTimeout(pendingClickTimeoutRef.current);\n }\n pendingClickTimeoutRef.current = setTimeout(() => {\n handleAssetClick(e, asset, index);\n pendingClickTimeoutRef.current = null;\n }, delayMs);\n },\n onDoubleClick: (e: React.MouseEvent) => {\n e.stopPropagation();\n if (pendingClickTimeoutRef.current) {\n clearTimeout(pendingClickTimeoutRef.current);\n pendingClickTimeoutRef.current = null;\n }\n setPreviewAsset(asset);\n },\n };\n}\n","/**\n * Get the URL for a DAM asset, preferring the CDN URL if available.\n * Falls back to the API proxy URL when CDN URL is not ready.\n *\n * @param asset - The asset object with code and variant info\n * @param apiBaseUrl - Base URL for fallback API proxy (e.g. \"https://api.fluid.app/api\")\n */\nexport function getDamAssetUrl(\n asset: {\n code: string;\n default_variant_id: string | number;\n default_variant_url?: string | null;\n },\n apiBaseUrl?: string,\n): string {\n if (asset.default_variant_url) {\n return asset.default_variant_url;\n }\n const base = apiBaseUrl || \"\";\n return `${base}/dam/assets/${asset.code}/variants/${asset.default_variant_id}/content`;\n}\n","/**\n * Sanitizes a filename for safe upload by:\n * 1. Removing or replacing problematic characters\n * 2. Ensuring proper encoding for spaces and special characters\n * 3. Maintaining file extension\n */\nexport function sanitizeFilename(filename: string): string {\n if (!filename) return filename;\n\n // Split filename into name and extension\n const lastDotIndex = filename.lastIndexOf(\".\");\n const name =\n lastDotIndex > 0 ? filename.substring(0, lastDotIndex) : filename;\n const rawExtension = lastDotIndex > 0 ? filename.substring(lastDotIndex) : \"\";\n const extension = (rawExtension.split(\"?\")[0] ?? \"\").split(\"#\")[0] ?? \"\";\n\n // Clean the name part\n let sanitizedName = name\n // Replace problematic characters with underscores\n .replace(/[<>:\"/\\\\|?*]/g, \"_\")\n // Replace multiple spaces with single space\n .replace(/\\s+/g, \" \")\n // Trim whitespace\n .trim()\n // Replace spaces with underscores for better compatibility\n .replace(/\\s/g, \"_\");\n\n // If the name is empty after sanitization, use a default\n if (!sanitizedName) {\n sanitizedName = \"file\";\n }\n\n // Return the sanitized filename with extension\n return sanitizedName + extension;\n}\n\n/**\n * Extracts the base name (without extension) from a filename\n * and sanitizes it for use as an asset name\n * Server validation only allows: word characters, spaces, and hyphens\n */\nexport function getSanitizedAssetName(filename: string): string {\n if (!filename) return \"asset\";\n\n // Split filename into name and extension\n const lastDotIndex = filename.lastIndexOf(\".\");\n const name =\n lastDotIndex > 0 ? filename.substring(0, lastDotIndex) : filename;\n\n // Clean the name part for asset naming\n // Only allow word characters (letters, numbers, underscore), spaces, and hyphens\n let sanitizedName = name\n // Replace any characters that are not word characters, spaces, or hyphens with spaces\n .replace(/[^\\w\\s-]/g, \" \")\n // Replace multiple spaces with single space\n .replace(/\\s+/g, \" \")\n // Trim whitespace\n .trim();\n\n // If the name is empty after sanitization, use a default\n if (!sanitizedName) {\n sanitizedName = \"asset\";\n }\n\n return sanitizedName;\n}\n","import type React from \"react\";\nimport { useState, useEffect } from \"react\";\n\nexport const useDebouncedSearch = (\n delay: number = 300,\n): {\n searchQuery: string;\n setSearchQuery: React.Dispatch<React.SetStateAction<string>>;\n debouncedSearchQuery: string;\n} => {\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(\"\");\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedSearchQuery(searchQuery);\n }, delay);\n\n return () => clearTimeout(timer);\n }, [searchQuery, delay]);\n\n return {\n searchQuery,\n setSearchQuery,\n debouncedSearchQuery,\n };\n};\n","import { useState, useCallback, useMemo, useEffect } from \"react\";\nimport { useInfiniteQuery } from \"@tanstack/react-query\";\nimport {\n damQueryKeys,\n type DamAsset,\n type DamTree,\n type FilePickerResult,\n type DamAssetApi,\n type DamQueryResponse,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerApi } from \"../context/FilePickerApiContext\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\nimport { useDebouncedSearch } from \"./use-debounced-search\";\n\nexport type UseDamLibraryControlledSearch = {\n searchQuery: string;\n setSearchQuery: (value: string) => void;\n};\n\nconst convertApiAssetToInternal = (apiAsset: DamAssetApi): DamAsset => {\n const defaultUrl =\n (apiAsset as { default_variant_url?: string }).default_variant_url ?? \"\";\n return {\n id: apiAsset.id,\n // Fallback to `asset_code` for legacy API responses that used that field name instead of `code`\n asset_code:\n apiAsset.code ||\n (apiAsset as unknown as { asset_code: string }).asset_code,\n name: apiAsset.name,\n category: apiAsset.category,\n default_variant_url: defaultUrl || undefined,\n variants: (Array.isArray(apiAsset.variants) ? apiAsset.variants : []).map(\n (variant) => {\n const variantAny = variant as unknown as {\n metadata?: Record<string, unknown>;\n ready?: boolean;\n };\n return {\n id: String(variant.id || \"\"),\n url: variant.url || defaultUrl || \"\",\n file_name: variant.file_name || \"\",\n mime_type: variant.mime_type || \"\",\n metadata: variantAny.metadata || {},\n ready: variantAny.ready ?? variant.processing_status === \"completed\",\n tags: variant.tags || [],\n };\n },\n ),\n };\n};\n\nconst isApiDamAsset = (value: unknown): value is DamAssetApi => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (\"code\" in value || \"asset_code\" in value) &&\n \"name\" in value &&\n \"category\" in value\n );\n};\n\nconst normalizeAsset = (asset: DamAsset | DamAssetApi): DamAsset => {\n // Always run through convertApiAssetToInternal for DamAssetApi objects.\n // We can't rely on \"asset_code\" as a discriminator because legacy API\n // responses also carry that field — using \"variants\" with mapped `ready`\n // boolean is a more reliable signal that conversion already happened.\n if (\n \"asset_code\" in asset &&\n Array.isArray((asset as DamAsset).variants) &&\n (asset as DamAsset).variants.length > 0 &&\n typeof (asset as DamAsset).variants[0]?.ready === \"boolean\"\n ) {\n return asset as DamAsset;\n }\n return convertApiAssetToInternal(asset as DamAssetApi);\n};\n\nconst flattenTree = (\n tree: DamTree,\n basePath = \"\",\n depth = 0,\n): { folders: string[]; assets: DamAsset[] } => {\n if (depth > 10) return { folders: [], assets: [] };\n\n const folders: string[] = [];\n const assets: DamAsset[] = [];\n\n for (const [key, value] of Object.entries(tree)) {\n const fullPath = basePath ? `${basePath}.${key}` : key;\n\n if (isApiDamAsset(value)) {\n assets.push(convertApiAssetToInternal(value));\n } else if (typeof value === \"object\" && value !== null) {\n if (Object.keys(value ?? {})?.length === 0) continue;\n folders.push(fullPath);\n const nested = flattenTree(value as DamTree, fullPath, depth + 1);\n folders.push(...nested.folders);\n assets.push(...nested.assets);\n }\n }\n\n return { folders, assets };\n};\n\nexport const useDamLibrary = (\n fileTypeFilter?: string[],\n controlledSearch?: UseDamLibraryControlledSearch,\n): {\n currentPath: string;\n searchQuery: string;\n setSearchQuery: (value: string) => void;\n navigateToPath: (path: string) => void;\n navigateUp: () => void;\n selectAsset: (asset: DamAsset | DamAssetApi, variantId?: string) => void;\n deselectAsset: (assetCode: string) => void;\n clearSelection: () => void;\n clearAndSelectAsset: (\n asset: DamAsset | DamAssetApi,\n variantId?: string,\n ) => void;\n getSelectedResults: () => FilePickerResult[];\n getSelectionIndex: (assetCode: string) => number;\n selectedAssets: string[];\n selectedAssetsMap: Map<string, { asset: DamAsset; variantId?: string }>;\n folders: string[];\n assets: DamAsset[];\n isLoading: boolean;\n error: Error | null;\n isSearching: boolean;\n hasNextPage: boolean;\n loadMore: () => void;\n isFetching: boolean;\n} => {\n const api = useFilePickerApi();\n const { companyId } = useFilePickerContext();\n const [currentPath, setCurrentPath] = useState(\"*\");\n\n const internalSearch = useDebouncedSearch(300);\n const isControlled = controlledSearch !== undefined;\n const searchQuery = isControlled\n ? controlledSearch!.searchQuery\n : internalSearch.searchQuery;\n const setSearchQuery = isControlled\n ? controlledSearch!.setSearchQuery\n : internalSearch.setSearchQuery;\n\n const [controlledDebounced, setControlledDebounced] = useState(\n controlledSearch?.searchQuery ?? \"\",\n );\n useEffect(() => {\n if (!isControlled) return;\n const timer = setTimeout(() => setControlledDebounced(searchQuery), 300);\n return () => clearTimeout(timer);\n }, [isControlled, searchQuery]);\n\n const debouncedSearchQuery = isControlled\n ? controlledDebounced\n : internalSearch.debouncedSearchQuery;\n\n const [selectedAssets, setSelectedAssets] = useState<\n Map<string, { asset: DamAsset; variantId?: string }>\n >(new Map());\n\n const canonicalPathFilters = useMemo(() => {\n if (!fileTypeFilter || !companyId) return fileTypeFilter;\n return fileTypeFilter.map((filter) =>\n filter.includes(\".\") ? filter : `${companyId}.${filter}.*`,\n );\n }, [fileTypeFilter, companyId]);\n\n const ltreeQueryPath = useMemo(() => {\n if (!canonicalPathFilters?.length) return currentPath;\n if (canonicalPathFilters?.length === 1) return canonicalPathFilters[0];\n if (!companyId) return currentPath;\n\n const categories = canonicalPathFilters\n .map((path) => path.split(\".\")[1])\n .filter(Boolean);\n\n return categories?.length\n ? `${companyId}.${categories.join(\"|\")}.*`\n : currentPath;\n }, [canonicalPathFilters, currentPath, companyId]);\n\n const {\n data,\n isLoading,\n error,\n isFetching,\n fetchNextPage,\n hasNextPage,\n isFetchingNextPage,\n } = useInfiniteQuery({\n queryKey: damQueryKeys.query({\n path: ltreeQueryPath,\n search: debouncedSearchQuery,\n filters: canonicalPathFilters,\n }),\n queryFn: ({ pageParam }) =>\n api.queryDamAssets({\n path: ltreeQueryPath || \"*\",\n search: debouncedSearchQuery,\n tags_string: \"*\",\n exclude_tags: \"file_resource\",\n exclude_categories: \"text,other\",\n cursor: pageParam as string | undefined,\n }),\n getNextPageParam: (lastPage) =>\n (lastPage as DamQueryResponse)?.meta?.next_cursor || undefined,\n initialPageParam: undefined as string | undefined,\n refetchOnWindowFocus: false,\n });\n\n const navigateUp = useCallback(() => {\n if (currentPath === \"*\") return;\n\n const pathParts = currentPath.split(\".\");\n if (pathParts?.length <= 1) {\n setCurrentPath(\"*\");\n return;\n }\n if (pathParts?.[pathParts?.length - 1] === \"*\") {\n const parentParts = pathParts.slice(0, -2);\n if (parentParts?.length === 0) {\n setCurrentPath(\"*\");\n } else {\n setCurrentPath(parentParts.join(\".\") + \".*\");\n }\n } else {\n const parentParts = pathParts.slice(0, -1);\n setCurrentPath(parentParts.join(\".\") + \".*\");\n }\n }, [currentPath]);\n\n const selectAsset = useCallback(\n (asset: DamAsset | DamAssetApi, variantId?: string) => {\n const normalized = normalizeAsset(asset);\n setSelectedAssets((prev) => {\n const next = new Map(prev);\n next.set(normalized.asset_code, { asset: normalized, variantId });\n return next;\n });\n },\n [],\n );\n\n const deselectAsset = useCallback((assetCode: string) => {\n setSelectedAssets((prev) => {\n if (!prev.has(assetCode)) return prev;\n const next = new Map(prev);\n next.delete(assetCode);\n return next;\n });\n }, []);\n\n const clearSelection = useCallback(() => {\n setSelectedAssets(new Map());\n }, []);\n\n const clearAndSelectAsset = useCallback(\n (asset: DamAsset | DamAssetApi, variantId?: string) => {\n const normalized = normalizeAsset(asset);\n setSelectedAssets(\n new Map([[normalized.asset_code, { asset: normalized, variantId }]]),\n );\n },\n [],\n );\n\n const getSelectedResults = useCallback((): FilePickerResult[] => {\n return Array.from(selectedAssets.values()).map(({ asset, variantId }) => {\n const variant = variantId\n ? asset.variants.find((v) => v.id === variantId)\n : asset.variants.find((v) => v.ready) || asset.variants[0];\n const defaultVariantUrl = asset.default_variant_url ?? \"\";\n const fileUrl = variant?.url || defaultVariantUrl || \"\";\n\n const metadata = variant?.metadata || {};\n const dimensions =\n typeof metadata.width === \"number\" &&\n typeof metadata.height === \"number\"\n ? { width: metadata.width, height: metadata.height }\n : undefined;\n\n return {\n asset_id: asset.id,\n asset_code: asset.asset_code,\n file_path: fileUrl,\n file_url: fileUrl,\n metadata: {\n file_name: variant?.file_name || asset.name,\n mime_type: variant?.mime_type || \"\",\n dimensions,\n },\n upload_status: \"ready\",\n variant_id: variant?.id || undefined,\n };\n });\n }, [selectedAssets]);\n\n const getSelectionIndex = useCallback(\n (assetCode: string): number => {\n const keys = Array.from(selectedAssets.keys());\n const index = keys.indexOf(assetCode);\n return index === -1 ? -1 : index + 1;\n },\n [selectedAssets],\n );\n\n const selectedAssetCodes = useMemo(\n () => Array.from(selectedAssets.keys()),\n [selectedAssets],\n );\n\n const getCompanyTree = useCallback(\n (tree: DamTree): DamTree => {\n const companyIdStr = companyId?.toString();\n return companyIdStr && tree[companyIdStr]\n ? { [companyIdStr]: tree[companyIdStr] }\n : tree;\n },\n [companyId],\n );\n\n const { folders, allAssets } = useMemo(() => {\n if (!data?.pages?.length) {\n return { folders: [], allAssets: [] };\n }\n\n const companyIdStr = companyId?.toString();\n const excluded: string[] = companyIdStr ? [companyIdStr] : [];\n if (fileTypeFilter?.length && companyIdStr) {\n fileTypeFilter.forEach((filter) => {\n if (!filter.includes(\".\")) {\n excluded.push(`${companyIdStr}.${filter}`);\n }\n });\n }\n\n const folderSet = new Set<string>();\n const assetMap = new Map<string, DamAsset>();\n for (const page of data.pages) {\n const response = page as DamQueryResponse;\n const flat = flattenTree(getCompanyTree(response.tree));\n for (const folder of flat.folders) {\n if (!excluded.includes(folder)) {\n folderSet.add(folder);\n }\n }\n for (const asset of flat.assets) {\n assetMap.set(asset.asset_code, asset);\n }\n }\n\n return {\n folders: Array.from(folderSet),\n allAssets: Array.from(assetMap.values()),\n };\n }, [data, getCompanyTree, companyId, fileTypeFilter]);\n\n return {\n currentPath,\n searchQuery,\n setSearchQuery,\n navigateToPath: setCurrentPath,\n navigateUp,\n selectAsset,\n deselectAsset,\n clearSelection,\n clearAndSelectAsset,\n getSelectedResults,\n getSelectionIndex,\n selectedAssets: selectedAssetCodes,\n selectedAssetsMap: selectedAssets,\n folders: folders ?? [],\n assets: allAssets ?? [],\n isLoading,\n error,\n isSearching: searchQuery !== debouncedSearchQuery,\n hasNextPage: Boolean(hasNextPage),\n loadMore: fetchNextPage,\n isFetching: isFetching || isFetchingNextPage,\n };\n};\n","import type React from \"react\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport * as z from \"zod\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n Button,\n} from \"@fluid-app/ui-primitives\";\n\nexport const folderSchema: z.ZodObject<{\n folderName: z.ZodString;\n}> = z.object({\n folderName: z\n .string()\n .min(1, \"Folder name is required\")\n .min(3, \"Folder name must be at least 3 characters\")\n .max(50, \"Folder name must be at most 50 characters\")\n .regex(\n /^[a-zA-Z0-9_]+$/,\n \"Folder name may only contain letters, numbers, and underscores\",\n ),\n});\n\ntype FolderFormValues = z.infer<typeof folderSchema>;\n\ninterface AddFolderModalProps {\n open: boolean;\n setOpen(b: boolean): void;\n onSubmit(v: FolderFormValues): void;\n form: UseFormReturn<FolderFormValues>;\n isLoading?: boolean;\n}\n\nexport function AddFolderModal({\n open,\n setOpen,\n onSubmit,\n form,\n isLoading,\n}: AddFolderModalProps): React.JSX.Element {\n const handleClose = () => {\n setOpen(false);\n form.reset();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleClose} modal>\n <DialogContent title=\"Add Folder\" className=\"z-[300] sm:max-w-[425px]\">\n <DialogHeader>\n <DialogTitle>Add Folder</DialogTitle>\n <DialogDescription>\n Create a new folder by entering a name below.\n </DialogDescription>\n </DialogHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"folderName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>Folder Name</FormLabel>\n <FormControl>\n <Input\n placeholder=\"Enter folder name\"\n {...field}\n disabled={isLoading}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button variant=\"default\" type=\"submit\" disabled={isLoading}>\n {isLoading ? \"Creating...\" : \"Add Folder\"}\n </Button>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n}\n","import type React from \"react\";\nimport {\n cn,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n Button,\n} from \"@fluid-app/ui-primitives\";\nimport { XIcon, Trash2Icon, AlertTriangleIcon } from \"lucide-react\";\nimport type { LucideIcon } from \"lucide-react\";\n\ntype AssetActionsProps = {\n onDiscard(): void;\n onDelete(): void;\n};\n\ntype HoverIconProps = {\n label: string;\n icon: LucideIcon;\n onClick(): void;\n className?: string;\n};\n\nconst HoverIcon = ({\n icon: Icon,\n label,\n onClick,\n className,\n}: HoverIconProps) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n \"mr-0.5 rounded-md border border-gray-300 bg-white p-2 text-gray-600 transition-colors hover:bg-gray-50 hover:text-gray-900\",\n className,\n )}\n onClick={(e) => {\n e.stopPropagation();\n e.preventDefault();\n onClick();\n }}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n <p>{label}</p>\n </TooltipContent>\n </Tooltip>\n );\n};\n\nexport function AssetActions({\n onDiscard,\n onDelete,\n}: AssetActionsProps): React.JSX.Element {\n return (\n <div className={\"absolute top-1 right-0.5 z-1 hidden group-hover:flex\"}>\n <TooltipProvider>\n <HoverIcon label=\"Discard\" icon={XIcon} onClick={onDiscard} />\n\n <HoverIcon\n label=\"Delete\"\n icon={Trash2Icon}\n onClick={onDelete}\n className=\"border-red-300 text-red-600 hover:bg-red-50 hover:text-red-700\"\n />\n </TooltipProvider>\n </div>\n );\n}\n\ntype ActionModalProps = {\n open: boolean;\n title: string;\n description: string;\n cancelLabel?: string;\n actionLabel?: string;\n onCancel?(): void;\n onAction(): void;\n actionVariant?:\n | \"default\"\n | \"destructive\"\n | \"outline\"\n | \"secondary\"\n | \"ghost\"\n | \"link\";\n loading?: boolean;\n};\n\nexport function ActionModal({\n title,\n description,\n actionLabel = \"Delete\",\n cancelLabel = \"Cancel\",\n open,\n onAction,\n onCancel,\n actionVariant = \"destructive\",\n loading,\n}: ActionModalProps): React.JSX.Element {\n return (\n <Dialog open={open} onOpenChange={onCancel}>\n <DialogContent className=\"z-[400] flex flex-col gap-5\">\n <DialogHeader className=\"flex-shrink-0\">\n <DialogTitle className=\"flex items-center gap-2\">\n <AlertTriangleIcon className=\"h-5 w-5 text-blue-600\" />\n {title}\n </DialogTitle>\n </DialogHeader>\n <div className=\"sm:flex sm:items-start\">\n <div className=\"mt-2\">\n <p className=\"text-sm text-gray-500\">{description}</p>\n </div>\n </div>\n\n <div className=\"mt-5 flex w-full justify-end gap-3 sm:mt-4\">\n <Button\n type=\"button\"\n data-autofocus\n onClick={onCancel}\n variant=\"secondary\"\n disabled={loading}\n className=\"cursor-pointer\"\n >\n {cancelLabel}\n </Button>\n <Button\n disabled={loading}\n type=\"button\"\n onClick={onAction}\n variant={actionVariant}\n className=\"cursor-pointer\"\n >\n {actionLabel}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n","import type { LucideIcon } from \"lucide-react\";\nimport { ImageIcon, VideoIcon, FileIcon } from \"lucide-react\";\n\nexport function getCategoryIcon(category: string): LucideIcon {\n switch (category) {\n case \"images\":\n return ImageIcon;\n case \"videos\":\n return VideoIcon;\n default:\n return FileIcon;\n }\n}\n","\"use client\";\n\nimport React, { useState, useRef, useEffect } from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport type { DamAsset, DamVariant } from \"@fluid-app/file-picker-core\";\nimport { getCategoryIcon } from \"../../utils/icons\";\n\nfunction formatDuration(seconds: number): string {\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = Math.floor(seconds % 60);\n if (h > 0)\n return `${h}:${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}`;\n return `${m}:${String(s).padStart(2, \"0\")}`;\n}\n\nfunction VideoDurationBadge({ src }: { src: string }) {\n const [duration, setDuration] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n\n useEffect(() => {\n const video = document.createElement(\"video\");\n video.preload = \"metadata\";\n video.src = src;\n video.onloadedmetadata = () => {\n if (video.duration && isFinite(video.duration)) {\n setDuration(formatDuration(video.duration));\n }\n };\n videoRef.current = video;\n return () => {\n video.onloadedmetadata = null;\n video.src = \"\";\n };\n }, [src]);\n\n if (!duration) return null;\n\n return (\n <span className=\"absolute right-1.5 bottom-1.5 rounded bg-black/70 px-1.5 py-0.5 text-[10px] font-medium text-white\">\n {duration}\n </span>\n );\n}\n\nexport type ThumbnailLayout = \"list\" | \"grid\" | \"preview\";\n\nexport interface AssetThumbnailProps {\n asset: DamAsset;\n variant: DamVariant | undefined;\n layout: ThumbnailLayout;\n imageSize?: number;\n className?: string;\n}\n\nexport function AssetThumbnail({\n asset,\n variant,\n layout,\n imageSize = 100,\n className,\n}: AssetThumbnailProps): React.ReactElement {\n const IconComponent = getCategoryIcon(asset.category);\n\n if (layout === \"list\") {\n return (\n <div\n className={cn(\n \"relative h-12 w-12 shrink-0 overflow-hidden rounded bg-gray-100\",\n className,\n )}\n >\n {variant?.url && asset.category === \"images\" ? (\n <img\n src={variant.url}\n alt={asset.name}\n width={48}\n height={48}\n className=\"h-full w-full object-cover\"\n />\n ) : variant?.url && asset.category === \"videos\" ? (\n <img\n src={`${variant.url.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={variant.url || \"Video\"}\n width={48}\n height={48}\n className=\"h-full w-full object-cover\"\n />\n ) : variant?.url && asset.category === \"documents\" ? (\n <img\n src={`${variant.url.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={asset.name || \"Document\"}\n width={48}\n height={48}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center\">\n <IconComponent className=\"h-5 w-5 text-gray-400\" />\n </div>\n )}\n </div>\n );\n }\n\n if (layout === \"preview\") {\n return (\n <div\n className={cn(\n \"relative aspect-video w-full overflow-hidden bg-gray-100\",\n className,\n )}\n >\n {variant?.url && asset.category === \"images\" ? (\n <img\n src={variant.url}\n alt={asset.name}\n width={960}\n height={540}\n className=\"h-full w-full object-contain\"\n />\n ) : variant?.url && asset.category === \"videos\" ? (\n <video\n src={variant.url}\n autoPlay\n muted\n controls\n className=\"h-full w-full object-contain\"\n />\n ) : variant?.url && asset.category === \"documents\" ? (\n <img\n src={`${variant.url.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={asset.name}\n width={960}\n height={540}\n className=\"h-full w-full object-contain\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center\">\n <IconComponent className=\"h-16 w-16 text-gray-400\" />\n </div>\n )}\n </div>\n );\n }\n\n // grid\n return (\n <div\n className={cn(\n \"relative aspect-square overflow-hidden rounded-t-lg bg-gray-100\",\n className,\n )}\n >\n {variant?.url && asset.category === \"images\" ? (\n <img\n src={variant.url}\n alt={asset.name}\n width={imageSize}\n height={imageSize}\n className=\"h-full w-full object-contain\"\n />\n ) : variant?.url && asset.category === \"videos\" ? (\n <>\n <img\n src={`${variant.url.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={asset.name}\n width={imageSize}\n height={imageSize}\n className=\"h-full w-full object-contain\"\n />\n <VideoDurationBadge src={variant.url} />\n </>\n ) : variant?.url && asset.category === \"documents\" ? (\n <img\n src={`${variant.url.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={asset.name}\n width={imageSize}\n height={imageSize}\n className=\"h-full w-full object-contain\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center\">\n <IconComponent className=\"h-6 w-6 text-gray-400\" />\n </div>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\n\nexport interface SelectionIndexBadgeProps {\n index: number;\n className?: string;\n}\n\nexport function SelectionIndexBadge({\n index,\n className,\n}: SelectionIndexBadgeProps): React.ReactElement {\n const baseClasses =\n \"flex items-center justify-center rounded-full bg-blue-600 text-xs font-medium text-white shadow-sm z-10\";\n return (\n <div\n className={cn(\"absolute top-2 left-2 h-5 w-5\", baseClasses, className)}\n >\n {index}\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { EllipsisVerticalIcon, XIcon, Trash2Icon } from \"lucide-react\";\n\nimport {\n cn,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport type { DamAsset } from \"@fluid-app/file-picker-core\";\n\nexport type ActionsMenuPosition = \"list\" | \"grid\";\n\nexport interface AssetActionsMenuProps {\n asset: DamAsset;\n position: ActionsMenuPosition;\n onDiscard: () => void;\n onDelete: () => void;\n}\n\nexport function AssetActionsMenu({\n position,\n onDiscard,\n onDelete,\n}: AssetActionsMenuProps): React.ReactElement {\n const wrapperClassName =\n position === \"list\"\n ? \"absolute top-1/2 right-2 z-10 hidden -translate-y-1/2 group-hover:block has-data-[state=open]:block\"\n : \"absolute top-2 right-2 z-10 hidden group-hover:block has-data-[state=open]:block\";\n\n return (\n <div\n className={cn(wrapperClassName)}\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n >\n <DropdownMenu>\n <DropdownMenuTrigger className=\"flex h-7 w-7 items-center justify-center rounded-md border border-gray-200 bg-white text-gray-500 shadow-sm transition-colors hover:bg-gray-50 hover:text-gray-700\">\n <EllipsisVerticalIcon className=\"h-3.5 w-3.5\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"z-301\">\n <DropdownMenuItem onClick={onDiscard}>\n <XIcon className=\"h-3.5 w-3.5\" />\n Discard\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={onDelete}\n className=\"text-red-600 focus:text-red-700\"\n >\n <Trash2Icon className=\"h-3.5 w-3.5\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\nimport { getAssetCardClassName } from \"@fluid-app/file-picker-core\";\nimport { SelectionIndexBadge } from \"./DamLibraryAsset\";\n\nexport type LibraryAssetViewMode = \"grid\" | \"list\";\n\n/**\n * Normalized item for the shared library/media grid.\n * Consumers map DAM assets or media items to this shape and provide renderThumbnail.\n */\nexport interface LibraryAssetItem<T = unknown> {\n id: string;\n name: string;\n subtitle?: string;\n isSelected: boolean;\n /** 0 = not selected, 1-based when selected (for badge) */\n selectionIndex: number;\n raw: T;\n}\n\nexport interface LibraryAssetGridProps<T> {\n items: LibraryAssetItem<T>[];\n viewMode: LibraryAssetViewMode;\n thumbnailSize: number;\n showNamesOnMedia: boolean;\n renderThumbnail: (item: T, layout: LibraryAssetViewMode) => React.ReactNode;\n onClick: (e: React.MouseEvent, id: string, index: number) => void;\n onDoubleClick?: (e: React.MouseEvent, id: string, index: number) => void;\n renderTopLeftOverlay?: (item: LibraryAssetItem<T>) => React.ReactNode;\n renderTopRightOverlay?: (item: LibraryAssetItem<T>) => React.ReactNode;\n wrapItem?: (\n item: LibraryAssetItem<T>,\n content: React.ReactNode,\n ) => React.ReactNode;\n}\n\nfunction getGridClasses(\n viewMode: LibraryAssetViewMode,\n thumbnailSize: number,\n): string {\n if (viewMode === \"list\") {\n return \"grid-cols-1\";\n }\n if (thumbnailSize <= 35) {\n return \"grid-cols-4 sm:grid-cols-6 md:grid-cols-8 lg:grid-cols-12 xl:grid-cols-16\";\n }\n if (thumbnailSize <= 50) {\n return \"grid-cols-3 sm:grid-cols-5 md:grid-cols-7 lg:grid-cols-10 xl:grid-cols-14\";\n }\n if (thumbnailSize <= 70) {\n return \"grid-cols-3 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8\";\n }\n if (thumbnailSize <= 90) {\n return \"grid-cols-2 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-7\";\n }\n if (thumbnailSize <= 110) {\n return \"grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6\";\n }\n if (thumbnailSize <= 130) {\n return \"grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5\";\n }\n return \"grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4\";\n}\n\nexport function LibraryAssetGrid<T>({\n items,\n viewMode,\n thumbnailSize,\n showNamesOnMedia,\n renderThumbnail,\n onClick,\n onDoubleClick,\n renderTopLeftOverlay,\n renderTopRightOverlay,\n wrapItem,\n}: LibraryAssetGridProps<T>): React.ReactElement {\n const gridClasses = getGridClasses(viewMode, thumbnailSize);\n\n const renderCard = (item: LibraryAssetItem<T>, index: number) => {\n const handleClick = (e: React.MouseEvent) => {\n e.preventDefault();\n onClick(e, item.id, index);\n };\n const handleDoubleClick = onDoubleClick\n ? (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onDoubleClick(e, item.id, index);\n }\n : undefined;\n\n const content = (\n <>\n {renderTopRightOverlay?.(item)}\n {viewMode === \"list\" ? (\n <div className=\"flex items-start gap-4\">\n <div className=\"h-12 w-12 shrink-0 overflow-hidden rounded bg-gray-100\">\n {renderThumbnail(item.raw, \"list\")}\n </div>\n <div className=\"min-w-0 flex-1 text-start\">\n <p className=\"truncate text-sm font-medium text-gray-900\">\n {item.name}\n </p>\n {item.subtitle != null && item.subtitle !== \"\" && (\n <p className=\"truncate text-xs text-gray-500\">\n {item.subtitle}\n </p>\n )}\n </div>\n </div>\n ) : (\n <>\n <div className=\"relative aspect-square overflow-hidden rounded-t-lg bg-gray-100 p-2\">\n {renderThumbnail(item.raw, \"grid\")}\n </div>\n {showNamesOnMedia && (\n <div className=\"bg-gray-100 px-2 py-1.5\">\n <p className=\"truncate text-xs font-medium text-gray-900\">\n {item.name}\n </p>\n {item.subtitle && (\n <p className=\"truncate text-[10px] text-gray-500\">\n {item.subtitle}\n </p>\n )}\n </div>\n )}\n </>\n )}\n {item.isSelected && item.selectionIndex > 0 && (\n <SelectionIndexBadge index={item.selectionIndex} />\n )}\n {renderTopLeftOverlay?.(item)}\n </>\n );\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n className={cn(\n \"group relative cursor-pointer overflow-hidden rounded-lg transition-all\",\n getAssetCardClassName(item.isSelected),\n viewMode === \"list\" && \"flex items-start gap-4 p-3\",\n )}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick(e as unknown as React.MouseEvent, item.id, index);\n }\n }}\n >\n {content}\n </div>\n );\n };\n\n return (\n <div className={cn(\"grid gap-4\", gridClasses)}>\n {items.map((item, index) => {\n const card = renderCard(item, index);\n const wrapped = wrapItem ? wrapItem(item, card) : card;\n return <React.Fragment key={item.id}>{wrapped}</React.Fragment>;\n })}\n </div>\n );\n}\n","import React, {\n useState,\n useEffect,\n useCallback,\n useImperativeHandle,\n forwardRef,\n useRef,\n useMemo,\n} from \"react\";\nimport {\n Button,\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n cn,\n Dialog,\n DialogOverlay,\n DialogPortal,\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n useZodForm,\n} from \"@fluid-app/ui-primitives\";\nimport { FolderIcon, LoaderIcon, ChevronDownIcon } from \"lucide-react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport {\n damQueryKeys,\n SORT_OPTIONS,\n createAssetClickHandlers,\n type CreateDamAssetPathForAssetsParams,\n type FilePickerConfig,\n type FilePickerResult,\n type DamAsset,\n type DamAssetApi,\n type SortOptionId,\n} from \"@fluid-app/file-picker-core\";\nimport { useDamLibrary } from \"../hooks/use-dam-library\";\nimport type { UseDamLibraryControlledSearch } from \"../hooks/use-dam-library\";\nimport { useFilePickerApi } from \"../context/FilePickerApiContext\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\nimport { AddFolderModal, folderSchema } from \"./AddFolderModal\";\nimport { ActionModal } from \"./AssetActions\";\nimport type { ViewMode } from \"./FilePickerHeader\";\nimport { AssetThumbnail, AssetActionsMenu } from \"./DamLibraryAsset\";\nimport {\n LibraryAssetGrid,\n type LibraryAssetItem,\n type LibraryAssetViewMode,\n} from \"./LibraryAssetGrid\";\n\ninterface DamLibraryProps {\n config: FilePickerConfig;\n onAssetsSelected: (results: FilePickerResult[]) => void;\n onSelectionChange?: (\n count: number,\n files?: FilePickerResult[],\n variantCounts?: Record<string, number>,\n ) => void;\n onConfirmAndClose?: (results: FilePickerResult[]) => void;\n onSearchingChange?: (searching: boolean) => void;\n showVariants?: boolean;\n searchQuery?: string;\n onSearchChange?: (value: string) => void;\n thumbnailSize?: number;\n viewMode?: ViewMode;\n showNamesOnMedia?: boolean;\n sortOption?: SortOptionId;\n onFoldersChange?: (folders: string[]) => void;\n previewContainer?: HTMLDivElement | null;\n previewAsset?: DamAsset | null;\n onPreviewAssetChange?: (asset: DamAsset | null) => void;\n}\n\nexport interface DamLibraryRef {\n clearSelection: () => void;\n confirmSelection: () => void;\n confirmAndClose: () => void;\n getSelectedResults: () => FilePickerResult[];\n deselectAssetByCode: (assetCode: string) => void;\n selectAssetsByCodes: (assetCodes: string[]) => string[];\n addAssetToSelection: (asset: DamAsset | DamAssetApi) => void;\n openAddFolderModal: () => void;\n addToExistingFolder: (folderPath: string) => void;\n getVariantCount: (assetCode: string) => number;\n getAssetWithVariants: (assetCode: string) => DamAsset | null;\n setVariantForAsset: (assetCode: string, variantId: string) => void;\n}\n\ntype ActionType = {\n type: \"Discard\" | \"Delete\";\n item: DamAsset;\n};\n\ntype DamBreadcrumbItem = { label: string; path: string; isCurrent: boolean };\n\nfunction getBreadcrumbsFromPath(currentPath: string): DamBreadcrumbItem[] {\n if (currentPath === \"*\") {\n return [{ label: \"All assets\", path: \"*\", isCurrent: true }];\n }\n const normalized = currentPath.endsWith(\".*\")\n ? currentPath.slice(0, -3)\n : currentPath;\n const segments = normalized.split(\".\").filter((s): s is string => Boolean(s));\n if (segments.length === 0) {\n return [{ label: \"All assets\", path: \"*\", isCurrent: true }];\n }\n const crumbs: DamBreadcrumbItem[] = [\n { label: \"All assets\", path: \"*\", isCurrent: false },\n ];\n let pathAcc = \"\";\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i] as string;\n pathAcc = pathAcc ? `${pathAcc}.${segment}` : segment;\n crumbs.push({\n label: segment,\n path: `${pathAcc}.*`,\n isCurrent: i === segments.length - 1,\n });\n }\n return crumbs;\n}\n\nexport const DamLibrary: React.ForwardRefExoticComponent<\n DamLibraryProps & React.RefAttributes<DamLibraryRef>\n> = forwardRef<DamLibraryRef, DamLibraryProps>(\n (\n {\n config,\n onAssetsSelected,\n onSelectionChange,\n onConfirmAndClose,\n onSearchingChange,\n showVariants: _showVariants = false,\n searchQuery: controlledSearchQuery,\n onSearchChange: controlledSetSearchQuery,\n thumbnailSize = 100,\n viewMode = \"grid\",\n showNamesOnMedia = true,\n sortOption,\n onFoldersChange,\n previewContainer,\n previewAsset,\n onPreviewAssetChange,\n },\n ref,\n ) => {\n \"use no memo\";\n\n const api = useFilePickerApi();\n const { companyId, toast } = useFilePickerContext();\n const queryClient = useQueryClient();\n\n const controlledSearch: UseDamLibraryControlledSearch | undefined =\n controlledSearchQuery !== undefined && controlledSetSearchQuery\n ? {\n searchQuery: controlledSearchQuery,\n setSearchQuery: controlledSetSearchQuery,\n }\n : undefined;\n\n const {\n currentPath,\n navigateToPath,\n selectAsset,\n deselectAsset,\n clearSelection,\n clearAndSelectAsset,\n getSelectedResults,\n getSelectionIndex,\n selectedAssets,\n selectedAssetsMap,\n folders,\n assets,\n isLoading,\n isSearching,\n hasNextPage,\n loadMore,\n isFetching,\n } = useDamLibrary(config.fileTypeFilter, controlledSearch);\n\n const breadcrumbs = useMemo(\n () => getBreadcrumbsFromPath(currentPath),\n [currentPath],\n );\n\n const sortedAssets = useMemo(() => {\n if (!sortOption || !assets?.length) return assets ?? [];\n const option = SORT_OPTIONS.find((o) => o.id === sortOption);\n if (!option) return assets ?? [];\n\n return [...(assets ?? [])].sort((a, b) => {\n if (option.sortBy === \"name\") {\n const cmp = (a.name ?? \"\").localeCompare(b.name ?? \"\", undefined, {\n sensitivity: \"base\",\n });\n return option.sortDirection === \"asc\" ? cmp : -cmp;\n }\n if (option.sortBy === \"created_at\") {\n const aId = a.id ?? 0;\n const bId = b.id ?? 0;\n const cmp = aId - bId;\n return option.sortDirection === \"asc\" ? cmp : -cmp;\n }\n return 0;\n });\n }, [assets, sortOption]);\n\n useEffect(() => {\n onSearchingChange?.(isSearching);\n }, [isSearching, onSearchingChange]);\n\n useEffect(() => {\n onFoldersChange?.(folders ?? []);\n }, [folders, onFoldersChange]);\n\n const [open, setOpen] = useState(false);\n\n const form = useZodForm(folderSchema, {\n defaultValues: {\n folderName: \"\",\n },\n });\n\n const { mutate, isPending } = useMutation({\n mutationFn: (data: CreateDamAssetPathForAssetsParams[]) => {\n const promises = data.map((params) =>\n api.createDamAssetPathForAssets(params),\n );\n return Promise.all(promises);\n },\n onSuccess: () => {\n toast.success(\"Assets moved to folder successfully\");\n queryClient.invalidateQueries({ queryKey: damQueryKeys.all });\n form.reset();\n setOpen(false);\n clearSelection();\n },\n onError: () => {\n toast.error(\"Failed to move assets to folder.\");\n },\n });\n\n const [action, setAction] = useState<ActionType | null>(null);\n const lastClickedIndexRef = useRef<number>(-1);\n const pendingClickTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(\n null,\n );\n\n const { mutate: deleteAssetMutate, isPending: isDeleting } = useMutation({\n mutationFn: (assetCode: string) => api.deleteDamAsset(assetCode),\n onSuccess: () => {\n toast.success(\"Asset deleted successfully\");\n queryClient.invalidateQueries({ queryKey: damQueryKeys.all });\n },\n onError: () => {\n toast.error(\"Failed to delete asset.\");\n },\n });\n\n const { mutate: discardAssetMutate, isPending: isDiscarding } = useMutation(\n {\n mutationFn: (assetCode: string) => api.discardDamAsset(assetCode),\n onSuccess: () => {\n toast.success(\"Asset discarded successfully\");\n queryClient.invalidateQueries({ queryKey: damQueryKeys.all });\n },\n onError: () => {\n toast.error(\"Failed to discard asset.\");\n },\n },\n );\n\n const getAssetBaseName = (fileName: string): string => {\n const dotIdx = fileName.lastIndexOf(\".\");\n const rawName = dotIdx > 0 ? fileName.substring(0, dotIdx) : fileName;\n return rawName.replace(/[^a-zA-Z0-9_]/g, \"_\") || \"file\";\n };\n\n const handleNewFolder = useCallback(\n (data: { folderName: string }) => {\n if (!companyId) {\n toast.error(\"Company ID is required to create folders\");\n return;\n }\n const promises = getSelectedResults().map((item) => {\n const basePath = companyId.toString() + \".\";\n const name = getAssetBaseName(item.metadata.file_name);\n\n return {\n code: item.asset_code,\n asset_paths: [`${basePath}${data.folderName}.${name}`],\n };\n });\n\n mutate(promises);\n },\n [getSelectedResults, companyId, mutate, toast],\n );\n\n const handleAddToExistingFolder = useCallback(\n (folderPath: string) => {\n const promises = getSelectedResults().map((item) => {\n const name = getAssetBaseName(item.metadata.file_name);\n\n return {\n code: item.asset_code,\n asset_paths: [`${folderPath}.${name}`],\n };\n });\n\n mutate(promises);\n },\n [getSelectedResults, mutate],\n );\n\n // Expose methods to parent component\n useImperativeHandle(\n ref,\n () => ({\n clearSelection: () => {\n clearSelection();\n },\n confirmSelection: () => {\n const results = getSelectedResults();\n onAssetsSelected(results);\n },\n confirmAndClose: () => {\n const results = getSelectedResults();\n if (onConfirmAndClose) {\n onConfirmAndClose(results);\n } else {\n onAssetsSelected(results);\n }\n },\n getSelectedResults: () => {\n return getSelectedResults();\n },\n deselectAssetByCode: (assetCode: string) => {\n deselectAsset(assetCode);\n },\n addAssetToSelection: (asset: DamAsset | DamAssetApi) => {\n selectAsset(asset);\n },\n selectAssetsByCodes: (assetCodes: string[]): string[] => {\n const setToSelect = new Set(assetCodes);\n const selected: string[] = [];\n for (const asset of sortedAssets || []) {\n if (setToSelect.has(asset.asset_code)) {\n selectAsset(asset);\n selected.push(asset.asset_code);\n }\n }\n return selected;\n },\n openAddFolderModal: () => {\n setOpen(true);\n },\n addToExistingFolder: (folderPath: string) => {\n handleAddToExistingFolder(folderPath);\n },\n getVariantCount: (assetCode: string) => {\n const entry = selectedAssetsMap.get(assetCode);\n return entry?.asset?.variants?.length ?? 0;\n },\n getAssetWithVariants: (assetCode: string) => {\n const entry = selectedAssetsMap.get(assetCode);\n return entry?.asset ?? null;\n },\n setVariantForAsset: (assetCode: string, variantId: string) => {\n const entry = selectedAssetsMap.get(assetCode);\n const asset = entry?.asset;\n if (asset) {\n if (config.maxFiles === 1) {\n clearAndSelectAsset(asset, variantId);\n } else {\n selectAsset(asset, variantId);\n }\n }\n },\n }),\n [\n clearSelection,\n getSelectedResults,\n onAssetsSelected,\n onConfirmAndClose,\n sortedAssets,\n deselectAsset,\n selectAsset,\n clearAndSelectAsset,\n handleAddToExistingFolder,\n selectedAssetsMap,\n config.maxFiles,\n ],\n );\n\n // Keep a stable ref to onSelectionChange to avoid re-running the effect\n // when the parent passes an unstable callback reference.\n const onSelectionChangeRef = useRef(onSelectionChange);\n onSelectionChangeRef.current = onSelectionChange;\n\n // Notify parent when selection count changes (include variant counts so parent can enable \"Change variant\" without reading ref during render)\n useEffect(() => {\n const count = (selectedAssets ?? []).length;\n const files = getSelectedResults();\n const variantCounts: Record<string, number> = {};\n selectedAssetsMap.forEach((entry, assetCode) => {\n const n = entry?.asset?.variants?.length ?? 0;\n if (n > 0) variantCounts[assetCode] = n;\n });\n onSelectionChangeRef.current?.(count, files, variantCounts);\n }, [selectedAssets, getSelectedResults, selectedAssetsMap]);\n\n const handleAssetClick = (\n e: React.MouseEvent,\n asset: DamAsset,\n index: number,\n ) => {\n const originalVariant =\n asset.variants.find((v) => v.ready) || asset.variants[0];\n\n if (e.shiftKey && config.maxFiles !== 1) {\n // Range select: from last clicked to current index\n const last = lastClickedIndexRef.current;\n const from = last >= 0 ? Math.min(last, index) : index;\n const to = last >= 0 ? Math.max(last, index) : index;\n const toSelect = sortedAssets?.slice(from, to + 1) ?? [];\n const maxToAdd = config.maxFiles\n ? Math.max(0, config.maxFiles - selectedAssets.length)\n : toSelect.length;\n let added = 0;\n toSelect.forEach((a: DamAsset) => {\n if (selectedAssets.includes(a.asset_code)) return;\n if (added >= maxToAdd) return;\n const v =\n a.variants.find((v: DamAsset[\"variants\"][number]) => v.ready) ||\n a.variants[0];\n selectAsset(a, v?.id);\n added += 1;\n });\n lastClickedIndexRef.current = index;\n return;\n }\n\n if ((e.metaKey || e.ctrlKey) && config.maxFiles !== 1) {\n // Toggle selection (add only if under maxFiles)\n if (selectedAssets.includes(asset.asset_code)) {\n deselectAsset(asset.asset_code);\n } else if (\n !config.maxFiles ||\n selectedAssets.length < config.maxFiles\n ) {\n selectAsset(asset, originalVariant?.id);\n }\n lastClickedIndexRef.current = index;\n return;\n }\n\n lastClickedIndexRef.current = index;\n\n if (selectedAssets.includes(asset.asset_code)) {\n deselectAsset(asset.asset_code);\n } else {\n if (config.maxFiles === 1) {\n clearAndSelectAsset(asset, originalVariant?.id);\n } else {\n selectAsset(asset, originalVariant?.id);\n }\n }\n };\n\n const closeAction = () => setAction(null);\n\n const libraryItems = useMemo((): LibraryAssetItem<DamAsset>[] => {\n if (!sortedAssets?.length) return [];\n return sortedAssets.map((asset: DamAsset) => {\n const isSelected = selectedAssets.includes(asset.asset_code);\n const selectionIndex = getSelectionIndex(asset.asset_code);\n return {\n id: asset.asset_code,\n name: asset.name ?? \"\",\n subtitle: `${asset.category} • ${asset.variants?.length ?? 0} variant${(asset.variants?.length ?? 0) !== 1 ? \"s\" : \"\"}`,\n isSelected,\n selectionIndex,\n raw: asset,\n };\n });\n }, [sortedAssets, selectedAssets, getSelectionIndex]);\n\n const getImageSize = () => {\n const baseSize = 200;\n return Math.round(baseSize * (thumbnailSize / 100));\n };\n\n return (\n <>\n <AddFolderModal\n open={open}\n setOpen={setOpen}\n onSubmit={handleNewFolder}\n form={form}\n isLoading={isPending}\n />\n\n <ActionModal\n open={action?.type === \"Delete\"}\n description={`This asset **${action?.item.name}** will be permanently deleted.`}\n onCancel={closeAction}\n onAction={() =>\n deleteAssetMutate(action?.item.asset_code ?? \"\", {\n onSuccess: closeAction,\n })\n }\n title=\"Are you sure?\"\n loading={isDeleting}\n />\n\n <ActionModal\n actionLabel=\"Discard\"\n open={action?.type === \"Discard\"}\n description={`This asset **${action?.item.name}** will be discarded from your library and will be permanently deleted after a month!`}\n onAction={() =>\n discardAssetMutate(action?.item.asset_code ?? \"\", {\n onSuccess: closeAction,\n })\n }\n title=\"Are you sure?\"\n onCancel={closeAction}\n actionVariant=\"default\"\n loading={isDiscarding}\n />\n\n {/* Preview popup on double-click */}\n <Dialog\n open={previewAsset !== null}\n onOpenChange={(open) => !open && onPreviewAssetChange?.(null)}\n >\n <DialogPortal container={previewContainer ?? undefined}>\n <DialogOverlay className=\"z-9999 bg-black/70 backdrop-blur-none\" />\n <DialogPrimitive.Content\n className=\"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-1/2 left-1/2 z-10000 max-h-[85vh] w-full max-w-4xl -translate-x-1/2 -translate-y-1/2 overflow-hidden bg-white shadow-xl\"\n style={{ zIndex: 10000 }}\n aria-label=\"Asset preview\"\n >\n {previewAsset && (\n <div className=\"flex max-h-[85vh] flex-col\">\n <AssetThumbnail\n asset={previewAsset}\n variant={\n previewAsset.variants.find((x) => x.ready) ||\n previewAsset.variants[0]\n }\n layout=\"preview\"\n />\n </div>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n </Dialog>\n\n <div>\n <div className=\"space-y-4\">\n <Breadcrumb>\n <BreadcrumbList className=\"min-w-0 flex-wrap\">\n {breadcrumbs.map((crumb, index) => (\n <React.Fragment key={crumb.path}>\n <BreadcrumbItem className=\"inline-flex min-w-0\">\n {crumb.isCurrent ? (\n <BreadcrumbPage className=\"max-w-48 truncate sm:max-w-xs\">\n {crumb.label}\n </BreadcrumbPage>\n ) : (\n <Button\n variant=\"ghost\"\n type=\"button\"\n onClick={() => navigateToPath(crumb.path)}\n className={cn(\n \"hover:text-foreground max-w-48 truncate transition-colors sm:max-w-xs\",\n )}\n >\n {crumb.label}\n </Button>\n )}\n </BreadcrumbItem>\n {index < breadcrumbs.length - 1 && <BreadcrumbSeparator />}\n </React.Fragment>\n ))}\n </BreadcrumbList>\n </Breadcrumb>\n\n {isLoading || isSearching ? (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-2 h-8 w-8 animate-spin rounded-full border-2 border-blue-600 border-t-transparent\"></div>\n <p className=\"text-sm text-gray-500\">\n {isSearching ? \"Searching...\" : \"Loading assets...\"}\n </p>\n </div>\n </div>\n ) : (\n <div className=\"space-y-6\">\n {folders?.length > 0 && (\n <div className=\"space-y-6\">\n <h3 className=\"text-sm font-medium text-gray-900\">\n Folders\n </h3>\n\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5\">\n {folders.map((folder) => (\n <Button\n variant=\"ghost\"\n key={folder}\n onClick={() => navigateToPath(folder + \".*\")}\n className=\"group flex items-center gap-3 rounded-lg border border-gray-200 bg-white p-3 text-left shadow-sm transition-colors hover:border-gray-300 hover:bg-gray-50\"\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-md bg-blue-50\">\n <FolderIcon className=\"h-4 w-4 text-blue-600\" />\n </div>\n <span className=\"truncate text-sm font-medium text-gray-900 group-hover:text-gray-700\">\n {folder.split(\".\").pop()}\n </span>\n </Button>\n ))}\n </div>\n </div>\n )}\n\n {sortedAssets?.length > 0 && (\n <div>\n <div className=\"mb-4 flex items-center justify-between\">\n <h3 className=\"text-sm font-medium text-gray-900\">\n Assets\n </h3>\n </div>\n\n <LibraryAssetGrid<DamAsset>\n items={libraryItems}\n viewMode={viewMode as LibraryAssetViewMode}\n thumbnailSize={thumbnailSize}\n showNamesOnMedia={showNamesOnMedia}\n renderThumbnail={(raw, layout) => {\n const defaultVariant =\n raw.variants.find((v) => v.ready) || raw.variants[0];\n return (\n <AssetThumbnail\n asset={raw}\n variant={defaultVariant}\n layout={layout}\n imageSize={getImageSize()}\n />\n );\n }}\n onClick={(e, id, index) => {\n const asset = sortedAssets?.[index];\n if (!asset) return;\n const handlers = createAssetClickHandlers(\n pendingClickTimeoutRef,\n handleAssetClick,\n (a) => onPreviewAssetChange?.(a),\n asset,\n index,\n );\n handlers.onClick(e);\n }}\n onDoubleClick={(e, _id, index) => {\n const asset = sortedAssets?.[index];\n if (!asset) return;\n const handlers = createAssetClickHandlers(\n pendingClickTimeoutRef,\n handleAssetClick,\n (a) => onPreviewAssetChange?.(a),\n asset,\n index,\n );\n handlers.onDoubleClick(e);\n }}\n renderTopRightOverlay={(item) => (\n <AssetActionsMenu\n asset={item.raw}\n position={viewMode === \"list\" ? \"list\" : \"grid\"}\n onDiscard={() =>\n setAction({ item: item.raw, type: \"Discard\" })\n }\n onDelete={() =>\n setAction({ item: item.raw, type: \"Delete\" })\n }\n />\n )}\n wrapItem={(item, content) => (\n <TooltipProvider key={item.id}>\n <Tooltip>\n <TooltipTrigger asChild>{content}</TooltipTrigger>\n <TooltipContent>{item.name}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n />\n {hasNextPage && (\n <div className=\"mt-4 flex justify-center\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n loadMore();\n }}\n disabled={isFetching}\n >\n {isFetching ? (\n <>\n <LoaderIcon className=\"mr-2 h-3 w-3 animate-spin\" />\n Loading...\n </>\n ) : (\n <>\n <ChevronDownIcon className=\"mr-2 h-3 w-3\" />\n Load more\n </>\n )}\n </Button>\n </div>\n )}\n </div>\n )}\n\n {folders?.length === 0 &&\n sortedAssets?.length === 0 &&\n !isLoading && (\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"mb-4 rounded-full bg-gray-100 p-3\">\n <FolderIcon className=\"h-6 w-6 text-gray-400\" />\n </div>\n <h3 className=\"mb-1 text-sm font-medium text-gray-900\">\n No assets found\n </h3>\n <p className=\"text-xs text-gray-500\">\n Try searching for something else or navigate to a\n different folder\n </p>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </>\n );\n },\n);\n\nDamLibrary.displayName = \"DamLibrary\";\n","import React from \"react\";\nimport type { UploadMethod } from \"@fluid-app/file-picker-core\";\nimport { Button } from \"@fluid-app/ui-primitives\";\n\ninterface FilePickerSidebarProps {\n currentStep: \"select\" | \"details\";\n activeMethod: UploadMethod;\n onMethodChange: (method: UploadMethod) => void;\n methods: Array<{\n id: UploadMethod;\n label: string;\n icon: React.ComponentType<{ className?: string }>;\n description: string;\n }>;\n}\n\nexport const FilePickerSidebar: React.FC<FilePickerSidebarProps> = ({\n currentStep,\n activeMethod,\n onMethodChange,\n methods,\n}) => {\n if (currentStep !== \"select\") {\n return null;\n }\n\n return (\n <div className=\"flex hidden h-full w-64 flex-col rounded-tl-lg border-r border-gray-200 bg-gray-50 md:flex\">\n <div className=\"flex min-h-0 flex-1 flex-col gap-2 overflow-auto p-2\">\n {/* Upload Files Title */}\n <div className=\"flex flex-col gap-2 pt-3\">\n <h3 className=\"text-sm font-semibold text-gray-900\">Select File</h3>\n </div>\n\n {/* Main Tabs */}\n <div className=\"flex w-full min-w-0 flex-col gap-1 p-2\">\n {methods\n .filter((method) =>\n [\"dam\", \"media\", \"upload\", \"url\", \"unsplash\"].includes(method.id),\n )\n .map((method) => (\n <Button\n variant=\"ghost\"\n key={method.id}\n onClick={() => onMethodChange(method.id)}\n className={`flex h-8 w-full cursor-pointer items-center justify-start gap-2 rounded-md p-2 text-left text-sm transition-colors hover:bg-gray-100 ${\n activeMethod === method.id\n ? \"bg-gray-100 font-medium text-gray-900\"\n : \"text-gray-700\"\n }`}\n >\n {React.createElement(method.icon, {\n className: \"h-4 w-4 text-gray-500\",\n })}\n <span className=\"font-semibold\">{method.label}</span>\n </Button>\n ))}\n </div>\n\n {/* Cloud Storage */}\n {/* <div className=\"flex w-full min-w-0 flex-col gap-1 p-2\">\n <div className=\"mb-1 px-2 text-xs font-medium text-gray-500\">\n Cloud Storage\n </div>\n {methods\n .filter((method) =>\n [\"google-drive\", \"dropbox\"].includes(method.id),\n )\n .map((method) => {\n const Icon = method.icon;\n return (\n <button\n key={method.id}\n onClick={() => onMethodChange(method.id)}\n className={`flex h-8 w-full cursor-pointer items-center gap-2 rounded-md p-2 text-left text-sm transition-colors hover:bg-blue-50 ${\n activeMethod === method.id\n ? \"bg-blue-50 font-medium text-blue-600\"\n : \"text-gray-700\"\n }`}\n >\n <Icon className=\"h-4 w-4 text-gray-500\" />\n <span className=\"font-semibold\">{method.label}</span>\n </button>\n );\n })}\n </div> */}\n\n {/* Social Media */}\n {/* <div className=\"flex w-full min-w-0 flex-col gap-1 p-2\">\n <div className=\"mb-1 px-2 text-xs font-medium text-gray-500\">\n Social Media\n </div>\n {methods\n .filter((method) =>\n [\"instagram\", \"facebook\", \"tiktok\"].includes(method.id),\n )\n .map((method) => {\n const Icon = method.icon;\n return (\n <button\n key={method.id}\n onClick={() => onMethodChange(method.id)}\n className={`flex h-8 w-full cursor-pointer items-center gap-2 rounded-md p-2 text-left text-sm transition-colors hover:bg-blue-50 ${\n activeMethod === method.id\n ? \"bg-blue-50 font-medium text-blue-600\"\n : \"text-gray-700\"\n }`}\n >\n <Icon className=\"h-4 w-4 text-gray-500\" />\n <span className=\"font-semibold\">{method.label}</span>\n </button>\n );\n })}\n </div> */}\n </div>\n </div>\n );\n};\n","import React from \"react\";\nimport {\n Button,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@fluid-app/ui-primitives\";\nimport {\n DAM_TYPE_FILTER_OPTIONS,\n FILTER_VALUE_ALL,\n} from \"@fluid-app/file-picker-core\";\n\nexport interface FilePickerFiltersState {\n type: string;\n date: string;\n uploadedBy: string;\n usageStatus: string;\n source: string;\n}\n\nconst defaultFilters: FilePickerFiltersState = {\n type: \"\",\n date: \"\",\n uploadedBy: \"\",\n usageStatus: \"\",\n source: \"\",\n};\n\ninterface FilePickerFiltersPanelProps {\n filters: FilePickerFiltersState;\n onFiltersChange: (filters: FilePickerFiltersState) => void;\n onClear: () => void;\n onDone: () => void;\n}\n\nexport const FilePickerFiltersPanel: React.FC<FilePickerFiltersPanelProps> = ({\n filters,\n onFiltersChange,\n onClear,\n onDone,\n}) => {\n const updateFilter = <K extends keyof FilePickerFiltersState>(\n key: K,\n value: FilePickerFiltersState[K],\n ) => {\n onFiltersChange({ ...filters, [key]: value });\n };\n\n const hasActiveFilters =\n filters.type !== \"\" ||\n filters.date !== \"\" ||\n filters.uploadedBy !== \"\" ||\n filters.usageStatus !== \"\" ||\n filters.source !== \"\";\n\n return (\n <div className=\"flex w-80 flex-col gap-4 p-4\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-gray-900\">Filters</span>\n {hasActiveFilters && (\n <button\n type=\"button\"\n onClick={onClear}\n className=\"text-sm text-blue-600 hover:underline\"\n >\n Clear\n </button>\n )}\n </div>\n\n <div className=\"grid gap-4\">\n <div className=\"grid gap-2\">\n <label className=\"text-sm font-medium text-gray-700\">Type</label>\n <Select\n value={filters.type || FILTER_VALUE_ALL}\n onValueChange={(value) =>\n updateFilter(\"type\", value === FILTER_VALUE_ALL ? \"\" : value)\n }\n >\n <SelectTrigger className=\"z-[350]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent className=\"z-[350]\">\n {DAM_TYPE_FILTER_OPTIONS.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Commented out until we have the date, source, uploaded by, and usage status filters implemented */}\n {/* <div className=\"grid gap-2\">\n <label className=\"text-sm font-medium text-gray-700\">Date</label>\n ...\n </div>\n\n <div className=\"grid gap-2\">\n <label className=\"text-sm font-medium text-gray-700\">\n Uploaded by\n </label>\n ...\n </div>\n\n <div className=\"grid gap-2\">\n <label className=\"text-sm font-medium text-gray-700\">\n Usage status\n </label>\n ...\n </div>\n\n <div className=\"grid gap-2\">\n <label className=\"text-sm font-medium text-gray-700\">Source</label>\n ...\n </div> */}\n </div>\n\n <div className=\"flex justify-end gap-2 border-t border-gray-100 pt-4\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onDone}>\n Done\n </Button>\n </div>\n </div>\n );\n};\n\nFilePickerFiltersPanel.displayName = \"FilePickerFiltersPanel\";\n\nexport { defaultFilters };\n","import React, { useState } from \"react\";\nimport {\n XIcon,\n MinusIcon,\n PlusIcon,\n FolderIcon,\n FolderPlusIcon,\n TypeIcon,\n LayoutGridIcon,\n ListIcon,\n SlidersHorizontalIcon,\n ArrowUpDownIcon,\n CheckIcon,\n} from \"lucide-react\";\nimport {\n Button,\n Input,\n Slider,\n Tooltip,\n TooltipTrigger,\n TooltipContent,\n TooltipProvider,\n Popover,\n PopoverContent,\n PopoverTrigger,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n} from \"@fluid-app/ui-primitives\";\n\nimport type { UploadMethod } from \"@fluid-app/file-picker-core\";\nimport {\n FilePickerFiltersPanel,\n defaultFilters as defaultFiltersState,\n} from \"./FilePickerFiltersPanel\";\nimport type { FilePickerFiltersState } from \"./FilePickerFiltersPanel\";\nimport { SORT_OPTIONS } from \"@fluid-app/file-picker-core\";\nimport type { SortOptionId } from \"@fluid-app/file-picker-core\";\n\nexport type ViewMode = \"grid\" | \"list\";\n\ninterface FilePickerHeaderProps {\n currentStep: \"select\" | \"details\";\n activeMethod: UploadMethod;\n methods: Array<{\n id: UploadMethod;\n label: string;\n icon: React.ComponentType<{ className?: string }>;\n description: string;\n }>;\n onClose: () => void;\n damSearchQuery?: string;\n onDamSearchChange?: (value: string) => void;\n damSearching?: boolean;\n thumbnailSize?: number;\n onThumbnailSizeChange?: (size: number) => void;\n viewMode?: ViewMode;\n onViewModeChange?: (mode: ViewMode) => void;\n showNamesOnMedia?: boolean;\n onShowNamesOnMediaChange?: (value: boolean) => void;\n hasSelectedFiles?: boolean;\n damFolders?: string[];\n onAddToNewFolder?: () => void;\n onAddToExistingFolder?: (folderPath: string) => void;\n filters?: FilePickerFiltersState;\n onFiltersChange?: (filters: FilePickerFiltersState) => void;\n onFiltersClear?: () => void;\n sortOption?: SortOptionId;\n onSortChange?: (optionId: SortOptionId) => void;\n unsplashSearchQuery?: string;\n onUnsplashSearchChange?: (value: string) => void;\n unsplashSearching?: boolean;\n isUnsplashUploading?: boolean;\n}\n\nexport const FilePickerHeader: React.FC<FilePickerHeaderProps> = ({\n currentStep,\n activeMethod,\n methods,\n onClose,\n damSearchQuery = \"\",\n onDamSearchChange,\n damSearching = false,\n thumbnailSize = 100,\n onThumbnailSizeChange,\n viewMode = \"grid\",\n onViewModeChange,\n showNamesOnMedia = true,\n onShowNamesOnMediaChange,\n hasSelectedFiles = false,\n damFolders = [],\n onAddToNewFolder,\n onAddToExistingFolder,\n filters,\n onFiltersChange,\n onFiltersClear,\n sortOption,\n onSortChange,\n unsplashSearchQuery = \"\",\n onUnsplashSearchChange,\n unsplashSearching = false,\n isUnsplashUploading = false,\n}) => {\n const [filtersOpen, setFiltersOpen] = useState(false);\n const showMediaToolbar =\n currentStep === \"select\" &&\n (activeMethod === \"dam\" || activeMethod === \"media\");\n const showUnsplashToolbar =\n currentStep === \"select\" && activeMethod === \"unsplash\";\n\n return (\n <div className=\"sticky top-0 z-20 flex w-full flex-wrap items-center justify-between gap-3 border-b border-gray-100 bg-white px-6 py-3\">\n <div className=\"flex min-w-0 flex-1 items-center gap-4\">\n <span className=\"shrink-0 text-lg font-semibold text-gray-900\">\n {currentStep === \"select\"\n ? methods.find((method) => method.id === activeMethod)?.label ||\n \"Select Files\"\n : \"Media Details\"}\n </span>\n\n {showMediaToolbar && (\n <div className=\"relative max-w-md min-w-0 flex-1\">\n <Input\n type=\"text\"\n placeholder=\"Search assets...\"\n value={damSearchQuery}\n onChange={(e) => onDamSearchChange?.(e.target.value)}\n className=\"h-9\"\n />\n {damSearching && (\n <div className=\"absolute top-1/2 right-3 -translate-y-1/2\">\n <div className=\"h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent\" />\n </div>\n )}\n </div>\n )}\n\n {showUnsplashToolbar && (\n <div className=\"flex min-w-0 flex-1 justify-center\">\n <div className=\"relative w-full max-w-md\">\n <Input\n type=\"text\"\n placeholder=\"Search for images...\"\n value={unsplashSearchQuery}\n onChange={(e) => onUnsplashSearchChange?.(e.target.value)}\n disabled={isUnsplashUploading}\n className=\"h-9\"\n />\n {unsplashSearching && (\n <div className=\"absolute top-1/2 right-3 -translate-y-1/2\">\n <div className=\"h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent\" />\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* DAM / Media Toolbar Controls */}\n {showMediaToolbar && (\n <div className=\"flex items-center gap-3\">\n {/* Zoom Slider (disabled in list view) */}\n <div\n className={\n viewMode === \"list\"\n ? \"pointer-events-none flex items-center gap-1.5 opacity-50\"\n : \"flex items-center gap-1.5\"\n }\n >\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n onClick={() => {\n const next = Math.max(25, thumbnailSize - 25);\n onThumbnailSizeChange?.(next);\n }}\n disabled={thumbnailSize <= 25 || viewMode === \"list\"}\n className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-transparent text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700 disabled:opacity-40 disabled:hover:bg-transparent\"\n >\n <MinusIcon className=\"h-3 w-3\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Zoom out</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <Slider\n value={[thumbnailSize]}\n onValueChange={(value) => {\n if (value[0] !== undefined) {\n onThumbnailSizeChange?.(value[0]);\n }\n }}\n min={25}\n max={150}\n step={25}\n className=\"w-20\"\n disabled={viewMode === \"list\"}\n />\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n onClick={() => {\n const next = Math.min(150, thumbnailSize + 25);\n onThumbnailSizeChange?.(next);\n }}\n disabled={thumbnailSize >= 150 || viewMode === \"list\"}\n className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-transparent text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700 disabled:opacity-40 disabled:hover:bg-transparent\"\n >\n <PlusIcon className=\"h-3 w-3\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Zoom in</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n\n <div className=\"h-5 w-px bg-gray-200\" />\n\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => onShowNamesOnMediaChange?.(!showNamesOnMedia)}\n disabled={viewMode === \"list\"}\n className={`flex h-8 w-8 items-center justify-center rounded-md bg-transparent transition-colors ${\n viewMode === \"list\"\n ? \"cursor-not-allowed opacity-50\"\n : showNamesOnMedia\n ? \"bg-blue-50 text-blue-600\"\n : \"text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n }`}\n >\n <TypeIcon className=\"h-4 w-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {viewMode === \"list\"\n ? \"Not available in list view\"\n : showNamesOnMedia\n ? \"Hide names on media\"\n : \"Show names on media\"}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n\n <div className=\"h-5 w-px bg-gray-200\" />\n\n {/* View Mode Toggles - Grid and List */}\n <div className=\"flex items-center gap-1 rounded-md border border-gray-200 bg-gray-50 p-0.5\">\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => onViewModeChange?.(\"grid\")}\n className={`flex h-7 w-7 items-center justify-center rounded bg-transparent transition-colors ${\n viewMode === \"grid\"\n ? \"bg-white text-blue-600 shadow-sm\"\n : \"text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n }`}\n >\n <LayoutGridIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Grid View</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => onViewModeChange?.(\"list\")}\n className={`flex h-7 w-7 items-center justify-center rounded bg-transparent transition-colors ${\n viewMode === \"list\"\n ? \"bg-white text-blue-600 shadow-sm\"\n : \"text-gray-500 hover:text-gray-700\"\n }`}\n >\n <ListIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>List View</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n\n <div className=\"h-5 w-px bg-gray-200\" />\n\n {activeMethod === \"dam\" && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n disabled={!hasSelectedFiles}\n className=\"flex h-8 w-8 items-center justify-center rounded-md bg-transparent text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700 disabled:opacity-40\"\n >\n <FolderPlusIcon className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"z-350 min-w-[200px]\">\n <DropdownMenuItem\n onClick={() => onAddToNewFolder?.()}\n className=\"cursor-pointer\"\n >\n <FolderPlusIcon className=\"mr-2 h-4 w-4\" />\n Add to New Folder\n </DropdownMenuItem>\n {damFolders.length > 0 && (\n <DropdownMenuSub>\n <DropdownMenuSubTrigger className=\"cursor-pointer\">\n <FolderPlusIcon className=\"mr-2 h-4 w-4\" />\n Add to Existing Folder\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent className=\"z-350 max-h-64 overflow-y-auto\">\n {damFolders.map((folder) => (\n <DropdownMenuItem\n key={folder}\n onClick={() =>\n onAddToExistingFolder?.(folder)\n }\n className=\"cursor-pointer\"\n >\n <FolderIcon className=\"mr-2 h-4 w-4\" />\n {folder.split(\".\").pop() || folder}\n </DropdownMenuItem>\n ))}\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n {hasSelectedFiles\n ? \"Add selected files to a folder\"\n : \"Select files to add to a folder\"}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n\n {activeMethod === \"dam\" && <div className=\"h-5 w-px bg-gray-200\" />}\n\n {/* Filters */}\n <Popover open={filtersOpen} onOpenChange={setFiltersOpen}>\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n className={`flex h-8 w-8 items-center justify-center rounded-md bg-transparent transition-colors ${\n filters &&\n (filters.type ||\n filters.date ||\n filters.uploadedBy ||\n filters.usageStatus ||\n filters.source)\n ? \"bg-blue-50 text-blue-600\"\n : \"text-gray-500 hover:bg-gray-100 hover:text-gray-700\"\n }`}\n >\n <SlidersHorizontalIcon className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>Filters</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n <PopoverContent align=\"end\" className=\"w-auto p-0\">\n <FilePickerFiltersPanel\n filters={filters ?? defaultFiltersState}\n onFiltersChange={(f) => onFiltersChange?.(f)}\n onClear={() => {\n onFiltersClear?.();\n setFiltersOpen(false);\n }}\n onDone={() => setFiltersOpen(false)}\n />\n </PopoverContent>\n </Popover>\n\n {/* Sort */}\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md bg-transparent text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700\"\n >\n <ArrowUpDownIcon className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"z-350 min-w-[180px]\">\n {SORT_OPTIONS.map((option) => (\n <DropdownMenuItem\n key={option.id}\n onClick={() => onSortChange?.(option.id)}\n >\n <span\n className={\n sortOption === option.id\n ? \"font-medium\"\n : undefined\n }\n >\n {option.label}\n </span>\n {sortOption === option.id && (\n <CheckIcon className=\"ml-auto h-4 w-4 text-blue-600\" />\n )}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </span>\n </TooltipTrigger>\n <TooltipContent>Sort</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n </div>\n )}\n\n {/* Close button - always visible */}\n <Button variant=\"ghost\" size=\"sm\" onClick={onClose} className=\"ml-2\">\n <XIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n );\n};\n","import React, { useState, useCallback, useEffect, useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport {\n ImageIcon,\n VideoIcon,\n FileIcon,\n LoaderIcon,\n SearchIcon,\n ChevronDownIcon,\n} from \"lucide-react\";\nimport {\n Button,\n Input,\n Dialog,\n DialogOverlay,\n DialogPortal,\n DialogContent,\n} from \"@fluid-app/ui-primitives\";\nimport type {\n FilePickerResult,\n SortOptionId,\n} from \"@fluid-app/file-picker-core\";\nimport { SORT_OPTIONS } from \"@fluid-app/file-picker-core\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\nimport {\n LibraryAssetGrid,\n type LibraryAssetItem,\n type LibraryAssetViewMode,\n} from \"./LibraryAssetGrid\";\nimport type { MediumResponse } from \"../types/media\";\n\ninterface MediaTabProps {\n config: {\n maxFiles?: number;\n fileTypeFilter?: string[];\n };\n onMediaSelected: (results: FilePickerResult[]) => void;\n onSelectionChange?: (count: number) => void;\n onMediaDataChange?: (data: FilePickerResult[]) => void;\n selectedMediaIds: number[];\n onMediaIdsChange: (ids: number[]) => void;\n searchQuery?: string;\n onSearchChange?: (value: string) => void;\n thumbnailSize?: number;\n viewMode?: LibraryAssetViewMode;\n showNamesOnMedia?: boolean;\n mediaTypeFilter?: string;\n sortOption?: SortOptionId;\n previewContainer?: HTMLDivElement | null;\n previewMedia?: MediumResponse | null;\n onPreviewMediaChange?: (media: MediumResponse | null) => void;\n}\n\nconst DAM_CATEGORY_TO_MEDIA_TYPE: Record<string, string> = {\n images: \"image\",\n videos: \"video\",\n documents: \"document\",\n audio: \"audio\",\n text: \"document\",\n other: \"image\",\n presentations: \"presentation\",\n};\n\nexport const MediaTab: React.FC<MediaTabProps> = ({\n config,\n onSelectionChange,\n onMediaDataChange,\n selectedMediaIds,\n onMediaIdsChange,\n searchQuery: controlledSearchQuery,\n onSearchChange: controlledSetSearchQuery,\n thumbnailSize = 100,\n viewMode = \"grid\",\n showNamesOnMedia = true,\n mediaTypeFilter: headerTypeFilter,\n sortOption,\n previewContainer,\n previewMedia,\n onPreviewMediaChange,\n}) => {\n const { shareablesClient } = useFilePickerContext();\n\n const [internalSearchQuery, setInternalSearchQuery] = useState(\"\");\n const isSearchControlled =\n controlledSearchQuery !== undefined && controlledSetSearchQuery != null;\n const searchQuery = isSearchControlled\n ? controlledSearchQuery\n : internalSearchQuery;\n const setSearchQuery = isSearchControlled\n ? controlledSetSearchQuery\n : setInternalSearchQuery;\n const [allMediaItems, setAllMediaItems] = useState<MediumResponse[]>([]);\n const [currentPage, setCurrentPage] = useState(1);\n const [loadingMore, setLoadingMore] = useState(false);\n\n const mediaTypeFilter = useMemo(() => {\n if (headerTypeFilter && DAM_CATEGORY_TO_MEDIA_TYPE[headerTypeFilter]) {\n return DAM_CATEGORY_TO_MEDIA_TYPE[headerTypeFilter];\n }\n if (!config.fileTypeFilter || config.fileTypeFilter.length === 0) {\n return undefined;\n }\n for (const filter of config.fileTypeFilter) {\n if (DAM_CATEGORY_TO_MEDIA_TYPE[filter]) {\n return DAM_CATEGORY_TO_MEDIA_TYPE[filter];\n }\n }\n return undefined;\n }, [headerTypeFilter, config.fileTypeFilter]);\n\n // Fetch all media (same as media index table)\n const {\n data: mediaResponse,\n isLoading,\n error,\n } = useQuery({\n queryKey: [\"media-tab\", searchQuery, mediaTypeFilter],\n queryFn: () => {\n if (!shareablesClient) {\n throw new Error(\"Shareables client is not configured\");\n }\n return shareablesClient.media.list({\n search_query: searchQuery,\n page: 1,\n per_page: 30,\n active: true,\n with_type: mediaTypeFilter,\n }) as Promise<{\n media: MediumResponse[];\n meta?: { next: string | null };\n }>;\n },\n enabled: !!shareablesClient,\n staleTime: 5 * 60 * 1000, // 5 minutes\n });\n\n // Reset pagination when search or media type filter changes\n useEffect(() => {\n setAllMediaItems([]);\n setCurrentPage(1);\n }, [searchQuery, mediaTypeFilter]);\n\n // Update accumulated media items when new data comes in\n useEffect(() => {\n if (!mediaResponse) return;\n\n const newMediaItems = (mediaResponse.media || []) as MediumResponse[];\n if (newMediaItems.length > 0) {\n setAllMediaItems((prev) => {\n // Merge without duplicates by id\n const map = new Map(prev.map((item) => [item.id, item]));\n for (const item of newMediaItems) {\n map.set(item.id, item);\n }\n return Array.from(map.values());\n });\n }\n }, [mediaResponse]);\n\n const hasNextPage = mediaResponse?.meta?.next !== null;\n\n // Load more media items\n const loadMore = useCallback(async () => {\n if (!hasNextPage || !shareablesClient) return;\n\n try {\n setLoadingMore(true);\n const nextPage = currentPage + 1;\n const response = (await shareablesClient.media.list({\n search_query: searchQuery,\n page: nextPage,\n per_page: 30,\n active: true,\n with_type: mediaTypeFilter,\n })) as { media: MediumResponse[]; meta?: { next: string | null } };\n\n const newMediaItems = (response.media || []) as MediumResponse[];\n if (newMediaItems.length > 0) {\n setAllMediaItems((prev) => {\n // Merge without duplicates by id\n const map = new Map(prev.map((item) => [item.id, item]));\n for (const item of newMediaItems) {\n map.set(item.id, item);\n }\n return Array.from(map.values());\n });\n setCurrentPage(nextPage);\n }\n } finally {\n setLoadingMore(false);\n }\n }, [\n hasNextPage,\n currentPage,\n searchQuery,\n mediaTypeFilter,\n shareablesClient,\n ]);\n\n // Convert MediumResponse to FilePickerResult\n const convertToFilePickerResult = useCallback(\n (media: MediumResponse): FilePickerResult => {\n // Determine the file URL based on media type\n let fileUrl = \"\";\n let mimeType = \"\";\n let fileName = media.title;\n let thumbnailUrl = \"\";\n let description = \"\";\n\n // Almost all media have image_url that stores the url for thumbnail/preview\n // so, we'll check the presence of image_url at the end of the logic\n if (media.video_url) {\n fileUrl = media.video_url;\n mimeType = \"video/mp4\"; // Default, could be improved with actual detection\n fileName = `${media.title}.mp4`;\n thumbnailUrl = media.image_url || \"\";\n description = media.description?.body || \"\";\n } else if (media.pdf_url) {\n fileUrl = media.pdf_url;\n mimeType = \"application/pdf\";\n fileName = `${media.title}.pdf`;\n } else if (media.image_url) {\n fileUrl = media.image_url;\n mimeType = \"image/jpeg\"; // Default, could be improved with actual detection\n fileName = `${media.title}.jpg`;\n }\n\n return {\n asset_id: media.id,\n asset_code: `media_${media.id}`,\n file_path: fileUrl,\n file_url: fileUrl,\n ...(thumbnailUrl ? { thumbnail_url: thumbnailUrl } : {}),\n ...(description ? { description: description } : {}),\n metadata: {\n file_name: fileName,\n mime_type: mimeType,\n },\n upload_status: \"ready\" as const,\n };\n },\n [],\n );\n\n const handleMediaClick = useCallback(\n (_e: React.MouseEvent, id: string, _index: number) => {\n const mediaId = parseInt(id.replace(/^media_/, \"\"), 10);\n if (Number.isNaN(mediaId)) return;\n\n const isSelected = selectedMediaIds.includes(mediaId);\n let newSelectedIds: number[];\n\n if (isSelected) {\n newSelectedIds = selectedMediaIds.filter((id) => id !== mediaId);\n } else {\n if (config.maxFiles === 1) {\n newSelectedIds = [mediaId];\n } else if (\n config.maxFiles &&\n selectedMediaIds.length >= config.maxFiles\n ) {\n return;\n } else {\n newSelectedIds = [...selectedMediaIds, mediaId];\n }\n }\n\n onMediaIdsChange(newSelectedIds);\n\n const idToMedia = new Map(allMediaItems.map((m) => [m.id, m]));\n const orderedMedia = newSelectedIds\n .map((id) => idToMedia.get(id))\n .filter((m): m is MediumResponse => m != null);\n const filePickerResults = orderedMedia.map(convertToFilePickerResult);\n onMediaDataChange?.(filePickerResults);\n },\n [\n selectedMediaIds,\n config.maxFiles,\n allMediaItems,\n convertToFilePickerResult,\n onMediaIdsChange,\n onMediaDataChange,\n ],\n );\n\n // Update selection count when selectedMediaIds changes\n React.useEffect(() => {\n onSelectionChange?.(selectedMediaIds.length);\n }, [selectedMediaIds.length, onSelectionChange]);\n\n const sortedMediaItems = useMemo(() => {\n if (!sortOption || !allMediaItems.length) return allMediaItems;\n const option = SORT_OPTIONS.find((o) => o.id === sortOption);\n if (!option) return allMediaItems;\n return [...allMediaItems].sort((a, b) => {\n if (option.sortBy === \"name\") {\n const cmp = (a.title ?? \"\").localeCompare(b.title ?? \"\", undefined, {\n sensitivity: \"base\",\n });\n return option.sortDirection === \"asc\" ? cmp : -cmp;\n }\n if (option.sortBy === \"created_at\") {\n const aId = a.id ?? 0;\n const bId = b.id ?? 0;\n const cmp = aId - bId;\n return option.sortDirection === \"asc\" ? cmp : -cmp;\n }\n return 0;\n });\n }, [allMediaItems, sortOption]);\n\n const getMediaIcon = (media: MediumResponse) => {\n if (media.image_url) return ImageIcon;\n if (media.video_url) return VideoIcon;\n if (media.pdf_url) return FileIcon;\n return FileIcon;\n };\n\n const renderMediaThumbnail = useCallback(\n (media: MediumResponse, _layout: LibraryAssetViewMode) => {\n if (media.image_url) {\n return (\n <img\n src={media.image_url}\n alt={media.title}\n width={200}\n height={150}\n className=\"h-full w-full object-cover\"\n />\n );\n }\n const MediaIcon = getMediaIcon(media);\n return (\n <div className=\"flex h-full w-full items-center justify-center bg-gray-100\">\n <MediaIcon className=\"h-8 w-8 text-gray-400\" />\n </div>\n );\n },\n [],\n );\n\n const libraryItems = useMemo((): LibraryAssetItem<MediumResponse>[] => {\n return sortedMediaItems.map((media) => {\n const id = `media_${media.id}`;\n const indexInSelection = selectedMediaIds.indexOf(media.id);\n const isSelected = indexInSelection >= 0;\n const selectionIndex = isSelected ? indexInSelection + 1 : 0;\n return {\n id,\n name: media.title ?? \"\",\n subtitle: media.kind ?? \"Media\",\n isSelected,\n selectionIndex,\n raw: media,\n };\n });\n }, [sortedMediaItems, selectedMediaIds]);\n\n const handleMediaDoubleClick = useCallback(\n (_e: React.MouseEvent, _id: string, index: number) => {\n const media = sortedMediaItems[index];\n if (media) onPreviewMediaChange?.(media);\n },\n [sortedMediaItems, onPreviewMediaChange],\n );\n\n if (error) {\n return (\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"text-center\">\n <p className=\"text-sm text-red-600\">Failed to load media</p>\n <p className=\"mt-1 text-xs text-gray-500\">Please try again later</p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n <Dialog\n open={!!previewMedia}\n onOpenChange={(open) => !open && onPreviewMediaChange?.(null)}\n >\n <DialogPortal container={previewContainer ?? undefined}>\n <DialogOverlay className=\"z-9999 bg-black/70 backdrop-blur-none\" />\n <DialogContent\n className=\"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-1/2 left-1/2 z-10000 max-h-[85vh] w-full max-w-4xl -translate-x-1/2 -translate-y-1/2 overflow-hidden bg-white shadow-xl\"\n style={{ zIndex: 10000 }}\n >\n {previewMedia && (\n <div className=\"flex max-h-[85vh] flex-col\">\n {previewMedia.image_url ? (\n <div className=\"relative flex min-h-0 justify-center overflow-hidden bg-gray-100\">\n <img\n src={previewMedia.image_url}\n alt={previewMedia.title}\n className=\"max-h-[85vh] w-auto max-w-full object-contain\"\n />\n </div>\n ) : previewMedia.video_url ? (\n <div className=\"relative aspect-video max-h-[85vh] overflow-hidden bg-black\">\n <video\n src={previewMedia.video_url}\n autoPlay\n muted\n controls\n className=\"h-full w-full object-contain\"\n />\n </div>\n ) : (\n <div className=\"flex aspect-video min-h-[200px] items-center justify-center bg-gray-100 p-8\">\n {(() => {\n const PreviewIcon = getMediaIcon(previewMedia);\n return (\n <PreviewIcon className=\"h-16 w-16 text-gray-400\" />\n );\n })()}\n <p className=\"ml-4 text-sm text-gray-600\">\n {previewMedia.title}\n </p>\n </div>\n )}\n </div>\n )}\n </DialogContent>\n </DialogPortal>\n </Dialog>\n\n {/* Search (only when not controlled from header) */}\n {!isSearchControlled && (\n <div className=\"relative\">\n <Input\n type=\"text\"\n placeholder=\"Search media...\"\n value={searchQuery}\n onChange={(e) => {\n setSearchQuery(e.target.value);\n }}\n className=\"h-9\"\n />\n <div className=\"absolute top-1/2 right-3 -translate-y-1/2\">\n <SearchIcon className=\"h-4 w-4 text-gray-400\" />\n </div>\n </div>\n )}\n\n {/* Media Grid */}\n {isLoading ? (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"text-center\">\n <LoaderIcon className=\"mx-auto mb-2 h-8 w-8 animate-spin text-blue-600\" />\n <p className=\"text-sm text-gray-500\">Loading media...</p>\n </div>\n </div>\n ) : allMediaItems.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"mb-4 rounded-full bg-gray-100 p-3\">\n <ImageIcon className=\"h-6 w-6 text-gray-400\" />\n </div>\n <h3 className=\"mb-1 text-sm font-medium text-gray-900\">\n No media found\n </h3>\n <p className=\"text-xs text-gray-500\">\n {searchQuery\n ? \"Try adjusting your search terms\"\n : \"Create some media to get started\"}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n <LibraryAssetGrid<MediumResponse>\n items={libraryItems}\n viewMode={viewMode ?? \"grid\"}\n thumbnailSize={thumbnailSize}\n showNamesOnMedia={showNamesOnMedia ?? true}\n renderThumbnail={renderMediaThumbnail}\n onClick={handleMediaClick}\n onDoubleClick={handleMediaDoubleClick}\n />\n\n {/* Load More Button */}\n {hasNextPage && (\n <div className=\"flex justify-center\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={loadMore}\n disabled={loadingMore}\n >\n {loadingMore ? (\n <>\n <LoaderIcon className=\"mr-2 h-3 w-3 animate-spin\" />\n Loading...\n </>\n ) : (\n <>\n <ChevronDownIcon className=\"mr-2 h-3 w-3\" />\n Load more\n </>\n )}\n </Button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default MediaTab;\n","import { useState, useCallback } from \"react\";\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport {\n damQueryKeys,\n getDamAssetUrl,\n getSanitizedAssetName,\n type CreateDamAssetParams,\n type FilePickerResult,\n type UnsplashImage,\n type UploadProgress,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerApi } from \"../context/FilePickerApiContext\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\n\ninterface UseUnsplashPickerOptions {\n controlledSearchQuery?: string;\n onControlledSearchQueryChange?: (value: string) => void;\n}\n\nexport const useUnsplashPicker = (\n options?: UseUnsplashPickerOptions,\n): {\n searchQuery: string;\n setSearchQuery: (value: string) => void;\n searchResults: UnsplashImage[];\n isSearching: boolean;\n searchImages: (query: string, page?: number) => void;\n downloadAndUpload: (image: UnsplashImage) => Promise<FilePickerResult>;\n uploadProgress: UploadProgress[];\n isUploading: boolean;\n clearProgress: () => void;\n hasMoreResults: boolean;\n loadMore: () => void;\n isLoadingMore: boolean;\n} => {\n const { controlledSearchQuery, onControlledSearchQueryChange } =\n options ?? {};\n const [internalSearchQuery, setInternalSearchQuery] = useState(\"\");\n const searchQuery = controlledSearchQuery ?? internalSearchQuery;\n const setSearchQuery =\n onControlledSearchQueryChange ?? setInternalSearchQuery;\n const [searchResults, setSearchResults] = useState<UnsplashImage[]>([]);\n const [isSearching, setIsSearching] = useState(false);\n const [isLoadingMore, setIsLoadingMore] = useState(false);\n const [currentPage, setCurrentPage] = useState(1);\n const [hasMoreResults, setHasMoreResults] = useState(true);\n const [uploadProgress, setUploadProgress] = useState<\n Map<string, UploadProgress>\n >(new Map());\n const queryClient = useQueryClient();\n const api = useFilePickerApi();\n const { apiBaseUrl, toast } = useFilePickerContext();\n\n const uploadMutation = useMutation({\n mutationFn: (params: CreateDamAssetParams) => api.createDamAsset(params),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: damQueryKeys.all });\n },\n });\n\n const searchImages = useCallback(\n async (query: string, page = 1) => {\n if (!query.trim()) {\n setSearchResults([]);\n setCurrentPage(1);\n setHasMoreResults(true);\n return;\n }\n\n if (page === 1) {\n setIsSearching(true);\n setCurrentPage(1);\n } else {\n setIsLoadingMore(true);\n }\n\n try {\n const data = await api.searchUnsplash(query, page);\n\n setSearchResults((prevResults) =>\n page === 1 ? data.results : [...prevResults, ...data.results],\n );\n\n setCurrentPage(page);\n setHasMoreResults(page < data.total_pages);\n } catch (err) {\n if (page === 1) {\n setSearchResults([]);\n }\n toast.error(\n err instanceof Error ? err.message : \"Unsplash search failed\",\n );\n } finally {\n setIsSearching(false);\n setIsLoadingMore(false);\n }\n },\n [api, toast],\n );\n\n const downloadAndUpload = useCallback(\n async (image: UnsplashImage): Promise<FilePickerResult> => {\n const uploadId = `unsplash-${image.id}`;\n const fileName = `unsplash-${image.id}.jpg`;\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: fileName,\n progress: 0,\n status: \"uploading\",\n });\n return next;\n });\n\n try {\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: fileName,\n progress: 25,\n status: \"uploading\",\n });\n return next;\n });\n\n const downloadUrlObj = new URL(image.urls.regular);\n downloadUrlObj.searchParams.set(\"fm\", \"jpg\");\n downloadUrlObj.searchParams.set(\"q\", \"80\");\n const downloadUrl = downloadUrlObj.toString();\n const response = await fetch(downloadUrl);\n\n if (!response.ok) {\n throw new Error(`Failed to download image: ${response.statusText}`);\n }\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: fileName,\n progress: 50,\n status: \"uploading\",\n });\n return next;\n });\n\n const blob = await response.blob();\n const file = new File([blob], fileName, { type: \"image/jpeg\" });\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: fileName,\n progress: 75,\n status: \"uploading\",\n });\n return next;\n });\n\n const damResponse = await uploadMutation.mutateAsync({\n file,\n name: getSanitizedAssetName(\n image.alt_description ||\n image.description ||\n `Unsplash ${image.id}`,\n ),\n description: `Downloaded from Unsplash. Photo by ${image.user.name} (@${image.user.username})`,\n tags: [\"unsplash\", image.user.username],\n });\n\n if (!damResponse.asset) {\n throw new Error(\n \"Invalid DAM response structure - missing asset property\",\n );\n }\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: fileName,\n progress: 100,\n status: \"ready\",\n });\n return next;\n });\n\n const asset = damResponse.asset;\n const fileUrl = getDamAssetUrl(asset, apiBaseUrl);\n\n return {\n asset_id: asset.id,\n asset_code: asset.code,\n file_path: fileUrl,\n file_url: fileUrl,\n metadata: {\n file_name: fileName,\n mime_type: \"image/jpeg\",\n dimensions: {\n width: image.width,\n height: image.height,\n },\n },\n upload_status: \"ready\",\n variant_id: asset.default_variant_id\n ? asset.default_variant_id.toString()\n : undefined,\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Upload failed\";\n toast.error(errorMessage);\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: fileName,\n progress: 0,\n status: \"error\",\n error: errorMessage,\n });\n return next;\n });\n\n return {\n asset_id: 0,\n asset_code: \"\",\n file_path: \"\",\n file_url: \"\",\n metadata: {\n file_name: fileName,\n mime_type: \"image/jpeg\",\n dimensions: {\n width: image.width,\n height: image.height,\n },\n },\n upload_status: \"error\",\n };\n }\n },\n [uploadMutation, apiBaseUrl, toast],\n );\n\n const clearProgress = useCallback(() => {\n setUploadProgress(new Map());\n }, []);\n\n const loadMore = useCallback(() => {\n if (searchQuery.trim() && hasMoreResults && !isLoadingMore) {\n searchImages(searchQuery, currentPage + 1);\n }\n }, [searchQuery, hasMoreResults, isLoadingMore, currentPage, searchImages]);\n\n return {\n searchQuery,\n setSearchQuery,\n searchResults,\n isSearching,\n searchImages,\n downloadAndUpload,\n uploadProgress: Array.from(uploadProgress.values()),\n isUploading: uploadMutation.isPending,\n clearProgress,\n hasMoreResults,\n loadMore,\n isLoadingMore,\n };\n};\n","import React, { useState, useEffect } from \"react\";\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport {\n DownloadIcon,\n CheckIcon,\n AlertTriangleIcon,\n UserIcon,\n LoaderIcon,\n} from \"lucide-react\";\nimport { useUnsplashPicker } from \"../hooks/use-unsplash-picker\";\nimport type {\n FilePickerConfig,\n FilePickerResult,\n} from \"@fluid-app/file-picker-core\";\n\ninterface UnsplashImage {\n id: string;\n urls: {\n raw: string;\n full: string;\n regular: string;\n small: string;\n thumb: string;\n };\n alt_description: string | null;\n description: string | null;\n user: {\n name: string;\n username: string;\n };\n width: number;\n height: number;\n}\n\ninterface UnsplashPickerProps {\n config: FilePickerConfig;\n onFileSelected: (result: FilePickerResult) => void;\n searchQuery?: string;\n onSearchQueryChange?: (value: string) => void;\n onSearchingChange?: (searching: boolean) => void;\n onUploadingChange?: (uploading: boolean) => void;\n}\n\nexport const UnsplashPicker: React.FC<UnsplashPickerProps> = ({\n config,\n onFileSelected,\n searchQuery: controlledSearchQuery,\n onSearchQueryChange: onControlledSearchQueryChange,\n onSearchingChange,\n onUploadingChange,\n}) => {\n const {\n searchQuery,\n searchResults,\n isSearching,\n searchImages,\n downloadAndUpload,\n uploadProgress,\n isUploading,\n clearProgress,\n hasMoreResults,\n loadMore,\n isLoadingMore,\n } = useUnsplashPicker(\n controlledSearchQuery !== undefined && onControlledSearchQueryChange\n ? {\n controlledSearchQuery,\n onControlledSearchQueryChange,\n }\n : undefined,\n );\n\n const [selectedImageId, setSelectedImageId] = useState<string | null>(null);\n\n useEffect(() => {\n const timeoutId = setTimeout(() => {\n if (searchQuery.trim()) {\n searchImages(searchQuery);\n }\n }, 500);\n\n return () => clearTimeout(timeoutId);\n }, [searchQuery, searchImages]);\n\n useEffect(() => {\n onSearchingChange?.(isSearching);\n }, [isSearching, onSearchingChange]);\n\n useEffect(() => {\n onUploadingChange?.(isUploading);\n }, [isUploading, onUploadingChange]);\n\n const handleImageSelect = async (image: UnsplashImage) => {\n setSelectedImageId(image.id);\n clearProgress();\n\n const result = await downloadAndUpload(image);\n\n if (result && result.upload_status === \"ready\") {\n setSelectedImageId(null);\n onFileSelected(result);\n } else {\n setSelectedImageId(null);\n }\n };\n\n return (\n <div className=\"space-y-4\">\n {isSearching && (\n <div className=\"py-4 text-center\">\n <p className=\"text-gray-500\">Searching Unsplash...</p>\n </div>\n )}\n\n {searchResults.length > 0 && (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4\">\n {searchResults.map((image) => (\n <div\n key={image.id}\n className={`group relative cursor-pointer overflow-hidden rounded-lg border-2 transition-all ${selectedImageId === image.id ? \"border-blue-500\" : \"border-transparent hover:border-gray-300\"} ${isUploading && selectedImageId === image.id ? \"opacity-50\" : \"\"} `}\n onClick={() => !isUploading && handleImageSelect(image)}\n >\n <img\n src={image.urls.small}\n alt={\n image.alt_description || image.description || \"Unsplash image\"\n }\n width={400}\n height={300}\n className=\"h-32 w-full object-cover\"\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n target.src = image.urls.thumb;\n }}\n />\n\n <div\n className=\"group-hover:bg-opacity-30 absolute inset-0 flex items-center justify-center transition-all\"\n style={{\n backgroundColor: \"rgba(0, 0, 0, 0)\",\n }}\n >\n <div className=\"opacity-0 transition-opacity group-hover:opacity-100\">\n <DownloadIcon className=\"h-6 w-6 text-white\" />\n </div>\n </div>\n\n <div className=\"absolute right-0 bottom-0 left-0 bg-linear-to-t from-black to-transparent p-2\">\n <div className=\"flex items-center space-x-1 text-xs text-white\">\n <UserIcon className=\"h-3 w-3\" />\n <span>\n Photo by{\" \"}\n <a\n href={`https://unsplash.com/@${image.user.username}?utm_source=fluid&utm_medium=referral`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline hover:text-gray-200\"\n onClick={(e) => e.stopPropagation()}\n >\n {image.user.name}\n </a>{\" \"}\n on{\" \"}\n <a\n href=\"https://unsplash.com/?utm_source=fluid&utm_medium=referral\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline hover:text-gray-200\"\n onClick={(e) => e.stopPropagation()}\n >\n Unsplash\n </a>\n </span>\n </div>\n </div>\n\n {selectedImageId === image.id && isUploading && (\n <div className=\"bg-opacity-75 absolute inset-0 flex items-center justify-center bg-blue-500\">\n <div className=\"text-center text-white\">\n <DownloadIcon className=\"mb-1 h-6 w-6 animate-pulse\" />\n <p className=\"text-xs\">Uploading...</p>\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n )}\n\n {searchQuery && !isSearching && searchResults.length === 0 && (\n <div className=\"py-8 text-center\">\n <p className=\"text-gray-500\">\n No images found for "{searchQuery}"\n </p>\n </div>\n )}\n\n {hasMoreResults && searchResults.length > 0 && (\n <div className=\"flex justify-center pt-4\">\n <Button onClick={loadMore} disabled={isLoadingMore} variant=\"outline\">\n {isLoadingMore ? (\n <>\n <LoaderIcon className=\"mr-2 animate-spin\" />\n Loading...\n </>\n ) : (\n <>\n <DownloadIcon className=\"mr-2\" />\n Load More\n </>\n )}\n </Button>\n </div>\n )}\n\n {config.showProgress && uploadProgress.length > 0 && (\n <div className=\"space-y-2\">\n <h4 className=\"text-sm font-medium text-gray-900\">Upload Progress</h4>\n {uploadProgress.map((progress) => (\n <div\n key={`${progress.file_name}-${progress.status}`}\n className=\"rounded-lg bg-gray-50 p-3\"\n >\n <div className=\"mb-2 flex items-center justify-between\">\n <div className=\"flex items-center space-x-2\">\n {(() => {\n const Icon =\n progress.status === \"ready\"\n ? CheckIcon\n : progress.status === \"error\"\n ? AlertTriangleIcon\n : DownloadIcon;\n return (\n <Icon\n className={`h-4 w-4 ${\n progress.status === \"ready\"\n ? \"text-green-500\"\n : progress.status === \"error\"\n ? \"text-red-500\"\n : \"text-blue-500\"\n }`}\n />\n );\n })()}\n <span className=\"text-sm font-medium text-gray-900\">\n {progress.file_name}\n </span>\n </div>\n <span className=\"text-xs text-gray-500 capitalize\">\n {progress.status}\n </span>\n </div>\n\n {progress.status === \"uploading\" && (\n <div className=\"h-2 w-full rounded-full bg-gray-200\">\n <div\n className=\"h-2 rounded-full bg-blue-600 transition-all duration-300\"\n style={{ width: `${progress.progress}%` }}\n />\n </div>\n )}\n\n {progress.error && (\n <p className=\"mt-1 text-xs text-red-600\">{progress.error}</p>\n )}\n </div>\n ))}\n </div>\n )}\n\n <div className=\"text-center text-xs text-gray-400\">\n Photos provided by{\" \"}\n <a\n href=\"https://unsplash.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline hover:text-gray-600\"\n >\n Unsplash\n </a>\n </div>\n </div>\n );\n};\n","import { useState, useCallback } from \"react\";\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport {\n damQueryKeys,\n getDamAssetUrl,\n sanitizeFilename,\n getSanitizedAssetName,\n type CreateDamAssetParams,\n type FilePickerResult,\n type UploadProgress,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerApi } from \"../context/FilePickerApiContext\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\n\nexport const useUrlUpload = (): {\n uploadFromUrl: (url: string, fileName?: string) => Promise<FilePickerResult>;\n uploadProgress: UploadProgress[];\n isUploading: boolean;\n clearProgress: () => void;\n} => {\n const [uploadProgress, setUploadProgress] = useState<\n Map<string, UploadProgress>\n >(new Map());\n const queryClient = useQueryClient();\n const api = useFilePickerApi();\n const { companyId, apiBaseUrl, toast } = useFilePickerContext();\n\n const uploadMutation = useMutation({\n mutationFn: (params: CreateDamAssetParams) => api.createDamAsset(params),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: damQueryKeys.all });\n },\n });\n\n const uploadFromUrl = useCallback(\n async (url: string, fileName?: string): Promise<FilePickerResult> => {\n const uploadId = `url-${Date.now()}`;\n const displayName =\n fileName ||\n url.split(\"/\").pop()?.split(\"?\")[0]?.split(\"#\")[0] ||\n \"url-upload\";\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: displayName,\n progress: 0,\n status: \"uploading\",\n });\n return next;\n });\n\n try {\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: displayName,\n progress: 25,\n status: \"uploading\",\n });\n return next;\n });\n\n let blob: Blob;\n let contentType: string;\n\n try {\n const response = await fetch(url, {\n mode: \"cors\",\n credentials: \"omit\",\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch file: ${response.statusText}`);\n }\n\n blob = await response.blob();\n contentType =\n response.headers.get(\"content-type\") || \"application/octet-stream\";\n } catch (fetchError) {\n const isCorsError =\n fetchError instanceof TypeError &&\n (fetchError.message.includes(\"CORS\") ||\n fetchError.message.includes(\"Failed to fetch\") ||\n fetchError.message.includes(\"NetworkError\"));\n\n if (isCorsError) {\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: displayName,\n progress: 30,\n status: \"uploading\",\n });\n return next;\n });\n\n try {\n const proxyResponse = await api.proxyUrlFetch(url);\n const binaryString = atob(proxyResponse.data);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n blob = new Blob([bytes], { type: proxyResponse.contentType });\n contentType = proxyResponse.contentType;\n } catch (proxyError) {\n let origin = url;\n try {\n origin = new URL(url).origin;\n } catch {\n // fallback to raw url\n }\n throw new Error(\n `CORS error: The server at ${origin} does not allow cross-origin requests, and the proxy also failed: ${\n proxyError instanceof Error\n ? proxyError.message\n : \"Unknown error\"\n }`,\n );\n }\n } else {\n throw fetchError;\n }\n }\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: displayName,\n progress: 50,\n status: \"uploading\",\n });\n return next;\n });\n const rawFileName = displayName;\n const finalFileName = sanitizeFilename(rawFileName);\n\n const file = new File([blob], finalFileName, { type: contentType });\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: finalFileName,\n progress: 75,\n status: \"uploading\",\n });\n return next;\n });\n\n const damResponse = await uploadMutation.mutateAsync({\n file,\n name: getSanitizedAssetName(finalFileName),\n description: `Uploaded from URL: ${url}`,\n companyId,\n });\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: finalFileName,\n progress: 100,\n status: \"ready\",\n });\n return next;\n });\n\n const asset = damResponse.asset;\n const fileUrl = getDamAssetUrl(asset, apiBaseUrl);\n\n return {\n asset_id: asset.id,\n asset_code: asset.code,\n file_path: fileUrl,\n file_url: fileUrl,\n metadata: {\n file_name: finalFileName,\n mime_type: contentType,\n file_size: blob.size,\n },\n upload_status: \"ready\",\n variant_id: asset.default_variant_id\n ? asset.default_variant_id.toString()\n : undefined,\n };\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Upload failed\";\n toast.error(errorMessage);\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(uploadId, {\n file_name: displayName,\n progress: 0,\n status: \"error\",\n error: errorMessage,\n });\n return next;\n });\n\n return {\n asset_id: 0,\n asset_code: \"\",\n file_path: \"\",\n file_url: \"\",\n metadata: {\n file_name: displayName,\n mime_type: \"\",\n },\n upload_status: \"error\",\n };\n }\n },\n [uploadMutation, companyId, apiBaseUrl, api, toast],\n );\n\n const clearProgress = useCallback(() => {\n setUploadProgress(new Map());\n }, []);\n\n return {\n uploadFromUrl,\n uploadProgress: Array.from(uploadProgress.values()),\n isUploading: uploadMutation.isPending,\n clearProgress,\n };\n};\n","import React, { useState } from \"react\";\nimport { Input, Switch, Button } from \"@fluid-app/ui-primitives\";\nimport {\n LinkIcon,\n CheckIcon,\n AlertTriangleIcon,\n LoaderIcon,\n FileIcon,\n ArrowRightIcon,\n} from \"lucide-react\";\nimport { useUrlUpload } from \"../hooks/use-url-upload\";\nimport {\n isFileTypeAccepted,\n getAcceptedTypesDescription,\n} from \"@fluid-app/file-picker-core\";\nimport type {\n FilePickerConfig,\n FilePickerResult,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\n\ninterface UrlUploadProps {\n config: FilePickerConfig;\n onFileSelected: (result: FilePickerResult) => void;\n enableShareableOption?: boolean;\n shareableEnabled?: boolean;\n onShareableChange?: (enabled: boolean) => void;\n /** When provided (e.g. FilePicker with selection panel), progress is only shown when there are selected files or an upload is in progress */\n selectedFilesCount?: number;\n}\n\nexport const UrlUpload: React.FC<UrlUploadProps> = ({\n config,\n onFileSelected,\n enableShareableOption = false,\n shareableEnabled = false,\n onShareableChange,\n selectedFilesCount,\n}) => {\n const { toast } = useFilePickerContext();\n const [url, setUrl] = useState(\"\");\n const [fileName, setFileName] = useState(\"\");\n const { uploadFromUrl, uploadProgress, isUploading, clearProgress } =\n useUrlUpload();\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!url.trim()) return;\n\n clearProgress();\n\n try {\n // Validate file type if restrictions are configured\n if (config.accept && config.accept.length > 0) {\n try {\n // Fetch the file to check its MIME type\n const response = await fetch(url.trim(), {\n method: \"HEAD\",\n mode: \"cors\",\n credentials: \"omit\",\n });\n const contentType = response.headers.get(\"content-type\") || \"\";\n const finalFileName =\n fileName.trim() || getFileNameFromUrl(url.trim());\n\n if (!isFileTypeAccepted(contentType, finalFileName, config.accept)) {\n const acceptedTypesDesc = getAcceptedTypesDescription(\n config.accept,\n );\n toast.error(\n `This file type is not allowed. Please upload ${acceptedTypesDesc.toLowerCase()}.`,\n );\n return;\n }\n } catch (error) {\n // If we can't check the file type due to CORS, proceed with upload\n // The server will handle validation, but warn the user about potential CORS issues\n if (\n error instanceof TypeError &&\n (error.message.includes(\"CORS\") ||\n error.message.includes(\"Failed to fetch\") ||\n error.message.includes(\"NetworkError\"))\n ) {\n // CORS error - we'll proceed but the actual upload might also fail\n // The uploadFromUrl function will handle the error more gracefully\n }\n // For other errors, proceed with upload - the server will handle validation\n }\n }\n\n const result = await uploadFromUrl(\n url.trim(),\n fileName.trim() || undefined,\n );\n\n // Only call onFileSelected if the upload was successful\n // If there's an error, the error will be shown in the progress section\n // and the modal should stay open so the user can see it\n if (result.upload_status === \"ready\") {\n onFileSelected(result);\n setUrl(\"\");\n setFileName(\"\");\n } else {\n // Explicitly do nothing on error - the error is already shown in progress\n // This ensures the modal stays open\n return;\n }\n } catch (error) {\n // Catch any unexpected errors to prevent the modal from closing\n // The error should already be handled by uploadFromUrl and shown in progress\n // This is just a safety net to ensure the modal stays open\n toast.error(error instanceof Error ? error.message : \"Unknown error\");\n }\n };\n\n const isValidUrl = (urlString: string): boolean => {\n try {\n new URL(urlString);\n return true;\n } catch {\n return false;\n }\n };\n\n const getFileNameFromUrl = (urlString: string): string => {\n try {\n const urlObj = new URL(urlString);\n const pathname = urlObj.pathname;\n const filename = pathname.split(\"/\").pop() || \"\";\n return filename.split(\"?\")[0] || \"\";\n } catch {\n return \"\";\n }\n };\n\n const handleUrlChange = (value: string) => {\n setUrl(value);\n if (value && isValidUrl(value) && !fileName) {\n const suggestedName = getFileNameFromUrl(value);\n if (suggestedName) {\n setFileName(suggestedName);\n }\n }\n };\n\n return (\n <div className=\"mx-auto max-w-5xl space-y-6 overflow-y-auto md:px-10 md:py-8\">\n {/* Enhanced header with better visual hierarchy */}\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100\">\n <LinkIcon className=\"h-6 w-6 text-blue-600\" />\n </div>\n <h2 className=\"text-xl font-semibold text-gray-900\">Upload from URL</h2>\n </div>\n\n {/* Enhanced form with better interaction design */}\n\n <form onSubmit={handleSubmit} className=\"mx-auto w-1/2 space-y-5\">\n <div className=\"flex gap-2\">\n <div className=\"relative flex-1\">\n <Input\n id=\"url\"\n type=\"url\"\n placeholder=\"https://example.com/image.jpg\"\n value={url}\n onChange={(e) => handleUrlChange(e.target.value)}\n disabled={isUploading}\n required\n className={`w-full pr-10 transition-all duration-200 ${\n url && !isValidUrl(url)\n ? \"border-red-300 bg-red-50/30 focus:border-red-500 focus:ring-red-500/20\"\n : \"focus:border-blue-500 focus:ring-blue-500/20\"\n }`}\n />\n {url && (\n <div className=\"absolute top-1/2 right-3 -translate-y-1/2\">\n {isValidUrl(url) ? (\n <div className=\"flex h-5 w-5 items-center justify-center rounded-full bg-green-100\">\n <CheckIcon className=\"h-3 w-3 text-green-600\" />\n </div>\n ) : (\n <div className=\"flex h-5 w-5 items-center justify-center rounded-full bg-red-100\">\n <AlertTriangleIcon className=\"h-3 w-3 text-red-600\" />\n </div>\n )}\n </div>\n )}\n </div>\n {url.trim() && isValidUrl(url) && (\n <Button variant=\"default\" type=\"submit\" disabled={isUploading}>\n {isUploading ? (\n <>\n <LoaderIcon className=\"h-3 w-3 animate-spin\" />\n </>\n ) : (\n <>\n <ArrowRightIcon className=\"h-3 w-3\" />\n </>\n )}\n </Button>\n )}\n </div>\n {url && !isValidUrl(url) && (\n <p className=\"text-xs text-red-600\">Please enter a valid URL</p>\n )}\n\n {/* Auto-suggest filename section */}\n {url && isValidUrl(url) && (\n <div className=\"space-y-2\">\n <label\n htmlFor=\"fileName\"\n className=\"flex items-center gap-2 text-sm font-medium text-gray-900\"\n >\n <FileIcon className=\"h-3.5 w-3.5 text-gray-400\" />\n File Name\n <span className=\"text-xs font-normal text-gray-500\">\n (optional)\n </span>\n </label>\n <Input\n id=\"fileName\"\n type=\"text\"\n placeholder={\n getFileNameFromUrl(url) ||\n \"Leave empty to use original filename\"\n }\n value={fileName}\n onChange={(e) => setFileName(e.target.value)}\n disabled={isUploading}\n className=\"w-full transition-all duration-200 focus:border-blue-500 focus:ring-blue-500/20\"\n />\n {getFileNameFromUrl(url) && !fileName && (\n <p className=\"text-xs text-gray-500\">\n Will use filename:{\" \"}\n <span className=\"font-medium\">{getFileNameFromUrl(url)}</span>\n </p>\n )}\n </div>\n )}\n </form>\n\n {/* Enhanced progress feedback */}\n {config.showProgress &&\n uploadProgress.length > 0 &&\n (selectedFilesCount === undefined ||\n selectedFilesCount > 0 ||\n isUploading) && (\n <div className=\"space-y-4\">\n {uploadProgress.map((progress, index) => (\n <div\n key={index}\n className=\"mx-auto w-1/2 overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm\"\n >\n <div className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div\n className={`flex h-10 w-10 items-center justify-center rounded-xl ${\n progress.status === \"ready\"\n ? \"bg-green-100\"\n : progress.status === \"error\"\n ? \"bg-red-100\"\n : \"bg-blue-100\"\n }`}\n >\n {(() => {\n const Icon =\n progress.status === \"ready\"\n ? CheckIcon\n : progress.status === \"error\"\n ? AlertTriangleIcon\n : LoaderIcon;\n return (\n <Icon\n className={`h-5 w-5 ${\n progress.status === \"ready\"\n ? \"text-green-600\"\n : progress.status === \"error\"\n ? \"text-red-600\"\n : \"animate-spin text-blue-600\"\n }`}\n />\n );\n })()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-gray-900\">\n {progress.file_name}\n </p>\n <div className=\"mt-1 flex items-center gap-2\">\n <p className=\"text-xs text-gray-500 capitalize\">\n {progress.status === \"uploading\"\n ? \"Uploading...\"\n : progress.status === \"ready\"\n ? \"Complete\"\n : progress.status}\n </p>\n {progress.status === \"uploading\" && (\n <span className=\"text-xs font-medium text-blue-600\">\n {progress.progress}%\n </span>\n )}\n </div>\n </div>\n </div>\n\n {progress.status === \"uploading\" && (\n <div className=\"mt-3\">\n <div className=\"h-2 w-full overflow-hidden rounded-full bg-gray-100\">\n <div\n className=\"h-2 rounded-full bg-linear-to-r from-blue-500 to-blue-600 transition-all duration-500 ease-out\"\n style={{ width: `${progress.progress}%` }}\n />\n </div>\n </div>\n )}\n\n {progress.error && (\n <div className=\"mt-3 rounded-lg bg-red-50 p-3\">\n <p className=\"text-sm text-red-700\">{progress.error}</p>\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Footer with Shareable Option */}\n {enableShareableOption && (\n <div className=\"mx-auto flex w-1/2 items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Switch\n checked={shareableEnabled}\n onCheckedChange={onShareableChange}\n id=\"shareable-toggle-url\"\n />\n <label\n htmlFor=\"shareable-toggle-url\"\n className=\"text-sm text-gray-700\"\n >\n Create as shareable media\n </label>\n </div>\n </div>\n )}\n </div>\n );\n};\n","import { useState, useCallback } from \"react\";\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport {\n damQueryKeys,\n getDamAssetUrl,\n getSanitizedAssetName,\n getFileMimeType,\n type CreateDamAssetParams,\n type FilePickerResult,\n type UploadProgress,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerApi } from \"../context/FilePickerApiContext\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\n\nexport const useComputerUpload = (): {\n uploadFiles: (files: File[]) => Promise<FilePickerResult[]>;\n uploadProgress: UploadProgress[];\n isUploading: boolean;\n clearProgress: () => void;\n} => {\n const [uploadProgress, setUploadProgress] = useState<\n Map<string, UploadProgress>\n >(new Map());\n const queryClient = useQueryClient();\n const api = useFilePickerApi();\n const { companyId, toast, apiBaseUrl } = useFilePickerContext();\n\n const uploadMutation = useMutation({\n mutationFn: (params: CreateDamAssetParams) => api.createDamAsset(params),\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: damQueryKeys.all });\n },\n });\n\n const uploadFiles = useCallback(\n async (files: File[]): Promise<FilePickerResult[]> => {\n const results: FilePickerResult[] = [];\n\n for (const file of files) {\n const fileId = `${file.name}-${Date.now()}`;\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(fileId, {\n file_name: file.name,\n progress: 0,\n status: \"uploading\",\n });\n return next;\n });\n\n try {\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(fileId, {\n file_name: file.name,\n progress: 50,\n status: \"uploading\",\n });\n return next;\n });\n\n const response = await uploadMutation.mutateAsync({\n file,\n name: getSanitizedAssetName(file.name),\n description: `Uploaded via FilePicker: ${file.name}`,\n companyId,\n });\n\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(fileId, {\n file_name: file.name,\n progress: 100,\n status: \"ready\",\n });\n return next;\n });\n\n const asset = response.asset;\n const fileUrl = getDamAssetUrl(asset, apiBaseUrl);\n\n results.push({\n asset_id: asset.id,\n asset_code: asset.code,\n file_path: fileUrl,\n file_url: fileUrl,\n metadata: {\n file_name: file.name,\n mime_type: getFileMimeType(file),\n file_size: file.size,\n },\n upload_status: \"ready\",\n variant_id: asset.default_variant_id\n ? asset.default_variant_id.toString()\n : undefined,\n });\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : \"Upload failed\";\n const status =\n error instanceof Error && \"status\" in error\n ? (error as { status: number }).status\n : undefined;\n const isFileSizeError =\n status === 413 ||\n (status === 400 &&\n errorMessage.toLowerCase().includes(\"file size\"));\n if (isFileSizeError) {\n toast.error(\n \"File size too large: Please compress or choose another file\",\n );\n } else {\n toast.error(errorMessage);\n }\n setUploadProgress((prev) => {\n const next = new Map(prev);\n next.set(fileId, {\n file_name: file.name,\n progress: 0,\n status: \"error\",\n error: errorMessage,\n });\n return next;\n });\n\n results.push({\n asset_id: 0,\n asset_code: \"\",\n file_path: \"\",\n file_url: \"\",\n metadata: {\n file_name: file.name,\n mime_type: getFileMimeType(file),\n file_size: file.size,\n },\n upload_status: \"error\",\n });\n }\n }\n\n return results;\n },\n [uploadMutation, companyId, toast, apiBaseUrl],\n );\n\n const clearProgress = useCallback(() => {\n setUploadProgress(new Map());\n }, []);\n\n return {\n uploadFiles,\n uploadProgress: Array.from(uploadProgress.values()),\n isUploading: uploadMutation.isPending,\n clearProgress,\n };\n};\n","import React, {\n useState,\n useRef,\n useCallback,\n useEffect,\n useMemo,\n} from \"react\";\nimport ReactCrop, { type Crop, type PixelCrop } from \"react-image-crop\";\nimport \"react-image-crop/dist/ReactCrop.css\";\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogTitle,\n Slider,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport {\n MoveHorizontalIcon,\n RotateCwIcon,\n ChevronDownIcon,\n MinusIcon,\n PlusIcon,\n} from \"lucide-react\";\nimport type {\n ImageCropModalProps,\n AspectValue,\n} from \"@fluid-app/file-picker-core\";\nimport {\n ASPECT_OPTIONS,\n ROTATION_MIN,\n ROTATION_MAX,\n computeInitialCrop,\n getCroppedImgFromViewport,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\n\nexport const ImageCropModal: React.FC<ImageCropModalProps> = ({\n isOpen,\n onClose,\n onCrop,\n imageFile,\n aspectRatio: aspectRatioProp,\n minWidth = 50,\n minHeight = 50,\n maxWidth = 2000,\n maxHeight = 2000,\n}) => {\n const { toast } = useFilePickerContext();\n const [crop, setCrop] = useState<Crop>();\n const [completedCrop, setCompletedCrop] = useState<PixelCrop>();\n const [imgSrc, setImgSrc] = useState<string>(\"\");\n const [isProcessing, setIsProcessing] = useState(false);\n const [aspectOption, setAspectOption] = useState<AspectValue>(\n aspectRatioProp ?? \"free\",\n );\n const [rotation, setRotation] = useState(0);\n const [flipHorizontal, setFlipHorizontal] = useState(false);\n const [zoom, setZoom] = useState(1);\n const [cropModified, setCropModified] = useState(false);\n const [cropViewportWidthPx, setCropViewportWidthPx] = useState<number | null>(\n null,\n );\n const imgRef = useRef<HTMLImageElement>(null);\n const cropContainerRef = useRef<HTMLDivElement>(null);\n const cropWrapperRef = useRef<HTMLDivElement>(null);\n\n const effectiveAspect = aspectOption === \"free\" ? undefined : aspectOption;\n\n const outputDimensions = useMemo(() => {\n const img = imgRef.current;\n if (!completedCrop || !img) return null;\n const nw = img.naturalWidth;\n const nh = img.naturalHeight;\n const vw = img.clientWidth;\n const vh = img.clientHeight;\n if (!vw || !vh) return null;\n const upscale = Math.max(nw / vw, nh / vh);\n return {\n width: Math.floor(completedCrop.width * upscale),\n height: Math.floor(completedCrop.height * upscale),\n };\n }, [completedCrop]);\n\n const initialAspect = aspectRatioProp ?? \"free\";\n const hasChanges =\n rotation !== 0 ||\n flipHorizontal !== false ||\n zoom !== 1 ||\n aspectOption !== initialAspect ||\n cropModified;\n\n useEffect(() => {\n if (isOpen && imageFile) {\n const reader = new FileReader();\n reader.addEventListener(\"load\", () => {\n setImgSrc(reader.result as string);\n });\n reader.readAsDataURL(imageFile);\n }\n if (!isOpen) {\n setRotation(0);\n setFlipHorizontal(false);\n setZoom(1);\n setCropModified(false);\n setCropViewportWidthPx(null);\n setAspectOption(aspectRatioProp ?? \"free\");\n }\n }, [isOpen, imageFile, aspectRatioProp]);\n\n /** Apply crop + completedCrop for given aspect, reading container dimensions. */\n const applyCropForAspect = useCallback((aspect: number | undefined) => {\n const img = imgRef.current;\n if (!img) return;\n const { crop: newCrop, completedCrop: newCompleted } = computeInitialCrop(\n img.clientWidth,\n img.clientHeight,\n aspect,\n );\n setCrop(newCrop);\n setTimeout(() => setCompletedCrop(newCompleted), 0);\n }, []);\n\n const onImageLoad = useCallback(() => {\n if (!imgRef.current) return;\n applyCropForAspect(effectiveAspect);\n }, [effectiveAspect, applyCropForAspect]);\n\n const handleCrop = async () => {\n if (!imgRef.current) return;\n setIsProcessing(true);\n try {\n const vw = imgRef.current.clientWidth;\n const vh = imgRef.current.clientHeight;\n\n let px: number, py: number, pw: number, ph: number;\n if (completedCrop) {\n px = completedCrop.x;\n py = completedCrop.y;\n pw = completedCrop.width;\n ph = completedCrop.height;\n } else if (crop) {\n if (crop.unit === \"%\") {\n px = (crop.x / 100) * vw;\n py = (crop.y / 100) * vh;\n pw = (crop.width / 100) * vw;\n ph = (crop.height / 100) * vh;\n } else {\n px = (crop as PixelCrop).x;\n py = (crop as PixelCrop).y;\n pw = (crop as PixelCrop).width;\n ph = (crop as PixelCrop).height;\n }\n } else {\n px = 0;\n py = 0;\n pw = vw;\n ph = vh;\n }\n\n // Use viewport-based export so rotation, flip, and zoom match the preview.\n // Pass sourceFile so the bitmap is decoded at full resolution from the\n // original bytes, not from the <img> element (which the browser may have\n // decoded at a reduced resolution due to its small CSS display size).\n const croppedFile = await getCroppedImgFromViewport(\n imgRef.current,\n vw,\n vh,\n { x: px, y: py, width: pw, height: ph },\n zoom,\n rotation,\n flipHorizontal,\n imageFile.name,\n imageFile.type,\n 1,\n imageFile,\n );\n await Promise.resolve(onCrop(croppedFile));\n onClose();\n } catch (error) {\n toast.error(\n error instanceof Error ? error.message : \"Failed to crop image\",\n );\n } finally {\n setIsProcessing(false);\n }\n };\n\n const resetCrop = () => {\n setRotation(0);\n setFlipHorizontal(false);\n setZoom(1);\n setCropModified(false);\n setAspectOption(aspectRatioProp ?? \"free\");\n applyCropForAspect(aspectRatioProp ?? undefined);\n };\n\n const aspectLabel =\n ASPECT_OPTIONS.find(\n (o) =>\n o.value === aspectOption ||\n (typeof o.value === \"number\" && o.value === aspectOption),\n )?.label ?? \"Free\";\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()} modal>\n <DialogContent\n overlayClassName=\"bg-gray-500/75\"\n showCloseButton={false}\n className=\"border-border text-foreground z-400 flex h-[90vh]! w-[95vw]! max-w-[1600px]! flex-col overflow-auto border bg-white p-0\"\n >\n <DialogTitle className=\"sr-only\">Crop Image</DialogTitle>\n <div className=\"bg-muted/30 flex shrink-0 flex-wrap items-center justify-center gap-2 px-4 py-2\">\n <DropdownMenu>\n <DropdownMenuTrigger className=\"inline-flex items-center gap-1 rounded-md border border-gray-200 bg-white px-3 py-1.5 text-sm text-gray-700 shadow-sm transition-colors hover:bg-gray-50\">\n {aspectLabel}\n <ChevronDownIcon className=\"h-3 w-3\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"z-410\">\n {ASPECT_OPTIONS.map((opt) => (\n <DropdownMenuItem\n key={String(opt.value)}\n onClick={() => {\n setAspectOption(opt.value);\n applyCropForAspect(\n opt.value === \"free\" ? undefined : opt.value,\n );\n }}\n >\n {opt.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n type=\"button\"\n onClick={() => setFlipHorizontal((f) => !f)}\n aria-label=\"Flip horizontal\"\n className=\"gap-1 bg-transparent\"\n >\n <MoveHorizontalIcon className=\"h-4 w-4\" />\n <span className=\"text-xs\">Flip</span>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n type=\"button\"\n onClick={() => {\n setRotation((r) => {\n const next = r + 90;\n if (next > ROTATION_MAX) return next - 360;\n if (next < ROTATION_MIN) return next + 360;\n return next;\n });\n }}\n aria-label=\"Rotate 90deg\"\n className=\"gap-1 bg-transparent\"\n >\n <RotateCwIcon className=\"h-4 w-4\" />\n <span className=\"text-xs\">Rotate</span>\n </Button>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n onClick={() =>\n setZoom((z) => Math.max(0.5, Math.round((z - 0.1) * 10) / 10))\n }\n className=\"bg-transparent\"\n aria-label=\"Zoom out\"\n >\n <MinusIcon className=\"h-3 w-3\" />\n </Button>\n <Slider\n min={0.5}\n max={2}\n step={0.1}\n value={[zoom]}\n onValueChange={([value]) => {\n if (value !== undefined) setZoom(value);\n }}\n className=\"accent-contrast h-2 w-24 shrink-0\"\n aria-label=\"Zoom\"\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n type=\"button\"\n onClick={() =>\n setZoom((z) => Math.min(2, Math.round((z + 0.1) * 10) / 10))\n }\n className=\"bg-transparent\"\n aria-label=\"Zoom in\"\n >\n <PlusIcon className=\"h-3 w-3\" />\n </Button>\n <span\n className=\"text-muted-foreground min-w-10 text-xs\"\n aria-hidden\n >\n {Math.round(zoom * 100)}%\n </span>\n </div>\n </div>\n\n <div className=\"relative flex w-full flex-1 items-center justify-center overflow-auto p-4\">\n {imgSrc && (\n <div\n ref={cropWrapperRef}\n className=\"mx-auto\"\n style={{\n width:\n cropViewportWidthPx != null\n ? `${cropViewportWidthPx}px`\n : \"100%\",\n }}\n >\n <div\n ref={cropContainerRef}\n className=\"image-crop-modal-crop [&_.ReactCrop__crop-selection]:border-contrast [&_.ReactCrop__rule]:border-border flex w-full items-center justify-center [&_.ReactCrop__crop-selection]:border-2 [&_.ReactCrop__crop-selection]:border-dashed [&_.ReactCrop__crop-selection]:shadow-[0_0_0_9999px_rgba(0,0,0,0.4)]\"\n >\n <ReactCrop\n crop={crop}\n onChange={(pixelCrop, percentCrop) => {\n setCrop(percentCrop);\n setCompletedCrop(pixelCrop);\n setCropModified(true);\n }}\n onComplete={(c) => setCompletedCrop(c)}\n aspect={effectiveAspect}\n minWidth={minWidth}\n minHeight={minHeight}\n maxWidth={maxWidth}\n maxHeight={maxHeight}\n >\n <img\n ref={imgRef}\n alt=\"Crop\"\n src={imgSrc}\n className=\"block max-h-full max-w-full object-contain sm:h-[300px] xl:h-[500px]\"\n style={{\n transform: [\n `rotate(${rotation}deg)`,\n `scale(${zoom})`,\n flipHorizontal ? \"scaleX(-1)\" : null,\n ]\n .filter(Boolean)\n .join(\" \"),\n transformOrigin: \"center center\",\n }}\n onLoad={onImageLoad}\n />\n </ReactCrop>\n </div>\n </div>\n )}\n </div>\n\n <div className=\"bg-muted/30 flex shrink-0 flex-col gap-3 px-4 py-3\">\n <div className=\"flex justify-center\">\n <span className=\"text-muted-foreground text-xs\" aria-hidden>\n {outputDimensions\n ? `${outputDimensions.width} x ${outputDimensions.height} px · ${rotation}deg`\n : `${rotation}deg`}\n </span>\n </div>\n <div className=\"flex items-center justify-end gap-2\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={resetCrop}\n disabled={isProcessing || !hasChanges}\n className=\"border-0 shadow-none\"\n >\n Reset to Default\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={onClose}\n disabled={isProcessing}\n className=\"border-0 shadow-none\"\n >\n Cancel\n </Button>\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={handleCrop}\n disabled={!crop || isProcessing}\n className=\"border-0\"\n >\n {isProcessing ? \"Processing...\" : \"Apply Crop\"}\n </Button>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n );\n};\n","import React, { useCallback, useState } from \"react\";\nimport { useDropzone, type FileRejection } from \"react-dropzone\";\nimport { Button, Card, CardContent, Switch } from \"@fluid-app/ui-primitives\";\nimport {\n CheckIcon,\n AlertTriangleIcon,\n LoaderIcon,\n ArrowUpIcon,\n} from \"lucide-react\";\nimport { useComputerUpload } from \"../hooks/use-computer-upload\";\nimport { ImageCropModal } from \"./ImageCropModal\";\nimport { getFileMimeType } from \"@fluid-app/file-picker-core\";\nimport type {\n FilePickerConfig,\n FilePickerResult,\n} from \"@fluid-app/file-picker-core\";\nimport { useFilePickerContext } from \"../context/FilePickerContext\";\n\nfunction formatFileSize(bytes: number): string {\n if (bytes === 0) return \"0 Bytes\";\n const k = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + \" \" + sizes[i];\n}\n\ninterface ComputerUploadProps {\n config: FilePickerConfig;\n onFilesSelected: (results: FilePickerResult[]) => void;\n enableShareableOption?: boolean;\n shareableEnabled?: boolean;\n onShareableChange?: (enabled: boolean) => void;\n skipCropper?: boolean;\n selectedFilesCount?: number;\n}\n\nexport const ComputerUpload: React.FC<ComputerUploadProps> = ({\n config,\n onFilesSelected,\n enableShareableOption = false,\n shareableEnabled = false,\n onShareableChange,\n skipCropper = false,\n selectedFilesCount,\n}) => {\n const { toast } = useFilePickerContext();\n const { uploadFiles, uploadProgress, isUploading, clearProgress } =\n useComputerUpload();\n const [dragActive, setDragActive] = useState(false);\n const [cropModalOpen, setCropModalOpen] = useState(false);\n const [pendingImageFile, setPendingImageFile] = useState<File | null>(null);\n const [pendingFiles, setPendingFiles] = useState<File[]>([]);\n\n const handleDrop = useCallback(\n async (acceptedFiles: File[]) => {\n setDragActive(false);\n clearProgress();\n\n const filesToUpload = config.maxFiles\n ? acceptedFiles.slice(0, config.maxFiles)\n : acceptedFiles;\n\n // Check if any files are images that can be cropped\n // HEIC/HEIF are excluded because <canvas> cannot render them natively\n const UNCROPABLE_TYPES = [\n \"image/heic\",\n \"image/heic-sequence\",\n \"image/heif\",\n \"image/svg+xml\",\n ];\n const isCropableImage = (file: File) => {\n const mime = getFileMimeType(file);\n return mime.startsWith(\"image/\") && !UNCROPABLE_TYPES.includes(mime);\n };\n const imageFiles = filesToUpload.filter(isCropableImage);\n const nonImageFiles = filesToUpload.filter((f) => !isCropableImage(f));\n\n if (imageFiles.length === 1 && !skipCropper) {\n // Only show crop tool for single image uploads\n // Store non-image files for later upload\n setPendingFiles(nonImageFiles);\n // Open crop modal for the single image\n setPendingImageFile(imageFiles[0] || null);\n setCropModalOpen(true);\n } else {\n // Multiple files or no images to crop or cropper is disabled, upload directly\n const results = await uploadFiles(filesToUpload);\n onFilesSelected(results);\n }\n },\n [uploadFiles, onFilesSelected, config.maxFiles, clearProgress, skipCropper],\n );\n\n const handleCropComplete = useCallback(\n async (croppedFile: File) => {\n setCropModalOpen(false);\n\n // Combine cropped file with any pending non-image files\n const allFiles = [croppedFile, ...pendingFiles];\n const results = await uploadFiles(allFiles);\n onFilesSelected(results);\n\n // Reset state\n setPendingImageFile(null);\n setPendingFiles([]);\n },\n [uploadFiles, onFilesSelected, pendingFiles],\n );\n\n const handleCropCancel = useCallback(() => {\n setCropModalOpen(false);\n setPendingImageFile(null);\n\n // Upload non-image files without cropping\n if (pendingFiles.length > 0) {\n uploadFiles(pendingFiles).then(onFilesSelected);\n }\n setPendingFiles([]);\n }, [uploadFiles, onFilesSelected, pendingFiles]);\n\n const handleDropRejected = useCallback(\n (fileRejections: FileRejection[]) => {\n fileRejections.forEach(({ file, errors }) => {\n errors.forEach((error) => {\n if (error.code === \"file-too-large\") {\n toast.error(\n `File size too large: \"${file.name}\" (${formatFileSize(file.size)}) exceeds the maximum allowed size.`,\n );\n } else if (error.code === \"file-invalid-type\") {\n toast.error(\n `Invalid file type: \"${file.name}\" is not an accepted file type.`,\n );\n } else if (error.code === \"too-many-files\") {\n toast.error(\n `Too many files: You can only upload ${config.maxFiles} file${config.maxFiles === 1 ? \"\" : \"s\"} at a time.`,\n );\n } else {\n toast.error(error.message);\n }\n });\n });\n },\n [config.maxFiles, toast],\n );\n\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\n onDrop: handleDrop,\n onDropRejected: (fileRejections: FileRejection[]) =>\n handleDropRejected(fileRejections),\n accept: config.accept\n ? config.accept.reduce(\n (acc, type) => {\n // Handle both MIME types (e.g., \"image/*\") and file extensions (e.g., \".jpg\")\n if (type.startsWith(\".\")) {\n // File extension - add to a generic MIME type\n acc[\"*/*\"] = acc[\"*/*\"] || [];\n acc[\"*/*\"].push(type);\n } else {\n // MIME type - add as is\n acc[type] = [];\n }\n return acc;\n },\n {} as Record<string, string[]>,\n )\n : undefined,\n maxSize: config.maxSize,\n maxFiles: config.maxFiles,\n onDragEnter: () => setDragActive(true),\n onDragLeave: () => setDragActive(false),\n });\n\n return (\n <div className=\"mx-auto max-w-7xl space-y-6 overflow-y-auto md:px-10 md:py-8\">\n {/* Enhanced dropzone card */}\n <Card className=\"mx-auto w-1/2 border-none shadow-none\">\n <CardContent className=\"p-6\">\n <div\n {...getRootProps()}\n className={`group cursor-pointer rounded-lg border-2 border-dashed p-8 text-center transition-all duration-200 ${\n isDragActive || dragActive\n ? \"scale-[1.02] border-blue-500 bg-blue-50/50\"\n : \"border-gray-300 hover:border-blue-400 hover:bg-blue-50/20\"\n } ${isUploading ? \"pointer-events-none opacity-50\" : \"\"}`}\n >\n <input {...getInputProps()} />\n <div className=\"space-y-4\">\n {/* Header with icon moved inside dropzone */}\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-gray-100 group-hover:bg-blue-200\">\n <ArrowUpIcon className=\"h-10 w-10 text-gray-600 group-hover:text-blue-500\" />\n </div>\n </div>\n\n {/* File constraints */}\n <p className=\"text-center text-xs text-gray-500\">\n 50MB for Images and Documents. 2GB for Videos.\n </p>\n\n <Button\n variant=\"default\"\n disabled={isUploading}\n className=\"transition-all duration-200\"\n >\n {isUploading ? (\n <>\n <LoaderIcon className=\"mr-2 h-4 w-4 animate-spin\" />\n Uploading...\n </>\n ) : (\n \"Choose Files\"\n )}\n </Button>\n </div>\n </div>\n </CardContent>\n </Card>\n\n {/* Enhanced progress feedback */}\n {config.showProgress &&\n uploadProgress.length > 0 &&\n (selectedFilesCount === undefined ||\n selectedFilesCount > 0 ||\n isUploading) && (\n <div className=\"space-y-4\">\n {uploadProgress.map((progress) => (\n <div\n key={`${progress.file_name}-${progress.status}`}\n className=\"mx-auto w-1/2 overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm\"\n >\n <div className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div\n className={`flex h-10 w-10 items-center justify-center rounded-xl ${\n progress.status === \"ready\"\n ? \"bg-green-100\"\n : progress.status === \"error\"\n ? \"bg-red-100\"\n : \"bg-blue-100\"\n }`}\n >\n {(() => {\n const Icon =\n progress.status === \"ready\"\n ? CheckIcon\n : progress.status === \"error\"\n ? AlertTriangleIcon\n : LoaderIcon;\n return (\n <Icon\n className={`h-5 w-5 ${\n progress.status === \"ready\"\n ? \"text-green-600\"\n : progress.status === \"error\"\n ? \"text-red-600\"\n : \"animate-spin text-blue-600\"\n }`}\n />\n );\n })()}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-gray-900\">\n {progress.file_name}\n </p>\n <div className=\"mt-1 flex items-center gap-2\">\n <p className=\"text-xs text-gray-500 capitalize\">\n {progress.status === \"uploading\"\n ? \"Uploading...\"\n : progress.status === \"ready\"\n ? \"Complete\"\n : progress.status}\n </p>\n {progress.status === \"uploading\" && (\n <span className=\"text-xs font-medium text-blue-600\">\n {progress.progress}%\n </span>\n )}\n </div>\n </div>\n </div>\n\n {progress.status === \"uploading\" && (\n <div className=\"mt-3\">\n <div className=\"h-2 w-full overflow-hidden rounded-full bg-gray-100\">\n <div\n className=\"h-2 rounded-full bg-linear-to-r from-blue-500 to-blue-600 transition-all duration-500 ease-out\"\n style={{ width: `${progress.progress}%` }}\n />\n </div>\n </div>\n )}\n\n {progress.error && (\n <div className=\"mt-3 rounded-lg bg-red-50 p-3\">\n <p className=\"text-sm text-red-700\">{progress.error}</p>\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Footer with Shareable Option */}\n {enableShareableOption && (\n <div className=\"mx-auto flex w-1/2 items-center justify-between px-4\">\n <div className=\"flex items-center gap-2\">\n <Switch\n checked={shareableEnabled}\n onCheckedChange={onShareableChange}\n id=\"shareable-toggle-computer\"\n />\n <label\n htmlFor=\"shareable-toggle-computer\"\n className=\"text-sm text-gray-700\"\n >\n Create as shareable media\n </label>\n </div>\n </div>\n )}\n\n {/* Image Crop Modal */}\n {pendingImageFile && (\n <ImageCropModal\n isOpen={cropModalOpen}\n onClose={handleCropCancel}\n onCrop={handleCropComplete}\n imageFile={pendingImageFile}\n minWidth={50}\n minHeight={50}\n maxWidth={2000}\n maxHeight={2000}\n />\n )}\n </div>\n );\n};\n","import React from \"react\";\nimport {\n GoogleIcon,\n InstagramIcon,\n FacebookIcon,\n TiktokIcon,\n DropboxIcon,\n} from \"../utils/brand-icons\";\nimport { DamLibrary, type DamLibraryRef } from \"./DamLibrary\";\nimport { MediaTab } from \"./MediaTab\";\nimport { UnsplashPicker } from \"./UnsplashPicker\";\nimport type {\n FilePickerConfig,\n FilePickerResult,\n UploadMethod,\n DamAsset,\n} from \"@fluid-app/file-picker-core\";\nimport type { ViewMode } from \"./FilePickerHeader\";\nimport type { SortOptionId } from \"@fluid-app/file-picker-core\";\nimport { UrlUpload } from \"./UrlUpload\";\nimport { ComputerUpload } from \"./ComputerUpload\";\nimport type { MediumResponse } from \"../types/media\";\n\nexport type { MediumResponse };\n\ninterface FilePickerContentProps {\n activeMethod: UploadMethod;\n config: FilePickerConfig;\n damTypeFilter?: string;\n sortOption?: SortOptionId;\n onFilesSelected: (results: FilePickerResult[]) => void;\n onUploadConfirmAndMaybeCreate: (results: FilePickerResult[]) => void;\n onSingleFileSelected: (result: FilePickerResult) => void;\n enableShareableOption?: boolean;\n shareableEnabled?: boolean;\n onShareableChange?: (enabled: boolean) => void;\n damLibraryRef: React.RefObject<DamLibraryRef | null>;\n onDamConfirmAndMaybeCreate: (results: FilePickerResult[]) => void;\n selectedMediaIds: number[];\n onMediaIdsChange: (ids: number[]) => void;\n onMediaSelectionChange: (count: number) => void;\n onMediaDataChange: (data: FilePickerResult[]) => void;\n onDamSelectionChange: (\n count: number,\n files?: FilePickerResult[],\n variantCounts?: Record<string, number>,\n ) => void;\n onDamSearchingChange?: (searching: boolean) => void;\n skipCropper?: boolean;\n damSearchQuery?: string;\n onDamSearchChange?: (value: string) => void;\n mediaSearchQuery?: string;\n onMediaSearchChange?: (value: string) => void;\n unsplashSearchQuery?: string;\n onUnsplashSearchChange?: (value: string) => void;\n onUnsplashSearchingChange?: (searching: boolean) => void;\n onUnsplashUploadingChange?: (uploading: boolean) => void;\n thumbnailSize?: number;\n viewMode?: ViewMode;\n showNamesOnMedia?: boolean;\n onDamFoldersChange?: (folders: string[]) => void;\n previewContainer?: HTMLDivElement | null;\n previewMedia?: MediumResponse | null;\n onPreviewMediaChange?: (media: MediumResponse | null) => void;\n previewAsset?: DamAsset | null;\n onPreviewAssetChange?: (asset: DamAsset | null) => void;\n uploadSelectionCount?: number;\n}\n\nexport const FilePickerContent: React.FC<FilePickerContentProps> = ({\n activeMethod,\n config,\n damTypeFilter,\n sortOption,\n onFilesSelected,\n onSingleFileSelected,\n enableShareableOption,\n shareableEnabled,\n onShareableChange,\n damLibraryRef,\n onDamConfirmAndMaybeCreate,\n selectedMediaIds,\n onMediaIdsChange,\n onMediaSelectionChange,\n onMediaDataChange,\n onDamSelectionChange,\n onDamSearchingChange,\n skipCropper = false,\n damSearchQuery = \"\",\n onDamSearchChange,\n mediaSearchQuery,\n onMediaSearchChange,\n unsplashSearchQuery,\n onUnsplashSearchChange,\n onUnsplashSearchingChange,\n onUnsplashUploadingChange,\n thumbnailSize = 100,\n viewMode = \"grid\",\n showNamesOnMedia = true,\n onDamFoldersChange,\n previewContainer,\n previewMedia,\n onPreviewMediaChange,\n previewAsset,\n onPreviewAssetChange,\n uploadSelectionCount,\n}) => {\n const damConfig = React.useMemo(\n () => ({\n ...config,\n fileTypeFilter: damTypeFilter ? [damTypeFilter] : config.fileTypeFilter,\n }),\n [config, damTypeFilter],\n );\n return (\n <div className=\"flex-1 overflow-x-hidden overflow-y-auto p-6\">\n {(activeMethod === \"upload\" || activeMethod === \"computer\") && (\n <ComputerUpload\n config={config}\n onFilesSelected={onFilesSelected}\n enableShareableOption={enableShareableOption}\n shareableEnabled={shareableEnabled}\n onShareableChange={onShareableChange}\n skipCropper={skipCropper}\n selectedFilesCount={uploadSelectionCount}\n />\n )}\n {activeMethod === \"url\" && (\n <UrlUpload\n config={config}\n onFileSelected={onSingleFileSelected}\n enableShareableOption={enableShareableOption}\n shareableEnabled={shareableEnabled}\n onShareableChange={onShareableChange}\n selectedFilesCount={uploadSelectionCount}\n />\n )}\n\n {activeMethod === (\"dam\" as UploadMethod) && (\n <DamLibrary\n ref={damLibraryRef}\n config={damConfig}\n sortOption={sortOption}\n onFoldersChange={onDamFoldersChange}\n onAssetsSelected={onFilesSelected}\n onSelectionChange={onDamSelectionChange}\n onConfirmAndClose={(results) => {\n void onDamConfirmAndMaybeCreate(results);\n }}\n onSearchingChange={onDamSearchingChange}\n showVariants={config.showVariants}\n searchQuery={damSearchQuery}\n onSearchChange={onDamSearchChange}\n thumbnailSize={thumbnailSize}\n viewMode={viewMode}\n showNamesOnMedia={showNamesOnMedia}\n previewContainer={previewContainer}\n previewAsset={previewAsset}\n onPreviewAssetChange={onPreviewAssetChange}\n />\n )}\n\n {activeMethod === (\"media\" as UploadMethod) && (\n <MediaTab\n config={config}\n onMediaSelected={() => {}} // Not used for media tab\n onSelectionChange={onMediaSelectionChange}\n onMediaDataChange={onMediaDataChange}\n selectedMediaIds={selectedMediaIds}\n onMediaIdsChange={onMediaIdsChange}\n searchQuery={mediaSearchQuery}\n onSearchChange={onMediaSearchChange}\n thumbnailSize={thumbnailSize}\n viewMode={viewMode}\n showNamesOnMedia={showNamesOnMedia}\n mediaTypeFilter={damTypeFilter}\n sortOption={sortOption}\n previewContainer={previewContainer}\n previewMedia={previewMedia}\n onPreviewMediaChange={onPreviewMediaChange}\n />\n )}\n\n {activeMethod === \"unsplash\" && (\n <UnsplashPicker\n config={config}\n onFileSelected={onSingleFileSelected}\n searchQuery={unsplashSearchQuery}\n onSearchQueryChange={onUnsplashSearchChange}\n onSearchingChange={onUnsplashSearchingChange}\n onUploadingChange={onUnsplashUploadingChange}\n />\n )}\n\n {activeMethod === \"google-drive\" && (\n <div className=\"mx-auto max-w-7xl space-y-6 md:px-10 md:py-8\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-linear-to-br from-blue-50 to-indigo-50 ring-4 ring-blue-50/50\">\n <GoogleIcon className=\"h-6 w-6 text-blue-600\" />\n </div>\n <h2 className=\"text-xl font-semibold text-gray-900\">\n Import from Google Drive\n </h2>\n <p className=\"mt-2 text-sm text-gray-600\">\n Connect your Google Drive account to import files\n </p>\n </div>\n <div className=\"rounded-lg border-2 border-dashed border-gray-300 p-8 text-center\">\n <p className=\"text-gray-500\">\n Google Drive integration coming soon...\n </p>\n </div>\n </div>\n )}\n\n {activeMethod === \"instagram\" && (\n <div className=\"mx-auto max-w-7xl space-y-6 md:px-10 md:py-8\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-linear-to-br from-pink-50 to-purple-50 ring-4 ring-pink-50/50\">\n <InstagramIcon className=\"h-6 w-6 text-pink-600\" />\n </div>\n <h2 className=\"text-xl font-semibold text-gray-900\">\n Import from Instagram\n </h2>\n <p className=\"mt-2 text-sm text-gray-600\">\n Connect your Instagram account to import your posts\n </p>\n </div>\n <div className=\"rounded-lg border-2 border-dashed border-gray-300 p-8 text-center\">\n <p className=\"text-gray-500\">\n Instagram integration coming soon...\n </p>\n </div>\n </div>\n )}\n\n {activeMethod === \"facebook\" && (\n <div className=\"mx-auto max-w-7xl space-y-6 md:px-10 md:py-8\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-linear-to-br from-blue-50 to-indigo-50 ring-4 ring-blue-50/50\">\n <FacebookIcon className=\"h-6 w-6 text-blue-600\" />\n </div>\n <h2 className=\"text-xl font-semibold text-gray-900\">\n Import from Facebook\n </h2>\n <p className=\"mt-2 text-sm text-gray-600\">\n Connect your Facebook account to import your photos\n </p>\n </div>\n <div className=\"rounded-lg border-2 border-dashed border-gray-300 p-8 text-center\">\n <p className=\"text-gray-500\">Facebook integration coming soon...</p>\n </div>\n </div>\n )}\n\n {activeMethod === \"tiktok\" && (\n <div className=\"mx-auto max-w-7xl space-y-6 md:px-10 md:py-8\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-linear-to-br from-gray-50 to-gray-100 ring-4 ring-gray-50/50\">\n <TiktokIcon className=\"h-6 w-6 text-gray-900\" />\n </div>\n <h2 className=\"text-xl font-semibold text-gray-900\">\n Import from TikTok\n </h2>\n <p className=\"mt-2 text-sm text-gray-600\">\n Connect your TikTok account to import your videos\n </p>\n </div>\n <div className=\"rounded-lg border-2 border-dashed border-gray-300 p-8 text-center\">\n <p className=\"text-gray-500\">TikTok integration coming soon...</p>\n </div>\n </div>\n )}\n\n {activeMethod === \"dropbox\" && (\n <div className=\"mx-auto max-w-7xl space-y-6 md:px-10 md:py-8\">\n <div className=\"text-center\">\n <div className=\"mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-linear-to-br from-blue-50 to-indigo-50 ring-4 ring-blue-50/50\">\n <DropboxIcon className=\"h-6 w-6 text-blue-600\" />\n </div>\n <h2 className=\"text-xl font-semibold text-gray-900\">\n Import from Dropbox\n </h2>\n <p className=\"mt-2 text-sm text-gray-600\">\n Connect your Dropbox account to import files\n </p>\n </div>\n <div className=\"rounded-lg border-2 border-dashed border-gray-300 p-8 text-center\">\n <p className=\"text-gray-500\">Dropbox integration coming soon...</p>\n </div>\n </div>\n )}\n </div>\n );\n};\n","import React, { useState, useCallback, useEffect } from \"react\";\nimport {\n XIcon,\n FileIcon,\n ImageIcon,\n VideoIcon,\n EllipsisVerticalIcon,\n CropIcon,\n LayersIcon,\n} from \"lucide-react\";\nimport type { LucideIcon } from \"lucide-react\";\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n Dialog,\n DialogPortal,\n DialogOverlay,\n} from \"@fluid-app/ui-primitives\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport type {\n FilePickerResult,\n DamAsset,\n DamVariant,\n} from \"@fluid-app/file-picker-core\";\nimport { ImageCropModal } from \"./ImageCropModal\";\nimport { getCategoryIcon } from \"../utils/icons\";\n\ninterface SelectionPanelProps {\n selectedFiles: FilePickerResult[];\n onRemoveFile: (assetCode: string) => void;\n onClear: () => void;\n onConfirm: () => void;\n shareableEnabled?: boolean;\n isVisible: boolean;\n hasVariants?: (assetCode: string) => boolean;\n /** Get full asset with variants for the variant picker modal (used with onVariantChange). */\n getAssetWithVariants?: (assetCode: string) => DamAsset | null;\n /** Called when user selects a different variant in the modal. */\n onVariantChange?: (assetCode: string, variantId: string) => void;\n /** @deprecated Use getAssetWithVariants + onVariantChange and open modal from SelectionPanel. */\n onOpenVariantModal?: (assetCode: string) => void;\n onCropImage?: (assetCode: string, croppedFile: File) => void;\n}\n\nconst getFileIcon = (mimeType: string | undefined): LucideIcon => {\n if (!mimeType) return FileIcon;\n if (mimeType.startsWith(\"image/\")) return ImageIcon;\n if (mimeType.startsWith(\"video/\")) return VideoIcon;\n return FileIcon;\n};\n\nconst isImageFile = (file: FilePickerResult): boolean =>\n Boolean(file.metadata.mime_type?.startsWith(\"image/\"));\n\nexport const SelectionPanel: React.FC<SelectionPanelProps> = ({\n selectedFiles,\n onRemoveFile,\n onClear,\n onConfirm,\n shareableEnabled = false,\n isVisible,\n hasVariants,\n getAssetWithVariants,\n onVariantChange,\n onOpenVariantModal,\n onCropImage,\n}) => {\n const [cropTarget, setCropTarget] = useState<{\n assetCode: string;\n file: FilePickerResult;\n } | null>(null);\n const [imageFileForCrop, setImageFileForCrop] = useState<File | null>(null);\n const [cropModalOpen, setCropModalOpen] = useState(false);\n const [variantModalAsset, setVariantModalAsset] = useState<{\n asset: DamAsset;\n assetCode: string;\n } | null>(null);\n\n const openVariantModal = useCallback(\n (assetCode: string) => {\n if (getAssetWithVariants && onVariantChange) {\n const asset = getAssetWithVariants(assetCode);\n if (asset && (asset.variants?.length ?? 0) > 1) {\n setVariantModalAsset({ asset, assetCode });\n return;\n }\n }\n onOpenVariantModal?.(assetCode);\n },\n [getAssetWithVariants, onVariantChange, onOpenVariantModal],\n );\n\n const handleVariantSelect = useCallback(\n (variant: DamVariant) => {\n if (variantModalAsset) {\n onVariantChange?.(variantModalAsset.assetCode, variant.id);\n setVariantModalAsset(null);\n }\n },\n [variantModalAsset, onVariantChange],\n );\n\n // When user clicks \"Crop image\", fetch the image and open crop modal\n useEffect(() => {\n if (!cropTarget?.file.file_url || !isImageFile(cropTarget.file)) {\n return;\n }\n let cancelled = false;\n const { file_url } = cropTarget.file;\n const fileName = cropTarget.file.metadata.file_name ?? \"image.jpg\";\n const mimeType = cropTarget.file.metadata.mime_type ?? \"image/jpeg\";\n fetch(file_url)\n .then((r) => r.blob())\n .then((blob) => {\n if (cancelled) return;\n const file = new File([blob], fileName, { type: mimeType });\n setImageFileForCrop(file);\n setCropModalOpen(true);\n })\n .catch(() => {\n if (!cancelled) setCropTarget(null);\n });\n return () => {\n cancelled = true;\n };\n }, [cropTarget]);\n\n const handleCropComplete = useCallback(\n async (croppedFile: File) => {\n if (cropTarget) {\n const result = onCropImage?.(cropTarget.assetCode, croppedFile);\n if (\n result != null &&\n typeof (result as Promise<unknown>)?.then === \"function\"\n ) {\n await (result as Promise<unknown>);\n }\n }\n setCropTarget(null);\n setImageFileForCrop(null);\n setCropModalOpen(false);\n },\n [cropTarget, onCropImage],\n );\n\n const handleCropCancel = useCallback(() => {\n setCropTarget(null);\n setImageFileForCrop(null);\n setCropModalOpen(false);\n }, []);\n\n if (!isVisible || selectedFiles.length === 0) {\n return null;\n }\n\n return (\n <div className=\"flex h-full w-72 shrink-0 flex-col border-l border-gray-200 bg-white\">\n <div className=\"border-b border-gray-200 px-4 py-3\">\n <h3 className=\"text-sm font-semibold text-gray-900\">Selection</h3>\n </div>\n\n <div className=\"flex-1 overflow-y-auto p-3\">\n <div className=\"space-y-2\">\n {selectedFiles.map((file) => {\n const canCrop = isImageFile(file) && onCropImage;\n const hasVariantOption =\n hasVariants?.(file.asset_code) &&\n (onOpenVariantModal || (getAssetWithVariants && onVariantChange));\n return (\n <div\n key={file.asset_code}\n className=\"group flex items-center gap-3 rounded-lg border border-gray-100 bg-gray-50 p-2 transition-colors hover:border-gray-200 hover:bg-gray-100\"\n >\n <div className=\"relative h-10 w-10 shrink-0 overflow-hidden rounded bg-gray-200\">\n {file.file_url &&\n file.metadata.mime_type?.startsWith(\"image/\") ? (\n <img\n src={file.file_url}\n alt={file.metadata.file_name}\n width={40}\n height={40}\n className=\"h-full w-full object-cover\"\n />\n ) : file.file_url &&\n file.metadata.mime_type?.startsWith(\"video/\") ? (\n <img\n src={`${file.file_url.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={file.metadata.file_name}\n width={40}\n height={40}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center\">\n {React.createElement(\n getFileIcon(file.metadata.mime_type),\n {\n className: \"h-4 w-4 text-gray-400\",\n },\n )}\n </div>\n )}\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-xs font-medium text-gray-900\">\n {file.metadata.file_name}\n </p>\n <p className=\"truncate text-xs text-gray-500\">\n {file.metadata.mime_type?.split(\"/\")[1]?.toUpperCase() ||\n \"FILE\"}\n </p>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-0.5\">\n <DropdownMenu>\n <DropdownMenuTrigger\n className=\"flex h-6 w-6 items-center justify-center rounded-full text-gray-400 opacity-0 transition-all group-hover:opacity-100 hover:bg-gray-200 hover:text-gray-600\"\n onClick={(e) => e.stopPropagation()}\n >\n <EllipsisVerticalIcon className=\"h-3 w-3\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"z-350\">\n <DropdownMenuItem\n disabled={!canCrop}\n onClick={(e) => {\n e.stopPropagation();\n if (canCrop && isImageFile(file))\n setCropTarget({ assetCode: file.asset_code, file });\n }}\n title={\n canCrop\n ? undefined\n : \"Crop is only available for image files\"\n }\n >\n <CropIcon className=\"mr-2 h-3.5 w-3.5 text-gray-600\" />\n Crop image\n </DropdownMenuItem>\n <DropdownMenuItem\n disabled={!hasVariantOption}\n onClick={(e) => {\n e.stopPropagation();\n if (hasVariantOption)\n openVariantModal(file.asset_code);\n }}\n >\n <LayersIcon\n className={`mr-2 h-3.5 w-3.5 ${hasVariantOption ? \"text-gray-600\" : \"text-gray-400\"}`}\n />\n Change variant\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onRemoveFile(file.asset_code);\n }}\n className=\"flex h-6 w-6 items-center justify-center rounded-full text-gray-400 opacity-0 transition-all group-hover:opacity-100 hover:bg-gray-200 hover:text-gray-600\"\n >\n <XIcon className=\"h-3 w-3\" />\n </button>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n\n <div className=\"flex items-center justify-between gap-2 border-t border-gray-200 p-4\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onClear}>\n Clear\n </Button>\n <Button variant=\"default\" size=\"sm\" onClick={onConfirm}>\n {shareableEnabled\n ? \"Next\"\n : `Use ${selectedFiles.length} File${selectedFiles.length !== 1 ? \"s\" : \"\"}`}\n </Button>\n </div>\n\n {imageFileForCrop && (\n <ImageCropModal\n isOpen={cropModalOpen}\n onClose={handleCropCancel}\n onCrop={handleCropComplete}\n imageFile={imageFileForCrop}\n />\n )}\n\n {variantModalAsset && (\n <Dialog\n open={true}\n onOpenChange={(open) => !open && setVariantModalAsset(null)}\n >\n <DialogPortal>\n <DialogOverlay className=\"z-9999 bg-black/70 backdrop-blur-none\" />\n <DialogPrimitive.Content\n className=\"fixed top-1/2 left-1/2 z-10000 max-h-[80vh] w-full max-w-3xl -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border border-gray-200 bg-white shadow-xl\"\n style={{ zIndex: 10000 }}\n >\n <div className=\"border-b bg-white p-6\">\n <h3 className=\"text-lg font-semibold text-gray-900\">\n Select variant\n </h3>\n <p className=\"mt-1 text-sm text-gray-500\">\n Choose a variant for "\n {variantModalAsset.asset.name || \"Unknown Asset\"}"\n </p>\n </div>\n <div className=\"max-h-[60vh] overflow-y-auto p-6\">\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {variantModalAsset.asset.variants?.map((variant) => (\n <button\n key={variant?.id}\n type=\"button\"\n onClick={() => handleVariantSelect(variant)}\n className=\"group rounded-lg border border-gray-200 bg-white p-4 text-left transition-colors hover:bg-gray-50\"\n >\n <div className=\"flex items-start gap-4\">\n <div className=\"shrink-0\">\n {variant.url &&\n variantModalAsset.asset.category === \"images\" ? (\n <img\n src={variant.url}\n alt={variant.file_name}\n width={64}\n height={64}\n className=\"h-16 w-16 rounded-md object-cover\"\n />\n ) : variantModalAsset.asset.category === \"videos\" &&\n variant?.url ? (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-md bg-gray-50\">\n <img\n src={`${variant?.url?.split(\"?\")[0]}/ik-thumbnail.jpg`}\n alt={variant.file_name}\n width={64}\n height={64}\n className=\"h-16 w-16 rounded-md object-cover\"\n />\n </div>\n ) : (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-md bg-gray-50\">\n {React.createElement(\n getCategoryIcon(\n variantModalAsset.asset?.category ||\n \"unknown\",\n ),\n { className: \"h-6 w-6 text-gray-400\" },\n )}\n </div>\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium text-gray-900 group-hover:text-gray-700\">\n {variant?.file_name || \"Unknown File\"}\n </p>\n <p className=\"mt-1 text-xs text-gray-500\">\n {variant?.mime_type || \"Unknown Type\"}\n </p>\n {typeof variant.metadata?.width === \"number\" &&\n typeof variant.metadata?.height === \"number\" && (\n <p className=\"mt-1 text-xs font-medium text-gray-600\">\n {variant.metadata.width}px ×{\" \"}\n {variant.metadata.height}px\n </p>\n )}\n </div>\n </div>\n </button>\n ))}\n </div>\n </div>\n <div className=\"border-t bg-gray-50 p-6\">\n <div className=\"flex justify-end\">\n <Button\n variant=\"secondary\"\n onClick={() => setVariantModalAsset(null)}\n >\n Cancel\n </Button>\n </div>\n </div>\n </DialogPrimitive.Content>\n </DialogPortal>\n </Dialog>\n )}\n </div>\n );\n};\n\nexport default SelectionPanel;\n","import React, {\n useState,\n useCallback,\n useEffect,\n useRef,\n useMemo,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { ImagesIcon, LaptopIcon, CloudIcon, LinkIcon } from \"lucide-react\";\nimport {\n GoogleIcon,\n InstagramIcon,\n FacebookIcon,\n TiktokIcon,\n DropboxIcon,\n UnsplashIcon,\n} from \"../utils/brand-icons\";\nimport { Dialog, DialogContent, DialogTitle } from \"@fluid-app/ui-primitives\";\nimport {\n filePickerConfigSchema,\n type FilePickerResult,\n type FilePickerConfigInput,\n type UploadMethod,\n type DamAsset,\n type SortOptionId,\n} from \"@fluid-app/file-picker-core\";\nimport { type DamLibraryRef } from \"./DamLibrary\";\nimport { FilePickerSidebar } from \"./FilePickerSidebar\";\nimport { FilePickerHeader, type ViewMode } from \"./FilePickerHeader\";\nimport { FilePickerContent } from \"./FilePickerContent\";\nimport {\n defaultFilters as defaultDamFilters,\n type FilePickerFiltersState,\n} from \"./FilePickerFiltersPanel\";\nimport { SelectionPanel } from \"./SelectionPanel\";\n\nexport interface FilePickerProps {\n config?: FilePickerConfigInput;\n onFilesSelected: (results: FilePickerResult[]) => void;\n onClose?: () => void;\n open: boolean;\n showMediaTab?: boolean;\n className?: string;\n skipCropper?: boolean;\n defaultMethod?: UploadMethod;\n}\n\nexport const FilePicker: React.FC<FilePickerProps> = ({\n config: configInput = {},\n onFilesSelected,\n onClose,\n open,\n showMediaTab = false,\n className,\n skipCropper = false,\n defaultMethod,\n}) => {\n const config = useMemo(() => {\n const result = filePickerConfigSchema.safeParse(configInput);\n return result.success ? result.data : filePickerConfigSchema.parse({});\n }, [configInput]);\n\n const defaultTab = defaultMethod ?? \"dam\";\n const [activeMethod, setActiveMethod] = useState<UploadMethod>(() => {\n if (config.allowedMethods && config.allowedMethods.length > 0) {\n const allowed = config.allowedMethods as UploadMethod[];\n if (allowed.includes(defaultTab)) return defaultTab;\n return allowed[0] ?? \"dam\";\n }\n return defaultTab;\n });\n // Re-sync activeMethod if allowedMethods changes and current tab is no longer allowed\n useEffect(() => {\n if (\n config.allowedMethods &&\n config.allowedMethods.length > 0 &&\n !config.allowedMethods.includes(activeMethod)\n ) {\n setActiveMethod((config.allowedMethods[0] as UploadMethod) ?? \"dam\");\n }\n }, [config.allowedMethods, activeMethod]);\n\n const [selectedResults, setSelectedResults] = useState<FilePickerResult[]>(\n [],\n );\n const [damSelectionCount, setDamSelectionCount] = useState(0);\n const [damSelectedFiles, setDamSelectedFiles] = useState<FilePickerResult[]>(\n [],\n );\n const [damVariantCounts, setDamVariantCounts] = useState<\n Record<string, number>\n >({});\n const [damSearchQuery, setDamSearchQuery] = useState(\"\");\n const [damSearching, setDamSearching] = useState(false);\n const [mediaSearchQuery, setMediaSearchQuery] = useState(\"\");\n const [unsplashSearchQuery, setUnsplashSearchQuery] = useState(\"\");\n const [unsplashSearching, setUnsplashSearching] = useState(false);\n const [isUnsplashUploading, setIsUnsplashUploading] = useState(false);\n const [mediaSelectionCount, setMediaSelectionCount] = useState(0);\n const [damFilters, setDamFilters] =\n useState<FilePickerFiltersState>(defaultDamFilters);\n const [sortOption, setSortOption] = useState<SortOptionId | undefined>(\n undefined,\n );\n const [damFolders, setDamFolders] = useState<string[]>([]);\n const [selectedMediaIds, setSelectedMediaIds] = useState<number[]>([]);\n const [selectedMediaData, setSelectedMediaData] = useState<\n FilePickerResult[]\n >([]);\n const damLibraryRef = useRef<DamLibraryRef | null>(null);\n const [previewContainer, setPreviewContainer] =\n useState<HTMLDivElement | null>(null);\n const [previewAsset, setPreviewAsset] = useState<DamAsset | null>(null);\n\n // DAM toolbar state\n const [thumbnailSize, setThumbnailSize] = useState(100);\n const [viewMode, setViewMode] = useState<ViewMode>(\"grid\");\n const [showNamesOnMedia, setShowNamesOnMedia] = useState(true);\n\n const resetPicker = useCallback(() => {\n setActiveMethod(defaultTab);\n setSelectedResults([]);\n setDamSelectionCount(0);\n setDamSelectedFiles([]);\n setDamVariantCounts({});\n setDamSearchQuery(\"\");\n setMediaSearchQuery(\"\");\n setUnsplashSearchQuery(\"\");\n setUnsplashSearching(false);\n setIsUnsplashUploading(false);\n setMediaSelectionCount(0);\n setSelectedMediaIds([]);\n setSelectedMediaData([]);\n setDamFilters(defaultDamFilters);\n setSortOption(undefined);\n damLibraryRef.current?.clearSelection?.();\n setPreviewAsset(null);\n }, [defaultTab]);\n\n const handleMethodChange = useCallback((newMethod: UploadMethod) => {\n setSelectedResults([]);\n setDamSelectionCount(0);\n setDamSelectedFiles([]);\n setDamVariantCounts({});\n setDamSearchQuery(\"\");\n setUnsplashSearchQuery(\"\");\n setUnsplashSearching(false);\n setIsUnsplashUploading(false);\n setMediaSelectionCount(0);\n setSelectedMediaIds([]);\n setSelectedMediaData([]);\n damLibraryRef.current?.clearSelection?.();\n setActiveMethod(newMethod);\n }, []);\n\n const handleFilesSelected = useCallback(\n (results: FilePickerResult[]) => {\n const validResults = results.filter(\n (result) => result.upload_status !== \"error\",\n );\n\n if (config.maxFiles === 1) {\n setSelectedResults(validResults.slice(0, 1));\n } else {\n setSelectedResults((prev) => {\n const totalFiles = prev.length + validResults.length;\n if (config.maxFiles && totalFiles > config.maxFiles) {\n const remainingSlots = config.maxFiles - prev.length;\n return [...prev, ...validResults.slice(0, remainingSlots)];\n }\n return [...prev, ...validResults];\n });\n }\n },\n [config.maxFiles],\n );\n\n const handleUploadConfirm = useCallback(\n (results: FilePickerResult[]) => {\n const validResults = results.filter(\n (result) => result.upload_status !== \"error\",\n );\n if (validResults.length === 0) return;\n onFilesSelected(validResults);\n onClose?.();\n },\n [onFilesSelected, onClose],\n );\n\n const handleSingleFileSelected = useCallback(\n (result: FilePickerResult) => {\n handleFilesSelected([result]);\n },\n [handleFilesSelected],\n );\n\n const handleDamSelectionChange = useCallback(\n (\n count: number,\n files?: FilePickerResult[],\n variantCounts?: Record<string, number>,\n ) => {\n setDamSelectionCount(count);\n setDamSelectedFiles(files ?? []);\n setDamVariantCounts(variantCounts ?? {});\n },\n [],\n );\n\n const handleMediaSelectionChange = useCallback((count: number) => {\n setMediaSelectionCount(count);\n }, []);\n\n const handleMediaDataChange = useCallback((data: FilePickerResult[]) => {\n setSelectedMediaData(data);\n }, []);\n\n const handleThumbnailSizeChange = useCallback((size: number) => {\n setThumbnailSize(size);\n }, []);\n\n const handleViewModeChange = useCallback((mode: ViewMode) => {\n setViewMode(mode);\n }, []);\n\n const handleDamConfirm = useCallback(\n (results: FilePickerResult[]) => {\n onFilesSelected(results);\n onClose?.();\n },\n [onFilesSelected, onClose],\n );\n\n const methods: Array<{\n id: UploadMethod;\n label: string;\n icon: React.ComponentType<{ className?: string }>;\n description: string;\n }> = useMemo(() => {\n const allMethods = [\n {\n id: \"dam\" as UploadMethod,\n label: \"Library\",\n icon: CloudIcon,\n description: \"Choose from DAM library\",\n },\n ...(showMediaTab ||\n (config.allowedMethods && config.allowedMethods.includes(\"media\"))\n ? [\n {\n id: \"media\" as UploadMethod,\n label: \"Media\",\n icon: ImagesIcon,\n description: \"Choose from existing media\",\n },\n ]\n : []),\n {\n id: \"upload\" as UploadMethod,\n label: \"Local Files\",\n icon: LaptopIcon,\n description: \"Upload files from computer or URL\",\n },\n {\n id: \"url\" as UploadMethod,\n label: \"URL\",\n icon: LinkIcon,\n description: \"Upload files from web URLs\",\n },\n {\n id: \"unsplash\" as UploadMethod,\n label: \"Unsplash\",\n icon: UnsplashIcon,\n description: \"Search Unsplash images\",\n },\n {\n id: \"google-drive\" as UploadMethod,\n label: \"Google Drive\",\n icon: GoogleIcon,\n description: \"Import from Google Drive\",\n },\n {\n id: \"instagram\" as UploadMethod,\n label: \"Instagram\",\n icon: InstagramIcon,\n description: \"Import from Instagram\",\n },\n {\n id: \"facebook\" as UploadMethod,\n label: \"Facebook\",\n icon: FacebookIcon,\n description: \"Import from Facebook\",\n },\n {\n id: \"tiktok\" as UploadMethod,\n label: \"TikTok\",\n icon: TiktokIcon,\n description: \"Import from TikTok\",\n },\n {\n id: \"dropbox\" as UploadMethod,\n label: \"Dropbox\",\n icon: DropboxIcon,\n description: \"Import from Dropbox\",\n },\n ];\n\n if (config.allowedMethods && config.allowedMethods.length > 0) {\n return allMethods.filter((method) =>\n config.allowedMethods!.includes(method.id),\n );\n }\n\n return allMethods;\n }, [showMediaTab, config.allowedMethods]);\n\n const showPreview = previewAsset !== null;\n\n return (\n <>\n {typeof document !== \"undefined\" &&\n createPortal(\n <div\n ref={setPreviewContainer}\n className=\"fixed inset-0\"\n style={{\n zIndex: 9999,\n pointerEvents: showPreview ? \"auto\" : \"none\",\n }}\n aria-hidden={!showPreview}\n />,\n document.body,\n )}\n <Dialog\n open={open}\n onOpenChange={(isOpen) => {\n if (!isOpen) {\n resetPicker();\n onClose?.();\n }\n }}\n >\n <DialogContent\n className={`data-[state=closed]:animate-out! data-[state=closed]:fade-out-0! data-[state=closed]:zoom-out-95! data-[state=open]:animate-in! data-[state=open]:fade-in-0! data-[state=open]:zoom-in-95! z-300! flex! h-[90vh]! max-h-[1000px]! w-[95vw]! max-w-[1600px]! flex-col! gap-0! overflow-y-auto! rounded-lg! border-0! bg-white p-0! data-[state=closed]:duration-150! data-[state=open]:duration-200! ${className || \"\"}`}\n >\n <DialogTitle className=\"sr-only\">File Picker</DialogTitle>\n <div className=\"flex flex-1 overflow-y-auto\">\n <FilePickerSidebar\n currentStep=\"select\"\n activeMethod={activeMethod}\n onMethodChange={handleMethodChange}\n methods={methods}\n />\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden\">\n <FilePickerHeader\n currentStep=\"select\"\n activeMethod={activeMethod}\n methods={methods}\n onClose={() => {\n resetPicker();\n onClose?.();\n }}\n damSearchQuery={\n activeMethod === \"dam\" ? damSearchQuery : mediaSearchQuery\n }\n onDamSearchChange={\n activeMethod === \"dam\"\n ? setDamSearchQuery\n : setMediaSearchQuery\n }\n damSearching={damSearching}\n thumbnailSize={thumbnailSize}\n onThumbnailSizeChange={handleThumbnailSizeChange}\n viewMode={viewMode}\n onViewModeChange={handleViewModeChange}\n showNamesOnMedia={showNamesOnMedia}\n onShowNamesOnMediaChange={setShowNamesOnMedia}\n hasSelectedFiles={damSelectionCount > 0}\n damFolders={damFolders}\n onAddToNewFolder={() =>\n damLibraryRef.current?.openAddFolderModal()\n }\n onAddToExistingFolder={(folderPath) =>\n damLibraryRef.current?.addToExistingFolder?.(folderPath)\n }\n filters={damFilters}\n onFiltersChange={setDamFilters}\n onFiltersClear={() => setDamFilters(defaultDamFilters)}\n sortOption={sortOption}\n onSortChange={setSortOption}\n unsplashSearchQuery={unsplashSearchQuery}\n onUnsplashSearchChange={setUnsplashSearchQuery}\n unsplashSearching={unsplashSearching}\n isUnsplashUploading={isUnsplashUploading}\n />\n <div className=\"flex min-h-0 min-w-0 flex-1 overflow-hidden\">\n <div className=\"min-h-0 min-w-0 flex-1 overflow-y-auto\">\n <FilePickerContent\n activeMethod={activeMethod}\n config={config}\n damTypeFilter={\n damFilters.type ? damFilters.type : undefined\n }\n sortOption={sortOption}\n onFilesSelected={handleFilesSelected}\n onUploadConfirmAndMaybeCreate={handleUploadConfirm}\n onSingleFileSelected={handleSingleFileSelected}\n damLibraryRef={damLibraryRef}\n onDamConfirmAndMaybeCreate={handleDamConfirm}\n selectedMediaIds={selectedMediaIds}\n onMediaIdsChange={setSelectedMediaIds}\n onMediaSelectionChange={handleMediaSelectionChange}\n onMediaDataChange={handleMediaDataChange}\n onDamSelectionChange={handleDamSelectionChange}\n onDamSearchingChange={setDamSearching}\n skipCropper={skipCropper}\n damSearchQuery={damSearchQuery}\n onDamSearchChange={setDamSearchQuery}\n mediaSearchQuery={mediaSearchQuery}\n onMediaSearchChange={setMediaSearchQuery}\n unsplashSearchQuery={unsplashSearchQuery}\n onUnsplashSearchChange={setUnsplashSearchQuery}\n onUnsplashSearchingChange={setUnsplashSearching}\n onUnsplashUploadingChange={setIsUnsplashUploading}\n thumbnailSize={thumbnailSize}\n viewMode={viewMode}\n showNamesOnMedia={showNamesOnMedia}\n onDamFoldersChange={setDamFolders}\n previewContainer={previewContainer}\n previewAsset={previewAsset}\n onPreviewAssetChange={setPreviewAsset}\n uploadSelectionCount={\n activeMethod === \"upload\" ||\n activeMethod === \"url\" ||\n activeMethod === \"unsplash\"\n ? selectedResults.length\n : undefined\n }\n />\n </div>\n {activeMethod === \"dam\" && (\n <SelectionPanel\n selectedFiles={damSelectedFiles}\n onRemoveFile={(assetCode) => {\n damLibraryRef.current?.deselectAssetByCode?.(assetCode);\n }}\n onClear={() => {\n damLibraryRef.current?.clearSelection();\n setDamSelectionCount(0);\n setDamSelectedFiles([]);\n setDamVariantCounts({});\n }}\n onConfirm={() => {\n damLibraryRef.current?.confirmAndClose();\n }}\n isVisible={damSelectionCount > 0}\n hasVariants={(assetCode) =>\n (damVariantCounts[assetCode] ?? 0) > 1\n }\n getAssetWithVariants={(assetCode) =>\n damLibraryRef.current?.getAssetWithVariants?.(\n assetCode,\n ) ?? null\n }\n onVariantChange={(assetCode, variantId) => {\n damLibraryRef.current?.setVariantForAsset?.(\n assetCode,\n variantId,\n );\n }}\n />\n )}\n {activeMethod === \"media\" && (\n <SelectionPanel\n selectedFiles={selectedMediaData}\n onRemoveFile={(assetCode) => {\n const id = parseInt(assetCode.replace(/^media_/, \"\"), 10);\n if (!Number.isNaN(id)) {\n setSelectedMediaIds((prev) =>\n prev.filter((mediaId) => mediaId !== id),\n );\n setSelectedMediaData((prev) =>\n prev.filter((r) => r.asset_code !== assetCode),\n );\n }\n }}\n onClear={() => {\n setSelectedMediaIds([]);\n setSelectedMediaData([]);\n setMediaSelectionCount(0);\n }}\n onConfirm={() => {\n onFilesSelected(selectedMediaData);\n onClose?.();\n }}\n isVisible={mediaSelectionCount > 0}\n hasVariants={() => false}\n />\n )}\n {(activeMethod === \"upload\" ||\n activeMethod === \"url\" ||\n activeMethod === \"unsplash\") && (\n <SelectionPanel\n selectedFiles={selectedResults}\n onRemoveFile={(assetCode) => {\n setSelectedResults((prev) =>\n prev.filter((r) => r.asset_code !== assetCode),\n );\n }}\n onClear={() => {\n setSelectedResults([]);\n }}\n onConfirm={() => {\n handleUploadConfirm(selectedResults);\n }}\n isVisible={selectedResults.length > 0}\n hasVariants={() => false}\n />\n )}\n </div>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n};\n","\"use client\";\n\nimport { useState, useCallback, useMemo } from \"react\";\nimport {\n useShareablesUser,\n useCreateMediaMutation,\n} from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n Button,\n Input,\n Spinner,\n} from \"@fluid-app/ui-primitives\";\nimport { Upload, Video, FileText } from \"lucide-react\";\nimport {\n FilePicker,\n FilePickerApiProvider,\n FilePickerProvider,\n type FilePickerContextValue,\n} from \"@fluid-app/file-picker-ui\";\nimport type { FilePickerResult } from \"@fluid-app/file-picker-core\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { useShareablesUI } from \"../../context\";\n\nexport interface MediaCreateScreenProps {\n onNavigate?: (screen: string, detailId?: string) => void;\n onBack?: () => void;\n}\n\nfunction deriveMediaType(mimeType: string): \"image\" | \"video\" | \"pdf\" {\n if (mimeType.startsWith(\"video/\")) return \"video\";\n if (mimeType === \"application/pdf\") return \"pdf\";\n return \"image\";\n}\n\nfunction FilePreview({\n result,\n mediaType,\n}: {\n result: FilePickerResult;\n mediaType: \"image\" | \"video\" | \"pdf\";\n}) {\n if (mediaType === \"image\") {\n return (\n <div className=\"relative aspect-video w-full overflow-hidden rounded-lg border\">\n <img\n src={result.file_url}\n alt={result.metadata.file_name}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n );\n }\n\n const Icon = mediaType === \"video\" ? Video : FileText;\n return (\n <div className=\"flex items-center gap-3 rounded-lg border p-4\">\n <Icon className=\"text-muted-foreground h-8 w-8 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-foreground truncate text-sm font-medium\">\n {result.metadata.file_name}\n </p>\n <p className=\"text-muted-foreground text-xs\">\n {result.metadata.mime_type}\n </p>\n </div>\n </div>\n );\n}\n\nexport function MediaCreateScreen({\n onNavigate,\n onBack,\n}: MediaCreateScreenProps) {\n const { navigate, showToast, filePickerApi } = useShareablesUI();\n const user = useShareablesUser();\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n (onBack ?? (() => navigate(\"media\")))();\n }}\n >\n Media\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">New Media</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [onBack, navigate],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n const [title, setTitle] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [active, setActive] = useState(true);\n const [selectedResult, setSelectedResult] = useState<FilePickerResult | null>(\n null,\n );\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n\n const mediaType = selectedResult\n ? deriveMediaType(selectedResult.metadata.mime_type)\n : null;\n\n const { mutate: createMedia, isPending: isCreating } = useCreateMediaMutation(\n {\n onSuccess: (newMedia: { id: number }) => {\n showToast({ title: \"Media created successfully\", type: \"success\" });\n onNavigate?.(\"media\", String(newMedia.id));\n },\n onError: (error: Error) => {\n showToast({\n title: `Failed to create media: ${error.message}`,\n type: \"error\",\n });\n },\n },\n );\n\n const handleSave = useCallback(() => {\n if (!title.trim()) {\n showToast({ title: \"Title is required\", type: \"warning\" });\n return;\n }\n if (!description.trim()) {\n showToast({ title: \"Description is required\", type: \"warning\" });\n return;\n }\n if (!selectedResult) {\n showToast({ title: \"Please select a file\", type: \"warning\" });\n return;\n }\n\n const mt = deriveMediaType(selectedResult.metadata.mime_type);\n\n createMedia({\n title: title.trim(),\n description: description.trim(),\n active,\n media_type: \"share\",\n kind: mt,\n image_url: mt === \"image\" ? selectedResult.file_url : undefined,\n video_url: mt === \"video\" ? selectedResult.file_url : undefined,\n pdf_url: mt === \"pdf\" ? selectedResult.file_url : undefined,\n user_id: user?.id,\n });\n }, [\n title,\n description,\n active,\n selectedResult,\n user,\n createMedia,\n showToast,\n ]);\n\n const handleFilesSelected = useCallback(\n (results: FilePickerResult[]) => {\n const result = results[0];\n if (!result) return;\n setSelectedResult(result);\n setIsPickerOpen(false);\n if (!title.trim()) {\n setTitle(result.metadata.file_name.replace(/\\.[^/.]+$/, \"\"));\n }\n },\n [title],\n );\n\n const filePickerContextValue = useMemo<FilePickerContextValue | null>(() => {\n if (!filePickerApi) return null;\n return {\n toast: {\n success: (msg: string) => showToast({ title: msg, type: \"success\" }),\n error: (msg: string, error?: unknown) =>\n showToast({\n title: error instanceof Error ? `${msg}: ${error.message}` : msg,\n type: \"error\",\n }),\n loading: () => \"\",\n dismiss: () => {},\n },\n };\n }, [filePickerApi, showToast]);\n\n return (\n <div className=\"flex flex-col gap-4 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"mx-auto flex w-full max-w-lg flex-col gap-6\">\n <h1 className=\"text-foreground text-[26px] leading-[1.2] font-semibold\">\n Add Media\n </h1>\n\n {/* File picker */}\n <div className=\"flex flex-col gap-2\">\n <label className=\"text-foreground text-sm font-medium\">File</label>\n {selectedResult && mediaType ? (\n <div className=\"flex flex-col gap-2\">\n <FilePreview result={selectedResult} mediaType={mediaType} />\n <Button\n onClick={() => setIsPickerOpen(true)}\n variant=\"outline\"\n size=\"sm\"\n className=\"w-fit\"\n >\n Change File\n </Button>\n </div>\n ) : (\n <Button\n onClick={() => setIsPickerOpen(true)}\n variant=\"outline\"\n className=\"flex h-32 w-full flex-col items-center justify-center gap-2 border-dashed\"\n disabled={!filePickerApi}\n >\n <Upload className=\"text-muted-foreground h-6 w-6\" />\n <span className=\"text-muted-foreground text-sm\">Select File</span>\n </Button>\n )}\n </div>\n\n {/* Title */}\n <div className=\"flex flex-col gap-2\">\n <label className=\"text-foreground text-sm font-medium\">\n Title <span className=\"text-red-500\">*</span>\n </label>\n <Input\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"Enter media title\"\n required\n />\n </div>\n\n {/* Description */}\n <div className=\"flex flex-col gap-2\">\n <label className=\"text-foreground text-sm font-medium\">\n Description <span className=\"text-red-500\">*</span>\n </label>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Enter description\"\n required\n rows={3}\n className=\"border-input bg-background text-foreground placeholder:text-muted-foreground rounded-md border px-3 py-2 text-sm focus:ring-2 focus:ring-offset-2 focus:outline-none\"\n />\n </div>\n\n {/* Active toggle */}\n <label className=\"flex items-center gap-3\">\n <input\n type=\"checkbox\"\n checked={active}\n onChange={(e) => setActive(e.target.checked)}\n className=\"h-4 w-4 rounded\"\n />\n <span className=\"text-foreground text-sm font-medium\">Active</span>\n </label>\n\n {/* Save button */}\n <Button\n onClick={handleSave}\n disabled={isCreating}\n className=\"bg-foreground text-background hover:bg-foreground/70 flex h-10 w-full items-center justify-center rounded-lg px-4 transition-all\"\n >\n {isCreating ? <Spinner className=\"size-4\" /> : \"Save Media\"}\n </Button>\n </div>\n\n {/* File Picker Dialog */}\n {filePickerContextValue && filePickerApi && (\n <FilePickerApiProvider api={filePickerApi}>\n <FilePickerProvider value={filePickerContextValue}>\n <FilePicker\n open={isPickerOpen}\n onFilesSelected={handleFilesSelected}\n onClose={() => setIsPickerOpen(false)}\n config={{\n maxFiles: 1,\n allowedMethods: [\"dam\", \"upload\", \"url\"],\n }}\n />\n </FilePickerProvider>\n </FilePickerApiProvider>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport {\n Badge,\n Checkbox,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n cn,\n} from \"@fluid-app/ui-primitives\";\nimport { Heart, MoreVertical, Pencil, Trash2 } from \"lucide-react\";\nimport { useShareablesUI, useRenderImage } from \"../../context\";\n\nexport interface PlaylistCardProps {\n title: string;\n imageUrl?: string | null;\n href: string;\n itemCount: number;\n isFavorited?: boolean;\n isSelectable?: boolean;\n isSelected?: boolean;\n canEdit?: boolean;\n onSelectionChange?: (selected: boolean) => void;\n onToggleFavorite?: () => void;\n onEdit?: () => void;\n onDelete?: () => void;\n}\n\nconst DEFAULT_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png\";\n\nexport function PlaylistCard({\n title,\n imageUrl,\n href,\n itemCount,\n isFavorited = false,\n isSelectable = false,\n isSelected = false,\n canEdit = false,\n onSelectionChange,\n onToggleFavorite,\n onEdit,\n onDelete,\n}: PlaylistCardProps) {\n const { navigate } = useShareablesUI();\n const renderImage = useRenderImage();\n const [imgError, setImgError] = useState(false);\n\n const hasStack = itemCount > 1;\n const badgeText = `${itemCount} ${itemCount === 1 ? \"item\" : \"items\"}`;\n\n return (\n <button\n type=\"button\"\n onClick={() => navigate(href)}\n className=\"group block w-full cursor-pointer text-left\"\n >\n {/* Stack effect container */}\n <div className=\"relative\">\n {/* Stack layers */}\n {hasStack && (\n <>\n <div\n className=\"bg-muted absolute -top-2 right-2 left-2 z-0 h-full rounded-lg shadow-sm transition-transform duration-300 ease-out\"\n style={{\n transform: isSelected ? \"rotate(0deg)\" : \"rotate(-4deg)\",\n }}\n />\n <div\n className=\"bg-muted absolute -top-1 right-1 left-1 z-0 h-full rounded-lg shadow-sm transition-transform duration-300 ease-out\"\n style={{\n transform: isSelected ? \"rotate(0deg)\" : \"rotate(7deg)\",\n }}\n />\n </>\n )}\n\n {/* Main card */}\n <div className=\"bg-background relative z-10 rounded-lg p-1 shadow-md\">\n <div className=\"bg-muted relative aspect-square overflow-hidden rounded-lg\">\n {renderImage({\n src: imgError ? DEFAULT_IMAGE : imageUrl || DEFAULT_IMAGE,\n alt: title,\n fill: true,\n className:\n \"object-cover transition-transform group-hover:scale-105\",\n onError: () => setImgError(true),\n })}\n\n {/* Selection checkbox */}\n {isSelectable && (\n <div\n className={cn(\n \"absolute top-2 left-2 z-10 transition-opacity\",\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100\",\n )}\n onClick={(e) => {\n e.stopPropagation();\n }}\n >\n <Checkbox\n checked={isSelected}\n onCheckedChange={() => onSelectionChange?.(!isSelected)}\n />\n </div>\n )}\n\n {/* Context menu */}\n {(onToggleFavorite || canEdit) && (\n <div\n className={cn(\n \"absolute top-2 right-2 z-20 transition-opacity\",\n \"opacity-0 group-hover:opacity-100\",\n )}\n >\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n onClick={(e) => e.stopPropagation()}\n className=\"bg-background/90 hover:bg-background flex h-8 w-8 items-center justify-center rounded-lg shadow-md backdrop-blur-sm transition-all\"\n aria-label=\"More options\"\n >\n <MoreVertical className=\"text-foreground h-4 w-4\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n onClick={(e) => e.stopPropagation()}\n >\n {onToggleFavorite && (\n <DropdownMenuItem onClick={onToggleFavorite}>\n <Heart\n className={cn(\n \"mr-2 h-4 w-4\",\n isFavorited && \"text-destructive fill-current\",\n )}\n />\n {isFavorited ? \"Unfavorite\" : \"Favorite\"}\n </DropdownMenuItem>\n )}\n {canEdit && onEdit && (\n <DropdownMenuItem onClick={onEdit}>\n <Pencil className=\"mr-2 h-4 w-4\" />\n Edit\n </DropdownMenuItem>\n )}\n {canEdit && onDelete && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n variant=\"destructive\"\n onClick={onDelete}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n )}\n\n {/* Radial gradient behind heart for visibility */}\n {onToggleFavorite && (\n <div className=\"pointer-events-none absolute -bottom-8 -left-8 z-9 h-24 w-24 rounded-full bg-[#00000020] blur-xl\" />\n )}\n\n {/* Favorite heart */}\n {onToggleFavorite && (\n <button\n type=\"button\"\n className=\"absolute bottom-3 left-3 z-10 cursor-pointer transition-transform hover:scale-110\"\n onClick={(e) => {\n e.stopPropagation();\n onToggleFavorite();\n }}\n aria-label={isFavorited ? \"Unfavorite\" : \"Favorite\"}\n >\n <Heart\n className={cn(\n \"h-6 w-6 drop-shadow-lg transition-all\",\n isFavorited\n ? \"fill-destructive text-destructive\"\n : \"text-[#ffffff]\",\n )}\n />\n </button>\n )}\n\n {/* Item count badge */}\n <div className=\"absolute right-2 bottom-2\">\n <Badge\n className=\"bg-foreground text-background shadow-lg backdrop-blur-sm\"\n variant=\"secondary\"\n >\n {badgeText}\n </Badge>\n </div>\n </div>\n\n {/* Title */}\n <div className=\"px-2 pt-2 pb-4\">\n <h3 className=\"text-foreground line-clamp-2 text-sm leading-tight font-bold\">\n {title || \"Untitled\"}\n </h3>\n </div>\n </div>\n </div>\n </button>\n );\n}\n","\"use client\";\n\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { X } from \"lucide-react\";\n\nexport interface BulkSelectionBarProps {\n selectedCount: number;\n totalCount: number;\n onSelectAll: () => void;\n onClearSelection: () => void;\n onBulkFavorite: () => void;\n}\n\nexport function BulkSelectionBar({\n selectedCount,\n totalCount,\n onSelectAll,\n onClearSelection,\n onBulkFavorite,\n}: BulkSelectionBarProps) {\n return (\n <div className=\"bg-foreground flex items-center justify-between rounded-lg px-4 py-3\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={onSelectAll}\n className=\"text-background hover:text-background/80 text-sm font-medium\"\n >\n {selectedCount === totalCount ? \"Deselect All\" : \"Select All\"}\n </button>\n <span className=\"text-background/70 text-sm\">\n {selectedCount} selected\n </span>\n </div>\n <div className=\"flex items-center gap-3\">\n <Button\n onClick={onBulkFavorite}\n disabled={selectedCount === 0}\n variant=\"secondary\"\n size=\"sm\"\n className=\"bg-background text-foreground hover:bg-background/90 rounded-md px-3 py-1.5 text-xs font-medium disabled:cursor-not-allowed disabled:opacity-50\"\n >\n Favorite\n </Button>\n <button\n type=\"button\"\n onClick={onClearSelection}\n className=\"text-background hover:text-background/80\"\n aria-label=\"Cancel selection\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport {\n useInfiniteQuery,\n useMutation,\n useQueryClient,\n keepPreviousData,\n} from \"@tanstack/react-query\";\nimport { useShareablesApi, shareablesKeys } from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n Button,\n Skeleton,\n} from \"@fluid-app/ui-primitives\";\nimport { Plus } from \"lucide-react\";\nimport {\n useScreenHeaderActions,\n useScreenHeaderBreadcrumbs,\n} from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { SearchSort } from \"@fluid-app/ui-components/components/SearchSort\";\nimport { useShareablesUI } from \"../../context\";\nimport { PlaylistCard } from \"../playlists/PlaylistCard\";\nimport { BulkSelectionBar } from \"../playlists/BulkSelectionBar\";\n\nconst PAGE_SIZE = 12;\n\nconst GRID_CLASS =\n \"grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4\";\n\nexport interface PlaylistsListingScreenProps {}\n\nexport function PlaylistsListingScreen(_props: PlaylistsListingScreenProps) {\n const api = useShareablesApi();\n const {\n navigate,\n showToast,\n user,\n onToggleFavorite,\n onDeletePlaylist,\n readOnly,\n } = useShareablesUI();\n const queryClient = useQueryClient();\n\n const headerActions = useMemo(\n () =>\n readOnly ? null : (\n <Button onClick={() => navigate(\"playlists/new\")} size=\"sm\">\n <Plus className=\"mr-1 h-4 w-4\" />\n Create Playlist\n </Button>\n ),\n [navigate, readOnly],\n );\n useScreenHeaderActions(headerActions);\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">Playlists</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n const [sortValue, setSortValue] = useState(\"title\");\n const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());\n\n useEffect(() => {\n const timer = setTimeout(() => setDebouncedSearch(searchTerm), 300);\n return () => clearTimeout(timer);\n }, [searchTerm]);\n const observerTarget = useRef<HTMLDivElement>(null);\n\n const queryKey = [\n ...shareablesKeys.playlists.all,\n \"list\",\n debouncedSearch,\n sortValue,\n ];\n\n const {\n data,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n isFetched,\n error,\n } = useInfiniteQuery({\n queryKey,\n queryFn: async ({ pageParam }) => {\n const response = await api.playlists.getPlaylists({\n \"filter[title]\": debouncedSearch || undefined,\n \"page[cursor]\": pageParam,\n \"page[limit]\": PAGE_SIZE,\n sort: sortValue,\n });\n return {\n playlists: response.playlists,\n nextCursor: response.meta.pagination.next_cursor,\n };\n },\n getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,\n initialPageParam: undefined as string | undefined,\n placeholderData: keepPreviousData,\n });\n\n const allPlaylists = useMemo(\n () => data?.pages.flatMap((page) => page.playlists) ?? [],\n [data?.pages],\n );\n\n // Infinite scroll\n useEffect(() => {\n const target = observerTarget.current;\n if (!target) return;\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n },\n { threshold: 0, rootMargin: \"200px\" },\n );\n observer.observe(target);\n return () => observer.disconnect();\n }, [fetchNextPage, hasNextPage, isFetchingNextPage]);\n\n // --- Selection ---\n const hasSelection = selectedIds.size > 0;\n\n const handleToggleSelection = useCallback((id: number, selected: boolean) => {\n setSelectedIds((prev) => {\n const next = new Set(prev);\n if (selected) next.add(id);\n else next.delete(id);\n return next;\n });\n }, []);\n\n const handleSelectAll = useCallback(() => {\n if (selectedIds.size === allPlaylists.length) {\n setSelectedIds(new Set());\n } else {\n setSelectedIds(new Set(allPlaylists.map((p) => p.id)));\n }\n }, [selectedIds.size, allPlaylists]);\n\n const handleClearSelection = useCallback(() => {\n setSelectedIds(new Set());\n }, []);\n\n // --- Favorites ---\n const favoriteMutation = useMutation({\n mutationFn: (playlistId: number) => {\n if (!onToggleFavorite) {\n return Promise.reject(new Error(\"Favorite not available\"));\n }\n return onToggleFavorite({\n favoriteableId: playlistId,\n favoriteableType: \"Library\",\n });\n },\n onMutate: async (playlistId) => {\n await queryClient.cancelQueries({ queryKey });\n const previousData = queryClient.getQueryData(queryKey);\n\n queryClient.setQueryData<typeof data>(queryKey, (oldData) => {\n if (!oldData) return oldData;\n return {\n ...oldData,\n pages: oldData.pages.map((page) => ({\n ...page,\n playlists: page.playlists.map((p) =>\n p.id === playlistId ? { ...p, is_favorited: !p.is_favorited } : p,\n ),\n })),\n };\n });\n\n return { previousData, capturedKey: queryKey };\n },\n onError: (_err, _playlistId, context) => {\n if (context?.previousData) {\n queryClient.setQueryData(context.capturedKey, context.previousData);\n }\n showToast({ title: \"Failed to update favorite\", type: \"error\" });\n },\n onSuccess: (result) => {\n showToast({\n title: result.is_favorited\n ? \"Added to favorites\"\n : \"Removed from favorites\",\n type: \"success\",\n });\n },\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: shareablesKeys.playlists.all });\n },\n });\n\n const handleFavorite = useCallback(\n (playlistId: number) => {\n if (!onToggleFavorite) return;\n favoriteMutation.mutate(playlistId);\n },\n [onToggleFavorite, favoriteMutation],\n );\n\n const handleBulkFavorite = useCallback(() => {\n for (const id of selectedIds) {\n handleFavorite(id);\n }\n setSelectedIds(new Set());\n }, [selectedIds, handleFavorite]);\n\n // --- Card actions ---\n const handleEdit = useCallback(\n (playlistId: number) => {\n navigate(`playlists/${playlistId}/edit`);\n },\n [navigate],\n );\n\n const handleDelete = useCallback(\n async (playlistId: number) => {\n if (!onDeletePlaylist) return;\n if (!window.confirm(\"Are you sure you want to delete this playlist?\"))\n return;\n try {\n await onDeletePlaylist(playlistId);\n queryClient.invalidateQueries({\n queryKey: shareablesKeys.playlists.all,\n });\n showToast({ title: \"Playlist deleted\", type: \"success\" });\n } catch {\n showToast({\n title: \"Failed to delete playlist\",\n type: \"error\",\n });\n }\n },\n [onDeletePlaylist, queryClient, showToast],\n );\n\n // Loading skeleton\n if (isLoading) {\n return (\n <div className=\"mx-auto space-y-6 px-2 md:px-10 md:py-6\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-10 flex-1\" />\n <Skeleton className=\"h-10 w-24\" />\n </div>\n <div className={GRID_CLASS}>\n {Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"space-y-2\">\n <Skeleton className=\"aspect-square w-full rounded-lg\" />\n <Skeleton className=\"h-4 w-3/4\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <>\n <div className=\"mx-auto px-2 md:px-10\">\n {hasSelection ? (\n <div className=\"my-4\">\n <BulkSelectionBar\n selectedCount={selectedIds.size}\n totalCount={allPlaylists.length}\n onSelectAll={handleSelectAll}\n onClearSelection={handleClearSelection}\n onBulkFavorite={handleBulkFavorite}\n />\n </div>\n ) : (\n <div className=\"flex items-center justify-end py-4\">\n <div className=\"w-full max-w-sm\">\n <SearchSort\n searchValue={searchTerm}\n onSearchChange={setSearchTerm}\n placeholder=\"Search playlists...\"\n sortOptions={[\n { label: \"Name (A-Z)\", value: \"title\" },\n { label: \"Name (Z-A)\", value: \"-title\" },\n { label: \"Date Created (Newest)\", value: \"-created_at\" },\n { label: \"Date Created (Oldest)\", value: \"created_at\" },\n ]}\n sortValue={sortValue}\n onSortChange={setSortValue}\n />\n </div>\n </div>\n )}\n </div>\n\n <div className=\"mx-auto space-y-8 px-2 md:px-10 md:py-8\">\n {allPlaylists.length > 0 && (\n <div className={GRID_CLASS}>\n {allPlaylists.map((playlist) => {\n const firstItem = playlist.items?.[0];\n const imageUrl =\n playlist.image_url ??\n firstItem?.image_url ??\n firstItem?.relateable?.image_url ??\n firstItem?.relateable?.compressed_image_url;\n const itemCount =\n playlist.items_count ?? playlist.items?.length ?? 0;\n const canEdit = !readOnly && playlist.user_id === user?.id;\n\n return (\n <PlaylistCard\n key={playlist.id}\n title={playlist.title || \"Untitled Playlist\"}\n imageUrl={imageUrl}\n href={`playlists/${playlist.id}`}\n itemCount={itemCount}\n isFavorited={playlist.is_favorited}\n isSelectable\n isSelected={selectedIds.has(playlist.id)}\n canEdit={canEdit}\n onSelectionChange={(selected) =>\n handleToggleSelection(playlist.id, selected)\n }\n onToggleFavorite={\n onToggleFavorite\n ? () => handleFavorite(playlist.id)\n : undefined\n }\n onEdit={() => handleEdit(playlist.id)}\n onDelete={\n onDeletePlaylist\n ? () => void handleDelete(playlist.id)\n : undefined\n }\n />\n );\n })}\n </div>\n )}\n\n <div ref={observerTarget} className=\"h-1\" />\n\n {isFetchingNextPage && (\n <div className=\"flex items-center justify-center\">\n <div className=\"border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent\" />\n </div>\n )}\n\n {isFetched && allPlaylists.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-8 text-center\">\n <p className=\"text-muted-foreground text-sm\">\n {searchTerm\n ? `No playlists match \"${searchTerm}\". Try a different search term.`\n : \"There are no playlists available at the moment.\"}\n </p>\n </div>\n )}\n\n {error && (\n <p className=\"bg-destructive/10 text-destructive mx-auto my-6 rounded-lg px-3 py-2\">\n Error: {error.message}\n </p>\n )}\n </div>\n </>\n );\n}\n","export const NAVIGABLE_RELATEABLE_TYPES = new Set<string>([\n \"Product\",\n \"Page\",\n \"Medium\",\n]);\n","\"use client\";\n\nimport { useRenderImage } from \"../../context\";\nimport { ShoppingBag, ArrowUpRight } from \"lucide-react\";\nimport type { shareables } from \"@fluid-app/shareables-core\";\n\nconst DEFAULT_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png\";\n\ntype TaggedProduct = shareables.Relateable;\n\ninterface TaggedProductsListProps {\n products: TaggedProduct[];\n /** Called when user clicks a product card */\n onProductClick?: (productId: number) => void;\n}\n\nfunction resolvePrice(product: TaggedProduct): string | null {\n let price = product.display_price || product.price;\n\n if (product.variants && product.variants.length > 0) {\n const firstVariant = product.variants[0];\n if (firstVariant?.display_price) {\n price = firstVariant.display_price;\n } else if (firstVariant?.price) {\n price = firstVariant.price;\n }\n }\n\n if (!price) return null;\n\n const numPrice = parseFloat(price.replace(/[^0-9.-]/g, \"\"));\n if (Number.isNaN(numPrice) || numPrice <= 0) return null;\n\n if (price.includes(\"$\")) return price;\n\n return `$${numPrice.toFixed(2)}`;\n}\n\nexport default function TaggedProductsList({\n products,\n onProductClick,\n}: TaggedProductsListProps) {\n const renderImage = useRenderImage();\n\n const handleProductClick = (\n productId: number | undefined,\n e: React.MouseEvent,\n ) => {\n e.stopPropagation();\n if (productId == null) return;\n onProductClick?.(productId);\n };\n\n if (!products || products.length === 0) {\n return (\n <div className=\"mb-6\">\n <div className=\"mb-4 px-4\">\n <h2 className=\"text-foreground text-[15px] leading-[1.4] font-semibold\">\n Tagged Products (0)\n </h2>\n </div>\n <div className=\"flex flex-1 items-center justify-center px-6 py-12\">\n <div className=\"text-center\">\n <div className=\"text-muted-foreground mb-2\">\n <ShoppingBag className=\"mx-auto h-12 w-12\" />\n </div>\n <div className=\"text-foreground mb-1 text-sm\">\n No Tagged Products\n </div>\n <div className=\"text-muted-foreground text-xs\">\n No products are tagged in this playlist\n </div>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"mb-6\">\n {/* Header */}\n <div className=\"mb-4 px-4\">\n <h2 className=\"text-foreground text-[15px] leading-[1.4] font-semibold\">\n Tagged Products ({products.length})\n </h2>\n </div>\n\n {/* Content */}\n <div className=\"px-4\">\n <div className=\"scrollbar-none flex gap-4 overflow-x-auto pb-2\">\n {products.map((product, index) => {\n const imageUrl =\n product.images?.[0]?.image_url ||\n product.image_url ||\n product.compressed_image_url ||\n DEFAULT_IMAGE;\n const title = product.title || \"Untitled\";\n const displayPrice = resolvePrice(product);\n return (\n <button\n key={product.id ?? index}\n onClick={(e) => handleProductClick(product.id, e)}\n className=\"group bg-muted hover:bg-muted-600 flex w-[168px] shrink-0 flex-col gap-2 rounded-lg p-3 text-left transition-all\"\n >\n {/* Product Image */}\n <div className=\"bg-background relative h-[168px] w-full overflow-hidden rounded-lg\">\n {renderImage({\n src: imageUrl,\n alt: title,\n fill: true,\n className: \"object-cover\",\n })}\n </div>\n\n {/* Content */}\n <div className=\"flex min-w-0 flex-col gap-1\">\n {/* Title with hover arrow */}\n <h3 className=\"text-foreground flex items-start gap-1.5 text-[15px] leading-[1.4] font-semibold\">\n <span className=\"line-clamp-2\">{title}</span>\n <ArrowUpRight className=\"text-foreground mt-0.5 h-3 w-3 shrink-0 opacity-0 transition-opacity group-hover:opacity-100\" />\n </h3>\n\n {/* Price */}\n {displayPrice && (\n <div className=\"text-foreground text-[15px] leading-[1.4] font-normal\">\n {displayPrice}\n </div>\n )}\n </div>\n </button>\n );\n })}\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useRenderImage } from \"../../context\";\nimport { ListMusic, Play, ArrowUpRight } from \"lucide-react\";\nimport type { shareables } from \"@fluid-app/shareables-core\";\nimport { NAVIGABLE_RELATEABLE_TYPES } from \"../../constants\";\n\nconst DEFAULT_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png\";\n\ninterface PlaylistItemsListProps {\n items: shareables.PlaylistItem[];\n onSelectItem?: (index: number) => void;\n selectedItemIndex?: number;\n /** Called when user clicks to navigate to an item's detail page */\n onNavigateToItem?: (itemId: number, relateableType?: string | null) => void;\n}\n\nfunction getItemType(type?: string | null, kind?: string | null) {\n if (type === \"Product\") return \"Product\";\n if (type === \"EnrollmentPack\") return \"Enrollment\";\n if (type === \"Page\") return \"Page\";\n if (kind === \"video\") return \"Video\";\n if (kind === \"image\") return \"Image\";\n return \"Media\";\n}\n\nfunction formatVideoLength(seconds?: number) {\n if (seconds == null) return null;\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${String(mins).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n}\n\nfunction getFileType(mediaFormat?: string | null, imageUrl?: string | null) {\n if (mediaFormat) {\n return mediaFormat.toLowerCase();\n }\n if (imageUrl) {\n const urlParts = imageUrl.split(\".\");\n const extension = urlParts[urlParts.length - 1]?.split(\"?\")[0];\n if (extension) {\n return extension.toLowerCase();\n }\n }\n return null;\n}\n\nexport default function PlaylistItemsList({\n items,\n onSelectItem,\n selectedItemIndex = 0,\n onNavigateToItem,\n}: PlaylistItemsListProps) {\n const handleNavigateToItem = (\n itemId: number,\n type?: string | null,\n e?: React.MouseEvent,\n ) => {\n e?.stopPropagation();\n onNavigateToItem?.(itemId, type);\n };\n\n const handleCardClick = (index: number) => {\n onSelectItem?.(index);\n };\n\n const renderImage = useRenderImage();\n\n const renderContent = () => {\n if (!items || items.length === 0) {\n return (\n <div className=\"flex flex-1 items-center justify-center px-6 py-12\">\n <div className=\"text-center\">\n <div className=\"mb-2 text-gray-400\">\n <ListMusic className=\"mx-auto h-12 w-12\" />\n </div>\n <div className=\"mb-1 text-sm text-gray-500\">No Items</div>\n <div className=\"text-xs text-gray-400\">\n This playlist doesn't have any items yet\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-3\">\n {items.map((item, index) => {\n const relateable = item.relateable;\n const imageUrl =\n item.image_url ??\n relateable?.image_url ??\n relateable?.compressed_image_url ??\n DEFAULT_IMAGE;\n const title = item.title ?? relateable?.title ?? \"Untitled\";\n const rawPrice = relateable?.display_price || relateable?.price;\n const price =\n rawPrice && parseFloat(rawPrice.replace(/[^0-9.-]/g, \"\")) > 0\n ? rawPrice\n : null;\n const kind = item.kind ?? relateable?.kind;\n const itemType = getItemType(item.relateable_type, kind);\n const isVideo = kind === \"video\";\n const isImage = kind === \"image\";\n const isProduct = item.relateable_type === \"Product\";\n const isNavigable = NAVIGABLE_RELATEABLE_TYPES.has(\n item.relateable_type ?? \"\",\n );\n const videoLength = formatVideoLength(\n item.duration ?? relateable?.duration,\n );\n const fileType = getFileType(\n item.media_format ?? relateable?.media_format,\n item.image_url ?? relateable?.image_url,\n );\n const isSelected = index === selectedItemIndex;\n\n return (\n <div\n key={item.id}\n onClick={() => handleCardClick(index)}\n className={`hover:bg-muted-600 flex w-full cursor-pointer items-start gap-3 rounded-lg p-3 text-left transition-all ${\n isSelected ? \"bg-muted-600\" : \"bg-muted\"\n }`}\n >\n {/* Thumbnail */}\n <div className=\"bg-background relative h-[104px] w-[104px] shrink-0 overflow-hidden rounded-lg\">\n {renderImage({\n src: imageUrl,\n alt: title,\n fill: true,\n className: \"object-cover\",\n })}\n {/* Play button overlay for videos */}\n {isVideo && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-background/90 flex h-10 w-10 items-center justify-center rounded-full shadow-md\">\n <Play className=\"text-foreground ml-0.5 h-4 w-4\" />\n </div>\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-1 py-1\">\n {/* Title - clickable to navigate for supported types */}\n {isNavigable ? (\n <button\n onClick={(e) =>\n handleNavigateToItem(\n relateable?.id ?? item.id,\n item.relateable_type,\n e,\n )\n }\n className=\"group text-foreground flex items-start gap-1.5 text-left text-[15px] leading-[1.4] font-semibold hover:underline\"\n >\n <span className=\"line-clamp-2\">{title}</span>\n <ArrowUpRight className=\"text-foreground mt-0.5 h-3 w-3 shrink-0 opacity-0 transition-opacity group-hover:opacity-100\" />\n </button>\n ) : (\n <div className=\"text-foreground text-[15px] leading-[1.4] font-semibold\">\n <span className=\"line-clamp-2\">{title}</span>\n </div>\n )}\n\n {/* Product: Price */}\n {isProduct && price && (\n <div className=\"text-foreground text-[15px] leading-[1.4] font-normal\">\n {price}\n </div>\n )}\n\n {/* Video: Duration */}\n {isVideo && (\n <div className=\"text-muted-foreground text-[13px] leading-[1.4] font-normal\">\n {videoLength || \"Video\"}\n </div>\n )}\n\n {/* Image: File type */}\n {isImage && (\n <div className=\"text-muted-foreground text-[13px] leading-[1.4] font-normal\">\n {fileType || \"image\"}\n </div>\n )}\n\n {/* Badge */}\n <div className=\"mt-1\">\n <span className=\"bg-background text-foreground inline-flex items-center rounded-md px-2.5 py-1 text-[13px] leading-[1.4] font-medium\">\n {itemType}\n </span>\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className=\"hide-scrollbar flex h-full flex-col\">\n {/* Header */}\n <div className=\"mb-4 px-4 pt-4\">\n <h2 className=\"text-foreground text-[15px] leading-[1.4] font-semibold\">\n Items in playlist ({items.length})\n </h2>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto px-4 pb-4\">{renderContent()}</div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useState, useCallback, useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { NAVIGABLE_RELATEABLE_TYPES } from \"../../constants\";\nimport {\n useShareablesApi,\n useShareLink,\n shareablesKeys,\n} from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n Button,\n Separator,\n Spinner,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@fluid-app/ui-primitives\";\nimport { Pencil, Trash2 } from \"lucide-react\";\nimport SharePageImageDisplay from \"../SharePage/SharePageImageDisplay\";\nimport ShareLinkSection from \"../SharePage/ShareLinkSection\";\nimport TaggedProductsList from \"../SharePage/TaggedProductsList\";\nimport PlaylistItemsList from \"../SharePage/PlaylistItemsList\";\nimport { stripTags } from \"../../utils/strip-tags\";\nimport {\n useScreenHeaderActions,\n useScreenHeaderBreadcrumbs,\n} from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { useShareablesUI } from \"../../context\";\n\nconst DEFAULT_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png\";\n\nexport interface PlaylistDetailScreenProps {\n playlistId: string;\n onNavigate?: (screen: string, detailId?: string) => void;\n onBack?: () => void;\n}\n\nexport function PlaylistDetailScreen({\n playlistId,\n onNavigate,\n}: PlaylistDetailScreenProps) {\n const api = useShareablesApi();\n const { navigate, showToast, onDeletePlaylist, user, readOnly } =\n useShareablesUI();\n const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false);\n const [selectedPlaylistItemIndex, setSelectedPlaylistItemIndex] = useState(0);\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n\n // Fetch playlist\n const { data: playlistResponse, isLoading } = useQuery({\n queryKey: shareablesKeys.playlists.detail(Number(playlistId)),\n queryFn: () => api.playlists.getPlaylistById(Number(playlistId)),\n });\n\n // Share link — relateableType for playlist is \"Library\"\n const {\n shareLink,\n loading: shareLinkLoading,\n error: shareLinkError,\n } = useShareLink({ id: Number(playlistId) }, \"Library\");\n\n const playlist = playlistResponse?.playlist;\n\n const canEdit = !readOnly && playlist?.user_id === user?.id;\n const displayTitle = playlist?.title || \"\";\n\n const headerActions = useMemo(() => {\n if (!canEdit) return null;\n return (\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => navigate(`playlists/${playlistId}/edit`)}\n >\n <Pencil className=\"mr-1 h-3.5 w-3.5\" />\n Edit\n </Button>\n {onDeletePlaylist && (\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => setIsDeleteOpen(true)}\n >\n <Trash2 className=\"mr-1 h-3.5 w-3.5\" />\n Delete\n </Button>\n )}\n </div>\n );\n }, [canEdit, navigate, playlistId, onDeletePlaylist]);\n useScreenHeaderActions(headerActions);\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n navigate(\"playlists\");\n }}\n >\n Playlists\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {displayTitle || \"Playlist\"}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [displayTitle, navigate],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n const handleDelete = useCallback(async () => {\n if (!onDeletePlaylist) return;\n setIsDeleting(true);\n try {\n await onDeletePlaylist(Number(playlistId));\n showToast({ title: \"Playlist deleted successfully\", type: \"success\" });\n navigate(\"playlists\");\n } catch {\n showToast({ title: \"Failed to delete playlist\", type: \"error\" });\n } finally {\n setIsDeleting(false);\n setIsDeleteOpen(false);\n }\n }, [onDeletePlaylist, playlistId, showToast, navigate]);\n\n // Get the selected playlist item\n const selectedPlaylistItem = playlist?.items?.[selectedPlaylistItemIndex];\n\n // Derive display values\n const displayImage =\n selectedPlaylistItem?.image_url ??\n selectedPlaylistItem?.relateable?.image_url ??\n selectedPlaylistItem?.relateable?.compressed_image_url ??\n DEFAULT_IMAGE;\n const displayDescription =\n playlist?.description ||\n playlist?.search_engine_optimizer?.description ||\n \"\";\n const strippedDescription = stripTags(displayDescription);\n const shouldShowReadMore = strippedDescription.length > 150;\n\n // Handle video display for playlist items\n const selectedKind =\n selectedPlaylistItem?.kind ?? selectedPlaylistItem?.relateable?.kind;\n const displayVideo =\n selectedKind === \"video\"\n ? (selectedPlaylistItem?.video_url ??\n selectedPlaylistItem?.relateable?.video_url ??\n undefined)\n : undefined;\n const isVideo = selectedKind === \"video\" && !!displayVideo;\n\n // Tagged products — filter playlist items where relateable_type is \"Product\"\n const taggedProducts =\n playlist?.items\n ?.filter((item) => item.relateable_type === \"Product\")\n .map((item) => item.relateable)\n .filter((p): p is NonNullable<typeof p> => !!p) || [];\n\n // Loading state\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center py-16\">\n <Spinner className=\"size-8\" />\n </div>\n );\n }\n\n // No data state\n if (!playlist) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-destructive text-sm\">\n Playlist not found or failed to load.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-col gap-4 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"mx-auto flex w-full max-w-480 flex-col gap-6 md:h-[calc(100vh-140px)] md:flex-row\">\n {/* Left Column - Image/Video with badge */}\n <div className=\"aspect-square w-full md:aspect-auto md:h-full\">\n <div className=\"relative h-full overflow-hidden rounded-2xl\">\n <SharePageImageDisplay\n displayImage={displayImage}\n displayTitle={displayTitle}\n displayVideo={displayVideo}\n isVideo={isVideo}\n badgeLabel=\"Playlist\"\n />\n </div>\n </div>\n\n {/* Right Column - Details and Related Sharables */}\n <div className=\"flex w-full flex-col md:overflow-y-auto\">\n {/* Details Panel */}\n <div className=\"space-y-4\">\n {/* Title */}\n <h1 className=\"text-foreground text-[26px] leading-[1.2] font-semibold\">\n {displayTitle}\n </h1>\n\n {/* Description */}\n {strippedDescription && (\n <div className=\"text-foreground/70 text-sm leading-relaxed\">\n <div\n className={\n !isDescriptionExpanded && shouldShowReadMore\n ? \"line-clamp-3\"\n : \"\"\n }\n >\n {strippedDescription}\n </div>\n {shouldShowReadMore && (\n <Button\n onClick={() =>\n setIsDescriptionExpanded(!isDescriptionExpanded)\n }\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-foreground hover:text-foreground/80 mt-1 h-auto p-0 text-xs font-normal underline\"\n >\n {isDescriptionExpanded ? \"Read less\" : \"Read more\"}\n </Button>\n )}\n </div>\n )}\n\n {/* Share Link Section */}\n <ShareLinkSection\n shareLink={shareLinkError ? null : shareLink || null}\n loading={shareLinkLoading}\n displayTitle={displayTitle}\n isVideo={isVideo}\n relateableId={Number(playlistId)}\n relateableType=\"Library\"\n />\n </div>\n\n <Separator className=\"border-foreground my-4\" />\n\n <div className=\"hide-scrollbar bg-background h-full overflow-y-auto rounded-lg\">\n {/* Tagged Products Section */}\n <TaggedProductsList\n products={taggedProducts}\n onProductClick={(productId) =>\n onNavigate?.(\"product\", String(productId))\n }\n />\n\n {/* Playlist Items Section */}\n <PlaylistItemsList\n items={playlist?.items || []}\n onSelectItem={setSelectedPlaylistItemIndex}\n selectedItemIndex={selectedPlaylistItemIndex}\n onNavigateToItem={(itemId, relateableType) => {\n if (!NAVIGABLE_RELATEABLE_TYPES.has(relateableType ?? \"\"))\n return;\n if (relateableType === \"Product\") {\n onNavigate?.(\"product\", String(itemId));\n } else if (relateableType === \"Page\") {\n onNavigate?.(\"page\", String(itemId));\n } else if (relateableType === \"Medium\") {\n onNavigate?.(\"media\", String(itemId));\n }\n }}\n />\n </div>\n </div>\n </div>\n {/* Delete confirmation dialog */}\n <Dialog open={isDeleteOpen} onOpenChange={setIsDeleteOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Delete Playlist</DialogTitle>\n <DialogDescription>\n Are you sure you want to delete this playlist? This action cannot\n be undone.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => setIsDeleteOpen(false)}\n disabled={isDeleting}\n >\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n onClick={() => void handleDelete()}\n disabled={isDeleting}\n >\n {isDeleting ? \"Deleting...\" : \"Delete\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type PlaylistSearchEngineOptimizer = {\n id?: number;\n title: string;\n description: string;\n image_url: string;\n image_path: string;\n block_crawler: boolean;\n};\n\nexport type PlaylistFormState = {\n id?: number;\n title: string;\n description: string | null;\n image_url: string | null;\n slug: string | null;\n custom_slug: boolean | null;\n category_id: number | null;\n application_theme_template_id: number | null;\n active: boolean;\n company_library: boolean | null;\n indexed_for_seo: boolean;\n countries: string[];\n search_engine_optimizer: PlaylistSearchEngineOptimizer | null;\n};\n\nexport type PlaylistLike = {\n id: number;\n title?: string | null;\n description?: string | null;\n image_url?: string | null;\n slug?: string | null;\n custom_slug?: boolean | null;\n category_id?: number | null;\n application_theme_template_id?: number | null;\n active?: boolean;\n company_library?: boolean | null;\n indexed_for_seo?: boolean;\n countries?: Array<{ iso: string }> | null;\n search_engine_optimizer?: PlaylistSearchEngineOptimizer | null;\n canonical_url?: string | null;\n preview_link?: string | null;\n items?: Array<unknown> | null;\n};\n\ntype ValidationErrors = {\n [K in keyof PlaylistFormState]?: string;\n};\n\ninterface PlaylistFormContextValue {\n form: PlaylistFormState;\n validationErrors: ValidationErrors;\n isDirty: boolean;\n updateField: <K extends keyof PlaylistFormState>(\n field: K,\n value: PlaylistFormState[K],\n ) => void;\n updateSeo: (\n updates: Partial<PlaylistSearchEngineOptimizer> & {\n slug?: string | null;\n },\n ) => void;\n validateForm: () => boolean;\n clearFieldError: (field: keyof PlaylistFormState) => void;\n resetForm: (nextPlaylist?: PlaylistLike) => void;\n}\n\nconst PlaylistFormContext = createContext<PlaylistFormContextValue | undefined>(\n undefined,\n);\n\nconst createDefaultSeo = (title: string): PlaylistSearchEngineOptimizer => ({\n title: title || \"\",\n description: \"\",\n image_url: \"\",\n image_path: \"\",\n block_crawler: false,\n});\n\nconst mapPlaylistToForm = (playlist?: PlaylistLike): PlaylistFormState => ({\n id: playlist?.id,\n title: playlist?.title ?? \"\",\n description: playlist?.description ?? null,\n image_url: playlist?.image_url ?? null,\n slug: playlist?.slug ?? \"\",\n custom_slug: playlist?.custom_slug ?? false,\n category_id: playlist?.category_id ?? null,\n application_theme_template_id:\n playlist?.application_theme_template_id ?? null,\n active: playlist?.active ?? false,\n company_library: playlist?.company_library ?? true,\n indexed_for_seo: playlist?.indexed_for_seo ?? false,\n countries: playlist?.countries?.map((country) => country.iso) ?? [],\n search_engine_optimizer: playlist?.search_engine_optimizer ?? null,\n});\n\nexport function PlaylistFormProvider({\n children,\n playlist,\n}: {\n children: React.ReactNode;\n playlist?: PlaylistLike;\n}) {\n const initialForm = useMemo(() => mapPlaylistToForm(playlist), [playlist]);\n const [form, setForm] = useState<PlaylistFormState>(initialForm);\n const [validationErrors, setValidationErrors] = useState<ValidationErrors>(\n {},\n );\n\n const isDirty = useMemo(() => {\n return JSON.stringify(form) !== JSON.stringify(initialForm);\n }, [form, initialForm]);\n\n const prevPlaylistRef = useRef<string>(JSON.stringify(playlist));\n\n useEffect(() => {\n const serialized = JSON.stringify(playlist);\n if (serialized === prevPlaylistRef.current) return;\n prevPlaylistRef.current = serialized;\n setForm(mapPlaylistToForm(playlist));\n }, [playlist]);\n\n const updateField = useCallback(\n <K extends keyof PlaylistFormState>(\n field: K,\n value: PlaylistFormState[K],\n ) => {\n setForm((prev) => ({ ...prev, [field]: value }));\n if (validationErrors[field]) {\n setValidationErrors((prev) => {\n const next = { ...prev };\n delete next[field];\n return next;\n });\n }\n },\n [validationErrors],\n );\n\n const updateSeo = useCallback(\n (\n updates: Partial<PlaylistSearchEngineOptimizer> & {\n slug?: string | null;\n },\n ) => {\n setForm((prev) => {\n const currentSeo =\n prev.search_engine_optimizer ?? createDefaultSeo(prev.title);\n const nextSeo = { ...currentSeo };\n\n if (updates.title !== undefined) nextSeo.title = updates.title ?? \"\";\n if (updates.description !== undefined)\n nextSeo.description = updates.description ?? \"\";\n if (updates.image_url !== undefined)\n nextSeo.image_url = updates.image_url ?? \"\";\n if (updates.image_path !== undefined)\n nextSeo.image_path = updates.image_path ?? \"\";\n if (updates.block_crawler !== undefined)\n nextSeo.block_crawler = updates.block_crawler ?? false;\n\n const nextSlug =\n updates.slug !== undefined ? (updates.slug ?? null) : prev.slug;\n\n return {\n ...prev,\n slug: nextSlug,\n search_engine_optimizer: nextSeo,\n };\n });\n },\n [],\n );\n\n const validateForm = useCallback(() => {\n const errors: ValidationErrors = {};\n if (!form.title || !form.title.trim()) {\n errors.title = \"Title is required\";\n }\n setValidationErrors(errors);\n return Object.keys(errors).length === 0;\n }, [form.title]);\n\n const clearFieldError = useCallback((field: keyof PlaylistFormState) => {\n setValidationErrors((prev) => {\n const next = { ...prev };\n delete next[field];\n return next;\n });\n }, []);\n\n const resetForm = useCallback(\n (nextPlaylist?: PlaylistLike) => {\n setForm(mapPlaylistToForm(nextPlaylist ?? playlist));\n setValidationErrors({});\n },\n [playlist],\n );\n\n const value = useMemo(\n () => ({\n form,\n validationErrors,\n isDirty,\n updateField,\n updateSeo,\n validateForm,\n clearFieldError,\n resetForm,\n }),\n [\n form,\n validationErrors,\n isDirty,\n updateField,\n updateSeo,\n validateForm,\n clearFieldError,\n resetForm,\n ],\n );\n\n return (\n <PlaylistFormContext.Provider value={value}>\n {children}\n </PlaylistFormContext.Provider>\n );\n}\n\nexport function usePlaylistForm() {\n const context = useContext(PlaylistFormContext);\n if (!context) {\n throw new Error(\"usePlaylistForm must be used within PlaylistFormProvider\");\n }\n return context;\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useState,\n useCallback,\n useMemo,\n useEffect,\n useRef,\n} from \"react\";\n\nexport interface PlaylistItemLike {\n id: number;\n order?: number;\n relateable_type?: string | null;\n // Flat fields from BFF (preferred over relateable nested fields)\n title?: string | null;\n image_url?: string | null;\n kind?: string | null;\n relateable?: {\n id?: number;\n title?: string | null;\n image_url?: string | null;\n compressed_image_url?: string | null;\n kind?: string | null;\n video_url?: string | null;\n price?: string | null;\n sku?: string | null;\n description?: { body?: string | null } | null;\n [key: string]: unknown;\n };\n}\n\nexport interface PlaylistItemsContextValue {\n items: PlaylistItemLike[];\n setItems: (items: PlaylistItemLike[]) => void;\n addItem: (item: PlaylistItemLike) => void;\n removeItem: (itemId: number) => void;\n updateItems: (\n items:\n | PlaylistItemLike[]\n | ((prev: PlaylistItemLike[]) => PlaylistItemLike[]),\n ) => void;\n isDirty: boolean;\n}\n\nconst PlaylistItemsContext = createContext<\n PlaylistItemsContextValue | undefined\n>(undefined);\n\nexport function usePlaylistItems() {\n const context = useContext(PlaylistItemsContext);\n if (!context) {\n throw new Error(\n \"usePlaylistItems must be used within PlaylistItemsProvider\",\n );\n }\n return context;\n}\n\nexport function PlaylistItemsProvider({\n children,\n initialItems = [],\n}: {\n children: React.ReactNode;\n initialItems?: PlaylistItemLike[];\n}) {\n const [items, setItems] = useState<PlaylistItemLike[]>(initialItems);\n const [initialSnapshot, setInitialSnapshot] =\n useState<PlaylistItemLike[]>(initialItems);\n\n const prevInitialRef = useRef<string>(JSON.stringify(initialItems));\n\n useEffect(() => {\n const serialized = JSON.stringify(initialItems);\n if (serialized === prevInitialRef.current) return;\n prevInitialRef.current = serialized;\n setItems(initialItems);\n setInitialSnapshot(initialItems);\n }, [initialItems]);\n\n const isDirty = useMemo(\n () => JSON.stringify(items) !== JSON.stringify(initialSnapshot),\n [items, initialSnapshot],\n );\n\n const addItem = useCallback((item: PlaylistItemLike) => {\n setItems((prev) => [...prev, item]);\n }, []);\n\n const removeItem = useCallback((itemId: number) => {\n setItems((prev) => prev.filter((item) => item.id !== itemId));\n }, []);\n\n const updateItems = useCallback(\n (\n newItems:\n | PlaylistItemLike[]\n | ((prev: PlaylistItemLike[]) => PlaylistItemLike[]),\n ) => {\n setItems((prev) =>\n typeof newItems === \"function\" ? newItems(prev) : newItems,\n );\n },\n [],\n );\n\n const value: PlaylistItemsContextValue = useMemo(\n () => ({\n items,\n setItems,\n addItem,\n removeItem,\n updateItems,\n isDirty,\n }),\n [items, addItem, removeItem, updateItems, isDirty],\n );\n\n return (\n <PlaylistItemsContext.Provider value={value}>\n {children}\n </PlaylistItemsContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@fluid-app/ui-primitives\";\nimport { Trash2 } from \"lucide-react\";\nimport {\n useScreenHeaderActions,\n useScreenHeaderBreadcrumbs,\n} from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { usePlaylistForm } from \"./PlaylistFormProvider\";\nimport { usePlaylistItems } from \"./PlaylistItemsContext\";\nimport { useShareablesUI } from \"../../../context\";\n\ninterface PlaylistFormHeaderProps {\n playlistId?: string;\n isEditMode: boolean;\n onSubmit: () => Promise<void>;\n isSaving: boolean;\n onBack?: () => void;\n}\n\nexport function PlaylistFormHeader({\n playlistId,\n isEditMode,\n onSubmit,\n isSaving,\n}: PlaylistFormHeaderProps) {\n const { form, isDirty: formIsDirty } = usePlaylistForm();\n const { isDirty: itemsIsDirty } = usePlaylistItems();\n const { onDeletePlaylist, showToast, navigate } = useShareablesUI();\n const [isDeleteOpen, setIsDeleteOpen] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n\n const isFormValid = useMemo(() => {\n return !!(form.title && form.title.trim());\n }, [form.title]);\n\n const isDirty = formIsDirty || itemsIsDirty;\n const isMutating = isDeleting || isSaving;\n\n const handleDelete = async () => {\n if (!playlistId || !onDeletePlaylist) return;\n setIsDeleting(true);\n try {\n await onDeletePlaylist(Number(playlistId));\n showToast({ title: \"Playlist deleted successfully\", type: \"success\" });\n navigate(\"playlists\");\n } catch (error) {\n showToast({\n title: \"Failed to delete playlist\",\n type: \"error\",\n error,\n });\n } finally {\n setIsDeleting(false);\n setIsDeleteOpen(false);\n }\n };\n\n // Push actions/breadcrumbs into the portal shell header.\n // Returns true if inside a ScreenHeaderProvider (portal shell).\n const headerActions = useMemo(\n () => (\n <div className=\"flex items-center gap-2\">\n {playlistId && onDeletePlaylist && (\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => setIsDeleteOpen(true)}\n disabled={isMutating}\n >\n <Trash2 className=\"mr-1 h-4 w-4\" />\n Delete\n </Button>\n )}\n <Button\n onClick={() => {\n onSubmit().catch(() => {});\n }}\n disabled={isMutating || !isDirty || !isFormValid}\n size=\"sm\"\n >\n {isSaving ? \"Saving...\" : \"Save\"}\n </Button>\n </div>\n ),\n [\n playlistId,\n onDeletePlaylist,\n isMutating,\n isDirty,\n isFormValid,\n isSaving,\n onSubmit,\n ],\n );\n useScreenHeaderActions(headerActions);\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbLink\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n navigate(\"playlists\");\n }}\n >\n Playlists\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">\n {isEditMode ? \"Edit Playlist\" : \"New Playlist\"}\n </BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [isEditMode, navigate],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n return (\n <Dialog open={isDeleteOpen} onOpenChange={setIsDeleteOpen}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Delete Playlist</DialogTitle>\n <DialogDescription>\n Are you sure you want to delete this playlist? This action cannot be\n undone.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button\n variant=\"outline\"\n onClick={() => setIsDeleteOpen(false)}\n disabled={isDeleting}\n >\n Cancel\n </Button>\n <Button\n variant=\"destructive\"\n onClick={() => void handleDelete()}\n disabled={isDeleting}\n >\n {isDeleting ? \"Deleting...\" : \"Delete\"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useEditor, EditorContent } from \"@tiptap/react\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport TextAlign from \"@tiptap/extension-text-align\";\nimport Underline from \"@tiptap/extension-underline\";\nimport {\n AlignLeft,\n AlignCenter,\n AlignRight,\n AlignJustify,\n List,\n ListOrdered,\n} from \"lucide-react\";\nimport { cn } from \"@fluid-app/ui-primitives\";\n\nexport interface RichTextEditorProps {\n value: string;\n onChange: (html: string) => void;\n placeholder?: string;\n className?: string;\n editorClassName?: string;\n}\n\nexport function RichTextEditor({\n value,\n onChange,\n placeholder = \"Start writing...\",\n className,\n editorClassName,\n}: RichTextEditorProps) {\n const editor = useEditor({\n extensions: [\n StarterKit.configure({\n bulletList: { keepMarks: true, keepAttributes: false },\n orderedList: { keepMarks: true, keepAttributes: false },\n }),\n Placeholder.configure({ placeholder }),\n TextAlign.configure({\n types: [\"paragraph\"],\n alignments: [\"left\", \"center\", \"right\", \"justify\"],\n }),\n Underline,\n ],\n content: value || \"\",\n onUpdate: ({ editor }) => {\n onChange(editor.getHTML());\n },\n });\n\n useEffect(() => {\n if (!editor) return;\n if (editor.getHTML() !== value) {\n editor.commands.setContent(value || \"\", false);\n }\n }, [editor, value]);\n\n const buttonBase =\n \"flex h-7 w-7 items-center justify-center rounded text-xs transition-colors\";\n const buttonActive = \"bg-gray-100 text-primary\";\n const buttonInactive = \"text-gray-400 hover:bg-gray-50\";\n const separator = <div className=\"mx-1 h-5 w-px bg-gray-200\" />;\n\n return (\n <div\n className={cn(\n \"border-border flex flex-col overflow-hidden rounded-lg border\",\n className,\n )}\n >\n {/* Toolbar */}\n <div className=\"border-border flex items-center gap-0.5 border-b bg-gray-50 px-2 py-1.5\">\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleBold().run()}\n disabled={!editor?.can().chain().focus().toggleBold().run()}\n className={cn(\n buttonBase,\n \"font-bold\",\n editor?.isActive(\"bold\") ? buttonActive : buttonInactive,\n )}\n title=\"Bold\"\n >\n B\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleItalic().run()}\n disabled={!editor?.can().chain().focus().toggleItalic().run()}\n className={cn(\n buttonBase,\n \"italic\",\n editor?.isActive(\"italic\") ? buttonActive : buttonInactive,\n )}\n title=\"Italic\"\n >\n I\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleUnderline().run()}\n disabled={!editor?.can().chain().focus().toggleUnderline().run()}\n className={cn(\n buttonBase,\n \"underline\",\n editor?.isActive(\"underline\") ? buttonActive : buttonInactive,\n )}\n title=\"Underline\"\n >\n U\n </button>\n {separator}\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().setTextAlign(\"left\").run()}\n className={cn(\n buttonBase,\n editor?.isActive({ textAlign: \"left\" })\n ? buttonActive\n : buttonInactive,\n )}\n title=\"Align left\"\n >\n <AlignLeft className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().setTextAlign(\"center\").run()}\n className={cn(\n buttonBase,\n editor?.isActive({ textAlign: \"center\" })\n ? buttonActive\n : buttonInactive,\n )}\n title=\"Align center\"\n >\n <AlignCenter className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().setTextAlign(\"right\").run()}\n className={cn(\n buttonBase,\n editor?.isActive({ textAlign: \"right\" })\n ? buttonActive\n : buttonInactive,\n )}\n title=\"Align right\"\n >\n <AlignRight className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().setTextAlign(\"justify\").run()}\n className={cn(\n buttonBase,\n editor?.isActive({ textAlign: \"justify\" })\n ? buttonActive\n : buttonInactive,\n )}\n title=\"Justify\"\n >\n <AlignJustify className=\"h-3.5 w-3.5\" />\n </button>\n {separator}\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleBulletList().run()}\n className={cn(\n buttonBase,\n editor?.isActive(\"bulletList\") ? buttonActive : buttonInactive,\n )}\n title=\"Bullet list\"\n >\n <List className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleOrderedList().run()}\n className={cn(\n buttonBase,\n editor?.isActive(\"orderedList\") ? buttonActive : buttonInactive,\n )}\n title=\"Ordered list\"\n >\n <ListOrdered className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n {/* Editor area */}\n <EditorContent\n editor={editor}\n className={cn(\"flex-1 overflow-y-auto p-4\", editorClassName)}\n />\n\n <style>{`\n .ProseMirror {\n outline: none;\n }\n .ProseMirror p.is-empty::before {\n color: #9ca3af;\n content: attr(data-placeholder);\n float: left;\n height: 0;\n pointer-events: none;\n }\n .ProseMirror ul {\n list-style-type: disc;\n padding-left: 1.5rem;\n margin: 0.5rem 0;\n }\n .ProseMirror ol {\n list-style-type: decimal;\n padding-left: 1.5rem;\n margin: 0.5rem 0;\n }\n .ProseMirror li {\n margin: 0.25rem 0;\n display: list-item;\n }\n .ProseMirror li > p {\n margin: 0;\n }\n `}</style>\n </div>\n );\n}\n","\"use client\";\n\nimport { Input, Label, cn } from \"@fluid-app/ui-primitives\";\nimport { usePlaylistForm } from \"./PlaylistFormProvider\";\nimport { RichTextEditor } from \"../RichTextEditor\";\n\nexport function PlaylistFormDetails() {\n const { form, updateField, validationErrors } = usePlaylistForm();\n\n return (\n <div className=\"border-border bg-card w-full rounded-lg border p-4 shadow-xs\">\n <div className=\"space-y-6\">\n <div>\n <h2 className=\"text-md text-foreground font-semibold\">Playlist</h2>\n <p className=\"text-muted-foreground text-sm\">\n Name your playlist and add a short description.\n </p>\n </div>\n\n <div className=\"space-y-4\">\n <div className=\"space-y-1\">\n <Label className=\"text-foreground font-medium\">Name *</Label>\n <Input\n name=\"title\"\n placeholder=\"Playlist name\"\n value={form.title}\n onChange={(e) => updateField(\"title\", e.target.value)}\n required\n className={cn(\n validationErrors.title && \"ring-destructive ring-1\",\n )}\n />\n {validationErrors.title && (\n <p className=\"text-destructive text-xs\">\n {validationErrors.title}\n </p>\n )}\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <Label className=\"text-foreground font-medium\">Description</Label>\n <div className=\"border-border rounded-[6px] border shadow-xs\">\n <RichTextEditor\n value={form.description || \"\"}\n onChange={(value) => updateField(\"description\", value)}\n className=\"h-48 border-0\"\n editorClassName=\"h-36 overflow-auto\"\n placeholder=\"Describe this playlist...\"\n />\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport React from \"react\";\nimport { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\ninterface SortableRowProps {\n children: React.ReactNode;\n id: string;\n enableReordering?: boolean;\n}\n\nexport function SortableRow({\n children,\n id,\n enableReordering = true,\n}: SortableRowProps) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id, disabled: !enableReordering });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n };\n\n return (\n <tr ref={setNodeRef} style={style} {...attributes}>\n {React.Children.map(children, (child, index) => {\n if (index === 0 && enableReordering) {\n return React.cloneElement(child as React.ReactElement, {\n ...listeners,\n });\n }\n return child;\n })}\n </tr>\n );\n}\n","\"use client\";\n\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@fluid-app/ui-primitives\";\nimport type { LucideIcon } from \"lucide-react\";\nimport {\n MoreHorizontal,\n Trash2,\n GripVertical,\n Image,\n ShoppingBag,\n FileText,\n Package,\n Video,\n} from \"lucide-react\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n type DragEndEvent,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport type { PlaylistItemLike } from \"./PlaylistItemsContext\";\nimport { SortableRow } from \"./SortableRow\";\n\nfunction typeBadgeIcon(relateableType: string, kind?: string): LucideIcon {\n const k = kind?.toLowerCase() ?? \"\";\n if (relateableType === \"Medium\") {\n if (k === \"video\" || k.includes(\"video\")) return Video;\n return Image;\n }\n if (relateableType === \"Page\") return FileText;\n if (relateableType === \"Product\") return ShoppingBag;\n if (relateableType === \"EnrollmentPack\") return Package;\n return ShoppingBag;\n}\n\nfunction getTypeDisplay(relateableType: string, relateableKind?: string) {\n switch (relateableType) {\n case \"Product\":\n return \"Product\";\n case \"EnrollmentPack\":\n return \"Enrollment Pack\";\n case \"Medium\": {\n const kind = relateableKind?.toLowerCase() ?? \"\";\n if (kind === \"video\" || kind.includes(\"video\")) return \"Video\";\n if (kind === \"image\" || kind.includes(\"image\")) return \"Image\";\n return relateableKind || \"Media\";\n }\n case \"Page\":\n return \"Page\";\n default:\n return relateableType?.replace(/_/g, \" \") || \"Unknown\";\n }\n}\n\nfunction getItemIcon(relateableType: string) {\n switch (relateableType) {\n case \"Medium\":\n return <Image className=\"text-muted-foreground h-4 w-4\" />;\n case \"Page\":\n return <FileText className=\"text-muted-foreground h-4 w-4\" />;\n case \"Product\":\n return <ShoppingBag className=\"text-muted-foreground h-4 w-4\" />;\n case \"EnrollmentPack\":\n return <Package className=\"text-muted-foreground h-4 w-4\" />;\n default:\n return <Image className=\"text-muted-foreground h-4 w-4\" />;\n }\n}\n\ntype TableRow = {\n id: number | string;\n relateable_type?: string | null;\n relateable_id?: number;\n relateable?: PlaylistItemLike[\"relateable\"];\n order: number;\n title: string;\n image_url?: string | null;\n kind?: string | null;\n};\n\ninterface SortableTableProps {\n items: PlaylistItemLike[];\n setItems?: (items: PlaylistItemLike[]) => void;\n onDeleteItem: (itemId: number) => void;\n isDeletePending: boolean;\n enableReordering?: boolean;\n}\n\nexport function SortableTable({\n items,\n setItems,\n onDeleteItem,\n isDeletePending,\n enableReordering = true,\n}: SortableTableProps) {\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n if (active.id !== over?.id && setItems) {\n const oldIndex = items.findIndex(\n (item) => item.id?.toString() === active.id,\n );\n const newIndex = items.findIndex(\n (item) => item.id?.toString() === over?.id,\n );\n setItems(arrayMove(items, oldIndex, newIndex));\n }\n };\n\n const tableData: TableRow[] = items.map((item, index) => ({\n id: item.id || `item-${index}`,\n relateable_type: item.relateable_type,\n relateable_id: item.relateable?.id,\n relateable: item.relateable,\n order: index + 1,\n title:\n item.title ??\n item.relateable?.title ??\n `${item.relateable_type} #${item.relateable?.id}`,\n image_url: item.image_url ?? item.relateable?.image_url ?? null,\n kind: item.kind ?? item.relateable?.kind ?? null,\n }));\n\n const tableContent = (\n <div className=\"border-border w-full overflow-x-auto rounded-lg border\">\n <table className=\"w-full min-w-max\">\n <thead className=\"bg-muted\">\n <tr>\n <th className=\"text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase\">\n Order\n </th>\n <th className=\"text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase\">\n Item\n </th>\n <th className=\"text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase\">\n Type\n </th>\n <th className=\"text-muted-foreground px-6 py-3 text-left text-xs font-medium tracking-wider uppercase\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-border bg-card divide-y\">\n {tableData.map((row) => (\n <SortableRow\n key={row.id}\n id={row.id.toString()}\n enableReordering={enableReordering}\n >\n <td className=\"px-6 py-4 whitespace-nowrap\">\n <div className=\"flex items-center gap-2\">\n <div className={enableReordering ? \"cursor-move\" : \"\"}>\n <GripVertical\n className={`h-4 w-4 ${enableReordering ? \"text-muted-foreground\" : \"text-muted-foreground/50\"}`}\n />\n </div>\n <div className=\"text-foreground text-sm font-medium\">\n {row.order}\n </div>\n </div>\n </td>\n <td className=\"max-w-xs px-6 py-4 lg:max-w-md\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <div className=\"bg-muted flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded\">\n {row.image_url ? (\n <img\n src={String(row.image_url)}\n alt={String(row.title)}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n getItemIcon(row.relateable_type || \"\")\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-foreground truncate text-sm font-medium\">\n {row.title || \"Untitled\"}\n </div>\n </div>\n </div>\n </td>\n <td className=\"px-6 py-4 whitespace-nowrap\">\n <div className=\"bg-muted text-foreground inline-flex items-center gap-1 rounded-full px-2 py-1 text-xs\">\n {(() => {\n const Icon = typeBadgeIcon(\n row.relateable_type || \"\",\n row.kind || \"\",\n );\n return (\n <>\n <Icon className=\"h-3 w-3 shrink-0\" />\n {getTypeDisplay(\n row.relateable_type || \"\",\n row.kind || \"\",\n )}\n </>\n );\n })()}\n </div>\n </td>\n <td className=\"px-6 py-4 text-right text-sm font-medium whitespace-nowrap\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"flex h-8 w-8 items-center justify-center p-0\"\n disabled={isDeletePending}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n onClick={() => {\n const itemId =\n typeof row.id === \"number\"\n ? row.id\n : parseInt(String(row.id).replace(\"item-\", \"\"));\n onDeleteItem(itemId);\n }}\n variant=\"destructive\"\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete Item\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </td>\n </SortableRow>\n ))}\n </tbody>\n </table>\n </div>\n );\n\n if (enableReordering) {\n return (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext\n items={tableData.map((item) => item.id.toString())}\n strategy={verticalListSortingStrategy}\n >\n {tableContent}\n </SortableContext>\n </DndContext>\n );\n }\n\n return tableContent;\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { Plus } from \"lucide-react\";\nimport {\n FilePicker,\n FilePickerApiProvider,\n FilePickerProvider,\n type FilePickerContextValue,\n} from \"@fluid-app/file-picker-ui\";\nimport type { FilePickerResult } from \"@fluid-app/file-picker-core\";\nimport {\n useAddItemToPlaylistMutation,\n useRemoveItemsFromPlaylistMutation,\n useShareablesApi,\n} from \"@fluid-app/shareables-core\";\nimport type { shareables } from \"@fluid-app/shareables-core\";\nimport { useShareablesUI } from \"../../../context\";\nimport {\n usePlaylistItems,\n type PlaylistItemLike,\n} from \"./PlaylistItemsContext\";\nimport { SortableTable } from \"./SortableTable\";\n\nconst PLAYLIST_CONTENT_TYPES = new Set<string>([\n \"Medium\",\n \"Page\",\n \"Product\",\n \"EnrollmentPack\",\n]);\n\nfunction computeOrderedItems(items: PlaylistItemLike[]): PlaylistItemLike[] {\n const required: PlaylistItemLike[] = [];\n const optional: PlaylistItemLike[] = [];\n\n items.forEach((item) => {\n const type = item.relateable_type;\n if (type === \"Medium\" || type === \"Page\") {\n required.push(item);\n } else if (type === \"Product\" || type === \"EnrollmentPack\") {\n optional.push(item);\n }\n });\n\n const result: PlaylistItemLike[] = [];\n required.forEach((item, index) => {\n if (item.id) {\n result.push({ ...item, order: index + 1 });\n }\n });\n optional.forEach((item, index) => {\n if (item.id) {\n result.push({ ...item, order: required.length + index + 1 });\n }\n });\n return result;\n}\n\ninterface PlaylistItemsSectionProps {\n playlistId?: number;\n}\n\nexport function PlaylistItemsSection({\n playlistId,\n}: PlaylistItemsSectionProps) {\n const { showToast, filePickerApi } = useShareablesUI();\n const api = useShareablesApi();\n const [filePickerOpen, setFilePickerOpen] = useState(false);\n\n const {\n items: contextItems,\n updateItems,\n addItem,\n removeItem,\n } = usePlaylistItems();\n\n const tableItems = contextItems;\n\n const { contentItems, tailItems } = useMemo(() => {\n const content: PlaylistItemLike[] = [];\n const tail: PlaylistItemLike[] = [];\n tableItems.forEach((item) => {\n if (\n item.relateable_type &&\n PLAYLIST_CONTENT_TYPES.has(item.relateable_type)\n ) {\n content.push(item);\n } else {\n tail.push(item);\n }\n });\n return { contentItems: content, tailItems: tail };\n }, [tableItems]);\n\n const addItemMutation = useAddItemToPlaylistMutation({\n onError: (error: Error) => {\n showToast({\n title: \"Failed to add item to playlist\",\n type: \"error\",\n error,\n });\n },\n });\n\n const removeItemMutation = useRemoveItemsFromPlaylistMutation({\n onSuccess: () => {\n showToast({\n title: \"Item removed from playlist successfully\",\n type: \"success\",\n });\n },\n onError: (error: Error) => {\n showToast({\n title: \"Failed to remove item from playlist\",\n type: \"error\",\n error,\n });\n },\n });\n\n const mergeAndOrder = useCallback(\n (reorderedContent: PlaylistItemLike[]) => {\n const merged = [...reorderedContent, ...tailItems];\n updateItems(computeOrderedItems(merged));\n },\n [tailItems, updateItems],\n );\n\n const handleDeleteItem = (itemId: number) => {\n removeItem(itemId);\n if (playlistId) {\n removeItemMutation.mutate({\n playlistId,\n itemIds: [itemId],\n });\n }\n };\n\n const handleFilePickerResults = async (results: FilePickerResult[]) => {\n setFilePickerOpen(false);\n const mediaResults = results.filter((r) =>\n r.asset_code.startsWith(\"media_\"),\n );\n if (mediaResults.length === 0) {\n showToast({\n title: \"No media items selected\",\n type: \"warning\",\n });\n return;\n }\n\n for (const result of mediaResults) {\n const label =\n result.metadata?.file_name?.replace(/\\.[^/.]+$/, \"\") ||\n `Medium #${result.asset_id}`;\n\n const relateableId = result.asset_id;\n const relateableType = \"Medium\";\n\n const itemExists = tableItems.some(\n (existingItem) =>\n existingItem.relateable_type === relateableType &&\n existingItem.relateable?.id === relateableId,\n );\n\n if (itemExists) {\n showToast({\n title: \"This item is already in the playlist\",\n type: \"error\",\n });\n continue;\n }\n\n const newItem: PlaylistItemLike = {\n id: Date.now() + Math.random(),\n order: 0,\n relateable_type: relateableType,\n relateable: {\n id: relateableId,\n title: label,\n image_url: result.thumbnail_url ?? result.file_url ?? null,\n },\n };\n\n if (playlistId) {\n try {\n await addItemMutation.mutateAsync({\n playlistId,\n newItem,\n data: {\n relateable_type: relateableType,\n relateable_id: relateableId,\n order: 0,\n },\n });\n showToast({\n title: \"Item added to playlist successfully\",\n type: \"success\",\n });\n } catch {\n // Error already handled by mutation onError\n }\n } else {\n addItem(newItem);\n showToast({\n title: \"Item added. Save the playlist to persist these items.\",\n type: \"warning\",\n });\n }\n }\n };\n\n const filePickerContextValue = useMemo<FilePickerContextValue | null>(() => {\n if (!filePickerApi) return null;\n return {\n toast: {\n success: (msg: string) => showToast({ title: msg, type: \"success\" }),\n error: (msg: string, error?: unknown) =>\n showToast({\n title: error instanceof Error ? `${msg}: ${error.message}` : msg,\n type: \"error\",\n }),\n loading: () => \"\",\n dismiss: () => {},\n },\n shareablesClient: {\n media: {\n list: (filters: unknown) =>\n api.media.getMedia((filters ?? {}) as shareables.MediaFilters),\n },\n },\n };\n }, [filePickerApi, showToast, api]);\n\n return (\n <div className=\"border-border bg-card rounded-lg border p-4\">\n <div className=\"space-y-4\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0\">\n <h3 className=\"text-md text-foreground font-semibold\">Content</h3>\n <p className=\"text-muted-foreground text-sm\">\n Use <strong>Add content</strong> to open the file picker and\n choose media from your library. Drag rows to reorder.\n </p>\n </div>\n <div className=\"flex shrink-0 flex-wrap items-center justify-end gap-2\">\n <Button\n type=\"button\"\n disabled={addItemMutation.isPending || !filePickerApi}\n variant=\"default\"\n size=\"sm\"\n className=\"flex min-w-25 items-center gap-2\"\n onClick={() => setFilePickerOpen(true)}\n >\n <Plus className=\"h-4 w-4\" />\n Add content\n </Button>\n </div>\n </div>\n\n <SortableTable\n items={contentItems}\n setItems={(reordered) => mergeAndOrder(reordered)}\n onDeleteItem={handleDeleteItem}\n isDeletePending={removeItemMutation.isPending}\n enableReordering\n />\n </div>\n\n {filePickerContextValue && filePickerApi && (\n <FilePickerApiProvider api={filePickerApi}>\n <FilePickerProvider value={filePickerContextValue}>\n <FilePicker\n open={filePickerOpen}\n onFilesSelected={(selected) =>\n void handleFilePickerResults(selected)\n }\n onClose={() => setFilePickerOpen(false)}\n config={{\n maxFiles: 50,\n allowedMethods: [\"media\"],\n }}\n />\n </FilePickerProvider>\n </FilePickerApiProvider>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { usePlaylistForm, type PlaylistLike } from \"./PlaylistFormProvider\";\nimport {\n usePlaylistItems,\n type PlaylistItemLike,\n} from \"./PlaylistItemsContext\";\n\nconst OG_PLACEHOLDER_IMAGE =\n \"https://ik.imagekit.io/fluid/s3/placeholders/image.jpg?w=1200&q=75\";\n\nconst PLAYLIST_PREVIEW_CONTENT_TYPES = new Set<string>([\n \"Medium\",\n \"Page\",\n \"Product\",\n \"EnrollmentPack\",\n]);\n\nfunction getImageFromRelateable(\n item: PlaylistItemLike | undefined,\n): string | null {\n const r = item?.relateable;\n if (!r) return null;\n const url = r.image_url || r.compressed_image_url;\n const t = url?.trim();\n return t || null;\n}\n\nfunction getFirstOrderedContentItem(\n items: PlaylistItemLike[],\n): PlaylistItemLike | undefined {\n const content = items.filter(\n (item) =>\n item.relateable_type &&\n PLAYLIST_PREVIEW_CONTENT_TYPES.has(item.relateable_type),\n );\n if (content.length === 0) return undefined;\n return [...content].sort(\n (a, b) =>\n (a.order ?? Number.POSITIVE_INFINITY) -\n (b.order ?? Number.POSITIVE_INFINITY),\n )[0];\n}\n\nfunction stripHtml(html: string): string {\n if (!html) return \"\";\n const doc = new DOMParser().parseFromString(html, \"text/html\");\n return doc.body.textContent || \"\";\n}\n\nfunction buildPlaylistUrl(options: {\n playlist?: PlaylistLike | null;\n formSlug?: string | null;\n baseUrl?: string;\n preview?: boolean;\n}): string {\n const { playlist, formSlug, baseUrl, preview = false } = options;\n\n if (playlist?.canonical_url) {\n return preview\n ? `${playlist.canonical_url}?preview=true`\n : playlist.canonical_url;\n }\n if (playlist?.preview_link) {\n return preview\n ? playlist.preview_link\n : playlist.preview_link.replace(\"?preview=true\", \"\");\n }\n const slug = formSlug || playlist?.slug;\n if (baseUrl && slug) {\n const cleanBaseUrl = baseUrl.replace(/\\/$/, \"\");\n const url = `${cleanBaseUrl}/playlists/${slug}`;\n return preview ? `${url}?preview=true` : url;\n }\n return \"\";\n}\n\nexport interface PlaylistOpenGraphPreviewProps {\n playlist?: PlaylistLike | null;\n playlistShareBaseUrl?: string;\n}\n\nexport function PlaylistOpenGraphPreview({\n playlist,\n playlistShareBaseUrl,\n}: PlaylistOpenGraphPreviewProps) {\n const { form } = usePlaylistForm();\n const { items } = usePlaylistItems();\n const seo = form.search_engine_optimizer;\n\n const firstContentItem = useMemo(\n () => getFirstOrderedContentItem(items),\n [items],\n );\n\n const firstItemImageUrl = useMemo(\n () => getImageFromRelateable(firstContentItem),\n [firstContentItem],\n );\n\n const title = (seo?.title || form.title || \"\").trim() || \"Playlist title\";\n\n const rawDescription =\n (seo?.description || \"\").trim() || stripHtml(form.description || \"\") || \"\";\n const description =\n rawDescription ||\n \"Description shown when this playlist is shared on social platforms.\";\n\n const imageUrl =\n firstItemImageUrl ||\n (seo?.image_url || \"\").trim() ||\n (form.image_url || \"\").trim();\n\n const shareUrl = useMemo(\n () =>\n buildPlaylistUrl({\n playlist,\n formSlug: form.slug,\n baseUrl: playlistShareBaseUrl,\n preview: false,\n }),\n [playlist, form.slug, playlistShareBaseUrl],\n );\n\n const hostname = useMemo(() => {\n if (!shareUrl) return \"\";\n try {\n return new URL(shareUrl).hostname;\n } catch {\n return shareUrl.replace(/^https?:\\/\\//, \"\").split(\"/\")[0] ?? \"\";\n }\n }, [shareUrl]);\n\n return (\n <div className=\"border-border bg-card rounded-lg border p-4 shadow-xs\">\n <h3 className=\"text-foreground mb-2 text-sm font-semibold\">Preview</h3>\n <div className=\"border-border bg-card overflow-hidden rounded-lg border\">\n <div className=\"bg-muted aspect-[1200/630] w-full\">\n <img\n key={imageUrl || \"placeholder\"}\n src={imageUrl || OG_PLACEHOLDER_IMAGE}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n </div>\n <div className=\"space-y-1 p-3\">\n <p className=\"text-muted-foreground text-[11px] tracking-wide uppercase\">\n {hostname || \"your-site.com\"}\n </p>\n <p className=\"text-foreground line-clamp-2 text-base font-semibold\">\n {title}\n </p>\n <p className=\"text-muted-foreground line-clamp-3 text-sm leading-snug\">\n {description}\n </p>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useCallback } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport {\n useShareablesApi,\n useCreatePlaylistMutation,\n useUpdatePlaylistMutation,\n shareablesKeys,\n} from \"@fluid-app/shareables-core\";\nimport { Skeleton } from \"@fluid-app/ui-primitives\";\nimport { useShareablesUI } from \"../../context\";\nimport {\n PlaylistFormProvider,\n usePlaylistForm,\n type PlaylistLike,\n} from \"../playlists/form/PlaylistFormProvider\";\nimport {\n PlaylistItemsProvider,\n usePlaylistItems,\n type PlaylistItemLike,\n} from \"../playlists/form/PlaylistItemsContext\";\nimport { PlaylistFormHeader } from \"../playlists/form/PlaylistFormHeader\";\nimport { PlaylistFormDetails } from \"../playlists/form/PlaylistFormDetails\";\nimport { PlaylistItemsSection } from \"../playlists/form/PlaylistItemsSection\";\nimport { PlaylistOpenGraphPreview } from \"../playlists/form/PlaylistOpenGraphPreview\";\n\nexport interface PlaylistCreateScreenProps {\n playlistId?: string;\n onBack?: () => void;\n /** Hide the built-in header (use when the host app provides its own header chrome) */\n hideHeader?: boolean;\n /** Render custom children inside the form providers (e.g. portal shell header wiring) */\n renderHeaderSlot?: (props: {\n onSubmit: () => Promise<void>;\n isSaving: boolean;\n playlistId?: string;\n isEditMode: boolean;\n }) => React.ReactNode;\n}\n\nfunction PlaylistFormContent({\n playlistId,\n playlist,\n isEditMode,\n itemsToUse,\n onBack,\n hideHeader,\n renderHeaderSlot,\n}: {\n playlistId?: string;\n playlist?: PlaylistLike | null;\n isEditMode: boolean;\n itemsToUse: PlaylistItemLike[];\n onBack?: () => void;\n hideHeader?: boolean;\n renderHeaderSlot?: PlaylistCreateScreenProps[\"renderHeaderSlot\"];\n}) {\n const api = useShareablesApi();\n const { showToast, navigate, user } = useShareablesUI();\n const { items: contextItems } = usePlaylistItems();\n const { form, updateField, validateForm } = usePlaylistForm();\n\n const playlistTitle = form.title || \"\";\n const slugValue = form.slug ?? \"\";\n\n // Auto-generate slug from title\n useEffect(() => {\n const isCustomSlug = form.custom_slug || playlist?.custom_slug || false;\n if (playlistTitle && !isCustomSlug) {\n const generatedSlug = playlistTitle\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .replace(/-+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n if (generatedSlug !== slugValue) {\n updateField(\"slug\", generatedSlug);\n }\n }\n }, [\n playlistTitle,\n form.custom_slug,\n playlist?.custom_slug,\n slugValue,\n updateField,\n ]);\n\n const createMutation = useCreatePlaylistMutation({\n onSuccess: (createdPlaylist) => {\n showToast({ title: \"Playlist created successfully\", type: \"success\" });\n const newId = createdPlaylist.playlist.id;\n navigate(`playlists/${newId}/edit`);\n },\n onError: (error: Error) => {\n showToast({\n title: \"Failed to create playlist\",\n type: \"error\",\n error,\n });\n },\n });\n\n const updateMutation = useUpdatePlaylistMutation({\n onSuccess: () => {\n showToast({ title: \"Playlist updated successfully\", type: \"success\" });\n },\n onError: (error: Error) => {\n showToast({\n title: \"Failed to update playlist\",\n type: \"error\",\n error,\n });\n },\n });\n\n const itemsForSubmission = contextItems;\n\n const onSaveForm = useCallback(async (): Promise<number> => {\n if (!validateForm()) {\n showToast({\n title: \"Please fill out all required fields\",\n type: \"error\",\n });\n return Promise.reject(new Error(\"Validation failed\"));\n }\n\n const formData = {\n title: form.title,\n description: form.description ?? null,\n image_url: form.image_url ?? null,\n slug: form.slug || null,\n custom_slug: form.custom_slug ?? false,\n category_id: form.category_id ?? null,\n application_theme_template_id: form.application_theme_template_id\n ? Number(form.application_theme_template_id)\n : null,\n active: isEditMode ? (form.active ?? false) : true,\n company_library: true,\n indexed_for_seo: form.indexed_for_seo ?? false,\n available_countries: form.countries ?? [],\n search_engine_optimizer_attributes:\n form.search_engine_optimizer ?? undefined,\n };\n\n if (isEditMode && playlistId) {\n await updateMutation.mutateAsync({\n playlistId: parseInt(playlistId),\n data: {\n playlist: {\n ...formData,\n library_items_attributes: itemsForSubmission?.map((item) => ({\n id: item.id,\n order: item.order,\n })),\n },\n },\n });\n return parseInt(playlistId);\n }\n\n let searchEngineOptimizer = form.search_engine_optimizer;\n if (!searchEngineOptimizer) {\n searchEngineOptimizer = {\n title: form.title || \"\",\n description: \"\",\n image_url: \"\",\n image_path: \"\",\n block_crawler: false,\n };\n }\n\n const createdPlaylist = await createMutation.mutateAsync({\n playlist: {\n ...formData,\n search_engine_optimizer_attributes: searchEngineOptimizer,\n ...(user?.id ? { user_id: user.id } : {}),\n },\n });\n const newPlaylistId = createdPlaylist.playlist.id;\n\n if (itemsForSubmission.length > 0) {\n try {\n const itemsData = itemsForSubmission\n .filter(\n (\n item,\n ): item is PlaylistItemLike & {\n relateable_type: string;\n relateable: { id: number };\n } =>\n !!item.relateable_type && typeof item.relateable?.id === \"number\",\n )\n .map((item, index) => ({\n relateable_type: item.relateable_type,\n relateable_id: item.relateable.id,\n order: index + 1,\n }));\n\n await api.playlists.addItemToPlaylist(newPlaylistId, {\n items: itemsData,\n });\n } catch (itemError) {\n console.error(\"Error adding items to playlist:\", itemError);\n showToast({\n title: \"Playlist created but some items failed to add\",\n type: \"warning\",\n });\n }\n }\n\n return newPlaylistId;\n }, [\n validateForm,\n form,\n isEditMode,\n playlistId,\n itemsForSubmission,\n createMutation,\n updateMutation,\n showToast,\n api,\n user?.id,\n ]);\n\n const isSaving = createMutation.isPending || updateMutation.isPending;\n const handleSubmit = async () => {\n await onSaveForm();\n };\n\n return (\n <>\n {renderHeaderSlot?.({\n onSubmit: handleSubmit,\n isSaving,\n playlistId,\n isEditMode,\n })}\n {!hideHeader && !renderHeaderSlot && (\n <PlaylistFormHeader\n playlistId={playlistId}\n isEditMode={isEditMode}\n onSubmit={handleSubmit}\n isSaving={isSaving}\n onBack={onBack}\n />\n )}\n <div className=\"mx-auto w-full max-w-7xl space-y-6 px-6 pt-6 pb-8 md:px-10 md:py-8\">\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <div className=\"space-y-6 lg:col-span-2\">\n <PlaylistFormDetails />\n <PlaylistItemsSection\n playlistId={playlistId ? parseInt(playlistId, 10) : undefined}\n />\n </div>\n <div className=\"space-y-6 lg:col-span-1\">\n <PlaylistOpenGraphPreview playlist={playlist} />\n </div>\n </div>\n </div>\n </>\n );\n}\n\nexport function PlaylistCreateScreen({\n playlistId,\n onBack,\n hideHeader,\n renderHeaderSlot,\n}: PlaylistCreateScreenProps) {\n const api = useShareablesApi();\n const isEditMode = !!playlistId;\n\n const { data: playlistResponse, isLoading } = useQuery({\n queryKey: playlistId\n ? shareablesKeys.playlists.detail(parseInt(playlistId, 10))\n : [\"playlists\", \"detail\", null],\n queryFn: () => api.playlists.getPlaylistById(parseInt(playlistId!, 10)),\n enabled: isEditMode,\n });\n\n const playlist = playlistResponse?.playlist as PlaylistLike | undefined;\n const itemsToUse: PlaylistItemLike[] =\n (playlist?.items as PlaylistItemLike[] | undefined) ?? [];\n\n if (isEditMode && isLoading) {\n return (\n <div className=\"mx-auto max-w-7xl space-y-6 px-6 pt-6 pb-8 md:px-10 md:py-8\">\n <Skeleton className=\"h-8 w-48\" />\n <Skeleton className=\"h-64 w-full\" />\n </div>\n );\n }\n\n return (\n <PlaylistFormProvider playlist={playlist}>\n <PlaylistItemsProvider initialItems={itemsToUse}>\n <PlaylistFormContent\n playlistId={playlistId}\n playlist={playlist}\n isEditMode={isEditMode}\n itemsToUse={itemsToUse}\n onBack={onBack}\n hideHeader={hideHeader}\n renderHeaderSlot={renderHeaderSlot}\n />\n </PlaylistItemsProvider>\n </PlaylistFormProvider>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useShareablesApi } from \"@fluid-app/shareables-core\";\nimport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbPage,\n Card,\n Badge,\n Skeleton,\n} from \"@fluid-app/ui-primitives\";\nimport { SearchSort } from \"@fluid-app/ui-components/components/SearchSort\";\nimport { CirclePlay } from \"lucide-react\";\nimport { useScreenHeaderBreadcrumbs } from \"@fluid-app/portal-react/shell/ScreenHeaderContext\";\nimport { useRenderImage } from \"../../context\";\n\nconst PAGE_SIZE = 24;\n\nconst GRID_CLASS =\n \"grid grid-cols-1 gap-8 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-4\";\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\nexport interface FilesListingScreenProps {\n onNavigate?: (screen: string, detailId?: string) => void;\n}\n\nconst DEFAULT_IMAGE =\n \"https://assets.fluid.app/fluid-admin/images/we-commerce/we-commerce.png\";\n\nexport function FilesListingScreen({ onNavigate }: FilesListingScreenProps) {\n const api = useShareablesApi();\n const renderImage = useRenderImage();\n\n const headerBreadcrumbs = useMemo(\n () => (\n <Breadcrumb>\n <BreadcrumbList className=\"text-lg\">\n <BreadcrumbItem>\n <BreadcrumbPage className=\"font-semibold\">Files</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n ),\n [],\n );\n useScreenHeaderBreadcrumbs(headerBreadcrumbs);\n\n const [searchTerm, setSearchTerm] = useState(\"\");\n const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n const observerTarget = useRef<HTMLDivElement>(null);\n\n // Debounce search input\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedSearch(searchTerm);\n }, 300);\n return () => clearTimeout(timer);\n }, [searchTerm]);\n\n const {\n data,\n isLoading,\n isFetchingNextPage,\n hasNextPage,\n fetchNextPage,\n error,\n } = useInfiniteQuery({\n queryKey: [\"shareables-files\", debouncedSearch],\n queryFn: async ({ pageParam = 1 }) => {\n const response = await api.fileResources.getFileResources({\n search_query: debouncedSearch || undefined,\n pageParam: pageParam.toString(),\n pageSize: PAGE_SIZE.toString(),\n });\n return response;\n },\n getNextPageParam: (lastPage) => {\n const { current_page, total_pages } = lastPage.meta;\n return current_page < total_pages ? current_page + 1 : undefined;\n },\n initialPageParam: 1,\n });\n\n const files = useMemo(\n () => data?.pages.flatMap((page) => page.file_resources) ?? [],\n [data?.pages],\n );\n\n const handleIntersect = useCallback(\n (entries: IntersectionObserverEntry[]) => {\n if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) {\n fetchNextPage();\n }\n },\n [hasNextPage, isFetchingNextPage, fetchNextPage],\n );\n\n useEffect(() => {\n const target = observerTarget.current;\n if (!target) return;\n\n const observer = new IntersectionObserver(handleIntersect, {\n threshold: 0.1,\n rootMargin: \"200px\",\n });\n observer.observe(target);\n return () => observer.disconnect();\n }, [handleIntersect]);\n\n // Loading skeleton\n if (isLoading) {\n return (\n <div className=\"space-y-6 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"flex items-center gap-3\">\n <Skeleton className=\"h-10 flex-1\" />\n </div>\n <div className={GRID_CLASS}>\n {Array.from({ length: 8 }).map((_, i) => (\n <div key={i} className=\"space-y-2\">\n <Skeleton className=\"aspect-square w-full rounded-lg\" />\n <Skeleton className=\"h-4 w-3/4\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (error) {\n return (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-destructive text-sm\">\n Failed to load files. Please try again.\n </p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 px-4 py-4 md:px-10 md:py-6\">\n <div className=\"flex justify-end\">\n <div className=\"w-full max-w-sm\">\n <SearchSort\n searchValue={searchTerm}\n onSearchChange={setSearchTerm}\n placeholder=\"Search files...\"\n />\n </div>\n </div>\n\n {/* Files grid */}\n {files.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-16\">\n <p className=\"text-muted-foreground text-sm\">\n {debouncedSearch\n ? `No files match \"${debouncedSearch}\". Try a different search term.`\n : \"No files available.\"}\n </p>\n </div>\n ) : (\n <div className={GRID_CLASS}>\n {files.map((file) => {\n const isVideo = file.content_type?.startsWith(\"video/\");\n const fileUrl = file.url || \"#\";\n\n return (\n <Card\n key={file.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => window.open(fileUrl, \"_blank\")}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n window.open(fileUrl, \"_blank\");\n }\n }}\n className=\"group hover:bg-muted cursor-pointer gap-0 overflow-hidden rounded-lg border-0 p-0 shadow-none transition-colors\"\n >\n <div className=\"bg-muted relative aspect-square overflow-hidden rounded-lg\">\n {renderImage({\n src: file.preview_image_url || DEFAULT_IMAGE,\n alt: file.filename || \"Untitled File\",\n fill: true,\n className:\n \"object-cover transition-transform group-hover:scale-105\",\n })}\n {isVideo && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <div className=\"bg-foreground/50 flex h-16 w-16 items-center justify-center rounded-full backdrop-blur-sm\">\n <CirclePlay className=\"text-background h-12 w-12\" />\n </div>\n </div>\n )}\n {!isVideo && (\n <Badge\n className=\"absolute top-2 right-2 shadow-lg\"\n variant=\"default\"\n >\n {formatFileSize(file.content_size)}\n </Badge>\n )}\n </div>\n <div className=\"px-2 pt-2 pb-4\">\n <h3 className=\"text-foreground line-clamp-2 text-sm leading-tight font-bold\">\n {file.filename || \"Untitled File\"}\n </h3>\n <p className=\"text-muted-foreground mt-1 text-xs\">\n {file.content_type || \"File\"}\n </p>\n </div>\n </Card>\n );\n })}\n </div>\n )}\n\n {/* Loading more indicator */}\n {isFetchingNextPage && (\n <div className=\"flex justify-center py-4\">\n <div className=\"border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent\" />\n </div>\n )}\n\n {/* Intersection observer sentinel */}\n <div ref={observerTarget} className=\"h-1\" />\n </div>\n );\n}\n","import { ProductsScreen } from \"./screens/ProductsScreen\";\nimport { ProductDetailScreen } from \"./screens/ProductDetailScreen\";\nimport { MediaListingScreen } from \"./screens/MediaListingScreen\";\nimport { MediaDetailScreen } from \"./screens/MediaDetailScreen\";\nimport { MediaCreateScreen } from \"./screens/MediaCreateScreen\";\nimport { PlaylistsListingScreen } from \"./screens/PlaylistsListingScreen\";\nimport { PlaylistDetailScreen } from \"./screens/PlaylistDetailScreen\";\nimport { PlaylistCreateScreen } from \"./screens/PlaylistCreateScreen\";\nimport { FilesListingScreen } from \"./screens/FilesListingScreen\";\nimport { useShareablesUI } from \"../context\";\nimport type {\n PortalProductsResponse,\n PortalProductResponse,\n} from \"./portal-product-types\";\n\nexport interface ShareablesAppProps {\n /** Current sub-route: \"products\" | \"media\" | \"playlists\" | \"files\" | null */\n screen?: string | null;\n /** Detail ID when viewing a specific item */\n detailId?: string | null;\n /** Action for detail pages (e.g., \"edit\") */\n action?: string | null;\n /** Company logo URL for image fallbacks */\n companyLogoUrl?: string | null;\n /** Country code for product pricing */\n countryCode?: string;\n /** Portal-tenant products list fetcher */\n fetchProducts?: (\n search: string,\n cursor?: string,\n limit?: number,\n ) => Promise<PortalProductsResponse>;\n /** Portal-tenant single product fetcher */\n fetchProduct?: (id: string | number) => Promise<PortalProductResponse>;\n /** Called when navigating to a sub-screen */\n onNavigate?: (screen: string, detailId?: string) => void;\n /** Called when navigating back */\n onBack?: () => void;\n}\n\nexport function ShareablesApp({\n screen,\n detailId,\n action,\n onNavigate,\n onBack,\n countryCode,\n fetchProducts,\n fetchProduct,\n}: ShareablesAppProps) {\n const { readOnly } = useShareablesUI();\n let content: React.JSX.Element;\n\n switch (screen) {\n case \"media\":\n if (detailId === \"new\" && !readOnly) {\n content = <MediaCreateScreen onBack={onBack} onNavigate={onNavigate} />;\n } else if (detailId && detailId !== \"new\") {\n content = (\n <MediaDetailScreen\n mediaId={detailId}\n onNavigate={onNavigate}\n onBack={onBack}\n />\n );\n } else {\n content = <MediaListingScreen onNavigate={onNavigate} />;\n }\n break;\n case \"playlists\":\n case \"playlist\":\n if (detailId === \"new\" && !readOnly) {\n content = <PlaylistCreateScreen onBack={onBack} />;\n } else if (detailId && action === \"edit\" && !readOnly) {\n content = (\n <PlaylistCreateScreen playlistId={detailId} onBack={onBack} />\n );\n } else if (detailId && detailId !== \"new\") {\n content = (\n <PlaylistDetailScreen\n playlistId={detailId}\n onNavigate={onNavigate}\n onBack={onBack}\n />\n );\n } else {\n content = <PlaylistsListingScreen />;\n }\n break;\n case \"files\":\n content = <FilesListingScreen onNavigate={onNavigate} />;\n break;\n case \"products\":\n default:\n content = detailId ? (\n <ProductDetailScreen\n productId={detailId}\n countryCode={countryCode}\n fetchProduct={fetchProduct}\n onNavigate={onNavigate}\n onBack={onBack}\n />\n ) : (\n <ProductsScreen\n countryCode={countryCode}\n fetchProducts={fetchProducts}\n onNavigate={onNavigate}\n />\n );\n break;\n }\n\n return content;\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { ProductsScreen } from \"./screens/ProductsScreen\";\nimport { ProductDetailScreen } from \"./screens/ProductDetailScreen\";\nimport type {\n PortalProductsResponse,\n PortalProductResponse,\n} from \"./portal-product-types\";\n\nexport type {\n PortalProduct,\n PortalProductsResponse,\n PortalProductResponse,\n} from \"./portal-product-types\";\n\nexport interface ProductsAppProps {\n countryCode?: string;\n companyLogoUrl?: string | null;\n /** Portal-tenant products fetcher. When provided, the listing uses this\n * instead of the legacy admin API. */\n fetchProducts?: (\n search: string,\n cursor?: string,\n limit?: number,\n ) => Promise<PortalProductsResponse>;\n /** Portal-tenant single product fetcher. When provided, the detail screen\n * uses this instead of the legacy admin API. */\n fetchProduct?: (id: string | number) => Promise<PortalProductResponse>;\n /** When provided, controls which product detail to show (URL-driven routing) */\n productId?: string | null;\n /** Called when a product is selected from the listing */\n onSelectProduct?: (productId: string) => void;\n /** Called when user navigates back from product detail */\n onBack?: () => void;\n}\n\nexport default function ProductsApp({\n countryCode,\n companyLogoUrl,\n fetchProducts,\n fetchProduct,\n productId: controlledProductId,\n onSelectProduct: onSelectProductProp,\n onBack: onBackProp,\n}: ProductsAppProps) {\n const [internalProductId, setInternalProductId] = useState<string | null>(\n null,\n );\n\n const isControlled = controlledProductId !== undefined;\n const activeProductId = isControlled\n ? controlledProductId\n : internalProductId;\n\n const handleSelectProduct = onSelectProductProp ?? setInternalProductId;\n const handleBack = onBackProp ?? (() => setInternalProductId(null));\n\n const handleNavigate = (screen: string, detailId?: string) => {\n if (screen === \"products\" && detailId) {\n handleSelectProduct(detailId);\n }\n // Ignore media navigation — ProductsApp only handles products\n };\n\n if (activeProductId) {\n return (\n <ProductDetailScreen\n productId={activeProductId}\n countryCode={countryCode}\n fetchProduct={fetchProduct}\n onNavigate={handleNavigate}\n onBack={handleBack}\n />\n );\n }\n\n return (\n <ProductsScreen\n countryCode={countryCode}\n fetchProducts={fetchProducts}\n onNavigate={(screen, detailId) => {\n if (detailId) {\n handleSelectProduct(detailId);\n }\n }}\n />\n );\n}\n","import { z } from \"zod\";\nimport type { UrlProxyResponse } from \"@fluid-app/file-picker-core\";\n\nexport type { UrlProxyResponse };\n\nconst urlProxyResponseSchema: z.ZodType<UrlProxyResponse> = z.object({\n data: z.string(),\n contentType: z.string(),\n size: z.number(),\n});\n\n/**\n * Proxy a URL fetch through the backend to bypass CORS restrictions.\n * The backend fetches the file and returns it as base64-encoded data.\n *\n * @param url - The URL to fetch\n * @param proxyEndpoint - The proxy endpoint (defaults to \"/api/proxy-url\")\n */\nexport async function proxyUrlFetch(\n url: string,\n proxyEndpoint: string = \"/api/proxy-url\",\n): Promise<UrlProxyResponse> {\n const response = await fetch(proxyEndpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ url }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({\n error: \"Failed to proxy URL fetch\",\n }));\n throw new Error(\n (errorData as { error?: string }).error || `HTTP ${response.status}`,\n );\n }\n\n const data: unknown = await response.json();\n return urlProxyResponseSchema.parse(data);\n}\n","import {\n damAssetSchema,\n damQueryResponseSchema,\n type CreateDamAssetParams,\n type CreateDamAssetPathForAssetsParams,\n type DamAssetCreateResponse,\n type DamAssetPathCreateResponse,\n type DamQueryParams,\n type DamQueryResponse,\n type FilePickerApi,\n type UnsplashSearchResponse,\n} from \"@fluid-app/file-picker-core\";\nimport { proxyUrlFetch } from \"@fluid-app/file-picker-api-client\";\nimport type { FetchClient } from \"@fluid-app/portal-tenant-api-client\";\nimport {\n portalTenantContent,\n type operations,\n} from \"@fluid-app/portal-tenant-content-api-client\";\n\n/** BFF create response — derived from the generated OpenAPI types. */\ntype DamAssetCreateBffResponse = Awaited<\n ReturnType<typeof portalTenantContent.dam_assets_create>\n>;\n\n/** BFF asset path create response — derived from the generated OpenAPI types. */\ntype DamAssetPathCreateBffResponse = Awaited<\n ReturnType<typeof portalTenantContent.dam_asset_paths_create>\n>;\n\n/**\n * Maps a BFF DAM asset to the file-picker port's DamAssetCreateResponse shape.\n *\n * The BFF response includes nullable meta.request_id (from Api::Response),\n * while the port schema requires a string. We coalesce to empty string.\n */\nfunction mapCreateResponse(\n response: DamAssetCreateBffResponse,\n): DamAssetCreateResponse {\n const raw = response.asset ?? {};\n return {\n asset: damAssetSchema.parse({\n ...raw,\n canonical_path: raw.canonical_path ?? \"\",\n category: raw.category ?? \"\",\n company: raw.company ?? \"\",\n description: raw.description ?? \"\",\n default_variant_id: raw.default_variant_id ?? \"\",\n }),\n meta: {\n request_id: response.meta?.request_id ?? \"\",\n timestamp: response.meta?.timestamp ?? new Date().toISOString(),\n },\n };\n}\n\n/**\n * Maps a BFF asset path response to the file-picker port's shape.\n */\nfunction mapAssetPathCreateResponse(\n response: DamAssetPathCreateBffResponse,\n): DamAssetPathCreateResponse {\n const assetPath = response.asset_path ?? {};\n return {\n asset: {\n id: assetPath.id ?? 0,\n canonical_path: assetPath.path ?? \"\",\n name: assetPath.asset_code ?? \"\",\n },\n meta: {\n request_id: response.meta?.request_id ?? \"\",\n timestamp: response.meta?.timestamp ?? new Date().toISOString(),\n },\n };\n}\n\n/**\n * Creates a FilePickerApi adapter backed by the portal-tenant BFF's\n * `/api/content/dam/*` endpoints, using cookie-based auth via the\n * provided FetchClient.\n *\n * Unsplash search is not available through the BFF — callers that need\n * Unsplash should use the legacy adapter or provide their own\n * implementation.\n *\n * The `onProgress` callback in `createDamAsset` is not supported — the\n * underlying `fetch` API does not expose upload progress events.\n *\n * URL proxy delegates to the same-origin `/api/proxy-url` endpoint\n * (served by the hosting app, not the BFF) for CORS bypass, identical\n * to the legacy adapter behaviour.\n */\nexport function createFilePickerApiAdapter(client: FetchClient): FilePickerApi {\n return {\n createDamAsset: async (\n params: CreateDamAssetParams,\n ): Promise<DamAssetCreateResponse> => {\n // The generated dam_assets_create uses client.post (JSON body), but\n // file uploads require multipart/form-data. Use requestWithFormData\n // directly, typing the response from the generated operation type.\n const formData = new FormData();\n formData.append(\"asset[file]\", params.file);\n formData.append(\"asset[name]\", params.name);\n\n if (params.description) {\n formData.append(\"asset[description]\", params.description);\n }\n\n if (params.tags && params.tags.length > 0) {\n formData.append(\"asset[tags]\", params.tags.join(\",\"));\n }\n\n const response =\n await client.requestWithFormData<DamAssetCreateBffResponse>(\n \"/api/content/dam/assets\",\n formData,\n { method: \"POST\" },\n );\n\n return mapCreateResponse(response);\n },\n\n queryDamAssets: async (\n params: DamQueryParams,\n ): Promise<DamQueryResponse> => {\n const response = await portalTenantContent.dam_query(\n client,\n params satisfies operations[\"dam_query\"][\"requestBody\"][\"content\"][\"application/json\"],\n );\n return damQueryResponseSchema.parse({\n ...response,\n meta: response.meta\n ? { next_cursor: response.meta.pagination?.next_cursor ?? undefined }\n : undefined,\n });\n },\n\n deleteDamAsset: async (code: string): Promise<unknown> => {\n return portalTenantContent.dam_assets_destroy(client, code);\n },\n\n discardDamAsset: async (code: string): Promise<unknown> => {\n return portalTenantContent.dam_assets_discard(client, code);\n },\n\n createDamAssetPathForAssets: async (\n params: CreateDamAssetPathForAssetsParams,\n ): Promise<DamAssetPathCreateResponse> => {\n const response = await portalTenantContent.dam_asset_paths_create(\n client,\n params.code,\n { asset_path: { path: params.asset_paths.join(\",\") } },\n );\n return mapAssetPathCreateResponse(response);\n },\n\n searchUnsplash: async (\n _query: string,\n _page?: number,\n _perPage?: number,\n ): Promise<UnsplashSearchResponse> => {\n throw new Error(\n \"Unsplash search is not available through the portal-tenant BFF. \" +\n \"Configure an Unsplash access key and use the standard FilePickerApi adapter instead.\",\n );\n },\n\n proxyUrlFetch: (url: string) => proxyUrlFetch(url),\n };\n}\n","/**\n * Portal Content Domain Adapter — Implements ContentDomainApi using the\n * portal-tenant Content BFF endpoints.\n *\n * Follows the composite adapter pattern (see contacts-api-adapter.ts):\n * all sub-factory functions are private; the only public export is the\n * composite `createPortalContentDomainApiAdapter`.\n */\n\nimport type { FetchClient } from \"@fluid-app/api-client-core\";\nimport type {\n ContentMediaApi,\n media,\n} from \"@fluid-app/shareables-core/media-api\";\nimport type {\n ContentPlaylistsApi,\n playlists,\n} from \"@fluid-app/shareables-core/playlists-api\";\nimport type {\n ContentSharesApi,\n shares,\n} from \"@fluid-app/shareables-core/shares-api\";\nimport type {\n ContentDamAssetsApi,\n damAssets,\n} from \"@fluid-app/shareables-core/dam-assets-api\";\nimport type {\n MediaApi,\n PlaylistsApi,\n FileResourcesApi,\n ProductMediaApi,\n ShareApi,\n} from \"@fluid-app/shareables-core/shareables-api\";\nimport type { ContentDomainApi } from \"@fluid-app/shareables-core/content-domain-api\";\nimport type {\n shareables,\n PlaylistsQuery,\n} from \"@fluid-app/shareables-core/types\";\nimport { portalTenantContent } from \"@fluid-app/portal-tenant-content-api-client\";\n\n// ============================================================================\n// Media — Raw BFF adapter (private)\n// ============================================================================\n\nfunction mapMedia(\n raw: NonNullable<\n Awaited<ReturnType<typeof portalTenantContent.media_show>>[\"media\"]\n >,\n): media.Media {\n return {\n id: raw.id ?? 0,\n title: raw.title ?? \"\",\n description: raw.description ?? null,\n media_type: raw.media_type ?? \"\",\n url: raw.url ?? null,\n thumbnail_url: raw.thumbnail_url ?? null,\n owner_type: raw.owner_type ?? \"\",\n created_at: raw.created_at ?? \"\",\n updated_at: raw.updated_at ?? \"\",\n };\n}\n\nfunction mapMediaMeta(\n raw: Awaited<ReturnType<typeof portalTenantContent.media_list>>[\"meta\"],\n): media.MediaListResponse[\"meta\"] {\n return {\n request_id: raw?.request_id ?? null,\n timestamp: raw?.timestamp ?? \"\",\n pagination: raw?.pagination\n ? {\n cursor: raw.pagination.cursor ?? null,\n limit: raw.pagination.limit,\n next_cursor: raw.pagination.next_cursor ?? null,\n prev_cursor: raw.pagination.prev_cursor ?? null,\n }\n : undefined,\n };\n}\n\nfunction createRawMediaAdapter(client: FetchClient): ContentMediaApi {\n return {\n listMedia: async (params) => {\n const response = await portalTenantContent.media_list(client, {\n \"page[cursor]\": params?.cursor,\n \"page[limit]\": params?.limit,\n media_type: params?.media_type,\n \"filter[title]\": params?.[\"filter[title]\"],\n sort: params?.sort,\n });\n return {\n media: (response.media ?? []).map(mapMedia),\n meta: mapMediaMeta(response.meta),\n };\n },\n\n createMedia: async (body) => {\n const response = await portalTenantContent.media_create(client, {\n media: body,\n });\n return {\n media: mapMedia(response.media ?? {}),\n meta: mapMediaMeta(response.meta),\n };\n },\n\n getMedia: async (id) => {\n const response = await portalTenantContent.media_show(client, id);\n return {\n media: mapMedia(response.media ?? {}),\n meta: mapMediaMeta(response.meta),\n };\n },\n\n updateMedia: async (id, body) => {\n const response = await portalTenantContent.media_update(client, id, {\n media: body,\n });\n return {\n media: mapMedia(response.media ?? {}),\n meta: mapMediaMeta(response.meta),\n };\n },\n\n deleteMedia: async (id) => {\n const response = await portalTenantContent.media_destroy(client, id);\n return {\n media: { id: response.media?.id ?? 0 },\n meta: mapMediaMeta(response.meta),\n };\n },\n };\n}\n\n// ============================================================================\n// Media — ShareablesApi-compatible adapter (private)\n// ============================================================================\n\nfunction mediaKindFromType(mediaType: string): string | null {\n if (mediaType === \"video\") return \"video\";\n if (mediaType === \"image\") return \"image\";\n if (mediaType === \"document\" || mediaType === \"pdf\") return \"pdf\";\n return null;\n}\n\nfunction toBffMediumResponse(bff: media.Media): shareables.MediumResponse {\n const kind = mediaKindFromType(bff.media_type);\n const isVideo = bff.media_type === \"video\";\n const isPdf = bff.media_type === \"pdf\" || bff.media_type === \"document\";\n\n return {\n id: bff.id,\n user_id: null,\n media_type: bff.media_type,\n media_format: bff.media_type,\n image_url:\n !isVideo && !isPdf\n ? (bff.url ?? bff.thumbnail_url ?? null)\n : (bff.thumbnail_url ?? null),\n video_url: isVideo ? (bff.url ?? null) : null,\n pdf_url: isPdf ? (bff.url ?? null) : null,\n title: bff.title,\n description: {\n id: null,\n name: null,\n body: bff.description ?? null,\n record_type: null,\n record_id: null,\n created_at: bff.created_at ?? null,\n updated_at: bff.updated_at ?? null,\n locale: null,\n },\n stripped: bff.description ?? null,\n kind,\n active: true,\n visibility: null,\n share_link: null,\n views: 0,\n leads: 0,\n watch: null,\n video_status: null,\n duration: null,\n cta_url: null,\n cta_button_text: null,\n cta_enabled: false,\n cta_action_type: null,\n video_shopping_enabled: false,\n prompts_enabled: false,\n ranks: [],\n preview_link: null,\n attached_shareables: [],\n created_at: bff.created_at,\n };\n}\n\nfunction createMediaAdapter(client: FetchClient): MediaApi {\n const portAdapter = createRawMediaAdapter(client);\n const cursorByPage = new Map<number, string>();\n let lastFilterKey = \"\";\n\n return {\n getMedia: async (options) => {\n const pageNumber = options?.page ?? 1;\n\n // Clear cursor cache when search/sort/type filters change\n const filterKey = `${options?.search_query ?? \"\"}|${options?.sorted_by ?? \"\"}|${options?.media_type ?? options?.with_type ?? \"\"}`;\n if (filterKey !== lastFilterKey) {\n cursorByPage.clear();\n lastFilterKey = filterKey;\n }\n\n const cursor = pageNumber > 1 ? cursorByPage.get(pageNumber) : undefined;\n\n // Map UI sort values (\"title_asc\", \"title_desc\") to BFF sort.\n const rawSort = options?.sorted_by;\n let bffSort: \"title_asc\" | \"title_desc\" | undefined;\n if (rawSort === \"title_asc\") {\n bffSort = \"title_asc\";\n } else if (rawSort === \"title_desc\") {\n bffSort = \"title_desc\";\n }\n\n const response = await portAdapter.listMedia({\n cursor,\n limit: options?.per_page,\n media_type: options?.media_type ?? options?.with_type,\n \"filter[title]\": options?.search_query,\n sort: bffSort,\n });\n\n const nextCursor = response.meta.pagination?.next_cursor;\n if (nextCursor) {\n cursorByPage.set(pageNumber + 1, nextCursor);\n }\n\n const transformedItems = response.media.map(toBffMediumResponse);\n\n return {\n data: transformedItems,\n status: \"success\",\n media: transformedItems,\n meta: {\n total_count: transformedItems.length,\n current: pageNumber,\n per_page: options?.per_page ?? 24,\n pages: nextCursor ? pageNumber + 1 : pageNumber,\n next: nextCursor ? pageNumber + 1 : null,\n previous: pageNumber > 1 ? pageNumber - 1 : null,\n },\n };\n },\n\n getMediaById: async (id) => {\n const response = await portAdapter.getMedia(id);\n const medium = toBffMediumResponse(response.media);\n return {\n data: medium,\n status: \"success\",\n media: medium,\n };\n },\n\n createMedia: async (mediaData) => {\n const response = await portAdapter.createMedia({\n title: mediaData.title ?? \"\",\n description: mediaData.description,\n media_type: mediaData.media_type ?? \"image\",\n url:\n mediaData.image_url ??\n mediaData.video_url ??\n mediaData.pdf_url ??\n undefined,\n });\n return toBffMediumResponse(response.media);\n },\n\n updateMedia: async (id, mediaData) => {\n const response = await portAdapter.updateMedia(id, {\n title: mediaData.title,\n description: mediaData.description,\n });\n return toBffMediumResponse(response.media);\n },\n\n deleteMedia: async (id) => {\n await portAdapter.deleteMedia(id);\n return { success: true };\n },\n };\n}\n\n// ============================================================================\n// Playlists — Raw BFF adapter (private)\n// ============================================================================\n\nfunction mapPlaylist(\n raw: NonNullable<\n Awaited<ReturnType<typeof portalTenantContent.playlists_show>>[\"playlist\"]\n >,\n): playlists.Playlist {\n return {\n id: raw.id ?? 0,\n title: raw.title ?? \"\",\n description: raw.description ?? null,\n items_count: raw.items_count ?? 0,\n user_id: raw.user_id ?? undefined,\n is_favorited: raw.is_favorited,\n image_url: raw.image_url ?? null,\n created_at: raw.created_at ?? \"\",\n updated_at: raw.updated_at ?? \"\",\n };\n}\n\nfunction mapPlaylistItem(\n raw: NonNullable<\n Awaited<\n ReturnType<typeof portalTenantContent.playlists_items_list>\n >[\"playlist_items\"]\n >[number],\n): playlists.PlaylistItem {\n // The BFF's PlaylistItem is polymorphic: relateable_type + inline relateable.\n // Map its nested fields to the consumer's flat PlaylistItem shape.\n const relateable = (raw.relateable ?? {}) as Record<string, unknown>;\n return {\n id: raw.id ?? 0,\n media_id: (relateable.id as number | undefined) ?? 0,\n position: raw.order ?? null,\n title: relateable.title as string | undefined,\n image_url: (relateable.image_url as string | null | undefined) ?? null,\n media_type: raw.relateable_type ?? undefined,\n video_url: (relateable.video_url as string | null | undefined) ?? null,\n duration: (relateable.duration as number | null | undefined) ?? null,\n created_at: (relateable.created_at as string | undefined) ?? \"\",\n };\n}\n\nfunction mapPlaylistsMeta(\n raw: Awaited<ReturnType<typeof portalTenantContent.playlists_list>>[\"meta\"],\n): playlists.PlaylistsListResponse[\"meta\"] {\n return {\n request_id: raw?.request_id ?? null,\n timestamp: raw?.timestamp ?? \"\",\n pagination: raw?.pagination\n ? {\n cursor: raw.pagination.cursor ?? null,\n limit: raw.pagination.limit,\n next_cursor: raw.pagination.next_cursor ?? null,\n prev_cursor: raw.pagination.prev_cursor ?? null,\n }\n : undefined,\n };\n}\n\nfunction createRawPlaylistsAdapter(client: FetchClient): ContentPlaylistsApi {\n return {\n listPlaylists: async (params) => {\n const response = await portalTenantContent.playlists_list(client, {\n \"page[cursor]\": params?.cursor,\n \"page[limit]\": params?.limit,\n \"filter[title]\": params?.[\"filter[title]\"],\n sort: params?.sort,\n });\n return {\n playlists: (response.playlists ?? []).map(mapPlaylist),\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n createPlaylist: async (body) => {\n const response = await portalTenantContent.playlists_create(client, {\n playlist: body,\n });\n return {\n playlist: mapPlaylist(response.playlist ?? {}),\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n getPlaylist: async (id) => {\n const response = await portalTenantContent.playlists_show(client, id);\n return {\n playlist: mapPlaylist(response.playlist ?? {}),\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n updatePlaylist: async (id, body) => {\n const response = await portalTenantContent.playlists_update(client, id, {\n playlist: body,\n });\n return {\n playlist: mapPlaylist(response.playlist ?? {}),\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n deletePlaylist: async (id) => {\n const response = await portalTenantContent.playlists_destroy(client, id);\n return {\n playlist: { id: response.playlist?.id ?? 0 },\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n listPlaylistItems: async (playlistId, params) => {\n const response = await portalTenantContent.playlists_items_list(\n client,\n playlistId,\n {\n \"page[cursor]\": params?.cursor,\n \"page[limit]\": params?.limit,\n },\n );\n return {\n playlist_items: (response.playlist_items ?? []).map(mapPlaylistItem),\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n addPlaylistItem: async (playlistId, body) => {\n const response = await portalTenantContent.playlists_items_add(\n client,\n playlistId,\n { item: body },\n );\n return {\n playlist_item: mapPlaylistItem(response.playlist_item ?? {}),\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n\n removePlaylistItem: async (playlistId, itemId) => {\n const response = await portalTenantContent.playlists_items_remove(\n client,\n playlistId,\n itemId,\n );\n return {\n playlist_item: { id: response.playlist_item?.id ?? 0 },\n meta: mapPlaylistsMeta(response.meta),\n };\n },\n };\n}\n\n// ============================================================================\n// Playlists — ShareablesApi-compatible adapter (private)\n// ============================================================================\n\nfunction toBffPlaylist(\n bff: playlists.Playlist,\n items?: shareables.PlaylistItem[],\n): shareables.Playlist {\n return {\n id: bff.id,\n title: bff.title,\n description: bff.description ?? null,\n image_url: bff.image_url ?? null,\n slug: null,\n active: true,\n user_id: bff.user_id ?? null,\n is_favorited: bff.is_favorited ?? false,\n items: items ?? [],\n items_count: bff.items_count,\n };\n}\n\nfunction createPlaylistsAdapter(client: FetchClient): PlaylistsApi {\n const portAdapter = createRawPlaylistsAdapter(client);\n\n return {\n getPlaylists: async (options?: PlaylistsQuery) => {\n // The UI sends Rails-style sort (\"-title\", \"title\", \"-created_at\")\n // but the BFF expects \"title_asc\", \"title_desc\", etc.\n const rawSort = options?.sort;\n let bffSort:\n | \"title_asc\"\n | \"title_desc\"\n | \"created_at_asc\"\n | \"created_at_desc\"\n | undefined;\n if (rawSort === \"title_asc\" || rawSort === \"title\") {\n bffSort = \"title_asc\";\n } else if (rawSort === \"title_desc\" || rawSort === \"-title\") {\n bffSort = \"title_desc\";\n } else if (rawSort === \"created_at_asc\" || rawSort === \"created_at\") {\n bffSort = \"created_at_asc\";\n } else if (rawSort === \"created_at_desc\" || rawSort === \"-created_at\") {\n bffSort = \"created_at_desc\";\n }\n\n const response = await portAdapter.listPlaylists({\n cursor: options?.[\"page[cursor]\"],\n limit: options?.[\"page[limit]\"],\n \"filter[title]\": options?.[\"filter[title]\"],\n sort: bffSort,\n });\n\n return {\n playlists: response.playlists.map((p) => toBffPlaylist(p)),\n meta: {\n request_id: response.meta.request_id ?? \"\",\n timestamp: response.meta.timestamp ?? \"\",\n pagination: {\n cursor: response.meta.pagination?.cursor ?? null,\n limit: response.meta.pagination?.limit ?? 12,\n prev_cursor: response.meta.pagination?.prev_cursor ?? null,\n next_cursor: response.meta.pagination?.next_cursor ?? null,\n total_count: 0,\n total_pages: 0,\n },\n },\n };\n },\n\n getPlaylistById: async (id) => {\n // Fetch playlist metadata and all items in parallel.\n // Items are cursor-paginated so we follow next_cursor until exhausted.\n const response = await portAdapter.getPlaylist(id);\n\n const allItems: playlists.PlaylistItem[] = [];\n let cursor: string | undefined;\n const MAX_PAGES = 50; // Safety limit: 50 pages × 100 items = 5,000 items max\n for (let i = 0; i < MAX_PAGES; i++) {\n const page = await portAdapter.listPlaylistItems(id, {\n cursor,\n limit: 100,\n });\n allItems.push(...page.playlist_items);\n cursor = page.meta.pagination?.next_cursor ?? undefined;\n if (!cursor) break;\n }\n\n const items: shareables.PlaylistItem[] = allItems.map((item) => ({\n id: item.id,\n order: item.position ?? undefined,\n relateable_type: \"Medium\",\n relateable: { id: item.media_id },\n // Flat fields from BFF — the UI reads these first\n title: item.title ?? \"Untitled\",\n image_url: item.image_url ?? null,\n kind: mediaKindFromType(item.media_type ?? \"\"),\n video_url: item.video_url ?? null,\n duration: item.duration ?? null,\n media_format: item.media_type ?? null,\n }));\n\n return {\n playlist: toBffPlaylist(response.playlist, items),\n meta: {\n request_id: response.meta.request_id ?? \"\",\n timestamp: response.meta.timestamp ?? \"\",\n },\n };\n },\n\n createPlaylist: async (data) => {\n const response = await portAdapter.createPlaylist({\n title: data.playlist.title,\n description: data.playlist.description,\n });\n return {\n playlist: toBffPlaylist(response.playlist),\n meta: {\n request_id: response.meta.request_id ?? \"\",\n timestamp: response.meta.timestamp ?? \"\",\n },\n };\n },\n\n updatePlaylist: async (id, data) => {\n const response = await portAdapter.updatePlaylist(id, {\n title: data.playlist.title,\n description: data.playlist.description,\n });\n return {\n playlist: toBffPlaylist(response.playlist),\n meta: {\n request_id: response.meta.request_id ?? \"\",\n timestamp: response.meta.timestamp ?? \"\",\n },\n };\n },\n\n addItemToPlaylist: async (id, data) => {\n await Promise.all(\n data.items.map((item) =>\n portAdapter.addPlaylistItem(id, {\n media_id: item.relateable_id,\n position:\n typeof item.order === \"number\" ? item.order : Number(item.order),\n }),\n ),\n );\n const updated = await portAdapter.getPlaylist(id);\n return toBffPlaylist(updated.playlist);\n },\n\n removeItemsFromPlaylist: async (playlistId, data) => {\n await Promise.all(\n data.item_ids.map((itemId) =>\n portAdapter.removePlaylistItem(playlistId, itemId),\n ),\n );\n const updated = await portAdapter.getPlaylist(playlistId);\n return toBffPlaylist(updated.playlist);\n },\n };\n}\n\n// ============================================================================\n// Shares — Raw BFF adapter (private)\n// ============================================================================\n\nfunction isShareableType(\n value: string | undefined,\n): value is shares.ShareableType {\n return (\n value === \"media\" ||\n value === \"product\" ||\n value === \"library\" ||\n value === \"page\"\n );\n}\n\nfunction mapShare(\n raw: NonNullable<\n Awaited<ReturnType<typeof portalTenantContent.shares_list>>[\"shares\"]\n >[number],\n): shares.Share {\n return {\n id: raw.id ?? 0,\n url: raw.url ?? \"\",\n shareable_type: isShareableType(raw.shareable_type)\n ? raw.shareable_type\n : \"media\",\n shareable_id: raw.shareable_id ?? 0,\n created_at: raw.created_at ?? \"\",\n };\n}\n\nfunction mapSharesMeta(\n raw: Awaited<ReturnType<typeof portalTenantContent.shares_list>>[\"meta\"],\n): shares.SharesListResponse[\"meta\"] {\n return {\n request_id: raw?.request_id ?? null,\n timestamp: raw?.timestamp ?? \"\",\n pagination: raw?.pagination\n ? {\n cursor: raw.pagination.cursor ?? null,\n limit: raw.pagination.limit,\n next_cursor: raw.pagination.next_cursor ?? null,\n prev_cursor: raw.pagination.prev_cursor ?? null,\n }\n : undefined,\n };\n}\n\nfunction createRawSharesAdapter(client: FetchClient): ContentSharesApi {\n return {\n listShares: async (params) => {\n const response = await portalTenantContent.shares_list(client, {\n \"page[cursor]\": params?.cursor,\n \"page[limit]\": params?.limit,\n });\n return {\n shares: (response.shares ?? []).map(mapShare),\n meta: mapSharesMeta(response.meta),\n };\n },\n\n createShare: async (body) => {\n const response = await portalTenantContent.shares_create(client, {\n share: body,\n });\n return {\n share: mapShare(response.share ?? {}),\n meta: mapSharesMeta(response.meta),\n };\n },\n };\n}\n\n// ============================================================================\n// Shares — ShareablesApi-compatible adapter (private)\n// ============================================================================\n\nconst SHAREABLE_TYPE_MAP: Record<string, shares.ShareableType> = {\n Medium: \"media\",\n media: \"media\",\n Product: \"product\",\n product: \"product\",\n Library: \"library\",\n library: \"library\",\n Page: \"page\",\n page: \"page\",\n};\n\nfunction createShareAdapter(client: FetchClient): ShareApi {\n const portAdapter = createRawSharesAdapter(client);\n\n return {\n createShareLink: async (input) => {\n if (!input.relateableId) {\n throw new Error(\"Cannot create share link without a relateableId\");\n }\n const shareableType = SHAREABLE_TYPE_MAP[input.relateableType];\n if (!shareableType) {\n throw new Error(`Unknown shareable type: \"${input.relateableType}\"`);\n }\n const response = await portAdapter.createShare({\n shareable_type: shareableType,\n shareable_id: input.relateableId,\n });\n return response.share.url;\n },\n };\n}\n\n// ============================================================================\n// DAM Assets / Files — Raw BFF adapter (private)\n// ============================================================================\n\nfunction mapDamAsset(\n raw: NonNullable<\n Awaited<ReturnType<typeof portalTenantContent.dam_assets_list>>[\"assets\"]\n >[number],\n): damAssets.DamAsset {\n return {\n id: raw.id ?? 0,\n code: raw.code ?? \"\",\n name: raw.name ?? \"\",\n description: raw.description ?? null,\n category: raw.category ?? null,\n company: raw.company ?? null,\n default_variant_id: raw.default_variant_id ?? null,\n default_variant_url: raw.default_variant_url ?? null,\n canonical_path: raw.canonical_path ?? null,\n created_at: raw.created_at ?? \"\",\n updated_at: raw.updated_at ?? \"\",\n };\n}\n\nfunction mapDamAssetPath(\n raw: NonNullable<\n Awaited<\n ReturnType<typeof portalTenantContent.dam_asset_paths_list>\n >[\"asset_paths\"]\n >[number],\n): damAssets.DamAssetPath {\n return {\n id: raw.id ?? 0,\n asset_code: raw.asset_code ?? \"\",\n path: raw.path ?? \"\",\n created_at: raw.created_at ?? \"\",\n };\n}\n\nfunction mapDamAssetsMeta(\n raw: Awaited<ReturnType<typeof portalTenantContent.dam_assets_list>>[\"meta\"],\n): damAssets.DamAssetsListResponse[\"meta\"] {\n return {\n request_id: raw?.request_id ?? null,\n timestamp: raw?.timestamp ?? \"\",\n pagination: raw?.pagination\n ? {\n cursor: raw.pagination.cursor ?? null,\n limit: raw.pagination.limit,\n next_cursor: raw.pagination.next_cursor ?? null,\n prev_cursor: raw.pagination.prev_cursor ?? null,\n }\n : undefined,\n };\n}\n\nfunction createRawDamAssetsAdapter(client: FetchClient): ContentDamAssetsApi {\n return {\n listAssets: async (params) => {\n const response = await portalTenantContent.dam_assets_list(client, {\n \"page[cursor]\": params?.cursor,\n \"page[limit]\": params?.limit,\n });\n return {\n assets: (response.assets ?? []).map(mapDamAsset),\n meta: mapDamAssetsMeta(response.meta),\n };\n },\n\n createAsset: async (body) => {\n const response = await portalTenantContent.dam_assets_create(client, {\n asset: body,\n });\n return {\n asset: mapDamAsset(response.asset ?? {}),\n meta: mapDamAssetsMeta(response.meta),\n };\n },\n\n listAssetPaths: async (assetCode, params) => {\n const response = await portalTenantContent.dam_asset_paths_list(\n client,\n assetCode,\n {\n \"page[cursor]\": params?.cursor,\n \"page[limit]\": params?.limit,\n },\n );\n return {\n asset_paths: (response.asset_paths ?? []).map(mapDamAssetPath),\n meta: mapDamAssetsMeta(response.meta),\n };\n },\n\n createAssetPath: async (assetCode, body) => {\n const response = await portalTenantContent.dam_asset_paths_create(\n client,\n assetCode,\n { asset_path: body },\n );\n return {\n asset_path: mapDamAssetPath(response.asset_path ?? {}),\n meta: mapDamAssetsMeta(response.meta),\n };\n },\n };\n}\n\n// ============================================================================\n// Files — ShareablesApi-compatible adapter (private)\n// ============================================================================\n\nfunction createFileResourcesAdapter(client: FetchClient): FileResourcesApi {\n const portAdapter = createRawDamAssetsAdapter(client);\n const cursorByPage = new Map<number, string>();\n\n return {\n getFileResources: async (params) => {\n const pageNumber = params?.pageParam ? Number(params.pageParam) : 1;\n const pageSize = params?.pageSize ? Number(params.pageSize) : 25;\n const cursor = pageNumber > 1 ? cursorByPage.get(pageNumber) : undefined;\n\n const response = await portAdapter.listAssets({\n cursor,\n limit: pageSize,\n });\n\n const nextCursor = response.meta.pagination?.next_cursor;\n if (nextCursor) {\n cursorByPage.set(pageNumber + 1, nextCursor);\n }\n\n const fileResources: shareables.FileResource[] = response.assets.map(\n (asset) => ({\n id: asset.id,\n alt_text: asset.name,\n url: asset.default_variant_url ?? \"\",\n filename: asset.name,\n content_type: \"application/octet-stream\",\n content_size: 0,\n handle: asset.code,\n dam_asset_code: asset.code,\n preview_image_url: asset.default_variant_url ?? \"\",\n created_at: asset.created_at,\n updated_at: asset.updated_at ?? \"\",\n relateable_type: null,\n relateable_id: null,\n content: null,\n }),\n );\n\n const hasNextPage = !!nextCursor;\n\n return {\n file_resources: fileResources,\n meta: {\n total_count: fileResources.length,\n per_page: pageSize,\n current_page: pageNumber,\n total_pages: hasNextPage ? pageNumber + 1 : pageNumber,\n },\n };\n },\n };\n}\n\n// ============================================================================\n// Product Media (private)\n// ============================================================================\n\n/**\n * Narrow interface for the product media endpoint. Matches\n * PortalProductsApi.getProductMedia without importing the full products-core\n * dependency graph, keeping the dependency graph clean.\n */\nexport interface ProductMediaSource {\n getProductMedia(productId: string | number): Promise<{\n media: ReadonlyArray<{\n id?: number;\n title?: string;\n media_type?: string;\n url?: string;\n }>;\n }>;\n}\n\nfunction mapProductMedia(raw: {\n id?: number;\n title?: string;\n media_type?: string;\n url?: string;\n}): shareables.ProductMedia {\n const isVideo = raw.media_type === \"video\";\n const isPdf = raw.media_type === \"pdf\" || raw.media_type === \"document\";\n return {\n id: raw.id ?? 0,\n slug: null,\n title: raw.title ?? \"\",\n kind: isVideo ? \"video\" : isPdf ? \"pdf\" : \"image\",\n media_type: raw.media_type ?? \"image\",\n media_format: raw.media_type ?? \"image\",\n image_url: !isVideo && !isPdf ? (raw.url ?? null) : null,\n video_url: isVideo ? (raw.url ?? null) : null,\n pdf_url: isPdf ? (raw.url ?? null) : null,\n powerpoint_url: null,\n duration: 0,\n description: null,\n subtitles: {},\n comments_count: 0,\n };\n}\n\nfunction createProductMediaAdapter(\n source: ProductMediaSource,\n): ProductMediaApi {\n return {\n getProductMedia: async (productId: number) => {\n const response = await source.getProductMedia(productId);\n return {\n media: (response.media ?? []).map(mapProductMedia),\n };\n },\n };\n}\n\n// Favorites Toggle\n// ============================================================================\n\nexport async function toggleFavorite(\n client: FetchClient,\n favoriteableId: number,\n favoriteableType: string,\n): Promise<{ is_favorited: boolean }> {\n const res = await client.post<{\n favorite: { is_favorited: boolean };\n }>(\"/api/content/favorites/toggle\", {\n favoriteable_id: favoriteableId,\n favoriteable_type: favoriteableType,\n });\n return { is_favorited: res.favorite?.is_favorited ?? false };\n}\n\n// ============================================================================\n// Internal test helpers (consumed by tests only — not re-exported from index.ts)\n// ============================================================================\n\n/** @internal — For tests only. */\nexport const _createRawMediaAdapter = createRawMediaAdapter;\n/** @internal — For tests only. */\nexport const _createRawDamAssetsAdapter = createRawDamAssetsAdapter;\n/** @internal — For tests only. */\nexport const _createRawSharesAdapter = createRawSharesAdapter;\n\n// ============================================================================\n// Public exports\n// ============================================================================\n\n/**\n * Creates a composite ContentDomainApi backed by the portal-tenant Content\n * BFF endpoints. Follows the same pattern as\n * `createPortalContactsDomainApiAdapter`.\n */\nexport function createPortalContentDomainApiAdapter(\n client: FetchClient,\n productsApi: ProductMediaSource,\n): ContentDomainApi {\n return {\n media: createMediaAdapter(client),\n playlists: createPlaylistsAdapter(client),\n fileResources: createFileResourcesAdapter(client),\n share: createShareAdapter(client),\n productMedia: createProductMediaAdapter(productsApi),\n };\n}\n\n/**\n * Creates a ContentPlaylistsApi (the port-level playlists adapter) for\n * operations that aren't part of the shareables PlaylistsApi — e.g.\n * `deletePlaylist`. Exposed separately because ContentDomainApi.playlists\n * is the higher-level shareables PlaylistsApi.\n */\nexport function createPortalContentPlaylistsAdapter(\n client: FetchClient,\n): ContentPlaylistsApi {\n return createRawPlaylistsAdapter(client);\n}\n","import {\n createContext,\n useContext,\n useMemo,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport { ShareablesApiProvider } from \"@fluid-app/shareables-core\";\nimport type { ContentPlaylistsApi } from \"@fluid-app/shareables-core/playlists-api\";\nimport type { PortalProductsApi } from \"@fluid-app/products-core\";\nimport type { FilePickerApi } from \"@fluid-app/file-picker-core\";\nimport { usePortalProductsApi } from \"@fluid-app/products-core\";\nimport { createFilePickerApiAdapter } from \"../adapters/file-picker-api-adapter\";\nimport { usePortalTenantClient } from \"../providers/PortalTenantClientProvider\";\nimport {\n createPortalContentDomainApiAdapter,\n createPortalContentPlaylistsAdapter,\n} from \"../adapters/content-api-adapter\";\n\n/**\n * Extra context values that screens need beyond ContentDomainApi.\n * ContentDomainApi flows through ShareablesApiProvider; these extras\n * are available via usePortalContentContext().\n */\nexport interface PortalContentContext {\n /** The products adapter — exposed so screens can call listProducts / getProduct\n * without a separate usePortalProductsApi() import. */\n productsApi: PortalProductsApi;\n /** Port-level playlists adapter for operations outside ShareablesApiProvider\n * (e.g. deletePlaylist). */\n playlistsAdapter: ContentPlaylistsApi;\n /** File picker adapter for the shareables UI config. */\n filePickerApi: FilePickerApi;\n}\n\nconst ContentContext = createContext<PortalContentContext | null>(null);\n\nexport function usePortalContentContext(): PortalContentContext {\n const ctx = useContext(ContentContext);\n if (!ctx) {\n throw new Error(\n \"usePortalContentContext must be used within a <PortalContentApiProvider>\",\n );\n }\n return ctx;\n}\n\n/**\n * Provides all content-domain adapters (media, playlists, shares,\n * fileResources, productMedia) via ShareablesApiProvider, plus extra\n * context values available through usePortalContentContext().\n *\n * **Required ancestor:** `<PortalProductsApiProvider>` must appear above\n * this in the tree — it supplies the `PortalProductsApi` consumed via\n * `usePortalProductsApi()` for product-media bridging.\n */\nexport function PortalContentApiProvider({\n children,\n}: {\n children: ReactNode;\n}): ReactElement {\n const client = usePortalTenantClient();\n const productsApi = usePortalProductsApi();\n\n const contentApi = useMemo(\n () => createPortalContentDomainApiAdapter(client, productsApi),\n [client, productsApi],\n );\n\n const playlistsAdapter = useMemo(\n () => createPortalContentPlaylistsAdapter(client),\n [client],\n );\n\n const filePickerApi = useMemo(\n () => createFilePickerApiAdapter(client),\n [client],\n );\n\n const ctx = useMemo(\n () => ({\n productsApi,\n playlistsAdapter,\n filePickerApi,\n }),\n [productsApi, playlistsAdapter, filePickerApi],\n );\n\n return (\n <ContentContext.Provider value={ctx}>\n <ShareablesApiProvider value={contentApi}>\n {children}\n </ShareablesApiProvider>\n </ContentContext.Provider>\n );\n}\n"],"x_google_ignoreList":[31],"mappings":"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"}
|