webapp/src/components/_shared/Lightbox/Lightbox.tsx

69 lines
1.7 KiB
TypeScript
Raw Normal View History

2023-11-13 08:05:05 +00:00
import { clsx } from 'clsx'
import { createSignal } from 'solid-js'
2023-11-13 16:55:32 +00:00
import { useEscKeyDownHandler } from '../../../utils/useEscKeyDownHandler'
import { Icon } from '../Icon'
import styles from './Lightbox.module.scss'
2023-11-13 08:05:05 +00:00
type Props = {
class?: string
image: string
onClose: () => void
}
const ZOOM_STEP = 1.08
export const Lightbox = (props: Props) => {
const [zoomLevel, setZoomLevel] = createSignal(1)
const closeLightbox = () => {
props.onClose()
}
const zoomIn = (event) => {
event.stopPropagation()
setZoomLevel(zoomLevel() * ZOOM_STEP)
}
const zoomOut = (event) => {
event.stopPropagation()
setZoomLevel(zoomLevel() / ZOOM_STEP)
}
2023-11-22 21:31:51 +00:00
const zoomReset = (event) => {
event.stopPropagation()
setZoomLevel(1)
}
2023-11-13 08:05:05 +00:00
const lightboxStyle = () => ({
transform: `scale(${zoomLevel()})`,
transition: 'transform 0.3s ease',
2023-11-13 08:05:05 +00:00
})
2023-11-13 16:55:32 +00:00
useEscKeyDownHandler(closeLightbox)
2023-11-13 08:05:05 +00:00
return (
<div class={clsx(styles.Lightbox, props.class)} onClick={closeLightbox}>
<span class={styles.close} onClick={closeLightbox}>
2023-11-22 21:31:51 +00:00
<Icon name="close-white" class={styles.icon} />
2023-11-13 08:05:05 +00:00
</span>
<div class={styles.zoomControls}>
<button class={styles.control} onClick={(event) => zoomOut(event)}>
2023-11-22 21:31:51 +00:00
&minus;
2023-11-13 08:05:05 +00:00
</button>
2023-11-22 21:31:51 +00:00
<button class={clsx(styles.control, styles.controlDefault)} onClick={(event) => zoomReset(event)}>
1:1
2023-11-13 16:55:32 +00:00
</button>
2023-11-13 08:05:05 +00:00
<button class={styles.control} onClick={(event) => zoomIn(event)}>
2023-11-22 21:31:51 +00:00
+
2023-11-13 08:05:05 +00:00
</button>
</div>
<img
class={styles.image}
src={props.image}
style={lightboxStyle()}
alt={''}
onClick={(event) => event.stopPropagation()}
/>
</div>
)
}