UNPKG

@gulibs/vgrove-ui

Version:

VGrove UI component library built with HeroUI and React

992 lines 28.7 kB
import type { KeyboardEvent, PressEvent } from '@react-types/shared'; import type * as React from 'react'; import type { UIMatch } from "react-router"; import type { ClassValue, TVReturnType, VariantProps } from 'tailwind-variants'; import type { MiddlewareContext } from './middleware'; export type SlotsToClasses<S extends string> = { [key in S]?: Exclude<ClassValue, 0n>; }; /** * 框架要求的最小用户接口 * 用户可以扩展此接口来定义自己的用户类型 */ export interface BaseUser { /** 用户唯一标识 */ id: string | number; [x: string]: any; } /** * 本地化类型,可以是任何字符串 */ export type LocalizedType<Keys extends string = string> = Keys | (string & {}); /** * 本地化对象,包含本地化ID */ export type Localized<Keys extends string = string> = { localizedId: LocalizedType<Keys>; }; /** * 本地化对象或React节点 */ export type LocalizedOrNode<Keys extends string = string> = Localized<Keys> | React.ReactNode; /** * 页面元数据 */ export type PageMeta<Keys extends string = string> = { /** 页面标题 */ title?: LocalizedOrNode<Keys>; /** 页面描述 */ description?: string; }; export type PageHeaderMeta<Keys extends string = string> = { /** 页面标题 */ title?: LocalizedOrNode<Keys>; /** 页面描述 */ description?: LocalizedOrNode<Keys>; }; /** * 路由保护状态类型 * 🔥 新增:细粒度的错误状态,区分不同的失败原因 */ export type RouteProtectionState = 'loading' | 'ready' | 'checking' | 'middleware_completed' | 'passed' | 'error' | 'redirecting' | 'unauthenticated' | 'insufficient_permissions' | 'role_mismatch' | 'forbidden'; /** * 路由保护状态渲染器的 props */ export interface RouteProtectionStateProps { /** 当前路径 */ path?: string; /** 错误信息 */ error?: string | null; /** 重试函数 */ retry?: () => void; /** 重定向路径 */ redirectPath?: string | null; /** 重定向倒计时(秒) */ redirectCountdown?: number; /** 取消重定向的回调函数 */ onCancelRedirect?: () => void; /** 重定向配置 */ redirectConfig?: RedirectConfig; /** 状态 */ status?: RouteProtectionState; /** 是否正在过渡 */ isTransitioning?: boolean; /** 自定义选项 */ customOptions?: { /** 自定义按钮文字 */ buttonTexts?: { /** 主要操作按钮文字(如"前往登录"、"申请权限"等) */ primaryAction?: string; /** 重试按钮文字 */ retryAction?: string; /** 取消按钮文字 */ cancelAction?: string; /** 返回按钮文字 */ backAction?: string; }; /** 自定义重定向路径 */ redirectPaths?: { /** 登录页面路径 */ loginPath?: string; /** 权限申请页面路径 */ permissionRequestPath?: string; /** 返回页面路径 */ backPath?: string; }; /** 自定义按钮行为 */ buttonActions?: { /** 主要操作按钮的自定义行为 */ primaryAction?: () => void; /** 重试按钮的自定义行为 */ retryAction?: () => void; /** 取消按钮的自定义行为 */ cancelAction?: () => void; /** 返回按钮的自定义行为 */ backAction?: () => void; }; /** 自定义标题和描述 */ texts?: { /** 自定义标题 */ title?: string; /** 自定义描述 */ description?: string; }; }; } export interface RouteProtectionCheckingProps { } export interface RouteProtectionPassedProps { } export interface RouteProtectionRedirectingProps { } export interface RouteProtectionUnknownProps { status?: RouteProtectionState; } /** * 路由保护状态渲染器 * 🔥 新增:细粒度的错误状态渲染器 */ export interface RouteProtectionStateRenderers { /** 🔥 新增:初始加载状态的渲染器 */ loading?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 🔥 新增:准备就绪状态的渲染器 */ ready?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 检查中状态的渲染器 */ checking?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 检查通过状态的渲染器 */ passed?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 错误状态的渲染器 */ error?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 重定向状态的渲染器 */ redirecting?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 🔥 新增:未认证状态的渲染器 */ unauthenticated?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 🔥 新增:权限不足状态的渲染器 */ insufficient_permissions?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 🔥 新增:角色不匹配状态的渲染器 */ role_mismatch?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); /** 🔥 新增:禁止访问状态的渲染器 */ forbidden?: React.ReactNode | ((props: RouteProtectionStateProps) => React.ReactNode); } /** * 路由保护智能配置选项 */ export interface RouteProtectionOptions { /** 是否启用智能循环检测(默认为 true) */ enableLoopDetection?: boolean; /** 是否排除常见的公共路径(默认为 true) */ excludeCommonPublicPaths?: boolean; } /** * 智能认证配置选项 */ export interface SmartAuthOptions<TUser extends BaseUser = BaseUser> extends Omit<AuthOptions<TUser>, 'check'> { /** 自定义认证检查函数 */ check?: (context: AuthContext<TUser>) => boolean | Promise<boolean>; /** 所需的角色 */ roles?: string[]; /** 所需的权限 */ permissions?: string[]; /** 额外的公共路径(不需要认证的路径) */ publicPaths?: string[]; /** 是否启用智能循环检测(默认为 true) */ enableLoopDetection?: boolean; /** 是否排除常见的公共路径(默认为 true) */ excludeCommonPublicPaths?: boolean; } declare const breadcrumbs: TVReturnType<{ size: { sm: {}; md: {}; lg: {}; }; radius: { none: { list: string; }; sm: { list: string; }; md: { list: string; }; lg: { list: string; }; full: { list: string; }; }; variant: { solid: { list: string; }; bordered: { list: string; }; light: {}; }; }, { base: string; list: string; ellipsis: string; separator: string; }, undefined, { size: { sm: {}; md: {}; lg: {}; }; radius: { none: { list: string; }; sm: { list: string; }; md: { list: string; }; lg: { list: string; }; full: { list: string; }; }; variant: { solid: { list: string; }; bordered: { list: string; }; light: {}; }; }, { base: string; list: string; ellipsis: string; separator: string; }, TVReturnType<{ size: { sm: {}; md: {}; lg: {}; }; radius: { none: { list: string; }; sm: { list: string; }; md: { list: string; }; lg: { list: string; }; full: { list: string; }; }; variant: { solid: { list: string; }; bordered: { list: string; }; light: {}; }; }, { base: string; list: string; ellipsis: string; separator: string; }, undefined, {}, {}, undefined>>; declare const breadcrumbItem: TVReturnType<{ color: { foreground: { item: string; separator: string; }; primary: { item: string; separator: string; }; secondary: { item: string; separator: string; }; success: { item: string; separator: string; }; warning: { item: string; separator: string; }; danger: { item: string; separator: string; }; }; size: { sm: { item: string; }; md: { item: string; }; lg: { item: string; }; }; underline: { none: { item: string; }; hover: { item: string; }; always: { item: string; }; active: { item: string; }; focus: { item: string; }; }; isCurrent: { true: { item: string; }; false: { item: string[]; }; }; isDisabled: { true: { item: string; separator: string; }; }; disableAnimation: { false: { item: string; }; true: { item: string; }; }; }, { base: string; item: string[]; separator: string; }, undefined, { color: { foreground: { item: string; separator: string; }; primary: { item: string; separator: string; }; secondary: { item: string; separator: string; }; success: { item: string; separator: string; }; warning: { item: string; separator: string; }; danger: { item: string; separator: string; }; }; size: { sm: { item: string; }; md: { item: string; }; lg: { item: string; }; }; underline: { none: { item: string; }; hover: { item: string; }; always: { item: string; }; active: { item: string; }; focus: { item: string; }; }; isCurrent: { true: { item: string; }; false: { item: string[]; }; }; isDisabled: { true: { item: string; separator: string; }; }; disableAnimation: { false: { item: string; }; true: { item: string; }; }; }, { base: string; item: string[]; separator: string; }, TVReturnType<{ color: { foreground: { item: string; separator: string; }; primary: { item: string; separator: string; }; secondary: { item: string; separator: string; }; success: { item: string; separator: string; }; warning: { item: string; separator: string; }; danger: { item: string; separator: string; }; }; size: { sm: { item: string; }; md: { item: string; }; lg: { item: string; }; }; underline: { none: { item: string; }; hover: { item: string; }; always: { item: string; }; active: { item: string; }; focus: { item: string; }; }; isCurrent: { true: { item: string; }; false: { item: string[]; }; }; isDisabled: { true: { item: string; separator: string; }; }; disableAnimation: { false: { item: string; }; true: { item: string; }; }; }, { base: string; item: string[]; separator: string; }, undefined, {}, {}, undefined>>; type BreadcrumbsVariantProps = VariantProps<typeof breadcrumbs>; type BreadcrumbItemVariantProps = VariantProps<typeof breadcrumbItem>; type BreadcrumbsColor = "foreground" | "primary" | "secondary" | "success" | "warning" | "danger"; type BreadcrumbsUnderline = "none" | "active" | "hover" | "focus" | "always"; type BreadcrumbItemUnderline = "none" | "active" | "hover" | "focus" | "always"; export interface BreadcrumbsProps extends BreadcrumbsVariantProps { /** The content of the breadcrumbs */ children: React.ReactNode; /** The color of the breadcrumbs */ color?: BreadcrumbsColor; /** When the underline should appear */ underline?: BreadcrumbsUnderline; /** Custom separator node */ separator?: React.ReactNode; /** Max number of breadcrumbs to display */ maxItems?: number; /** Number of breadcrumbs to show before the ellipsis */ itemsBeforeCollapse?: number; /** Number of breadcrumbs to show after the ellipsis */ itemsAfterCollapse?: number; /** Whether to hide the separator */ hideSeparator?: boolean; /** Whether the breadcrumbs are disabled */ isDisabled?: boolean; /** Whether to disable animations */ disableAnimation?: boolean; /** Classes for different parts of the breadcrumbs */ itemClasses?: SlotsToClasses<"base" | "item" | "separator">; /** Class names for different parts of the breadcrumbs */ classNames?: SlotsToClasses<"base" | "list" | "ellipsis" | "separator">; /** Callback when any of the breadcrumbs is pressed */ onAction?: (key: React.Key) => void; [key: string]: any; } export interface BreadcrumbItemProps extends BreadcrumbItemVariantProps { /** The content of the breadcrumb item */ children: React.ReactNode; /** When the underline should appear */ underline?: BreadcrumbItemUnderline; /** Content to display before the children */ startContent?: React.ReactNode; /** Content to display after the children */ endContent?: React.ReactNode; /** Custom separator node */ separator?: React.ReactNode; /** Whether this item represents the current page */ isCurrent?: boolean; /** Whether this item is the last one in the breadcrumbs */ isLast?: boolean; /** Whether to hide the separator */ hideSeparator?: boolean; /** Whether the breadcrumb item is disabled */ isDisabled?: boolean; /** Whether to disable animations */ disableAnimation?: boolean; /** Class names for different parts of the breadcrumb item */ classNames?: SlotsToClasses<"base" | "item" | "separator">; /** Handler called when the press is released over the target */ onPress?: (e: PressEvent) => void; /** Handler called when a press interaction starts */ onPressStart?: (e: PressEvent) => void; /** Handler called when a press interaction ends, either over the target or when the pointer leaves the target */ onPressEnd?: (e: PressEvent) => void; /** Handler called when a key is pressed while the target has focus */ onKeyDown?: (e: KeyboardEvent) => void; /** Handler called when a key is released while the target has focus */ onKeyUp?: (e: KeyboardEvent) => void; [key: string]: any; } /** * 页面额外内容上下文 */ export interface PageExtrasContext<Keys extends string = string> { /** 当前路由路径 */ path: string; /** 路由参数 */ params: Record<string, string>; /** 查询参数 */ query: Record<string, string>; /** 当前路由匹配信息 */ matches: UIMatch[]; /** 当前页面的 handle */ handle: PageHandle<Keys>; } /** * 页面处理配置 */ export type PageHandle<Keys extends string = string> = { /** 元数据 */ meta?: PageMeta<Keys>; /** 页面元数据 */ pageMeta?: PageHeaderMeta<Keys>; /** 额外内容 */ pageExtras?: ((context: PageExtrasContext<Keys>) => React.ReactNode) | React.ReactNode; /** 面包屑配置 */ breadcrumbs?: Omit<BreadcrumbItemProps, "children">; /** 路由匹配 */ matches?: UIMatch[]; /** 其他自定义属性 */ [x: string]: any; }; /** * 守卫执行上下文 */ export interface GuardContext<TUser extends BaseUser = BaseUser> { /** 当前路由路径 */ path: string; /** 路由参数 */ params: Record<string, string>; /** 查询参数 */ query: Record<string, string>; /** 用户信息 */ user?: TUser | null; /** 用户权限 */ permissions?: string[]; /** 用户角色 */ roles?: string[]; /** 自定义数据 */ data: Record<string, any>; } /** * 认证上下文 */ export interface AuthContext<TUser extends BaseUser = BaseUser> { /** 当前路由路径 */ path: string; /** 路由参数 */ params: Record<string, string>; /** 查询参数 */ query: Record<string, string>; /** 用户信息 */ user?: TUser | null; /** 用户权限 */ permissions?: string[]; /** 用户角色 */ roles?: string[]; /** 自定义数据 */ data: Record<string, any>; } /** * 认证状态 */ export interface AuthState<TUser extends BaseUser = BaseUser> { user: TUser | null; token: string | null; refreshToken: string | null; isAuthenticated: boolean; isLoading: boolean; error: string | null; } /** * 认证操作 */ export interface AuthActions<TUser extends BaseUser = BaseUser, TCredentials = any> { login: (credentials: TCredentials) => Promise<void>; logout: () => void; refreshUser: () => Promise<void>; refreshTokenAction: () => Promise<void>; updateUser: (userData: Partial<TUser>) => void; setToken: (token: string) => void; setRefreshToken: (refreshToken: string) => void; clearError: () => void; } /** * API 字段映射 */ export interface FieldMapping { /** 用户数据字段名,默认 'user' */ userField?: string; /** Token字段名,默认 'token' */ tokenField?: string; /** RefreshToken字段名,默认 'refreshToken' */ refreshTokenField?: string; } /** * 数据转换器 */ export interface DataTransformers<TUser extends BaseUser = BaseUser, TCredentials = any> { /** 登录前转换凭据 */ transformCredentials?: (credentials: TCredentials) => any; /** 登录后转换用户数据 */ transformUser?: (userData: any) => TUser; /** 存储前转换用户数据 */ beforeStore?: (userData: TUser) => any; /** 读取后转换用户数据 */ afterRestore?: (userData: any) => TUser; } /** * useUser 配置 */ export interface UseUserOptions<TUser extends BaseUser = BaseUser, TCredentials = any> { /** 存储键前缀 */ storagePrefix?: string; /** 是否使用 sessionStorage(默认使用 localStorage) */ useSessionStorage?: boolean; /** 获取用户信息的函数 */ fetchUser?: (token: string) => Promise<TUser>; /** 登录API */ loginApi?: (credentials: TCredentials) => Promise<{ user: TUser; token: string; refreshToken?: string; }>; /** 刷新Token API */ refreshTokenApi?: (refreshToken: string) => Promise<{ token: string; refreshToken?: string; user?: TUser; }>; /** 自动刷新间隔(毫秒,0表示禁用) */ autoRefreshInterval?: number; /** Token过期检查函数 */ isTokenExpired?: (token: string) => boolean; /** RefreshToken过期检查函数 */ isRefreshTokenExpired?: (refreshToken: string) => boolean; /** API字段映射 */ fieldMapping?: FieldMapping; /** 数据转换器 */ transformers?: DataTransformers<TUser, TCredentials>; } /** * 中间件选项 */ export interface MiddlewareOptions { /** 中间件名称 */ name?: string; /** 执行优先级(数字越小越先执行)*/ priority?: number; /** 是否仅在开发环境执行 */ devOnly?: boolean; /** 中间件处理函数 */ handler: (context: MiddlewareContext, next: () => Promise<void> | void) => Promise<void> | void; } /** * 守卫选项 */ export interface GuardOptions<TUser extends BaseUser = BaseUser> { /** 守卫名称 */ name?: string; /** 守卫类型 */ type?: 'auth' | 'role' | 'permission' | 'custom'; /** 守卫条件函数 */ condition: (context: AuthContext<TUser>) => boolean | Promise<boolean>; /** 失败时的重定向路径 */ redirectTo?: string; /** 错误消息 */ errorMessage?: string; /** 重定向配置 */ redirectConfig?: RedirectConfig; } /** * 认证选项 */ export interface AuthOptions<TUser extends BaseUser = BaseUser> { /** 认证名称 */ name?: string; /** 认证失败时的重定向路径 */ redirectTo?: string; /** 错误信息 */ errorMessage?: string; /** 自定义认证检查函数 */ check?: (context: AuthContext<TUser>) => boolean | Promise<boolean>; /** 所需的角色 */ roles?: string[]; /** 所需的权限 */ permissions?: string[]; /** 重定向配置 */ redirectConfig?: RedirectConfig; /** 是否已经增强(内部使用) */ _isEnhanced?: boolean; /** 是否为智能认证(内部使用) */ _isSmartAuth?: boolean; /** 是否为根级认证(内部使用) */ _isRootAuth?: boolean; /** 公共路径配置 */ publicPaths?: string[]; /** 是否启用循环检测 */ enableLoopDetection?: boolean; /** 是否排除常见公共路径 */ excludeCommonPublicPaths?: boolean; /** 🔥 新增:自定义渲染器选项 */ customOptions?: RouteProtectionStateProps['customOptions']; } /** * 增强的国际化 Handle 类型 */ export interface I18nHandle<Keys extends string = string> extends PageHandle<Keys> { /** 标记为需要国际化处理 */ i18n: boolean; /** 国际化元数据处理器 */ getI18nMeta?: (t: (key: string) => string) => { title?: string; description?: string; [key: string]: any; }; } /** * 路由加载器数据类型 */ export interface RouteI18nData { /** 当前语言 */ locale: string; /** 国际化资源是否已加载 */ i18nLoaded: boolean; /** 国际化资源 Promise(用于 defer 加载) */ i18n?: Promise<any>; /** 其他数据 */ data?: any; } /** * 国际化路由 loader 选项 */ export interface I18nRouteLoaderOptions { /** 要预加载的语言列表,默认使用当前语言 */ locales?: string[]; /** 是否预加载所有支持的语言 */ preloadAll?: boolean; /** 延迟加载时间(毫秒),用于演示加载状态 */ delay?: number; } /** * 增强路由的国际化选项 */ export interface EnhanceRoutesI18nOptions { /** 是否为所有路由添加国际化 loader */ autoAddLoader?: boolean; } /** * 路由配置文件中的错误组件属性 */ export interface RouteErrorComponentProps { /** 错误对象 */ error?: Error; /** 重试函数 */ retry?: () => void; /** 重置错误状态 */ reset?: () => void; } /** * 路由配置文件中的加载组件属性 */ export interface RouteLoadingComponentProps { /** 加载进度 (0-1) */ progress?: number; /** 是否显示取消按钮 */ showCancel?: boolean; /** 取消加载回调 */ onCancel?: () => void; } export type ClientConfigMergeStrategy = 'override' | 'inherit' | 'deep-merge' | 'partial-override'; export interface ClientConfigMergeRules { /** 认证配置合并策略 */ auth: ClientConfigMergeStrategy; /** 守卫配置合并策略 */ guard: ClientConfigMergeStrategy; /** 错误组件合并策略 */ error: ClientConfigMergeStrategy; /** 加载组件合并策略 */ loading: ClientConfigMergeStrategy; /** 状态渲染器合并策略 */ stateRenderers: ClientConfigMergeStrategy; /** 重定向配置合并策略 */ redirectConfig: ClientConfigMergeStrategy; } /** * 路由配置文件类型定义 * 与 vgrove-autoroutes 中的 RouteConfigs 对应 */ export interface ClientRouteConfigs<TUser extends BaseUser = BaseUser> { /** 认证配置 */ auth?: AuthOptions<TUser>; /** 路由守卫配置 */ guard?: GuardOptions<TUser>; /** 错误边界组件 */ error?: ((props: RouteErrorComponentProps) => React.ReactNode) | React.ReactNode; /** 加载组件 */ loading?: ((props: RouteLoadingComponentProps) => React.ReactNode) | React.ReactNode; /** 自定义状态渲染器 */ stateRenderers?: RouteProtectionStateRenderers; /** 其他配置项 */ [key: string]: any; } export interface ClientConfigInheritanceNode<TUser extends BaseUser = BaseUser> extends Record<string, any> { /** 配置文件路径 */ configPath: string; /** 配置文件内容解析结果 */ configs: ClientRouteConfigs<TUser>; /** 是否有实际保护配置 */ hasProtectionConfig: boolean; /** 路由路径(相对于根目录) */ routePath: string; /** 继承层级(0为根目录) */ level: number; } export interface ClientConfigInheritanceInfo<TUser extends BaseUser = BaseUser> extends Record<string, any> { /** 是否启用了配置继承 */ enabled: boolean; /** 配置继承链 */ chain: ClientConfigInheritanceChain<TUser>; /** 配置查找缓存键 */ cacheKey: string; } export interface ClientConfigInheritanceChain<TUser extends BaseUser = BaseUser> extends Record<string, any> { /** 当前路由节点 */ current: ClientConfigInheritanceNode<TUser> | null; /** 父级配置节点链(从直接父级到根级) */ parents: ClientConfigInheritanceNode<TUser>[]; /** 合并后的最终配置 */ merged: ClientRouteConfigs<TUser>; } export interface RedirectConfig { /** 重定向延迟时间(毫秒),设置为 0 表示立即跳转,默认 1500ms */ delay?: number; /** 是否可以取消重定向,默认 true */ cancellable?: boolean; /** 自定义取消按钮文本 */ cancelText?: string; /** 取消重定向的回调函数 */ onCancel?: () => void; /** 重定向开始的回调函数 */ onRedirectStart?: (redirectTo: string, countdown: number) => void; /** 重定向执行的回调函数 */ onRedirectExecute?: (redirectTo: string) => void; } export type Middlewares = (MiddlewareOptions | ((context: any, next: () => void) => Promise<void> | void))[]; export type Guards<TUser extends BaseUser = BaseUser> = (AuthOptions<TUser> | GuardOptions<TUser> | (() => Promise<boolean> | boolean))[]; /** * 路由保护包装器组件的属性 */ export interface RouteProtectionWrapperProps<TUser extends BaseUser = BaseUser> extends RouteProtectionOptions { /** 守卫配置列表 (向后兼容) */ guards?: Guards<TUser>; /** 加载组件 (向后兼容) */ loadingComponent?: ((props: RouteProtectionStateProps) => React.ReactNode) | React.ReactNode; /** 错误边界组件 (向后兼容) */ errorComponent?: ((props: RouteErrorComponentProps) => React.ReactNode) | React.ReactNode; /** 自定义状态渲染器 (支持合并后的配置) */ stateRenderers?: RouteProtectionStateRenderers; /** 要保护的组件 */ component?: React.ReactNode; /** 配置继承信息 */ inheritanceInfo?: ClientConfigInheritanceInfo<TUser>; /** 中间件配置列表 */ middlewares?: Middlewares; } /** * 异步函数检查选项 */ export interface IsAsyncFunctionOptions { /** 是否启用调试模式 */ debug?: boolean; /** 是否启用行为检查 */ enableBehaviorCheck?: boolean; /** 是否严格检查 */ strict?: boolean; /** 是否检查 Promise 返回类型 */ checkPromiseReturn?: boolean; } export {}; //# sourceMappingURL=types.d.ts.map