react photoswipe gallery of thumbnails will not display as grid - css

I'm using photoswipe gallery.
When I do so, I get all the thumbnails in a single line... I would like them to fill the page like a grid.
Below is my react component code. I have noticed that if I go to each thumbnail in dev tools->inspect and change display to 'inline' I don't end up with a line break after/before each. It still looks garbage because lack of frames and other things, However, I don't know how or where to modify the look or styling of the thumbnails put that in my code.
import { PhotoSwipeGallery } from 'react-photoswipe-2';
const useStyles = makeStyles((theme) => ({
loadingPaper: {
margin: "auto",
width: '50%',
padding: '10px',
marginTop: "50px"
}
}));
function FrameViewer(props) {
const classes = useStyles();
let { cameraAccessor } = useParams();
const [frames, setFrames] = useState([]);
const [isGalleryOpen, setIsGalleryOpen] = useState(false);
const [imgGalleryH, setGalleryImgH] = useState(0);
const [imgGalleryW, setGalleryImgW] = useState(0);
const [cameraID, setCameraID] = useState("");
const { cameras } = props;
async function fetchCameraData(cameraAccessor) { // TODO: check if already loading before running. // code to get filenames and what not
}
useEffect(() => {
// code to lead camera data
}, [cameraAccessor]);
const getThumbnailContent = item => (
<img src={item.thumbnail} width={120} height={90} alt="" />
);
let cam = cameras[cameraID];
if (cam) { // Photoswipe requires a Height and Width ... so we need to load the first image and see how big before we can incept Photoswipe.
var img = new Image();
img.onload = function () {
setGalleryImgH(img.height);
setGalleryImgW(img.width);
}
img.src = "https://apps.usgs.gov/sstl/media/cameras/" + cameraFolderName(cam) + "/" + cameraFolderName(cam) + MOST_RECENT_FRAME_SUFFIX;
}
return (
<React.Fragment>
{cam && frames && frames.length && imgGalleryH > 0 && imgGalleryW > 0
? <PhotoSwipeGallery
items={frames.map((filename) => {
return {
src: 'https://example.com/media/cameras/' + cameraFolderName(cam) + '/' + filename,
thumbnail: 'https://example.com/media/cameras/' + cameraFolderName(cam) + '/' + filename,
w: imgGalleryW,
h: imgGalleryH,
title: filename.replace("_overlay.jpg", "").split("___")[1].replace("_", " ")
}
})}
options={{
closeOnScroll: false
}}
thumbnailContent={getThumbnailContent}
isOpen={isGalleryOpen}
onClose={() => setIsGalleryOpen(false)}
/>
: <Paper elevation={5} className={classes.loadingPaper}><Typography color="textSecondary" align='center'>loading...</Typography></Paper>
}
</React.Fragment >
);
}

Edit your CSS. Try overriding the display property at the container level (.pswp-thumbnails):
.pswp-thumbnails
{
display: flex;
}
... OR at the thumbnail level (.pswp-thumbnail):
.pswp-thumbnail {
display: inline-block;
}

Related

I want to increase height of this react native curve image

I want to increase the height of this image. How can we change the CSS for that? my code also have below image
You can create a custom component that will handle height and width, and use it.
You can do something like that.
import React, { useEffect, useState } from "react";
import { Image, ImageSourcePropType, ImageStyle, StyleProp } from "react-native";
interface ScaledImageProps {
source: ImageSourcePropType;
width?: number;
height?: number;
style?: StyleProp<ImageStyle> | undefined;
onGetHeight?: (height: number) => void
onGetWidth?: (width: number) => void
}
export const ScaledImage = (props: ScaledImageProps) => {
const [currentWidth, setCurrentWidth] = useState(0);
const [currentHeight, setCurrentHeight] = useState(0);
const setWidth = (width: number) => {
setCurrentWidth(width)
if (props.onGetWidth) props.onGetWidth(width)
}
const setHeight = (height: number) => {
setCurrentHeight(height)
if (props.onGetHeight) props.onGetHeight(height)
}
useEffect(() => {
const uri = Image.resolveAssetSource(props.source).uri
Image.getSize(uri, (width, height) => {
if (props.width && !props.height) {
setWidth(props.width);
setHeight(height * (props.width / width));
} else if (!props.width && props.height) {
setWidth(width * (props.height / height));
setHeight(props.height);
} else {
setWidth(width);
setHeight(height);
}
});
}, []);
return (
<Image
source={props.source}
style={[props.style ,{ height: currentHeight, width: currentWidth, }]}
/>
);
};
and if you want to use it, just call it like the following
<ScaledImage width={100} source={YourImage} />

