@proca/widget
Version:
Proca is an open-source campaign toolkit designed to empower activists and organisations in their digital advocacy efforts. It provides a flexible and customisable platform for creating and managing online petitions, email campaigns, and other forms of di
187 lines (171 loc) • 4.48 kB
JavaScript
import React, { useState, useEffect, useLayoutEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Button, Card, CardActionArea } from "@material-ui/core";
import { List, ListItem } from "@material-ui/core";
import { useCampaignConfig } from "@hooks/useConfig";
//import UploadIcon from '@material-ui/icons/CloudUploadTwoTone';
import UploadIcon from "@material-ui/icons/PhotoCamera";
const useStyles = makeStyles(() => ({
overflow: {
overflow: "auto",
},
selected: {
opacity: "0.8",
position: "relative",
aawidth: "100%",
},
thumb: {
zIndex: 1,
width: "30%",
},
image: {
zIndex: 1,
width: "100%",
},
imageList: {
display: "flex",
padding: 0,
flexDirection: "row",
flexWrap: "nowrap",
width: "100%",
// Promote the list into his own layer on Chrome. This cost memory but helps keeping high FPS.
transform: "translateZ(0)",
cursor: "pointer",
aheight: "150px",
maxWidth: 350,
overflow: "auto",
"& img": {
maxHeight: 120,
width: 100,
maxWidth: "unset",
padding: "0!important",
marging: "0!important",
},
},
default: {
flex: "0 1 auto",
opacity: "0.2",
"&:hover": {
opacity: "0.8",
},
},
icon: {
color: "white",
},
input: {
display: "none",
},
}));
const UploadButton = props => {
const classes = useStyles();
const config = useCampaignConfig();
const getData = async file => {
return new Promise(resolve => {
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = event => {
const r = `data:${file.type};base64,${btoa(event.target.result)}`;
resolve(r);
};
});
};
const addImage = async event => {
const file = event.target.files[0];
const d = await getData(file);
props.addImage(d);
};
if (!config.component.meme?.upload) return null; // disable addImage
return (
<div className={classes.root}>
<input
accept="image/*"
className={classes.input}
id="contained-button-file"
onChange={addImage}
type="file"
/>
<label htmlFor="contained-button-file">
<Button
variant="contained"
color="primary"
component="span"
startIcon={<UploadIcon />}
>
Upload
</Button>
</label>
</div>
);
};
const ImageSelected = props => {
const classes = useStyles();
return (
<Card>
<CardActionArea>
<img
src={props.original}
alt={props.name || props.topText || "meme"}
className={classes.image}
/>
</CardActionArea>
</Card>
);
};
const ImageSelector = props => {
const classes = useStyles();
const [items, setItems] = useState(props.items);
const [selected, _select] = useState(0);
const [width, setWidth] = useState(350);
const select = i => {
_select(i);
if (props.onClick) props.onClick(i);
};
useLayoutEffect(() => {
setTimeout(() => {
const canvas = document.getElementById("proca-meme");
const width = canvas?.offsetWidth;
if (width) setWidth(width);
}, 2000);
}, [setWidth]);
useEffect(() => {
if (items.length === 0 && props.items.length > 0) setItems(props.items);
}, [props.items]);
const Selected = props.Selected || ImageSelected;
const addImage = data => {
const newImage = { original: data, top: "", bottom: "" };
//select (items.length);
if (props.addImage) props.addImage(newImage);
_select(items.length);
};
return (
<>
<Selected {...items[selected]} />
<List
component="div"
className={classes.imageList}
style={{ maxWidth: width }}
>
{items.map((_d, i) => (
<ListItem
component="div"
disableGutters={true}
dense={true}
key={i}
className={i === selected ? classes.selected : classes.default}
onClick={() => select(i)}
>
<img
src={items[i].original}
alt={items[i].name || items[i].topText || "meme"}
className={classes.thumb}
/>
</ListItem>
))}
<ListItem disableGutters={true} dense={true} key="new">
<UploadButton addImage={addImage} />
</ListItem>
</List>
</>
);
};
export default ImageSelector;