npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nvoo/ui-layout

v1.0.0

Published

Nvoo — Admin framework layout shell (sidebar + header + tabs + keep-alive)

Downloads

19

Readme

@nvoo/ui-layout

Nvoo — Admin 管理框架布局壳:侧边栏 + 顶栏 + 多标签页 + Keep-Alive。

基于 ant-design-vue 4.x 构建,依赖 @nvoo/store 提供状态管理、@nvoo/ui 提供业务组件。内置 chrome / line / pill 三种标签变体,并附带 schema 驱动的 PC / H5 列表页渲染器(H5 端依赖 vant 4,可选)。


安装

pnpm add @nvoo/ui-layout

Peer Dependencies

| 包 | 版本 | 必需 | 说明 | | ----------------------- | ------------- | -------- | ---------------------------------------- | | vue | ^3.5.0 | 是 | Composition API + <script setup> | | vue-router | ^4.4.0 | 是 | 路由同步 / Keep-Alive 模式 | | pinia | ^3.0.0 | 是 | store 注入 | | ant-design-vue | ^4.0.0 | 是 | 基础组件 + theme token | | @ant-design/icons-vue | ^7.0.0 | 是 | 头部/菜单/折叠按钮图标 | | @emotion/css | ^11.0.0 | 是 | 运行时样式注入 | | @vueuse/core | ^14.0.0 | 是 | useElementSize / useFullscreen 等 | | dayjs | ^1.11.0 | 是 | 列表页日期控件 | | @nvoo/store | workspace:* | 是 | appStore / navTabStore / menuStore | | @nvoo/ui | workspace:* | 是 | 业务组件 | | @nvoo/schema | workspace:* | 是 | 列表页 schema 类型 | | @nvoo/dictionary | workspace:* | 是 | 列表页字典 | | vant | ^4.9.0 | 可选 | 仅当使用 @nvoo/ui-layout/h5 时需要 |


文档导航

详细的组件 API、主题、教程文档均在 ./docs/ 下,本 README 只做索引。

组件 API(每组件一文件)

| 组件 | 文档 | 一句话定位 | | ----------------- | --------------------------------------------- | --------------------------------------- | | BLayout | docs/components/BLayout.md | 主壳:Sider + HeaderLayout + Content | | BHeaderLayout | docs/components/BHeaderLayout.md | 顶栏:Collapse + Tabs + Actions + User | | BRouterContent | docs/components/BRouterContent.md | Keep-Alive 路由视图(matched 层模式) | | BKeepAliveView | docs/components/BKeepAliveView.md | 嵌套子路由专用 Keep-Alive | | BAppTheme | docs/components/BAppTheme.md | 主题 ConfigProvider | | BTab | docs/components/BTab.md | 多标签页导航栏(变体可插拔) | | BAppLayout | docs/components/BAppLayout.md | 设备响应式布局容器 | | BListLayout | docs/components/BListLayout.md | 列表/表格页布局 | | BShowLayout | docs/components/BShowLayout.md | 详情/编辑页布局 | | BMenu | docs/components/BMenu.md | 侧边栏导航菜单 |

主题与专题

| 主题 | 文档 | 说明 | | ------------------- | --------------------------------------------- | ----------------------------------------------------- | | 主题与视觉预设 | docs/theme/README.md | 4 层体系 / 12 套 sider 预设 / MenuThemeOverride cookbook | | Header 内部子组件 | docs/header-internals.md | Collapse / Actions / User / Search | | Tab 变体系统 | docs/tab-variants.md | base + shape + modifier 组合契约 | | Tab 内部子组件 | docs/tab-internals.md | TabItem / Overflow / ContextMenu | | Context 系统 | docs/context.md | AppContext / CustomPresetsKey 等 | | Hooks | docs/hooks.md | useDesign / useAntdToken / useResolvedTheme | | Utils | docs/utils.md | useMenuCore | | 多层级路由缓存 | docs/multi-level-cache.md | 两层缓存 + tabGroup + meta.keepAlive | | 自动导入 Resolver | docs/resolver.md | unplugin-vue-components 适配 | | PC 列表页渲染器 | docs/list-page/README.md | schema 驱动 PC 列表页 | | H5 列表页渲染器 | docs/h5-list-page/README.md | schema 驱动 H5 列表页(Vant 4) |


入口与导出(三入口架构)

包通过 exports 暴露三个入口,按需引入可避免 PC 项目被迫打包 list-page / vant:

| 入口 | 路径 | 内容 | 依赖 vant | | ------------------- | ------------------------ | ------------------------------------------------------------------------------------------------- | --------- | | 主入口(shell) | @nvoo/ui-layout | 布局壳组件(BLayout / BHeaderLayout / BTab …)+ Tab 变体工厂 + Context / Hooks / Utils + Resolver | 否 | | PC 子系统 | @nvoo/ui-layout/pc | PcListPageRenderer + PC 表单控件注册表 + 共享 schema 工具 | 否 | | H5 子系统 | @nvoo/ui-layout/h5 | H5ListPageRenderer + H5 表单控件注册表 + 共享 schema 工具 | 是 |

主入口在 import 时会自动调用 injectGlobalStyles()(注入全局滚动条隐藏 + 路由过渡动画样式)。


目录结构

src/
├── index.ts                        # 主入口(shell 组件 + Hooks/Utils/Context)
├── pc.ts                           # PC 子入口(PcListPageRenderer + schema 工具)
├── h5.ts                           # H5 子入口(H5ListPageRenderer + schema 工具)
├── resolver.ts                     # unplugin-vue-components 自动导入 resolver
├── context/                        # AppContextKey / CustomPresetsKey
├── hooks/                          # useDesign / useAntdToken / useResolvedTheme
├── composables/                    # useFullscreen / useMenuSearch
├── utils/                          # useMenuCore / withInstall
├── styles/                         # injectGlobalStyles + header / tab 样式
└── components/
    ├── layout/                     # BLayout / BHeaderLayout / Header* / siderPresets / use*Theme
    ├── menu/                       # BMenu + useMenuTheme + style
    ├── tab/                        # BTab + variants(chrome/line/pill)+ composables
    └── list-page/                  # PC + H5 双端 schema 驱动列表页

完整组件目录详见各 docs/components/*.md 文档。


快速开始

// main.ts
import { createKernel, createPiniaPlugin, createRouterPlugin } from "@nvoo/core";

const kernel = createKernel({ rootComponent: App });

kernel.use(createPiniaPlugin());
kernel.use(createRouterPlugin({ routes }));

await kernel.start();
<!-- App.vue -->
<script setup lang="ts">
  import { BAppTheme, BAppLayout, BLayout } from "@nvoo/ui-layout";
</script>

<template>
  <BAppTheme>
    <BAppLayout>
      <template #desktop>
        <BLayout>
          <template #logo><img src="/logo.svg" /></template>
        </BLayout>
      </template>
    </BAppLayout>
  </BAppTheme>
</template>

完整示例(列表页 / 详情页 / 多层级缓存)见对应组件文档。


架构

┌─────────────────────────────────────────────────────┐
│                    BLayout                           │
│  ┌──────────┐  ┌──────────────────────────────────┐ │
│  │          │  │  BHeaderLayout                   │ │
│  │  BMenu   │  │  ┌──────┐ ┌────────┐ ┌─────────┐ │ │
│  │          │  │  │Fold  │ │  BTab  │ │Actions  │ │ │
│  │  logo    │  │  │btn  │ │ (Nav)  │ │+ User   │ │ │
│  │  [slot]  │  │  └──────┘ └────────┘ └─────────┘ │ │
│  │          │  ├──────────────────────────────────┤ │
│  │          │  │  BRouterContent                  │ │
│  │          │  │  (Keep-Alive matched 层模式)     │ │
│  └──────────┘  └──────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

        ▲ provide(AppContextKey)
        │
  ┌─────┴──────────┬─────────────────┐
  │                │                 │
watermarkContent  onReloadPage   enableTabContextMenu
renderMenuIcon

页面级布局(BListLayout / BShowLayout 结构图)详见各自组件文档。


导出总览

主入口 @nvoo/ui-layout

// Vue 组件(均带 withInstall,可 app.use 注册也可直接用)
export const BLayout: DefineComponent;
export const BHeaderLayout: DefineComponent;
export const BRouterContent: DefineComponent;
export const BKeepAliveView: DefineComponent;
export const BAppTheme: DefineComponent;
export const BTab: DefineComponent;

// TSX 组件
export const BAppLayout: DefineComponent;
export const BListLayout: DefineComponent;
export const BShowLayout: DefineComponent;
export const BMenu: DefineComponent;

// Tab 变体工厂 + 解析器
export { chromeVariant, lineVariant, pillVariant, resolveVariant } from "./components/tab/variants";

// Tab 类型
export type {
  TabItemData,
  TabVariantName,
  TabVariantDef,
  TabStateFlags,
  TabOverflowState,
  TabProps,
  TabExpose
} from "./components/tab/types";
export type { TabVariant } from "@nvoo/store"; // 严格 3 联合:"chrome" | "line" | "pill"

// Layout 类型
export type {
  HeaderUserInfo,
  HeaderUserMenuItem,
  HeaderUserProps,
  MenuThemeOverride,
  SiderThemeOverride
} from "./components/layout";

// Sider 预设契约(类型 + 视觉资产 + 中文 label)
export type {
  SiderPresetName,
  SiderPresetFactory,
  SiderPresetDef
} from "./components/layout";
export { siderPresetFactories, siderPresetLabels } from "./components/layout";

// 主题 hook + 类型
export { useResolvedTheme } from "./hooks/useResolvedTheme";
export type { ResolvedTheme } from "./hooks/useResolvedTheme";

// Context
export { AppContextKey } from "./context/AppContext";
export type { AppContext } from "./context/AppContext";
export { CustomSiderPresetsKey } from "./context/CustomSiderPresets";

// Hooks
export { useDesign, useAntdToken } from "./hooks/useDesign";

// Utils
export { default as useMenuCore } from "./utils/useMenuCore";
export type { MenuItem, MenuItemBadge, BadgeType } from "./utils/useMenuCore";

// Resolver
export { NvUiLayoutResolver } from "./resolver";

PC 子入口 @nvoo/ui-layout/pc

export { PcListPageRenderer } from "./components/list-page/PcListPageRenderer";

// 表单控件注册表
export {
  registerFormControl,
  getControl,
  resolveControl,
  renderRegistration,
  type ControlRegistration,
  type ControlRenderer
} from "./components/list-page/control-registry";

// 共享 schema 工具
export {
  resolveTableColumns,
  resolveSearchFields,
  resolveCardFields,
  type ResolvedTableColumn
} from "./components/list-page/column-resolver";
export {
  useDictResolver,
  type UseDictResolverOptions,
  type DictResolverReturn
} from "./components/list-page/dict-resolver";
export { useRendererState, type RendererState } from "./components/list-page/useRendererState";

H5 子入口 @nvoo/ui-layout/h5

export { H5ListPageRenderer } from "./components/list-page/H5ListPageRenderer";
export { type H5CardSlotScope } from "./components/list-page/primitives/H5CardList";

export {
  registerH5FormControl,
  getH5Control,
  resolveH5Control,
  renderH5Registration,
  type H5ControlRegistration,
  type H5ControlRenderer
} from "./components/list-page/h5-control-registry";

// 共享 schema 工具(与 PC 入口相同)
export {
  resolveTableColumns,
  resolveSearchFields,
  resolveCardFields,
  type ResolvedTableColumn
} from "./components/list-page/column-resolver";
export {
  useDictResolver,
  type UseDictResolverOptions,
  type DictResolverReturn
} from "./components/list-page/dict-resolver";
export { useRendererState, type RendererState } from "./components/list-page/useRendererState";

注意事项

  1. 色彩消费契约(强制):业务 UI 组件禁止硬编码颜色十六进制值,禁止消费 SDK 内部的 --b-* CSS 变量(这些是 SDK 私有样式系统的实现细节,随时可能变更)。唯一入口为 useAntdToken(),通过 emotion 模板插值或 CSS Module 内插值消费。违反契约的代码不可合入。

  2. Keep-Alive 模式:外层 BRouterContent 按 matched 当前渲染层的 path/name 做稳定缓存(父路由 wrapper 在嵌套子路由切换时不销毁),缓存白名单由 meta.keepAlive === true + navTabStore.list 共同决定。嵌套子路由缓存交给父页面内部的 BKeepAliveView,按子路由 meta.keepAlive 过滤。详见 多层级路由缓存。

  3. 路由 Meta 约定:

    • meta.title:BShowLayout 的页面标题、Tab 标签页标题
    • meta.keepAlive:是否缓存该页面
    • meta.keepOpen / TabItemData.affix:标签页是否不可关闭
  4. 样式引入:组件样式通过 @emotion/css 运行时注入,无需额外引入 CSS 文件。全局滚动条隐藏 + 路由过渡样式会在首次 import 主入口时通过 injectGlobalStyles() 自动注入。

  5. DeviceStore 初始化:BAppLayout 依赖 useDeviceStore,需确保 device.initBreakpoints() 已调用(通常由 @nvoo/store 的初始化流程自动处理)。

  6. Tab 变体消费:业务侧请通过 useAppStore().tabVariant / tabBordered 全局切换,NavTabAdapter 会自动响应;独立使用 <BTab> 时通过 variant / bordered props 控制。详见 Tab 变体系统。

  7. 已废弃组件:早期版本的 SettingDrawer / BlockCheckbox / tab/Search.tsx / MobileList 顶层导出均已移除,不要再引用。

  8. 多入口按需引入:PC 项目不要 import @nvoo/ui-layout/h5(会拖入 vant)。仅当需要列表页渲染器时再引入 pc 或 h5 子入口;纯 shell 用主入口即可。

  9. siderPreset 字段位置:早期版本 siderPreset 存在 appStore.ui.siderPreset,现已提升为顶层字段 appStore.siderPreset(默认 "content",参与持久化)。SDK 消费时顶层优先:store.siderPreset ?? store.ui?.siderPreset ?? "auto"。新代码请直接用顶层字段;setUi({ siderPreset }) 仍可用(内部双写)。


协议

MIT