rich text editor

This commit is contained in:
shamsmosowi
2019-11-28 09:40:54 +11:00
parent 2a73776c56
commit 4834e1361f
11 changed files with 448 additions and 14 deletions

View File

@@ -30,6 +30,7 @@
"hotkeys-js": "^3.7.2",
"lodash": "^4.17.15",
"query-string": "^6.8.3",
"quill-delta": "^4.2.1",
"ramda": "^0.26.1",
"react": "^16.9.0",
"react-color": "^2.17.3",
@@ -37,6 +38,7 @@
"react-data-grid-addons": "^6.1.0",
"react-dom": "^16.9.0",
"react-dropzone": "^10.1.8",
"react-quill": "^1.3.3",
"react-router-dom": "^5.0.1",
"react-scripts": "3.1.2",
"start": "^5.1.0",

View File

@@ -8,6 +8,7 @@ import Paper from "@material-ui/core/Paper";
import TextareaAutosize from "@material-ui/core/TextareaAutosize";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import EditorContext from "contexts/editorContext";
import { FieldType } from ".";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
@@ -38,7 +39,7 @@ const LongText = (props: Props) => {
<div className={classes.root}>
<IconButton
onClick={() => {
editorContext.open(props);
editorContext.open(props, FieldType.longText);
}}
>
<ExpandIcon />

View File

@@ -0,0 +1,47 @@
import React, { useContext } from "react";
import ExpandIcon from "@material-ui/icons/AspectRatio";
import IconButton from "@material-ui/core/IconButton";
import Typography from "@material-ui/core/Typography";
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
import EditorContext from "contexts/editorContext";
import { FieldType } from ".";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
position: "relative",
display: "flex",
flexWrap: "wrap",
},
typography: {
position: "relative",
marginTop: 15,
maxWidth: "calc(100% - 80px)",
wordWrap: "break-word",
},
})
);
interface Props {
value: any;
row: { ref: firebase.firestore.DocumentReference; id: string };
onSubmit: Function;
}
const RichText = (props: Props) => {
const editorContext = useContext(EditorContext);
const { value } = props;
const classes = useStyles();
return (
<div className={classes.root}>
<IconButton
onClick={() => {
editorContext.open(props, FieldType.richText);
}}
>
<ExpandIcon />
</IconButton>
<Typography className={classes.typography}>{value}</Typography>
</div>
);
};
export default RichText;

View File

