desk view
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
background: #7a7c7c;
|
||||
background-color: var(--surface-subtle);
|
||||
}
|
||||
|
||||
.skeuo-header {
|
||||
@@ -21,7 +21,7 @@
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.75rem 1rem 0.5rem;
|
||||
background-color: var(--surface-subtle, rgba(255, 255, 255, 0.08));
|
||||
background-color: var(--surface-subtle);
|
||||
}
|
||||
|
||||
.skeuo-header__meta {
|
||||
@@ -277,6 +277,20 @@ body.skeuo-cursor-remove * {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skeuo-item__card--empty {
|
||||
background:
|
||||
radial-gradient(circle at 28% 24%, rgba(255, 255, 255, 0.32), transparent 60%),
|
||||
radial-gradient(circle at 72% 78%, rgba(0, 0, 0, 0.08), transparent 65%),
|
||||
linear-gradient(135deg, #e6e1d6 0%, #d2cdc2 100%);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.skeuo-item__card img {
|
||||
}
|
||||
|
||||
@@ -286,3 +300,25 @@ body.skeuo-cursor-remove * {
|
||||
letter-spacing: normal;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.skeuo-item__empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.skeuo-item__title {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
color: #3b3b3b;
|
||||
max-width: 90%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,10 @@ 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_WIDTH_MIN = 200;
|
||||
const CARD_WIDTH_MAX = 260;
|
||||
const CARD_HEIGHT_MIN = 240;
|
||||
const CARD_HEIGHT_MAX = 340;
|
||||
const CARD_ASPECT_MIN = 0.8; // height / width
|
||||
const CARD_ASPECT_MAX = 1.35;
|
||||
const ZOOM_FILL_RATIO = 0.97;
|
||||
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;
|
||||
@@ -554,54 +551,40 @@ const SkeuomorphicWorkspace = ({
|
||||
|
||||
const intrinsic = resolvePreviewDimensions(doc);
|
||||
if (intrinsic?.width && intrinsic?.height) {
|
||||
const ratio = intrinsic.height / intrinsic.width || 1;
|
||||
width = intrinsic.width;
|
||||
height = intrinsic.height;
|
||||
|
||||
// scale down to fit within max bounds
|
||||
if (width > CARD_WIDTH_MAX || height > CARD_HEIGHT_MAX) {
|
||||
const scale = Math.min(CARD_WIDTH_MAX / width, CARD_HEIGHT_MAX / height);
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
}
|
||||
|
||||
// scale up to satisfy minimum bounds while respecting ratio
|
||||
if (width < CARD_WIDTH_MIN || height < CARD_HEIGHT_MIN) {
|
||||
const scale = Math.max(CARD_WIDTH_MIN / width, CARD_HEIGHT_MIN / height);
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
if (width > CARD_WIDTH_MAX || height > CARD_HEIGHT_MAX) {
|
||||
const downScale = Math.min(CARD_WIDTH_MAX / width, CARD_HEIGHT_MAX / height);
|
||||
width *= downScale;
|
||||
height *= downScale;
|
||||
}
|
||||
}
|
||||
|
||||
width = clamp(width, CARD_WIDTH_MIN, CARD_WIDTH_MAX);
|
||||
height = clamp(height, CARD_HEIGHT_MIN, CARD_HEIGHT_MAX);
|
||||
} else {
|
||||
const widthSeed = seededRandom(`${key}:width`);
|
||||
const ratioSeed = seededRandom(`${key}:ratio`);
|
||||
const ratio = CARD_ASPECT_MIN + ratioSeed * (CARD_ASPECT_MAX - CARD_ASPECT_MIN);
|
||||
width = CARD_WIDTH_MIN + widthSeed * (CARD_WIDTH_MAX - CARD_WIDTH_MIN);
|
||||
height = width * ratio;
|
||||
|
||||
if (width > CARD_WIDTH_MAX || height > CARD_HEIGHT_MAX) {
|
||||
const scale = Math.min(CARD_WIDTH_MAX / width, CARD_HEIGHT_MAX / height);
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
}
|
||||
|
||||
if (width < CARD_WIDTH_MIN || height < CARD_HEIGHT_MIN) {
|
||||
const scale = Math.max(CARD_WIDTH_MIN / width, CARD_HEIGHT_MIN / height);
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
}
|
||||
|
||||
width = clamp(width, CARD_WIDTH_MIN, CARD_WIDTH_MAX);
|
||||
height = clamp(height, CARD_HEIGHT_MIN, CARD_HEIGHT_MAX);
|
||||
const seed = seededRandom(`${key}:size`);
|
||||
width = CARD_MIN + seed * (Math.min(CARD_MAX, CARD_MAX / EMPTY_CARD_ASPECT) - CARD_MIN);
|
||||
width = clamp(width, CARD_MIN, Math.min(CARD_MAX, CARD_MAX / EMPTY_CARD_ASPECT));
|
||||
height = width * EMPTY_CARD_ASPECT;
|
||||
}
|
||||
|
||||
if (!Number.isFinite(width) || width <= 0) {
|
||||
width = CARD_MIN;
|
||||
}
|
||||
if (!Number.isFinite(height) || height <= 0) {
|
||||
height = CARD_MIN;
|
||||
}
|
||||
|
||||
const scaleDown = Math.min(1, CARD_MAX / width, CARD_MAX / height);
|
||||
width *= scaleDown;
|
||||
height *= scaleDown;
|
||||
|
||||
const minDim = Math.min(width, height);
|
||||
if (minDim < CARD_MIN) {
|
||||
const scaleUp = CARD_MIN / minDim;
|
||||
width *= scaleUp;
|
||||
height *= scaleUp;
|
||||
|
||||
const adjust = Math.min(1, CARD_MAX / width, CARD_MAX / height);
|
||||
width *= adjust;
|
||||
height *= adjust;
|
||||
}
|
||||
|
||||
width = clamp(width, CARD_MIN, CARD_MAX);
|
||||
height = clamp(height, CARD_MIN, CARD_MAX);
|
||||
|
||||
const size = { width, height };
|
||||
docSizeMapRef.current.set(key, size);
|
||||
return size;
|
||||
@@ -636,8 +619,8 @@ const SkeuomorphicWorkspace = ({
|
||||
(doc, cardWidth, cardHeight) => {
|
||||
const canvasWidth = canvasSize.width || DEFAULT_CANVAS_WIDTH;
|
||||
const canvasHeight = canvasSize.height || DEFAULT_CANVAS_HEIGHT;
|
||||
const safeCardWidth = cardWidth || CARD_WIDTH_MIN;
|
||||
const safeCardHeight = cardHeight || CARD_HEIGHT_MIN;
|
||||
const safeCardWidth = cardWidth || CARD_MIN;
|
||||
const safeCardHeight = cardHeight || CARD_MIN;
|
||||
const usableWidth = Math.max(canvasWidth - CANVAS_PADDING * 2, safeCardWidth);
|
||||
const usableHeight = Math.max(canvasHeight - CANVAS_PADDING * 2, safeCardHeight);
|
||||
const viewportTargetWidth = usableWidth * ZOOM_FILL_RATIO;
|
||||
@@ -1406,6 +1389,7 @@ const SkeuomorphicWorkspace = ({
|
||||
const tagsStyle = { '--tag-scale': inverseTagScale };
|
||||
const previewUrl = resolvePreviewUrl(doc);
|
||||
const imageUrl = previewUrl;
|
||||
const hasPreview = Boolean(imageUrl);
|
||||
const title = doc.title || doc.original_name || 'Document';
|
||||
const dragging = draggingId === doc.id;
|
||||
const tags = Array.isArray(doc.tags) ? doc.tags : [];
|
||||
@@ -1422,6 +1406,8 @@ const SkeuomorphicWorkspace = ({
|
||||
if (dropActive) itemClasses.push('is-tag-target');
|
||||
if (dropPending) itemClasses.push('is-tag-pending');
|
||||
if (!matchesFilter) itemClasses.push('is-filtered-out');
|
||||
const cardClasses = ['skeuo-item__card'];
|
||||
if (!hasPreview) cardClasses.push('skeuo-item__card--empty');
|
||||
const docTagTokens = docTagKeys.join(' ');
|
||||
return (
|
||||
<div
|
||||
@@ -1458,11 +1444,16 @@ const SkeuomorphicWorkspace = ({
|
||||
}}
|
||||
>
|
||||
<div className="skeuo-item__body" style={bodyStyle}>
|
||||
<div className="skeuo-item__card">
|
||||
{imageUrl ? (
|
||||
<div className={cardClasses.join(' ')}>
|
||||
{hasPreview ? (
|
||||
<img src={imageUrl} alt={title} />
|
||||
) : (
|
||||
<div className="skeuo-item__placeholder">DOC</div>
|
||||
<div className="skeuo-item__empty">
|
||||
<div className="skeuo-item__placeholder">DOC</div>
|
||||
<div className="skeuo-item__title" title={title}>
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{tags.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user