Upload folder using huggingface_hub
Browse files
client/src/components/Refinity.tsx
CHANGED
|
@@ -2,10 +2,11 @@ import React from 'react';
|
|
| 2 |
import { motion, AnimatePresence } from 'framer-motion';
|
| 3 |
import { Swiper as SwiperRoot, SwiperSlide } from 'swiper/react';
|
| 4 |
import type { Swiper as SwiperInstance } from 'swiper';
|
| 5 |
-
import { EffectCoverflow, Navigation, A11y } from 'swiper/modules';
|
| 6 |
import 'swiper/css';
|
| 7 |
import 'swiper/css/effect-coverflow';
|
| 8 |
import 'swiper/css/navigation';
|
|
|
|
| 9 |
import { api } from '../services/api';
|
| 10 |
|
| 11 |
type Stage = 'task' | 'flow' | 'preview' | 'editor';
|
|
@@ -368,26 +369,32 @@ const Refinity: React.FC = () => {
|
|
| 368 |
</div>
|
| 369 |
<div className="relative">
|
| 370 |
<SwiperRoot
|
| 371 |
-
modules={[EffectCoverflow, Navigation, A11y]}
|
| 372 |
effect="coverflow"
|
| 373 |
onSlideChange={(s: SwiperInstance)=> setFlowIndex(s.activeIndex)}
|
| 374 |
onAfterInit={(s: SwiperInstance)=> setFlowIndex(s.activeIndex)}
|
| 375 |
navigation
|
|
|
|
| 376 |
centeredSlides
|
| 377 |
-
slidesPerView={
|
| 378 |
-
spaceBetween={
|
| 379 |
-
|
| 380 |
-
|
|
|
|
|
|
|
|
|
|
| 381 |
>
|
| 382 |
{taskVersions.map((v, idx) => {
|
| 383 |
const snippet = (v.content || '').slice(0, 220) + ((v.content || '').length > 220 ? '…' : '');
|
| 384 |
const isCenter = idx === flowIndex;
|
| 385 |
return (
|
| 386 |
-
<SwiperSlide key={v.id} style={{ width:
|
| 387 |
-
<div className="relative rounded-
|
|
|
|
|
|
|
| 388 |
<div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
|
| 389 |
<div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
|
| 390 |
-
<div className="text-gray-900 whitespace-pre-wrap break-words leading-relaxed">{snippet}</div>
|
| 391 |
{isCenter && (
|
| 392 |
<div className="mt-4 flex gap-3">
|
| 393 |
<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">Full Text</button>
|
|
|
|
| 2 |
import { motion, AnimatePresence } from 'framer-motion';
|
| 3 |
import { Swiper as SwiperRoot, SwiperSlide } from 'swiper/react';
|
| 4 |
import type { Swiper as SwiperInstance } from 'swiper';
|
| 5 |
+
import { EffectCoverflow, Navigation, Pagination, A11y } from 'swiper/modules';
|
| 6 |
import 'swiper/css';
|
| 7 |
import 'swiper/css/effect-coverflow';
|
| 8 |
import 'swiper/css/navigation';
|
| 9 |
+
import 'swiper/css/pagination';
|
| 10 |
import { api } from '../services/api';
|
| 11 |
|
| 12 |
type Stage = 'task' | 'flow' | 'preview' | 'editor';
|
|
|
|
| 369 |
</div>
|
| 370 |
<div className="relative">
|
| 371 |
<SwiperRoot
|
| 372 |
+
modules={[EffectCoverflow, Navigation, Pagination, A11y]}
|
| 373 |
effect="coverflow"
|
| 374 |
onSlideChange={(s: SwiperInstance)=> setFlowIndex(s.activeIndex)}
|
| 375 |
onAfterInit={(s: SwiperInstance)=> setFlowIndex(s.activeIndex)}
|
| 376 |
navigation
|
| 377 |
+
pagination={{ clickable: true }}
|
| 378 |
centeredSlides
|
| 379 |
+
slidesPerView={'auto'}
|
| 380 |
+
spaceBetween={16}
|
| 381 |
+
breakpoints={{ 640: { spaceBetween: 16 }, 1024: { spaceBetween: 24 }, 1536: { spaceBetween: 32 } }}
|
| 382 |
+
grabCursor
|
| 383 |
+
coverflowEffect={{ rotate: 0, stretch: 0, depth: 120, modifier: 1, slideShadows: false }}
|
| 384 |
+
className="!px-6"
|
| 385 |
+
style={{ height: 'clamp(420px, 70vh, 820px)' }}
|
| 386 |
>
|
| 387 |
{taskVersions.map((v, idx) => {
|
| 388 |
const snippet = (v.content || '').slice(0, 220) + ((v.content || '').length > 220 ? '…' : '');
|
| 389 |
const isCenter = idx === flowIndex;
|
| 390 |
return (
|
| 391 |
+
<SwiperSlide key={v.id} style={{ width: 'clamp(320px, 56vw, 720px)' }}>
|
| 392 |
+
<div className="relative h-full rounded-2xl p-5 bg-white ring-1 ring-gray-200 shadow-xl text-base">
|
| 393 |
+
<div className="pointer-events-none absolute inset-0 rounded-2xl opacity-40 [background:linear-gradient(to_bottom,rgba(255,255,255,0.45),rgba(255,255,255,0)_28%),linear-gradient(to_right,rgba(255,255,255,0.35),rgba(255,255,255,0)_28%)]" />
|
| 394 |
+
<div className="pointer-events-none absolute inset-0 rounded-2xl bg-gradient-to-tr from-white/30 via-white/10 to-transparent opacity-30" />
|
| 395 |
<div className="text-gray-800 text-sm mb-2">Original: {v.originalAuthor}</div>
|
| 396 |
<div className="text-gray-600 text-xs mb-3">Revised by: {v.revisedBy ? `${v.revisedBy} (v${v.versionNumber})` : `— (v${v.versionNumber})`}</div>
|
| 397 |
+
<div className="text-gray-900 whitespace-pre-wrap break-words leading-relaxed max-h-[calc(100%-56px)] overflow-auto pr-1">{snippet}</div>
|
| 398 |
{isCenter && (
|
| 399 |
<div className="mt-4 flex gap-3">
|
| 400 |
<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">Full Text</button>
|