mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 21:06:42 +07:00
photoswipe element
This commit is contained in:
parent
55c806ce21
commit
19aeb8a334
16 changed files with 260 additions and 58 deletions
|
@ -8,6 +8,7 @@ import { PRESETS } from '~/constants/urls';
|
|||
|
||||
interface IProps {
|
||||
node: INode;
|
||||
modalShowPhotoswipe: any;
|
||||
}
|
||||
|
||||
const NodeAudioImageBlock: FC<IProps> = ({ node }) => {
|
||||
|
|
|
@ -1,27 +1,22 @@
|
|||
import React, {
|
||||
FC,
|
||||
useMemo,
|
||||
useState,
|
||||
useEffect,
|
||||
useRef,
|
||||
useCallback
|
||||
} from "react";
|
||||
import { ImageSwitcher } from "../ImageSwitcher";
|
||||
import * as styles from "./styles.scss";
|
||||
import { INode } from "~/redux/types";
|
||||
import classNames from "classnames";
|
||||
import { getURL } from "~/utils/dom";
|
||||
import { UPLOAD_TYPES } from "~/redux/uploads/constants";
|
||||
import { PRESETS } from "~/constants/urls";
|
||||
import React, { FC, useMemo, useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { ImageSwitcher } from '../ImageSwitcher';
|
||||
import * as styles from './styles.scss';
|
||||
import { INode } from '~/redux/types';
|
||||
import classNames from 'classnames';
|
||||
import { getURL } from '~/utils/dom';
|
||||
import { UPLOAD_TYPES } from '~/redux/uploads/constants';
|
||||
import { PRESETS } from '~/constants/urls';
|
||||
import * as MODAL_ACTIONS from '~/redux/modal/actions';
|
||||
|
||||
interface IProps {
|
||||
is_loading: boolean;
|
||||
node: INode;
|
||||
layout: {};
|
||||
updateLayout: () => void;
|
||||
modalShowPhotoswipe: typeof MODAL_ACTIONS.modalShowPhotoswipe;
|
||||
}
|
||||
|
||||
const NodeImageBlock: FC<IProps> = ({ node, is_loading, updateLayout }) => {
|
||||
const NodeImageBlock: FC<IProps> = ({ node, is_loading, updateLayout, modalShowPhotoswipe }) => {
|
||||
const [is_animated, setIsAnimated] = useState(false);
|
||||
const [current, setCurrent] = useState(0);
|
||||
const [height, setHeight] = useState(320);
|
||||
|
@ -30,36 +25,35 @@ const NodeImageBlock: FC<IProps> = ({ node, is_loading, updateLayout }) => {
|
|||
|
||||
const images = useMemo(
|
||||
() =>
|
||||
(node &&
|
||||
node.files &&
|
||||
node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) ||
|
||||
[],
|
||||
(node && node.files && node.files.filter(({ type }) => type === UPLOAD_TYPES.IMAGE)) || [],
|
||||
[node]
|
||||
);
|
||||
|
||||
const setRef = useCallback(index => el => (refs.current[index] = el), [refs]);
|
||||
const onImageLoad = useCallback(
|
||||
index => () => setLoaded({ ...loaded, [index]: true }),
|
||||
[setLoaded, loaded]
|
||||
const onImageLoad = useCallback(index => () => setLoaded({ ...loaded, [index]: true }), [
|
||||
setLoaded,
|
||||
loaded,
|
||||
]);
|
||||
|
||||
const onOpenPhotoSwipe = useCallback(
|
||||
(index: number) => () => modalShowPhotoswipe(images, index),
|
||||
[modalShowPhotoswipe, images]
|
||||
);
|
||||
|
||||
useEffect(() => updateLayout(), [loaded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!refs || !refs.current[current] || !loaded[current])
|
||||
return setHeight(320);
|
||||
if (!refs || !refs.current[current] || !loaded[current]) return setHeight(320);
|
||||
|
||||
const el = refs.current[current];
|
||||
|
||||
const element_height =
|
||||
el.getBoundingClientRect && el.getBoundingClientRect().height;
|
||||
const element_height = el.getBoundingClientRect && el.getBoundingClientRect().height;
|
||||
|
||||
setHeight(element_height);
|
||||
}, [refs, current, loaded]);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setIsAnimated(true), 250);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
|
@ -74,21 +68,19 @@ const NodeImageBlock: FC<IProps> = ({ node, is_loading, updateLayout }) => {
|
|||
/>
|
||||
|
||||
<div className={styles.image_container} style={{ height }}>
|
||||
{(is_loading || !loaded[0] || !images.length) && (
|
||||
<div className={styles.placeholder} />
|
||||
)}
|
||||
{(is_loading || !loaded[0] || !images.length) && <div className={styles.placeholder} />}
|
||||
|
||||
{images.map((file, index) => (
|
||||
<div
|
||||
className={classNames(styles.image_wrap, {
|
||||
is_active: index === current && loaded[index]
|
||||
is_active: index === current && loaded[index],
|
||||
})}
|
||||
ref={setRef(index)}
|
||||
key={file.id}
|
||||
>
|
||||
<img
|
||||
className={styles.image}
|
||||
src={getURL(file, PRESETS["1600"])}
|
||||
src={getURL(file, PRESETS['1600'])}
|
||||
alt=""
|
||||
key={file.id}
|
||||
onLoad={onImageLoad(index)}
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
import React, {
|
||||
FC,
|
||||
useMemo,
|
||||
useState,
|
||||
useEffect,
|
||||
useRef,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
} from 'react';
|
||||
import React, { FC, useMemo, useState, useEffect, useRef, useCallback } from 'react';
|
||||
import { ImageSwitcher } from '../ImageSwitcher';
|
||||
import * as styles from './styles.scss';
|
||||
import { INode } from '~/redux/types';
|
||||
|
@ -17,17 +9,24 @@ import { getURL } from '~/utils/dom';
|
|||
import { PRESETS } from '~/constants/urls';
|
||||
import { LoaderCircle } from '~/components/input/LoaderCircle';
|
||||
import { throttle } from 'throttle-debounce';
|
||||
import * as MODAL_ACTIONS from '~/redux/modal/actions';
|
||||
|
||||
interface IProps {
|
||||
is_loading: boolean;
|
||||
node: INode;
|
||||
layout: {};
|
||||
updateLayout: () => void;
|
||||
modalShowPhotoswipe: typeof MODAL_ACTIONS.modalShowPhotoswipe;
|
||||
}
|
||||
|
||||
const getX = event => (event.touches ? event.touches[0].clientX : event.clientX);
|
||||
|
||||
const NodeImageSlideBlock: FC<IProps> = ({ node, is_loading, updateLayout }) => {
|
||||
const NodeImageSlideBlock: FC<IProps> = ({
|
||||
node,
|
||||
is_loading,
|
||||
updateLayout,
|
||||
modalShowPhotoswipe,
|
||||
}) => {
|
||||
const [current, setCurrent] = useState(0);
|
||||
const [height, setHeight] = useState(320);
|
||||
const [max_height, setMaxHeight] = useState(960);
|
||||
|
@ -39,6 +38,8 @@ const NodeImageSlideBlock: FC<IProps> = ({ node, is_loading, updateLayout }) =>
|
|||
const [initial_x, setInitialX] = useState(0);
|
||||
const [offset, setOffset] = useState(0);
|
||||
const [is_dragging, setIsDragging] = useState(false);
|
||||
const [drag_start_time, setDragStartTime] = useState(0);
|
||||
|
||||
const slide = useRef<HTMLDivElement>();
|
||||
const wrap = useRef<HTMLDivElement>();
|
||||
|
||||
|
@ -166,12 +167,25 @@ const NodeImageSlideBlock: FC<IProps> = ({ node, is_loading, updateLayout }) =>
|
|||
normalizeOffset();
|
||||
}, [wrap, setMaxHeight, normalizeOffset]);
|
||||
|
||||
const stopDragging = useCallback(() => {
|
||||
if (!is_dragging) return;
|
||||
const onOpenPhotoSwipe = useCallback(() => modalShowPhotoswipe(images, current), [
|
||||
modalShowPhotoswipe,
|
||||
images,
|
||||
current,
|
||||
]);
|
||||
|
||||
setIsDragging(false);
|
||||
normalizeOffset();
|
||||
}, [setIsDragging, is_dragging, normalizeOffset]);
|
||||
const stopDragging = useCallback(
|
||||
event => {
|
||||
if (!is_dragging) return;
|
||||
|
||||
setIsDragging(false);
|
||||
normalizeOffset();
|
||||
|
||||
if (initial_x - event.clientX < 10) {
|
||||
onOpenPhotoSwipe();
|
||||
}
|
||||
},
|
||||
[setIsDragging, is_dragging, normalizeOffset, onOpenPhotoSwipe]
|
||||
);
|
||||
|
||||
const startDragging = useCallback(
|
||||
event => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue