mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
# Description of Changes This pull request primarily focuses on code style improvements across several frontend files, standardizing the use of semicolons and ensuring consistent formatting. No functional or logic changes are introduced; the updates are purely syntactic to improve code readability and maintainability. **Code Style and Formatting Improvements:** * Added missing semicolons and standardized import statements in multiple files, including `DividerWithText.tsx`, `LoginRightCarousel.tsx`, `loginSlides.ts`, `AuthCallback.tsx`, `Landing.tsx`, `Login.tsx`, and `Signup.tsx`. [[1]](diffhunk://#diff-5de1b22e63fe3b6c9781c2a476db7440818f18d2aeb5c6c1ddeb446517cf001fL1-R1) [[2]](diffhunk://#diff-7cc961105816564bebd8656fe59119970d5859b4557f48c37fe920d344a948c3L1-R1) [[3]](diffhunk://#diff-1fc806abd10f8882945f54b56828db4c4b9a8b986743250b26dd9bdf0ec49bdbL41-R43) [[4]](diffhunk://#diff-540ce2405611334ce0bdff1f48d187218be99ce64fb92f054b9cf5a71cb1ed8cL1-R3) [[5]](diffhunk://#diff-d55dde4f28998eb9b30f332a1c96a4c79ec6a70b568bb51eea81d11a3715c35cL1-R5) [[6]](diffhunk://#diff-183a38f7c78b7c2950c4bed87ff2843de146d960e28591865d91c3cd86c3fadbL1-R39) [[7]](diffhunk://#diff-0a98c2e661e58f226f98c90b2e82198090b9fd986bbd98c2af6574d19f2ee37aL1-R25) * Updated function bodies and return statements to use consistent semicolon placement and code formatting throughout the affected files. [[1]](diffhunk://#diff-5de1b22e63fe3b6c9781c2a476db7440818f18d2aeb5c6c1ddeb446517cf001fL13-R15) [[2]](diffhunk://#diff-5de1b22e63fe3b6c9781c2a476db7440818f18d2aeb5c6c1ddeb446517cf001fL27-R35) [[3]](diffhunk://#diff-7cc961105816564bebd8656fe59119970d5859b4557f48c37fe920d344a948c3L17-R63) [[4]](diffhunk://#diff-7cc961105816564bebd8656fe59119970d5859b4557f48c37fe920d344a948c3L82-R82) [[5]](diffhunk://#diff-7cc961105816564bebd8656fe59119970d5859b4557f48c37fe920d344a948c3L158-R158) [[6]](diffhunk://#diff-540ce2405611334ce0bdff1f48d187218be99ce64fb92f054b9cf5a71cb1ed8cL13-R56) [[7]](diffhunk://#diff-540ce2405611334ce0bdff1f48d187218be99ce64fb92f054b9cf5a71cb1ed8cL72-R72) [[8]](diffhunk://#diff-d55dde4f28998eb9b30f332a1c96a4c79ec6a70b568bb51eea81d11a3715c35cL15-R26) [[9]](diffhunk://#diff-d55dde4f28998eb9b30f332a1c96a4c79ec6a70b568bb51eea81d11a3715c35cL39-R61) [[10]](diffhunk://#diff-183a38f7c78b7c2950c4bed87ff2843de146d960e28591865d91c3cd86c3fadbL51-R118) [[11]](diffhunk://#diff-183a38f7c78b7c2950c4bed87ff2843de146d960e28591865d91c3cd86c3fadbL188-R188) [[12]](diffhunk://#diff-0a98c2e661e58f226f98c90b2e82198090b9fd986bbd98c2af6574d19f2ee37aL1-R25) No business logic, UI, or feature behavior has been changed as part of this update. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. Co-authored-by: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com>
160 lines
5.1 KiB
TypeScript
160 lines
5.1 KiB
TypeScript
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
import { BASE_PATH } from '../../constants/app';
|
|
|
|
type ImageSlide = { src: string; alt?: string; cornerModelUrl?: string; title?: string; subtitle?: string; followMouseTilt?: boolean; tiltMaxDeg?: number }
|
|
|
|
export default function LoginRightCarousel({
|
|
imageSlides = [],
|
|
showBackground = true,
|
|
initialSeconds = 5,
|
|
slideSeconds = 8,
|
|
}: {
|
|
imageSlides?: ImageSlide[]
|
|
showBackground?: boolean
|
|
initialSeconds?: number
|
|
slideSeconds?: number
|
|
}) {
|
|
const totalSlides = imageSlides.length;
|
|
const [index, setIndex] = useState(0);
|
|
const mouse = useRef({ x: 0, y: 0 });
|
|
|
|
const durationsMs = useMemo(() => {
|
|
if (imageSlides.length === 0) return [];
|
|
return imageSlides.map((_, i) => (i === 0 ? (initialSeconds ?? slideSeconds) : slideSeconds) * 1000);
|
|
}, [imageSlides, initialSeconds, slideSeconds]);
|
|
|
|
useEffect(() => {
|
|
if (totalSlides <= 1) return;
|
|
const timeout = setTimeout(() => {
|
|
setIndex((i) => (i + 1) % totalSlides);
|
|
}, durationsMs[index] ?? slideSeconds * 1000);
|
|
return () => clearTimeout(timeout);
|
|
}, [index, totalSlides, durationsMs, slideSeconds]);
|
|
|
|
useEffect(() => {
|
|
const onMove = (e: MouseEvent) => {
|
|
mouse.current.x = (e.clientX / window.innerWidth) * 2 - 1;
|
|
mouse.current.y = (e.clientY / window.innerHeight) * 2 - 1;
|
|
};
|
|
window.addEventListener('mousemove', onMove);
|
|
return () => window.removeEventListener('mousemove', onMove);
|
|
}, []);
|
|
|
|
function TiltImage({ src, alt, enabled, maxDeg = 6 }: { src: string; alt?: string; enabled: boolean; maxDeg?: number }) {
|
|
const imgRef = useRef<HTMLImageElement | null>(null);
|
|
|
|
useEffect(() => {
|
|
const el = imgRef.current;
|
|
if (!el) return;
|
|
|
|
let raf = 0;
|
|
const tick = () => {
|
|
if (enabled) {
|
|
const rotY = (mouse.current.x || 0) * maxDeg;
|
|
const rotX = -(mouse.current.y || 0) * maxDeg;
|
|
el.style.transform = `translateY(-2rem) rotateX(${rotX.toFixed(2)}deg) rotateY(${rotY.toFixed(2)}deg)`;
|
|
} else {
|
|
el.style.transform = 'translateY(-2rem)';
|
|
}
|
|
raf = requestAnimationFrame(tick);
|
|
};
|
|
raf = requestAnimationFrame(tick);
|
|
return () => cancelAnimationFrame(raf);
|
|
}, [enabled, maxDeg]);
|
|
|
|
return (
|
|
<img
|
|
ref={imgRef}
|
|
src={src}
|
|
alt={alt ?? 'Carousel slide'}
|
|
style={{
|
|
maxWidth: '86%',
|
|
maxHeight: '78%',
|
|
objectFit: 'contain',
|
|
borderRadius: '18px',
|
|
background: 'transparent',
|
|
transform: 'translateY(-2rem)',
|
|
transition: 'transform 80ms ease-out',
|
|
willChange: 'transform',
|
|
transformOrigin: '50% 50%',
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div style={{ position: 'relative', overflow: 'hidden', width: '100%', height: '100%' }}>
|
|
{showBackground && (
|
|
<img
|
|
src={`${BASE_PATH}/Login/LoginBackgroundPanel.png`}
|
|
alt="Background panel"
|
|
style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover' }}
|
|
/>
|
|
)}
|
|
|
|
{/* Image slides */}
|
|
{imageSlides.map((s, idx) => (
|
|
<div
|
|
key={s.src}
|
|
style={{
|
|
position: 'absolute',
|
|
inset: 0,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
transition: 'opacity 600ms ease',
|
|
opacity: index === idx ? 1 : 0,
|
|
perspective: '900px',
|
|
}}
|
|
>
|
|
{(s.title || s.subtitle) && (
|
|
<div style={{ position: 'absolute', bottom: 24 + 32, left: 0, right: 0, textAlign: 'center', padding: '0 2rem', width: '100%' }}>
|
|
{s.title && (
|
|
<div style={{ fontSize: 20, fontWeight: 800, color: '#ffffff', textShadow: '0 2px 6px rgba(0,0,0,0.25)', marginBottom: 6 }}>{s.title}</div>
|
|
)}
|
|
{s.subtitle && (
|
|
<div style={{ fontSize: 13, color: 'rgba(255,255,255,0.92)', textShadow: '0 1px 4px rgba(0,0,0,0.25)' }}>{s.subtitle}</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
<TiltImage src={s.src} alt={s.alt} enabled={index === idx && !!s.followMouseTilt} maxDeg={s.tiltMaxDeg ?? 6} />
|
|
|
|
</div>
|
|
))}
|
|
|
|
{/* Dot navigation */}
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: 16,
|
|
left: 0,
|
|
right: 0,
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
gap: 10,
|
|
zIndex: 2,
|
|
}}
|
|
>
|
|
{Array.from({ length: totalSlides }).map((_, i) => (
|
|
<button
|
|
key={i}
|
|
aria-label={`Go to slide ${i + 1}`}
|
|
onClick={() => setIndex(i)}
|
|
style={{
|
|
width: '10px',
|
|
height: '12px',
|
|
borderRadius: '50%',
|
|
border: 'none',
|
|
cursor: 'pointer',
|
|
backgroundColor: i === index ? '#ffffff' : 'rgba(255,255,255,0.5)',
|
|
boxShadow: '0 2px 6px rgba(0,0,0,0.25)',
|
|
display: 'block',
|
|
flexShrink: 0,
|
|
}}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|