@flatbiz/layout
Version:
WEB菜单布局
328 lines (324 loc) • 9.24 kB
TypeScript
/// <reference types="node" />
/// <reference types="prop-types" />
/// <reference types="scheduler" />
import { ButtonProps } from 'antd';
import { SizeType } from 'antd/lib/config-provider/SizeContext';
import { Locale } from 'antd/lib/locale-provider';
import { CSSProperties, ComponentType, FC, ReactElement } from 'react';
export interface AclProps {
/** 标识当前组件的唯一性 */
aclName: string;
children?: ReactElement;
}
export declare const isElemVisible: (elemAclLimits: string[], aclName: string) => boolean;
export declare const Acl: ({ children, aclName }: AclProps) => JSX.Element | null;
export declare type BreadRoutePathFn = (data: BreadRouteMatchPath) => string;
export interface BreadRoute {
/**
* 当前面包屑UI显示名
*/
name: string | (() => string);
/**
* Path 匹配,字符串,匹配URL路径
*/
path: string;
/**
* 覆盖`path`如果存在,则点击跳转链接使用to, 通常情况 `path`匹配成功之后,可以指定对应的另外的 `to`来替换当前的`path`作为跳转链接.
* 支持函数(match)获取计算后的动态`path`
*/
to?: string | BreadRoutePathFn;
/**
* 保留的URL query参数. 默认保留 `env`
*/
query?: string[];
}
export declare type BreadsData = AppBreads | ((data: BreadRouteMatchPath) => AppBreads);
export interface AppBreads {
[index: string]: BreadRoute[];
}
export declare type BreadRouteMatchPath = {
params: Readonly<Record<string, string | undefined>>;
search: URLSearchParams;
};
export interface ModuleMenu {
id: string | number;
name: string;
path?: string;
link: string | null;
sort?: number;
target?: "_blank" | "_self" | null;
metaTitle?: string;
/**
* iconImg&iconImgActive为自定义png图标
*/
iconImg?: string;
iconImgActive?: string;
routeBaseName?: string;
defaultPage?: string;
parentId: null | number | string;
children: ModuleMenu[];
}
export declare type GlobalData = {
appName?: string;
user: AdminUser;
menus: ModuleMenu[];
apiBase: string;
hostUrl: string;
defaultPage?: string;
routeBaseName: string;
elemAclLimits: string[];
};
export declare type AdminUser = null | {
id: string;
userName: string;
emailAddress: string;
};
export interface FallbackProps {
error: Error;
resetErrorBoundary: (...args: Array<unknown>) => void;
}
export declare type BootstrapOptions = {
/**
* 品牌logo尺寸:40px * ?(?不超过64)
*/
logoPath?: string;
/**
* 品牌名称
*/
brandName?: string | JSX.Element;
/**
* 是否隐藏头部,默认值false
*/
hideHeader?: boolean;
/**
* @default 220
*/
sidebarWidth?: number;
/**
* @default zhCN
*/
locale?: Locale;
/**
* 是否禁用顶部菜单
*/
disableTopbarMenu?: boolean;
/**
* ANTD 默认的组建尺寸
*/
componentSize?: SizeType;
/**
* 仅仅针对`LayoutFrame`有效
*/
multiFrameTabs?: boolean;
Footer?: (() => JSX.Element) | null;
Header?: (() => JSX.Element) | null;
HeaderBrand?: ((props: {
logoPath?: string;
}) => JSX.Element) | null;
LayoutComponent?: ComponentType<{
style?: CSSProperties;
}>;
ErrorFallback?: ComponentType<FallbackProps>;
/**
* 是否禁用全局异常处理
* 如果未设置ErrorHandling,则走默认ErrorHandling逻辑
*/
disableErrorHandling?: boolean;
/**
* 自定义ErrorHandling
*/
ErrorHandling?: (() => JSX.Element) | null;
onError?: (error: Error, info: {
componentStack: string;
}) => void;
onErrorReset?: (...args: any[]) => void;
onSignOut?: (user: AdminUser, hostUrl: string) => void;
AccountOperateMenus?: (() => JSX.Element) | null;
onSessionExpired: (user: AdminUser, hostUrl: string) => void;
verifySessionExpired: (err: any) => boolean;
/**
* 当sidebar菜单有level限制时,限制数目
*/
leaveMenuLevel?: number;
LeaveMenu?: ((props: LeaveMenuProps) => JSX.Element) | null;
/**
* 面包屑起始标题
*/
breadTitle?: string | JSX.Element;
/**
* 面包屑位置功能扩展
*/
breadExtendRender?: JSX.Element;
/**
* 隐藏默认设置的面包屑,默认值false
*/
hideDefaultBread?: boolean;
headerThemeConfig?: {
bgColor?: string;
activeBgColor?: string;
color?: string;
activeColor?: string;
};
sidebarThemeConfig?: {
bgColor?: string;
menuActiveBgColor?: string;
menuSelectedBgColor?: string;
color?: string;
activeColor?: string;
/**
* 默认值 16
*/
inlineIndent?: number;
};
/**
* 设置iframe模式TabBarExtra
* ```
* 1. 赋值后,默认的刷新、删除Dropdown将被取消
* ```
*/
iframeTabBarExtra?: JSX.Element;
/**
*是否显示顶部菜单中收缩按键
*/
showTopMenuShrink?: boolean;
/**
* 是否隐藏侧边栏中收缩按键
*/
hideSidebarShrink?: boolean;
};
export declare type LayoutCtxProps = {
breads: BreadsData;
sidebarWidth: number;
componentSize: SizeType;
locale: Locale;
routeConfig: RouteConfig;
} & Omit<BootstrapOptions, "sidebarWidth" | "componentSize" | "locale">;
export interface LeaveMenuProps {
leaveMenus?: ModuleMenu[];
selectedKeys?: string[];
}
export interface RouteItemProps {
path: string;
element: (props: any) => ReactElement | null;
redirect?: string | false;
caseSensitive?: boolean;
}
export interface ModuleItemProps {
path: string;
redirect: string | false;
/**
* allow use use lazy import(``) with webpack `webpackChunkName`
*/
module: ComponentType | null;
caseSensitive?: boolean;
}
export declare class RouteConfig {
private flattenTree;
private flattenTreePaths;
private modules;
private routeBaseName;
constructor(modules: ModuleItemProps[]);
findOneByBestMatchedRequestUrlPath(reqPath: string, ignorePath: string): string | undefined;
get routes(): RouteItemProps[];
}
export declare const bootstrap: (routeConfig: RouteConfig, breads: BreadsData, options: BootstrapOptions, callback?: () => void) => void;
export declare const Bread: (props: any) => JSX.Element | null;
export declare type HistoryBackProps = {
breads: BreadsData;
level?: number;
};
/**
* 路由返回,依赖面包屑配置
* @param props
* @returns
* ```
* 1. breads 模块面包屑配置
* 2. level回退级别,如果传递数据未获取到路由配置,则取上一级
* 例如:-1,-2,-3
* 3. 为什么不能使用useNavigate(-1)
* 因为内部iframe和外部浏览器共用history历史记录,导致里外浏览器栈混乱
* 4. 什么场景使用
* 使用iframe tab的项目,在执行路由回退时使用
* ```
*/
export declare const HistoryBackButton: (props: HistoryBackProps & ButtonProps) => JSX.Element;
export declare const useHistoryBack: (props: HistoryBackProps) => {
path: string;
};
export declare const LeaveMenuDefault: (props: LeaveMenuProps) => JSX.Element;
export declare type LoaderProps = {
spinning?: boolean;
fullScreen?: boolean;
style?: CSSProperties;
inner?: boolean;
};
export declare const Loader: ({ spinning, fullScreen, style }: LoaderProps) => JSX.Element;
export interface PageProps {
loading?: boolean;
className?: string;
style?: CSSProperties;
fullIndex?: number;
bread?: JSX.Element;
children?: ReactElement | ReactElement[];
}
export declare const Page: (props: PageProps) => JSX.Element;
export declare const layoutContext: {
useLayoutCtx: () => LayoutCtxProps;
};
export declare type UseBreadRoute = {
path: string;
name: string;
query: Record<string, string>;
};
export declare const useBread: (breads: BreadsData, routeBaseName: string) => UseBreadRoute[];
export declare type IframeHandler<T = unknown> = (data: T) => void;
/**
* 使用Iframe通讯的API
* @param onReceivedMessageCallback 接收iframe通讯消息的回调函数引用
* @example
* ```tsx
* const iframeApi = useIframe<MessageData>((data) => {
* console.log('onMainMessageReceived', data.name);
* updateMessage(data);
* });
*
* const handleClick = hooks.useCallbackRef(() => {
* iframeApi.broadcastMessages({
* fromHeader: '1',
* });
* });
*
* ```
* @returns
*/
export declare const useIframe: <T>(onReceivedMessageCallback?: IframeHandler<T>) => {
broadcastMessages<T_1>(data: T_1): any;
postMessage<T_2>(data: T_2): any;
openNewTabItem(data: {
link: string;
name: string;
metaTitle?: string | undefined;
}): any;
openBrowserWindow(url: string): any;
locationHref(url: string): any;
};
/**
* 用来处理, 当前URL state动态改变的时候, 我们需要reload菜单, 因为URL状态 Browserhash状态更改可能通过代码动态触发
*/
export declare const useLayoutHistory: () => void;
export declare const useMobileDetect: () => boolean;
export declare const LayoutIFrame: FC;
export declare const LayoutNormal: (props: any) => JSX.Element;
export declare const LayoutPage: (props: {
style?: CSSProperties;
children: ReactElement;
}) => JSX.Element;
export declare const utils: {
ensureSlash: (str: string, slashEndfix?: boolean) => string;
isHttpUri: (uri?: string | undefined) => boolean;
toLinkPath: (path?: string | null | undefined, query?: Record<string, any>) => string;
toLinkPathWithQuery: (path?: string | null | undefined, query?: Record<string, any>) => string;
urlJoin: (first: string, second: string) => string;
menuRouteFilter: (routes: RouteItemProps[]) => RouteItemProps[];
};
export {};