change the id inside an svg on scroll at viewport in React

So I have an svg with an animation, but I want the animation to start when I'm scolled on viewport. I cant quite get there tho.
My code:
export const useScrollHandler = () => {
const [scroll, setScroll] = useState(1);
useEffect(() => {
const onScroll = () => {
const scrollCheck = window.scrollY > 100;
setScroll(scrollCheck);
};
document.addEventListener("scroll", onScroll);
return () => {
document.removeEventListener("scroll", onScroll);
};
}, [scroll, setScroll]);
return scroll;
};
then I add it on my svg component ( i wont put the whole svg cause its too long):
const ImageEssentials = (props) => {
const scroll = useScrollHandler();
<svg ...>
<g id={scroll ? "" : "Box1"}>
</svg>
}
So basicly when I scroll i want the svg group to get the id "Box1" that it has the animation.

React Wait until transition end for vertical scroll

I'm trying to make vertical scroll page looks like fullpage.js with react
https://alvarotrigo.com/fullPage/
Page scroll works well but having hard time to prevent double scroll..
I want to make scroll doesn't work until finish move to next page.
Using setTimeout and clearTimeout works well but it has pre delay before moving pages.
I don't like that so tried to use onTransitionEnd to detect change but doesn't work well.
Currently my code is like this
const Container = () => {
const [index, setIndex] = useState(0);
const [isAnimating, setAnimating] = useState(false);
const ref = useRef<HTMLDivElement>(null);
const animatingRef = useRef(false);
const indexRef = useRef(0);
indexRef.current = index;
useEffect(() => {
if (!isAnimating) {
const updater = (e: WheelEvent) => {
setAnimating(true);
let dir = e.deltaY;
if (dir < 0) {
indexRef.current > 0 && setIndex(indexRef.current - 1);
} else {
indexRef.current < 2 && setIndex(indexRef.current + 1);
}
};
window.addEventListener('wheel', e => updater(e));
return () => {
window.removeEventListener('wheel', e => updater(e));
};
}
}, [isAnimating]);
useEffect(() => {
if (ref && ref.current) {
ref.current.style.transition = 'all 0.5s ease-in-out';
ref.current.style.transform = `translate3d(0,-${index * 100}%,0)`;
}
}, [index]);
return (
<Wrapper>
<ViewContainer ref={ref} onTransitionEnd={() => setAnimating(false)}>
<View color="orange" />
<View color="red" />
<View color="yellow" />
</ViewContainer>
</Wrapper>
);
};

Rerender Tooltip when Scrolling React

