add ImportWizard, Step1

This commit is contained in:
Sidney Alcantara
2020-08-31 14:40:52 +10:00
parent 8fe92f3cd1
commit 41037845b6
10 changed files with 563 additions and 27 deletions

View File

@@ -30,6 +30,7 @@
"ramda": "^0.26.1",
"react": "^16.9.0",
"react-ace": "^9.1.1",
"react-beautiful-dnd": "^13.0.0",
"react-color": "^2.17.3",
"react-data-grid": "^7.0.0-alpha.29",
"react-data-grid-addons": "^7.0.0-alpha.24",
@@ -85,6 +86,7 @@
"@types/lodash": "^4.14.138",
"@types/ramda": "^0.26.21",
"@types/react": "^16.9.2",
"@types/react-beautiful-dnd": "^13.0.0",
"@types/react-color": "^3.0.1",
"@types/react-div-100vh": "^0.3.0",
"@types/react-dom": "16.9.0",

View File

@@ -1,14 +1,26 @@
import React from "react";
import { TextField, MenuItem, ListItemIcon } from "@material-ui/core";
import {
TextField,
MenuItem,
ListItemIcon,
TextFieldProps,
} from "@material-ui/core";
import { FIELDS, FieldType } from "constants/fields";
export interface IFieldsDropdownProps {
value: FieldType;
onChange: TextFieldProps["onChange"];
}
/**
* Returns dropdown component of all available types
*/
const FieldsDropdown = (props: { value: FieldType | null; onChange: any }) => {
const { value, onChange } = props;
export default function FieldsDropdown({
value,
onChange,
}: IFieldsDropdownProps) {
return (
<TextField
fullWidth
@@ -36,6 +48,4 @@ const FieldsDropdown = (props: { value: FieldType | null; onChange: any }) => {
)}
</TextField>
);
};
export default FieldsDropdown;
}

View File

