mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
ui: add support for lazily loading menu items
This commit is contained in:
@@ -21,11 +21,12 @@ import React, {
|
||||
useCallback,
|
||||
useRef,
|
||||
useEffect,
|
||||
PropsWithChildren
|
||||
PropsWithChildren,
|
||||
useState
|
||||
} from "react";
|
||||
import { Box, FlexProps, Text } from "@theme-ui/components";
|
||||
import { getPosition } from "../../utils/position";
|
||||
import { MenuButtonItem, MenuItem } from "./types";
|
||||
import { LazyMenuItemsLoader, MenuButtonItem, MenuItem } from "./types";
|
||||
import { useFocus } from "./use-focus";
|
||||
import { MenuSeparator } from "./menu-separator";
|
||||
import { MenuButton } from "./menu-button";
|
||||
@@ -90,10 +91,12 @@ export function Menu(props: MenuProps) {
|
||||
return (
|
||||
<>
|
||||
<MenuContainer {...containerProps}>
|
||||
{items.map((item, index) => {
|
||||
{items.map(function mapper(item, index) {
|
||||
if (item.isHidden) return null;
|
||||
|
||||
switch (item.type) {
|
||||
case "lazy-loader":
|
||||
return <LazyLoader key={item.key} item={item} mapper={mapper} />;
|
||||
case "separator":
|
||||
return <MenuSeparator key={item.key} />;
|
||||
case "button":
|
||||
@@ -246,6 +249,24 @@ export function MenuPresenter(props: PropsWithChildren<MenuPresenterProps>) {
|
||||
);
|
||||
}
|
||||
|
||||
function LazyLoader(props: {
|
||||
item: LazyMenuItemsLoader;
|
||||
mapper: (item: MenuItem, index: number) => JSX.Element | null;
|
||||
}) {
|
||||
const { item, mapper } = props;
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [items, setItems] = useState<MenuItem[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
setItems(await item.items());
|
||||
setIsLoading(false);
|
||||
})();
|
||||
}, [item]);
|
||||
|
||||
return isLoading ? <></> : <>{items.map(mapper)}</>;
|
||||
}
|
||||
|
||||
export * from "./types";
|
||||
export * from "./menu-button";
|
||||
export * from "./menu-separator";
|
||||
|
||||
@@ -23,7 +23,7 @@ export type MenuItemComponentProps = {
|
||||
onClick?: (e?: Event) => void;
|
||||
};
|
||||
|
||||
export type MenuItemTypes = "button" | "separator" | "popup";
|
||||
export type MenuItemTypes = "button" | "separator" | "popup" | "lazy-loader";
|
||||
export type BaseMenuItem<TType extends MenuItemTypes> = {
|
||||
type: TType;
|
||||
key: string;
|
||||
@@ -37,6 +37,10 @@ export type MenuPopupItem = BaseMenuItem<"popup"> & {
|
||||
component: (props: MenuItemComponentProps) => JSX.Element;
|
||||
};
|
||||
|
||||
export type LazyMenuItemsLoader = BaseMenuItem<"lazy-loader"> & {
|
||||
items: () => Promise<MenuItem[]>;
|
||||
};
|
||||
|
||||
export type MenuButtonItem = BaseMenuItem<"button"> & {
|
||||
onClick?: () => void;
|
||||
title: string;
|
||||
@@ -54,4 +58,8 @@ export type MenuButtonItem = BaseMenuItem<"button"> & {
|
||||
};
|
||||
};
|
||||
|
||||
export type MenuItem = MenuButtonItem | MenuSeperatorItem | MenuPopupItem;
|
||||
export type MenuItem =
|
||||
| MenuButtonItem
|
||||
| MenuSeperatorItem
|
||||
| MenuPopupItem
|
||||
| LazyMenuItemsLoader;
|
||||
|
||||
Reference in New Issue
Block a user