Thanks for your help in advance, I have an issue with a tooltip, it is supposed that I should show the tooltip when a condition is given, but due to the scroll when rerendering the list the validation fails.
Here is working right, the complete list shows the tooltips where it is supposed to be. enter image description here
But then, when I scroll down the view is re-render and the tooltip fails. enter image description here
The idea is that the tooltip (and the underline) should be shown when I have group names too long using this boolean disableHoverListener={textDoesOverflow}, and it is working at the beginning but then ... fails.
Here's the code and the styles.
Please help!!
export const BaseFilteredUsersGroups: React.FC<IFilteredUsersGroups> = (props) => {
const {
userId,
filteredGroupIds = [],
localize,
} = props;
const sizeGroupsRef = React.useRef(null);
const sizeTitleRef = React.useRef(null);
const styles = useStyles();
const usersGroups = useSelector((state: IDuxStore) => {
const groups = filteredGroupIds.map(groupId => select.group.getGroupByGroupId(state, groupId));
return groups.filter(group => group?.memberships?.some(user => user.userId === userId));
});
const labelTitle = localize.formatItems(usersGroups.map(group => group.title));
const textDoesOverflow = sizeGroupsRef?.current?.getBoundingClientRect()?.width >= sizeTitleRef?.current?.getBoundingClientRect()?.width;
const finalStyle = textDoesOverflow ? styles.groupTitle : styles.groupTitleOverflow;
return (<div className={styles.usersGroups} ref={sizeGroupsRef}>
{<Tooltip title={labelTitle} disableHoverListener={textDoesOverflow} placement="top" onScrollCapture={}>
{<span className={finalStyle} ref={sizeTitleRef}>
{labelTitle}
</span>}
</Tooltip>}
</div >);
};
Here the styles:
export const useStyles = makeStyles(theme => {
return createStyles({
usersGroups:{
textOverflow: 'ellipsis',
overflow: 'hidden',
},
groupTitle: {
whiteSpace: 'nowrap',
fontWeight: theme.typography.fontWeightMedium,
color: theme.palette.text.secondary,
},
groupTitleOverflow: {
whiteSpace: 'nowrap',
fontWeight: theme.typography.fontWeightMedium,
color: theme.palette.text.secondary,
textDecorationLine: 'underline',
}
});
});
const textDoesOverflow =
sizeGroupsRef?.current?.getBoundingClientRect()?.width
>= sizeTitleRef?.current?.getBoundingClientRect()?.width;
const finalStyle = textDoesOverflow ? styles.groupTitle : styles.groupTitleOverflow;
The conditional logic here is reversed. Right now if the text width is greater than the sizeTitleRef width it will return groupTitle not groupTitleOverflow. So instead you may want to switch up the ternary operator to this:
const finalStyle = textDoesOverflow ? styles.groupTitleOverflow : styles.groupTitle;

How to make a responsive number os slides in a react carousel

I have a React Carousel that shows 3 elements at once. I would like to adjust this number of elements according to the size available. So for example
const RCarousel = ({items}) => {
const numItems = 3;
return (
<Carousel
numItemsPerView={numItems}
>
{
items.map(
(item) => <Item item={item} />
)
}
</Carousel>
)
}
I would like to change numItems to 2 if the RCarousel size is tablet size and 1 if is mobile size.
RCarousel may have a different width of the window width. Any suggestions how to make this? :)
You can use window.innerWidth and window.innerHight to get the size of the window.
Once you have the sizes, you can conditionally change it. I would stick the numItems in the useState and use useEffect to change it. Something along those lines
const [numItems, setNumItems] = useState(3);
const width = window.width;
useEffect(() => {
if (width > 800) {
setNumItems(3);
} else {
setNumItems(1);
}
}, [width])
Improving #szczocik's answer I was able to solve it using the following:
created a hook to get window size
useWindow.size.js
import {useState, useEffect} from 'react'
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: undefined,
height: undefined,
});
useEffect(() => {
if (typeof window === 'undefined') return; //specific for gatsby or applications using webpack
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
window.addEventListener("resize", handleResize);
handleResize();
return () => window.removeEventListener("resize", handleResize);
}, []);
return windowSize;
}
export default useWindowSize;
mycomponent.js
const windowSize = useWindowSize();
useEffect(() => {
const width = windowSize.width;
if (width >= 1200) {
if (numItems !== 3) {
setNumItems(3);
}
} else if (width > 900) {
if (numItems !== 2) {
setNumItems(2);
}
} else {
if (numItems !== 1) {
setNumItems(1);
}
}
}, windowSize)

Resources