mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
Merge branch 'develop' into support-dervi-context-menu
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
"jszip": "^3.6.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"lodash": "^4.17.21",
|
||||
"match-sorter": "^6.3.1",
|
||||
"notistack": "^2.0.2",
|
||||
"pb-util": "^1.0.1",
|
||||
"query-string": "^6.8.3",
|
||||
@@ -56,7 +57,6 @@
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.21.2",
|
||||
"react-image": "^4.0.3",
|
||||
"react-joyride": "^2.3.0",
|
||||
"react-json-view": "^1.19.1",
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-router-dom": "^5.0.1",
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import SvgIcon, { SvgIconProps } from "@mui/material/SvgIcon";
|
||||
import { mdiContentCut } from "@mdi/js";
|
||||
|
||||
export default function Cut(props: SvgIconProps) {
|
||||
return (
|
||||
<SvgIcon {...props}>
|
||||
<path d={mdiContentCut} />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import SvgIcon, { SvgIconProps } from "@mui/material/SvgIcon";
|
||||
import { mdiContentPaste } from "@mdi/js";
|
||||
|
||||
export default function Paste(props: SvgIconProps) {
|
||||
return (
|
||||
<SvgIcon {...props}>
|
||||
<path d={mdiContentPaste} />
|
||||
</SvgIcon>
|
||||
);
|
||||
}
|
||||
40
src/atoms/ContextMenu.ts
Normal file
40
src/atoms/ContextMenu.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useAtom } from "jotai";
|
||||
import { atomWithReset, useResetAtom, useUpdateAtom } from "jotai/utils";
|
||||
|
||||
export type SelectedCell = {
|
||||
rowIndex: number;
|
||||
colIndex: number;
|
||||
};
|
||||
|
||||
export type anchorEl = HTMLElement;
|
||||
|
||||
const selectedCellAtom = atomWithReset<SelectedCell | null>(null);
|
||||
const anchorEleAtom = atomWithReset<HTMLElement | null>(null);
|
||||
|
||||
export function useSetAnchorEle() {
|
||||
const setAnchorEle = useUpdateAtom(anchorEleAtom);
|
||||
return { setAnchorEle };
|
||||
}
|
||||
|
||||
export function useSetSelectedCell() {
|
||||
const setSelectedCell = useUpdateAtom(selectedCellAtom);
|
||||
return { setSelectedCell };
|
||||
}
|
||||
|
||||
export function useContextMenuAtom() {
|
||||
const [anchorEle] = useAtom(anchorEleAtom);
|
||||
const [selectedCell] = useAtom(selectedCellAtom);
|
||||
const resetAnchorEle = useResetAtom(anchorEleAtom);
|
||||
const resetSelectedCell = useResetAtom(selectedCellAtom);
|
||||
|
||||
const resetContextMenu = async () => {
|
||||
await resetAnchorEle();
|
||||
await resetSelectedCell();
|
||||
};
|
||||
|
||||
return {
|
||||
anchorEle,
|
||||
selectedCell,
|
||||
resetContextMenu,
|
||||
};
|
||||
}
|
||||
@@ -352,6 +352,7 @@ export default function ColumnMenu() {
|
||||
open={modal.type === ModalStates.typeChange}
|
||||
/>
|
||||
<FieldSettings
|
||||
key={column.key}
|
||||
{...menuModalProps}
|
||||
open={modal.type === ModalStates.settings}
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Menu } from "@mui/material";
|
||||
import MenuRow, { IMenuRow } from "./MenuRow";
|
||||
import { default as MenuItem } from "./MenuItem";
|
||||
import { IContextMenuItem } from "./MenuItem";
|
||||
|
||||
interface IMenuContents {
|
||||
anchorEl: HTMLElement;
|
||||
open: boolean;
|
||||
handleClose: () => void;
|
||||
items: IMenuRow[];
|
||||
items: IContextMenuItem[];
|
||||
}
|
||||
|
||||
export function MenuContents({
|
||||
@@ -15,6 +16,7 @@ export function MenuContents({
|
||||
items,
|
||||
}: IMenuContents) {
|
||||
const handleContext = (e: React.MouseEvent) => e.preventDefault();
|
||||
|
||||
return (
|
||||
<Menu
|
||||
id="cell-context-menu"
|
||||
@@ -30,12 +32,17 @@ export function MenuContents({
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
sx={{ "& .MuiMenu-paper": { backgroundColor: "background.default" } }}
|
||||
MenuListProps={{ disablePadding: true }}
|
||||
sx={{
|
||||
"& .MuiMenu-paper": {
|
||||
backgroundColor: "background.default",
|
||||
width: 200,
|
||||
maxWidth: "100%",
|
||||
},
|
||||
}}
|
||||
onContextMenu={handleContext}
|
||||
>
|
||||
{items.map((item, indx: number) => (
|
||||
<MenuRow key={indx} {...item} />
|
||||
<MenuItem key={indx} {...item} />
|
||||
))}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
34
src/components/Table/ContextMenu/MenuItem.tsx
Normal file
34
src/components/Table/ContextMenu/MenuItem.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
MenuItem,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
|
||||
export interface IContextMenuItem {
|
||||
onClick: () => void;
|
||||
icon: JSX.Element;
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
hotkeyLabel?: string;
|
||||
}
|
||||
|
||||
export default function ContextMenuItem({
|
||||
onClick,
|
||||
icon,
|
||||
label,
|
||||
disabled,
|
||||
hotkeyLabel,
|
||||
}: IContextMenuItem) {
|
||||
return (
|
||||
<MenuItem disabled={disabled} onClick={onClick}>
|
||||
<ListItemIcon>{icon} </ListItemIcon>
|
||||
<ListItemText> {label} </ListItemText>
|
||||
{hotkeyLabel && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{hotkeyLabel}
|
||||
</Typography>
|
||||
)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { ListItemIcon, ListItemText, MenuItem } from "@mui/material";
|
||||
|
||||
export interface IMenuRow {
|
||||
onClick: () => void;
|
||||
icon: JSX.Element;
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export default function MenuRow({ onClick, icon, label, disabled }: IMenuRow) {
|
||||
return (
|
||||
<MenuItem disabled={disabled} onClick={onClick}>
|
||||
<ListItemIcon>{icon} </ListItemIcon>
|
||||
<ListItemText> {label} </ListItemText>
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
@@ -1,42 +1,16 @@
|
||||
import React from "react";
|
||||
import _find from "lodash/find";
|
||||
import { PopoverProps } from "@mui/material";
|
||||
|
||||
import { PopoverProps } from "@mui/material";
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
import { getFieldProp } from "@src/components/fields";
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
|
||||
import { MenuContents } from "./MenuContent";
|
||||
|
||||
export type SelectedCell = {
|
||||
rowIndex: number;
|
||||
colIndex: number;
|
||||
};
|
||||
|
||||
export type ContextMenuRef = {
|
||||
selectedCell: SelectedCell;
|
||||
setSelectedCell: React.Dispatch<React.SetStateAction<SelectedCell | null>>;
|
||||
anchorEl: HTMLElement | null;
|
||||
setAnchorEl: React.Dispatch<
|
||||
React.SetStateAction<PopoverProps["anchorEl"] | null>
|
||||
>;
|
||||
};
|
||||
import { useContextMenuAtom, useSetSelectedCell } from "@src/atoms/ContextMenu";
|
||||
|
||||
export default function ContextMenu() {
|
||||
const { contextMenuRef, tableState }: any = useProjectContext();
|
||||
const [anchorEl, setAnchorEl] = React.useState<any | null>(null);
|
||||
const [selectedCell, setSelectedCell] = React.useState<any | null>();
|
||||
const open = Boolean(anchorEl);
|
||||
const handleClose = () => setAnchorEl(null);
|
||||
|
||||
if (contextMenuRef)
|
||||
contextMenuRef.current = {
|
||||
anchorEl,
|
||||
setAnchorEl,
|
||||
selectedCell,
|
||||
setSelectedCell,
|
||||
} as {};
|
||||
|
||||
const { tableState } = useProjectContext();
|
||||
const { anchorEle, selectedCell, resetContextMenu } = useContextMenuAtom();
|
||||
const columns = tableState?.columns;
|
||||
const selectedColIndex = selectedCell?.colIndex;
|
||||
const selectedCol = _find(tableState?.columns, { index: selectedColIndex });
|
||||
|
||||
@@ -52,13 +26,20 @@ export default function ContextMenu() {
|
||||
getFieldProp("contextMenuActions", columnType) || function empty() {};
|
||||
const actions = getActions() || [];
|
||||
const hasNoActions = Boolean(actions.length === 0);
|
||||
|
||||
const selectedCol = _find(columns, { index: selectedColIndex });
|
||||
const configActions =
|
||||
getFieldProp("contextMenuActions", selectedCol?.type) ||
|
||||
function empty() {};
|
||||
const actions = configActions(selectedCell, resetContextMenu) || [];
|
||||
|
||||
|
||||
if (!contextMenuRef.current || !open || hasNoActions) return <></>;
|
||||
if (!anchorEle || actions.length === 0) return <></>;
|
||||
return (
|
||||
<MenuContents
|
||||
anchorEl={anchorEl}
|
||||
open={open}
|
||||
handleClose={handleClose}
|
||||
anchorEl={anchorEle}
|
||||
open={Boolean(anchorEle)}
|
||||
handleClose={resetContextMenu}
|
||||
items={actions}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,35 +1,24 @@
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import { useSetAnchorEle } from "@src/atoms/ContextMenu";
|
||||
import { Fragment } from "react";
|
||||
import { Row, RowRendererProps } from "react-data-grid";
|
||||
|
||||
import OutOfOrderIndicator from "./OutOfOrderIndicator";
|
||||
|
||||
export default function TableRow(props: RowRendererProps<any>) {
|
||||
const { setAnchorEle } = useSetAnchorEle();
|
||||
const handleContextMenu = (
|
||||
e: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
) => {
|
||||
e.preventDefault();
|
||||
setAnchorEle?.(e?.target as HTMLElement);
|
||||
};
|
||||
if (props.row._rowy_outOfOrder)
|
||||
return (
|
||||
<Fragment key={props.row.id}>
|
||||
<OutOfOrderIndicator top={props.top} height={props.height} />
|
||||
<ContextMenu>
|
||||
<Row {...props} />
|
||||
</ContextMenu>
|
||||
<Row onContextMenu={handleContextMenu} {...props} />
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
return (
|
||||
<ContextMenu>
|
||||
<Row {...props} />
|
||||
</ContextMenu>
|
||||
);
|
||||
return <Row onContextMenu={handleContextMenu} {...props} />;
|
||||
}
|
||||
|
||||
const ContextMenu = (props: any) => {
|
||||
const { contextMenuRef }: any = useProjectContext();
|
||||
function handleClick(e: any) {
|
||||
e.preventDefault();
|
||||
const input = e?.target as HTMLElement;
|
||||
if (contextMenuRef?.current) {
|
||||
contextMenuRef?.current?.setAnchorEl(input);
|
||||
}
|
||||
}
|
||||
return <span onContextMenu={(e) => handleClick(e)}>{props.children}</span>;
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@ import { formatSubTableName } from "@src/utils/fns";
|
||||
import { useAppContext } from "@src/contexts/AppContext";
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import useWindowSize from "@src/hooks/useWindowSize";
|
||||
import { useSetSelectedCell } from "@src/atoms/ContextMenu";
|
||||
|
||||
export type TableColumn = Column<any> & {
|
||||
isNew?: boolean;
|
||||
@@ -49,11 +50,11 @@ export default function Table() {
|
||||
tableState,
|
||||
tableActions,
|
||||
dataGridRef,
|
||||
contextMenuRef,
|
||||
sideDrawerRef,
|
||||
updateCell,
|
||||
} = useProjectContext();
|
||||
const { userDoc, userClaims } = useAppContext();
|
||||
const { setSelectedCell } = useSetSelectedCell();
|
||||
|
||||
const userDocHiddenFields =
|
||||
userDoc.state.doc?.tables?.[formatSubTableName(tableState?.config.id)]
|
||||
@@ -264,13 +265,12 @@ export default function Table() {
|
||||
});
|
||||
}
|
||||
}}
|
||||
onSelectedCellChange={({ rowIdx, idx }) => {
|
||||
console.log("firing");
|
||||
contextMenuRef?.current?.setSelectedCell({
|
||||
onSelectedCellChange={({ rowIdx, idx }) =>
|
||||
setSelectedCell({
|
||||
rowIndex: rowIdx,
|
||||
colIndex: idx,
|
||||
});
|
||||
}}
|
||||
})
|
||||
}
|
||||
/>
|
||||
</DndProvider>
|
||||
) : (
|
||||
|
||||
@@ -229,9 +229,10 @@ export default function Filters() {
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
{overrideTableFilters
|
||||
? " (ignore table filter)"
|
||||
: " (use table filter)"}
|
||||
{hasTableFilters &&
|
||||
(overrideTableFilters
|
||||
? " (ignore table filter)"
|
||||
: " (use table filter)")}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
@@ -337,20 +338,16 @@ export default function Filters() {
|
||||
<div className="content">
|
||||
<FilterInputs {...userFilterInputs} />
|
||||
|
||||
{hasTableFilters && (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={overrideTableFilters}
|
||||
onChange={(e) =>
|
||||
setOverrideTableFilters(e.target.checked)
|
||||
}
|
||||
/>
|
||||
}
|
||||
label="Override table filters"
|
||||
sx={{ justifyContent: "center", mb: 1, mr: 0 }}
|
||||
/>
|
||||
)}
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={overrideTableFilters}
|
||||
onChange={(e) => setOverrideTableFilters(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="Override table filters"
|
||||
sx={{ justifyContent: "center", mb: 1, mr: 0 }}
|
||||
/>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
|
||||
@@ -134,8 +134,10 @@ export default function TableSettings({
|
||||
await settingsActions?.updateTable(data);
|
||||
deployExtensionsWebhooks();
|
||||
clearDialog();
|
||||
analytics.logEvent("update_table", { type: values.tableType });
|
||||
} else {
|
||||
await settingsActions?.createTable(data);
|
||||
await analytics.logEvent("create_table", { type: values.tableType });
|
||||
deployExtensionsWebhooks(() => {
|
||||
if (router.location.pathname === "/") {
|
||||
router.history.push(
|
||||
@@ -149,10 +151,6 @@ export default function TableSettings({
|
||||
clearDialog();
|
||||
});
|
||||
}
|
||||
analytics.logEvent(
|
||||
TableSettingsDialogModes.update ? "update_table" : "create_table",
|
||||
{ type: values.tableType }
|
||||
);
|
||||
};
|
||||
|
||||
const fields = tableSettings(
|
||||
|
||||
@@ -1,70 +1,74 @@
|
||||
import _find from "lodash/find";
|
||||
import CopyCells from "@src/assets/icons/CopyCells";
|
||||
import Cut from "@src/assets/icons/Cut";
|
||||
import Paste from "@src/assets/icons/Paste";
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
|
||||
export default function BasicContextMenuActions() {
|
||||
const { contextMenuRef, tableState, deleteCell, updateCell } =
|
||||
useProjectContext();
|
||||
import Cut from "@mui/icons-material/ContentCut";
|
||||
import CopyCells from "@src/assets/icons/CopyCells";
|
||||
import Paste from "@mui/icons-material/ContentPaste";
|
||||
|
||||
import { useProjectContext } from "@src/contexts/ProjectContext";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { SelectedCell } from "@src/atoms/ContextMenu";
|
||||
|
||||
export interface IContextMenuActions {
|
||||
label: string;
|
||||
icon: React.ReactNode;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export default function BasicContextMenuActions(
|
||||
selectedCell: SelectedCell,
|
||||
reset: () => void | Promise<void>
|
||||
): IContextMenuActions[] {
|
||||
const { tableState, deleteCell, updateCell } = useProjectContext();
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const columns = tableState?.columns;
|
||||
const rows = tableState?.rows;
|
||||
const selectedRowIndex = contextMenuRef?.current?.selectedCell
|
||||
.rowIndex as number;
|
||||
const selectedColIndex = contextMenuRef?.current?.selectedCell?.colIndex;
|
||||
const selectedRowIndex = selectedCell.rowIndex as number;
|
||||
const selectedColIndex = selectedCell?.colIndex;
|
||||
const selectedCol = _find(columns, { index: selectedColIndex });
|
||||
const selectedRow = rows?.[selectedRowIndex];
|
||||
const cell = selectedRow?.[selectedCol.key];
|
||||
|
||||
const handleClose = () => {
|
||||
contextMenuRef?.current?.setSelectedCell(null);
|
||||
contextMenuRef?.current?.setAnchorEl(null);
|
||||
const handleClose = async () => await reset?.();
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(JSON.stringify(cell));
|
||||
enqueueSnackbar("Copied to clipboard", { variant: "success" });
|
||||
} catch (error) {
|
||||
enqueueSnackbar(`Failed to copy:${error}`, { variant: "error" });
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleCopy = () => {
|
||||
const cell = selectedRow?.[selectedCol.key];
|
||||
const onFail = () => console.log("Fail to copy");
|
||||
const onSuccess = () => console.log("Save to clipboard successful");
|
||||
const copy = navigator.clipboard.writeText(JSON.stringify(cell));
|
||||
copy.then(onSuccess, onFail);
|
||||
const handleCut = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(JSON.stringify(cell));
|
||||
if (typeof cell !== "undefined")
|
||||
deleteCell?.(selectedRow?.ref, selectedCol?.key);
|
||||
} catch (error) {
|
||||
enqueueSnackbar(`Failed to cut: ${error}`, { variant: "error" });
|
||||
}
|
||||
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleCut = () => {
|
||||
const cell = selectedRow?.[selectedCol.key];
|
||||
const notUndefined = Boolean(typeof cell !== "undefined");
|
||||
if (deleteCell && notUndefined)
|
||||
deleteCell(selectedRow?.ref, selectedCol?.key);
|
||||
const handlePaste = async () => {
|
||||
try {
|
||||
const text = await navigator.clipboard.readText();
|
||||
const paste = await JSON.parse(text);
|
||||
updateCell?.(selectedRow?.ref, selectedCol.key, paste);
|
||||
} catch (error) {
|
||||
enqueueSnackbar(`Failed to paste: ${error}`, { variant: "error" });
|
||||
}
|
||||
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handlePaste = () => {
|
||||
console.log("home", rows);
|
||||
const paste = navigator.clipboard.readText();
|
||||
paste.then(async (clipText) => {
|
||||
try {
|
||||
const paste = await JSON.parse(clipText);
|
||||
updateCell?.(selectedRow?.ref, selectedCol.key, paste);
|
||||
} catch (error) {
|
||||
//TODO check the coding style guide about error message
|
||||
//Add breadcrumb handler her
|
||||
console.log(error);
|
||||
}
|
||||
});
|
||||
|
||||
handleClose();
|
||||
};
|
||||
|
||||
// const handleDisable = () => {
|
||||
// const cell = selectedRow?.[selectedCol.key];
|
||||
// return typeof cell === "undefined" ? true : false;
|
||||
// };
|
||||
|
||||
const cellMenuAction = [
|
||||
const contextMenuActions = [
|
||||
{ label: "Cut", icon: <Cut />, onClick: handleCut },
|
||||
{ label: "Copy", icon: <CopyCells />, onClick: handleCopy },
|
||||
{ label: "Paste", icon: <Paste />, onClick: handlePaste },
|
||||
];
|
||||
return cellMenuAction;
|
||||
|
||||
return contextMenuActions;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { FieldType } from "@src/constants/fields";
|
||||
|
||||
import { FormatterProps, EditorProps } from "react-data-grid";
|
||||
import { Control, UseFormReturn } from "react-hook-form";
|
||||
import { PopoverProps } from "@mui/material";
|
||||
import { SelectedCell } from "@src/atoms/ContextMenu";
|
||||
import { IContextMenuActions } from "./_BasicCell/BasicCellContextMenuActions";
|
||||
|
||||
export { FieldType };
|
||||
|
||||
@@ -17,7 +18,10 @@ export interface IFieldConfig {
|
||||
icon?: React.ReactNode;
|
||||
description?: string;
|
||||
setupGuideLink?: string;
|
||||
contextMenuActions?: () => void;
|
||||
contextMenuActions?: (
|
||||
selectedCell: SelectedCell,
|
||||
reset: () => Promise<void>
|
||||
) => IContextMenuActions[];
|
||||
TableCell: React.ComponentType<FormatterProps<any>>;
|
||||
TableEditor: React.ComponentType<EditorProps<any, any>>;
|
||||
SideDrawerField: React.ComponentType<ISideDrawerFieldProps>;
|
||||
|
||||
@@ -14,7 +14,6 @@ import useSettings from "@src/hooks/useSettings";
|
||||
import { useAppContext } from "./AppContext";
|
||||
import { SideDrawerRef } from "@src/components/SideDrawer";
|
||||
import { ColumnMenuRef } from "@src/components/Table/ColumnMenu";
|
||||
import { ContextMenuRef } from "@src/components/Table/ContextMenu";
|
||||
import { ImportWizardRef } from "@src/components/Wizards/ImportWizard";
|
||||
|
||||
import { rowyRun, IRowyRunRequestProps } from "@src/utils/rowyRun";
|
||||
@@ -105,8 +104,6 @@ export interface IProjectContext {
|
||||
dataGridRef: React.RefObject<DataGridHandle>;
|
||||
// A ref to the side drawer state. Prevents unnecessary re-renders
|
||||
sideDrawerRef: React.MutableRefObject<SideDrawerRef | undefined>;
|
||||
//A ref to the cell menu. Prevents unnecessary re-render
|
||||
contextMenuRef: React.MutableRefObject<ContextMenuRef | undefined>;
|
||||
// A ref to the column menu. Prevents unnecessary re-renders
|
||||
columnMenuRef: React.MutableRefObject<ColumnMenuRef | undefined>;
|
||||
// A ref ot the import wizard. Prevents unnecessary re-renders
|
||||
@@ -401,7 +398,6 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
|
||||
// A ref to the data grid. Contains data grid functions
|
||||
const dataGridRef = useRef<DataGridHandle>(null);
|
||||
const sideDrawerRef = useRef<SideDrawerRef>();
|
||||
const contextMenuRef = useRef<ContextMenuRef>();
|
||||
const columnMenuRef = useRef<ColumnMenuRef>();
|
||||
const importWizardRef = useRef<ImportWizardRef>();
|
||||
|
||||
@@ -422,7 +418,6 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
|
||||
table,
|
||||
dataGridRef,
|
||||
sideDrawerRef,
|
||||
contextMenuRef,
|
||||
columnMenuRef,
|
||||
importWizardRef,
|
||||
rowyRun: _rowyRun,
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { useDebouncedCallback } from "use-debounce";
|
||||
import { matchSorter } from "match-sorter";
|
||||
|
||||
export default function useBasicSearch<T>(
|
||||
list: T[],
|
||||
predicate: (item: T, query: string) => boolean,
|
||||
keys: string[],
|
||||
debounce: number = 400
|
||||
) {
|
||||
const [query, setQuery] = useState("");
|
||||
const [handleQuery] = useDebouncedCallback(setQuery, debounce);
|
||||
|
||||
const results = query
|
||||
? list.filter((user) => predicate(user, query.toLowerCase()))
|
||||
: list;
|
||||
const results = query ? matchSorter(list, query, { keys }) : list;
|
||||
|
||||
return [results, query, handleQuery] as const;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import { SETTINGS } from "@src/config/dbPaths";
|
||||
import { APP_BAR_HEIGHT } from "@src/components/Navigation";
|
||||
|
||||
const useHomeViewState = createPersistedState("__ROWY__HOME_VIEW");
|
||||
const SEARCH_KEYS = ["id", "name", "section", "description"];
|
||||
|
||||
export default function HomePage() {
|
||||
const { userDoc, userRoles } = useAppContext();
|
||||
@@ -53,11 +54,7 @@ export default function HomePage() {
|
||||
|
||||
const [results, query, handleQuery] = useBasicSearch(
|
||||
tables ?? [],
|
||||
(table, query) =>
|
||||
table.id.toLowerCase().includes(query) ||
|
||||
table.name.toLowerCase().includes(query) ||
|
||||
table.section.toLowerCase().includes(query) ||
|
||||
table.description.toLowerCase().includes(query)
|
||||
SEARCH_KEYS
|
||||
);
|
||||
|
||||
const [view, setView] = useHomeViewState("grid");
|
||||
|
||||
@@ -20,6 +20,8 @@ import useCollection from "@src/hooks/useCollection";
|
||||
import useBasicSearch from "@src/hooks/useBasicSearch";
|
||||
import { USERS } from "@src/config/dbPaths";
|
||||
|
||||
const SEARCH_KEYS = ["id", "user.displayName", "user.email"];
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
user: {
|
||||
@@ -35,13 +37,7 @@ export default function UserManagementPage() {
|
||||
const users: User[] = usersState.documents ?? [];
|
||||
const loading = usersState.loading || !Array.isArray(usersState.documents);
|
||||
|
||||
const [results, query, handleQuery] = useBasicSearch(
|
||||
users,
|
||||
(user, query) =>
|
||||
user.id.toLowerCase() === query ||
|
||||
user.user.displayName.toLowerCase().includes(query) ||
|
||||
user.user.email.toLowerCase().includes(query)
|
||||
);
|
||||
const [results, query, handleQuery] = useBasicSearch(users, SEARCH_KEYS);
|
||||
|
||||
return (
|
||||
<Container maxWidth="sm" sx={{ px: 1, pt: 1, pb: 7 + 3 + 3 }}>
|
||||
|
||||
161
yarn.lock
161
yarn.lock
@@ -1481,6 +1481,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.12.5":
|
||||
version "7.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.0.tgz#b8d142fc0f7664fb3d9b5833fd40dcbab89276c0"
|
||||
integrity sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.13.10", "@babel/runtime@^7.8.4":
|
||||
version "7.15.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
|
||||
@@ -6285,38 +6292,24 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.1.1:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@4.3.1, debug@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
|
||||
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^3.0.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debug@^4.0.0:
|
||||
debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^4.0.1, debug@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
debug@4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
|
||||
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^3.1.1, debug@^3.2.6, debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
@@ -6354,11 +6347,6 @@ dedent@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
|
||||
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
|
||||
|
||||
deep-diff@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-1.0.2.tgz#afd3d1f749115be965e89c63edc7abb1506b9c26"
|
||||
integrity sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
|
||||
@@ -7467,11 +7455,6 @@ exegesis@^4.1.0:
|
||||
raw-body "^2.3.3"
|
||||
semver "^7.0.0"
|
||||
|
||||
exenv@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
|
||||
|
||||
exit-code@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/exit-code/-/exit-code-1.0.2.tgz#ce165811c9f117af6a5f882940b96ae7f9aecc34"
|
||||
@@ -8028,11 +8011,9 @@ fn.name@1.x.x:
|
||||
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
|
||||
|
||||
follow-redirects@^1.0.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.10.0.tgz#01f5263aee921c6a54fb91667f08f4155ce169eb"
|
||||
integrity sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==
|
||||
dependencies:
|
||||
debug "^3.0.0"
|
||||
version "1.14.7"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
|
||||
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
|
||||
|
||||
for-in@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -9463,11 +9444,6 @@ is-lambda@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
|
||||
integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=
|
||||
|
||||
is-lite@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/is-lite/-/is-lite-0.8.1.tgz#a9bd03c90ea723d450c78c991b84f78e7e3126f9"
|
||||
integrity sha512-ekSwuewzOmwFnzzAOWuA5fRFPqOeTrLIL3GWT7hdVVi+oLuD+Rau8gCmkb94vH5hjXc1Q/CfIW/y/td1RrNQIg==
|
||||
|
||||
is-module@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
|
||||
@@ -11134,6 +11110,14 @@ marked@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e"
|
||||
integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==
|
||||
|
||||
match-sorter@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda"
|
||||
integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
remove-accents "0.4.2"
|
||||
|
||||
material-colors@^1.2.1:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
|
||||
@@ -12009,9 +11993,9 @@ nanoclone@^0.2.1:
|
||||
integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==
|
||||
|
||||
nanoid@^3.1.23:
|
||||
version "3.1.23"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
|
||||
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
|
||||
integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
@@ -12067,16 +12051,6 @@ neo-async@^2.6.2:
|
||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||
|
||||
nested-property@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/nested-property/-/nested-property-1.0.1.tgz#2001105b5c69413411b876bba9b86f4316af613f"
|
||||
integrity sha512-BnBBoo/8bBNRdAnJc7+m79oWk7dXwW1+vCesaEQhfDGVwXGLMvmI4NwYgLTW94R/x+R2s/yr2g/hB/4w/YSAvA==
|
||||
|
||||
nested-property@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/nested-property/-/nested-property-4.0.0.tgz#a67b5a31991e701e03cdbaa6453bc5b1011bb88d"
|
||||
integrity sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==
|
||||
|
||||
netmask@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7"
|
||||
@@ -13030,11 +13004,6 @@ pnp-webpack-plugin@1.6.4:
|
||||
dependencies:
|
||||
ts-pnp "^1.1.6"
|
||||
|
||||
popper.js@^1.16.0:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
|
||||
integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
|
||||
|
||||
portfinder@^1.0.23, portfinder@^1.0.26:
|
||||
version "1.0.28"
|
||||
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
|
||||
@@ -14365,18 +14334,6 @@ react-firebaseui@^5.0.2:
|
||||
dependencies:
|
||||
firebaseui "^4.8.0"
|
||||
|
||||
react-floater@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/react-floater/-/react-floater-0.7.3.tgz#f57947960682586866ec21540e73c9049ca9f787"
|
||||
integrity sha512-d1wAEph+xRxQ0RJ3woMmYLlZHTaCIsja7Bv6JNo2ezsVUgdMan4CxOR4Do4/xgpmRFfsQMdlygexLAZZypWirw==
|
||||
dependencies:
|
||||
deepmerge "^4.2.2"
|
||||
exenv "^1.2.2"
|
||||
is-lite "^0.8.1"
|
||||
popper.js "^1.16.0"
|
||||
react-proptype-conditional-require "^1.0.4"
|
||||
tree-changes "^0.5.1"
|
||||
|
||||
react-helmet@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726"
|
||||
@@ -14407,22 +14364,6 @@ react-is@^17.0.0, react-is@^17.0.1, react-is@^17.0.2:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||
|
||||
react-joyride@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-joyride/-/react-joyride-2.3.1.tgz#de3c8e8bfd6b58f62e7c6e8b38467e807ef8f90f"
|
||||
integrity sha512-MmyhECU3V+4kZAJrcDPPXcXxaoTpwc7g+E7Cq6QZ5IqJZrWYSVvpVCfudQcdcf6BsNbgawRhvCvbQyeWoPtNig==
|
||||
dependencies:
|
||||
deep-diff "^1.0.2"
|
||||
deepmerge "^4.2.2"
|
||||
exenv "^1.2.2"
|
||||
is-lite "^0.8.1"
|
||||
nested-property "^4.0.0"
|
||||
react-floater "^0.7.3"
|
||||
react-is "^16.13.1"
|
||||
scroll "^3.0.1"
|
||||
scrollparent "^2.0.1"
|
||||
tree-changes "^0.7.1"
|
||||
|
||||
react-json-view@^1.19.1:
|
||||
version "1.21.3"
|
||||
resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475"
|
||||
@@ -14458,11 +14399,6 @@ react-markdown@^8.0.0:
|
||||
unist-util-visit "^4.0.0"
|
||||
vfile "^5.0.0"
|
||||
|
||||
react-proptype-conditional-require@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz#69c2d5741e6df5e08f230f36bbc2944ee1222555"
|
||||
integrity sha1-acLVdB5t9eCPIw82u8KUTuEiJVU=
|
||||
|
||||
react-redux@^7.2.0:
|
||||
version "7.2.4"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225"
|
||||
@@ -14918,6 +14854,11 @@ remark-rehype@^10.0.0:
|
||||
mdast-util-to-hast "^12.1.0"
|
||||
unified "^10.0.0"
|
||||
|
||||
remove-accents@0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5"
|
||||
integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=
|
||||
|
||||
remove-trailing-separator@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
|
||||
@@ -15355,16 +15296,6 @@ schema-utils@^3.0.0:
|
||||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
scroll@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/scroll/-/scroll-3.0.1.tgz#d5afb59fb3592ee3df31c89743e78b39e4cd8a26"
|
||||
integrity sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg==
|
||||
|
||||
scrollparent@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/scrollparent/-/scrollparent-2.0.1.tgz#715d5b9cc57760fb22bdccc3befb5bfe06b1a317"
|
||||
integrity sha1-cV1bnMV3YPsivczDvvtb/gaxoxc=
|
||||
|
||||
select-hose@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||
@@ -16698,22 +16629,6 @@ tr46@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
|
||||
integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=
|
||||
|
||||
tree-changes@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/tree-changes/-/tree-changes-0.5.1.tgz#e31cc8a0f56c8c401f0a88243d9165dbea4f570c"
|
||||
integrity sha512-O873xzV2xRZ6N059Mn06QzmGKEE21LlvIPbsk2G+GS9ZX5OCur6PIwuuh0rWpAPvLWQZPj0XObyG27zZyLHUzw==
|
||||
dependencies:
|
||||
deep-diff "^1.0.2"
|
||||
nested-property "1.0.1"
|
||||
|
||||
tree-changes@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/tree-changes/-/tree-changes-0.7.1.tgz#fa8810cbe417e80b9a42c4b018f934c7ad8fa156"
|
||||
integrity sha512-sPIt8PKDi0OQTglr7lsetcB9DU19Ls/ZgFSjFvK6DWJGisAn4sOxtjpmQfuqjexQE4UU9U53LNmataL1kRJ3Uw==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.3"
|
||||
is-lite "^0.8.1"
|
||||
|
||||
triple-beam@^1.2.0, triple-beam@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
|
||||
|
||||
Reference in New Issue
Block a user