@caprionlinesrl/puck-plugin-media 0.1.4

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/createMediaPlugin.tsx","../src/components/ImageField/ImageField.tsx","../src/components/ImagePickerModal/ImagePickerModal.tsx","../src/components/Modal/Modal.tsx","../src/components/Modal/Modal.module.css","../src/components/SearchBar/SearchBar.tsx","../src/components/SearchBar/SearchBar.module.css","../src/components/LoadMoreButton/LoadMoreButton.tsx","../src/components/LoadMoreButton/LoadMoreButton.module.css","../src/components/ConfirmDialog/ConfirmDialog.tsx","../src/components/ConfirmDialog/ConfirmDialog.module.css","../src/components/SelectionToolbar/SelectionToolbar.tsx","../src/components/SelectionToolbar/SelectionToolbar.module.css","../src/components/ImageGrid/ImageGrid.tsx","../src/components/ImageGrid/ImageGrid.module.css","../src/components/UploadDropzone/UploadDropzone.tsx","../src/hooks/useUpload.ts","../src/components/UploadDropzone/UploadDropzone.module.css","../src/components/UploadQueue/UploadQueue.tsx","../src/components/UploadQueue/UploadQueue.module.css","../src/components/ImagePickerModal/ImagePickerModal.module.css","../src/components/ImageField/ImageField.module.css","../src/components/GalleryField/GalleryField.tsx","../src/components/GalleryPickerModal/GalleryPickerModal.tsx","../src/components/GalleryPickerModal/GalleryPickerModal.module.css","../src/components/GalleryField/GalleryField.module.css","../src/components/DocumentField/DocumentField.tsx","../src/components/DocumentPickerModal/DocumentPickerModal.tsx","../src/components/DocumentPickerModal/DocumentPickerModal.module.css","../src/components/DocumentField/DocumentField.module.css","../src/components/MediaPanel/MediaPanel.tsx","../src/components/MediaPanel/MediaPanel.module.css","../src/types.ts"],"sourcesContent":["export { createMediaPlugin } from './createMediaPlugin';\n\nexport type {\n Language,\n LocalizedString,\n ImageItem,\n ImageOptions,\n GalleryItem,\n GalleryOptions,\n DocumentItem,\n DocumentOptions,\n MediaPluginOptions,\n FetchListParams,\n FetchListResult,\n FetchListFn,\n UploadFn,\n UploadConfig,\n UploadCallbacks,\n UploadingFile,\n UploadStatus,\n} from './types';\n\nexport { DEFAULT_LANGUAGES } from './types';\n\nexport { ImageField } from './components/ImageField/ImageField';\nexport { ImagePickerModal } from './components/ImagePickerModal/ImagePickerModal';\nexport { ImageGrid } from './components/ImageGrid/ImageGrid';\nexport { GalleryField } from './components/GalleryField/GalleryField';\nexport { GalleryPickerModal } from './components/GalleryPickerModal/GalleryPickerModal';\nexport { DocumentField } from './components/DocumentField/DocumentField';\nexport { DocumentPickerModal } from './components/DocumentPickerModal/DocumentPickerModal';\nexport { MediaPanel } from './components/MediaPanel/MediaPanel';\nexport { UploadDropzone } from './components/UploadDropzone/UploadDropzone';\nexport { UploadQueue } from './components/UploadQueue/UploadQueue';\n\nexport { useUpload, formatFileSize } from './hooks/useUpload';\n","import { Image } from 'lucide-react';\nimport { ImageField } from './components/ImageField/ImageField';\nimport { GalleryField } from './components/GalleryField/GalleryField';\nimport { DocumentField } from './components/DocumentField/DocumentField';\nimport { MediaPanel } from './components/MediaPanel/MediaPanel';\nimport type {\n MediaPluginOptions,\n PuckPlugin,\n ImageFieldProps,\n GalleryFieldProps,\n DocumentFieldProps,\n} from './types';\n\n/**\n * Create a Puck plugin for media library integration\n *\n * @example\n * ```tsx\n * import { createMediaPlugin } from '@onda-suite/puck-plugin-media';\n *\n * const mediaPlugin = createMediaPlugin({\n * // Optional: configure languages for alt/title fields\n * languages: [\n * { code: 'it', label: 'Italiano' },\n * { code: 'en', label: 'English' },\n * ],\n *\n * // Image configuration (required)\n * image: {\n * fetchList: async ({ query, page, pageSize }) => {\n * const res = await fetch(`/api/images?q=${query}&page=${page}`);\n * return res.json();\n * },\n * upload: async (file, { onProgress }) => {\n * // Upload with progress tracking...\n * return uploadedImageItem;\n * },\n * update: async (id, { alt }) => {\n * // Update alt text\n * return updatedImageItem;\n * },\n * delete: async (id) => {\n * // Delete image (enables \"Select Items\" mode)\n * },\n * uploadConfig: {\n * accept: 'image/*',\n * maxSize: 10 * 1024 * 1024, // 10MB\n * multiple: true,\n * },\n * },\n *\n * // Gallery configuration (optional)\n * gallery: {\n * fetchList: async ({ query, page }) => { ... },\n * fetch: async (id) => { ... },\n * create: async (name) => { ... },\n * delete: async (id) => { ... },\n * upload: async (galleryId, file, { onProgress }) => { ... },\n * removeImage: async (galleryId, imageId) => { ... },\n * updateImage: async (galleryId, imageId, { alt }) => { ... },\n * },\n *\n * // Document configuration (optional)\n * document: {\n * fetchList: async ({ query, page }) => { ... },\n * upload: async (file, { onProgress }) => { ... },\n * update: async (id, { title }) => { ... },\n * delete: async (id) => {\n * // Delete document (enables \"Select Items\" mode)\n * },\n * uploadConfig: {\n * accept: '.pdf,.doc,.docx,.xls,.xlsx',\n * maxSize: 20 * 1024 * 1024, // 20MB\n * multiple: true,\n * },\n * },\n * });\n *\n * <Puck config={config} plugins={[mediaPlugin]} />\n * ```\n */\nexport function createMediaPlugin(options: MediaPluginOptions): PuckPlugin {\n const {\n languages = [\n { code: 'en', label: 'English' },\n { code: 'it', label: 'Italiano' },\n ],\n image,\n gallery,\n document,\n } = options;\n\n const fieldTypes: Record<string, (props: unknown) => React.ReactNode> = {\n // Image field type (always available)\n image: (props: unknown) => {\n const fieldProps = props as ImageFieldProps;\n return (\n <ImageField\n {...fieldProps}\n languages={languages}\n imageOptions={image}\n />\n );\n },\n };\n\n // Gallery field type (only if gallery options provided)\n if (gallery) {\n fieldTypes.gallery = (props: unknown) => {\n const fieldProps = props as GalleryFieldProps;\n return (\n <GalleryField\n {...fieldProps}\n languages={languages}\n galleryOptions={gallery}\n />\n );\n };\n }\n\n // Document field type (only if document options provided)\n if (document) {\n fieldTypes.document = (props: unknown) => {\n const fieldProps = props as DocumentFieldProps;\n return (\n <DocumentField\n {...fieldProps}\n languages={languages}\n documentOptions={document}\n />\n );\n };\n }\n\n return {\n name: 'puck-media',\n label: 'Media',\n icon: <Image size={20} />,\n render: () => (\n <MediaPanel\n languages={languages}\n imageOptions={image}\n galleryOptions={gallery}\n documentOptions={document}\n />\n ),\n overrides: {\n fieldTypes,\n },\n };\n}\n","import { useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { FieldLabel } from '@puckeditor/core';\nimport { ImagePlus, X } from 'lucide-react';\nimport { ImagePickerModal } from '../ImagePickerModal/ImagePickerModal';\nimport type { ImageFieldProps, ImageItem } from '../../types';\nimport styles from './ImageField.module.css';\n\nexport function ImageField({\n value,\n onChange,\n field,\n languages,\n imageOptions,\n}: ImageFieldProps) {\n const [isModalOpen, setIsModalOpen] = useState(false);\n\n const handleSelect = (item: ImageItem) => {\n onChange(item);\n setIsModalOpen(false);\n };\n\n const handleRemove = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange(null);\n };\n\n const handleOpenModal = () => {\n setIsModalOpen(true);\n };\n\n const getAltDisplay = (): string => {\n if (!value?.alt) return '';\n for (const lang of languages) {\n if (value.alt[lang.code]) {\n return value.alt[lang.code] as string;\n }\n }\n return '';\n };\n\n return (\n <FieldLabel label={field.label || 'Image'}>\n <div className={styles.container}>\n {value ? (\n <div className={styles.preview}>\n <img\n src={value.url}\n alt={getAltDisplay()}\n className={styles.image}\n />\n <div className={styles.overlay}>\n <button\n type=\"button\"\n onClick={handleOpenModal}\n className={styles.changeButton}\n >\n Change\n </button>\n <button\n type=\"button\"\n onClick={handleRemove}\n className={styles.removeButton}\n aria-label=\"Remove image\"\n >\n <X size={16} />\n </button>\n </div>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={handleOpenModal}\n className={styles.selectButton}\n >\n <ImagePlus size={24} />\n <span>Select image</span>\n </button>\n )}\n </div>\n\n {isModalOpen && createPortal(\n <ImagePickerModal\n languages={languages}\n imageOptions={imageOptions}\n title=\"Select Image\"\n selectedImage={value}\n onSelect={handleSelect}\n onClose={() => setIsModalOpen(false)}\n />,\n document.body\n )}\n </FieldLabel>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { ArrowLeft, Loader2 } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { SearchBar } from '../SearchBar';\nimport { LoadMoreButton } from '../LoadMoreButton';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { SelectionToolbar } from '../SelectionToolbar';\nimport { ImageGrid } from '../ImageGrid/ImageGrid';\nimport { UploadDropzone } from '../UploadDropzone/UploadDropzone';\nimport { UploadQueue } from '../UploadQueue/UploadQueue';\nimport { useUpload } from '../../hooks/useUpload';\nimport type { ImagePickerModalProps, ImageItem, LocalizedString } from '../../types';\nimport styles from './ImagePickerModal.module.css';\n\nconst DEFAULT_UPLOAD_CONFIG = {\n accept: 'image/*',\n maxSize: 10 * 1024 * 1024,\n multiple: true,\n};\n\nconst PAGE_SIZE = 20;\n\ntype ModalView = 'picker' | 'edit';\n\nexport function ImagePickerModal({\n languages,\n imageOptions,\n title = 'Select Image',\n selectedImage,\n onSelect,\n onClose,\n selectable = true,\n}: ImagePickerModalProps) {\n const { fetchList, upload, update, delete: deleteImage, uploadConfig } = imageOptions;\n\n const [view, setView] = useState<ModalView>('picker');\n const [editingItem, setEditingItem] = useState<ImageItem | null>(null);\n const [selectMode, setSelectMode] = useState(false);\n const [selectedForDelete, setSelectedForDelete] = useState<Set<string>>(new Set());\n const [items, setItems] = useState<ImageItem[]>([]);\n const [search, setSearch] = useState('');\n const [loading, setLoading] = useState(true);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [selectedItem, setSelectedItem] = useState<ImageItem | null>(null);\n const [altValues, setAltValues] = useState<LocalizedString>({});\n const [activeLang, setActiveLang] = useState(languages[0]?.code || 'it');\n const [isSaving, setIsSaving] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n\n const canUpload = !!upload;\n const {\n uploading,\n isUploading,\n addFiles,\n cancelUpload,\n clearCompleted,\n uploadConfig: mergedUploadConfig,\n } = useUpload({\n upload: upload || (async () => { throw new Error('Upload not configured'); }),\n config: uploadConfig || DEFAULT_UPLOAD_CONFIG,\n onUploadComplete: (newItem) => {\n setItems((prev) => [newItem as ImageItem, ...prev]);\n },\n });\n\n const loadItems = useCallback(\n async (searchQuery: string, pageNum: number, append = false) => {\n setLoading(true);\n try {\n const result = await fetchList({\n query: searchQuery || undefined,\n page: pageNum,\n pageSize: PAGE_SIZE,\n });\n\n const newItems = Array.isArray(result) ? result : result.items;\n const more = Array.isArray(result) ? newItems.length === PAGE_SIZE : (result.hasMore ?? false);\n\n setItems((prev) => (append ? [...prev, ...newItems] : newItems));\n setHasMore(more);\n } catch (error) {\n console.error('Failed to fetch images:', error);\n setItems([]);\n setHasMore(false);\n } finally {\n setLoading(false);\n }\n },\n [fetchList]\n );\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setPage(1);\n loadItems(search, 1);\n }, 300);\n return () => clearTimeout(timer);\n }, [search, loadItems]);\n\n useEffect(() => {\n if (selectedImage) {\n const existingItem = items.find((item) => item.id === selectedImage.id);\n if (existingItem) {\n setSelectedItem(existingItem);\n }\n }\n }, [selectedImage, items]);\n\n const handleClose = useCallback(() => {\n onClose();\n }, [onClose]);\n\n const handleLoadMore = () => {\n const nextPage = page + 1;\n setPage(nextPage);\n loadItems(search, nextPage, true);\n };\n\n const handleImageClick = (item: ImageItem) => {\n if (selectedItem?.id === item.id) {\n setSelectedItem(null);\n } else {\n setSelectedItem(item);\n }\n };\n\n const handleConfirmSelection = () => {\n if (!selectedItem || !onSelect) return;\n onSelect(selectedItem);\n };\n\n const handleEditAlt = (item: ImageItem) => {\n setEditingItem(item);\n setAltValues(item.alt || {});\n setActiveLang(languages[0]?.code || 'it');\n setView('edit');\n };\n\n const handleAltChange = (langCode: string, value: string) => {\n setAltValues((prev) => ({\n ...prev,\n [langCode]: value,\n }));\n };\n\n const handleSaveAlt = async () => {\n if (!editingItem || !update) return;\n\n setIsSaving(true);\n try {\n await update(editingItem.id, { alt: altValues });\n setItems((prev) =>\n prev.map((item) =>\n item.id === editingItem.id ? { ...item, alt: altValues } : item\n )\n );\n if (selectedItem?.id === editingItem.id) {\n setSelectedItem((prev) => prev ? { ...prev, alt: altValues } : null);\n }\n setView('picker');\n setEditingItem(null);\n setAltValues({});\n } catch (error) {\n console.error('Failed to update alt text:', error);\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleToggleSelect = (item: ImageItem) => {\n setSelectedForDelete((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(item.id)) {\n newSet.delete(item.id);\n } else {\n newSet.add(item.id);\n }\n return newSet;\n });\n };\n\n const handleSelectAll = () => {\n if (selectedForDelete.size === items.length) {\n setSelectedForDelete(new Set());\n } else {\n setSelectedForDelete(new Set(items.map((item) => item.id)));\n }\n };\n\n const handleConfirmDelete = async () => {\n if (!deleteImage || selectedForDelete.size === 0) return;\n\n setIsDeleting(true);\n try {\n const deletePromises = Array.from(selectedForDelete).map((id) => deleteImage(id));\n await Promise.all(deletePromises);\n setItems((prev) => prev.filter((item) => !selectedForDelete.has(item.id)));\n if (selectedItem && selectedForDelete.has(selectedItem.id)) {\n setSelectedItem(null);\n }\n setShowDeleteConfirm(false);\n setSelectedForDelete(new Set());\n setSelectMode(false);\n } catch (error) {\n console.error('Failed to delete images:', error);\n } finally {\n setIsDeleting(false);\n }\n };\n\n const formatFileSize = (bytes?: number): string => {\n if (!bytes) return '';\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n const isAllSelected = items.length > 0 && selectedForDelete.size === items.length;\n const isSomeSelected = selectedForDelete.size > 0 && selectedForDelete.size < items.length;\n\n // Edit View\n if (view === 'edit' && editingItem) {\n return (\n <Modal\n title=\"Edit Image Details\"\n onClose={handleClose}\n headerLeft={\n <button\n type=\"button\"\n onClick={() => {\n setView('picker');\n setEditingItem(null);\n setAltValues({});\n }}\n className={styles.backButton}\n aria-label=\"Back to grid\"\n >\n <ArrowLeft size={20} />\n </button>\n }\n footer={\n <div className={styles.editFooter}>\n <div />\n <button\n type=\"button\"\n onClick={handleSaveAlt}\n className={styles.saveButton}\n disabled={isSaving || !update}\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className={styles.spinner} />\n Saving...\n </>\n ) : (\n 'Save'\n )}\n </button>\n </div>\n }\n >\n <div className={styles.editContent}>\n <div className={styles.editPreview}>\n <img\n src={editingItem.url}\n alt={editingItem.filename || ''}\n className={styles.editImage}\n />\n </div>\n\n <div className={styles.editInfo}>\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Filename</span>\n <span className={styles.editInfoValue}>{editingItem.filename}</span>\n </div>\n {editingItem.width && editingItem.height && (\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Dimensions</span>\n <span className={styles.editInfoValue}>\n {editingItem.width}×{editingItem.height}\n </span>\n </div>\n )}\n {editingItem.size && (\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Size</span>\n <span className={styles.editInfoValue}>\n {formatFileSize(editingItem.size)}\n </span>\n </div>\n )}\n </div>\n\n <div className={styles.editField}>\n <div className={styles.editFieldHeader}>\n <label className={styles.editFieldLabel}>Alt</label>\n <div className={styles.langTabs}>\n {languages.map((lang) => (\n <button\n key={lang.code}\n type=\"button\"\n onClick={() => setActiveLang(lang.code)}\n className={`${styles.langTab} ${activeLang === lang.code ? styles.langTabActive : ''}`}\n >\n {lang.code.toUpperCase()}\n </button>\n ))}\n </div>\n </div>\n <input\n type=\"text\"\n value={altValues[activeLang] || ''}\n onChange={(e) => handleAltChange(activeLang, e.target.value)}\n placeholder={`Alt text in ${languages.find(l => l.code === activeLang)?.label || activeLang}...`}\n className={styles.editInput}\n />\n </div>\n </div>\n </Modal>\n );\n }\n\n // Picker View\n const renderFooter = () => {\n if (selectMode) {\n return (\n <SelectionToolbar\n selectedCount={selectedForDelete.size}\n totalCount={items.length}\n onSelectAll={handleSelectAll}\n onCancel={() => {\n setSelectMode(false);\n setSelectedForDelete(new Set());\n }}\n onDelete={() => setShowDeleteConfirm(true)}\n isAllSelected={isAllSelected}\n isIndeterminate={isSomeSelected}\n />\n );\n }\n\n if (selectedItem && selectable) {\n return (\n <div className={styles.footer}>\n <div className={styles.footerInfo}>\n <img\n src={selectedItem.thumbnailUrl || selectedItem.url}\n alt=\"\"\n className={styles.footerImage}\n />\n <span className={styles.footerFilename}>\n {selectedItem.filename}\n </span>\n {selectedItem.width && selectedItem.height && (\n <span className={styles.footerMeta}>\n {selectedItem.width}×{selectedItem.height}\n </span>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleConfirmSelection}\n className={styles.selectButton}\n >\n Select Image\n </button>\n </div>\n );\n }\n\n return undefined;\n };\n\n return (\n <Modal\n title={title}\n onClose={handleClose}\n headerActions={\n !selectMode && deleteImage ? (\n <button\n type=\"button\"\n onClick={() => setSelectMode(true)}\n className={styles.selectModeButton}\n >\n Select Items\n </button>\n ) : undefined\n }\n toolbar={\n <div className={styles.toolbar}>\n <SearchBar\n value={search}\n onChange={setSearch}\n placeholder=\"Search images...\"\n autoFocus={!selectMode}\n />\n </div>\n }\n footer={renderFooter()}\n overlay={\n showDeleteConfirm ? (\n <ConfirmDialog\n title=\"Delete Images\"\n message={`Are you sure you want to delete ${selectedForDelete.size} image${selectedForDelete.size > 1 ? 's' : ''}? This action cannot be undone.`}\n confirmLabel={isDeleting ? 'Deleting...' : `Delete ${selectedForDelete.size} image${selectedForDelete.size > 1 ? 's' : ''}`}\n onConfirm={handleConfirmDelete}\n onCancel={() => setShowDeleteConfirm(false)}\n loading={isDeleting}\n variant=\"danger\"\n />\n ) : undefined\n }\n loading={loading && items.length === 0}\n empty={!loading && items.length === 0}\n emptyMessage=\"No images found\"\n >\n {canUpload && !selectMode && (\n <div className={styles.uploadSection}>\n <UploadDropzone\n onFilesSelected={addFiles}\n config={mergedUploadConfig}\n disabled={isUploading && uploading.length >= 10}\n />\n {uploading.length > 0 && (\n <UploadQueue\n files={uploading}\n onCancel={cancelUpload}\n onClearCompleted={clearCompleted}\n />\n )}\n </div>\n )}\n\n <ImageGrid\n items={items}\n onSelect={handleImageClick}\n selectedId={selectedItem?.id}\n onEditAlt={update ? handleEditAlt : undefined}\n manageMode={selectMode}\n selectedIds={selectedForDelete}\n onToggleSelect={handleToggleSelect}\n />\n\n {hasMore && (\n <LoadMoreButton onClick={handleLoadMore} loading={loading} />\n )}\n </Modal>\n );\n}\n","import { useEffect } from 'react';\nimport { X, Loader2 } from 'lucide-react';\nimport styles from './Modal.module.css';\n\nexport interface ModalProps {\n title: string;\n onClose: () => void;\n size?: 'default' | 'small';\n headerLeft?: React.ReactNode;\n headerActions?: React.ReactNode;\n toolbar?: React.ReactNode;\n children: React.ReactNode;\n footer?: React.ReactNode;\n overlay?: React.ReactNode;\n loading?: boolean;\n empty?: boolean;\n emptyMessage?: string;\n}\n\nexport function Modal({\n title,\n onClose,\n size = 'default',\n headerLeft,\n headerActions,\n toolbar,\n children,\n footer,\n overlay,\n loading = false,\n empty = false,\n emptyMessage = 'No items found',\n}: ModalProps) {\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n }\n };\n window.addEventListener('keydown', handleEscape);\n return () => window.removeEventListener('keydown', handleEscape);\n }, [onClose]);\n\n useEffect(() => {\n const originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = originalOverflow;\n };\n }, []);\n\n const handleBackdropClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n return (\n <div className={styles.backdrop} onClick={handleBackdropClick}>\n <div\n className={`${styles.modal} ${size === 'small' ? styles.small : ''}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"modal-title\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className={styles.header}>\n {headerLeft}\n <h2 id=\"modal-title\" className={styles.title}>\n {title}\n </h2>\n <div className={styles.headerActions}>\n {headerActions}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onClose();\n }}\n className={styles.closeButton}\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n </div>\n\n {toolbar && <div className={styles.toolbar}>{toolbar}</div>}\n\n <div className={styles.content}>\n {loading ? (\n <div className={styles.loading}>\n <Loader2 size={32} className={styles.spinner} />\n <span>Loading...</span>\n </div>\n ) : empty ? (\n <div className={styles.empty}>{emptyMessage}</div>\n ) : (\n children\n )}\n </div>\n\n {footer && <div className={styles.footer}>{footer}</div>}\n\n {overlay}\n </div>\n </div>\n );\n}\n",".backdrop {\n position: fixed;\n inset: 0;\n z-index: 9999;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.modal {\n position: relative;\n width: 100%;\n max-width: 900px;\n max-height: calc(100vh - 48px);\n background: white;\n border-radius: 12px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n animation: slideUp 0.2s ease;\n}\n\n.modal.small {\n max-width: 700px;\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(16px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e5e5;\n flex-shrink: 0;\n}\n\n.title {\n flex: 1;\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #171717;\n}\n\n.headerActions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.closeButton {\n padding: 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n\n.closeButton:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n.toolbar {\n padding: 16px 20px;\n border-bottom: 1px solid #e5e5e5;\n flex-shrink: 0;\n}\n\n.content {\n flex: 1;\n overflow-y: scroll;\n padding: 20px;\n min-height: 200px;\n}\n\n.loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n height: 200px;\n color: #737373;\n font-size: 14px;\n}\n\n.spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n.empty {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 200px;\n color: #737373;\n font-size: 14px;\n text-align: center;\n}\n\n.footer {\n flex-shrink: 0;\n padding: 12px 20px;\n border-top: 1px solid #e5e5e5;\n background: #fafafa;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n\n/* Mobile Responsive */\n@media (max-width: 640px) {\n .backdrop {\n padding: 0;\n align-items: flex-end;\n }\n\n .modal {\n width: 100%;\n max-width: 100%;\n max-height: 90vh;\n min-height: 400px;\n border-radius: 12px 12px 0 0;\n }\n\n .header {\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .headerActions {\n flex-wrap: wrap;\n }\n\n .footer {\n flex-direction: column;\n gap: 12px;\n }\n}\n","import { useRef, useEffect } from 'react';\nimport { Search, X } from 'lucide-react';\nimport styles from './SearchBar.module.css';\n\nexport interface SearchBarProps {\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n autoFocus?: boolean;\n}\n\nexport function SearchBar({\n value,\n onChange,\n placeholder = 'Search...',\n autoFocus = false,\n}: SearchBarProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (autoFocus && inputRef.current) {\n inputRef.current.focus();\n }\n }, [autoFocus]);\n\n const handleClear = () => {\n onChange('');\n inputRef.current?.focus();\n };\n\n return (\n <div className={styles.container}>\n <Search size={18} className={styles.icon} />\n <input\n ref={inputRef}\n type=\"search\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder}\n className={styles.input}\n />\n {value && (\n <button\n type=\"button\"\n onClick={handleClear}\n className={styles.clearButton}\n aria-label=\"Clear search\"\n >\n <X size={16} />\n </button>\n )}\n </div>\n );\n}\n",".container {\n position: relative;\n flex: 1;\n}\n\n.icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: #a3a3a3;\n pointer-events: none;\n}\n\n.input {\n width: 100%;\n padding: 10px 40px 10px 44px;\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n font-size: 14px;\n background: #fafafa;\n transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;\n}\n\n.input:focus {\n outline: none;\n border-color: #3b82f6;\n background: white;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.input::placeholder {\n color: #a3a3a3;\n}\n\n.input::-webkit-search-cancel-button {\n display: none;\n}\n\n.clearButton {\n position: absolute;\n right: 12px;\n top: 50%;\n transform: translateY(-50%);\n padding: 4px;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.clearButton:hover {\n background: #e5e5e5;\n color: #171717;\n}\n","import { Loader2 } from 'lucide-react';\nimport styles from './LoadMoreButton.module.css';\n\nexport interface LoadMoreButtonProps {\n onClick: () => void;\n loading?: boolean;\n}\n\nexport function LoadMoreButton({ onClick, loading = false }: LoadMoreButtonProps) {\n return (\n <div className={styles.container}>\n <button\n type=\"button\"\n onClick={onClick}\n disabled={loading}\n className={styles.button}\n >\n {loading ? (\n <>\n <Loader2 size={16} className={styles.spinner} />\n Loading...\n </>\n ) : (\n 'Load more'\n )}\n </button>\n </div>\n );\n}\n",".container {\n display: flex;\n justify-content: center;\n margin-top: 20px;\n}\n\n.button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: #f5f5f5;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: #171717;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.button:hover:not(:disabled) {\n background: #ebebeb;\n border-color: #d4d4d4;\n}\n\n.button:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n","import { useEffect } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport styles from './ConfirmDialog.module.css';\n\nexport interface ConfirmDialogProps {\n title: string;\n message: string;\n confirmLabel: string;\n onConfirm: () => void;\n onCancel: () => void;\n loading?: boolean;\n variant?: 'danger' | 'default';\n}\n\nexport function ConfirmDialog({\n title,\n message,\n confirmLabel,\n onConfirm,\n onCancel,\n loading = false,\n variant = 'danger',\n}: ConfirmDialogProps) {\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && !loading) {\n e.stopPropagation();\n onCancel();\n }\n };\n window.addEventListener('keydown', handleEscape);\n return () => window.removeEventListener('keydown', handleEscape);\n }, [onCancel, loading]);\n\n return (\n <div className={styles.overlay}>\n <div className={styles.dialog}>\n <h3 className={styles.title}>{title}</h3>\n <p className={styles.message}>{message}</p>\n <div className={styles.actions}>\n <button\n type=\"button\"\n onClick={onCancel}\n className={styles.cancelButton}\n disabled={loading}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={`${styles.confirmButton} ${variant === 'danger' ? styles.danger : ''}`}\n disabled={loading}\n >\n {loading ? (\n <>\n <Loader2 size={16} className={styles.spinner} />\n {confirmLabel}\n </>\n ) : (\n confirmLabel\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n",".overlay {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n animation: fadeIn 0.15s ease;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.dialog {\n background: white;\n border-radius: 12px;\n padding: 24px;\n max-width: 400px;\n width: 90%;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n animation: slideUp 0.2s ease;\n}\n\n@keyframes slideUp {\n from { opacity: 0; transform: translateY(16px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.title {\n margin: 0 0 12px 0;\n font-size: 18px;\n font-weight: 600;\n color: #171717;\n}\n\n.message {\n margin: 0 0 20px 0;\n font-size: 14px;\n color: #525252;\n line-height: 1.5;\n}\n\n.actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.cancelButton {\n padding: 10px 16px;\n background: #f5f5f5;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: #171717;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.cancelButton:hover:not(:disabled) {\n background: #ebebeb;\n}\n\n.cancelButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.confirmButton {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 16px;\n background: #3b82f6;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.confirmButton:hover:not(:disabled) {\n background: #2563eb;\n}\n\n.confirmButton.danger {\n background: #dc2626;\n}\n\n.confirmButton.danger:hover:not(:disabled) {\n background: #b91c1c;\n}\n\n.confirmButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Mobile Responsive */\n@media (max-width: 640px) {\n .actions {\n flex-direction: column;\n }\n\n .cancelButton,\n .confirmButton {\n width: 100%;\n justify-content: center;\n }\n}\n","import { Check } from 'lucide-react';\nimport styles from './SelectionToolbar.module.css';\n\nexport interface SelectionToolbarProps {\n selectedCount: number;\n totalCount: number;\n onSelectAll: () => void;\n onCancel: () => void;\n onDelete: () => void;\n isAllSelected: boolean;\n isIndeterminate: boolean;\n deleteLabel?: string;\n}\n\nexport function SelectionToolbar({\n selectedCount,\n totalCount: _totalCount,\n onSelectAll,\n onCancel,\n onDelete,\n isAllSelected,\n isIndeterminate,\n deleteLabel = 'Delete',\n}: SelectionToolbarProps) {\n // totalCount is kept in the interface for future use (e.g., \"X of Y selected\")\n void _totalCount;\n return (\n <div className={styles.toolbar}>\n <button\n type=\"button\"\n onClick={onSelectAll}\n className={`${styles.selectAllButton} ${isAllSelected ? styles.checked : ''} ${isIndeterminate ? styles.indeterminate : ''}`}\n aria-label={isAllSelected ? 'Deselect all' : 'Select all'}\n >\n <div className={styles.checkbox}>\n {isAllSelected && <Check size={14} strokeWidth={3} />}\n {isIndeterminate && !isAllSelected && <div className={styles.indeterminateLine} />}\n </div>\n <span>Select All</span>\n </button>\n\n <div className={styles.actions}>\n <button\n type=\"button\"\n onClick={onCancel}\n className={styles.cancelButton}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={onDelete}\n className={styles.deleteButton}\n disabled={selectedCount === 0}\n >\n {deleteLabel} ({selectedCount})\n </button>\n </div>\n </div>\n );\n}\n",".toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n gap: 16px;\n}\n\n.selectAllButton {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: #525252;\n transition: background 0.15s;\n}\n\n.selectAllButton:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.checkbox {\n width: 20px;\n height: 20px;\n border: 2px solid #d4d4d4;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, border-color 0.15s;\n background: white;\n}\n\n.checked .checkbox {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n}\n\n.indeterminate .checkbox {\n background: #3b82f6;\n border-color: #3b82f6;\n}\n\n.indeterminateLine {\n width: 10px;\n height: 2px;\n background: white;\n border-radius: 1px;\n}\n\n.actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.cancelButton {\n padding: 8px 16px;\n background: transparent;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.cancelButton:hover {\n background: #f5f5f5;\n border-color: #d4d4d4;\n}\n\n.deleteButton {\n padding: 8px 16px;\n background: #dc2626;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s, opacity 0.15s;\n}\n\n.deleteButton:hover:not(:disabled) {\n background: #b91c1c;\n}\n\n.deleteButton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Mobile Responsive */\n@media (max-width: 640px) {\n .toolbar {\n flex-wrap: wrap;\n gap: 12px;\n }\n\n .selectAllButton {\n order: 1;\n }\n\n .actions {\n order: 2;\n width: 100%;\n justify-content: stretch;\n }\n\n .cancelButton,\n .deleteButton {\n flex: 1;\n }\n}\n","import { Pencil, Check } from 'lucide-react';\nimport type { ImageGridProps, ImageItem } from '../../types';\nimport styles from './ImageGrid.module.css';\n\nexport function ImageGrid({\n items,\n onSelect,\n selectedId,\n onEditAlt,\n manageMode = false,\n selectedIds,\n onToggleSelect,\n}: ImageGridProps) {\n const formatFileSize = (bytes?: number): string => {\n if (!bytes) return '';\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n const handleItemClick = (item: ImageItem) => {\n if (manageMode && onToggleSelect) {\n onToggleSelect(item);\n } else {\n onSelect(item);\n }\n };\n\n const handleEditClick = (e: React.MouseEvent, item: ImageItem) => {\n e.stopPropagation();\n onEditAlt?.(item);\n };\n\n const isSelected = (item: ImageItem): boolean => {\n if (manageMode) {\n return selectedIds?.has(item.id) ?? false;\n }\n return selectedId === item.id;\n };\n\n return (\n <div className={styles.grid}>\n {items.map((item) => {\n const selected = isSelected(item);\n const isSelectedForInsert = !manageMode && selectedId === item.id;\n\n return (\n <div key={item.id} className={styles.itemContainer}>\n <button\n type=\"button\"\n onClick={() => handleItemClick(item)}\n className={`${styles.item} ${isSelectedForInsert ? styles.selected : ''}`}\n title={item.filename}\n >\n <div className={styles.imageWrapper}>\n <img\n src={item.thumbnailUrl || item.url}\n alt={item.filename || ''}\n className={styles.image}\n loading=\"lazy\"\n />\n {manageMode && (\n <div className={`${styles.checkbox} ${selected ? styles.checkboxChecked : ''}`}>\n {selected && <Check size={14} strokeWidth={3} />}\n </div>\n )}\n {isSelectedForInsert && (\n <div className={styles.checkmark}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M13.5 4.5L6 12L2.5 8.5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </div>\n )}\n </div>\n </button>\n <div className={styles.info}>\n <div className={styles.infoRow}>\n <div className={styles.infoText}>\n {item.filename && (\n <span className={styles.filename}>{item.filename}</span>\n )}\n <span className={styles.meta}>\n {item.width && item.height && (\n <span>{item.width}×{item.height}</span>\n )}\n {item.size && (\n <span>{formatFileSize(item.size)}</span>\n )}\n </span>\n </div>\n {!manageMode && onEditAlt && (\n <button\n type=\"button\"\n onClick={(e) => handleEditClick(e, item)}\n className={styles.editButton}\n aria-label=\"Edit alt\"\n >\n <Pencil size={14} />\n </button>\n )}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n",".grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));\n gap: 12px;\n}\n\n@media (min-width: 640px) {\n .grid {\n grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n }\n}\n\n.itemContainer {\n display: flex;\n flex-direction: column;\n background: white;\n border: 2px solid #e5e5e5;\n border-radius: 8px;\n overflow: hidden;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.itemContainer:hover {\n border-color: #3b82f6;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n}\n\n.itemContainer:has(.item:focus) {\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);\n}\n\n.itemContainer:has(.selected) {\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);\n}\n\n.item {\n display: block;\n background: transparent;\n border: none;\n cursor: pointer;\n text-align: left;\n padding: 0;\n transition: transform 0.15s;\n}\n\n.item:focus {\n outline: none;\n}\n\n.item:active {\n transform: scale(0.98);\n}\n\n.imageWrapper {\n position: relative;\n aspect-ratio: 1;\n background: #f5f5f5;\n overflow: hidden;\n}\n\n.image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n transition: transform 0.2s;\n}\n\n.itemContainer:hover .image {\n transform: scale(1.05);\n}\n\n/* Checkmark for selection (normal mode) */\n.checkmark {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 24px;\n height: 24px;\n background: #3b82f6;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n}\n\n/* Checkbox for manage mode */\n.checkbox {\n position: absolute;\n top: 8px;\n left: 8px;\n width: 22px;\n height: 22px;\n background: white;\n border: 2px solid #d4d4d4;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n transition: background 0.15s, border-color 0.15s;\n}\n\n.checkbox:hover {\n border-color: #3b82f6;\n}\n\n.checkboxChecked {\n background: #3b82f6;\n border-color: #3b82f6;\n}\n\n.info {\n padding: 8px 10px;\n min-height: 48px;\n}\n\n.infoRow {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 4px;\n}\n\n.infoText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.filename {\n font-size: 12px;\n font-weight: 500;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n line-height: 1.4;\n}\n\n.meta {\n display: flex;\n gap: 8px;\n font-size: 11px;\n color: #737373;\n}\n\n.meta span {\n white-space: nowrap;\n}\n\n/* Edit Button */\n.editButton {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #a3a3a3;\n transition: background 0.15s, color 0.15s;\n flex-shrink: 0;\n}\n\n.editButton:hover {\n background: #f5f5f5;\n color: #3b82f6;\n}\n\n.editButton:focus {\n outline: none;\n background: #f5f5f5;\n color: #3b82f6;\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { Upload } from 'lucide-react';\nimport { formatFileSize } from '../../hooks/useUpload';\nimport type { UploadConfig } from '../../types';\nimport styles from './UploadDropzone.module.css';\n\nexport interface UploadDropzoneProps {\n onFilesSelected: (files: FileList) => void;\n config: Required<UploadConfig>;\n disabled?: boolean;\n}\n\nexport function UploadDropzone({\n onFilesSelected,\n config,\n disabled = false,\n}: UploadDropzoneProps) {\n const [isDragging, setIsDragging] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const dragCounterRef = useRef(0);\n\n const handleDragEnter = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounterRef.current++;\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n setIsDragging(true);\n }\n }, []);\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n dragCounterRef.current--;\n if (dragCounterRef.current === 0) {\n setIsDragging(false);\n }\n }, []);\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragging(false);\n dragCounterRef.current = 0;\n\n if (disabled) return;\n\n const { files } = e.dataTransfer;\n if (files && files.length > 0) {\n onFilesSelected(files);\n }\n },\n [disabled, onFilesSelected]\n );\n\n const handleClick = useCallback(() => {\n if (!disabled && inputRef.current) {\n inputRef.current.click();\n }\n }, [disabled]);\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const { files } = e.target;\n if (files && files.length > 0) {\n onFilesSelected(files);\n // Reset input so same file can be selected again\n e.target.value = '';\n }\n },\n [onFilesSelected]\n );\n\n const formatAcceptedTypes = (accept: string): string => {\n const types = accept.split(',').map((t) => t.trim());\n const formatted = types.map((type) => {\n if (type === 'image/*') return 'Images';\n if (type === 'image/jpeg') return 'JPG';\n if (type === 'image/png') return 'PNG';\n if (type === 'image/gif') return 'GIF';\n if (type === 'image/webp') return 'WebP';\n if (type === 'image/svg+xml') return 'SVG';\n return type.replace('image/', '').toUpperCase();\n });\n return formatted.join(', ');\n };\n\n return (\n <div\n className={`${styles.dropzone} ${isDragging ? styles.dragging : ''} ${disabled ? styles.disabled : ''}`}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n onClick={handleClick}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleClick();\n }\n }}\n >\n <input\n ref={inputRef}\n type=\"file\"\n accept={config.accept}\n multiple={config.multiple}\n onChange={handleInputChange}\n className={styles.input}\n disabled={disabled}\n />\n <Upload size={24} className={styles.icon} />\n <span className={styles.text}>\n {isDragging ? 'Drop files here' : 'Drop files here or click to upload'}\n </span>\n <span className={styles.hint}>\n {formatAcceptedTypes(config.accept)} (max {formatFileSize(config.maxSize)})\n </span>\n </div>\n );\n}\n","import { useState, useCallback, useRef } from 'react';\nimport type { UploadFn, UploadConfig, UploadingFile, ImageItem, DocumentItem } from '../types';\n\nconst DEFAULT_CONFIG: Required<UploadConfig> = {\n accept: 'image/*',\n maxSize: 10 * 1024 * 1024, // 10MB\n multiple: true,\n};\n\n/** Maximum concurrent uploads */\nconst MAX_CONCURRENT_UPLOADS = 3;\n\nconst generateId = () => `upload-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\nexport const formatFileSize = (bytes: number): string => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n};\n\nconst validateFile = (\n file: File,\n config: Required<UploadConfig>\n): { valid: boolean; error?: string } => {\n if (file.size > config.maxSize) {\n return {\n valid: false,\n error: `File too large. Maximum size is ${formatFileSize(config.maxSize)}`,\n };\n }\n\n const acceptedTypes = config.accept.split(',').map((t) => t.trim());\n const isAccepted = acceptedTypes.some((type) => {\n if (type === '*/*' || type === '*') return true;\n if (type.endsWith('/*')) {\n const category = type.slice(0, -2);\n return file.type.startsWith(category);\n }\n if (type.startsWith('.')) {\n return file.name.toLowerCase().endsWith(type.toLowerCase());\n }\n return file.type === type;\n });\n\n if (!isAccepted) {\n return {\n valid: false,\n error: `File type not accepted. Accepted types: ${config.accept}`,\n };\n }\n\n return { valid: true };\n};\n\nconst createPreviewUrl = (file: File): string | undefined => {\n if (file.type.startsWith('image/')) {\n return URL.createObjectURL(file);\n }\n return undefined;\n};\n\nexport interface UseUploadOptions<T extends ImageItem | DocumentItem> {\n upload: UploadFn<T>;\n config?: UploadConfig;\n onUploadComplete?: (item: T) => void;\n}\n\nexport interface UseUploadReturn {\n /** Files currently being uploaded */\n uploading: UploadingFile[];\n /** Whether any upload is in progress */\n isUploading: boolean;\n /** Add files to upload queue */\n addFiles: (files: FileList | File[]) => void;\n /** Cancel a specific upload */\n cancelUpload: (id: string) => void;\n /** Clear completed/errored uploads */\n clearCompleted: () => void;\n /** The merged config being used */\n uploadConfig: Required<UploadConfig>;\n}\n\nexport function useUpload<T extends ImageItem | DocumentItem>({\n upload,\n config,\n onUploadComplete,\n}: UseUploadOptions<T>): UseUploadReturn {\n const [uploading, setUploading] = useState<UploadingFile[]>([]);\n const activeUploadsRef = useRef<Set<string>>(new Set());\n const uploadConfig = { ...DEFAULT_CONFIG, ...config };\n\n const startUpload = useCallback(\n async (id: string, file: File) => {\n try {\n const result = await upload(file, {\n onProgress: (percent) => {\n setUploading((current) =>\n current.map((f) => (f.id === id ? { ...f, progress: percent } : f))\n );\n },\n });\n\n const singleResult = Array.isArray(result) ? result[0] : result;\n\n setUploading((current) =>\n current.map((f) =>\n f.id === id\n ? { ...f, status: 'completed' as const, progress: 100, result: singleResult }\n : f\n )\n );\n\n onUploadComplete?.(singleResult as T);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Upload failed';\n setUploading((current) =>\n current.map((f) =>\n f.id === id ? { ...f, status: 'error' as const, error: errorMessage } : f\n )\n );\n } finally {\n activeUploadsRef.current.delete(id);\n processQueue();\n }\n },\n [upload, onUploadComplete]\n );\n\n const processQueue = useCallback(() => {\n setUploading((current) => {\n const pending = current.filter(\n (f) => f.status === 'pending' && !activeUploadsRef.current.has(f.id)\n );\n const activeCount = activeUploadsRef.current.size;\n const slotsAvailable = MAX_CONCURRENT_UPLOADS - activeCount;\n\n if (slotsAvailable <= 0 || pending.length === 0) {\n return current;\n }\n\n const toStart = pending.slice(0, slotsAvailable);\n toStart.forEach((file) => {\n activeUploadsRef.current.add(file.id);\n startUpload(file.id, file.file);\n });\n\n return current.map((f) =>\n toStart.some((t) => t.id === f.id) ? { ...f, status: 'uploading' as const } : f\n );\n });\n }, [startUpload]);\n\n const addFiles = useCallback(\n (files: FileList | File[]) => {\n const fileArray = Array.from(files);\n \n // If multiple not allowed, only take first file\n const filesToAdd = uploadConfig.multiple ? fileArray : fileArray.slice(0, 1);\n\n const newUploads: UploadingFile[] = filesToAdd.map((file) => {\n const validation = validateFile(file, uploadConfig);\n const previewUrl = createPreviewUrl(file);\n\n return {\n id: generateId(),\n file,\n progress: 0,\n status: validation.valid ? 'pending' : 'error',\n error: validation.error,\n previewUrl,\n };\n });\n\n setUploading((current) => [...newUploads, ...current]);\n\n // Start processing queue after state update\n setTimeout(processQueue, 0);\n },\n [uploadConfig, processQueue]\n );\n\n const cancelUpload = useCallback((id: string) => {\n setUploading((current) => {\n const file = current.find((f) => f.id === id);\n if (file?.previewUrl) {\n URL.revokeObjectURL(file.previewUrl);\n }\n return current.filter((f) => f.id !== id);\n });\n activeUploadsRef.current.delete(id);\n }, []);\n\n const clearCompleted = useCallback(() => {\n setUploading((current) => {\n current\n .filter((f) => f.status === 'completed' || f.status === 'error')\n .forEach((f) => {\n if (f.previewUrl) {\n URL.revokeObjectURL(f.previewUrl);\n }\n });\n return current.filter((f) => f.status === 'pending' || f.status === 'uploading');\n });\n }, []);\n\n const isUploading = uploading.some(\n (f) => f.status === 'pending' || f.status === 'uploading'\n );\n\n return {\n uploading,\n isUploading,\n addFiles,\n cancelUpload,\n clearCompleted,\n uploadConfig,\n };\n}\n",".dropzone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px 16px;\n border: 2px dashed #d4d4d4;\n border-radius: 8px;\n background: #fafafa;\n cursor: pointer;\n transition: border-color 0.15s, background 0.15s;\n user-select: none;\n}\n\n.dropzone:hover:not(.disabled) {\n border-color: #3b82f6;\n background: #eff6ff;\n}\n\n.dropzone:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);\n}\n\n.dropzone.dragging {\n border-color: #3b82f6;\n background: #dbeafe;\n border-style: solid;\n}\n\n.dropzone.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.input {\n display: none;\n}\n\n.icon {\n color: #737373;\n transition: color 0.15s;\n}\n\n.dropzone:hover:not(.disabled) .icon,\n.dropzone.dragging .icon {\n color: #3b82f6;\n}\n\n.text {\n font-size: 14px;\n font-weight: 500;\n color: #525252;\n text-align: center;\n}\n\n.dropzone:hover:not(.disabled) .text,\n.dropzone.dragging .text {\n color: #3b82f6;\n}\n\n.hint {\n font-size: 12px;\n color: #a3a3a3;\n text-align: center;\n}\n","import { X, CheckCircle, AlertCircle, Loader2 } from 'lucide-react';\nimport { formatFileSize } from '../../hooks/useUpload';\nimport type { UploadingFile } from '../../types';\nimport styles from './UploadQueue.module.css';\n\nexport interface UploadQueueProps {\n files: UploadingFile[];\n onCancel: (id: string) => void;\n onClearCompleted: () => void;\n}\n\nexport function UploadQueue({ files, onCancel, onClearCompleted }: UploadQueueProps) {\n if (files.length === 0) return null;\n\n const hasCompleted = files.some((f) => f.status === 'completed' || f.status === 'error');\n\n return (\n <div className={styles.container}>\n <div className={styles.header}>\n <span className={styles.title}>\n Uploading ({files.filter((f) => f.status === 'uploading' || f.status === 'pending').length})\n </span>\n {hasCompleted && (\n <button\n type=\"button\"\n onClick={onClearCompleted}\n className={styles.clearButton}\n >\n Clear completed\n </button>\n )}\n </div>\n <div className={styles.list}>\n {files.map((file) => (\n <UploadItem key={file.id} file={file} onCancel={() => onCancel(file.id)} />\n ))}\n </div>\n </div>\n );\n}\n\ninterface UploadItemProps {\n file: UploadingFile;\n onCancel: () => void;\n}\n\nfunction UploadItem({ file, onCancel }: UploadItemProps) {\n return (\n <div className={`${styles.item} ${styles[file.status]}`}>\n <div className={styles.preview}>\n {file.previewUrl ? (\n <img src={file.previewUrl} alt=\"\" className={styles.previewImage} />\n ) : (\n <div className={styles.previewPlaceholder} />\n )}\n {file.status === 'uploading' && (\n <div className={styles.progressOverlay}>\n <div \n className={styles.progressBar} \n style={{ height: `${100 - file.progress}%` }}\n />\n <span className={styles.progressText}>{file.progress}%</span>\n </div>\n )}\n </div>\n\n <div className={styles.info}>\n <span className={styles.filename} title={file.file.name}>\n {file.file.name}\n </span>\n <span className={styles.size}>{formatFileSize(file.file.size)}</span>\n {file.error && <span className={styles.error}>{file.error}</span>}\n </div>\n\n <div className={styles.actions}>\n {file.status === 'pending' && (\n <button\n type=\"button\"\n onClick={onCancel}\n className={styles.cancelButton}\n aria-label=\"Cancel upload\"\n >\n <X size={16} />\n </button>\n )}\n {file.status === 'uploading' && (\n <Loader2 size={18} className={styles.spinner} />\n )}\n {file.status === 'completed' && (\n <CheckCircle size={18} className={styles.successIcon} />\n )}\n {file.status === 'error' && (\n <AlertCircle size={18} className={styles.errorIcon} />\n )}\n </div>\n </div>\n );\n}\n",".container {\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n background: white;\n overflow: hidden;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 12px;\n background: #f5f5f5;\n border-bottom: 1px solid #e5e5e5;\n}\n\n.title {\n font-size: 13px;\n font-weight: 500;\n color: #171717;\n}\n\n.clearButton {\n padding: 4px 8px;\n background: transparent;\n border: none;\n border-radius: 4px;\n font-size: 12px;\n color: #3b82f6;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.clearButton:hover {\n background: #eff6ff;\n}\n\n.list {\n max-height: 200px;\n overflow-y: auto;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 8px 12px;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.item:last-child {\n border-bottom: none;\n}\n\n.preview {\n position: relative;\n width: 40px;\n height: 40px;\n border-radius: 4px;\n overflow: hidden;\n flex-shrink: 0;\n background: #f5f5f5;\n}\n\n.previewImage {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.previewPlaceholder {\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, #e5e5e5 0%, #f5f5f5 100%);\n}\n\n.progressOverlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0, 0, 0, 0.3);\n}\n\n.progressBar {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.5);\n transition: height 0.2s ease;\n}\n\n.progressText {\n position: relative;\n z-index: 1;\n font-size: 10px;\n font-weight: 600;\n color: white;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n.info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.filename {\n font-size: 13px;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.size {\n font-size: 11px;\n color: #737373;\n}\n\n.error {\n font-size: 11px;\n color: #dc2626;\n}\n\n.actions {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n}\n\n.cancelButton {\n padding: 4px;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n\n.cancelButton:hover {\n background: #fee2e2;\n color: #dc2626;\n}\n\n.spinner {\n color: #3b82f6;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n.successIcon {\n color: #16a34a;\n}\n\n.errorIcon {\n color: #dc2626;\n}\n\n/* Status-based item styles */\n.item.completed {\n background: #f0fdf4;\n}\n\n.item.error {\n background: #fef2f2;\n}\n","/* Header Buttons */\n.backButton {\n padding: 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n\n.backButton:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n.selectModeButton {\n padding: 8px 14px;\n background: #f5f5f5;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 13px;\n font-weight: 500;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.selectModeButton:hover {\n background: #ebebeb;\n border-color: #d4d4d4;\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n gap: 12px;\n}\n\n/* Upload Section */\n.uploadSection {\n margin-bottom: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* Footer */\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n width: 100%;\n}\n\n.footerInfo {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.footerImage {\n width: 36px;\n height: 36px;\n object-fit: cover;\n border-radius: 4px;\n border: 1px solid #e5e5e5;\n flex-shrink: 0;\n}\n\n.footerFilename {\n font-size: 13px;\n font-weight: 500;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.footerMeta {\n font-size: 12px;\n color: #737373;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.selectButton {\n padding: 10px 20px;\n background: #3b82f6;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.selectButton:hover {\n background: #2563eb;\n}\n\n/* Edit View */\n.editContent {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.editPreview {\n display: flex;\n justify-content: center;\n align-items: center;\n background: #f5f5f5;\n border-radius: 8px;\n padding: 20px;\n min-height: 200px;\n max-height: 300px;\n}\n\n.editImage {\n max-width: 100%;\n max-height: 260px;\n object-fit: contain;\n border-radius: 4px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n.editInfo {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 16px;\n background: #fafafa;\n border-radius: 8px;\n}\n\n.editInfoRow {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.editInfoLabel {\n font-size: 13px;\n font-weight: 500;\n color: #737373;\n min-width: 100px;\n}\n\n.editInfoValue {\n font-size: 13px;\n color: #171717;\n}\n\n.editField {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.editFieldHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.editFieldLabel {\n font-size: 14px;\n font-weight: 600;\n color: #171717;\n margin: 0;\n}\n\n.langTabs {\n display: flex;\n gap: 2px;\n background: #e5e5e5;\n border-radius: 6px;\n padding: 3px;\n}\n\n.langTab {\n padding: 6px 12px;\n font-size: 12px;\n font-weight: 600;\n color: #737373;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n\n.langTab:hover {\n color: #525252;\n}\n\n.langTabActive {\n background: white;\n color: #171717;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.editInput {\n padding: 12px 14px;\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n font-size: 14px;\n background: white;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.editInput:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.editInput::placeholder {\n color: #a3a3a3;\n}\n\n.editFooter {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n}\n\n.saveButton {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: #10b981;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.saveButton:hover:not(:disabled) {\n background: #059669;\n}\n\n.saveButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Mobile Responsive */\n@media (max-width: 640px) {\n .footer {\n flex-direction: column;\n gap: 12px;\n }\n\n .footerInfo {\n width: 100%;\n }\n\n .selectButton {\n width: 100%;\n }\n\n .editPreview {\n min-height: 150px;\n max-height: 200px;\n }\n\n .editImage {\n max-height: 160px;\n }\n\n .editInfoRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n\n .editInfoLabel {\n min-width: auto;\n }\n}\n",".container {\n margin-top: 8px;\n}\n\n.preview {\n position: relative;\n border-radius: 6px;\n overflow: hidden;\n border: 1px solid #e5e5e5;\n background: #f5f5f5;\n}\n\n.image {\n width: 100%;\n height: 128px;\n object-fit: cover;\n display: block;\n}\n\n.overlay {\n position: absolute;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n opacity: 0;\n transition: opacity 0.15s ease;\n}\n\n.preview:hover .overlay {\n opacity: 1;\n}\n\n.changeButton {\n padding: 8px 16px;\n background: white;\n border: none;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.changeButton:hover {\n background: #f0f0f0;\n}\n\n.removeButton {\n padding: 8px;\n background: white;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #dc2626;\n transition: background 0.15s;\n}\n\n.removeButton:hover {\n background: #fee2e2;\n}\n\n.selectButton {\n width: 100%;\n padding: 24px 16px;\n border: 2px dashed #d4d4d4;\n border-radius: 6px;\n background: transparent;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n color: #737373;\n font-size: 13px;\n transition: border-color 0.15s, color 0.15s, background 0.15s;\n}\n\n.selectButton:hover {\n border-color: #3b82f6;\n color: #3b82f6;\n background: #eff6ff;\n}\n\n.selectButton:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);\n}\n","import { useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { FieldLabel } from '@puckeditor/core';\nimport { Images, X } from 'lucide-react';\nimport { GalleryPickerModal } from '../GalleryPickerModal/GalleryPickerModal';\nimport type { GalleryFieldProps, GalleryItem } from '../../types';\nimport styles from './GalleryField.module.css';\n\nexport function GalleryField({\n value,\n onChange,\n field,\n languages,\n galleryOptions,\n}: GalleryFieldProps) {\n const [isModalOpen, setIsModalOpen] = useState(false);\n\n const handleSelect = (gallery: GalleryItem) => {\n onChange(gallery);\n setIsModalOpen(false);\n };\n\n const handleRemove = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange(null);\n };\n\n const handleOpenModal = () => {\n setIsModalOpen(true);\n };\n\n const previewImages = value?.images?.slice(0, 4) || [];\n const remainingCount = (value?.images?.length || 0) - 4;\n\n return (\n <FieldLabel label={field.label || 'Gallery'}>\n <div className={styles.container}>\n {value ? (\n <div className={styles.preview}>\n <div className={styles.header}>\n <span className={styles.name}>{value.name}</span>\n <span className={styles.count}>\n {value.images.length} {value.images.length === 1 ? 'image' : 'images'}\n </span>\n </div>\n \n {previewImages.length > 0 && (\n <div className={styles.thumbnails}>\n {previewImages.map((img) => (\n <div key={img.id} className={styles.thumbnail}>\n <img src={img.url} alt=\"\" />\n </div>\n ))}\n {remainingCount > 0 && (\n <div className={styles.more}>\n +{remainingCount}\n </div>\n )}\n </div>\n )}\n\n <div className={styles.actions}>\n <button\n type=\"button\"\n onClick={handleOpenModal}\n className={styles.changeButton}\n >\n Change Gallery\n </button>\n <button\n type=\"button\"\n onClick={handleRemove}\n className={styles.removeButton}\n aria-label=\"Remove gallery\"\n >\n <X size={16} />\n </button>\n </div>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={handleOpenModal}\n className={styles.selectButton}\n >\n <Images size={24} />\n <span>Select gallery</span>\n </button>\n )}\n </div>\n\n {isModalOpen && createPortal(\n <GalleryPickerModal\n languages={languages}\n galleryOptions={galleryOptions}\n title=\"Select Gallery\"\n onSelect={handleSelect}\n onClose={() => setIsModalOpen(false)}\n />,\n document.body\n )}\n </FieldLabel>\n );\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { Plus, ArrowLeft, Loader2, Check } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { SearchBar } from '../SearchBar';\nimport { LoadMoreButton } from '../LoadMoreButton';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { SelectionToolbar } from '../SelectionToolbar';\nimport { ImageGrid } from '../ImageGrid/ImageGrid';\nimport { UploadDropzone } from '../UploadDropzone/UploadDropzone';\nimport { UploadQueue } from '../UploadQueue/UploadQueue';\nimport { useUpload } from '../../hooks/useUpload';\nimport type { GalleryPickerModalProps, GalleryItem, ImageItem, LocalizedString } from '../../types';\nimport styles from './GalleryPickerModal.module.css';\n\ntype ViewMode = 'list' | 'detail' | 'editImage';\n\nconst DEFAULT_UPLOAD_CONFIG = {\n accept: 'image/*',\n maxSize: 10 * 1024 * 1024,\n multiple: true,\n};\n\nconst PAGE_SIZE = 20;\n\nexport function GalleryPickerModal({\n languages,\n galleryOptions,\n title = 'Select Gallery',\n selectedGallery: _initialSelectedGallery,\n onSelect,\n onClose,\n selectable = true,\n}: GalleryPickerModalProps) {\n void _initialSelectedGallery;\n const { fetchList, fetch, create, delete: deleteGallery, upload, removeImage, updateImage } = galleryOptions;\n\n const [viewMode, setViewMode] = useState<ViewMode>('list');\n const [editingImage, setEditingImage] = useState<ImageItem | null>(null);\n const [galleries, setGalleries] = useState<GalleryItem[]>([]);\n const [selectedGalleryItem, setSelectedGalleryItem] = useState<GalleryItem | null>(null);\n const [search, setSearch] = useState('');\n const [loading, setLoading] = useState(true);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [gallerySelectMode, setGallerySelectMode] = useState(false);\n const [selectedGalleryIds, setSelectedGalleryIds] = useState<Set<string>>(new Set());\n const [imageSelectMode, setImageSelectMode] = useState(false);\n const [selectedImageIds, setSelectedImageIds] = useState<Set<string>>(new Set());\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [deleteTarget, setDeleteTarget] = useState<'gallery' | 'image'>('gallery');\n const [isDeleting, setIsDeleting] = useState(false);\n const [isCreating, setIsCreating] = useState(false);\n const [newGalleryName, setNewGalleryName] = useState('');\n const [createLoading, setCreateLoading] = useState(false);\n const [altValues, setAltValues] = useState<LocalizedString>({});\n const [activeLang, setActiveLang] = useState(languages[0]?.code || 'it');\n const [isSaving, setIsSaving] = useState(false);\n const newGalleryInputRef = useRef<HTMLInputElement>(null);\n\n const {\n uploading,\n isUploading,\n addFiles,\n cancelUpload,\n clearCompleted,\n uploadConfig: mergedUploadConfig,\n } = useUpload({\n upload: async (file, callbacks) => {\n if (!selectedGalleryItem) throw new Error('No gallery selected');\n const result = await upload(selectedGalleryItem.id, file, callbacks);\n return Array.isArray(result) ? result[0] : result;\n },\n config: DEFAULT_UPLOAD_CONFIG,\n onUploadComplete: (newItem) => {\n if (selectedGalleryItem) {\n setSelectedGalleryItem((prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n images: [newItem as ImageItem, ...prev.images],\n imageCount: (prev.imageCount || 0) + 1,\n };\n });\n }\n },\n });\n\n const loadGalleries = useCallback(\n async (searchQuery: string, pageNum: number, append = false) => {\n setLoading(true);\n try {\n const result = await fetchList({\n query: searchQuery || undefined,\n page: pageNum,\n pageSize: PAGE_SIZE,\n });\n\n const newItems = Array.isArray(result) ? result : result.items;\n const more = Array.isArray(result) ? newItems.length === PAGE_SIZE : (result.hasMore ?? false);\n\n setGalleries((prev) => (append ? [...prev, ...newItems] : newItems));\n setHasMore(more);\n } catch (error) {\n console.error('Failed to fetch galleries:', error);\n setGalleries([]);\n setHasMore(false);\n } finally {\n setLoading(false);\n }\n },\n [fetchList]\n );\n\n const loadGalleryDetail = useCallback(\n async (id: string) => {\n setLoading(true);\n try {\n const gallery = await fetch(id);\n setSelectedGalleryItem(gallery);\n } catch (error) {\n console.error('Failed to fetch gallery:', error);\n } finally {\n setLoading(false);\n }\n },\n [fetch]\n );\n\n useEffect(() => {\n if (viewMode === 'list') {\n const timer = setTimeout(() => {\n setPage(1);\n loadGalleries(search, 1);\n }, 300);\n return () => clearTimeout(timer);\n }\n }, [search, loadGalleries, viewMode]);\n\n useEffect(() => {\n if (isCreating && newGalleryInputRef.current) {\n newGalleryInputRef.current.focus();\n }\n }, [isCreating]);\n\n const handleClose = useCallback(() => {\n onClose();\n }, [onClose]);\n\n const handleLoadMore = () => {\n const nextPage = page + 1;\n setPage(nextPage);\n loadGalleries(search, nextPage, true);\n };\n\n const handleGalleryClick = (gallery: GalleryItem) => {\n if (gallerySelectMode) {\n setSelectedGalleryIds((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(gallery.id)) {\n newSet.delete(gallery.id);\n } else {\n newSet.add(gallery.id);\n }\n return newSet;\n });\n } else {\n setViewMode('detail');\n loadGalleryDetail(gallery.id);\n }\n };\n\n const handleCreateGallery = async () => {\n if (!newGalleryName.trim()) return;\n \n setCreateLoading(true);\n try {\n const newGallery = await create(newGalleryName.trim());\n setGalleries((prev) => [newGallery, ...prev]);\n setIsCreating(false);\n setNewGalleryName('');\n } catch (error) {\n console.error('Failed to create gallery:', error);\n } finally {\n setCreateLoading(false);\n }\n };\n\n const handleSelectAllGalleries = () => {\n if (selectedGalleryIds.size === galleries.length) {\n setSelectedGalleryIds(new Set());\n } else {\n setSelectedGalleryIds(new Set(galleries.map((g) => g.id)));\n }\n };\n\n const handleSelectAllImages = () => {\n if (!selectedGalleryItem) return;\n if (selectedImageIds.size === selectedGalleryItem.images.length) {\n setSelectedImageIds(new Set());\n } else {\n setSelectedImageIds(new Set(selectedGalleryItem.images.map((img) => img.id)));\n }\n };\n\n const handleToggleImageSelect = (image: ImageItem) => {\n setSelectedImageIds((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(image.id)) {\n newSet.delete(image.id);\n } else {\n newSet.add(image.id);\n }\n return newSet;\n });\n };\n\n const handleConfirmDelete = async () => {\n setIsDeleting(true);\n try {\n if (deleteTarget === 'gallery') {\n const deletePromises = Array.from(selectedGalleryIds).map((id) => deleteGallery(id));\n await Promise.all(deletePromises);\n setGalleries((prev) => prev.filter((g) => !selectedGalleryIds.has(g.id)));\n setSelectedGalleryIds(new Set());\n setGallerySelectMode(false);\n } else {\n if (!selectedGalleryItem) return;\n const removePromises = Array.from(selectedImageIds).map((imageId) =>\n removeImage(selectedGalleryItem.id, imageId)\n );\n await Promise.all(removePromises);\n setSelectedGalleryItem((prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n images: prev.images.filter((img) => !selectedImageIds.has(img.id)),\n imageCount: (prev.imageCount || prev.images.length) - selectedImageIds.size,\n };\n });\n setSelectedImageIds(new Set());\n setImageSelectMode(false);\n }\n setShowDeleteConfirm(false);\n } catch (error) {\n console.error('Failed to delete:', error);\n } finally {\n setIsDeleting(false);\n }\n };\n\n const handleEditAlt = (image: ImageItem) => {\n setEditingImage(image);\n setAltValues(image.alt || {});\n setActiveLang(languages[0]?.code || 'it');\n setViewMode('editImage');\n };\n\n const handleAltChange = (langCode: string, value: string) => {\n setAltValues((prev) => ({\n ...prev,\n [langCode]: value,\n }));\n };\n\n const handleSaveAlt = async () => {\n if (!selectedGalleryItem || !editingImage || !updateImage) return;\n\n setIsSaving(true);\n try {\n await updateImage(selectedGalleryItem.id, editingImage.id, { alt: altValues });\n setSelectedGalleryItem((prev) => {\n if (!prev) return prev;\n return {\n ...prev,\n images: prev.images.map((img) =>\n img.id === editingImage.id ? { ...img, alt: altValues } : img\n ),\n };\n });\n setViewMode('detail');\n setEditingImage(null);\n setAltValues({});\n } catch (error) {\n console.error('Failed to update alt text:', error);\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleSelectGallery = () => {\n if (selectedGalleryItem && onSelect) {\n onSelect(selectedGalleryItem);\n }\n };\n\n const formatFileSize = (bytes?: number): string => {\n if (!bytes) return '';\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n };\n\n const isAllGalleriesSelected = galleries.length > 0 && selectedGalleryIds.size === galleries.length;\n const isSomeGalleriesSelected = selectedGalleryIds.size > 0 && selectedGalleryIds.size < galleries.length;\n const isAllImagesSelected = selectedGalleryItem && selectedGalleryItem.images.length > 0 && selectedImageIds.size === selectedGalleryItem.images.length;\n const isSomeImagesSelected = selectedImageIds.size > 0 && selectedGalleryItem && selectedImageIds.size < selectedGalleryItem.images.length;\n\n // Edit Image View\n if (viewMode === 'editImage' && editingImage) {\n return (\n <Modal\n title=\"Edit Image Details\"\n onClose={handleClose}\n headerLeft={\n <button\n type=\"button\"\n onClick={() => {\n setViewMode('detail');\n setEditingImage(null);\n setAltValues({});\n }}\n className={styles.backButton}\n aria-label=\"Back to gallery\"\n >\n <ArrowLeft size={20} />\n </button>\n }\n footer={\n <div className={styles.editFooter}>\n <div />\n <button\n type=\"button\"\n onClick={handleSaveAlt}\n className={styles.saveButton}\n disabled={isSaving || !updateImage}\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className={styles.spinner} />\n Saving...\n </>\n ) : (\n 'Save'\n )}\n </button>\n </div>\n }\n >\n <div className={styles.editContent}>\n <div className={styles.editPreview}>\n <img\n src={editingImage.url}\n alt={editingImage.filename || ''}\n className={styles.editImage}\n />\n </div>\n\n <div className={styles.editInfo}>\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Filename</span>\n <span className={styles.editInfoValue}>{editingImage.filename}</span>\n </div>\n {editingImage.width && editingImage.height && (\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Dimensions</span>\n <span className={styles.editInfoValue}>\n {editingImage.width}×{editingImage.height}\n </span>\n </div>\n )}\n {editingImage.size && (\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Size</span>\n <span className={styles.editInfoValue}>\n {formatFileSize(editingImage.size)}\n </span>\n </div>\n )}\n </div>\n\n <div className={styles.editField}>\n <div className={styles.editFieldHeader}>\n <label className={styles.editFieldLabel}>Alt</label>\n <div className={styles.langTabs}>\n {languages.map((lang) => (\n <button\n key={lang.code}\n type=\"button\"\n onClick={() => setActiveLang(lang.code)}\n className={`${styles.langTab} ${activeLang === lang.code ? styles.langTabActive : ''}`}\n >\n {lang.code.toUpperCase()}\n </button>\n ))}\n </div>\n </div>\n <input\n type=\"text\"\n value={altValues[activeLang] || ''}\n onChange={(e) => handleAltChange(activeLang, e.target.value)}\n placeholder={`Alt text in ${languages.find(l => l.code === activeLang)?.label || activeLang}...`}\n className={styles.editInput}\n />\n </div>\n </div>\n </Modal>\n );\n }\n\n // Detail View\n if (viewMode === 'detail' && selectedGalleryItem) {\n const renderDetailFooter = () => {\n if (imageSelectMode) {\n return (\n <SelectionToolbar\n selectedCount={selectedImageIds.size}\n totalCount={selectedGalleryItem.images.length}\n onSelectAll={handleSelectAllImages}\n onCancel={() => {\n setImageSelectMode(false);\n setSelectedImageIds(new Set());\n }}\n onDelete={() => {\n setDeleteTarget('image');\n setShowDeleteConfirm(true);\n }}\n isAllSelected={!!isAllImagesSelected}\n isIndeterminate={!!isSomeImagesSelected}\n deleteLabel=\"Remove\"\n />\n );\n }\n\n if (selectable) {\n return (\n <div className={styles.footer}>\n <div className={styles.footerInfo}>\n <span className={styles.footerText}>\n {selectedGalleryItem.images.length} {selectedGalleryItem.images.length === 1 ? 'image' : 'images'}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={handleSelectGallery}\n className={styles.selectButton}\n >\n Select this Gallery\n </button>\n </div>\n );\n }\n\n return undefined;\n };\n\n return (\n <Modal\n title={selectedGalleryItem.name}\n onClose={handleClose}\n headerLeft={\n <button\n type=\"button\"\n onClick={() => {\n setViewMode('list');\n setSelectedGalleryItem(null);\n }}\n className={styles.backButton}\n aria-label=\"Back to galleries\"\n >\n <ArrowLeft size={20} />\n </button>\n }\n headerActions={\n !imageSelectMode && typeof removeImage === 'function' ? (\n <button\n type=\"button\"\n onClick={() => setImageSelectMode(true)}\n className={styles.selectModeButton}\n >\n Select Items\n </button>\n ) : undefined\n }\n toolbar={\n !imageSelectMode ? (\n <div className={styles.uploadSection}>\n <UploadDropzone\n onFilesSelected={addFiles}\n config={mergedUploadConfig}\n disabled={isUploading && uploading.length >= 10}\n />\n {uploading.length > 0 && (\n <UploadQueue\n files={uploading}\n onCancel={cancelUpload}\n onClearCompleted={clearCompleted}\n />\n )}\n </div>\n ) : undefined\n }\n footer={renderDetailFooter()}\n overlay={\n showDeleteConfirm ? (\n <ConfirmDialog\n title=\"Remove Images\"\n message={`Are you sure you want to remove ${selectedImageIds.size} ${selectedImageIds.size > 1 ? 'images' : 'image'} from this gallery?`}\n confirmLabel={isDeleting ? 'Removing...' : `Remove ${selectedImageIds.size} ${selectedImageIds.size > 1 ? 'images' : 'image'}`}\n onConfirm={handleConfirmDelete}\n onCancel={() => setShowDeleteConfirm(false)}\n loading={isDeleting}\n variant=\"danger\"\n />\n ) : undefined\n }\n loading={loading}\n empty={!loading && selectedGalleryItem.images.length === 0}\n emptyMessage=\"No images in this gallery. Upload some images above.\"\n >\n <ImageGrid\n items={selectedGalleryItem.images}\n onSelect={() => {}}\n onEditAlt={updateImage ? handleEditAlt : undefined}\n manageMode={imageSelectMode}\n selectedIds={selectedImageIds}\n onToggleSelect={handleToggleImageSelect}\n />\n </Modal>\n );\n }\n\n // List View (default)\n const renderListFooter = () => {\n if (gallerySelectMode) {\n return (\n <SelectionToolbar\n selectedCount={selectedGalleryIds.size}\n totalCount={galleries.length}\n onSelectAll={handleSelectAllGalleries}\n onCancel={() => {\n setGallerySelectMode(false);\n setSelectedGalleryIds(new Set());\n }}\n onDelete={() => {\n setDeleteTarget('gallery');\n setShowDeleteConfirm(true);\n }}\n isAllSelected={isAllGalleriesSelected}\n isIndeterminate={isSomeGalleriesSelected}\n />\n );\n }\n return undefined;\n };\n\n return (\n <Modal\n title={title}\n onClose={handleClose}\n headerActions={\n !gallerySelectMode && typeof deleteGallery === 'function' ? (\n <button\n type=\"button\"\n onClick={() => setGallerySelectMode(true)}\n className={styles.selectModeButton}\n >\n Select Items\n </button>\n ) : undefined\n }\n toolbar={\n !gallerySelectMode ? (\n <div className={styles.toolbar}>\n <SearchBar\n value={search}\n onChange={setSearch}\n placeholder=\"Search galleries...\"\n autoFocus\n />\n <button\n type=\"button\"\n onClick={() => setIsCreating(true)}\n className={styles.createButton}\n >\n <Plus size={18} />\n New Gallery\n </button>\n </div>\n ) : undefined\n }\n footer={renderListFooter()}\n overlay={\n showDeleteConfirm ? (\n <ConfirmDialog\n title=\"Delete Galleries\"\n message={`Are you sure you want to delete ${selectedGalleryIds.size} ${selectedGalleryIds.size > 1 ? 'galleries' : 'gallery'}? This action cannot be undone.`}\n confirmLabel={isDeleting ? 'Deleting...' : `Delete ${selectedGalleryIds.size} ${selectedGalleryIds.size > 1 ? 'galleries' : 'gallery'}`}\n onConfirm={handleConfirmDelete}\n onCancel={() => setShowDeleteConfirm(false)}\n loading={isDeleting}\n variant=\"danger\"\n />\n ) : undefined\n }\n loading={loading && galleries.length === 0}\n empty={!loading && galleries.length === 0}\n emptyMessage=\"No galleries found\"\n >\n {isCreating && (\n <div className={styles.createForm}>\n <input\n ref={newGalleryInputRef}\n type=\"text\"\n value={newGalleryName}\n onChange={(e) => setNewGalleryName(e.target.value)}\n placeholder=\"Gallery name...\"\n className={styles.createInput}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleCreateGallery();\n if (e.key === 'Escape') {\n setIsCreating(false);\n setNewGalleryName('');\n }\n }}\n />\n <button\n type=\"button\"\n onClick={handleCreateGallery}\n disabled={!newGalleryName.trim() || createLoading}\n className={styles.createSubmitButton}\n >\n {createLoading ? <Loader2 size={16} className={styles.spinner} /> : 'Create'}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setIsCreating(false);\n setNewGalleryName('');\n }}\n className={styles.createCancelButton}\n >\n Cancel\n </button>\n </div>\n )}\n\n <div className={styles.galleryGrid}>\n {galleries.map((gallery) => {\n const isSelected = selectedGalleryIds.has(gallery.id);\n return (\n <div key={gallery.id} className={styles.galleryCard}>\n <button\n type=\"button\"\n onClick={() => handleGalleryClick(gallery)}\n className={`${styles.galleryCardButton} ${gallerySelectMode && isSelected ? styles.selected : ''}`}\n >\n {gallerySelectMode && (\n <div className={`${styles.checkbox} ${isSelected ? styles.checkboxChecked : ''}`}>\n {isSelected && <Check size={14} strokeWidth={3} />}\n </div>\n )}\n <div className={styles.galleryCover}>\n {gallery.coverImage ? (\n <img\n src={gallery.coverImage.thumbnailUrl || gallery.coverImage.url}\n alt=\"\"\n />\n ) : (\n <div className={styles.galleryCoverPlaceholder} />\n )}\n </div>\n <div className={styles.galleryInfo}>\n <span className={styles.galleryName}>{gallery.name}</span>\n <span className={styles.galleryCount}>\n {gallery.imageCount ?? gallery.images.length} {(gallery.imageCount ?? gallery.images.length) === 1 ? 'image' : 'images'}\n </span>\n </div>\n </button>\n </div>\n );\n })}\n </div>\n\n {hasMore && (\n <LoadMoreButton onClick={handleLoadMore} loading={loading} />\n )}\n </Modal>\n );\n}\n","/* Header Buttons */\n.backButton {\n padding: 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n\n.backButton:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n.selectModeButton {\n padding: 8px 16px;\n background: #f5f5f5;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.selectModeButton:hover {\n background: #ebebeb;\n border-color: #d4d4d4;\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n gap: 12px;\n}\n\n.createButton {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 10px 16px;\n background: #3b82f6;\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.15s;\n}\n\n.createButton:hover {\n background: #2563eb;\n}\n\n/* Create Form */\n.createForm {\n display: flex;\n gap: 8px;\n padding: 12px;\n background: #f5f5f5;\n border-radius: 8px;\n margin-bottom: 16px;\n}\n\n.createInput {\n flex: 1;\n padding: 8px 12px;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n background: white;\n}\n\n.createInput:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.createSubmitButton {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: #3b82f6;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.createSubmitButton:hover:not(:disabled) {\n background: #2563eb;\n}\n\n.createSubmitButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.createCancelButton {\n padding: 8px 12px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.createCancelButton:hover {\n background: #f5f5f5;\n}\n\n/* Upload Section */\n.uploadSection {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* Gallery Grid */\n.galleryGrid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n gap: 16px;\n}\n\n.galleryCard {\n position: relative;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.galleryCardButton {\n display: block;\n width: 100%;\n padding: 0;\n background: white;\n border: 2px solid #e5e5e5;\n border-radius: 8px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s, box-shadow 0.15s;\n overflow: hidden;\n}\n\n.galleryCardButton:hover {\n border-color: #3b82f6;\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);\n}\n\n.galleryCardButton.selected {\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);\n}\n\n.checkbox {\n position: absolute;\n top: 8px;\n left: 8px;\n width: 22px;\n height: 22px;\n background: white;\n border: 2px solid #d4d4d4;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1;\n transition: background 0.15s, border-color 0.15s;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.checkboxChecked {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n}\n\n.galleryCover {\n aspect-ratio: 4/3;\n background: #f5f5f5;\n overflow: hidden;\n}\n\n.galleryCover img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.2s;\n}\n\n.galleryCardButton:hover .galleryCover img {\n transform: scale(1.05);\n}\n\n.galleryCoverPlaceholder {\n width: 100%;\n height: 100%;\n background: linear-gradient(135deg, #e5e5e5 0%, #f5f5f5 100%);\n}\n\n.galleryInfo {\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.galleryName {\n font-size: 14px;\n font-weight: 500;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.galleryCount {\n font-size: 12px;\n color: #737373;\n}\n\n/* Footer */\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n width: 100%;\n}\n\n.footerInfo {\n display: flex;\n align-items: center;\n gap: 10px;\n flex: 1;\n}\n\n.footerText {\n font-size: 13px;\n color: #737373;\n}\n\n.selectButton {\n padding: 10px 20px;\n background: #3b82f6;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.selectButton:hover {\n background: #2563eb;\n}\n\n/* Edit View */\n.editContent {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.editPreview {\n display: flex;\n justify-content: center;\n align-items: center;\n background: #f5f5f5;\n border-radius: 8px;\n padding: 20px;\n min-height: 200px;\n max-height: 300px;\n}\n\n.editImage {\n max-width: 100%;\n max-height: 260px;\n object-fit: contain;\n border-radius: 4px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n.editInfo {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 16px;\n background: #fafafa;\n border-radius: 8px;\n}\n\n.editInfoRow {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.editInfoLabel {\n font-size: 13px;\n font-weight: 500;\n color: #737373;\n min-width: 100px;\n}\n\n.editInfoValue {\n font-size: 13px;\n color: #171717;\n}\n\n.editField {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.editFieldHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.editFieldLabel {\n font-size: 14px;\n font-weight: 600;\n color: #171717;\n margin: 0;\n}\n\n.langTabs {\n display: flex;\n gap: 2px;\n background: #e5e5e5;\n border-radius: 6px;\n padding: 3px;\n}\n\n.langTab {\n padding: 6px 12px;\n font-size: 12px;\n font-weight: 600;\n color: #737373;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n\n.langTab:hover {\n color: #525252;\n}\n\n.langTabActive {\n background: white;\n color: #171717;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.editInput {\n padding: 12px 14px;\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n font-size: 14px;\n background: white;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.editInput:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.editInput::placeholder {\n color: #a3a3a3;\n}\n\n.editFooter {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n}\n\n.saveButton {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: #10b981;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.saveButton:hover:not(:disabled) {\n background: #059669;\n}\n\n.saveButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Mobile Responsive */\n@media (max-width: 640px) {\n .toolbar {\n flex-direction: column;\n }\n\n .createButton {\n width: 100%;\n justify-content: center;\n }\n\n .footer {\n flex-direction: column;\n gap: 12px;\n }\n\n .footerInfo {\n width: 100%;\n }\n\n .selectButton {\n width: 100%;\n }\n\n .editPreview {\n min-height: 150px;\n max-height: 200px;\n }\n\n .editImage {\n max-height: 160px;\n }\n\n .editInfoRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n\n .editInfoLabel {\n min-width: auto;\n }\n}\n",".container {\n margin-top: 8px;\n}\n\n.preview {\n border-radius: 6px;\n border: 1px solid #e5e5e5;\n background: #fafafa;\n padding: 12px;\n}\n\n.header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 12px;\n}\n\n.name {\n font-size: 14px;\n font-weight: 500;\n color: #171717;\n}\n\n.count {\n font-size: 12px;\n color: #737373;\n}\n\n.thumbnails {\n display: flex;\n gap: 6px;\n margin-bottom: 12px;\n}\n\n.thumbnail {\n width: 48px;\n height: 48px;\n border-radius: 4px;\n overflow: hidden;\n border: 1px solid #e5e5e5;\n background: #f5f5f5;\n}\n\n.thumbnail img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.more {\n width: 48px;\n height: 48px;\n border-radius: 4px;\n border: 1px solid #e5e5e5;\n background: #f5f5f5;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n font-weight: 500;\n color: #737373;\n}\n\n.actions {\n display: flex;\n gap: 8px;\n}\n\n.changeButton {\n flex: 1;\n padding: 8px 12px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.changeButton:hover {\n background: #f5f5f5;\n border-color: #d4d4d4;\n}\n\n.removeButton {\n padding: 8px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #dc2626;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.removeButton:hover {\n background: #fee2e2;\n border-color: #fecaca;\n}\n\n.selectButton {\n width: 100%;\n padding: 24px 16px;\n border: 2px dashed #d4d4d4;\n border-radius: 6px;\n background: transparent;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n color: #737373;\n font-size: 13px;\n transition: border-color 0.15s, color 0.15s, background 0.15s;\n}\n\n.selectButton:hover {\n border-color: #3b82f6;\n color: #3b82f6;\n background: #eff6ff;\n}\n\n.selectButton:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);\n}\n","import { useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { FieldLabel } from '@puckeditor/core';\nimport { FileText, File, X } from 'lucide-react';\nimport { DocumentPickerModal } from '../DocumentPickerModal/DocumentPickerModal';\nimport { formatFileSize } from '../../hooks/useUpload';\nimport type { DocumentFieldProps, DocumentItem } from '../../types';\nimport styles from './DocumentField.module.css';\n\nexport function DocumentField({\n value,\n onChange,\n field,\n languages,\n documentOptions,\n}: DocumentFieldProps) {\n const [isModalOpen, setIsModalOpen] = useState(false);\n\n const handleSelect = (item: DocumentItem) => {\n onChange(item);\n setIsModalOpen(false);\n };\n\n const handleRemove = (e: React.MouseEvent) => {\n e.stopPropagation();\n onChange(null);\n };\n\n const handleOpenModal = () => {\n setIsModalOpen(true);\n };\n\n const getTitleDisplay = (): string => {\n if (value?.title) {\n for (const lang of languages) {\n if (value.title[lang.code]) {\n return value.title[lang.code] as string;\n }\n }\n }\n return value?.filename || '';\n };\n\n const getIcon = () => {\n if (value?.mimeType === 'application/pdf') {\n return <FileText size={24} className={styles.pdfIcon} />;\n }\n return <File size={24} className={styles.fileIcon} />;\n };\n\n return (\n <FieldLabel label={field.label || 'Document'}>\n <div className={styles.container}>\n {value ? (\n <div className={styles.preview}>\n <div className={styles.iconWrapper}>\n {getIcon()}\n </div>\n <div className={styles.info}>\n <span className={styles.title}>{getTitleDisplay()}</span>\n <span className={styles.meta}>\n {value.extension?.toUpperCase()} • {formatFileSize(value.size)}\n </span>\n </div>\n <div className={styles.actions}>\n <button\n type=\"button\"\n onClick={handleOpenModal}\n className={styles.changeButton}\n >\n Change\n </button>\n <button\n type=\"button\"\n onClick={handleRemove}\n className={styles.removeButton}\n aria-label=\"Remove document\"\n >\n <X size={16} />\n </button>\n </div>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={handleOpenModal}\n className={styles.selectButton}\n >\n <FileText size={24} />\n <span>Select document</span>\n </button>\n )}\n </div>\n\n {isModalOpen && createPortal(\n <DocumentPickerModal\n languages={languages}\n documentOptions={documentOptions}\n title=\"Select Document\"\n onSelect={handleSelect}\n onClose={() => setIsModalOpen(false)}\n />,\n document.body\n )}\n </FieldLabel>\n );\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { FileText, File, ArrowLeft, Loader2, Check, Pencil } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { SearchBar } from '../SearchBar';\nimport { LoadMoreButton } from '../LoadMoreButton';\nimport { ConfirmDialog } from '../ConfirmDialog';\nimport { SelectionToolbar } from '../SelectionToolbar';\nimport { UploadDropzone } from '../UploadDropzone/UploadDropzone';\nimport { UploadQueue } from '../UploadQueue/UploadQueue';\nimport { useUpload, formatFileSize } from '../../hooks/useUpload';\nimport type { DocumentPickerModalProps, DocumentItem, LocalizedString } from '../../types';\nimport styles from './DocumentPickerModal.module.css';\n\ntype ViewMode = 'picker' | 'edit';\n\nconst DEFAULT_UPLOAD_CONFIG = {\n accept: '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt',\n maxSize: 20 * 1024 * 1024,\n multiple: true,\n};\n\nconst PAGE_SIZE = 20;\n\nexport function DocumentPickerModal({\n languages,\n documentOptions,\n title = 'Select Document',\n selectedDocument,\n onSelect,\n onClose,\n selectable = true,\n}: DocumentPickerModalProps) {\n const { fetchList, upload, update, delete: deleteDocument, uploadConfig } = documentOptions;\n\n const [view, setView] = useState<ViewMode>('picker');\n const [editingItem, setEditingItem] = useState<DocumentItem | null>(null);\n const [selectMode, setSelectMode] = useState(false);\n const [selectedForDelete, setSelectedForDelete] = useState<Set<string>>(new Set());\n const [items, setItems] = useState<DocumentItem[]>([]);\n const [search, setSearch] = useState('');\n const [loading, setLoading] = useState(true);\n const [page, setPage] = useState(1);\n const [hasMore, setHasMore] = useState(false);\n const [selectedItem, setSelectedItem] = useState<DocumentItem | null>(null);\n const [titleValues, setTitleValues] = useState<LocalizedString>({});\n const [activeLang, setActiveLang] = useState(languages[0]?.code || 'it');\n const [isSaving, setIsSaving] = useState(false);\n const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n\n const canUpload = !!upload;\n const {\n uploading,\n isUploading,\n addFiles,\n cancelUpload,\n clearCompleted,\n uploadConfig: mergedUploadConfig,\n } = useUpload({\n upload: upload || (async () => { throw new Error('Upload not configured'); }),\n config: uploadConfig || DEFAULT_UPLOAD_CONFIG,\n onUploadComplete: (newItem) => {\n setItems((prev) => [newItem as DocumentItem, ...prev]);\n },\n });\n\n const loadItems = useCallback(\n async (searchQuery: string, pageNum: number, append = false) => {\n setLoading(true);\n try {\n const result = await fetchList({\n query: searchQuery || undefined,\n page: pageNum,\n pageSize: PAGE_SIZE,\n });\n\n const newItems = Array.isArray(result) ? result : result.items;\n const more = Array.isArray(result) ? newItems.length === PAGE_SIZE : (result.hasMore ?? false);\n\n setItems((prev) => (append ? [...prev, ...newItems] : newItems));\n setHasMore(more);\n } catch (error) {\n console.error('Failed to fetch documents:', error);\n setItems([]);\n setHasMore(false);\n } finally {\n setLoading(false);\n }\n },\n [fetchList]\n );\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setPage(1);\n loadItems(search, 1);\n }, 300);\n return () => clearTimeout(timer);\n }, [search, loadItems]);\n\n useEffect(() => {\n if (selectedDocument) {\n const existingItem = items.find((item) => item.id === selectedDocument.id);\n if (existingItem) {\n setSelectedItem(existingItem);\n }\n }\n }, [selectedDocument, items]);\n\n const handleClose = useCallback(() => {\n onClose();\n }, [onClose]);\n\n const handleLoadMore = () => {\n const nextPage = page + 1;\n setPage(nextPage);\n loadItems(search, nextPage, true);\n };\n\n const handleDocumentClick = (item: DocumentItem) => {\n if (selectMode) {\n setSelectedForDelete((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(item.id)) {\n newSet.delete(item.id);\n } else {\n newSet.add(item.id);\n }\n return newSet;\n });\n } else {\n if (selectedItem?.id === item.id) {\n setSelectedItem(null);\n } else {\n setSelectedItem(item);\n }\n }\n };\n\n const handleConfirmSelection = () => {\n if (!selectedItem || !onSelect) return;\n onSelect(selectedItem);\n };\n\n const handleEditTitle = (item: DocumentItem) => {\n setEditingItem(item);\n setTitleValues(item.title || {});\n setActiveLang(languages[0]?.code || 'it');\n setView('edit');\n };\n\n const handleTitleChange = (langCode: string, value: string) => {\n setTitleValues((prev) => ({\n ...prev,\n [langCode]: value,\n }));\n };\n\n const handleSaveTitle = async () => {\n if (!editingItem || !update) return;\n\n setIsSaving(true);\n try {\n await update(editingItem.id, { title: titleValues });\n setItems((prev) =>\n prev.map((item) =>\n item.id === editingItem.id ? { ...item, title: titleValues } : item\n )\n );\n if (selectedItem?.id === editingItem.id) {\n setSelectedItem((prev) => prev ? { ...prev, title: titleValues } : null);\n }\n setView('picker');\n setEditingItem(null);\n setTitleValues({});\n } catch (error) {\n console.error('Failed to update title:', error);\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleSelectAll = () => {\n if (selectedForDelete.size === items.length) {\n setSelectedForDelete(new Set());\n } else {\n setSelectedForDelete(new Set(items.map((item) => item.id)));\n }\n };\n\n const handleConfirmDelete = async () => {\n if (!deleteDocument || selectedForDelete.size === 0) return;\n\n setIsDeleting(true);\n try {\n const deletePromises = Array.from(selectedForDelete).map((id) => deleteDocument(id));\n await Promise.all(deletePromises);\n\n setItems((prev) => prev.filter((item) => !selectedForDelete.has(item.id)));\n \n if (selectedItem && selectedForDelete.has(selectedItem.id)) {\n setSelectedItem(null);\n }\n\n setShowDeleteConfirm(false);\n setSelectedForDelete(new Set());\n setSelectMode(false);\n } catch (error) {\n console.error('Failed to delete documents:', error);\n } finally {\n setIsDeleting(false);\n }\n };\n\n const getIcon = (mimeType: string) => {\n if (mimeType === 'application/pdf') {\n return <FileText size={20} className={styles.pdfIcon} />;\n }\n return <File size={20} className={styles.fileIcon} />;\n };\n\n const isAllSelected = items.length > 0 && selectedForDelete.size === items.length;\n const isSomeSelected = selectedForDelete.size > 0 && selectedForDelete.size < items.length;\n\n // Edit View\n if (view === 'edit' && editingItem) {\n return (\n <Modal\n title=\"Edit Document Details\"\n onClose={handleClose}\n size=\"small\"\n headerLeft={\n <button\n type=\"button\"\n onClick={() => {\n setView('picker');\n setEditingItem(null);\n setTitleValues({});\n }}\n className={styles.backButton}\n aria-label=\"Back to list\"\n >\n <ArrowLeft size={20} />\n </button>\n }\n footer={\n <div className={styles.editFooter}>\n <div />\n <button\n type=\"button\"\n onClick={handleSaveTitle}\n className={styles.saveButton}\n disabled={isSaving || !update}\n >\n {isSaving ? (\n <>\n <Loader2 size={16} className={styles.spinner} />\n Saving...\n </>\n ) : (\n 'Save'\n )}\n </button>\n </div>\n }\n >\n <div className={styles.editContent}>\n <div className={styles.editPreview}>\n <div className={styles.editIcon}>\n {getIcon(editingItem.mimeType)}\n </div>\n </div>\n\n <div className={styles.editInfo}>\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Filename</span>\n <span className={styles.editInfoValue}>{editingItem.filename}</span>\n </div>\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Type</span>\n <span className={styles.editInfoValue}>\n {editingItem.extension?.toUpperCase()}\n </span>\n </div>\n <div className={styles.editInfoRow}>\n <span className={styles.editInfoLabel}>Size</span>\n <span className={styles.editInfoValue}>\n {formatFileSize(editingItem.size)}\n </span>\n </div>\n </div>\n\n <div className={styles.editField}>\n <div className={styles.editFieldHeader}>\n <label className={styles.editFieldLabel}>Title</label>\n <div className={styles.langTabs}>\n {languages.map((lang) => (\n <button\n key={lang.code}\n type=\"button\"\n onClick={() => setActiveLang(lang.code)}\n className={`${styles.langTab} ${activeLang === lang.code ? styles.langTabActive : ''}`}\n >\n {lang.code.toUpperCase()}\n </button>\n ))}\n </div>\n </div>\n <input\n type=\"text\"\n value={titleValues[activeLang] || ''}\n onChange={(e) => handleTitleChange(activeLang, e.target.value)}\n placeholder={`Title in ${languages.find(l => l.code === activeLang)?.label || activeLang}...`}\n className={styles.editInput}\n />\n </div>\n </div>\n </Modal>\n );\n }\n\n // Picker View\n const renderFooter = () => {\n if (selectMode) {\n return (\n <SelectionToolbar\n selectedCount={selectedForDelete.size}\n totalCount={items.length}\n onSelectAll={handleSelectAll}\n onCancel={() => {\n setSelectMode(false);\n setSelectedForDelete(new Set());\n }}\n onDelete={() => setShowDeleteConfirm(true)}\n isAllSelected={isAllSelected}\n isIndeterminate={isSomeSelected}\n />\n );\n }\n\n if (selectedItem && selectable) {\n return (\n <div className={styles.footer}>\n <div className={styles.footerInfo}>\n <div className={styles.footerIcon}>\n {getIcon(selectedItem.mimeType)}\n </div>\n <span className={styles.footerFilename}>\n {selectedItem.filename}\n </span>\n <span className={styles.footerMeta}>\n {selectedItem.extension?.toUpperCase()} - {formatFileSize(selectedItem.size)}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={handleConfirmSelection}\n className={styles.selectButton}\n >\n Select Document\n </button>\n </div>\n );\n }\n\n return undefined;\n };\n\n return (\n <Modal\n title={title}\n onClose={handleClose}\n size=\"small\"\n headerActions={\n !selectMode && deleteDocument ? (\n <button\n type=\"button\"\n onClick={() => setSelectMode(true)}\n className={styles.selectModeButton}\n >\n Select Items\n </button>\n ) : undefined\n }\n toolbar={\n <div className={styles.toolbar}>\n <SearchBar\n value={search}\n onChange={setSearch}\n placeholder=\"Search documents...\"\n autoFocus={!selectMode}\n />\n </div>\n }\n footer={renderFooter()}\n overlay={\n showDeleteConfirm ? (\n <ConfirmDialog\n title=\"Delete Documents\"\n message={`Are you sure you want to delete ${selectedForDelete.size} document${selectedForDelete.size > 1 ? 's' : ''}? This action cannot be undone.`}\n confirmLabel={isDeleting ? 'Deleting...' : `Delete ${selectedForDelete.size} document${selectedForDelete.size > 1 ? 's' : ''}`}\n onConfirm={handleConfirmDelete}\n onCancel={() => setShowDeleteConfirm(false)}\n loading={isDeleting}\n variant=\"danger\"\n />\n ) : undefined\n }\n loading={loading && items.length === 0}\n empty={!loading && items.length === 0}\n emptyMessage=\"No documents found\"\n >\n {canUpload && !selectMode && (\n <div className={styles.uploadSection}>\n <UploadDropzone\n onFilesSelected={addFiles}\n config={mergedUploadConfig}\n disabled={isUploading && uploading.length >= 10}\n />\n {uploading.length > 0 && (\n <UploadQueue\n files={uploading}\n onCancel={cancelUpload}\n onClearCompleted={clearCompleted}\n />\n )}\n </div>\n )}\n\n <div className={styles.documentList}>\n {items.map((item) => {\n const isSelected = selectMode \n ? selectedForDelete.has(item.id)\n : selectedItem?.id === item.id;\n \n return (\n <div key={item.id} className={styles.documentItemContainer}>\n <button\n type=\"button\"\n onClick={() => handleDocumentClick(item)}\n className={`${styles.documentItem} ${isSelected ? styles.selected : ''}`}\n >\n {selectMode && (\n <div className={`${styles.checkbox} ${isSelected ? styles.checkboxChecked : ''}`}>\n {isSelected && <Check size={14} strokeWidth={3} />}\n </div>\n )}\n <div className={styles.documentIcon}>\n {getIcon(item.mimeType)}\n </div>\n <div className={styles.documentInfo}>\n <span className={styles.documentName}>\n {item.title?.[languages[0]?.code] || item.filename}\n </span>\n <span className={styles.documentMeta}>\n {item.extension?.toUpperCase()} - {formatFileSize(item.size)}\n </span>\n </div>\n {!selectMode && selectedItem?.id === item.id && (\n <div className={styles.checkmark}>\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M13.5 4.5L6 12L2.5 8.5\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </div>\n )}\n </button>\n {!selectMode && update && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleEditTitle(item);\n }}\n className={styles.editButton}\n aria-label=\"Edit title\"\n >\n <Pencil size={14} />\n </button>\n )}\n </div>\n );\n })}\n </div>\n\n {hasMore && (\n <LoadMoreButton onClick={handleLoadMore} loading={loading} />\n )}\n </Modal>\n );\n}\n","/* Header Buttons */\n.backButton {\n padding: 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n}\n\n.backButton:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n.selectModeButton {\n padding: 8px 16px;\n background: #f5f5f5;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.selectModeButton:hover {\n background: #ebebeb;\n border-color: #d4d4d4;\n}\n\n/* Toolbar */\n.toolbar {\n display: flex;\n gap: 12px;\n}\n\n/* Upload Section */\n.uploadSection {\n margin-bottom: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* Document List */\n.documentList {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.documentItemContainer {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.documentItem {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n cursor: pointer;\n text-align: left;\n transition: border-color 0.15s, background 0.15s;\n}\n\n.documentItem:hover {\n border-color: #3b82f6;\n background: #f9fafb;\n}\n\n.documentItem.selected {\n border-color: #3b82f6;\n background: #eff6ff;\n}\n\n.checkbox {\n width: 20px;\n height: 20px;\n border: 2px solid #d4d4d4;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.checkboxChecked {\n background: #3b82f6;\n border-color: #3b82f6;\n color: white;\n}\n\n.documentIcon {\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #f5f5f5;\n border-radius: 6px;\n}\n\n.pdfIcon {\n color: #dc2626;\n}\n\n.fileIcon {\n color: #737373;\n}\n\n.documentInfo {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.documentName {\n font-size: 14px;\n font-weight: 500;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.documentMeta {\n font-size: 12px;\n color: #737373;\n}\n\n.checkmark {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n background: #3b82f6;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n}\n\n.editButton {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n padding: 8px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 6px;\n cursor: pointer;\n color: #737373;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s, color 0.15s;\n}\n\n.documentItemContainer:hover .editButton {\n opacity: 1;\n}\n\n.editButton:hover {\n background: #f5f5f5;\n color: #171717;\n}\n\n/* Footer */\n.footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n width: 100%;\n}\n\n.footerInfo {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n}\n\n.footerIcon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n border-radius: 6px;\n border: 1px solid #e5e5e5;\n flex-shrink: 0;\n}\n\n.footerFilename {\n font-size: 13px;\n font-weight: 500;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.footerMeta {\n font-size: 12px;\n color: #737373;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.selectButton {\n padding: 10px 20px;\n background: #3b82f6;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n flex-shrink: 0;\n}\n\n.selectButton:hover {\n background: #2563eb;\n}\n\n/* Edit View */\n.editContent {\n display: flex;\n flex-direction: column;\n gap: 24px;\n}\n\n.editPreview {\n display: flex;\n justify-content: center;\n align-items: center;\n background: #f5f5f5;\n border-radius: 8px;\n padding: 40px;\n}\n\n.editIcon {\n width: 80px;\n height: 80px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n border-radius: 12px;\n border: 1px solid #e5e5e5;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n.editIcon svg {\n width: 40px;\n height: 40px;\n}\n\n.editInfo {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 16px;\n background: #fafafa;\n border-radius: 8px;\n}\n\n.editInfoRow {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.editInfoLabel {\n font-size: 13px;\n font-weight: 500;\n color: #737373;\n min-width: 80px;\n}\n\n.editInfoValue {\n font-size: 13px;\n color: #171717;\n}\n\n.editField {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.editFieldHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n\n.editFieldLabel {\n font-size: 14px;\n font-weight: 600;\n color: #171717;\n margin: 0;\n}\n\n.langTabs {\n display: flex;\n gap: 2px;\n background: #e5e5e5;\n border-radius: 6px;\n padding: 3px;\n}\n\n.langTab {\n padding: 6px 12px;\n font-size: 12px;\n font-weight: 600;\n color: #737373;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n}\n\n.langTab:hover {\n color: #525252;\n}\n\n.langTabActive {\n background: white;\n color: #171717;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n\n.editInput {\n padding: 12px 14px;\n border: 1px solid #e5e5e5;\n border-radius: 8px;\n font-size: 14px;\n background: white;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.editInput:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.editInput::placeholder {\n color: #a3a3a3;\n}\n\n.editFooter {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n}\n\n.saveButton {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n background: #10b981;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n color: white;\n cursor: pointer;\n transition: background 0.15s;\n}\n\n.saveButton:hover:not(:disabled) {\n background: #059669;\n}\n\n.saveButton:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.spinner {\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Mobile Responsive */\n@media (max-width: 640px) {\n .footer {\n flex-direction: column;\n gap: 12px;\n }\n\n .footerInfo {\n width: 100%;\n }\n\n .selectButton {\n width: 100%;\n }\n\n .editInfoRow {\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n }\n\n .editInfoLabel {\n min-width: auto;\n }\n}\n",".container {\n margin-top: 8px;\n}\n\n.preview {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n border-radius: 6px;\n border: 1px solid #e5e5e5;\n background: #fafafa;\n}\n\n.iconWrapper {\n flex-shrink: 0;\n width: 40px;\n height: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: white;\n border-radius: 6px;\n border: 1px solid #e5e5e5;\n}\n\n.pdfIcon {\n color: #dc2626;\n}\n\n.fileIcon {\n color: #737373;\n}\n\n.info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.title {\n font-size: 13px;\n font-weight: 500;\n color: #171717;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.meta {\n font-size: 11px;\n color: #737373;\n}\n\n.actions {\n flex-shrink: 0;\n display: flex;\n gap: 6px;\n}\n\n.changeButton {\n padding: 6px 12px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n color: #525252;\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.changeButton:hover {\n background: #f5f5f5;\n border-color: #d4d4d4;\n}\n\n.removeButton {\n padding: 6px;\n background: white;\n border: 1px solid #e5e5e5;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #dc2626;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.removeButton:hover {\n background: #fee2e2;\n border-color: #fecaca;\n}\n\n.selectButton {\n width: 100%;\n padding: 24px 16px;\n border: 2px dashed #d4d4d4;\n border-radius: 6px;\n background: transparent;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n color: #737373;\n font-size: 13px;\n transition: border-color 0.15s, color 0.15s, background 0.15s;\n}\n\n.selectButton:hover {\n border-color: #3b82f6;\n color: #3b82f6;\n background: #eff6ff;\n}\n\n.selectButton:focus {\n outline: none;\n border-color: #3b82f6;\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);\n}\n","import { useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Image, Images, FileText } from 'lucide-react';\nimport { ImagePickerModal } from '../ImagePickerModal/ImagePickerModal';\nimport { GalleryPickerModal } from '../GalleryPickerModal/GalleryPickerModal';\nimport { DocumentPickerModal } from '../DocumentPickerModal/DocumentPickerModal';\nimport type { Language, ImageOptions, GalleryOptions, DocumentOptions } from '../../types';\nimport styles from './MediaPanel.module.css';\n\nexport interface MediaPanelProps {\n languages: Language[];\n imageOptions: ImageOptions;\n galleryOptions?: GalleryOptions;\n documentOptions?: DocumentOptions;\n}\n\ntype ModalType = 'image' | 'gallery' | 'document' | null;\n\nexport function MediaPanel({\n languages,\n imageOptions,\n galleryOptions,\n documentOptions,\n}: MediaPanelProps) {\n const [openModal, setOpenModal] = useState<ModalType>(null);\n\n const handleCloseModal = () => {\n setOpenModal(null);\n };\n\n return (\n <div className={styles.panel}>\n <button\n type=\"button\"\n className={styles.item}\n onClick={() => setOpenModal('image')}\n >\n <Image size={20} />\n <span>Images</span>\n </button>\n\n {galleryOptions && (\n <button\n type=\"button\"\n className={styles.item}\n onClick={() => setOpenModal('gallery')}\n >\n <Images size={20} />\n <span>Gallery</span>\n </button>\n )}\n\n {documentOptions && (\n <button\n type=\"button\"\n className={styles.item}\n onClick={() => setOpenModal('document')}\n >\n <FileText size={20} />\n <span>Documents</span>\n </button>\n )}\n\n {openModal === 'image' && createPortal(\n <ImagePickerModal\n languages={languages}\n imageOptions={imageOptions}\n title=\"Media Library\"\n selectable={false}\n onClose={handleCloseModal}\n />,\n document.body\n )}\n\n {openModal === 'gallery' && galleryOptions && createPortal(\n <GalleryPickerModal\n languages={languages}\n galleryOptions={galleryOptions}\n title=\"Gallery Library\"\n selectable={false}\n onClose={handleCloseModal}\n />,\n document.body\n )}\n\n {openModal === 'document' && documentOptions && createPortal(\n <DocumentPickerModal\n languages={languages}\n documentOptions={documentOptions}\n title=\"Document Library\"\n selectable={false}\n onClose={handleCloseModal}\n />,\n document.body\n )}\n </div>\n );\n}\n",".panel {\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 16px;\n background: var(--puck-color-grey-12, #f5f5f5);\n border: 1px solid var(--puck-color-grey-09, #e5e5e5);\n border-radius: 8px;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--puck-color-grey-02, #171717);\n transition: background 0.15s, border-color 0.15s;\n text-align: left;\n width: 100%;\n}\n\n.item:hover {\n background: var(--puck-color-grey-11, #ebebeb);\n border-color: var(--puck-color-grey-08, #d4d4d4);\n}\n\n.item:active {\n background: var(--puck-color-grey-10, #e0e0e0);\n}\n\n.item svg {\n flex-shrink: 0;\n color: var(--puck-color-grey-05, #737373);\n}\n\n.item:hover svg {\n color: var(--puck-color-grey-03, #525252);\n}\n","import type { ReactNode } from 'react';\n\n// =============================================================================\n// LANGUAGE CONFIGURATION\n// =============================================================================\n\n/**\n * Language configuration for multilingual fields\n */\nexport interface Language {\n code: string;\n label: string;\n}\n\n/**\n * Default languages when not specified\n */\nexport const DEFAULT_LANGUAGES: Language[] = [\n { code: 'en', label: 'English' },\n { code: 'it', label: 'Italiano' },\n];\n\n/**\n * Localized string value (e.g., { en: 'Hello', it: 'Ciao' })\n */\nexport type LocalizedString = Record<string, string | undefined>;\n\n// =============================================================================\n// IMAGE TYPES\n// =============================================================================\n\n/**\n * Image item - used both for API responses and stored values in Puck JSON\n */\nexport interface ImageItem {\n /** Unique identifier */\n id: string;\n /** Full URL to the image file */\n url: string;\n /** Original filename */\n filename?: string;\n /** Alt text (multilingual) */\n alt?: LocalizedString;\n /** Image width in pixels */\n width?: number;\n /** Image height in pixels */\n height?: number;\n /** File size in bytes */\n size?: number;\n /** Thumbnail URL for faster loading in picker (falls back to url if not provided) */\n thumbnailUrl?: string;\n /** Creation date (useful for cache invalidation) */\n createdAt?: string;\n}\n\n// =============================================================================\n// DOCUMENT TYPES\n// =============================================================================\n\n/**\n * Document item - used both for API responses and stored values in Puck JSON\n */\nexport interface DocumentItem {\n /** Unique identifier */\n id: string;\n /** Full URL to the document file */\n url: string;\n /** Original filename */\n filename: string;\n /** Display title (multilingual) */\n title?: LocalizedString;\n /** MIME type (e.g., 'application/pdf') */\n mimeType: string;\n /** File size in bytes */\n size: number;\n /** File extension (e.g., 'pdf', 'docx') */\n extension: string;\n /** Creation date (useful for cache invalidation) */\n createdAt?: string;\n}\n\n// =============================================================================\n// GALLERY TYPES\n// =============================================================================\n\n/**\n * Gallery item - used both for API responses and stored values in Puck JSON\n */\nexport interface GalleryItem {\n /** Unique identifier */\n id: string;\n /** Gallery name */\n name: string;\n /** Cover image for preview */\n coverImage?: ImageItem;\n /** Images in the gallery */\n images: ImageItem[];\n /** Number of images in the gallery (optional, can be calculated from images.length) */\n imageCount?: number;\n /** Creation date (useful for cache invalidation) */\n createdAt?: string;\n}\n\n// =============================================================================\n// FETCH/UPLOAD TYPES\n// =============================================================================\n\n/**\n * Parameters passed to fetchList functions\n */\nexport interface FetchListParams {\n /** Search query string */\n query?: string;\n /** Page number (1-indexed) */\n page?: number;\n /** Items per page */\n pageSize?: number;\n /** Additional filters */\n filters?: Record<string, unknown>;\n}\n\n/**\n * Result from fetchList - paginated result\n */\nexport interface FetchListResult<T> {\n /** Array of items */\n items: T[];\n /** Total number of items (for pagination) */\n total?: number;\n /** Whether there are more items to load */\n hasMore?: boolean;\n}\n\n/**\n * Generic fetch list function type\n */\nexport type FetchListFn<T> = (\n params: FetchListParams\n) => Promise<T[] | FetchListResult<T>>;\n\n/**\n * Callbacks passed to upload functions\n */\nexport interface UploadCallbacks {\n /** Called with upload progress (0-100) */\n onProgress: (percent: number) => void;\n}\n\n/**\n * Upload function that handles single or multiple files\n */\nexport type UploadFn<T> = (\n files: File | File[],\n callbacks: UploadCallbacks\n) => Promise<T | T[]>;\n\n/**\n * Configuration for file uploads\n */\nexport interface UploadConfig {\n /**\n * Accepted file types (MIME types or extensions)\n * @default 'image/*' for images, '*' for documents\n */\n accept?: string;\n\n /**\n * Maximum file size in bytes\n * @default 10485760 (10MB)\n */\n maxSize?: number;\n\n /**\n * Allow multiple file uploads\n * @default true\n */\n multiple?: boolean;\n}\n\n/**\n * Status of a file being uploaded\n */\nexport type UploadStatus = 'pending' | 'uploading' | 'completed' | 'error';\n\n/**\n * State of a file in the upload queue\n */\nexport interface UploadingFile {\n /** Unique ID for this upload */\n id: string;\n /** The file being uploaded */\n file: File;\n /** Upload progress (0-100) */\n progress: number;\n /** Current upload status */\n status: UploadStatus;\n /** Error message if status is 'error' */\n error?: string;\n /** Resulting item if status is 'completed' */\n result?: ImageItem | DocumentItem;\n /** Preview URL for the file (blob URL) */\n previewUrl?: string;\n}\n\n// =============================================================================\n// PLUGIN OPTIONS\n// =============================================================================\n\n/**\n * Image-related callbacks\n */\nexport interface ImageOptions {\n /** Function to fetch image list from your API */\n fetchList: FetchListFn<ImageItem>;\n /** Function to upload images (optional) */\n upload?: UploadFn<ImageItem>;\n /** Function to update image metadata (alt text) */\n update?: (id: string, data: { alt?: LocalizedString }) => Promise<ImageItem>;\n /** Function to delete an image (optional) */\n delete?: (id: string) => Promise<void>;\n /** Configuration for file uploads */\n uploadConfig?: UploadConfig;\n}\n\n/**\n * Gallery-related callbacks\n */\nexport interface GalleryOptions {\n /** Function to fetch gallery list from your API (required) */\n fetchList: FetchListFn<GalleryItem>;\n /** Function to fetch a single gallery by ID */\n fetch: (id: string) => Promise<GalleryItem>;\n /** Function to create a new gallery */\n create: (name: string) => Promise<GalleryItem>;\n /** Function to delete a gallery */\n delete: (id: string) => Promise<void>;\n /** Function to upload images to a gallery */\n upload: (\n galleryId: string,\n files: File | File[],\n callbacks: UploadCallbacks\n ) => Promise<ImageItem | ImageItem[]>;\n /** Function to remove an image from a gallery */\n removeImage: (galleryId: string, imageId: string) => Promise<void>;\n /** Function to update image metadata within a gallery (optional - hides alt editing if not provided) */\n updateImage?: (\n galleryId: string,\n imageId: string,\n data: { alt?: LocalizedString }\n ) => Promise<ImageItem>;\n}\n\n/**\n * Document-related callbacks\n */\nexport interface DocumentOptions {\n /** Function to fetch document list from your API */\n fetchList: FetchListFn<DocumentItem>;\n /** Function to upload documents (optional - hides upload area if not provided) */\n upload?: UploadFn<DocumentItem>;\n /** Function to update document metadata (title) (optional - hides edit icon if not provided) */\n update?: (id: string, data: { title?: LocalizedString }) => Promise<DocumentItem>;\n /** Function to delete a document (optional - hides manage button if not provided) */\n delete?: (id: string) => Promise<void>;\n /** Configuration for file uploads */\n uploadConfig?: UploadConfig;\n}\n\n/**\n * Plugin configuration options\n */\nexport interface MediaPluginOptions {\n /**\n * Languages for multilingual fields (alt, title)\n * @default [{ code: 'it', label: 'Italiano' }, { code: 'en', label: 'English' }]\n */\n languages?: Language[];\n\n /**\n * Image-related configuration (required)\n */\n image: ImageOptions;\n\n /**\n * Gallery-related configuration (optional)\n */\n gallery?: GalleryOptions;\n\n /**\n * Document-related configuration (optional)\n */\n document?: DocumentOptions;\n}\n\n// =============================================================================\n// COMPONENT PROPS\n// =============================================================================\n\n/**\n * Internal props passed to ImageField component\n */\nexport interface ImageFieldProps {\n name: string;\n value: ImageItem | null;\n onChange: (value: ImageItem | null) => void;\n field: {\n label?: string;\n [key: string]: unknown;\n };\n languages: Language[];\n imageOptions: ImageOptions;\n}\n\n/**\n * Internal props passed to GalleryField component\n */\nexport interface GalleryFieldProps {\n name: string;\n value: GalleryItem | null;\n onChange: (value: GalleryItem | null) => void;\n field: {\n label?: string;\n [key: string]: unknown;\n };\n languages: Language[];\n galleryOptions: GalleryOptions;\n}\n\n/**\n * Internal props passed to DocumentField component\n */\nexport interface DocumentFieldProps {\n name: string;\n value: DocumentItem | null;\n onChange: (value: DocumentItem | null) => void;\n field: {\n label?: string;\n [key: string]: unknown;\n };\n languages: Language[];\n documentOptions: DocumentOptions;\n}\n\n/**\n * Props for ImagePickerModal component\n */\nexport interface ImagePickerModalProps {\n languages: Language[];\n imageOptions: ImageOptions;\n title?: string;\n selectedImage?: ImageItem | null;\n onSelect?: (item: ImageItem) => void;\n onClose: () => void;\n /** When false, hides the \"Select Image\" button. Useful for media library mode. Default: true */\n selectable?: boolean;\n}\n\n/**\n * Props for GalleryPickerModal component\n */\nexport interface GalleryPickerModalProps {\n languages: Language[];\n galleryOptions: GalleryOptions;\n title?: string;\n selectedGallery?: GalleryItem | null;\n onSelect?: (gallery: GalleryItem) => void;\n onClose: () => void;\n /** When false, hides the \"Select Gallery\" button. Useful for media library mode. Default: true */\n selectable?: boolean;\n}\n\n/**\n * Props for DocumentPickerModal component\n */\nexport interface DocumentPickerModalProps {\n languages: Language[];\n documentOptions: DocumentOptions;\n title?: string;\n selectedDocument?: DocumentItem | null;\n onSelect?: (item: DocumentItem) => void;\n onClose: () => void;\n /** When false, hides the \"Select Document\" button. Useful for media library mode. Default: true */\n selectable?: boolean;\n}\n\n/**\n * Props for ImageGrid component\n */\nexport interface ImageGridProps {\n items: ImageItem[];\n onSelect: (item: ImageItem) => void;\n selectedId?: string;\n loading?: boolean;\n /** Callback when user clicks edit icon */\n onEditAlt?: (item: ImageItem) => void;\n /** Whether manage mode is active (for bulk delete) */\n manageMode?: boolean;\n /** Set of selected item IDs for bulk operations */\n selectedIds?: Set<string>;\n /** Callback when user toggles selection in manage mode */\n onToggleSelect?: (item: ImageItem) => void;\n}\n\n/**\n * Props for GalleryList component\n */\nexport interface GalleryListProps {\n items: GalleryItem[];\n onSelect: (item: GalleryItem) => void;\n onDelete?: (item: GalleryItem) => void;\n selectedId?: string;\n loading?: boolean;\n}\n\n/**\n * Props for DocumentList component\n */\nexport interface DocumentListProps {\n items: DocumentItem[];\n onSelect: (item: DocumentItem) => void;\n selectedId?: string;\n loading?: boolean;\n}\n\n// =============================================================================\n// PUCK PLUGIN TYPE\n// =============================================================================\n\n/**\n * Puck Plugin type\n */\nexport interface PuckPlugin {\n name: string;\n label?: string;\n icon?: ReactNode;\n render?: () => ReactNode;\n overrides?: {\n fieldTypes?: Record<string, (props: unknown) => ReactNode>;\n [key: string]: unknown;\n };\n}\n"],"mappings":"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","names":["import_lucide_react","import_react","import_lucide_react","import_react","import_lucide_react","backdrop","fadeIn","modal","slideUp","small","header","title","headerActions","closeButton","toolbar","content","loading","spinner","spin","empty","footer","import_react","import_lucide_react","container","icon","input","clearButton","import_jsx_runtime","import_lucide_react","container","button","spinner","spin","import_jsx_runtime","import_react","import_lucide_react","overlay","fadeIn","dialog","slideUp","title","message","actions","cancelButton","confirmButton","danger","spinner","spin","import_jsx_runtime","import_lucide_react","toolbar","selectAllButton","checkbox","checked","indeterminate","indeterminateLine","actions","cancelButton","deleteButton","import_jsx_runtime","import_lucide_react","grid","itemContainer","item","selected","imageWrapper","image","checkmark","checkbox","checkboxChecked","info","infoRow","infoText","filename","meta","editButton","import_jsx_runtime","formatFileSize","import_react","import_lucide_react","import_react","dropzone","disabled","dragging","input","icon","text","hint","import_jsx_runtime","import_lucide_react","container","header","title","clearButton","list","item","preview","previewImage","previewPlaceholder","progressOverlay","progressBar","progressText","info","filename","size","error","actions","cancelButton","spinner","spin","successIcon","errorIcon","completed","import_jsx_runtime","backButton","selectModeButton","toolbar","uploadSection","footer","footerInfo","footerImage","footerFilename","footerMeta","selectButton","editContent","editPreview","editImage","editInfo","editInfoRow","editInfoLabel","editInfoValue","editField","editFieldHeader","editFieldLabel","langTabs","langTab","langTabActive","editInput","editFooter","saveButton","spinner","spin","import_jsx_runtime","formatFileSize","container","preview","image","overlay","changeButton","removeButton","selectButton","import_jsx_runtime","import_react","import_react_dom","import_core","import_lucide_react","import_react","import_lucide_react","backButton","selectModeButton","toolbar","createButton","createForm","createInput","createSubmitButton","createCancelButton","uploadSection","galleryGrid","galleryCard","galleryCardButton","selected","checkbox","checkboxChecked","galleryCover","galleryCoverPlaceholder","galleryInfo","galleryName","galleryCount","footer","footerInfo","footerText","selectButton","editContent","editPreview","editImage","editInfo","editInfoRow","editInfoLabel","editInfoValue","editField","editFieldHeader","editFieldLabel","langTabs","langTab","langTabActive","editInput","editFooter","saveButton","spinner","spin","import_jsx_runtime","DEFAULT_UPLOAD_CONFIG","PAGE_SIZE","formatFileSize","container","preview","header","name","count","thumbnails","thumbnail","more","actions","changeButton","removeButton","selectButton","import_jsx_runtime","import_react","import_react_dom","import_core","import_lucide_react","import_react","import_lucide_react","backButton","selectModeButton","toolbar","uploadSection","documentList","documentItemContainer","documentItem","selected","checkbox","checkboxChecked","documentIcon","pdfIcon","fileIcon","documentInfo","documentName","documentMeta","checkmark","editButton","footer","footerInfo","footerIcon","footerFilename","footerMeta","selectButton","editContent","editPreview","editIcon","editInfo","editInfoRow","editInfoLabel","editInfoValue","editField","editFieldHeader","editFieldLabel","langTabs","langTab","langTabActive","editInput","editFooter","saveButton","spinner","spin","import_jsx_runtime","DEFAULT_UPLOAD_CONFIG","PAGE_SIZE","container","preview","iconWrapper","pdfIcon","fileIcon","info","title","meta","actions","changeButton","removeButton","selectButton","import_jsx_runtime","import_react","import_react_dom","import_lucide_react","panel","item","import_jsx_runtime","import_jsx_runtime","document"]}