import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react'; import { resolveDocumentAssetUrl, createAssetView } from './asset_manager'; import { useAssetNavigator } from './hooks/useAssetNavigator'; import { ArrowLeftIcon, ArrowRightIcon } from './ui/icons'; import { getReadableTextColor } from './utils/colors'; import './skeuomorphic_ws.css'; const ITEM_WIDTH = 220; const ITEM_HEIGHT = 260; const CANVAS_PADDING = 24; const ROTATION_RANGE = 7; const JITTER_X = 26; const JITTER_Y = 32; const DEFAULT_CANVAS_WIDTH = 1024; const DEFAULT_CANVAS_HEIGHT = 680; const TAG_MIME_TYPES = ['application/x-papercrate-tag', 'text/papercrate-tag']; const resolveSizeKey = (doc) => doc?.id || doc?.document_id || doc?.uuid || doc?.original_name || doc?.title || 'doc'; const CARD_MIN = 240; const CARD_MAX = 340; const EMPTY_CARD_ASPECT = 1.4; const ZOOM_FILL_RATIO = 0.99; const ZOOM_MIN_SCALE = 1.05; const ZOOM_MAX_SCALE = 5; const TAG_REMOVE_DISTANCE = 160; const DEBUG_DRAG = false; const DEBUG_FOCUS = true; const DEBUG_DROP = true; const resolveTagKey = (tag) => { if (!tag) { return null; } const key = tag.id ?? tag.uuid ?? tag.slug ?? tag.label; return key != null ? String(key) : null; }; const SkeuoPreviewCard = ({ doc, title, ensureAssetUrl, getDocumentAsset, navScale = 1, prefetch = 3, }) => { const navigator = useAssetNavigator({ document: doc, assetType: 'preview', ensureAssetUrl, getAsset: getDocumentAsset, prefetch, }); const { currentUrl, cardinality, canGoPrev, canGoNext } = navigator; const hasPreview = Boolean(currentUrl); const cardClasses = ['skeuo-item__card']; if (!hasPreview) cardClasses.push('skeuo-item__card--empty'); const showNav = hasPreview && (cardinality > 1 || canGoPrev || canGoNext); const navStyle = useMemo(() => ({ '--nav-scale': navScale }), [navScale]); return (
No documents to show here yet. Drop files to make this space come alive.