linguabot commited on
Commit
5feb47c
·
verified ·
1 Parent(s): 0ad2920

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. client/src/components/Refinity.tsx +52 -12
client/src/components/Refinity.tsx CHANGED
@@ -94,6 +94,19 @@ const Refinity: React.FC = () => {
94
  return Math.min(Math.max(taskVersions.length - 1, 0), flowIndex);
95
  }, [taskVersions, currentVersionId, flowIndex]);
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  const uploadDocx = async (file: File) => {
98
  setUploading(true);
99
  try {
@@ -351,29 +364,56 @@ const Refinity: React.FC = () => {
351
  </div>
352
  </div>
353
 
354
- <div className="relative overflow-hidden py-10">
355
  <div className="absolute left-2 top-1/2 -translate-y-1/2 z-10">
356
  <button onClick={()=> setFlowIndex((i)=> Math.max(i-1, 0))} className="px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm">‹</button>
357
  </div>
358
  <div className="absolute right-2 top-1/2 -translate-y-1/2 z-10">
359
  <button onClick={()=> setFlowIndex((i)=> Math.min(i+1, Math.max(taskVersions.length-1, 0)))} className="px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm">›</button>
360
  </div>
361
- <div className="flex items-center justify-center gap-8 px-16 transition-transform duration-300">
 
 
 
 
 
 
 
 
 
 
 
362
  {taskVersions.map((v, idx) => {
363
- const isCenter = idx === focusedIndex;
364
- const sideOffset = Math.abs(idx - focusedIndex);
365
- // Apple coverflow style: center slightly larger; others equal smaller, slight angle
366
- const scale = isCenter ? 1.05 : 0.9;
367
- const rotate = isCenter ? 0 : (idx < focusedIndex ? -10 : 10);
368
- const opacity = isCenter ? 1 : 0.85;
369
- const snippet = (v.content || '').slice(0, 160) + ((v.content || '').length > 160 ? '…' : '');
 
 
 
370
  return (
371
- <div key={v.id} className="transition-transform duration-300"
372
- style={{ transform: `scale(${scale}) rotateY(${rotate}deg)`, opacity }}>
373
- <div className="relative w-[520px] rounded-xl p-5 bg-white/10 backdrop-blur-md ring-1 ring-inset ring-white/30 shadow-[inset_0_0.5px_0_rgba(255,255,255,0.5),inset_0_-1px_1.5px_rgba(0,0,0,0.12)]">
 
 
 
 
 
 
 
 
374
  <div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
375
  <div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
376
  <div className="text-gray-900 whitespace-pre-wrap break-words min-h-[100px]">{snippet}</div>
 
 
 
 
 
377
  {isCenter && (
378
  <div className="mt-4 flex gap-3">
379
  <button onClick={()=>{ setPreviewVersionId(v.id); setStage('preview'); }} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">
 
94
  return Math.min(Math.max(taskVersions.length - 1, 0), flowIndex);
95
  }, [taskVersions, currentVersionId, flowIndex]);
96
 
97
+ // Keyboard navigation for cover flow
98
+ React.useEffect(() => {
99
+ const handler = (e: KeyboardEvent) => {
100
+ if (e.key === 'ArrowLeft') {
101
+ setFlowIndex(i => Math.max(i - 1, 0));
102
+ } else if (e.key === 'ArrowRight') {
103
+ setFlowIndex(i => Math.min(i + 1, Math.max(taskVersions.length - 1, 0)));
104
+ }
105
+ };
106
+ window.addEventListener('keydown', handler);
107
+ return () => window.removeEventListener('keydown', handler);
108
+ }, [taskVersions.length]);
109
+
110
  const uploadDocx = async (file: File) => {
111
  setUploading(true);
112
  try {
 
364
  </div>
365
  </div>
366
 
367
+ <div className="relative overflow-hidden py-10" style={{ perspective: '1200px' }}>
368
  <div className="absolute left-2 top-1/2 -translate-y-1/2 z-10">
369
  <button onClick={()=> setFlowIndex((i)=> Math.max(i-1, 0))} className="px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm">‹</button>
370
  </div>
371
  <div className="absolute right-2 top-1/2 -translate-y-1/2 z-10">
372
  <button onClick={()=> setFlowIndex((i)=> Math.min(i+1, Math.max(taskVersions.length-1, 0)))} className="px-2 py-1 rounded-2xl bg-white/50 ring-1 ring-white/50 backdrop-blur-md text-sm">›</button>
373
  </div>
374
+ <div
375
+ className="flex items-center justify-center gap-10 px-16 transition-transform duration-300"
376
+ onWheel={(e)=>{
377
+ if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {
378
+ if (e.deltaX > 0) setFlowIndex(i => Math.min(i+1, Math.max(taskVersions.length-1,0)));
379
+ else setFlowIndex(i => Math.max(i-1, 0));
380
+ } else {
381
+ if (e.deltaY > 0) setFlowIndex(i => Math.min(i+1, Math.max(taskVersions.length-1,0)));
382
+ else setFlowIndex(i => Math.max(i-1, 0));
383
+ }
384
+ }}
385
+ >
386
  {taskVersions.map((v, idx) => {
387
+ const offset = idx - focusedIndex;
388
+ const abs = Math.abs(offset);
389
+ const isCenter = abs === 0;
390
+ const translateX = offset * 260; // spacing between cards
391
+ const rotateY = -offset * 45; // angle for side cards
392
+ const translateZ = -abs * 140; // push side cards back a bit
393
+ const scale = isCenter ? 1.08 : 0.9;
394
+ const opacity = isCenter ? 1 : Math.max(0.6, 1 - abs * 0.15);
395
+ const zIndex = 100 - abs;
396
+ const snippet = (v.content || '').slice(0, 140) + ((v.content || '').length > 140 ? '…' : '');
397
  return (
398
+ <div
399
+ key={v.id}
400
+ className="transition-transform duration-300 cursor-pointer"
401
+ style={{
402
+ transform: `translateX(${translateX}px) translateZ(${translateZ}px) rotateY(${rotateY}deg) scale(${scale})`,
403
+ opacity,
404
+ zIndex,
405
+ }}
406
+ onClick={() => { if (!isCenter) setFlowIndex(idx); }}
407
+ >
408
+ <div className="relative w-[520px] rounded-xl p-5 bg-white/10 backdrop-blur-md ring-1 ring-inset ring-white/30 shadow-[0_20px_40px_rgba(0,0,0,0.15),inset_0_0.5px_0_rgba(255,255,255,0.5),inset_0_-1px_1.5px_rgba(0,0,0,0.12)]">
409
  <div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
410
  <div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
411
  <div className="text-gray-900 whitespace-pre-wrap break-words min-h-[100px]">{snippet}</div>
412
+ {/* Reflection */}
413
+ <div className="pointer-events-none absolute left-0 right-0 -bottom-20 h-16 opacity-35" style={{ transform: 'scaleY(-1)' }}>
414
+ <div className="w-full h-full rounded-xl bg-white/10 ring-1 ring-inset ring-white/30" />
415
+ <div className="absolute inset-0 bg-gradient-to-t from-white to-transparent" />
416
+ </div>
417
  {isCenter && (
418
  <div className="mt-4 flex gap-3">
419
  <button onClick={()=>{ setPreviewVersionId(v.id); setStage('preview'); }} className="relative overflow-hidden inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium rounded-2xl text-black ring-1 ring-inset ring-white/50 backdrop-blur-md bg-white/30 active:translate-y-0.5 transition-all duration-200">