mirror of
https://github.com/balzack/databag.git
synced 2025-04-21 00:55:16 +00:00
rendering asset carousel
This commit is contained in:
parent
6d60525774
commit
fc5de3ee08
@ -11,6 +11,7 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-easy-crop": "^4.1.4",
|
||||
"react-resize-detector": "^7.0.0",
|
||||
"react-router-dom": "^6.2.2",
|
||||
"react-scripts": "5.0.0",
|
||||
"react-virtualized": "^9.22.3",
|
||||
|
@ -0,0 +1,103 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { AddCarouselWrapper } from './AddCarousel.styled';
|
||||
import { RightOutlined, LeftOutlined } from '@ant-design/icons';
|
||||
import ReactResizeDetector from 'react-resize-detector';
|
||||
|
||||
import login from '../../../../login.png';
|
||||
import test from '../../../../test.png';
|
||||
|
||||
export function AddCarousel({ state, actions }) {
|
||||
const [items, setItems] = useState([]);
|
||||
|
||||
let carousel = useRef();
|
||||
let itemWidth = useRef(new Map());
|
||||
let itemIndex = useRef(0);
|
||||
let itemCount = useRef(0);
|
||||
const [scrollLeft, setScrollLeft] = useState('hidden');
|
||||
const [scrollRight, setScrollRight] = useState('hidden');
|
||||
|
||||
const onLeft = () => {
|
||||
console.log(itemIndex.current);
|
||||
if (itemIndex.current > 0) {
|
||||
itemIndex.current -= 1;
|
||||
setScroll();
|
||||
}
|
||||
}
|
||||
|
||||
const onRight = () => {
|
||||
console.log(itemIndex.current);
|
||||
if(itemIndex.current + 1 < itemCount.current) {
|
||||
itemIndex.current += 1;
|
||||
setScroll();
|
||||
}
|
||||
}
|
||||
|
||||
const setScroll = () => {
|
||||
console.log(">>", itemIndex.current);
|
||||
let pos = 0;
|
||||
for (let i = 0; i < itemIndex.current; i++) {
|
||||
pos += itemWidth.current.get(i) + 32;
|
||||
}
|
||||
carousel.current.scrollTo({ top: 0, left: pos, behavior: 'smooth' });
|
||||
setArrows();
|
||||
}
|
||||
|
||||
const setArrows = () => {
|
||||
if (itemIndex.current == 0) {
|
||||
setScrollLeft('hidden');
|
||||
}
|
||||
else {
|
||||
setScrollLeft('unset');
|
||||
}
|
||||
if (itemIndex.current + 1 >= itemCount.current) {
|
||||
setScrollRight('hidden');
|
||||
}
|
||||
else {
|
||||
setScrollRight('unset');
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (state.assets == null || state.assets.length == 0) {
|
||||
setItems([]);
|
||||
return;
|
||||
}
|
||||
let assets = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
assets.push((
|
||||
<ReactResizeDetector handleWidth={true} handleHeight={false}>
|
||||
{({ width, height }) => {
|
||||
itemWidth.current.set(i, width);
|
||||
if (i % 2 == 0) {
|
||||
return <div class="item"><img class="object" src={login} alt="" /></div>
|
||||
}
|
||||
return <div class="item"><img class="object" src={test} alt="" /></div>
|
||||
}}
|
||||
</ReactResizeDetector>
|
||||
));
|
||||
}
|
||||
itemCount.current = assets.length;
|
||||
if (itemIndex.current >= itemCount.current) {
|
||||
itemIndex.current = itemCount.current - 1;
|
||||
}
|
||||
setItems(assets);
|
||||
setArrows();
|
||||
}, [state]);
|
||||
|
||||
if (items.length != 0) {
|
||||
return (
|
||||
<AddCarouselWrapper>
|
||||
<div class="carousel" ref={carousel}>
|
||||
{items}
|
||||
</div>
|
||||
<div class="arrows">
|
||||
<div class="arrow" style={{ visibility: scrollLeft }} onClick={onLeft}><LeftOutlined /></div>
|
||||
<div class="arrow" style={{ visibility: scrollRight }} onClick={onRight}><RightOutlined /></div>
|
||||
</div>
|
||||
</AddCarouselWrapper>
|
||||
);
|
||||
}
|
||||
return <></>
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const AddCarouselWrapper = styled.div`
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
height: 128px;
|
||||
margin-top: 16px;
|
||||
|
||||
.carousel {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding-left: 16px;
|
||||
overflow: hidden;
|
||||
padding-right: 100%;
|
||||
|
||||
/* hide scrollbar for IE, Edge and Firefox */
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.carousel::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.arrows {
|
||||
width: 128px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: absolute;
|
||||
left: calc(50% - 64px);
|
||||
justify-content: center;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
background-color: #888888;
|
||||
color: white;
|
||||
opacity: 0.8;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
font-size: 20px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.arrow:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 128px;
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.space {
|
||||
width: 100%;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.object {
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
`;
|
||||
|
@ -0,0 +1,21 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export function useAddCarousel() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
});
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const actions = {
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
||||
|
66
net/web/src/User/Conversation/AddTopic/AddTopic.jsx
Normal file
66
net/web/src/User/Conversation/AddTopic/AddTopic.jsx
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react';
|
||||
import { Button, Dropdown, Input, Tooltip, Menu } from 'antd';
|
||||
import { AddTopicWrapper } from './AddTopic.styled';
|
||||
import { AddCarousel } from './AddCarousel/AddCarousel';
|
||||
import { useAddTopic } from './useAddTopic.hook';
|
||||
import { BgColorsOutlined, FontColorsOutlined, FontSizeOutlined, PaperClipOutlined, SendOutlined } from '@ant-design/icons';
|
||||
|
||||
export function AddTopic() {
|
||||
|
||||
const { state, actions } = useAddTopic();
|
||||
|
||||
const onAttach = () => {
|
||||
console.log("ADD IMAGE");
|
||||
actions.addImage(null);
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="0">
|
||||
<div onClick={() => actions.addImage()}>Attach Image</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="1">
|
||||
<div onClick={() => actions.addVideo()}>Attach Video</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2">
|
||||
<div onClick={() => actions.addAudio()}>Attach Audio</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="3">
|
||||
<div onClick={() => actions.addIframe()}>Embed Link</div>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<AddTopicWrapper>
|
||||
<div class="container">
|
||||
<AddCarousel state={state} actions={actions} />
|
||||
<div class="input">
|
||||
<Input.TextArea placeholder="Message" autoSize={{ minRows: 2, maxRows: 6 }}
|
||||
onChange={(e) => actions.setMessageText(e.target.value)} value={state.messageText} />
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="option">
|
||||
<Dropdown overlay={menu} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="topRight">
|
||||
<Button icon={<PaperClipOutlined />} size="medium" />
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div class="option">
|
||||
<Button icon={<FontSizeOutlined />} size="medium" />
|
||||
</div>
|
||||
<div class="option">
|
||||
<Button icon={<FontColorsOutlined />} size="medium" />
|
||||
</div>
|
||||
<div class="option">
|
||||
<Button icon={<BgColorsOutlined />} size="medium" />
|
||||
</div>
|
||||
<div class="send">
|
||||
<Button icon={<SendOutlined />} size="medium" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AddTopicWrapper>
|
||||
);
|
||||
|
||||
}
|
||||
|
41
net/web/src/User/Conversation/AddTopic/AddTopic.styled.js
Normal file
41
net/web/src/User/Conversation/AddTopic/AddTopic.styled.js
Normal file
@ -0,0 +1,41 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const AddTopicWrapper = styled.div`
|
||||
width: 100%;
|
||||
|
||||
.container {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 24px;
|
||||
border-top: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
.input {
|
||||
margin-top: 16px;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.option {
|
||||
padding-right: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.send {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-end;
|
||||
padding-top: 4px;
|
||||
}
|
||||
`;
|
||||
|
55
net/web/src/User/Conversation/AddTopic/useAddTopic.hook.js
Normal file
55
net/web/src/User/Conversation/AddTopic/useAddTopic.hook.js
Normal file
@ -0,0 +1,55 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export function useAddTopic() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
assets: [],
|
||||
messageText: null,
|
||||
messageColor: null,
|
||||
messageWeight: null,
|
||||
messageSize: null,
|
||||
backgroundColor: null,
|
||||
});
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const addAsset = (value) => {
|
||||
setState((s) => {
|
||||
s.assets.push(value);
|
||||
return { ...s };
|
||||
});
|
||||
}
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const actions = {
|
||||
addImage: (image) => { addAsset(image) },
|
||||
addVideo: (video) => { addAsset(video) },
|
||||
addAudio: (audio) => { addAsset(audio) },
|
||||
addIframe: (iframe) => { addAsset(iframe) },
|
||||
removeAsset: (idx) => {},
|
||||
setMessageText: (value) => {
|
||||
updateState({ messageText: value });
|
||||
},
|
||||
setMessageColor: (value) => {
|
||||
updateState({ messageColor: value });
|
||||
},
|
||||
setMessageWeight: (value) => {
|
||||
updateState({ messageWeight: value });
|
||||
},
|
||||
setMessageSize: (value) => {
|
||||
updateState({ messageSize: value });
|
||||
},
|
||||
setBackgroundColor: (value) => {
|
||||
updateState({ backgroundColor: value });
|
||||
},
|
||||
addTopic: () => {},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,9 @@ import styled from 'styled-components';
|
||||
export const SideBarWrapper = styled.div`
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
max-width: 300px;
|
||||
min-width: 260px;
|
||||
max-width: 300px;
|
||||
flex-shrink 0;
|
||||
border-right: 1px solid #8fbea7;
|
||||
background-color: #8fbea7;
|
||||
`;
|
||||
|
@ -1933,6 +1933,11 @@
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/resize-observer-browser@^0.1.6":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.7.tgz#294aaadf24ac6580b8fbd1fe3ab7b59fe85f9ef3"
|
||||
integrity sha512-G9eN0Sn0ii9PWQ3Vl72jDPgeJwRWhv2Qk/nQkJuWmRmOB4HX3/BhD5SE1dZs/hzPZL/WKnvF0RHdTSG54QJFyg==
|
||||
|
||||
"@types/resolve@1.17.1":
|
||||
version "1.17.1"
|
||||
resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz"
|
||||
@ -7688,6 +7693,14 @@ react-refresh@^0.11.0:
|
||||
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz"
|
||||
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
|
||||
|
||||
react-resize-detector@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-7.0.0.tgz#fbd46917ee905b7796c797aa6b301b454a6b9229"
|
||||
integrity sha512-Xd1POfpVzH9O3F/xB/0xYy2ijtKjE/z7y4c/aJP593YSzhPy2vDhsNPjes+uQbgL1RezxJajQ679qPs8K5LAFw==
|
||||
dependencies:
|
||||
"@types/resize-observer-browser" "^0.1.6"
|
||||
lodash "^4.17.21"
|
||||
|
||||
react-router-dom@^6.2.2:
|
||||
version "6.2.2"
|
||||
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.2.tgz"
|
||||
|
Loading…
x
Reference in New Issue
Block a user