@@ -1,15 +1,20 @@
import React, { useState, useEffect } from "react";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";
import Dialog from "@material-ui/core/Dialog";
import Grid from "@material-ui/core/Grid";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import { Typography, IconButton } from "@material-ui/core";
import _camel from "lodash/camelCase";
import {
Button,
TextField,
Dialog,
Grid,
DialogActions,
DialogContent,
Typography,
IconButton,
} from "@material-ui/core";
import CloseIcon from "@material-ui/icons/Close";
import { FieldType } from "constants/fields";
import FieldsDropdown from "./FieldsDropdown";
import _camel from "lodash/camelCase";
export default function FormDialog({
open,
@@ -63,7 +68,7 @@ export default function FormDialog({
label="Column Header"
type="text"
fullWidth
onChange={e => {
onChange={(e) => {
setColumnLabel(e.target.value);
}}
/>
@@ -75,7 +80,7 @@ export default function FormDialog({
label="Field Key"
type="text"
fullWidth
onChange={e => {
onChange={(e) => {
setFieldKey(e.target.value);
}}
/>
@@ -83,8 +88,8 @@ export default function FormDialog({
<FieldsDropdown
value={type}
onChange={(newType: any) => {
setType(newType.target.value);
onChange={(newType) => {
setType(newType.target.value as FieldType);
}}
/>
</DialogContent>

View File

@@ -0,0 +1,102 @@
import React from "react";
import clsx from "clsx";
import {
makeStyles,
createStyles,
Grid,
GridProps,
Typography,
} from "@material-ui/core";
import { fade } from "@material-ui/core/styles";
import { FieldType, getFieldIcon } from "constants/fields";
const useStyles = makeStyles((theme) =>
createStyles({
root: {
width: "100%",
height: 44,
border: `1px solid ${theme.palette.divider}`,
backgroundColor: theme.palette.background.default,
padding: theme.spacing(0, 1.5),
color: theme.palette.text.secondary,
transition: theme.transitions.create("color", {
duration: theme.transitions.duration.short,
}),
"&:hover": { color: theme.palette.text.primary },
"& svg": { display: "block" },
},
active: {
backgroundColor: fade(
theme.palette.primary.main,
theme.palette.action.activatedOpacity
),
color: theme.palette.primary.main,
borderColor: fade(
theme.palette.primary.main,
theme.palette.action.disabledOpacity
),
"&:hover": { color: theme.palette.primary.dark },
},
columnName: {
lineHeight: "44px",
display: "block",
userSelect: "none",
marginLeft: theme.spacing(0.5),
marginTop: -1,
},
})
);
export interface IColumnProps extends Partial<GridProps> {
label: string;
type?: FieldType;
secondaryItem?: React.ReactNode;
active?: boolean;
}
export default function Column({
label,
type,
secondaryItem,
active,
...props
}: IColumnProps) {
const classes = useStyles();
return (
<Grid
container
alignItems="center"
className={clsx(classes.root, active && classes.active)}
{...props}
>
{type && <Grid item>{getFieldIcon(type)}</Grid>}
<Grid item xs>
<Typography
component={Grid}
item
variant="caption"
noWrap
className={classes.columnName}
>
{label}
</Typography>
</Grid>
{secondaryItem && <Grid item>{secondaryItem}</Grid>}
</Grid>
);
}

View File

@@ -0,0 +1,53 @@
import React from "react";
import { makeStyles, createStyles } from "@material-ui/core";
const useStyles = makeStyles((theme) =>
createStyles({
listWrapper: {
position: "relative",
"&::after": {
content: '""',
display: "block",
pointerEvents: "none",
position: "absolute",
bottom: 0,
left: 0,
right: 0,
height: theme.spacing(3),
backgroundImage: `linear-gradient(to top, ${theme.palette.background.paper}, transparent)`,
},
},
list: {
listStyleType: "none",
margin: 0,
padding: theme.spacing(1.5, 0, 2.5),
height: 200,
overflowY: "auto",
"& li": { margin: theme.spacing(0.5, 0) },
},
})
);
export interface IFadeListProps {
children?: React.ReactNode | React.ElementType[];
}
export const FadeList = React.forwardRef<HTMLDivElement, IFadeListProps>(
function FadeList_({ children }, ref) {
const classes = useStyles();
return (
<div className={classes.listWrapper} ref={ref}>
<ul className={classes.list}>{children}</ul>
</div>
);
}
);
export default FadeList;

View File

@@ -0,0 +1,167 @@
import React, { useMemo, useState, useEffect } from "react";
import {
DragDropContext,
DropResult,
Droppable,
Draggable,
} from "react-beautiful-dnd";
import _sortBy from "lodash/sortBy";
import {
makeStyles,
createStyles,
Grid,
Typography,
Divider,
FormControlLabel,
Checkbox,
} from "@material-ui/core";
import DragHandleIcon from "@material-ui/icons/DragHandle";
import { IStepProps } from ".";
import FadeList from "./FadeList";
import Column from "./Column";
import EmptyState from "components/EmptyState";
import AddColumnIcon from "assets/icons/ColumnPlusAfter";
import { useFiretableContext } from "contexts/firetableContext";
import { FieldType } from "constants/fields";
const useStyles = makeStyles(() =>
createStyles({
formControlLabel: { marginRight: 0 },
columnLabel: { flex: 1 },
})
);
export default function Step1Columns({ config, setConfig }: IStepProps) {
const classes = useStyles();
// Get a list of fields from first 50 documents
const { tableState } = useFiretableContext();
const allFields = useMemo(() => {
const sample = tableState!.rows.slice(0, 50);
const fields_ = new Set<string>();
sample.forEach((doc) =>
Object.keys(doc).forEach((key) => fields_.add(key))
);
return Array.from(fields_).sort();
}, [tableState?.rows]);
// Store selected fields
const [selectedFields, setSelectedFields] = useState<string[]>(
_sortBy(Object.keys(config), "index")
);
const handleSelect = (field: string) => (_, checked: boolean) => {
if (checked) {
setSelectedFields([...selectedFields, field]);
} else {
const newSelection = [...selectedFields];
newSelection.splice(newSelection.indexOf(field), 1);
setSelectedFields(newSelection);
}
};
const handleDragEnd = (result: DropResult) => {
const newOrder = [...selectedFields];
const [removed] = newOrder.splice(result.source.index, 1);
newOrder.splice(result.destination!.index, 0, removed);
setSelectedFields(newOrder);
};
useEffect(() => {
setConfig(
selectedFields.reduce(
(a, c, i) => ({
...a,
[c]: {
fieldName: c,
key: c,
name: c,
type: FieldType.shortText,
index: i,
},
}),
{}
)
);
}, [selectedFields]);
return (
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<Typography variant="overline" gutterBottom component="h2">
Select Columns ({selectedFields.length} of {allFields.length})
</Typography>
<Divider />
<FadeList>
{allFields.map((field) => (
<li key={field}>
<FormControlLabel
key={field}
control={
<Checkbox
checked={selectedFields.indexOf(field) > -1}
aria-label={`Select column ${field}`}
onChange={handleSelect(field)}
color="default"
/>
}
label={<Column label={field} />}
classes={{
root: classes.formControlLabel,
label: classes.columnLabel,
}}
/>
</li>
))}
</FadeList>
</Grid>
<Grid item xs={12} sm={6}>
<Typography variant="overline" gutterBottom component="h2">
Sort Firetable Columns
</Typography>
<Divider />
{selectedFields.length === 0 ? (
<FadeList>
<EmptyState Icon={AddColumnIcon} message="No columns selected" />
</FadeList>
) : (
<DragDropContext onDragEnd={handleDragEnd}>
<FadeList>
<Droppable droppableId="droppable">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{selectedFields.map((field, i) => (
<li key={field}>
<Draggable draggableId={field} index={i}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<Column
label={field}
active={snapshot.isDragging}
secondaryItem={<DragHandleIcon />}
/>
</div>
)}
</Draggable>
</li>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</FadeList>
</DragDropContext>
)}
</Grid>
</Grid>
);
}

View File

@@ -0,0 +1,120 @@
import React, { useState } from "react";
import { Typography } from "@material-ui/core";
import WizardDialog from "../WizardDialog";
import Step1Columns from "./Step1Columns";
import { ColumnConfig } from "hooks/useFiretable/useTableConfig";
import { useFiretableContext } from "contexts/firetableContext";
import { FieldType } from "constants/fields";
export type TableColumnsConfig = { [key: string]: ColumnConfig };
export interface IStepProps {
config: TableColumnsConfig;
setConfig: React.Dispatch<React.SetStateAction<TableColumnsConfig>>;
}
export default function ImportWizard() {
const [config, setConfig] = useState<TableColumnsConfig>({
attachments: {
fieldName: "attachments",
key: "attachments",
name: "attachments",
type: FieldType.shortText,
index: 0,
},
calendarEventDescription: {
fieldName: "calendarEventDescription",
key: "calendarEventDescription",
name: "calendarEventDescription",
type: FieldType.shortText,
index: 1,
},
email: {
fieldName: "email",
key: "email",
name: "email",
type: FieldType.shortText,
index: 2,
},
isInvestor: {
fieldName: "isInvestor",
key: "isInvestor",
name: "isInvestor",
type: FieldType.shortText,
index: 3,
},
introVideo: {
fieldName: "introVideo",
key: "introVideo",
name: "introVideo",
type: FieldType.shortText,
index: 4,
},
introDemoDay: {
fieldName: "introDemoDay",
key: "introDemoDay",
name: "introDemoDay",
type: FieldType.shortText,
index: 5,
},
sectors: {
fieldName: "sectors",
key: "sectors",
name: "sectors",
type: FieldType.shortText,
index: 6,
},
resend: {
fieldName: "resend",
key: "resend",
name: "resend",
type: FieldType.shortText,
index: 7,
},
showOnDemoDayWebsite: {
fieldName: "showOnDemoDayWebsite",
key: "showOnDemoDayWebsite",
name: "showOnDemoDayWebsite",
type: FieldType.shortText,
index: 8,
},
});
const { tableState } = useFiretableContext();
if (tableState?.rows.length === 0) return null;
return (
<WizardDialog
open
title="Import"
steps={[
{
title: "choose columns",
description: (
<>
<Typography gutterBottom>
It looks like you already have data in this table. You can
import and view the data by setting up columns for this table.
</Typography>
<Typography gutterBottom>
Start by choosing which columns you want to display.
</Typography>
</>
),
content: <Step1Columns config={config} setConfig={setConfig} />,
disableNext: Object.keys(config).length === 0,
},
{
title: "rename columns",
description:
"Rename your Firetable columns with user-friendly names. These changes will not update the field names in your database.",
content: <Step1Columns config={config} setConfig={setConfig} />,
},
]}
onFinish={() => alert("FINISHED")}
/>
);
}

View File

@@ -1,16 +1,15 @@
import { useEffect } from "react";
import { useDebouncedCallback } from "use-debounce";
import useDoc, { DocActions } from "../useDoc";
import { FieldType } from "constants/fields";
import _camelCase from "lodash/camelCase";
import _findIndex from "lodash/findIndex";
import _find from "lodash/find";
import _sortBy from "lodash/sortBy";
import useDoc, { DocActions } from "../useDoc";
import { FieldType } from "constants/fields";
import { arrayMover, isCollectionGroup } from "../../util/fns";
import { db, deleteField } from "../../firebase";
//import
const formatPathRegex = /\/[^\/]+\/([^\/]+)/g;
const formatPath = (tablePath: string) => {
@@ -18,6 +17,18 @@ const formatPath = (tablePath: string) => {
isCollectionGroup() ? "groupSchema" : "schema"
}/${tablePath.replace(formatPathRegex, "/subTables/$1")}`;
};
export type ColumnConfig = {
fieldName: string;
key: string;
name: string;
type: FieldType;
index: number;
width?: number;
editable?: boolean;
[key: string]: any;
};
const useTableConfig = (tablePath?: string) => {
const [tableConfigState, documentDispatch] = useDoc({
path: tablePath ? formatPath(tablePath) : "",
@@ -125,7 +136,7 @@ const useTableConfig = (tablePath?: string) => {
let updatedColumns = columns;
columnsArray
.filter(c => c) // arrayMover has a bug creating undefined items
.filter((c) => c) // arrayMover has a bug creating undefined items
.forEach((column: any, index) => {
console.log({ column });
updatedColumns[column.key] = { ...column, index };

View File

@@ -11,6 +11,8 @@ import SideDrawer from "components/SideDrawer";
import { FireTableFilter } from "hooks/useFiretable";
import useRouter from "hooks/useRouter";
import ImportWizard from "components/Wizards/ImportWizard";
export default function TableView() {
const router = useRouter();
const tableCollection = decodeURIComponent(router.match.params.id);
@@ -38,6 +40,9 @@ export default function TableView() {
return (
<Navigation tableCollection={tableCollection}>
<Table key={tableCollection} />
<ImportWizard />
<Hidden smDown>
<SideDrawer />
</Hidden>

View File

@@ -2074,6 +2074,13 @@
dependencies:
ts-toolbelt "^6.3.3"
"@types/react-beautiful-dnd@^13.0.0":
version "13.0.0"
resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz#e60d3d965312fcf1516894af92dc3e9249587db4"
integrity sha512-by80tJ8aTTDXT256Gl+RfLRtFjYbUWOnZuEigJgNsJrSEGxvFe5eY6k3g4VIvf0M/6+xoLgfYWoWonlOo6Wqdg==
dependencies:
"@types/react" "*"
"@types/react-color@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/react-color/-/react-color-3.0.1.tgz#5433e2f503ea0e0831cbc6fd0c20f8157d93add0"
@@ -4463,6 +4470,13 @@ css-blank-pseudo@^0.1.4:
dependencies:
postcss "^7.0.5"
css-box-model@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==
dependencies:
tiny-invariant "^1.0.6"
css-color-names@0.0.4, css-color-names@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
@@ -7025,7 +7039,7 @@ hoist-non-react-statics@^2.1.0:
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.2:
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -9380,6 +9394,11 @@ mem@^4.0.0:
mimic-fn "^2.0.0"
p-is-promise "^2.0.0"
memoize-one@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
memoizee@^0.4.14:
version "0.4.14"
resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.14.tgz#07a00f204699f9a95c2d9e77218271c7cd610d57"
@@ -11685,6 +11704,11 @@ querystringify@^2.1.1:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
raf-schd@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0"
integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ==
raf@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
@@ -11775,6 +11799,19 @@ react-base16-styling@^0.6.0:
lodash.flow "^3.3.0"
pure-color "^1.2.0"
react-beautiful-dnd@^13.0.0:
version "13.0.0"
resolved "https://registry.yarnpkg.com/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz#f70cc8ff82b84bc718f8af157c9f95757a6c3b40"
integrity sha512-87It8sN0ineoC3nBW0SbQuTFXM6bUqM62uJGY4BtTf0yzPl8/3+bHMWkgIe0Z6m8e+gJgjWxefGRVfpE3VcdEg==
dependencies:
"@babel/runtime" "^7.8.4"
css-box-model "^1.2.0"
memoize-one "^5.1.1"
raf-schd "^4.0.2"
react-redux "^7.1.1"
redux "^4.0.4"
use-memo-one "^1.1.1"
react-color@^2.17.3:
version "2.18.0"
resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.18.0.tgz#34956f0bac394f6c3bc01692fd695644cc775ffd"
@@ -11921,7 +11958,7 @@ react-is@^16.12.0, react-is@^16.6.0, react-is@^16.8.4:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"
integrity sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==
react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1:
react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.9.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -11941,6 +11978,17 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-redux@^7.1.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985"
integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg==
dependencies:
"@babel/runtime" "^7.5.5"
hoist-non-react-statics "^3.3.0"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.9.0"
react-router-dom@^5.0.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18"
@@ -12197,6 +12245,14 @@ redux@^3.7.1:
loose-envify "^1.1.0"
symbol-observable "^1.0.3"
redux@^4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
regenerate-unicode-properties@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
@@ -13508,7 +13564,7 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"
symbol-observable@^1.0.3:
symbol-observable@^1.0.3, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
@@ -13694,7 +13750,7 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-invariant@^1.0.2:
tiny-invariant@^1.0.2, tiny-invariant@^1.0.6:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
@@ -14143,6 +14199,11 @@ use-debounce@^3.3.0:
resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-3.4.0.tgz#e61653fd4daad9beaa6e4695bc1d3fbd35f7e5b3"
integrity sha512-FSUfs/x7eJUusqvbk/UboMlWKQFBEGTegqK2tvm8+59bcbs77f0DeAy4MuychfxN7E+6rxXDpbv41Kq+aSJPow==
use-memo-one@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.1.tgz#39e6f08fe27e422a7d7b234b5f9056af313bd22c"
integrity sha512-oFfsyun+bP7RX8X2AskHNTxu+R3QdE/RC5IefMbqptmACAA/gfol1KDD5KRzPsGMa62sWxGZw+Ui43u6x4ddoQ==
use-persisted-state@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/use-persisted-state/-/use-persisted-state-0.3.0.tgz#f8e3d2fd8eee67e0c86fd596c3ea3e8121c07402"