@blitheforge/media-library 1.0.7 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -15
- package/dist/client.cjs +140 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +68 -0
- package/dist/client.d.ts +68 -0
- package/dist/client.js +106 -0
- package/dist/client.js.map +1 -0
- package/dist/index.cjs +23 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -39
- package/dist/index.js.map +1 -1
- package/dist/style.css +83 -1
- package/package.json +19 -7
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/client.ts","../src/components/media-library-modal.tsx","../src/utils/cn.ts","../src/utils/bfml-theme.ts","../src/components/media-library-panel.tsx","../src/components/ui/button.tsx","../src/components/ui/confirm-dialog.tsx","../src/components/ui/input.tsx","../src/components/ui/toast-container.tsx","../src/utils/toast-store.ts","../src/components/upload-preview.tsx","../src/utils/media-library-utils.ts","../src/components/media-library-widget.tsx","../src/components/media-picker.tsx","../src/components/picker-thumbnail.tsx","../src/components/media-picker-multi.tsx"],"sourcesContent":["export {\n createMediaLibraryClient,\n fileMatchesAccept,\n fileMatchesAcceptForUpload,\n fileNameFromPath,\n formatUploadSizeLimit,\n isFileWithinUploadSizeLimit,\n isImagePath,\n MAX_MEDIA_UPLOAD_BYTES\n} from \"./client\";\nexport { MediaLibraryModal, MediaPreview } from \"./components/media-library-modal\";\nexport { MediaLibraryPanel } from \"./components/media-library-panel\";\nexport { MediaLibraryWidget } from \"./components/media-library-widget\";\nexport { MediaPicker } from \"./components/media-picker\";\nexport { MediaPickerMulti } from \"./components/media-picker-multi\";\nexport { bfmlRootProps, resolveThemeMode } from \"./utils/bfml-theme\";\nexport type { MediaLibraryThemeMode } from \"./theme\";\nexport {\n defaultMediaLibraryConfig,\n defaultMediaCapabilities,\n type MediaCapabilities,\n type MediaFile,\n type MediaFolder,\n type MediaLibraryConfig,\n type MediaLibraryModalProps,\n type MediaLibraryPanelProps,\n type MediaLibraryWidgetProps,\n type MediaListing,\n type MediaPickerMultiProps,\n type MediaPickerProps\n} from \"./types\";\n","import type { MediaLibraryThemeMode } from \"./theme\";\n\nexport type MediaFile = {\n name: string;\n path: string;\n url: string;\n size: number;\n mimeType: string;\n updatedAt: string;\n};\n\nexport type MediaFolder = {\n name: string;\n path: string;\n};\n\nexport type MediaCapabilities = {\n view: boolean;\n upload: boolean;\n createFolder: boolean;\n delete: boolean;\n rename: boolean;\n select: boolean;\n};\n\nexport const defaultMediaCapabilities: MediaCapabilities = {\n view: true,\n upload: true,\n createFolder: true,\n delete: true,\n rename: true,\n select: true\n};\n\nexport type MediaListing = {\n path: string;\n folders: MediaFolder[];\n files: MediaFile[];\n capabilities?: MediaCapabilities;\n};\n\n/**\n * Configure API endpoints for your backend.\n * See README.md for the required request/response contract.\n */\nexport type MediaLibraryConfig = {\n listUrl: string;\n uploadUrl: string;\n createFolderUrl: string;\n updateUrl: string;\n deleteUrl: string;\n rootLabel?: string;\n /** `sync` inherits host CSS variables (default). Use `light` or `dark` for standalone theming. */\n theme?: MediaLibraryThemeMode;\n};\n\nexport const defaultMediaLibraryConfig: MediaLibraryConfig = {\n listUrl: \"/api/media\",\n uploadUrl: \"/api/media/upload\",\n createFolderUrl: \"/api/media/folders\",\n updateUrl: \"/api/media\",\n deleteUrl: \"/api/media\",\n rootLabel: \"Root\"\n};\n\nexport type MediaLibraryPanelProps = {\n /** When false, the panel does not load or render. */\n active?: boolean;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n title?: string;\n description?: string;\n accept?: Array<\"image\" | \"pdf\">;\n variant?: \"modal\" | \"embedded\";\n /** Show selection footer with Done button (picker flow). */\n selectable?: boolean;\n /** Close modal after selecting a file. Default true. */\n closeOnSelect?: boolean;\n /** `multi` allows selecting several files before confirming. Default `single`. */\n selectionMode?: \"single\" | \"multi\";\n /** Max files that can be added in one modal session (multi mode). */\n maxSelections?: number;\n /** After upload completes, add uploaded files and close (multi picker). */\n autoSelectUploads?: boolean;\n onClose?: () => void;\n onSelect?: (file: MediaFile) => void;\n onSelectMany?: (files: MediaFile[]) => void;\n className?: string;\n};\n\nexport type MediaLibraryWidgetProps = {\n /** CSS width, e.g. `\"100%\"`, `800`, or `\"70vw\"`. Default `\"100%\"`. */\n width?: string | number;\n /** CSS height, e.g. `640`, `\"600px\"`, or `\"70vh\"`. Default `640`. */\n height?: string | number;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n title?: string;\n description?: string;\n accept?: Array<\"image\" | \"pdf\">;\n selectable?: boolean;\n onSelect?: (file: MediaFile) => void;\n className?: string;\n};\n\nexport type MediaLibraryModalProps = {\n open: boolean;\n onClose: () => void;\n onSelect?: (file: MediaFile) => void;\n onSelectMany?: (files: MediaFile[]) => void;\n closeOnSelect?: boolean;\n selectionMode?: \"single\" | \"multi\";\n maxSelections?: number;\n autoSelectUploads?: boolean;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n title?: string;\n description?: string;\n accept?: Array<\"image\" | \"pdf\">;\n};\n\nexport type MediaPickerProps = {\n name: string;\n label?: string;\n title?: string;\n description?: string;\n /** @deprecated Preview is shown inline in the picker button. */\n previewTitle?: string;\n /** @deprecated Preview is shown inline in the picker button. */\n previewDescription?: string;\n value?: string;\n defaultValue?: string;\n onChange?: (path: string) => void;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n accept?: Array<\"image\" | \"pdf\">;\n className?: string;\n};\n\nexport type MediaPickerMultiProps = {\n name: string;\n label?: string;\n title?: string;\n description?: string;\n max?: number;\n values?: string[];\n defaultValues?: string[];\n onChange?: (paths: string[]) => void;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n accept?: Array<\"image\" | \"pdf\">;\n className?: string;\n};\n","import type { MediaFile, MediaLibraryConfig, MediaListing } from \"./types\";\nimport { defaultMediaLibraryConfig } from \"./types\";\n\ntype ApiPayload<T> = { success: boolean; data?: T; error?: { message?: string } };\n\nfunction resolveConfig(config?: Partial<MediaLibraryConfig>): MediaLibraryConfig {\n return { ...defaultMediaLibraryConfig, ...config };\n}\n\nasync function parseResponse<T>(response: Response): Promise<T> {\n const payload = (await response.json()) as ApiPayload<T>;\n if (!payload.success) throw new Error(payload.error?.message ?? \"Media request failed.\");\n return payload.data as T;\n}\n\nexport function createMediaLibraryClient(config?: Partial<MediaLibraryConfig>) {\n const urls = resolveConfig(config);\n\n return {\n async list(path = \"\", q = \"\") {\n const params = new URLSearchParams();\n if (path) params.set(\"path\", path);\n if (q) params.set(\"q\", q);\n const response = await fetch(`${urls.listUrl}?${params.toString()}`);\n return parseResponse<MediaListing>(response);\n },\n\n async createFolder(path: string, name: string, nested = true) {\n const response = await fetch(urls.createFolderUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ path, name, nested })\n });\n return parseResponse<{ name: string; path: string }>(response);\n },\n\n async upload(path: string, files: File[]) {\n const form = new FormData();\n form.set(\"path\", path);\n files.forEach((file) => form.append(\"files\", file));\n const response = await fetch(urls.uploadUrl, { method: \"POST\", body: form });\n return parseResponse<MediaFile[]>(response);\n },\n\n async uploadOne(path: string, file: File) {\n const uploaded = await this.upload(path, [file]);\n return uploaded[0];\n },\n\n async rename(path: string, newName: string, type: \"file\" | \"folder\") {\n const response = await fetch(urls.updateUrl, {\n method: \"PATCH\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ path, newName, type })\n });\n return parseResponse<MediaFile | { name: string; path: string }>(response);\n },\n\n async remove(path: string, type: \"file\" | \"folder\") {\n const response = await fetch(urls.deleteUrl, {\n method: \"DELETE\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ path, type })\n });\n return parseResponse<{ path: string }>(response);\n }\n };\n}\n\nexport const MAX_MEDIA_UPLOAD_BYTES = 5 * 1024 * 1024;\n\nexport function isFileWithinUploadSizeLimit(file: File, maxBytes = MAX_MEDIA_UPLOAD_BYTES) {\n return file.size <= maxBytes;\n}\n\nexport function formatUploadSizeLimit(maxBytes = MAX_MEDIA_UPLOAD_BYTES) {\n return `${Math.round(maxBytes / (1024 * 1024))} MB`;\n}\n\nexport function fileMatchesAccept(file: MediaFile, accept?: Array<\"image\" | \"pdf\">) {\n if (!accept || accept.length === 0) return true;\n const isImage = file.mimeType.startsWith(\"image/\");\n const isPdf = file.mimeType === \"application/pdf\";\n if (accept.includes(\"image\") && isImage) return true;\n if (accept.includes(\"pdf\") && isPdf) return true;\n return false;\n}\n\nexport function fileMatchesAcceptForUpload(file: File, accept?: Array<\"image\" | \"pdf\">) {\n if (!accept || accept.length === 0) return true;\n const isImage = file.type.startsWith(\"image/\");\n const isPdf = file.type === \"application/pdf\";\n if (accept.includes(\"image\") && isImage) return true;\n if (accept.includes(\"pdf\") && isPdf) return true;\n return false;\n}\n\nexport function fileNameFromPath(path: string) {\n return path.split(\"/\").pop() ?? path;\n}\n\nexport function isImagePath(path: string) {\n return /\\.(png|jpe?g|webp|gif)$/i.test(path);\n}\n","import { createPortal } from \"react-dom\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { defaultMediaLibraryConfig } from \"../types\";\nimport type { MediaLibraryModalProps } from \"../types\";\nimport { MediaLibraryPanel } from \"./media-library-panel\";\nimport { fileNameFromPath } from \"../client\";\n\nexport function MediaLibraryModal({\n open,\n onClose,\n onSelect,\n onSelectMany,\n closeOnSelect = true,\n selectionMode = \"single\",\n maxSelections,\n autoSelectUploads = false,\n config,\n theme,\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose media.\",\n accept\n}: MediaLibraryModalProps) {\n const resolved = { ...defaultMediaLibraryConfig, ...config };\n const themeMode = resolveThemeMode(theme ?? resolved.theme);\n const rootProps = bfmlRootProps(themeMode);\n\n if (!open || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n {...rootProps}\n className={cn(\n rootProps.className,\n \"fixed inset-0 z-[9999] flex items-stretch justify-center p-0 backdrop-blur-sm sm:items-center sm:p-2 md:p-4\"\n )}\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n >\n <MediaLibraryPanel\n active={open}\n variant=\"modal\"\n selectable\n config={config}\n theme={theme}\n title={title}\n description={description}\n accept={accept}\n onClose={onClose}\n onSelect={onSelect}\n onSelectMany={onSelectMany}\n closeOnSelect={closeOnSelect}\n selectionMode={selectionMode}\n maxSelections={maxSelections}\n autoSelectUploads={autoSelectUploads}\n />\n </div>,\n document.body\n );\n}\n\nexport function MediaPreview({ path, alt }: { path: string; alt?: string }) {\n const isImage = /\\.(png|jpe?g|webp|gif)$/i.test(path);\n if (!path) {\n return (\n <div className=\"flex h-32 items-center justify-center rounded-xl border border-dashed border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] px-4 text-center text-sm text-[var(--bfml-muted-foreground)] sm:h-40\">\n No media selected\n </div>\n );\n }\n\n if (isImage) {\n return (\n <div className=\"overflow-hidden rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)]\">\n <img src={path} alt={alt ?? fileNameFromPath(path)} className=\"h-32 w-full object-contain sm:h-40\" />\n </div>\n );\n }\n\n return (\n <div className=\"flex h-32 items-center justify-center rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] px-4 text-center text-sm font-medium text-[var(--bfml-foreground)] sm:h-40\">\n {fileNameFromPath(path)}\n </div>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","export type MediaLibraryThemeMode = \"sync\" | \"light\" | \"dark\";\n\nexport function bfmlRootProps(theme: MediaLibraryThemeMode = \"sync\") {\n return {\n className: \"bfml-root\",\n ...(theme !== \"sync\" ? ({ \"data-theme\": theme } as const) : {})\n };\n}\n\nexport function resolveThemeMode(theme?: MediaLibraryThemeMode) {\n return theme ?? \"sync\";\n}\n","import { useEffect, useMemo, useRef, useState, type DragEvent, type MouseEvent } from \"react\";\nimport { ChevronRight, Folder, ImagePlus, LoaderCircle, PanelLeft, Search, Trash2, Upload, X } from \"lucide-react\";\nimport { Button } from \"./ui/button\";\nimport { ConfirmDialog } from \"./ui/confirm-dialog\";\nimport { Input } from \"./ui/input\";\nimport { ToastContainer } from \"./ui/toast-container\";\nimport { UploadPreviewCard, type UploadQueueItem } from \"./upload-preview\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport {\n buildBreadcrumb,\n createQueueId,\n isPathInside,\n parentPath,\n type DeleteTarget\n} from \"../utils/media-library-utils\";\nimport { toastError, toastSuccess, toastWarning } from \"../utils/toast-store\";\nimport {\n createMediaLibraryClient,\n fileMatchesAccept,\n fileMatchesAcceptForUpload,\n formatUploadSizeLimit,\n isFileWithinUploadSizeLimit\n} from \"../client\";\nimport type { MediaCapabilities, MediaFile, MediaFolder, MediaLibraryPanelProps } from \"../types\";\nimport { defaultMediaCapabilities, defaultMediaLibraryConfig } from \"../types\";\n\nexport function MediaLibraryPanel({\n active = true,\n config,\n theme,\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose media.\",\n accept,\n variant = \"embedded\",\n selectable = false,\n closeOnSelect = true,\n selectionMode = \"single\",\n maxSelections,\n autoSelectUploads = false,\n onClose,\n onSelect,\n onSelectMany,\n className\n}: MediaLibraryPanelProps) {\n const client = useMemo(() => createMediaLibraryClient(config), [config]);\n const resolved = useMemo(() => ({ ...defaultMediaLibraryConfig, ...config }), [config]);\n const themeMode = resolveThemeMode(theme ?? resolved.theme);\n const rootProps = bfmlRootProps(themeMode);\n const uploadInputRef = useRef<HTMLInputElement>(null);\n const dragCounterRef = useRef(0);\n\n const [currentPath, setCurrentPath] = useState(\"\");\n const [search, setSearch] = useState(\"\");\n const [folderName, setFolderName] = useState(\"\");\n const [nestedFolder, setNestedFolder] = useState(true);\n const [loading, setLoading] = useState(false);\n const [uploading, setUploading] = useState(false);\n const [dragActive, setDragActive] = useState(false);\n const [capabilities, setCapabilities] = useState<MediaCapabilities>(defaultMediaCapabilities);\n const [uploadQueue, setUploadQueue] = useState<UploadQueueItem[]>([]);\n const [folders, setFolders] = useState<Array<{ name: string; path: string }>>([]);\n const [files, setFiles] = useState<MediaFile[]>([]);\n const [selected, setSelected] = useState<MediaFile | null>(null);\n const [selectedFiles, setSelectedFiles] = useState<MediaFile[]>([]);\n const [deleteTarget, setDeleteTarget] = useState<DeleteTarget | null>(null);\n const [deleting, setDeleting] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n async function load(path = currentPath, q = search, options?: { silent?: boolean }) {\n if (!options?.silent) setLoading(true);\n try {\n const listing = await client.list(path, q);\n setCurrentPath(listing.path);\n setFolders(listing.folders);\n setFiles(listing.files.filter((file) => fileMatchesAccept(file, accept)));\n setCapabilities({ ...defaultMediaCapabilities, ...listing.capabilities });\n } catch (caught) {\n toastError(caught instanceof Error ? caught.message : \"Failed to load media.\");\n } finally {\n if (!options?.silent) setLoading(false);\n }\n }\n\n function clearUploadQueue() {\n setUploadQueue((current) => {\n current.forEach((item) => URL.revokeObjectURL(item.previewUrl));\n return [];\n });\n }\n\n useEffect(() => {\n if (!active) return;\n setSelected(null);\n setSelectedFiles([]);\n setDeleteTarget(null);\n setSidebarOpen(false);\n clearUploadQueue();\n setDragActive(false);\n dragCounterRef.current = 0;\n setSearch(\"\");\n void load(\"\", \"\");\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [active]);\n\n useEffect(() => {\n if (!active || variant !== \"modal\" || !onClose) return;\n const handleClose = onClose;\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== \"Escape\") return;\n if (deleteTarget && !deleting) {\n setDeleteTarget(null);\n return;\n }\n handleClose();\n }\n document.body.style.overflow = \"hidden\";\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.body.style.overflow = \"\";\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [active, deleteTarget, deleting, onClose, variant]);\n\n async function createFolder() {\n if (!capabilities.createFolder) {\n toastError(\"You do not have permission to create folders.\");\n return;\n }\n const name = folderName.trim();\n if (!name) {\n toastError(\"Enter a folder name.\");\n return;\n }\n try {\n await client.createFolder(currentPath, name, nestedFolder);\n setFolderName(\"\");\n await load(currentPath, search);\n toastSuccess(`Folder \"${name}\" created.`);\n } catch (caught) {\n toastError(caught instanceof Error ? caught.message : \"Failed to create folder.\");\n }\n }\n\n async function processFiles(incoming: File[]) {\n if (!capabilities.upload || incoming.length === 0 || uploading) return;\n\n const sizeLimit = formatUploadSizeLimit();\n const accepted: File[] = [];\n let invalidTypeCount = 0;\n\n for (const file of incoming) {\n if (!fileMatchesAcceptForUpload(file, accept)) {\n invalidTypeCount += 1;\n continue;\n }\n if (!isFileWithinUploadSizeLimit(file)) {\n toastWarning(`\"${file.name}\" exceeds ${sizeLimit} and was skipped.`);\n continue;\n }\n accepted.push(file);\n }\n\n if (invalidTypeCount > 0) {\n toastError(`${invalidTypeCount} file(s) were skipped due to type restrictions.`);\n }\n if (accepted.length === 0) return;\n\n const queue: UploadQueueItem[] = accepted.map((file) => ({\n id: createQueueId(),\n file,\n previewUrl: URL.createObjectURL(file),\n status: \"pending\"\n }));\n\n setUploadQueue(queue);\n setUploading(true);\n\n const uploadedFiles: MediaFile[] = [];\n let successCount = 0;\n for (const item of queue) {\n setUploadQueue((current) =>\n current.map((entry) => (entry.id === item.id ? { ...entry, status: \"uploading\" } : entry))\n );\n\n try {\n const uploaded = await client.uploadOne(currentPath, item.file);\n uploadedFiles.push(uploaded);\n successCount += 1;\n URL.revokeObjectURL(item.previewUrl);\n setUploadQueue((current) => current.filter((entry) => entry.id !== item.id));\n await load(currentPath, search, { silent: true });\n } catch (caught) {\n const message = caught instanceof Error ? caught.message : \"Upload failed.\";\n URL.revokeObjectURL(item.previewUrl);\n setUploadQueue((current) => current.filter((entry) => entry.id !== item.id));\n if (/5\\s*mb|too large|file size/i.test(message)) {\n toastWarning(`\"${item.file.name}\" exceeds ${sizeLimit} and was skipped.`);\n } else {\n toastError(`${item.file.name}: ${message}`);\n }\n }\n }\n\n if (successCount > 0) {\n toastSuccess(successCount === 1 ? \"File uploaded successfully.\" : `${successCount} files uploaded successfully.`);\n if (autoSelectUploads && onSelectMany && uploadedFiles.length > 0) {\n const limit = maxSelections ?? uploadedFiles.length;\n onSelectMany(uploadedFiles.slice(0, limit));\n onClose?.();\n }\n }\n\n setUploading(false);\n if (uploadInputRef.current) uploadInputRef.current.value = \"\";\n }\n\n async function uploadFiles(fileList: FileList | null) {\n if (!fileList?.length) return;\n await processFiles(Array.from(fileList));\n }\n\n function handleDragEnter(event: DragEvent) {\n event.preventDefault();\n if (!capabilities.upload) return;\n dragCounterRef.current += 1;\n setDragActive(true);\n }\n\n function handleDragLeave(event: DragEvent) {\n event.preventDefault();\n dragCounterRef.current -= 1;\n if (dragCounterRef.current <= 0) {\n dragCounterRef.current = 0;\n setDragActive(false);\n }\n }\n\n function handleDragOver(event: DragEvent) {\n event.preventDefault();\n }\n\n function handleDrop(event: DragEvent) {\n event.preventDefault();\n dragCounterRef.current = 0;\n setDragActive(false);\n if (!capabilities.upload) return;\n void processFiles(Array.from(event.dataTransfer.files ?? []));\n }\n\n async function confirmDelete() {\n if (!deleteTarget) return;\n setDeleting(true);\n try {\n await client.remove(deleteTarget.path, deleteTarget.type);\n if (deleteTarget.type === \"file\" && selected?.path === deleteTarget.path) {\n setSelected(null);\n }\n const reloadPath =\n deleteTarget.type === \"folder\" && isPathInside(currentPath, deleteTarget.path)\n ? parentPath(deleteTarget.path)\n : currentPath;\n const deletedName = deleteTarget.name;\n const deletedType = deleteTarget.type;\n setDeleteTarget(null);\n await load(reloadPath, search);\n toastSuccess(deletedType === \"folder\" ? `Folder \"${deletedName}\" deleted.` : `File \"${deletedName}\" deleted.`);\n } catch (caught) {\n toastError(caught instanceof Error ? caught.message : \"Delete failed.\");\n } finally {\n setDeleting(false);\n }\n }\n\n function requestDelete(target: DeleteTarget, event?: MouseEvent) {\n if (!capabilities.delete) {\n toastError(\"You do not have permission to delete media.\");\n return;\n }\n event?.preventDefault();\n event?.stopPropagation();\n setDeleteTarget(target);\n }\n\n function navigateTo(path: string) {\n void load(path, search);\n setSidebarOpen(false);\n }\n\n function toggleFileSelection(file: MediaFile) {\n setSelectedFiles((current) => {\n const exists = current.some((item) => item.path === file.path);\n if (exists) {\n return current.filter((item) => item.path !== file.path);\n }\n const limit = maxSelections ?? Number.POSITIVE_INFINITY;\n if (current.length >= limit) {\n toastWarning(`You can add up to ${limit} file${limit === 1 ? \"\" : \"s\"} at a time.`);\n return current;\n }\n return [...current, file];\n });\n setSelected(file);\n }\n\n function confirmSelection() {\n if (selectionMode === \"multi\" && onSelectMany) {\n if (selectedFiles.length === 0) return;\n onSelectMany(selectedFiles);\n onClose?.();\n return;\n }\n if (!selected) return;\n onSelect?.(selected);\n if (closeOnSelect) onClose?.();\n else setSelected(null);\n }\n\n function handleFileClick(file: MediaFile) {\n if (selectionMode === \"multi\" && onSelectMany) {\n toggleFileSelection(file);\n return;\n }\n setSelected(file);\n if (!selectable && onSelect) {\n onSelect(file);\n }\n }\n\n function handleFileDoubleClick(file: MediaFile) {\n if (selectionMode === \"multi\" && onSelectMany) {\n onSelectMany([file]);\n onClose?.();\n return;\n }\n setSelected(file);\n if (selectable) {\n onSelect?.(file);\n if (closeOnSelect) onClose?.();\n else setSelected(null);\n } else if (onSelect) {\n onSelect(file);\n }\n }\n\n if (!active) return null;\n\n const crumbs = buildBreadcrumb(currentPath, resolved.rootLabel ?? \"Root\");\n const sidebarFolders = [{ name: resolved.rootLabel ?? \"Root\", path: \"\" }, ...folders];\n const showFooter = selectable;\n const isMultiSelect = selectionMode === \"multi\" && Boolean(onSelectMany);\n const footerSelectionCount = isMultiSelect ? selectedFiles.length : selected ? 1 : 0;\n const footerCanConfirm = isMultiSelect ? selectedFiles.length > 0 : Boolean(selected);\n const showCloseButton = variant === \"modal\" && Boolean(onClose);\n\n const sidebarFolderList = (\n <div className=\"mt-4 space-y-1 lg:mt-5\">\n {sidebarFolders.map((folder) => {\n const folderActive = folder.path === currentPath;\n const canDelete = Boolean(folder.path) && capabilities.delete;\n return (\n <div\n key={folder.path || \"root\"}\n className={cn(\n \"flex items-center gap-1 rounded-lg transition\",\n folderActive ? \"bg-[var(--bfml-primary)]\" : \"hover:bg-[var(--bfml-surface)]\"\n )}\n >\n <button\n type=\"button\"\n onClick={() => navigateTo(folder.path)}\n className={cn(\n \"flex min-w-0 flex-1 items-center gap-2 px-3 py-2.5 text-left text-sm font-medium transition\",\n folderActive ? \"text-[var(--bfml-primary-foreground)]\" : \"text-[var(--bfml-foreground)]\"\n )}\n >\n <Folder className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{folder.name}</span>\n </button>\n {canDelete ? (\n <button\n type=\"button\"\n title=\"Delete folder\"\n className={cn(\n \"mr-1 rounded-md p-1.5 transition\",\n folderActive\n ? \"text-[var(--bfml-primary-foreground)] hover:bg-[var(--bfml-primary-foreground)]/15\"\n : \"text-[var(--bfml-destructive)] hover:bg-[var(--bfml-destructive-soft)]\"\n )}\n onClick={(event) => requestDelete({ path: folder.path, name: folder.name, type: \"folder\" }, event)}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n\n return (\n <section\n {...rootProps}\n className={cn(\n rootProps.className,\n \"relative flex h-full min-h-0 flex-col overflow-hidden bg-[var(--bfml-surface)]\",\n variant === \"modal\" &&\n \"h-[100dvh] w-full max-w-none border-0 shadow-[var(--bfml-shadow-lg)] sm:h-[min(92vh,760px)] sm:max-w-6xl sm:rounded-2xl sm:border sm:border-[var(--bfml-border)]\",\n variant === \"embedded\" && \"rounded-none border-0 shadow-none\",\n className\n )}\n >\n <header className=\"flex shrink-0 items-start justify-between gap-3 border-b border-[var(--bfml-border)] px-4 py-3 sm:gap-4 sm:px-6 sm:py-5\">\n <div className=\"min-w-0 pr-2\">\n <h2 className=\"truncate text-base font-semibold text-[var(--bfml-foreground)] sm:text-lg\">{title}</h2>\n {description ? (\n <p className=\"mt-1 hidden text-sm text-[var(--bfml-muted-foreground)] sm:block\">{description}</p>\n ) : null}\n </div>\n {showCloseButton ? (\n <Button type=\"button\" variant=\"ghost\" className=\"h-10 w-10 shrink-0 px-0\" onClick={onClose} aria-label=\"Close media library\">\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n ) : null}\n </header>\n\n <ToastContainer theme={themeMode} />\n\n <div className=\"relative flex min-h-0 flex-1 flex-col overflow-hidden lg:grid lg:h-full lg:min-h-0 lg:grid-cols-[minmax(0,240px)_1fr] lg:grid-rows-1\">\n {sidebarOpen ? (\n <button\n type=\"button\"\n className=\"absolute inset-0 z-20 lg:hidden\"\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n aria-label=\"Close folders panel\"\n onClick={() => setSidebarOpen(false)}\n />\n ) : null}\n\n <aside\n className={cn(\n \"absolute inset-y-0 left-0 z-30 flex w-[min(88vw,280px)] flex-col overflow-y-auto border-r border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] p-4 shadow-xl transition-transform duration-200 ease-out lg:static lg:z-auto lg:h-full lg:min-h-0 lg:w-auto lg:translate-x-0 lg:shadow-none\",\n sidebarOpen ? \"translate-x-0\" : \"-translate-x-full lg:translate-x-0\"\n )}\n >\n <div className=\"mb-3 flex items-center justify-between lg:hidden\">\n <p className=\"text-sm font-semibold text-[var(--bfml-foreground)]\">Folders</p>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 px-0\" onClick={() => setSidebarOpen(false)} aria-label=\"Close folders panel\">\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {capabilities.createFolder ? (\n <div className=\"space-y-3\">\n <div className=\"flex flex-col gap-2 sm:flex-row\">\n <Input\n value={folderName}\n onChange={(event) => setFolderName(event.target.value)}\n placeholder=\"new-folder\"\n className=\"min-w-0\"\n />\n <Button type=\"button\" variant=\"secondary\" className=\"shrink-0 sm:px-4\" onClick={createFolder}>\n Add\n </Button>\n </div>\n <label className=\"flex items-start gap-2 text-xs leading-5 text-[var(--bfml-muted-foreground)]\">\n <input\n type=\"checkbox\"\n className=\"mt-0.5\"\n checked={nestedFolder}\n onChange={(event) => setNestedFolder(event.target.checked)}\n />\n <span>Create as nested folder of current path</span>\n </label>\n </div>\n ) : null}\n\n {sidebarFolderList}\n </aside>\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden p-3 sm:p-5 lg:h-full lg:min-h-0\">\n <div className=\"flex flex-wrap items-center gap-2 sm:gap-3\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"shrink-0 lg:hidden\"\n onClick={() => setSidebarOpen(true)}\n aria-label=\"Open folders panel\"\n >\n <PanelLeft className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Folders</span>\n </Button>\n\n <div className=\"relative min-w-0 flex-1 basis-[180px]\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--bfml-muted-foreground)]\" />\n <Input\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") void load(currentPath, search);\n }}\n placeholder=\"Search files\"\n />\n </div>\n\n <input\n ref={uploadInputRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n accept={accept?.includes(\"pdf\") ? \"image/*,application/pdf\" : \"image/*\"}\n onChange={(event) => void uploadFiles(event.target.files)}\n />\n {capabilities.upload ? (\n <Button\n type=\"button\"\n disabled={uploading}\n className=\"w-full shrink-0 sm:w-auto\"\n onClick={() => uploadInputRef.current?.click()}\n aria-label=\"Upload files\"\n >\n {uploading ? <LoaderCircle className=\"h-4 w-4 animate-spin\" /> : <Upload className=\"h-4 w-4\" />}\n <span className=\"sm:inline\">Upload</span>\n </Button>\n ) : null}\n </div>\n\n <div className=\"-mx-1 mt-3 flex items-center gap-1 overflow-x-auto px-1 pb-1 text-sm sm:mt-4\">\n {crumbs.map((crumb, index) => (\n <div key={crumb.path} className=\"flex shrink-0 items-center gap-1\">\n <button\n type=\"button\"\n className={cn(\n \"max-w-[9rem] truncate rounded px-1.5 py-1 font-medium transition sm:max-w-none\",\n index === crumbs.length - 1\n ? \"text-[var(--bfml-primary)]\"\n : \"text-[var(--bfml-muted-foreground)] hover:text-[var(--bfml-foreground)]\"\n )}\n onClick={() => navigateTo(crumb.path)}\n >\n {crumb.label}\n </button>\n {index < crumbs.length - 1 ? (\n <ChevronRight className=\"h-4 w-4 shrink-0 text-[var(--bfml-muted-foreground)]\" />\n ) : null}\n </div>\n ))}\n </div>\n\n <div\n className={cn(\n \"relative mt-3 min-h-0 flex-1 overflow-y-auto sm:mt-4\",\n dragActive && capabilities.upload && \"rounded-xl ring-2 ring-[var(--bfml-primary)] ring-offset-2 ring-offset-[var(--bfml-surface)]\"\n )}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {dragActive && capabilities.upload ? (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-xl border-2 border-dashed border-[var(--bfml-primary)] bg-[var(--bfml-primary-soft)]/80 px-4 text-center\">\n <div>\n <Upload className=\"mx-auto mb-2 h-8 w-8 text-[var(--bfml-primary)]\" />\n <p className=\"text-sm font-semibold text-[var(--bfml-foreground)]\">Drop files to upload</p>\n <p className=\"mt-1 text-xs text-[var(--bfml-muted-foreground)]\">Files upload one by one</p>\n </div>\n </div>\n ) : null}\n\n {loading && uploadQueue.length === 0 ? (\n <div className=\"flex h-32 items-center justify-center text-sm text-[var(--bfml-muted-foreground)] sm:h-40\">\n <LoaderCircle className=\"mr-2 h-4 w-4 animate-spin\" />\n Loading media...\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4 lg:grid-cols-3 xl:grid-cols-4\">\n {uploadQueue.map((item) => (\n <UploadPreviewCard key={item.id} item={item} />\n ))}\n\n {folders.map((folder: MediaFolder) => (\n <div\n key={folder.path}\n className=\"group relative rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] transition hover:border-[var(--bfml-primary-border)]\"\n >\n <button\n type=\"button\"\n onDoubleClick={() => navigateTo(folder.path)}\n onClick={() => navigateTo(folder.path)}\n className=\"block w-full p-3 text-left sm:p-4\"\n >\n <Folder className=\"h-7 w-7 text-[var(--bfml-primary)] sm:h-8 sm:w-8\" />\n <p className=\"mt-2 truncate text-sm font-medium text-[var(--bfml-foreground)] sm:mt-3\">{folder.name}</p>\n <p className=\"text-xs text-[var(--bfml-muted-foreground)]\">Folder</p>\n </button>\n {capabilities.delete ? (\n <button\n type=\"button\"\n title=\"Delete folder\"\n className=\"absolute right-1.5 top-1.5 rounded-md border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-1.5 shadow-sm transition hover:bg-[var(--bfml-destructive-soft)] sm:right-2 sm:top-2\"\n onClick={(event) =>\n requestDelete({ path: folder.path, name: folder.name, type: \"folder\" }, event)\n }\n >\n <Trash2 className=\"h-3.5 w-3.5 text-[var(--bfml-destructive)] sm:h-4 sm:w-4\" />\n </button>\n ) : null}\n </div>\n ))}\n\n {files.map((file) => {\n const fileActive = isMultiSelect\n ? selectedFiles.some((item) => item.path === file.path)\n : selected?.path === file.path;\n const isImage = file.mimeType.startsWith(\"image/\");\n return (\n <div\n key={file.path}\n className={cn(\n \"group relative overflow-hidden rounded-xl border bg-[var(--bfml-surface)] transition\",\n fileActive && selectable\n ? \"border-[var(--bfml-primary)] ring-2 ring-[var(--bfml-primary-soft)]\"\n : \"border-[var(--bfml-border)] hover:border-[var(--bfml-primary-border)]\"\n )}\n >\n <button\n type=\"button\"\n className=\"block w-full p-2 text-left sm:p-3\"\n onClick={() => handleFileClick(file)}\n onDoubleClick={() => handleFileDoubleClick(file)}\n >\n <div className=\"flex h-20 items-center justify-center overflow-hidden rounded-lg bg-[var(--bfml-surface-soft)] sm:h-28\">\n {isImage ? (\n <img src={file.url} alt={file.name} className=\"h-full w-full object-contain\" />\n ) : (\n <div className=\"text-xs font-semibold uppercase text-[var(--bfml-muted-foreground)]\">PDF</div>\n )}\n </div>\n <p className=\"mt-2 truncate text-sm font-medium text-[var(--bfml-foreground)] sm:mt-3\">{file.name}</p>\n <p className=\"text-xs text-[var(--bfml-muted-foreground)]\">File</p>\n </button>\n {capabilities.delete ? (\n <button\n type=\"button\"\n title=\"Delete file\"\n className=\"absolute right-1.5 top-1.5 rounded-md border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-1.5 shadow-sm transition hover:bg-[var(--bfml-destructive-soft)] sm:right-2 sm:top-2\"\n onClick={(event) => requestDelete({ path: file.path, name: file.name, type: \"file\" }, event)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-[var(--bfml-destructive)] sm:h-4 sm:w-4\" />\n </button>\n ) : null}\n </div>\n );\n })}\n </div>\n )}\n\n {!loading && folders.length === 0 && files.length === 0 && uploadQueue.length === 0 ? (\n <div className=\"flex h-32 flex-col items-center justify-center rounded-xl border border-dashed border-[var(--bfml-border)] px-4 text-center text-sm text-[var(--bfml-muted-foreground)] sm:h-40\">\n <ImagePlus className=\"mb-2 h-6 w-6\" />\n No files in this folder yet.\n {capabilities.upload ? <p className=\"mt-2 text-xs\">Drag and drop files here or use Upload.</p> : null}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n\n {showFooter ? (\n <footer className=\"flex shrink-0 flex-col-reverse gap-2 border-t border-[var(--bfml-border)] px-4 py-3 sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:px-6 sm:py-4\">\n <p className=\"truncate text-center text-sm text-[var(--bfml-muted-foreground)] sm:text-left\">\n {isMultiSelect\n ? footerSelectionCount === 0\n ? \"Select one or more files\"\n : `${footerSelectionCount} file${footerSelectionCount === 1 ? \"\" : \"s\"} selected`\n : `Selected: ${selected ? selected.name : \"None\"}`}\n </p>\n <Button type=\"button\" className=\"w-full sm:w-auto\" disabled={!footerCanConfirm} onClick={confirmSelection}>\n {isMultiSelect\n ? footerSelectionCount > 0\n ? `Add ${footerSelectionCount} file${footerSelectionCount === 1 ? \"\" : \"s\"}`\n : \"Add files\"\n : closeOnSelect\n ? \"Done\"\n : \"Add\"}\n </Button>\n </footer>\n ) : null}\n\n <ConfirmDialog\n open={Boolean(deleteTarget)}\n title={deleteTarget?.type === \"folder\" ? \"Delete folder?\" : \"Delete file?\"}\n description={\n deleteTarget\n ? deleteTarget.type === \"folder\"\n ? `Are you sure you want to delete the folder \"${deleteTarget.name}\" and everything inside it? This action cannot be undone.`\n : `Are you sure you want to delete \"${deleteTarget.name}\"? This action cannot be undone.`\n : \"\"\n }\n confirmLabel=\"Delete\"\n loading={deleting}\n onCancel={() => {\n if (!deleting) setDeleteTarget(null);\n }}\n onConfirm={() => void confirmDelete()}\n theme={themeMode}\n />\n </section>\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\ntype ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: \"primary\" | \"secondary\" | \"danger\" | \"ghost\";\n};\n\nconst variants = {\n primary: \"bg-[var(--bfml-primary)] text-[var(--bfml-primary-foreground)] shadow-[var(--bfml-shadow)] hover:brightness-95\",\n secondary:\n \"border border-[var(--bfml-border)] bg-[var(--bfml-surface)] text-[var(--bfml-foreground)] shadow-[var(--bfml-shadow)] hover:bg-[var(--bfml-surface-soft)]\",\n danger: \"bg-[var(--bfml-destructive)] text-[var(--bfml-primary-foreground)] hover:brightness-95\",\n ghost: \"bg-transparent text-[var(--bfml-muted-foreground)] hover:bg-[var(--bfml-surface-soft)] hover:text-[var(--bfml-foreground)]\"\n};\n\nexport function Button({ className, variant = \"primary\", disabled, children, ...props }: ButtonProps) {\n return (\n <button\n className={cn(\n \"inline-flex h-10 items-center justify-center gap-2 rounded-lg px-4 text-sm font-semibold transition disabled:pointer-events-none disabled:opacity-50\",\n variants[variant],\n className\n )}\n disabled={disabled}\n {...props}\n >\n {children}\n </button>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport type { MediaLibraryThemeMode } from \"../../theme\";\nimport { bfmlRootProps } from \"../../utils/bfml-theme\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"./button\";\n\ntype ConfirmDialogProps = {\n open: boolean;\n title: string;\n description: string;\n confirmLabel?: string;\n cancelLabel?: string;\n loading?: boolean;\n theme?: MediaLibraryThemeMode;\n onCancel: () => void;\n onConfirm: () => void;\n};\n\nexport function ConfirmDialog({\n open,\n title,\n description,\n confirmLabel = \"Delete\",\n cancelLabel = \"Cancel\",\n loading = false,\n theme = \"sync\",\n onCancel,\n onConfirm\n}: ConfirmDialogProps) {\n if (!open || typeof document === \"undefined\") return null;\n\n const rootProps = bfmlRootProps(theme);\n\n return createPortal(\n <div\n {...rootProps}\n className={cn(rootProps.className, \"fixed inset-0 z-[10001] flex items-end justify-center p-0 backdrop-blur-sm sm:items-center sm:p-4\")}\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n role=\"presentation\"\n onClick={onCancel}\n >\n <section\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"bfml-confirm-title\"\n aria-describedby=\"bfml-confirm-description\"\n className=\"w-full max-w-md rounded-t-2xl border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-4 shadow-[var(--bfml-shadow-lg)] sm:rounded-2xl sm:p-6\"\n onClick={(event) => event.stopPropagation()}\n >\n <h3 id=\"bfml-confirm-title\" className=\"text-lg font-semibold text-[var(--bfml-foreground)]\">\n {title}\n </h3>\n <p id=\"bfml-confirm-description\" className=\"mt-2 text-sm text-[var(--bfml-muted-foreground)]\">\n {description}\n </p>\n <div className=\"mt-5 flex flex-col-reverse gap-2 sm:mt-6 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" disabled={loading} className=\"w-full sm:w-auto\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button type=\"button\" variant=\"danger\" disabled={loading} className=\"w-full sm:w-auto\" onClick={onConfirm}>\n {loading ? \"Deleting...\" : confirmLabel}\n </Button>\n </div>\n </section>\n </div>,\n document.body\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(function Input(\n { className, ...props },\n ref\n) {\n return (\n <input\n ref={ref}\n className={cn(\n \"h-11 w-full rounded-lg border border-[var(--bfml-border)] bg-[var(--bfml-surface)] px-4 text-sm text-[var(--bfml-foreground)] shadow-[var(--bfml-shadow)] outline-none transition placeholder:text-[var(--bfml-muted-foreground)] focus:border-[var(--bfml-primary-border)] focus:ring-4 focus:ring-[var(--bfml-primary-soft)]\",\n className\n )}\n {...props}\n />\n );\n});\n","import { useEffect, useState } from \"react\";\nimport { CheckCircle2, TriangleAlert, X, XCircle } from \"lucide-react\";\nimport type { MediaLibraryThemeMode } from \"../../theme\";\nimport { dismissToast, subscribeToasts, type ToastItem } from \"../../utils/toast-store\";\nimport { bfmlRootProps } from \"../../utils/bfml-theme\";\nimport { cn } from \"../../utils/cn\";\n\nfunction ToastCard({ toast }: { toast: ToastItem }) {\n const isSuccess = toast.type === \"success\";\n const isWarning = toast.type === \"warning\";\n\n return (\n <div\n role=\"status\"\n className={cn(\n \"pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border px-4 py-3 shadow-[var(--bfml-shadow-lg)] transition\",\n isSuccess\n ? \"border-[var(--bfml-success)]/30 bg-[var(--bfml-success-soft)] text-[var(--bfml-success-foreground)]\"\n : isWarning\n ? \"border-[var(--bfml-warning)]/30 bg-[var(--bfml-warning-soft)] text-[var(--bfml-warning-foreground)]\"\n : \"border-[var(--bfml-destructive)]/30 bg-[var(--bfml-destructive-soft)] text-[var(--bfml-foreground)]\"\n )}\n >\n {isSuccess ? (\n <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-[var(--bfml-success)]\" aria-hidden=\"true\" />\n ) : isWarning ? (\n <TriangleAlert className=\"mt-0.5 h-4 w-4 shrink-0 text-[var(--bfml-warning)]\" aria-hidden=\"true\" />\n ) : (\n <XCircle className=\"mt-0.5 h-4 w-4 shrink-0 text-[var(--bfml-destructive)]\" aria-hidden=\"true\" />\n )}\n <p className=\"min-w-0 flex-1 text-sm font-medium leading-5\">{toast.message}</p>\n <button\n type=\"button\"\n className=\"rounded-md p-0.5 opacity-70 transition hover:opacity-100\"\n aria-label=\"Dismiss notification\"\n onClick={() => dismissToast(toast.id)}\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n );\n}\n\nexport function ToastContainer({ theme = \"sync\" }: { theme?: MediaLibraryThemeMode }) {\n const [items, setItems] = useState<ToastItem[]>([]);\n const rootProps = bfmlRootProps(theme);\n\n useEffect(() => {\n return subscribeToasts(setItems);\n }, []);\n\n if (items.length === 0) return null;\n\n return (\n <div\n {...rootProps}\n className={cn(rootProps.className, \"pointer-events-none absolute right-3 top-3 z-[45] flex w-[min(100%,20rem)] flex-col items-end gap-2 sm:right-4 sm:top-4\")}\n >\n {items.map((toast) => (\n <ToastCard key={toast.id} toast={toast} />\n ))}\n </div>\n );\n}\n","export type ToastType = \"success\" | \"error\" | \"warning\";\n\nexport type ToastItem = {\n id: string;\n type: ToastType;\n message: string;\n};\n\ntype ToastListener = (toasts: ToastItem[]) => void;\n\nconst listeners = new Set<ToastListener>();\nlet toasts: ToastItem[] = [];\n\nfunction emit() {\n listeners.forEach((listener) => listener([...toasts]));\n}\n\nfunction createId() {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nexport function dismissToast(id: string) {\n toasts = toasts.filter((toast) => toast.id !== id);\n emit();\n}\n\nexport function showToast(type: ToastType, message: string, durationMs = 3500) {\n const id = createId();\n toasts = [...toasts, { id, type, message }];\n emit();\n window.setTimeout(() => dismissToast(id), durationMs);\n}\n\nexport function subscribeToasts(listener: ToastListener) {\n listeners.add(listener);\n listener([...toasts]);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function toastSuccess(message: string) {\n showToast(\"success\", message);\n}\n\nexport function toastError(message: string) {\n showToast(\"error\", message);\n}\n\nexport function toastWarning(message: string) {\n showToast(\"warning\", message);\n}\n","import { CheckCircle2, LoaderCircle, XCircle } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\n\nexport type UploadQueueItem = {\n id: string;\n file: File;\n previewUrl: string;\n status: \"pending\" | \"uploading\" | \"done\" | \"error\";\n error?: string;\n};\n\nexport function UploadPreviewCard({ item }: { item: UploadQueueItem }) {\n const isImage = item.file.type.startsWith(\"image/\");\n\n return (\n <div\n className={cn(\n \"relative overflow-hidden rounded-xl border bg-[var(--bfml-surface)] p-2 sm:p-3\",\n item.status === \"done\"\n ? \"border-[var(--bfml-success)]/40\"\n : item.status === \"error\"\n ? \"border-[var(--bfml-destructive)]/40\"\n : \"border-[var(--bfml-border)]\"\n )}\n >\n <div className=\"relative flex h-20 items-center justify-center overflow-hidden rounded-lg bg-[var(--bfml-surface-soft)] sm:h-28\">\n {isImage ? (\n <img src={item.previewUrl} alt={item.file.name} className=\"h-full w-full object-contain opacity-80\" />\n ) : (\n <div className=\"text-xs font-semibold uppercase text-[var(--bfml-muted-foreground)]\">PDF</div>\n )}\n\n {item.status === \"pending\" || item.status === \"uploading\" ? (\n <div\n className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 px-2 text-[var(--bfml-primary-foreground)]\"\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n >\n <LoaderCircle className=\"h-6 w-6 animate-spin\" />\n <span className=\"text-xs font-medium\">{item.status === \"uploading\" ? \"Uploading...\" : \"Waiting...\"}</span>\n </div>\n ) : null}\n\n {item.status === \"done\" ? (\n <div\n className=\"absolute inset-0 flex items-center justify-center\"\n style={{ backgroundColor: \"color-mix(in srgb, var(--bfml-success) 25%, transparent)\" }}\n >\n <CheckCircle2 className=\"h-8 w-8 text-[var(--bfml-success)]\" />\n </div>\n ) : null}\n\n {item.status === \"error\" ? (\n <div\n className=\"absolute inset-0 flex items-center justify-center\"\n style={{ backgroundColor: \"color-mix(in srgb, var(--bfml-destructive) 25%, transparent)\" }}\n >\n <XCircle className=\"h-8 w-8 text-[var(--bfml-destructive)]\" />\n </div>\n ) : null}\n </div>\n\n <p className=\"mt-2 truncate text-sm font-medium text-[var(--bfml-foreground)]\">{item.file.name}</p>\n <p className=\"truncate text-xs text-[var(--bfml-muted-foreground)]\">\n {item.status === \"error\" ? item.error ?? \"Upload failed\" : item.status === \"done\" ? \"Uploaded\" : \"In queue\"}\n </p>\n </div>\n );\n}\n","export type DeleteTarget = {\n path: string;\n name: string;\n type: \"file\" | \"folder\";\n};\n\nexport function parentPath(path: string) {\n const segments = path.split(\"/\").filter(Boolean);\n segments.pop();\n return segments.join(\"/\");\n}\n\nexport function isPathInside(path: string, folderPath: string) {\n return path === folderPath || path.startsWith(`${folderPath}/`);\n}\n\nexport function buildBreadcrumb(path: string, rootLabel: string) {\n const segments = path ? path.split(\"/\").filter(Boolean) : [];\n const crumbs = [{ label: rootLabel, path: \"\" }];\n segments.forEach((segment, index) => {\n crumbs.push({ label: segment, path: segments.slice(0, index + 1).join(\"/\") });\n });\n return crumbs;\n}\n\nexport function createQueueId() {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nexport function toCssSize(value?: string | number) {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return `${value}px`;\n\n const trimmed = value.trim();\n if (/^calc\\s*\\(/i.test(trimmed) || /^var\\s*\\(/i.test(trimmed)) return trimmed;\n\n // e.g. \"100vh-200px\" or \"100vh - 200px\" → calc(100vh - 200px)\n if (/^[\\d.]+\\s*(vh|vw|vmin|vmax|%|px|rem|em)\\s*[-+]\\s*[\\d.]+/i.test(trimmed)) {\n const normalized = trimmed.replace(/\\s*([+-])\\s*/g, \" $1 \");\n return `calc(${normalized})`;\n }\n\n return trimmed;\n}\n","import { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { toCssSize } from \"../utils/media-library-utils\";\nimport { defaultMediaLibraryConfig } from \"../types\";\nimport type { MediaLibraryWidgetProps } from \"../types\";\nimport { MediaLibraryPanel } from \"./media-library-panel\";\n\nexport function MediaLibraryWidget({\n width = \"100%\",\n height = 640,\n config,\n theme,\n title = \"Media Library\",\n description = \"Create folders, upload files, and manage media.\",\n accept,\n selectable = false,\n onSelect,\n className\n}: MediaLibraryWidgetProps) {\n const resolved = { ...defaultMediaLibraryConfig, ...config };\n const themeMode = resolveThemeMode(theme ?? resolved.theme);\n const rootProps = bfmlRootProps(themeMode);\n\n return (\n <div\n {...rootProps}\n className={cn(\n rootProps.className,\n \"overflow-hidden rounded-2xl border border-[var(--bfml-border)] bg-[var(--bfml-surface)] shadow-[var(--bfml-shadow-lg)]\",\n className\n )}\n style={{\n width: toCssSize(width),\n height: toCssSize(height)\n }}\n >\n <MediaLibraryPanel\n active\n variant=\"embedded\"\n config={config}\n theme={theme}\n title={title}\n description={description}\n accept={accept}\n selectable={selectable}\n onSelect={onSelect}\n className=\"h-full\"\n />\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { Upload } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { fileNameFromPath } from \"../client\";\nimport { MediaLibraryModal } from \"./media-library-modal\";\nimport { PickerThumbnail } from \"./picker-thumbnail\";\nimport type { MediaPickerProps } from \"../types\";\n\nexport function MediaPicker({\n name,\n label = \"Choose image\",\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose media.\",\n value,\n defaultValue = \"\",\n onChange,\n config,\n theme,\n accept = [\"image\"],\n className\n}: MediaPickerProps) {\n const themeMode = resolveThemeMode(theme ?? config?.theme);\n const rootProps = bfmlRootProps(themeMode);\n const [open, setOpen] = useState(false);\n const [selectedPath, setSelectedPath] = useState(value ?? defaultValue);\n\n useEffect(() => {\n if (value !== undefined) setSelectedPath(value);\n }, [value]);\n\n function handleSelect(file: { url: string }) {\n setSelectedPath(file.url);\n onChange?.(file.url);\n setOpen(false);\n }\n\n const currentValue = value ?? selectedPath;\n const fileName = currentValue ? fileNameFromPath(currentValue) : null;\n\n return (\n <div {...rootProps} className={cn(rootProps.className, \"space-y-2\", className)}>\n {label ? <label className=\"text-sm font-medium text-[var(--bfml-foreground)]\">{label}</label> : null}\n\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"flex w-full items-center gap-3 rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] px-3 py-3 text-left transition hover:border-[var(--bfml-primary-border)] hover:bg-[var(--bfml-surface)] sm:gap-4 sm:px-4 sm:py-4\"\n >\n <PickerThumbnail path={currentValue} alt={fileName ?? label} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-semibold text-[var(--bfml-foreground)]\">{label}</span>\n <span className=\"mt-0.5 block truncate text-xs text-[var(--bfml-muted-foreground)]\">\n {fileName ?? \"Select from folders or upload new\"}\n </span>\n </span>\n <Upload className=\"hidden h-5 w-5 shrink-0 text-[var(--bfml-muted-foreground)] sm:block\" aria-hidden=\"true\" />\n </button>\n\n <input type=\"hidden\" name={name} value={currentValue} />\n\n <MediaLibraryModal\n open={open}\n onClose={() => setOpen(false)}\n onSelect={handleSelect}\n config={config}\n theme={themeMode}\n title={title}\n description={description}\n accept={accept}\n />\n </div>\n );\n}\n","import { FileText, ImagePlus } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { isImagePath } from \"../client\";\n\ntype PickerThumbnailProps = {\n path?: string;\n alt?: string;\n size?: \"sm\" | \"md\" | \"grid\";\n shape?: \"circle\" | \"square\";\n className?: string;\n};\n\nconst sizeClasses = {\n sm: \"h-9 w-9\",\n md: \"h-10 w-10 sm:h-12 sm:w-12\",\n grid: \"h-full w-full\"\n};\n\nexport function PickerThumbnail({\n path,\n alt,\n size = \"md\",\n shape = \"circle\",\n className\n}: PickerThumbnailProps) {\n const isImage = Boolean(path && isImagePath(path));\n const rounded = shape === \"circle\" ? \"rounded-full\" : \"rounded-lg\";\n\n return (\n <span\n className={cn(\n \"flex shrink-0 items-center justify-center overflow-hidden border border-[var(--bfml-border)] bg-[var(--bfml-surface)]\",\n size !== \"grid\" && sizeClasses[size],\n rounded,\n !path && \"text-[var(--bfml-primary)]\",\n className\n )}\n >\n {!path ? (\n <ImagePlus className={size === \"sm\" ? \"h-4 w-4\" : \"h-5 w-5\"} aria-hidden=\"true\" />\n ) : isImage ? (\n <img src={path} alt={alt ?? \"Selected media\"} className=\"h-full w-full object-cover\" />\n ) : (\n <FileText className={size === \"sm\" ? \"h-4 w-4\" : \"h-5 w-5\"} aria-hidden=\"true\" />\n )}\n </span>\n );\n}\n\nexport function PickerThumbnailStack({ paths }: { paths: string[] }) {\n if (paths.length === 0) {\n return (\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[var(--bfml-surface)] text-[var(--bfml-primary)] sm:h-12 sm:w-12\">\n <ImagePlus className=\"h-5 w-5\" aria-hidden=\"true\" />\n </span>\n );\n }\n\n if (paths.length === 1) {\n return <PickerThumbnail path={paths[0]} alt=\"Selected media\" />;\n }\n\n const visible = paths.slice(0, 3);\n\n return (\n <span className=\"relative flex h-10 w-10 shrink-0 items-center sm:h-12 sm:w-12\">\n {visible.map((path, index) => (\n <span\n key={`${path}-${index}`}\n className={cn(\n \"absolute overflow-hidden rounded-full border-2 border-[var(--bfml-surface-soft)] bg-[var(--bfml-surface)]\",\n index === 0 && \"left-0 top-0 z-30 h-7 w-7 sm:h-8 sm:w-8\",\n index === 1 && \"left-3 top-1 z-20 h-7 w-7 sm:left-4 sm:h-8 sm:w-8\",\n index === 2 && \"left-1 top-3 z-10 h-7 w-7 sm:top-4 sm:h-8 sm:w-8\"\n )}\n >\n <PickerThumbnail path={path} size=\"grid\" shape=\"circle\" className=\"h-full w-full border-0\" />\n </span>\n ))}\n {paths.length > 3 ? (\n <span className=\"absolute -bottom-0.5 -right-0.5 z-40 rounded-full bg-[var(--bfml-primary)] px-1.5 py-0.5 text-[10px] font-semibold leading-none text-[var(--bfml-primary-foreground)]\">\n +{paths.length - 3}\n </span>\n ) : null}\n </span>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { Upload, X } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { fileNameFromPath, isImagePath } from \"../client\";\nimport { MediaLibraryModal } from \"./media-library-modal\";\nimport { PickerThumbnailStack } from \"./picker-thumbnail\";\nimport type { MediaFile } from \"../types\";\nimport type { MediaPickerMultiProps } from \"../types\";\n\nexport function MediaPickerMulti({\n name,\n label = \"Choose attachments\",\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose one or more attachments.\",\n max = 10,\n values,\n defaultValues = [],\n onChange,\n config,\n theme,\n accept = [\"image\", \"pdf\"],\n className\n}: MediaPickerMultiProps) {\n const themeMode = resolveThemeMode(theme ?? config?.theme);\n const rootProps = bfmlRootProps(themeMode);\n const [open, setOpen] = useState(false);\n const [selectedPaths, setSelectedPaths] = useState<string[]>(values ?? defaultValues);\n\n useEffect(() => {\n if (values !== undefined) setSelectedPaths(values);\n }, [values]);\n\n const currentValues = values ?? selectedPaths;\n const atMax = currentValues.length >= max;\n\n function handleSelectMany(files: MediaFile[]) {\n setSelectedPaths((current) => {\n const next = [...current];\n for (const file of files) {\n if (next.includes(file.url) || next.length >= max) continue;\n next.push(file.url);\n }\n onChange?.(next);\n return next;\n });\n setOpen(false);\n }\n\n function removeAt(index: number) {\n setSelectedPaths((current) => {\n const next = current.filter((_, itemIndex) => itemIndex !== index);\n onChange?.(next);\n return next;\n });\n }\n\n return (\n <div {...rootProps} className={cn(rootProps.className, \"space-y-2\", className)}>\n {label ? <label className=\"text-sm font-medium text-[var(--bfml-foreground)]\">{label}</label> : null}\n\n <div className=\"overflow-hidden rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)]\">\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n disabled={atMax}\n className=\"flex w-full items-center gap-3 px-3 py-3 text-left transition hover:bg-[var(--bfml-surface)] disabled:cursor-not-allowed disabled:opacity-60 sm:gap-4 sm:px-4 sm:py-4\"\n >\n <PickerThumbnailStack paths={currentValues} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-semibold text-[var(--bfml-foreground)]\">{label}</span>\n <span className=\"mt-0.5 block text-xs text-[var(--bfml-muted-foreground)]\">\n {currentValues.length > 0\n ? `${currentValues.length} selected · click to add more (${currentValues.length}/${max})`\n : `Select from folders or upload new (0/${max})`}\n </span>\n </span>\n <Upload className=\"hidden h-5 w-5 shrink-0 text-[var(--bfml-muted-foreground)] sm:block\" aria-hidden=\"true\" />\n </button>\n\n {currentValues.length > 0 ? (\n <div className=\"grid grid-cols-3 gap-2 border-t border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-3 sm:grid-cols-4 sm:p-4\">\n {currentValues.map((path, index) => {\n const fileName = fileNameFromPath(path);\n const isImage = isImagePath(path);\n return (\n <div\n key={`${path}-${index}`}\n className=\"group relative aspect-square overflow-hidden rounded-lg border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)]\"\n >\n {isImage ? (\n <img src={path} alt={fileName} className=\"h-full w-full object-cover\" />\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-1 px-1 text-center text-[var(--bfml-muted-foreground)]\">\n <span className=\"text-[10px] font-semibold uppercase\">PDF</span>\n </div>\n )}\n <button\n type=\"button\"\n className=\"absolute right-1 top-1 rounded-md border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-1 shadow-sm transition hover:bg-[var(--bfml-destructive-soft)]\"\n onClick={() => removeAt(index)}\n title=\"Remove attachment\"\n >\n <X className=\"h-3 w-3 text-[var(--bfml-destructive)]\" />\n </button>\n <div className=\"absolute inset-x-0 bottom-0 bg-[var(--bfml-overlay)] px-1.5 py-1\">\n <p className=\"truncate text-[10px] font-medium text-[var(--bfml-primary-foreground)]\">{fileName}</p>\n </div>\n </div>\n );\n })}\n </div>\n ) : null}\n </div>\n\n {currentValues.map((path, index) => (\n <input key={`${path}-${index}`} type=\"hidden\" name={`${name}[${index}]`} value={path} />\n ))}\n\n <MediaLibraryModal\n open={open}\n onClose={() => setOpen(false)}\n onSelectMany={handleSelectMany}\n selectionMode=\"multi\"\n maxSelections={Math.max(0, max - currentValues.length)}\n autoSelectUploads\n config={config}\n theme={themeMode}\n title={title}\n description={description}\n accept={accept}\n />\n </div>\n );\n}\n"],"mappings":"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","names":["import_react_dom","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","Input","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/client.ts","../src/components/media-library-modal.tsx","../src/utils/bfml-theme.ts","../src/components/media-library-panel.tsx","../src/utils/cn.ts","../src/components/ui/button.tsx","../src/components/ui/confirm-dialog.tsx","../src/components/ui/input.tsx","../src/components/ui/toast-container.tsx","../src/utils/toast-store.ts","../src/components/upload-preview.tsx","../src/utils/media-library-utils.ts","../src/components/media-library-widget.tsx","../src/components/media-picker.tsx","../src/components/picker-thumbnail.tsx","../src/components/media-picker-multi.tsx"],"sourcesContent":["export {\n createMediaLibraryClient,\n fileMatchesAccept,\n fileMatchesAcceptForUpload,\n fileNameFromPath,\n formatUploadSizeLimit,\n isFileWithinUploadSizeLimit,\n isImagePath,\n MAX_MEDIA_UPLOAD_BYTES\n} from \"./client\";\nexport { MediaLibraryModal, MediaPreview } from \"./components/media-library-modal\";\nexport { MediaLibraryPanel } from \"./components/media-library-panel\";\nexport { MediaLibraryWidget } from \"./components/media-library-widget\";\nexport { MediaPicker } from \"./components/media-picker\";\nexport { MediaPickerMulti } from \"./components/media-picker-multi\";\nexport { bfmlRootProps, resolveThemeMode } from \"./utils/bfml-theme\";\nexport type { MediaLibraryThemeMode } from \"./theme\";\nexport {\n defaultMediaLibraryConfig,\n defaultMediaCapabilities,\n type MediaCapabilities,\n type MediaFile,\n type MediaFolder,\n type MediaLibraryConfig,\n type MediaLibraryModalProps,\n type MediaLibraryPanelProps,\n type MediaLibraryWidgetProps,\n type MediaListing,\n type MediaPickerMultiProps,\n type MediaPickerProps\n} from \"./types\";\n","import type { MediaLibraryThemeMode } from \"./theme\";\n\nexport type MediaFile = {\n name: string;\n path: string;\n url: string;\n size: number;\n mimeType: string;\n updatedAt: string;\n};\n\nexport type MediaFolder = {\n name: string;\n path: string;\n};\n\nexport type MediaCapabilities = {\n view: boolean;\n upload: boolean;\n createFolder: boolean;\n delete: boolean;\n rename: boolean;\n select: boolean;\n};\n\nexport const defaultMediaCapabilities: MediaCapabilities = {\n view: true,\n upload: true,\n createFolder: true,\n delete: true,\n rename: true,\n select: true\n};\n\nexport type MediaListing = {\n path: string;\n folders: MediaFolder[];\n files: MediaFile[];\n capabilities?: MediaCapabilities;\n};\n\n/**\n * Configure API endpoints for your backend.\n * See README.md for the required request/response contract.\n */\nexport type MediaLibraryConfig = {\n listUrl: string;\n uploadUrl: string;\n createFolderUrl: string;\n updateUrl: string;\n deleteUrl: string;\n rootLabel?: string;\n /** `sync` inherits host CSS variables (default). Use `light` or `dark` for standalone theming. */\n theme?: MediaLibraryThemeMode;\n};\n\nexport const defaultMediaLibraryConfig: MediaLibraryConfig = {\n listUrl: \"/api/media\",\n uploadUrl: \"/api/media/upload\",\n createFolderUrl: \"/api/media/folders\",\n updateUrl: \"/api/media\",\n deleteUrl: \"/api/media\",\n rootLabel: \"Root\"\n};\n\nexport type MediaLibraryPanelProps = {\n /** When false, the panel does not load or render. */\n active?: boolean;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n title?: string;\n description?: string;\n accept?: Array<\"image\" | \"pdf\">;\n variant?: \"modal\" | \"embedded\";\n /** Show selection footer with Done button (picker flow). */\n selectable?: boolean;\n /** Close modal after selecting a file. Default true. */\n closeOnSelect?: boolean;\n /** `multi` allows selecting several files before confirming. Default `single`. */\n selectionMode?: \"single\" | \"multi\";\n /** Max files that can be added in one modal session (multi mode). */\n maxSelections?: number;\n /** After upload completes, add uploaded files and close (multi picker). */\n autoSelectUploads?: boolean;\n onClose?: () => void;\n onSelect?: (file: MediaFile) => void;\n onSelectMany?: (files: MediaFile[]) => void;\n className?: string;\n};\n\nexport type MediaLibraryWidgetProps = {\n /** CSS width, e.g. `\"100%\"`, `800`, or `\"70vw\"`. Default `\"100%\"`. */\n width?: string | number;\n /** CSS height, e.g. `640`, `\"600px\"`, or `\"70vh\"`. Default `640`. */\n height?: string | number;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n title?: string;\n description?: string;\n accept?: Array<\"image\" | \"pdf\">;\n selectable?: boolean;\n onSelect?: (file: MediaFile) => void;\n className?: string;\n};\n\nexport type MediaLibraryModalProps = {\n open: boolean;\n onClose: () => void;\n onSelect?: (file: MediaFile) => void;\n onSelectMany?: (files: MediaFile[]) => void;\n closeOnSelect?: boolean;\n selectionMode?: \"single\" | \"multi\";\n maxSelections?: number;\n autoSelectUploads?: boolean;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n title?: string;\n description?: string;\n accept?: Array<\"image\" | \"pdf\">;\n};\n\nexport type MediaPickerProps = {\n name: string;\n label?: string;\n title?: string;\n description?: string;\n /** @deprecated Preview is shown inline in the picker button. */\n previewTitle?: string;\n /** @deprecated Preview is shown inline in the picker button. */\n previewDescription?: string;\n value?: string;\n defaultValue?: string;\n onChange?: (path: string) => void;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n accept?: Array<\"image\" | \"pdf\">;\n className?: string;\n};\n\nexport type MediaPickerMultiProps = {\n name: string;\n label?: string;\n title?: string;\n description?: string;\n max?: number;\n values?: string[];\n defaultValues?: string[];\n onChange?: (paths: string[]) => void;\n config?: Partial<MediaLibraryConfig>;\n theme?: MediaLibraryThemeMode;\n accept?: Array<\"image\" | \"pdf\">;\n className?: string;\n};\n","import type { MediaFile, MediaLibraryConfig, MediaListing } from \"./types\";\nimport { defaultMediaLibraryConfig } from \"./types\";\n\ntype ApiPayload<T> = { success: boolean; data?: T; error?: { message?: string } };\n\nfunction resolveConfig(config?: Partial<MediaLibraryConfig>): MediaLibraryConfig {\n return { ...defaultMediaLibraryConfig, ...config };\n}\n\nasync function parseResponse<T>(response: Response): Promise<T> {\n const payload = (await response.json()) as ApiPayload<T>;\n if (!payload.success) throw new Error(payload.error?.message ?? \"Media request failed.\");\n return payload.data as T;\n}\n\nexport function createMediaLibraryClient(config?: Partial<MediaLibraryConfig>) {\n const urls = resolveConfig(config);\n\n return {\n async list(path = \"\", q = \"\") {\n const params = new URLSearchParams();\n if (path) params.set(\"path\", path);\n if (q) params.set(\"q\", q);\n const response = await fetch(`${urls.listUrl}?${params.toString()}`);\n return parseResponse<MediaListing>(response);\n },\n\n async createFolder(path: string, name: string, nested = true) {\n const response = await fetch(urls.createFolderUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ path, name, nested })\n });\n return parseResponse<{ name: string; path: string }>(response);\n },\n\n async upload(path: string, files: File[]) {\n const form = new FormData();\n form.set(\"path\", path);\n files.forEach((file) => form.append(\"files\", file));\n const response = await fetch(urls.uploadUrl, { method: \"POST\", body: form });\n return parseResponse<MediaFile[]>(response);\n },\n\n async uploadOne(path: string, file: File) {\n const uploaded = await this.upload(path, [file]);\n return uploaded[0];\n },\n\n async rename(path: string, newName: string, type: \"file\" | \"folder\") {\n const response = await fetch(urls.updateUrl, {\n method: \"PATCH\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ path, newName, type })\n });\n return parseResponse<MediaFile | { name: string; path: string }>(response);\n },\n\n async remove(path: string, type: \"file\" | \"folder\") {\n const response = await fetch(urls.deleteUrl, {\n method: \"DELETE\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ path, type })\n });\n return parseResponse<{ path: string }>(response);\n }\n };\n}\n\nexport const MAX_MEDIA_UPLOAD_BYTES = 5 * 1024 * 1024;\n\nexport function isFileWithinUploadSizeLimit(file: File, maxBytes = MAX_MEDIA_UPLOAD_BYTES) {\n return file.size <= maxBytes;\n}\n\nexport function formatUploadSizeLimit(maxBytes = MAX_MEDIA_UPLOAD_BYTES) {\n return `${Math.round(maxBytes / (1024 * 1024))} MB`;\n}\n\nexport function fileMatchesAccept(file: MediaFile, accept?: Array<\"image\" | \"pdf\">) {\n if (!accept || accept.length === 0) return true;\n const isImage = file.mimeType.startsWith(\"image/\");\n const isPdf = file.mimeType === \"application/pdf\";\n if (accept.includes(\"image\") && isImage) return true;\n if (accept.includes(\"pdf\") && isPdf) return true;\n return false;\n}\n\nexport function fileMatchesAcceptForUpload(file: File, accept?: Array<\"image\" | \"pdf\">) {\n if (!accept || accept.length === 0) return true;\n const isImage = file.type.startsWith(\"image/\");\n const isPdf = file.type === \"application/pdf\";\n if (accept.includes(\"image\") && isImage) return true;\n if (accept.includes(\"pdf\") && isPdf) return true;\n return false;\n}\n\nexport function fileNameFromPath(path: string) {\n return path.split(\"/\").pop() ?? path;\n}\n\nexport function isImagePath(path: string) {\n return /\\.(png|jpe?g|webp|gif)$/i.test(path);\n}\n","import { createPortal } from \"react-dom\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { defaultMediaLibraryConfig } from \"../types\";\nimport type { MediaLibraryModalProps } from \"../types\";\nimport { MediaLibraryPanel } from \"./media-library-panel\";\nimport { fileNameFromPath } from \"../client\";\n\nexport function MediaLibraryModal({\n open,\n onClose,\n onSelect,\n onSelectMany,\n closeOnSelect = true,\n selectionMode = \"single\",\n maxSelections,\n autoSelectUploads = false,\n config,\n theme,\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose media.\",\n accept\n}: MediaLibraryModalProps) {\n const resolved = { ...defaultMediaLibraryConfig, ...config };\n const themeMode = resolveThemeMode(theme ?? resolved.theme);\n const rootProps = bfmlRootProps(themeMode);\n\n if (!open || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div {...rootProps}>\n <div\n className=\"fixed inset-0 z-[10050] flex items-stretch justify-center p-0 backdrop-blur-sm sm:items-center sm:p-2 md:p-4\"\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n >\n <MediaLibraryPanel\n active={open}\n variant=\"modal\"\n selectable\n config={config}\n theme={theme}\n title={title}\n description={description}\n accept={accept}\n onClose={onClose}\n onSelect={onSelect}\n onSelectMany={onSelectMany}\n closeOnSelect={closeOnSelect}\n selectionMode={selectionMode}\n maxSelections={maxSelections}\n autoSelectUploads={autoSelectUploads}\n />\n </div>\n </div>,\n document.body\n );\n}\n\nexport function MediaPreview({ path, alt }: { path: string; alt?: string }) {\n const isImage = /\\.(png|jpe?g|webp|gif)$/i.test(path);\n if (!path) {\n return (\n <div className=\"flex h-32 items-center justify-center rounded-xl border border-dashed border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] px-4 text-center text-sm text-[var(--bfml-muted-foreground)] sm:h-40\">\n No media selected\n </div>\n );\n }\n\n if (isImage) {\n return (\n <div className=\"overflow-hidden rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)]\">\n <img src={path} alt={alt ?? fileNameFromPath(path)} className=\"h-32 w-full object-contain sm:h-40\" />\n </div>\n );\n }\n\n return (\n <div className=\"flex h-32 items-center justify-center rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] px-4 text-center text-sm font-medium text-[var(--bfml-foreground)] sm:h-40\">\n {fileNameFromPath(path)}\n </div>\n );\n}\n","export type MediaLibraryThemeMode = \"sync\" | \"light\" | \"dark\";\n\nexport function bfmlRootProps(theme: MediaLibraryThemeMode = \"sync\") {\n return {\n className: \"bfml-root\",\n ...(theme !== \"sync\" ? ({ \"data-theme\": theme } as const) : {})\n };\n}\n\nexport function resolveThemeMode(theme?: MediaLibraryThemeMode) {\n return theme ?? \"sync\";\n}\n","import { useEffect, useMemo, useRef, useState, type DragEvent, type MouseEvent } from \"react\";\nimport { ChevronRight, Folder, ImagePlus, LoaderCircle, PanelLeft, Search, Trash2, Upload, X } from \"lucide-react\";\nimport { Button } from \"./ui/button\";\nimport { ConfirmDialog } from \"./ui/confirm-dialog\";\nimport { Input } from \"./ui/input\";\nimport { ToastContainer } from \"./ui/toast-container\";\nimport { UploadPreviewCard, type UploadQueueItem } from \"./upload-preview\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport {\n buildBreadcrumb,\n createQueueId,\n isPathInside,\n parentPath,\n type DeleteTarget\n} from \"../utils/media-library-utils\";\nimport { toastError, toastSuccess, toastWarning } from \"../utils/toast-store\";\nimport {\n createMediaLibraryClient,\n fileMatchesAccept,\n fileMatchesAcceptForUpload,\n formatUploadSizeLimit,\n isFileWithinUploadSizeLimit\n} from \"../client\";\nimport type { MediaCapabilities, MediaFile, MediaFolder, MediaLibraryPanelProps } from \"../types\";\nimport { defaultMediaCapabilities, defaultMediaLibraryConfig } from \"../types\";\n\nexport function MediaLibraryPanel({\n active = true,\n config,\n theme,\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose media.\",\n accept,\n variant = \"embedded\",\n selectable = false,\n closeOnSelect = true,\n selectionMode = \"single\",\n maxSelections,\n autoSelectUploads = false,\n onClose,\n onSelect,\n onSelectMany,\n className\n}: MediaLibraryPanelProps) {\n const client = useMemo(() => createMediaLibraryClient(config), [config]);\n const resolved = useMemo(() => ({ ...defaultMediaLibraryConfig, ...config }), [config]);\n const themeMode = resolveThemeMode(theme ?? resolved.theme);\n const rootProps = bfmlRootProps(themeMode);\n const uploadInputRef = useRef<HTMLInputElement>(null);\n const dragCounterRef = useRef(0);\n\n const [currentPath, setCurrentPath] = useState(\"\");\n const [search, setSearch] = useState(\"\");\n const [folderName, setFolderName] = useState(\"\");\n const [nestedFolder, setNestedFolder] = useState(true);\n const [loading, setLoading] = useState(false);\n const [uploading, setUploading] = useState(false);\n const [dragActive, setDragActive] = useState(false);\n const [capabilities, setCapabilities] = useState<MediaCapabilities>(defaultMediaCapabilities);\n const [uploadQueue, setUploadQueue] = useState<UploadQueueItem[]>([]);\n const [folders, setFolders] = useState<Array<{ name: string; path: string }>>([]);\n const [files, setFiles] = useState<MediaFile[]>([]);\n const [selected, setSelected] = useState<MediaFile | null>(null);\n const [selectedFiles, setSelectedFiles] = useState<MediaFile[]>([]);\n const [deleteTarget, setDeleteTarget] = useState<DeleteTarget | null>(null);\n const [deleting, setDeleting] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n async function load(path = currentPath, q = search, options?: { silent?: boolean }) {\n if (!options?.silent) setLoading(true);\n try {\n const listing = await client.list(path, q);\n setCurrentPath(listing.path);\n setFolders(listing.folders);\n setFiles(listing.files.filter((file) => fileMatchesAccept(file, accept)));\n setCapabilities({ ...defaultMediaCapabilities, ...listing.capabilities });\n } catch (caught) {\n toastError(caught instanceof Error ? caught.message : \"Failed to load media.\");\n } finally {\n if (!options?.silent) setLoading(false);\n }\n }\n\n function clearUploadQueue() {\n setUploadQueue((current) => {\n current.forEach((item) => URL.revokeObjectURL(item.previewUrl));\n return [];\n });\n }\n\n useEffect(() => {\n if (!active) return;\n setSelected(null);\n setSelectedFiles([]);\n setDeleteTarget(null);\n setSidebarOpen(false);\n clearUploadQueue();\n setDragActive(false);\n dragCounterRef.current = 0;\n setSearch(\"\");\n void load(\"\", \"\");\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [active]);\n\n useEffect(() => {\n if (!active || variant !== \"modal\" || !onClose) return;\n const handleClose = onClose;\n function onKeyDown(event: KeyboardEvent) {\n if (event.key !== \"Escape\") return;\n if (deleteTarget && !deleting) {\n setDeleteTarget(null);\n return;\n }\n handleClose();\n }\n document.body.style.overflow = \"hidden\";\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.body.style.overflow = \"\";\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [active, deleteTarget, deleting, onClose, variant]);\n\n async function createFolder() {\n if (!capabilities.createFolder) {\n toastError(\"You do not have permission to create folders.\");\n return;\n }\n const name = folderName.trim();\n if (!name) {\n toastError(\"Enter a folder name.\");\n return;\n }\n try {\n await client.createFolder(currentPath, name, nestedFolder);\n setFolderName(\"\");\n await load(currentPath, search);\n toastSuccess(`Folder \"${name}\" created.`);\n } catch (caught) {\n toastError(caught instanceof Error ? caught.message : \"Failed to create folder.\");\n }\n }\n\n async function processFiles(incoming: File[]) {\n if (!capabilities.upload || incoming.length === 0 || uploading) return;\n\n const sizeLimit = formatUploadSizeLimit();\n const accepted: File[] = [];\n let invalidTypeCount = 0;\n\n for (const file of incoming) {\n if (!fileMatchesAcceptForUpload(file, accept)) {\n invalidTypeCount += 1;\n continue;\n }\n if (!isFileWithinUploadSizeLimit(file)) {\n toastWarning(`\"${file.name}\" exceeds ${sizeLimit} and was skipped.`);\n continue;\n }\n accepted.push(file);\n }\n\n if (invalidTypeCount > 0) {\n toastError(`${invalidTypeCount} file(s) were skipped due to type restrictions.`);\n }\n if (accepted.length === 0) return;\n\n const queue: UploadQueueItem[] = accepted.map((file) => ({\n id: createQueueId(),\n file,\n previewUrl: URL.createObjectURL(file),\n status: \"pending\"\n }));\n\n setUploadQueue(queue);\n setUploading(true);\n\n const uploadedFiles: MediaFile[] = [];\n let successCount = 0;\n for (const item of queue) {\n setUploadQueue((current) =>\n current.map((entry) => (entry.id === item.id ? { ...entry, status: \"uploading\" } : entry))\n );\n\n try {\n const uploaded = await client.uploadOne(currentPath, item.file);\n uploadedFiles.push(uploaded);\n successCount += 1;\n URL.revokeObjectURL(item.previewUrl);\n setUploadQueue((current) => current.filter((entry) => entry.id !== item.id));\n await load(currentPath, search, { silent: true });\n } catch (caught) {\n const message = caught instanceof Error ? caught.message : \"Upload failed.\";\n URL.revokeObjectURL(item.previewUrl);\n setUploadQueue((current) => current.filter((entry) => entry.id !== item.id));\n if (/5\\s*mb|too large|file size/i.test(message)) {\n toastWarning(`\"${item.file.name}\" exceeds ${sizeLimit} and was skipped.`);\n } else {\n toastError(`${item.file.name}: ${message}`);\n }\n }\n }\n\n if (successCount > 0) {\n toastSuccess(successCount === 1 ? \"File uploaded successfully.\" : `${successCount} files uploaded successfully.`);\n if (autoSelectUploads && onSelectMany && uploadedFiles.length > 0) {\n const limit = maxSelections ?? uploadedFiles.length;\n onSelectMany(uploadedFiles.slice(0, limit));\n onClose?.();\n }\n }\n\n setUploading(false);\n if (uploadInputRef.current) uploadInputRef.current.value = \"\";\n }\n\n async function uploadFiles(fileList: FileList | null) {\n if (!fileList?.length) return;\n await processFiles(Array.from(fileList));\n }\n\n function handleDragEnter(event: DragEvent) {\n event.preventDefault();\n if (!capabilities.upload) return;\n dragCounterRef.current += 1;\n setDragActive(true);\n }\n\n function handleDragLeave(event: DragEvent) {\n event.preventDefault();\n dragCounterRef.current -= 1;\n if (dragCounterRef.current <= 0) {\n dragCounterRef.current = 0;\n setDragActive(false);\n }\n }\n\n function handleDragOver(event: DragEvent) {\n event.preventDefault();\n }\n\n function handleDrop(event: DragEvent) {\n event.preventDefault();\n dragCounterRef.current = 0;\n setDragActive(false);\n if (!capabilities.upload) return;\n void processFiles(Array.from(event.dataTransfer.files ?? []));\n }\n\n async function confirmDelete() {\n if (!deleteTarget) return;\n setDeleting(true);\n try {\n await client.remove(deleteTarget.path, deleteTarget.type);\n if (deleteTarget.type === \"file\" && selected?.path === deleteTarget.path) {\n setSelected(null);\n }\n const reloadPath =\n deleteTarget.type === \"folder\" && isPathInside(currentPath, deleteTarget.path)\n ? parentPath(deleteTarget.path)\n : currentPath;\n const deletedName = deleteTarget.name;\n const deletedType = deleteTarget.type;\n setDeleteTarget(null);\n await load(reloadPath, search);\n toastSuccess(deletedType === \"folder\" ? `Folder \"${deletedName}\" deleted.` : `File \"${deletedName}\" deleted.`);\n } catch (caught) {\n toastError(caught instanceof Error ? caught.message : \"Delete failed.\");\n } finally {\n setDeleting(false);\n }\n }\n\n function requestDelete(target: DeleteTarget, event?: MouseEvent) {\n if (!capabilities.delete) {\n toastError(\"You do not have permission to delete media.\");\n return;\n }\n event?.preventDefault();\n event?.stopPropagation();\n setDeleteTarget(target);\n }\n\n function navigateTo(path: string) {\n void load(path, search);\n setSidebarOpen(false);\n }\n\n function toggleFileSelection(file: MediaFile) {\n setSelectedFiles((current) => {\n const exists = current.some((item) => item.path === file.path);\n if (exists) {\n return current.filter((item) => item.path !== file.path);\n }\n const limit = maxSelections ?? Number.POSITIVE_INFINITY;\n if (current.length >= limit) {\n toastWarning(`You can add up to ${limit} file${limit === 1 ? \"\" : \"s\"} at a time.`);\n return current;\n }\n return [...current, file];\n });\n setSelected(file);\n }\n\n function confirmSelection() {\n if (selectionMode === \"multi\" && onSelectMany) {\n if (selectedFiles.length === 0) return;\n onSelectMany(selectedFiles);\n onClose?.();\n return;\n }\n if (!selected) return;\n onSelect?.(selected);\n if (closeOnSelect) onClose?.();\n else setSelected(null);\n }\n\n function handleFileClick(file: MediaFile) {\n if (selectionMode === \"multi\" && onSelectMany) {\n toggleFileSelection(file);\n return;\n }\n setSelected(file);\n if (!selectable && onSelect) {\n onSelect(file);\n }\n }\n\n function handleFileDoubleClick(file: MediaFile) {\n if (selectionMode === \"multi\" && onSelectMany) {\n onSelectMany([file]);\n onClose?.();\n return;\n }\n setSelected(file);\n if (selectable) {\n onSelect?.(file);\n if (closeOnSelect) onClose?.();\n else setSelected(null);\n } else if (onSelect) {\n onSelect(file);\n }\n }\n\n if (!active) return null;\n\n const crumbs = buildBreadcrumb(currentPath, resolved.rootLabel ?? \"Root\");\n const sidebarFolders = [{ name: resolved.rootLabel ?? \"Root\", path: \"\" }, ...folders];\n const showFooter = selectable;\n const isMultiSelect = selectionMode === \"multi\" && Boolean(onSelectMany);\n const footerSelectionCount = isMultiSelect ? selectedFiles.length : selected ? 1 : 0;\n const footerCanConfirm = isMultiSelect ? selectedFiles.length > 0 : Boolean(selected);\n const showCloseButton = variant === \"modal\" && Boolean(onClose);\n\n const sidebarFolderList = (\n <div className=\"mt-4 space-y-1 lg:mt-5\">\n {sidebarFolders.map((folder) => {\n const folderActive = folder.path === currentPath;\n const canDelete = Boolean(folder.path) && capabilities.delete;\n return (\n <div\n key={folder.path || \"root\"}\n className={cn(\n \"flex items-center gap-1 rounded-lg transition\",\n folderActive ? \"bg-[var(--bfml-primary)]\" : \"hover:bg-[var(--bfml-surface)]\"\n )}\n >\n <button\n type=\"button\"\n onClick={() => navigateTo(folder.path)}\n className={cn(\n \"flex min-w-0 flex-1 items-center gap-2 px-3 py-2.5 text-left text-sm font-medium transition\",\n folderActive ? \"text-[var(--bfml-primary-foreground)]\" : \"text-[var(--bfml-foreground)]\"\n )}\n >\n <Folder className=\"h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{folder.name}</span>\n </button>\n {canDelete ? (\n <button\n type=\"button\"\n title=\"Delete folder\"\n className={cn(\n \"mr-1 rounded-md p-1.5 transition\",\n folderActive\n ? \"text-[var(--bfml-primary-foreground)] hover:bg-[var(--bfml-primary-foreground)]/15\"\n : \"text-[var(--bfml-destructive)] hover:bg-[var(--bfml-destructive-soft)]\"\n )}\n onClick={(event) => requestDelete({ path: folder.path, name: folder.name, type: \"folder\" }, event)}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n\n return (\n <div {...rootProps} className=\"h-full min-h-0\">\n <section\n className={cn(\n \"relative flex h-full min-h-0 flex-col overflow-hidden bg-[var(--bfml-surface)]\",\n variant === \"modal\" &&\n \"h-[100dvh] w-full max-w-none border-0 shadow-[var(--bfml-shadow-lg)] sm:h-[min(92vh,760px)] sm:max-w-6xl sm:rounded-2xl sm:border sm:border-[var(--bfml-border)]\",\n variant === \"embedded\" && \"rounded-none border-0 shadow-none\",\n className\n )}\n >\n <header className=\"flex shrink-0 items-start justify-between gap-3 border-b border-[var(--bfml-border)] px-4 py-3 sm:gap-4 sm:px-6 sm:py-5\">\n <div className=\"min-w-0 pr-2\">\n <h2 className=\"truncate text-base font-semibold text-[var(--bfml-foreground)] sm:text-lg\">{title}</h2>\n {description ? (\n <p className=\"mt-1 hidden text-sm text-[var(--bfml-muted-foreground)] sm:block\">{description}</p>\n ) : null}\n </div>\n {showCloseButton ? (\n <Button type=\"button\" variant=\"ghost\" className=\"h-10 w-10 shrink-0 px-0\" onClick={onClose} aria-label=\"Close media library\">\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </Button>\n ) : null}\n </header>\n\n <ToastContainer theme={themeMode} />\n\n <div className=\"relative flex min-h-0 flex-1 flex-col overflow-hidden lg:grid lg:h-full lg:min-h-0 lg:grid-cols-[minmax(0,240px)_1fr] lg:grid-rows-1\">\n {sidebarOpen ? (\n <button\n type=\"button\"\n className=\"absolute inset-0 z-20 lg:hidden\"\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n aria-label=\"Close folders panel\"\n onClick={() => setSidebarOpen(false)}\n />\n ) : null}\n\n <aside\n className={cn(\n \"absolute inset-y-0 left-0 z-30 flex w-[min(88vw,280px)] flex-col overflow-y-auto border-r border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] p-4 shadow-xl transition-transform duration-200 ease-out lg:static lg:z-auto lg:h-full lg:min-h-0 lg:w-auto lg:translate-x-0 lg:shadow-none\",\n sidebarOpen ? \"translate-x-0\" : \"-translate-x-full lg:translate-x-0\"\n )}\n >\n <div className=\"mb-3 flex items-center justify-between lg:hidden\">\n <p className=\"text-sm font-semibold text-[var(--bfml-foreground)]\">Folders</p>\n <Button type=\"button\" variant=\"ghost\" className=\"h-9 w-9 px-0\" onClick={() => setSidebarOpen(false)} aria-label=\"Close folders panel\">\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n\n {capabilities.createFolder ? (\n <div className=\"space-y-3\">\n <div className=\"flex flex-col gap-2 sm:flex-row\">\n <Input\n value={folderName}\n onChange={(event) => setFolderName(event.target.value)}\n placeholder=\"new-folder\"\n className=\"min-w-0\"\n />\n <Button type=\"button\" variant=\"secondary\" className=\"shrink-0 sm:px-4\" onClick={createFolder}>\n Add\n </Button>\n </div>\n <label className=\"flex items-start gap-2 text-xs leading-5 text-[var(--bfml-muted-foreground)]\">\n <input\n type=\"checkbox\"\n className=\"mt-0.5\"\n checked={nestedFolder}\n onChange={(event) => setNestedFolder(event.target.checked)}\n />\n <span>Create as nested folder of current path</span>\n </label>\n </div>\n ) : null}\n\n {sidebarFolderList}\n </aside>\n\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden p-3 sm:p-5 lg:h-full lg:min-h-0\">\n <div className=\"flex flex-wrap items-center gap-2 sm:gap-3\">\n <Button\n type=\"button\"\n variant=\"secondary\"\n className=\"shrink-0 lg:hidden\"\n onClick={() => setSidebarOpen(true)}\n aria-label=\"Open folders panel\"\n >\n <PanelLeft className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Folders</span>\n </Button>\n\n <div className=\"relative min-w-0 flex-1 basis-[180px]\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[var(--bfml-muted-foreground)]\" />\n <Input\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") void load(currentPath, search);\n }}\n placeholder=\"Search files\"\n />\n </div>\n\n <input\n ref={uploadInputRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n accept={accept?.includes(\"pdf\") ? \"image/*,application/pdf\" : \"image/*\"}\n onChange={(event) => void uploadFiles(event.target.files)}\n />\n {capabilities.upload ? (\n <Button\n type=\"button\"\n disabled={uploading}\n className=\"w-full shrink-0 sm:w-auto\"\n onClick={() => uploadInputRef.current?.click()}\n aria-label=\"Upload files\"\n >\n {uploading ? <LoaderCircle className=\"h-4 w-4 animate-spin\" /> : <Upload className=\"h-4 w-4\" />}\n <span className=\"sm:inline\">Upload</span>\n </Button>\n ) : null}\n </div>\n\n <div className=\"-mx-1 mt-3 flex items-center gap-1 overflow-x-auto px-1 pb-1 text-sm sm:mt-4\">\n {crumbs.map((crumb, index) => (\n <div key={crumb.path} className=\"flex shrink-0 items-center gap-1\">\n <button\n type=\"button\"\n className={cn(\n \"max-w-[9rem] truncate rounded px-1.5 py-1 font-medium transition sm:max-w-none\",\n index === crumbs.length - 1\n ? \"text-[var(--bfml-primary)]\"\n : \"text-[var(--bfml-muted-foreground)] hover:text-[var(--bfml-foreground)]\"\n )}\n onClick={() => navigateTo(crumb.path)}\n >\n {crumb.label}\n </button>\n {index < crumbs.length - 1 ? (\n <ChevronRight className=\"h-4 w-4 shrink-0 text-[var(--bfml-muted-foreground)]\" />\n ) : null}\n </div>\n ))}\n </div>\n\n <div\n className={cn(\n \"relative mt-3 min-h-0 flex-1 overflow-y-auto sm:mt-4\",\n dragActive && capabilities.upload && \"rounded-xl ring-2 ring-[var(--bfml-primary)] ring-offset-2 ring-offset-[var(--bfml-surface)]\"\n )}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n {dragActive && capabilities.upload ? (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center rounded-xl border-2 border-dashed border-[var(--bfml-primary)] bg-[var(--bfml-primary-soft)]/80 px-4 text-center\">\n <div>\n <Upload className=\"mx-auto mb-2 h-8 w-8 text-[var(--bfml-primary)]\" />\n <p className=\"text-sm font-semibold text-[var(--bfml-foreground)]\">Drop files to upload</p>\n <p className=\"mt-1 text-xs text-[var(--bfml-muted-foreground)]\">Files upload one by one</p>\n </div>\n </div>\n ) : null}\n\n {loading && uploadQueue.length === 0 ? (\n <div className=\"flex h-32 items-center justify-center text-sm text-[var(--bfml-muted-foreground)] sm:h-40\">\n <LoaderCircle className=\"mr-2 h-4 w-4 animate-spin\" />\n Loading media...\n </div>\n ) : (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4 lg:grid-cols-3 xl:grid-cols-4\">\n {uploadQueue.map((item) => (\n <UploadPreviewCard key={item.id} item={item} />\n ))}\n\n {folders.map((folder: MediaFolder) => (\n <div\n key={folder.path}\n className=\"group relative rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] transition hover:border-[var(--bfml-primary-border)]\"\n >\n <button\n type=\"button\"\n onDoubleClick={() => navigateTo(folder.path)}\n onClick={() => navigateTo(folder.path)}\n className=\"block w-full p-3 text-left sm:p-4\"\n >\n <Folder className=\"h-7 w-7 text-[var(--bfml-primary)] sm:h-8 sm:w-8\" />\n <p className=\"mt-2 truncate text-sm font-medium text-[var(--bfml-foreground)] sm:mt-3\">{folder.name}</p>\n <p className=\"text-xs text-[var(--bfml-muted-foreground)]\">Folder</p>\n </button>\n {capabilities.delete ? (\n <button\n type=\"button\"\n title=\"Delete folder\"\n className=\"absolute right-1.5 top-1.5 rounded-md border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-1.5 shadow-sm transition hover:bg-[var(--bfml-destructive-soft)] sm:right-2 sm:top-2\"\n onClick={(event) =>\n requestDelete({ path: folder.path, name: folder.name, type: \"folder\" }, event)\n }\n >\n <Trash2 className=\"h-3.5 w-3.5 text-[var(--bfml-destructive)] sm:h-4 sm:w-4\" />\n </button>\n ) : null}\n </div>\n ))}\n\n {files.map((file) => {\n const fileActive = isMultiSelect\n ? selectedFiles.some((item) => item.path === file.path)\n : selected?.path === file.path;\n const isImage = file.mimeType.startsWith(\"image/\");\n return (\n <div\n key={file.path}\n className={cn(\n \"group relative overflow-hidden rounded-xl border bg-[var(--bfml-surface)] transition\",\n fileActive && selectable\n ? \"border-[var(--bfml-primary)] ring-2 ring-[var(--bfml-primary-soft)]\"\n : \"border-[var(--bfml-border)] hover:border-[var(--bfml-primary-border)]\"\n )}\n >\n <button\n type=\"button\"\n className=\"block w-full p-2 text-left sm:p-3\"\n onClick={() => handleFileClick(file)}\n onDoubleClick={() => handleFileDoubleClick(file)}\n >\n <div className=\"flex h-20 items-center justify-center overflow-hidden rounded-lg bg-[var(--bfml-surface-soft)] sm:h-28\">\n {isImage ? (\n <img src={file.url} alt={file.name} className=\"h-full w-full object-contain\" />\n ) : (\n <div className=\"text-xs font-semibold uppercase text-[var(--bfml-muted-foreground)]\">PDF</div>\n )}\n </div>\n <p className=\"mt-2 truncate text-sm font-medium text-[var(--bfml-foreground)] sm:mt-3\">{file.name}</p>\n <p className=\"text-xs text-[var(--bfml-muted-foreground)]\">File</p>\n </button>\n {capabilities.delete ? (\n <button\n type=\"button\"\n title=\"Delete file\"\n className=\"absolute right-1.5 top-1.5 rounded-md border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-1.5 shadow-sm transition hover:bg-[var(--bfml-destructive-soft)] sm:right-2 sm:top-2\"\n onClick={(event) => requestDelete({ path: file.path, name: file.name, type: \"file\" }, event)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-[var(--bfml-destructive)] sm:h-4 sm:w-4\" />\n </button>\n ) : null}\n </div>\n );\n })}\n </div>\n )}\n\n {!loading && folders.length === 0 && files.length === 0 && uploadQueue.length === 0 ? (\n <div className=\"flex h-32 flex-col items-center justify-center rounded-xl border border-dashed border-[var(--bfml-border)] px-4 text-center text-sm text-[var(--bfml-muted-foreground)] sm:h-40\">\n <ImagePlus className=\"mb-2 h-6 w-6\" />\n No files in this folder yet.\n {capabilities.upload ? <p className=\"mt-2 text-xs\">Drag and drop files here or use Upload.</p> : null}\n </div>\n ) : null}\n </div>\n </div>\n </div>\n\n {showFooter ? (\n <footer className=\"flex shrink-0 flex-col-reverse gap-2 border-t border-[var(--bfml-border)] px-4 py-3 sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:px-6 sm:py-4\">\n <p className=\"truncate text-center text-sm text-[var(--bfml-muted-foreground)] sm:text-left\">\n {isMultiSelect\n ? footerSelectionCount === 0\n ? \"Select one or more files\"\n : `${footerSelectionCount} file${footerSelectionCount === 1 ? \"\" : \"s\"} selected`\n : `Selected: ${selected ? selected.name : \"None\"}`}\n </p>\n <Button type=\"button\" className=\"w-full sm:w-auto\" disabled={!footerCanConfirm} onClick={confirmSelection}>\n {isMultiSelect\n ? footerSelectionCount > 0\n ? `Add ${footerSelectionCount} file${footerSelectionCount === 1 ? \"\" : \"s\"}`\n : \"Add files\"\n : closeOnSelect\n ? \"Done\"\n : \"Add\"}\n </Button>\n </footer>\n ) : null}\n\n <ConfirmDialog\n open={Boolean(deleteTarget)}\n title={deleteTarget?.type === \"folder\" ? \"Delete folder?\" : \"Delete file?\"}\n description={\n deleteTarget\n ? deleteTarget.type === \"folder\"\n ? `Are you sure you want to delete the folder \"${deleteTarget.name}\" and everything inside it? This action cannot be undone.`\n : `Are you sure you want to delete \"${deleteTarget.name}\"? This action cannot be undone.`\n : \"\"\n }\n confirmLabel=\"Delete\"\n loading={deleting}\n onCancel={() => {\n if (!deleting) setDeleteTarget(null);\n }}\n onConfirm={() => void confirmDelete()}\n theme={themeMode}\n />\n </section>\n </div>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\ntype ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n variant?: \"primary\" | \"secondary\" | \"danger\" | \"ghost\";\n};\n\nconst variants = {\n primary: \"bg-[var(--bfml-primary)] text-[var(--bfml-primary-foreground)] shadow-[var(--bfml-shadow)] hover:brightness-95\",\n secondary:\n \"border border-[var(--bfml-border)] bg-[var(--bfml-surface)] text-[var(--bfml-foreground)] shadow-[var(--bfml-shadow)] hover:bg-[var(--bfml-surface-soft)]\",\n danger: \"bg-[var(--bfml-destructive)] text-[var(--bfml-primary-foreground)] hover:brightness-95\",\n ghost: \"bg-transparent text-[var(--bfml-muted-foreground)] hover:bg-[var(--bfml-surface-soft)] hover:text-[var(--bfml-foreground)]\"\n};\n\nexport function Button({ className, variant = \"primary\", disabled, children, ...props }: ButtonProps) {\n return (\n <button\n className={cn(\n \"inline-flex h-10 items-center justify-center gap-2 rounded-lg px-4 text-sm font-semibold transition disabled:pointer-events-none disabled:opacity-50\",\n variants[variant],\n className\n )}\n disabled={disabled}\n {...props}\n >\n {children}\n </button>\n );\n}\n","import { createPortal } from \"react-dom\";\nimport type { MediaLibraryThemeMode } from \"../../theme\";\nimport { bfmlRootProps } from \"../../utils/bfml-theme\";\nimport { Button } from \"./button\";\n\ntype ConfirmDialogProps = {\n open: boolean;\n title: string;\n description: string;\n confirmLabel?: string;\n cancelLabel?: string;\n loading?: boolean;\n theme?: MediaLibraryThemeMode;\n onCancel: () => void;\n onConfirm: () => void;\n};\n\nexport function ConfirmDialog({\n open,\n title,\n description,\n confirmLabel = \"Delete\",\n cancelLabel = \"Cancel\",\n loading = false,\n theme = \"sync\",\n onCancel,\n onConfirm\n}: ConfirmDialogProps) {\n if (!open || typeof document === \"undefined\") return null;\n\n const rootProps = bfmlRootProps(theme);\n\n return createPortal(\n <div {...rootProps}>\n <div\n className=\"fixed inset-0 z-[10060] flex items-end justify-center p-0 backdrop-blur-sm sm:items-center sm:p-4\"\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n role=\"presentation\"\n onClick={onCancel}\n >\n <section\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"bfml-confirm-title\"\n aria-describedby=\"bfml-confirm-description\"\n className=\"w-full max-w-md rounded-t-2xl border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-4 shadow-[var(--bfml-shadow-lg)] sm:rounded-2xl sm:p-6\"\n onClick={(event) => event.stopPropagation()}\n >\n <h3 id=\"bfml-confirm-title\" className=\"text-lg font-semibold text-[var(--bfml-foreground)]\">\n {title}\n </h3>\n <p id=\"bfml-confirm-description\" className=\"mt-2 text-sm text-[var(--bfml-muted-foreground)]\">\n {description}\n </p>\n <div className=\"mt-5 flex flex-col-reverse gap-2 sm:mt-6 sm:flex-row sm:justify-end\">\n <Button type=\"button\" variant=\"secondary\" disabled={loading} className=\"w-full sm:w-auto\" onClick={onCancel}>\n {cancelLabel}\n </Button>\n <Button type=\"button\" variant=\"danger\" disabled={loading} className=\"w-full sm:w-auto\" onClick={onConfirm}>\n {loading ? \"Deleting...\" : confirmLabel}\n </Button>\n </div>\n </section>\n </div>\n </div>,\n document.body\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(function Input(\n { className, ...props },\n ref\n) {\n return (\n <input\n ref={ref}\n className={cn(\n \"h-11 w-full rounded-lg border border-[var(--bfml-border)] bg-[var(--bfml-surface)] px-4 text-sm text-[var(--bfml-foreground)] shadow-[var(--bfml-shadow)] outline-none transition placeholder:text-[var(--bfml-muted-foreground)] focus:border-[var(--bfml-primary-border)] focus:ring-4 focus:ring-[var(--bfml-primary-soft)]\",\n className\n )}\n {...props}\n />\n );\n});\n","import { useEffect, useState } from \"react\";\nimport { CheckCircle2, TriangleAlert, X, XCircle } from \"lucide-react\";\nimport type { MediaLibraryThemeMode } from \"../../theme\";\nimport { dismissToast, subscribeToasts, type ToastItem } from \"../../utils/toast-store\";\nimport { cn } from \"../../utils/cn\";\n\nfunction ToastCard({ toast }: { toast: ToastItem }) {\n const isSuccess = toast.type === \"success\";\n const isWarning = toast.type === \"warning\";\n\n return (\n <div\n role=\"status\"\n className={cn(\n \"pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-xl border px-4 py-3 shadow-[var(--bfml-shadow-lg)] transition\",\n isSuccess\n ? \"border-[var(--bfml-success)]/30 bg-[var(--bfml-success-soft)] text-[var(--bfml-success-foreground)]\"\n : isWarning\n ? \"border-[var(--bfml-warning)]/30 bg-[var(--bfml-warning-soft)] text-[var(--bfml-warning-foreground)]\"\n : \"border-[var(--bfml-destructive)]/30 bg-[var(--bfml-destructive-soft)] text-[var(--bfml-foreground)]\"\n )}\n >\n {isSuccess ? (\n <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-[var(--bfml-success)]\" aria-hidden=\"true\" />\n ) : isWarning ? (\n <TriangleAlert className=\"mt-0.5 h-4 w-4 shrink-0 text-[var(--bfml-warning)]\" aria-hidden=\"true\" />\n ) : (\n <XCircle className=\"mt-0.5 h-4 w-4 shrink-0 text-[var(--bfml-destructive)]\" aria-hidden=\"true\" />\n )}\n <p className=\"min-w-0 flex-1 text-sm font-medium leading-5\">{toast.message}</p>\n <button\n type=\"button\"\n className=\"rounded-md p-0.5 opacity-70 transition hover:opacity-100\"\n aria-label=\"Dismiss notification\"\n onClick={() => dismissToast(toast.id)}\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n );\n}\n\nexport function ToastContainer({ theme = \"sync\" }: { theme?: MediaLibraryThemeMode }) {\n const [items, setItems] = useState<ToastItem[]>([]);\n void theme;\n\n useEffect(() => {\n return subscribeToasts(setItems);\n }, []);\n\n if (items.length === 0) return null;\n\n return (\n <div className=\"pointer-events-none absolute right-3 top-3 z-[45] flex w-[min(100%,20rem)] flex-col items-end gap-2 sm:right-4 sm:top-4\">\n {items.map((toast) => (\n <ToastCard key={toast.id} toast={toast} />\n ))}\n </div>\n );\n}\n","export type ToastType = \"success\" | \"error\" | \"warning\";\n\nexport type ToastItem = {\n id: string;\n type: ToastType;\n message: string;\n};\n\ntype ToastListener = (toasts: ToastItem[]) => void;\n\nconst listeners = new Set<ToastListener>();\nlet toasts: ToastItem[] = [];\n\nfunction emit() {\n listeners.forEach((listener) => listener([...toasts]));\n}\n\nfunction createId() {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nexport function dismissToast(id: string) {\n toasts = toasts.filter((toast) => toast.id !== id);\n emit();\n}\n\nexport function showToast(type: ToastType, message: string, durationMs = 3500) {\n const id = createId();\n toasts = [...toasts, { id, type, message }];\n emit();\n window.setTimeout(() => dismissToast(id), durationMs);\n}\n\nexport function subscribeToasts(listener: ToastListener) {\n listeners.add(listener);\n listener([...toasts]);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function toastSuccess(message: string) {\n showToast(\"success\", message);\n}\n\nexport function toastError(message: string) {\n showToast(\"error\", message);\n}\n\nexport function toastWarning(message: string) {\n showToast(\"warning\", message);\n}\n","import { CheckCircle2, LoaderCircle, XCircle } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\n\nexport type UploadQueueItem = {\n id: string;\n file: File;\n previewUrl: string;\n status: \"pending\" | \"uploading\" | \"done\" | \"error\";\n error?: string;\n};\n\nexport function UploadPreviewCard({ item }: { item: UploadQueueItem }) {\n const isImage = item.file.type.startsWith(\"image/\");\n\n return (\n <div\n className={cn(\n \"relative overflow-hidden rounded-xl border bg-[var(--bfml-surface)] p-2 sm:p-3\",\n item.status === \"done\"\n ? \"border-[var(--bfml-success)]/40\"\n : item.status === \"error\"\n ? \"border-[var(--bfml-destructive)]/40\"\n : \"border-[var(--bfml-border)]\"\n )}\n >\n <div className=\"relative flex h-20 items-center justify-center overflow-hidden rounded-lg bg-[var(--bfml-surface-soft)] sm:h-28\">\n {isImage ? (\n <img src={item.previewUrl} alt={item.file.name} className=\"h-full w-full object-contain opacity-80\" />\n ) : (\n <div className=\"text-xs font-semibold uppercase text-[var(--bfml-muted-foreground)]\">PDF</div>\n )}\n\n {item.status === \"pending\" || item.status === \"uploading\" ? (\n <div\n className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 px-2 text-[var(--bfml-primary-foreground)]\"\n style={{ backgroundColor: \"var(--bfml-overlay)\" }}\n >\n <LoaderCircle className=\"h-6 w-6 animate-spin\" />\n <span className=\"text-xs font-medium\">{item.status === \"uploading\" ? \"Uploading...\" : \"Waiting...\"}</span>\n </div>\n ) : null}\n\n {item.status === \"done\" ? (\n <div\n className=\"absolute inset-0 flex items-center justify-center\"\n style={{ backgroundColor: \"color-mix(in srgb, var(--bfml-success) 25%, transparent)\" }}\n >\n <CheckCircle2 className=\"h-8 w-8 text-[var(--bfml-success)]\" />\n </div>\n ) : null}\n\n {item.status === \"error\" ? (\n <div\n className=\"absolute inset-0 flex items-center justify-center\"\n style={{ backgroundColor: \"color-mix(in srgb, var(--bfml-destructive) 25%, transparent)\" }}\n >\n <XCircle className=\"h-8 w-8 text-[var(--bfml-destructive)]\" />\n </div>\n ) : null}\n </div>\n\n <p className=\"mt-2 truncate text-sm font-medium text-[var(--bfml-foreground)]\">{item.file.name}</p>\n <p className=\"truncate text-xs text-[var(--bfml-muted-foreground)]\">\n {item.status === \"error\" ? item.error ?? \"Upload failed\" : item.status === \"done\" ? \"Uploaded\" : \"In queue\"}\n </p>\n </div>\n );\n}\n","export type DeleteTarget = {\n path: string;\n name: string;\n type: \"file\" | \"folder\";\n};\n\nexport function parentPath(path: string) {\n const segments = path.split(\"/\").filter(Boolean);\n segments.pop();\n return segments.join(\"/\");\n}\n\nexport function isPathInside(path: string, folderPath: string) {\n return path === folderPath || path.startsWith(`${folderPath}/`);\n}\n\nexport function buildBreadcrumb(path: string, rootLabel: string) {\n const segments = path ? path.split(\"/\").filter(Boolean) : [];\n const crumbs = [{ label: rootLabel, path: \"\" }];\n segments.forEach((segment, index) => {\n crumbs.push({ label: segment, path: segments.slice(0, index + 1).join(\"/\") });\n });\n return crumbs;\n}\n\nexport function createQueueId() {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nexport function toCssSize(value?: string | number) {\n if (value === undefined) return undefined;\n if (typeof value === \"number\") return `${value}px`;\n\n const trimmed = value.trim();\n if (/^calc\\s*\\(/i.test(trimmed) || /^var\\s*\\(/i.test(trimmed)) return trimmed;\n\n // e.g. \"100vh-200px\" or \"100vh - 200px\" → calc(100vh - 200px)\n if (/^[\\d.]+\\s*(vh|vw|vmin|vmax|%|px|rem|em)\\s*[-+]\\s*[\\d.]+/i.test(trimmed)) {\n const normalized = trimmed.replace(/\\s*([+-])\\s*/g, \" $1 \");\n return `calc(${normalized})`;\n }\n\n return trimmed;\n}\n","import { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { toCssSize } from \"../utils/media-library-utils\";\nimport { defaultMediaLibraryConfig } from \"../types\";\nimport type { MediaLibraryWidgetProps } from \"../types\";\nimport { MediaLibraryPanel } from \"./media-library-panel\";\n\nexport function MediaLibraryWidget({\n width = \"100%\",\n height = 640,\n config,\n theme,\n title = \"Media Library\",\n description = \"Create folders, upload files, and manage media.\",\n accept,\n selectable = false,\n onSelect,\n className\n}: MediaLibraryWidgetProps) {\n const resolved = { ...defaultMediaLibraryConfig, ...config };\n const themeMode = resolveThemeMode(theme ?? resolved.theme);\n const rootProps = bfmlRootProps(themeMode);\n\n return (\n <div {...rootProps}>\n <div\n className={cn(\n \"overflow-hidden rounded-2xl border border-[var(--bfml-border)] bg-[var(--bfml-surface)] shadow-[var(--bfml-shadow-lg)]\",\n className\n )}\n style={{\n width: toCssSize(width),\n height: toCssSize(height)\n }}\n >\n <MediaLibraryPanel\n active\n variant=\"embedded\"\n config={config}\n theme={theme}\n title={title}\n description={description}\n accept={accept}\n selectable={selectable}\n onSelect={onSelect}\n className=\"h-full\"\n />\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { Upload } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { fileNameFromPath } from \"../client\";\nimport { MediaLibraryModal } from \"./media-library-modal\";\nimport { PickerThumbnail } from \"./picker-thumbnail\";\nimport type { MediaPickerProps } from \"../types\";\n\nexport function MediaPicker({\n name,\n label = \"Choose image\",\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose media.\",\n value,\n defaultValue = \"\",\n onChange,\n config,\n theme,\n accept = [\"image\"],\n className\n}: MediaPickerProps) {\n const themeMode = resolveThemeMode(theme ?? config?.theme);\n const rootProps = bfmlRootProps(themeMode);\n const [open, setOpen] = useState(false);\n const [selectedPath, setSelectedPath] = useState(value ?? defaultValue);\n\n useEffect(() => {\n if (value !== undefined) setSelectedPath(value);\n }, [value]);\n\n function handleSelect(file: { url: string }) {\n setSelectedPath(file.url);\n onChange?.(file.url);\n setOpen(false);\n }\n\n const currentValue = value ?? selectedPath;\n const fileName = currentValue ? fileNameFromPath(currentValue) : null;\n\n return (\n <div {...rootProps}>\n <div className={cn(\"space-y-2\", className)}>\n {label ? <label className=\"text-sm font-medium text-[var(--bfml-foreground)]\">{label}</label> : null}\n\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"flex w-full items-center gap-3 rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)] px-3 py-3 text-left transition hover:border-[var(--bfml-primary-border)] hover:bg-[var(--bfml-surface)] sm:gap-4 sm:px-4 sm:py-4\"\n >\n <PickerThumbnail path={currentValue} alt={fileName ?? label} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-semibold text-[var(--bfml-foreground)]\">{label}</span>\n <span className=\"mt-0.5 block truncate text-xs text-[var(--bfml-muted-foreground)]\">\n {fileName ?? \"Select from folders or upload new\"}\n </span>\n </span>\n <Upload className=\"hidden h-5 w-5 shrink-0 text-[var(--bfml-muted-foreground)] sm:block\" aria-hidden=\"true\" />\n </button>\n\n <input type=\"hidden\" name={name} value={currentValue} />\n\n <MediaLibraryModal\n open={open}\n onClose={() => setOpen(false)}\n onSelect={handleSelect}\n config={config}\n theme={themeMode}\n title={title}\n description={description}\n accept={accept}\n />\n </div>\n </div>\n );\n}\n","import { FileText, ImagePlus } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { isImagePath } from \"../client\";\n\ntype PickerThumbnailProps = {\n path?: string;\n alt?: string;\n size?: \"sm\" | \"md\" | \"grid\";\n shape?: \"circle\" | \"square\";\n className?: string;\n};\n\nconst sizeClasses = {\n sm: \"h-9 w-9\",\n md: \"h-10 w-10 sm:h-12 sm:w-12\",\n grid: \"h-full w-full\"\n};\n\nexport function PickerThumbnail({\n path,\n alt,\n size = \"md\",\n shape = \"circle\",\n className\n}: PickerThumbnailProps) {\n const isImage = Boolean(path && isImagePath(path));\n const rounded = shape === \"circle\" ? \"rounded-full\" : \"rounded-lg\";\n\n return (\n <span\n className={cn(\n \"flex shrink-0 items-center justify-center overflow-hidden border border-[var(--bfml-border)] bg-[var(--bfml-surface)]\",\n size !== \"grid\" && sizeClasses[size],\n rounded,\n !path && \"text-[var(--bfml-primary)]\",\n className\n )}\n >\n {!path ? (\n <ImagePlus className={size === \"sm\" ? \"h-4 w-4\" : \"h-5 w-5\"} aria-hidden=\"true\" />\n ) : isImage ? (\n <img src={path} alt={alt ?? \"Selected media\"} className=\"h-full w-full object-cover\" />\n ) : (\n <FileText className={size === \"sm\" ? \"h-4 w-4\" : \"h-5 w-5\"} aria-hidden=\"true\" />\n )}\n </span>\n );\n}\n\nexport function PickerThumbnailStack({ paths }: { paths: string[] }) {\n if (paths.length === 0) {\n return (\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[var(--bfml-surface)] text-[var(--bfml-primary)] sm:h-12 sm:w-12\">\n <ImagePlus className=\"h-5 w-5\" aria-hidden=\"true\" />\n </span>\n );\n }\n\n if (paths.length === 1) {\n return <PickerThumbnail path={paths[0]} alt=\"Selected media\" />;\n }\n\n const visible = paths.slice(0, 3);\n\n return (\n <span className=\"relative flex h-10 w-10 shrink-0 items-center sm:h-12 sm:w-12\">\n {visible.map((path, index) => (\n <span\n key={`${path}-${index}`}\n className={cn(\n \"absolute overflow-hidden rounded-full border-2 border-[var(--bfml-surface-soft)] bg-[var(--bfml-surface)]\",\n index === 0 && \"left-0 top-0 z-30 h-7 w-7 sm:h-8 sm:w-8\",\n index === 1 && \"left-3 top-1 z-20 h-7 w-7 sm:left-4 sm:h-8 sm:w-8\",\n index === 2 && \"left-1 top-3 z-10 h-7 w-7 sm:top-4 sm:h-8 sm:w-8\"\n )}\n >\n <PickerThumbnail path={path} size=\"grid\" shape=\"circle\" className=\"h-full w-full border-0\" />\n </span>\n ))}\n {paths.length > 3 ? (\n <span className=\"absolute -bottom-0.5 -right-0.5 z-40 rounded-full bg-[var(--bfml-primary)] px-1.5 py-0.5 text-[10px] font-semibold leading-none text-[var(--bfml-primary-foreground)]\">\n +{paths.length - 3}\n </span>\n ) : null}\n </span>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { Upload, X } from \"lucide-react\";\nimport { cn } from \"../utils/cn\";\nimport { bfmlRootProps, resolveThemeMode } from \"../utils/bfml-theme\";\nimport { fileNameFromPath, isImagePath } from \"../client\";\nimport { MediaLibraryModal } from \"./media-library-modal\";\nimport { PickerThumbnailStack } from \"./picker-thumbnail\";\nimport type { MediaFile } from \"../types\";\nimport type { MediaPickerMultiProps } from \"../types\";\n\nexport function MediaPickerMulti({\n name,\n label = \"Choose attachments\",\n title = \"Media Library\",\n description = \"Create folders, upload files, and choose one or more attachments.\",\n max = 10,\n values,\n defaultValues = [],\n onChange,\n config,\n theme,\n accept = [\"image\", \"pdf\"],\n className\n}: MediaPickerMultiProps) {\n const themeMode = resolveThemeMode(theme ?? config?.theme);\n const rootProps = bfmlRootProps(themeMode);\n const [open, setOpen] = useState(false);\n const [selectedPaths, setSelectedPaths] = useState<string[]>(values ?? defaultValues);\n\n useEffect(() => {\n if (values !== undefined) setSelectedPaths(values);\n }, [values]);\n\n const currentValues = values ?? selectedPaths;\n const atMax = currentValues.length >= max;\n\n function handleSelectMany(files: MediaFile[]) {\n setSelectedPaths((current) => {\n const next = [...current];\n for (const file of files) {\n if (next.includes(file.url) || next.length >= max) continue;\n next.push(file.url);\n }\n onChange?.(next);\n return next;\n });\n setOpen(false);\n }\n\n function removeAt(index: number) {\n setSelectedPaths((current) => {\n const next = current.filter((_, itemIndex) => itemIndex !== index);\n onChange?.(next);\n return next;\n });\n }\n\n return (\n <div {...rootProps}>\n <div className={cn(\"space-y-2\", className)}>\n {label ? <label className=\"text-sm font-medium text-[var(--bfml-foreground)]\">{label}</label> : null}\n\n <div className=\"overflow-hidden rounded-xl border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)]\">\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n disabled={atMax}\n className=\"flex w-full items-center gap-3 px-3 py-3 text-left transition hover:bg-[var(--bfml-surface)] disabled:cursor-not-allowed disabled:opacity-60 sm:gap-4 sm:px-4 sm:py-4\"\n >\n <PickerThumbnailStack paths={currentValues} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-semibold text-[var(--bfml-foreground)]\">{label}</span>\n <span className=\"mt-0.5 block text-xs text-[var(--bfml-muted-foreground)]\">\n {currentValues.length > 0\n ? `${currentValues.length} selected · click to add more (${currentValues.length}/${max})`\n : `Select from folders or upload new (0/${max})`}\n </span>\n </span>\n <Upload className=\"hidden h-5 w-5 shrink-0 text-[var(--bfml-muted-foreground)] sm:block\" aria-hidden=\"true\" />\n </button>\n\n {currentValues.length > 0 ? (\n <div className=\"grid grid-cols-3 gap-2 border-t border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-3 sm:grid-cols-4 sm:p-4\">\n {currentValues.map((path, index) => {\n const fileName = fileNameFromPath(path);\n const isImage = isImagePath(path);\n return (\n <div\n key={`${path}-${index}`}\n className=\"group relative aspect-square overflow-hidden rounded-lg border border-[var(--bfml-border)] bg-[var(--bfml-surface-soft)]\"\n >\n {isImage ? (\n <img src={path} alt={fileName} className=\"h-full w-full object-cover\" />\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-1 px-1 text-center text-[var(--bfml-muted-foreground)]\">\n <span className=\"text-[10px] font-semibold uppercase\">PDF</span>\n </div>\n )}\n <button\n type=\"button\"\n className=\"absolute right-1 top-1 rounded-md border border-[var(--bfml-border)] bg-[var(--bfml-surface)] p-1 shadow-sm transition hover:bg-[var(--bfml-destructive-soft)]\"\n onClick={() => removeAt(index)}\n title=\"Remove attachment\"\n >\n <X className=\"h-3 w-3 text-[var(--bfml-destructive)]\" />\n </button>\n <div className=\"absolute inset-x-0 bottom-0 bg-[var(--bfml-overlay)] px-1.5 py-1\">\n <p className=\"truncate text-[10px] font-medium text-[var(--bfml-primary-foreground)]\">{fileName}</p>\n </div>\n </div>\n );\n })}\n </div>\n ) : null}\n </div>\n\n {currentValues.map((path, index) => (\n <input key={`${path}-${index}`} type=\"hidden\" name={`${name}[${index}]`} value={path} />\n ))}\n\n <MediaLibraryModal\n open={open}\n onClose={() => setOpen(false)}\n onSelectMany={handleSelectMany}\n selectionMode=\"multi\"\n maxSelections={Math.max(0, max - currentValues.length)}\n autoSelectUploads\n config={config}\n theme={themeMode}\n title={title}\n description={description}\n accept={accept}\n />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_react_dom","import_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","Input","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_lucide_react","import_jsx_runtime"]}
|