I want to change on the image slider used with UI material when I drag on the slider, but it changes only grayscale but nothing happens on the slider, why?
I will try to do function but I don't have idea how to do? somebody have?
import React, { useState, useEffect } from 'react';
import logo from '../logo.svg';
import defaultImage from '../Image/sen.jpg';
import Typography from "#material-ui/core/Typography";
import Slider from "#material-ui/lab/Slider";
function ImageSlider ({ value, max, onChange, children }) {
return (
<>
<Typography id="label">
{children}
</Typography>
<Slider className="slider"
min={0}
max={max}
value={value}
aria-labelledby="label"
step={1}
onChange={onChange}
/>
</>
)
}
export default function Hooks () {
const [name, setName] = useState('Franek!');
const [contrast, setContrast] = useState('100%');
const [brightness, setBrightness] = useState('100%');
const [invert, setInvert] = useState("0%");
const [hue, setHue] = useState("0deg");
const [saturate, setSaturate] = useState("100%");
const [sepia, setSepia] = useState("0%");
const [grayscale, setGrayscale] = useState('0%');
const [rotation, setRotation] = useState("0deg");
const [width, setWidth] = useState('0');
const [height, setHeight] = useState('0');
const [color, setColor] = useState('black');
const container = {
display: 'grid',
gridTemplateColumns: 'auto auto auto',
gridTemplateRows: '80px 200px',
gridGap: '200px',
padding: '10px'
}
const settings = {
width: '200px',
maxHeight: '1000px'
}
const buttonStyle = {
height: '50px',
width: '200px'
}
const parametersStyle = {
height: '50px',
width: '100px',
marginBlockEnd: '0',
marginBlockStart: '0',
backgroundColor: 'rgba(46, 56, 79, 0.85)',
padding: '1em'
}
const imgStyle = {
width: '300px',
height: '300px',
transform: `rotate(${rotation})`,
filter: `sepia(${sepia}) grayscale(${grayscale}) hue-rotate(${hue}) saturate(${saturate}) invert(${invert}) contrast(${contrast}) brightness(${brightness})`,
color: color
}
const elementChangingStyle = {
maxWidth: '600px',
maxHeight: '600px'
}
const headerTitle = {
color: '#ffffff',
fontSize: '40px',
padding: '1em'
}
// thiw function but they are get only 50 and see
function onGrayscale (e, grayscale) {
let newGrey = grayscale;
console.log("this onGrayscale " + setGrayscale('50'));
}
return (
<div>
<div style={headerTitle}>
React Photo-Modifier <br/> with Hooks
</div>
<div style={container}>
<div style={settings}>
<ImageSlider
max={100}
value={grayscale}
onChange={e => setGrayscale(e.target.value)}
>
Grayscale {grayscale}
</ImageSlider>
</div>
<div style={elementChangingStyle}>
<div>
<span>
<img src={logo} className="App-logo" alt="logo" />
</span>
</div>
<img style={imgStyle} src={defaultImage} />
<p style={imgStyle} > {name}</p>
</div>
</div>
</div>
)
}
If I triggered function onGrayscale the I have only slide to 50 but I want do this dynamically? How to do?
If I set ImageSlider to target value then change to grayscale but I can't then change manually using the slider?
What I'm doing wrong?
EDIT 1:
This. it's working now! Under the function and return in return.
function onGrayscale (e, grayscale) {
setGrayscale(grayscale);
}
<ImageSlider
max={100}
value={grayscale}
onChange={onGrayscale}
>
Grayscale {grayscale}
</ImageSlider>
You aren't using the function arguments correctly in onGrayScale function. This function is only passed the value and not the event, so it would look like
function onGrayscale (grayscale) {
let newGrey = grayscale;
setGrayscale(grayScale);
}
Related
I am visualising a List of Cards with content and what I want to achieve is to set contentEditable=true to the clicked card via its button. I am able to select the content of the element, however contentEditable is not set to true and it returns the following error instead:
Uncaught TypeError: Cannot create property 'contentEditable' on string
And I cant figure out why. What am I doing wrong here and how can I set contentEditable to true for the clicked element via its button?
Here is my code:
import * as React from 'react';
import { ListView } from '#progress/kendo-react-listview';
import { Input } from '#progress/kendo-react-inputs';
import {
Card,
CardTitle,
CardImage,
CardActions,
CardBody,
} from '#progress/kendo-react-layout';
import { Pager } from '#progress/kendo-react-data-tools';
import articles from '../data/articles.json';
import { BubbleChart } from "../components/products/BubbleChart"
const onEdit = (item) => {
console.log(item.Content)
let cardContent = item.Content.contentEditable = "true";
return cardContent
}
const MyItemRender = (props) => {
let item = props.dataItem;
return (
<div
style={{
padding: '20px 20px',
}}
className="parent-container"
>
<div className="k-card-list">
<Card
style={{
width: 260,
height: 340
}}
>
<CardBody
style={{
borderBottom: 'solid 1px rgba(0,0,0,.08)'
}}
>
<CardImage
src={require(`../assets/article-images/${item.Image}`)}
style={{
width: 260,
height: 140,
maxWidth: 260,
}}
/>
<CardTitle
style={{
fontSize: 18,
}}
/>
<CardTitle>{item.Title}</CardTitle>
<CardTitle>{item.Subtitle}</CardTitle>
<p className="content">
Some quick example text to build on the card title and make up the
bulk of the card content.
</p>
</CardBody>
<CardActions>
<div className="footer-buttons-container">
<span>
<span className="k-button k-button-md k-button-rectangle k-rounded-md k-button-flat k-button-flat-base">
<span className="k-icon k-i-preview"></span>Review
</span>
</span>
<span>
<span className="k-button k-edit-button k-button-md k-button-rectangle k-rounded-md k-button-flat k-button-flat-primary" onClick={() => onEdit(item)}>
<span className="k-icon k-i-edit"></span>Edit
</span>
</span>
</div>
</CardActions>
</Card>
</div>
</div>
);
};
export const Products = () => {
const [filteredList, setFilteredList] = React.useState(articles);
const [value, setValue] = React.useState('');
const [page, setPage] = React.useState({
skip: 0,
take: 10,
});
const handlePageChange = (e) => {
setPage({
skip: e.skip,
take: e.take,
});
};
const handleChange = React.useCallback((event) => {
setValue(event.target.value);
const results = articles.filter(post => {
if (event.target.value === "") return articles
return post.Title.includes(event.target.value)
})
console.log(results)
setFilteredList(results)
});
const { skip, take } = page;
return <div>
<div className="chart-container">
<br/>
<br/>
<BubbleChart/>
</div>
<div className="input-container">
<Input
style={{
border: '2px solid #ccc',
boxShadow: 'inset 0px 0px 0.5px 0px rgba(0,0,0,0.0.1)',
}}
placeholder={'Search'}
value={value}
onChange={handleChange}
/>
</div>
<div className="listbox-card-container">
<ListView
data={filteredList.slice(skip, skip + take)}
item={MyItemRender}
style={{
width: '100%',
height: '100%',
}}
/>
<Pager
skip={skip}
take={take}
onPageChange={handlePageChange}
total={articles.length}
/>
</div>
</div>
}
Can't do multiple assigning in one line. add separate lines
const onEdit = (item) => {
console.log(item.Content)
const content = {...item.Content }
content.contentEditable = "true";
return content
}
I've been trying to upload multiple images WITH preview in NextJS (React). I tried changing the constants to arrays and tried mapping through them but it just doesn't seem to work and I don't know how I could get it to work.
I've made a component out of the upload functionality and here is the code that works for uploading a single image with a Preview.
uploadImage.js
import React, { useEffect, useRef, useState } from "react";
import styled from "styled-components";
function imageUpload() {
const [image, setImage] = useState(null);
const fileInputRef = useRef();
const [preview, setPreview] = useState();
useEffect(() => {
if (image) {
const reader = new FileReader();
reader.onloadend = () => {
setPreview(reader.result);
};
reader.readAsDataURL(image);
} else {
}
}, [image]);
return (
<div className="flex ">
<StyledImg
src={preview}
style={{ objectFit: "cover" }}
onClick={() => setImage(null)}
/>
<StyledButton
onClick={(e) => {
e.preventDefault();
fileInputRef.current.click();
}}
/>
<input
type="file"
style={{ display: "none" }}
accept="image/*"
ref={fileInputRef}
onChange={(e) => {
const file = e.target.files[0];
if (file && file.type.substr(0, 5) === "image") {
setImage(file);
} else {
setImage(null);
}
}}
/>
</div>
);
}
const StyledButton = styled.button`
`;
const StyledImg = styled.img`
width: 100px;
height: 100px;
margin-right: 10px;
`;
export default imageUpload;
Based on these references https://react-dropzone.js.org/#section-previews and https://stackblitz.com/edit/nextjs-buk2rw?file=pages%2Findex.js I replaced my code with the following
ImageUpload.js
import React, { useEffect, useState } from "react";
import { useDropzone } from "react-dropzone";
import styled from "styled-components";
function DragAndDrop() {
const [files, setFiles] = useState([]);
const { getRootProps, getInputProps } = useDropzone({
accept: "image/*",
onDrop: (acceptedFiles) => {
setFiles((files) => [
...files,
...acceptedFiles.map((file) =>
Object.assign(file, {
key: file.name + randomId(), // to allow adding files with same name
preview: URL.createObjectURL(file),
})
),
]);
},
});
const removeFile = (file) => {
setFiles((files) => {
const newFiles = [...files];
newFiles.splice(file, 1);
return newFiles;
});
};
const thumbs = files.map((file, i) => (
<div style={thumb} key={file.key}>
<div style={thumbInner}>
<img src={file.preview} style={img} />
</div>
<button type="button" style={removeButton} onClick={() => removeFile(i)}>
X
</button>
</div>
));
useEffect(
() => () => {
files.forEach((file) => URL.revokeObjectURL(file.preview));
},
[files]
);
return (
<section className="container">
<div {...getRootProps({ className: "dropzone" })}>
<input {...getInputProps()} />
<StyledP className="flex align-center justify-center">
Glisser Images Ici ou Cliquer pour selectionner
</StyledP>
</div>
<aside style={thumbsContainer}>{thumbs}</aside>
</section>
);
}
const StyledP = styled.p`
cursor: pointer;
padding: 30px;
`;
const randomId = () => (Math.random() + 1).toString(36).substring(7);
const thumbsContainer = {
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
marginTop: 16,
};
const thumb = {
display: "inline-flex",
borderRadius: 2,
border: "1px solid #eaeaea",
marginBottom: 8,
marginRight: 8,
width: 100,
height: 100,
padding: 4,
boxSizing: "border-box",
position: "relative",
};
const thumbInner = {
display: "flex",
minWidth: 0,
overflow: "hidden",
};
const img = {
display: "block",
width: "auto",
height: "100%",
};
const removeButton = {
color: "red",
position: "absolute",
right: 4,
};
export default DragAndDrop;
Haven't made this feature before where you can change the color of button's hover.
I have already made a feature to change the radius with a slider, background color and font color using color-picker. However, I noticed the hover (for background AND font) could be better.
Here is the code:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Grid from "#material-ui/core/Grid";
import Slider from "#material-ui/core/Slider";
import Input from "#material-ui/core/Input";
import Button from "#material-ui/core/Button";
import { ChromePicker } from "react-color";
const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1)
}
},
Button: {
width: 150,
height: 50,
borderRadius: "var(--borderRadius)"
},
color: {
width: "36px",
height: "14px",
borderRadius: "2px"
},
swatch: {
padding: "5px",
background: "#fff",
borderRadius: "1px",
display: "inline-block",
cursor: "pointer"
},
popover: {
position: "absolute",
zIndex: "2"
},
cover: {
position: "fixed",
top: "0px",
right: "0px",
bottom: "0px",
left: "0px"
}
}));
export default function InputSlider() {
const classes = useStyles();
const [value, setValue] = React.useState(30);
const [color, setColor] = React.useState({ r: 0, g: 0, b: 0, a: 1 });
const [fontColor, setFontColor] = React.useState({
r: 255,
g: 255,
b: 255,
a: 1
});
const [displayColorPicker, setDisplayColorPicker] = React.useState(true);
const handleSliderChange = (event, newValue) => {
setValue(newValue);
};
const handleInputChange = (event) => {
setValue(event.target.value === "" ? "" : Number(event.target.value));
};
const handleBlur = () => {
if (value < 0) {
setValue(0);
} else if (value > 30) {
setValue(30);
}
};
const handleClick = () => {
setDisplayColorPicker(!displayColorPicker);
};
const handleClose = () => {
setDisplayColorPicker(false);
};
const handleChange = (color) => {
setColor(color.rgb);
};
const handleFontColorChange = (color) => {
setFontColor(color.rgb);
};
return (
<div className={classes.root}>
<style>
{`:root {
--borderRadius = ${value}px;
}`}
</style>
<Button
style={{
borderRadius: value,
background: `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`,
color: `rgba(${fontColor.r}, ${fontColor.g}, ${fontColor.b}, ${fontColor.a})`
}}
variant="contained"
color="primary"
value="value"
onChange={handleSliderChange}
className={classes.Button}
>
Fire laser
</Button>
<Grid container spacing={2}>
<Grid item xs>
<Slider
value={typeof value === "number" ? value : 0}
onChange={handleSliderChange}
aria-labelledby="input-slider"
/>
</Grid>
<Grid item>
<Input
value={value}
margin="dense"
onChange={handleInputChange}
onBlur={handleBlur}
inputProps={{
step: 10,
min: 0,
max: 24,
type: "number"
}}
/>
</Grid>
</Grid>
<div>
<div style={useStyles.swatch} onClick={handleClick}>
{displayColorPicker} <p class="h4">Background</p>
<div style={useStyles.color} />
</div>
{displayColorPicker ? (
<div style={useStyles.popover}>
<div style={useStyles.cover} onClick={handleClose}></div>
<ChromePicker color={color} onChange={handleChange} />
</div>
) : null}
</div>
<div>
<div style={useStyles.swatch} onClick={handleClick}>
{displayColorPicker} <p class="h4">Font</p>
<div style={useStyles.color} />
</div>
{displayColorPicker ? (
<div style={useStyles.popover}>
<div style={useStyles.cover} onClick={handleClose}></div>
<ChromePicker color={fontColor} onChange={handleFontColorChange} />
</div>
) : null}
</div>
</div>
);
}
And here is the sandbox - https://codesandbox.io/s/material-demo-forked-t8xut?file=/demo.js
Any advice?
Does anyone have a good Material UI article for editing/cool features and projects to play with?
You need to pass props to makeStyles.
First, pass fontColor variable as below when declaring classes:
const classes = useStyles({ hoverBackgroundColor, hoverFontColor })();
then in the useStyles, you can have access to the fontColor as a prop, as below:
const useStyles = ({ hoverBackgroundColor, hoverFontColor }) =>
makeStyles((theme) => ({
Button: {
width: 150,
height: 50,
borderRadius: "var(--borderRadius)",
"&:hover": {
backgroundColor: `rgba(${hoverBackgroundColor.r}, ${hoverBackgroundColor.g}, ${hoverBackgroundColor.b}, ${hoverBackgroundColor.a}) !important`,
color: `rgba(${hoverFontColor.r}, ${hoverFontColor.g}, ${hoverFontColor.b}, ${hoverFontColor.a}) !important`
}
},
sandbox
I have multiple external makestyle that I want to combine. So, I can organize the style per component. The single makestyle is also good but the length of the file is too much.
I saw this on material ui documentation but it's not working
Makestyle
import useStyles from '../styles/style';
import useAddTaskStyles from '../styles/addTaskStyle';
const classes = useStyles();
const classesAddTask = useAddTaskStyles();
const className = clsx(classes, classesAddTask);
<Modal
className={className.modalContainer}
open={showAddTask}
onClose={handleCloseAddTask}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={showAddTask}>
<Tasks ref={useRef} />
</Fade>
</Modal>
import useStyles from '../styles/style';
import useAddTaskStyles from '../styles/addTaskStyle';
const classes = useStyles();
const classesAddTask = useAddTaskStyles();
<Modal
className={`${classes.modalContainer} ${classesAddTask.modalContainer}`}
open={showAddTask}
onClose={handleCloseAddTask}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<Fade in={showAddTask}>
<Tasks ref={useRef} />
</Fade>
</Modal>;
You may combine it like this
const className = { ...classes, ...classesAddTask }
Codesandbox => https://codesandbox.io/s/nice-fire-xgvz2?file=/src/App.js
For Example (creating a useStyle hook that combines all style hooks)
import { makeStyles } from "#material-ui/styles";
const useStyles1 = makeStyles({
red: {
backgroundColor: "red"
}
});
const useStyles2 = makeStyles({
blue: {
backgroundColor: "blue"
}
});
const useStyles = () => {
const classes = useStyles1();
const classes2 = useStyles2();
return { ...classes, ...classes2 };
};
export default function App() {
const classes = useStyles();
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div className={classes.blue} style={{ width: "200px", height: "200px" }}>
blue box
</div>
<div className={classes.red} style={{ width: "200px", height: "200px" }}>
red box
</div>
</div>
);
}
I've tried multiple different ways to try to attach an image in draft-js.
My attempts followed the example in the tutorial https://www.draft-js-plugins.com/plugin/image. For the "Add Image Button Example", the full source of which can be found here https://github.com/draft-js-plugins/draft-js-plugins/tree/master/docs/client/components/pages/Image/AddImageEditor. I have also tried to follow this medium article that does not use the image plugin to do a similar thing https://medium.com/#siobhanpmahoney/building-a-rich-text-editor-with-react-and-draft-js-part-2-4-persisting-data-to-server-cd68e81c820.
If I set the initial state with the image already embedded it renders. However, when using a mechanism that adds it later on it doesn't seem to work. I've read some mentions of various version of plugins / draft.js having issues.
My versions:
"draft-js-image-plugin": "^2.0.7",
"draft-js": "^0.11.6",
import { EditorState } from 'draft-js';
import Editor from 'draft-js-plugins-editor';
import createInlineToolbarPlugin, { Separator } from 'draft-js-inline-toolbar-plugin';
import createImagePlugin from 'draft-js-image-plugin';
import 'draft-js/dist/Draft.css';
import 'draft-js-inline-toolbar-plugin/lib/plugin.css';
import {
ItalicButton,
BoldButton,
UnderlineButton,
HeadlineOneButton,
CodeButton,
UnorderedListButton,
OrderedListButton,
BlockquoteButton,
} from 'draft-js-buttons';
interface TextEditorProps {
label?: string;
value: EditorState;
onChange?: (editorState: EditorState) => void;
className?: string;
disabled?: boolean;
}
const useStyles = makeStyles((theme) => ({
label: {
margin: theme.spacing(1)
},
editor: {
boxSizing: 'border-box',
border: '1px solid #ddd',
cursor: 'text',
padding: '16px',
borderRadius: '2px',
marginBottom: '2em',
boxShadow: 'inset 0px 1px 8px -3px #ABABAB',
background: '#fefefe',
minHeight: '50vh'
}
}));
const inlineToolbarPlugin = createInlineToolbarPlugin();
const imagePlugin = createImagePlugin();
const { InlineToolbar } = inlineToolbarPlugin;
const plugins = [inlineToolbarPlugin, imagePlugin];
const TextEditor:React.FunctionComponent<TextEditorProps> = ({label, value, onChange, className, disabled }: TextEditorProps) => {
const editor = React.useRef(null);
const focusEditor = () => {
editor.current.focus();
}
React.useEffect(() => {
focusEditor()
}, []);
const classes = useStyles();
const insertImage = () => {
onChange(imagePlugin.addImage(value, "https://ichef.bbci.co.uk/news/976/cpsprodpb/12A9B/production/_111434467_gettyimages-1143489763.jpg"));
}
return (
<Box className={className} onClick={focusEditor}>
{label && <InputLabel className={classes.label}>{label}</InputLabel>}
<div className="menuButtons">
<button className="inline styleButton">
<i
className="material-icons"
style={{
fontSize: "16px",
textAlign: "center",
padding: "0px",
margin: "0px"
}}
onClick={insertImage}
>
image
</i>
</button>
</div>
<Box className={!disabled && classes.editor} >
<Editor
ref={editor}
editorState={value}
onChange={onChange}
plugins={plugins}
spellCheck={true}
readOnly={disabled}
/>
{<InlineToolbar>
{(externalProps) => (
<>
<BoldButton {...externalProps} />
<ItalicButton {...externalProps} />
<UnderlineButton {...externalProps} />
<CodeButton {...externalProps} />
<Separator {...externalProps} />
<UnorderedListButton {...externalProps} />
<OrderedListButton {...externalProps} />
<BlockquoteButton {...externalProps} />
<HeadlineOneButton {...externalProps} />
</>
)}
</InlineToolbar>}
</Box>
</Box>
)
}
You editorState change is overriding the change from insertImage. You are triggering focusEditor along with onClick insertImage
Don't need additional plugins, if you don't mind getting hands dirty and learning how to insert into content.
<i
className="material-icons"
style={{
fontSize: "16px",
textAlign: "center",
padding: "0px",
margin: "0px"
}}
onClick={() => insertImage('https://ichef.bbci.co.uk/news/976/cpsprodpb/12A9B/production/_111434467_gettyimages-1143489763.jpg')}
>
custom insertImage function, in your case, editorState should be replaced with 'value'
import { EditorState, AtomicBlockUtils } from “draft-js”; //<-- need add this import
const insertImage = ( url ) => {
const contentState = editorState.getCurrentContent();
const contentStateWithEntity = contentState.createEntity(
'IMAGE',
'IMMUTABLE',
{ src: url },)
const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
const newEditorState = EditorState.set( editorState, { currentContent: contentStateWithEntity });
onChange(AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, '')) //Update the editor state
};
image upload with draftjs