@@ -20,6 +20,7 @@ import MenuItem from "@material-ui/core/MenuItem";
export enum FieldType {
simpleText = "SIMPLE_TEXT",
longText = "LONG_TEXT",
richText = "RICH_TEXT",
email = "EMAIL",
PhoneNumber = "PHONE_NUMBER",
checkBox = "CHECK_BOX",
@@ -55,6 +56,7 @@ export const FIELDS = [
{ icon: <FileIcon />, name: "Multi Select", type: FieldType.multiSelect },
{ icon: <FileIcon />, name: "Doc Select", type: FieldType.documentSelect },
{ icon: <FileIcon />, name: "Action", type: FieldType.action },
{ icon: <FileIcon />, name: "Rich Text", type: FieldType.richText },
{ icon: <PalleteIcon />, name: "Color", type: FieldType.color },
];

View File

@@ -6,6 +6,7 @@ import Fade from "@material-ui/core/Fade";
import TextareaAutosize from "@material-ui/core/TextareaAutosize";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import { FieldType } from "./Fields";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
test: { position: "absolute", top: 10, left: 10 },
@@ -37,6 +38,7 @@ interface Props {}
const LongTextEditor = (props: Props) => {
const classes = useStyles();
const editorContext = useContext(EditorContext);
if (editorContext.fieldType !== FieldType.longText) return <></>;
const isOpen = editorContext.editorValue !== null;
return (
<Modal

View File

@@ -0,0 +1,235 @@
import React, { useContext, useRef, useEffect } from "react";
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
import EditorContext from "contexts/editorContext";
import Modal from "@material-ui/core/Modal";
import Fade from "@material-ui/core/Fade";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import { FieldType } from "./Fields";
import ReactQuill from "react-quill";
import Delta from "quill-delta";
import "react-quill/dist/quill.snow.css";
import { bucket } from "../firebase";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
test: { position: "absolute", top: 10, left: 10 },
modal: {
display: "flex",
alignItems: "center",
justifyContent: "center",
maxWidth: 600,
width: "100%",
},
paper: { padding: theme.spacing(2) },
root: {
margin: `${theme.spacing(1)}px 0`,
"&:focus-within $sectionTitle": {
color:
theme.palette.type === "dark"
? theme.palette.primary.dark
: theme.palette.primary.main,
},
},
typography: {
padding: theme.spacing(2),
},
textArea: {
fontSize: 16,
minWidth: 230,
width: "100%",
},
quillEditor: {
minHeight: 100,
// match styling
"& .ql-toolbar": {
borderRadius: `${theme.shape.borderRadius}px ${theme.shape.borderRadius}px 0 0`,
transition: theme.transitions.create("border-color", {
duration: theme.transitions.duration.shortest,
}),
},
"& .ql-container": {
borderRadius: `0 0 ${theme.shape.borderRadius}px ${theme.shape.borderRadius}px`,
transition: theme.transitions.create("border-color", {
duration: theme.transitions.duration.shortest,
}),
},
"& .ql-editor": {
minHeight: 100,
fontFamily: theme.typography.fontFamily,
fontSize: ".875rem",
color: theme.palette.text.primary,
"&.ql-blank::before": {
fontStyle: "normal",
color: theme.palette.text.disabled,
},
},
// highlight border on focus
"&:focus-within .ql-toolbar.ql-snow, &:focus-within .ql-container.ql-snow": {
borderColor: theme.palette.primary.main,
},
// buttons stroke/fill colour matching
"& .ql-snow.ql-toolbar button, & .ql-snow .ql-picker-label": {
borderRadius: theme.shape.borderRadius / 2,
transition: theme.transitions.create("background-color", {
duration: theme.transitions.duration.shortest,
}),
},
"& .ql-snow .ql-stroke": {
stroke: theme.palette.text.primary,
transition: theme.transitions.create("stroke", {
duration: theme.transitions.duration.shortest,
}),
},
"& .ql-snow .ql-fill": {
fill: theme.palette.text.primary,
transition: theme.transitions.create("fill", {
duration: theme.transitions.duration.shortest,
}),
},
// colour buttons on hover
"& button:hover .ql-stroke": {
stroke: `${theme.palette.primary.main} !important`,
},
"& button:hover .ql-fill": {
fill: `${theme.palette.primary.main} !important`,
},
// highlight buttons when selected/active
"& .ql-snow.ql-toolbar .ql-active": {
backgroundColor: theme.palette.primary.light,
"& .ql-stroke": {
stroke: `${theme.palette.primary.main} !important`,
},
"& .ql-fill": {
fill: `${theme.palette.primary.main} !important`,
},
},
// dropdown styling
"& .ql-snow.ql-toolbar button:hover, & .ql-snow .ql-toolbar button:hover, & .ql-snow.ql-toolbar button:focus, & .ql-snow .ql-toolbar button:focus, & .ql-snow.ql-toolbar button.ql-active, & .ql-snow .ql-toolbar button.ql-active, & .ql-snow.ql-toolbar .ql-picker-label:hover, & .ql-snow .ql-toolbar .ql-picker-label:hover, & .ql-snow.ql-toolbar .ql-picker-label.ql-active, & .ql-snow .ql-toolbar .ql-picker-label.ql-active, & .ql-snow.ql-toolbar .ql-picker-item:hover, & .ql-snow .ql-toolbar .ql-picker-item:hover, & .ql-snow.ql-toolbar .ql-picker-item.ql-selected, & .ql-snow .ql-toolbar .ql-picker-item.ql-selected": {
color: theme.palette.primary.main,
"& polygon": { stroke: theme.palette.primary.main + " !important" },
},
},
})
);
interface Props {}
async function asyncUploader(ref: any, file: File) {
const documentRef = bucket.ref("test").child(ref);
const snapShot = await documentRef.put(file);
const downloadUrl = await bucket
.ref("test")
.child(snapShot.metadata.fullPath)
.getDownloadURL();
return downloadUrl;
}
const imageHandler = (quillRef: any) => () => {
const now = new Date();
const quill = quillRef.current.getEditor();
let fileInput: any = document.body.querySelector("input.ql-image[type=file]");
if (fileInput == null) {
fileInput = document.createElement("input");
fileInput.setAttribute("type", "file");
fileInput.setAttribute(
"accept",
"image/png, image/gif, image/jpeg, image/bmp, image/x-icon"
);
fileInput.classList.add("ql-image");
fileInput.addEventListener("change", async () => {
if (fileInput.files != null && fileInput.files[0] != null) {
const ref = `quill-images/${now.getTime()}/${fileInput.files[0].name}`;
const downloadUrl = await asyncUploader(ref, fileInput.files[0]);
let range = quill.getSelection(true);
quill.updateContents(
new Delta()
.retain(range.index)
.delete(range.length)
.insert({ image: downloadUrl }),
"user"
);
fileInput.value = "";
document.body.removeChild(fileInput);
}
});
document.body.appendChild(fileInput);
}
fileInput.click();
};
const RichTextEditor = (props: Props) => {
const classes = useStyles();
const editorContext = useContext(EditorContext);
const quillRef = useRef(null);
useEffect(() => {
if (quillRef !== null && quillRef.current) {
// quillRef.current
// .getEditor()
// .getModule("toolbar")
// .addHandler("image", imageHandler(quillRef));
}
}, [quillRef]);
if (editorContext.fieldType !== FieldType.richText) return <></>;
const isOpen = editorContext.editorValue !== null;
return (
<Modal
className={classes.modal}
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={isOpen}
onClose={() => {
editorContext.close();
}}
>
<Fade in={isOpen}>
<Paper className={classes.paper}>
<ReactQuill
//placeholder={placeholder}
value={editorContext.editorValue}
ref={quillRef}
onChange={val => {
// const dataURLregEx = /"data:.*?"/;
// let matches = val.match(dataURLregEx);
// delete matches.index;
// delete matches.input;
// delete matches.groups;
// console.log(matches);
editorContext.setEditorValue(val);
}}
theme="snow"
className={classes.quillEditor}
// preserveWhiteSpace
modules={{
toolbar: {
container: [
["bold", "italic", "underline"],
[{ header: [1, 2, 3, 4, false] }],
[{ list: "bullet" }, { list: "ordered" }],
[{ indent: "-1" }, { indent: "+1" }],
["blockquote", "code-block", "video"],
["link"],
],
},
clipboard: {
matchVisual: false,
},
}}
/>
<Typography variant="caption">
click away or press escape to save
</Typography>
</Paper>
</Fade>
</Modal>
);
};
export default RichTextEditor;

