ultisuite-client/lib/drive/drive-drag-preview.tsx
R3D347HR4Y 6ec95262af Add OnlyOffice integration and update project configurations
- Updated .env.example to include configuration for OnlyOffice Document Server.
- Modified the workspace configuration to remove the drive-suite path.
- Adjusted TypeScript environment imports for consistency.
- Enhanced Next.js configuration to disable canvas in Webpack.
- Updated package.json to include new dependencies for OnlyOffice and PDF.js.
- Added global styles for OnlyOffice theme integration in the CSS.
- Created new layout and page components for the Drive feature, including public sharing and editing functionalities.
- Updated metadata handling across various layouts to reflect the new app structure.
2026-06-07 15:49:21 +02:00

139 lines
3.8 KiB
TypeScript

"use client"
import type { DriveFileInfo } from "@/lib/api/types"
import { displayFileName } from "@/lib/drive/display-file-name"
import {
driveFolderIconMeta,
driveMimeCategoryFor,
driveMimeIconMeta,
} from "@/lib/drive/drive-file-icon"
const PREVIEW_WIDTH_PX = 200
const PREVIEW_HEIGHT_PX = 48
const ICON_COLOR_HEX: Record<string, string> = {
"text-amber-500": "#f59e0b",
"text-amber-600": "#d97706",
"text-blue-500": "#3b82f6",
"text-blue-600": "#2563eb",
"text-green-600": "#16a34a",
"text-red-500": "#ef4444",
"text-red-600": "#dc2626",
"text-rose-500": "#f43f5e",
"text-[#5f6368]": "#5f6368",
}
let activePreview: HTMLElement | null = null
function iconMetaForFile(file: DriveFileInfo) {
const category = driveMimeCategoryFor(file)
if (category === "folder") return driveFolderIconMeta(file)
return driveMimeIconMeta(category)
}
function iconifySvgUrl(iconId: string, colorHex: string) {
const [prefix, name] = iconId.split(":")
return `https://api.iconify.design/${prefix}/${name}.svg?width=24&height=24&color=${encodeURIComponent(colorHex)}`
}
function appendTypeIcon(
root: HTMLElement,
file: DriveFileInfo,
dragSourceEl: HTMLElement | null
) {
const iconSlot = document.createElement("span")
iconSlot.setAttribute("data-drive-type-icon", "")
iconSlot.style.cssText =
"display:inline-flex;width:20px;height:20px;flex-shrink:0;align-items:center;justify-content:center;"
const cardRoot =
dragSourceEl?.closest("[data-drive-card]") ?? dragSourceEl ?? null
const liveSvg = cardRoot?.querySelector("[data-drive-type-icon] svg")
if (liveSvg) {
const svg = liveSvg.cloneNode(true) as SVGElement
svg.setAttribute("width", "20")
svg.setAttribute("height", "20")
svg.style.width = "20px"
svg.style.height = "20px"
iconSlot.appendChild(svg)
} else {
const { icon, color } = iconMetaForFile(file)
const img = document.createElement("img")
img.src = iconifySvgUrl(icon, ICON_COLOR_HEX[color] ?? "#5f6368")
img.width = 20
img.height = 20
img.alt = ""
img.draggable = false
img.style.display = "block"
iconSlot.appendChild(img)
}
root.appendChild(iconSlot)
}
function buildPreviewElement(
files: DriveFileInfo[],
dragSourceEl: HTMLElement | null
): HTMLElement {
const primary = files[0]
const label =
files.length === 1
? displayFileName(primary.name)
: `${files.length} élément${files.length > 1 ? "s" : ""}`
const root = document.createElement("div")
root.style.cssText = [
`width:${PREVIEW_WIDTH_PX}px`,
`height:${PREVIEW_HEIGHT_PX}px`,
"box-sizing:border-box",
"display:flex",
"align-items:center",
"gap:12px",
"padding:0 12px",
"border-radius:12px",
"border:1px solid rgba(232,234,237,0.8)",
"background:#f8f9fa",
"box-shadow:0 2px 8px rgba(60,64,67,0.28)",
"font-family:system-ui,sans-serif",
"font-size:14px",
"font-weight:500",
"color:#3c4043",
"pointer-events:none",
].join(";")
appendTypeIcon(root, primary, dragSourceEl)
const text = document.createElement("span")
text.textContent = label
text.style.cssText =
"min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;"
root.appendChild(text)
return root
}
export function applyDriveDragPreview(
dataTransfer: DataTransfer,
files: DriveFileInfo[],
dragSourceEl: HTMLElement | null
): void {
removeDriveDragPreview()
if (files.length === 0) return
const root = buildPreviewElement(files, dragSourceEl)
root.style.position = "fixed"
root.style.left = "-9999px"
root.style.top = "0"
root.style.zIndex = "99999"
document.body.appendChild(root)
activePreview = root
dataTransfer.setDragImage(root, PREVIEW_WIDTH_PX / 2, PREVIEW_HEIGHT_PX / 2)
}
export function removeDriveDragPreview(): void {
activePreview?.remove()
activePreview = null
}