View File

@@ -13,6 +13,7 @@ const UrlLink = lazy(() => import("../Fields/UrlLink"));
const Image = lazy(() => import("../Fields/Image"));
const File = lazy(() => import("../Fields/File"));
const LongText = lazy(() => import("../Fields/LongText"));
const RichText = lazy(() => import("../Fields/RichText"));
const Color = lazy(() => import("../Fields/Color"));
const Action = lazy(() => import("../Fields/Action"));
@@ -26,6 +27,7 @@ export const editable = (fieldType: FieldType) => {
case FieldType.image:
case FieldType.file:
case FieldType.longText:
case FieldType.richText:
case FieldType.documentSelect:
case FieldType.color:
case FieldType.action:
@@ -164,7 +166,18 @@ export const cellFormatter = (column: any) => {
</Suspense>
);
};
case FieldType.richText:
return (props: any) => {
return (
<Suspense fallback={<div />}>
<RichText
{...props}
fieldName={key}
onSubmit={onSubmit(key, props.row)}
/>
</Suspense>
);
};
default:
return false;
}

View File

@@ -27,6 +27,7 @@ import Grid from "./Grid";
import Tooltip from "@material-ui/core/Tooltip";
import { EditorProvider } from "../../util/EditorProvider";
import LongTextEditor from "../LongTextEditor";
import RichTextEditor from "../RichTextEditor";
const Hotkeys = lazy(() => import("./HotKeys"));
const TableHeader = lazy(() => import("./TableHeader"));
@@ -297,6 +298,7 @@ function Table(props: Props) {
/>
<SearchBox searchData={search} clearSearch={clearSearch} />
<RichTextEditor />
<LongTextEditor />
</Suspense>
</EditorProvider>

View File

@@ -1,4 +1,5 @@
import React from "react";
import { FieldType } from "../components/Fields";
export interface EditorContextInterface {
// row: any;
@@ -9,6 +10,7 @@ export interface EditorContextInterface {
open: any;
close: any;
setEditorValue: any;
fieldType: FieldType | null;
}
const EditorContext = React.createContext<EditorContextInterface>({
@@ -20,6 +22,7 @@ const EditorContext = React.createContext<EditorContextInterface>({
close: undefined,
editorValue: undefined,
setEditorValue: undefined,
fieldType: null,
});
export default EditorContext;

View File

@@ -1,5 +1,6 @@
import React, { useState } from "react";
import EditorContext from "../contexts/editorContext";
import { FieldType } from "../components/Fields";
interface IEditorProviderProps {
children: React.ReactNode;
@@ -7,6 +8,7 @@ interface IEditorProviderProps {
export const EditorProvider: React.FC<IEditorProviderProps> = ({
children,
}) => {
const [fieldType, setFieldType] = useState<FieldType | null>(null);
const [props, setProps] = useState<any>();
const [editorValue, setEditorValue] = useState<null | string>(null);
const close = () => {
@@ -14,14 +16,19 @@ export const EditorProvider: React.FC<IEditorProviderProps> = ({
props.onSubmit(editorValue);
}
setEditorValue(null);
setFieldType(null);
};
const open = (props: {
row: any;
onSubmit: any;
fieldName: string;
value: string;
anchorEl: any;
}) => {
const open = (
props: {
row: any;
onSubmit: any;
fieldName: string;
value: string;
anchorEl: any;
},
type: FieldType
) => {
setFieldType(type);
setProps(props);
setEditorValue(props.value);
};
@@ -30,6 +37,7 @@ export const EditorProvider: React.FC<IEditorProviderProps> = ({
value={{
close,
open,
fieldType,
editorValue,
setEditorValue,
}}

View File

@@ -1653,6 +1653,13 @@
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
"@types/quill@1.3.10":
version "1.3.10"
resolved "https://registry.yarnpkg.com/@types/quill/-/quill-1.3.10.tgz#dc1f7b6587f7ee94bdf5291bc92289f6f0497613"
integrity sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==
dependencies:
parchment "^1.1.2"
"@types/ramda@^0.26.21":
version "0.26.21"
resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.26.21.tgz#cfd552c679453d153a9e2fd89ffc5dd5aa93d2c9"
@@ -2240,7 +2247,7 @@ arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
asap@^2.0.6, asap@~2.0.6:
asap@^2.0.6, asap@~2.0.3, asap@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
@@ -3233,6 +3240,11 @@ clone-deep@^4.0.1:
kind-of "^6.0.2"
shallow-clone "^3.0.0"
clone@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
clsx@^1.0.2, clsx@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec"
@@ -3538,6 +3550,11 @@ core-js@3.2.1:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.2.1.tgz#cd41f38534da6cc59f7db050fe67307de9868b09"
integrity sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==
core-js@^1.0.0:
version "1.2.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
core-js@^2.4.0, core-js@^2.5.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
@@ -3589,6 +3606,15 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
create-react-class@^15.6.0:
version "15.6.3"
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036"
integrity sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==
dependencies:
fbjs "^0.8.9"
loose-envify "^1.3.1"
object-assign "^4.1.1"
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -4812,6 +4838,11 @@ eventemitter3@1.x.x:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=
eventemitter3@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba"
integrity sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=
eventemitter3@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
@@ -4954,7 +4985,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
extend@~3.0.2:
extend@^3.0.2, extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@@ -4997,6 +5028,16 @@ fast-deep-equal@^2.0.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
fast-diff@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
fast-diff@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-glob@^2.0.2:
version "2.2.7"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
@@ -5040,6 +5081,19 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
fbjs@^0.8.9:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.18"
figgy-pudding@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
@@ -6619,7 +6673,7 @@ isobject@^4.0.0:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
isomorphic-fetch@2.2.1:
isomorphic-fetch@2.2.1, isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=
@@ -7702,7 +7756,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1:
"lodash@>=3.5 <5", lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -8778,6 +8832,11 @@ param-case@2.1.x:
dependencies:
no-case "^2.2.0"
parchment@^1.1.2, parchment@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5"
integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
@@ -9823,6 +9882,13 @@ promise@8.0.3:
dependencies:
asap "~2.0.6"
promise@^7.1.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==
dependencies:
asap "~2.0.3"
prompts@^2.0.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.2.1.tgz#f901dd2a2dfee080359c0e20059b24188d75ad35"
@@ -10001,6 +10067,36 @@ querystringify@^2.1.1:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
quill-delta@^3.6.2:
version "3.6.3"
resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032"
integrity sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==
dependencies:
deep-equal "^1.0.1"
extend "^3.0.2"
fast-diff "1.1.2"
quill-delta@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-4.2.1.tgz#ad4f191cdf3be5079c5dc3991b9603a5cc0db69a"
integrity sha512-Y2nksOj6Q+4hizre8n0dml76vLNGK4/y86EoI1d7rv6EL1bx7DPDYRmqQMPu1UqFQO/uQuVHQ3fOmm4ZSzWrfA==
dependencies:
deep-equal "^1.0.1"
extend "^3.0.2"
fast-diff "1.2.0"
quill@^1.2.6:
version "1.3.7"
resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8"
integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==
dependencies:
clone "^2.1.1"
deep-equal "^1.0.1"
eventemitter3 "^2.0.3"
extend "^3.0.2"
parchment "^1.1.4"
quill-delta "^3.6.2"
raf@3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@@ -10166,6 +10262,11 @@ react-dnd@^2.6.0:
lodash "^4.2.0"
prop-types "^15.5.10"
react-dom-factories@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/react-dom-factories/-/react-dom-factories-1.0.2.tgz#eb7705c4db36fb501b3aa38ff759616aa0ff96e0"
integrity sha1-63cFxNs2+1AbOqOP91lhaqD/luA=
react-dom@^16.9.0:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962"
@@ -10207,6 +10308,19 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
react-quill@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/react-quill/-/react-quill-1.3.3.tgz#95b8e088ad4e4acc6c79c2f85bdc0460eebe08eb"
integrity sha512-T9RubLaWJ8gCfp7sOqmFupjiTiEp/EdGqhCG+PWGKc5UHiK6xIWNKWYsOHHEhQ+sZCKs8u/DPx47gc1VfFmcLg==
dependencies:
"@types/quill" "1.3.10"
"@types/react" "*"
create-react-class "^15.6.0"
lodash "^4.17.4"
prop-types "^15.5.10"
quill "^1.2.6"
react-dom-factories "^1.0.0"
react-router-dom@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be"
@@ -11054,7 +11168,7 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@^1.0.4:
setimmediate@^1.0.4, setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
@@ -12087,6 +12201,11 @@ ua-parser-js@0.7.17:
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac"
integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==
ua-parser-js@^0.7.18:
version "0.7.20"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
uglify-js@3.4.x:
version "3.4.10"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"