@robot-admin/naive-ui-components 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +2 -0
  3. package/README_EN.md +2 -0
  4. package/SECURITY.md +10 -0
  5. package/THIRD_PARTY_NOTICES.md +10 -0
  6. package/dist/C_AntV2.cjs +1 -1
  7. package/dist/C_Barcode2.cjs +1 -1
  8. package/dist/C_Editor.css +18 -18
  9. package/dist/C_Editor2.cjs +1 -1
  10. package/dist/C_Editor2.js +1 -1
  11. package/dist/C_FilePreview.css +60 -60
  12. package/dist/C_FilePreview2.cjs +1 -1
  13. package/dist/C_FilePreview2.js +1 -1
  14. package/dist/C_Form.css +18 -18
  15. package/dist/C_FullCalendar2.cjs +1 -1
  16. package/dist/C_Markdown.css +38 -39
  17. package/dist/C_Markdown2.cjs +1 -1
  18. package/dist/C_Markdown2.js +1 -1
  19. package/dist/C_QRCode2.cjs +1 -1
  20. package/dist/C_Table.css +18 -18
  21. package/dist/C_Upload2.cjs +1 -1
  22. package/dist/C_WaterFall.css +49 -31
  23. package/dist/C_WaterFall2.cjs +1 -1
  24. package/dist/C_WaterFall2.js +1 -1
  25. package/dist/C_WorkFlow.css +112 -111
  26. package/dist/C_WorkFlow2.cjs +1 -1
  27. package/dist/C_WorkFlow2.js +1 -1
  28. package/dist/chunk.cjs +1 -1
  29. package/dist/constants.d.cts +1 -1
  30. package/dist/constants.d.ts +1 -1
  31. package/dist/constants3.d.cts +1 -1
  32. package/dist/constants3.d.ts +1 -1
  33. package/dist/constants4.d.cts +5 -5
  34. package/dist/constants4.d.ts +5 -5
  35. package/dist/constants5.d.cts +2 -2
  36. package/dist/constants5.d.ts +2 -2
  37. package/dist/data.cjs +1 -1
  38. package/dist/data.d.cts +7 -7
  39. package/dist/data.d.ts +7 -7
  40. package/dist/data.js +1 -1
  41. package/dist/graphics.d.cts +17 -11
  42. package/dist/graphics.d.ts +17 -11
  43. package/dist/helpers.cjs +1 -1
  44. package/dist/helpers.js +1 -1
  45. package/dist/html.cjs +1 -1
  46. package/dist/index.cjs +1 -1
  47. package/dist/index.vue.d.cts +2 -2
  48. package/dist/index.vue.d.ts +2 -2
  49. package/dist/index10.vue.d.cts +4 -4
  50. package/dist/index10.vue.d.ts +5 -5
  51. package/dist/index11.vue.d.cts +5 -5
  52. package/dist/index12.vue.d.ts +3 -3
  53. package/dist/index13.vue.d.cts +3 -3
  54. package/dist/index13.vue.d.ts +9 -9
  55. package/dist/index14.vue.d.cts +9 -9
  56. package/dist/index16.vue.d.ts +1 -1
  57. package/dist/index17.vue.d.cts +1 -1
  58. package/dist/index17.vue.d.ts +1 -1
  59. package/dist/index18.vue.d.cts +1 -1
  60. package/dist/index19.vue.d.cts +2 -2
  61. package/dist/index19.vue.d.ts +2 -2
  62. package/dist/index2.vue.d.cts +2 -2
  63. package/dist/index2.vue.d.ts +2 -2
  64. package/dist/index20.vue.d.cts +1 -1
  65. package/dist/index20.vue.d.ts +1 -1
  66. package/dist/index21.vue.d.cts +1 -1
  67. package/dist/index21.vue.d.ts +1 -1
  68. package/dist/index24.vue.d.cts +1 -1
  69. package/dist/index24.vue.d.ts +1 -1
  70. package/dist/index25.vue.d.cts +2 -2
  71. package/dist/index25.vue.d.ts +2 -2
  72. package/dist/index26.vue.d.cts +2 -2
  73. package/dist/index26.vue.d.ts +2 -2
  74. package/dist/index3.vue.d.cts +4 -4
  75. package/dist/index3.vue.d.ts +4 -4
  76. package/dist/index6.vue.d.ts +2 -2
  77. package/dist/index7.vue.d.cts +2 -2
  78. package/dist/index8.vue.d.ts +1 -1
  79. package/dist/index9.vue.d.cts +1 -1
  80. package/dist/index9.vue.d.ts +4 -4
  81. package/dist/mapUtils.d.cts +1 -1
  82. package/dist/mapUtils.d.ts +1 -1
  83. package/dist/style.css +277 -259
  84. package/dist/types.d.ts +5 -0
  85. package/dist/types2.d.cts +5 -0
  86. package/dist/useCalendarEvents.d.cts +1 -1
  87. package/dist/useCalendarEvents.d.ts +1 -1
  88. package/dist/useCollapsePanel.d.cts +1 -1
  89. package/dist/useCollapsePanel.d.ts +1 -1
  90. package/dist/useCropperCore.d.cts +9 -9
  91. package/dist/useCropperCore.d.ts +9 -9
  92. package/dist/useDynamicFormState.d.cts +2 -2
  93. package/dist/useDynamicFormState.d.ts +2 -2
  94. package/dist/useEdgeInteraction.d.cts +2 -2
  95. package/dist/useEdgeInteraction.d.ts +2 -2
  96. package/dist/useFullscreen.d.cts +1 -1
  97. package/dist/useFullscreen.d.ts +1 -1
  98. package/dist/useInfiniteScroll.d.cts +17 -18
  99. package/dist/useInfiniteScroll.d.ts +17 -18
  100. package/dist/useQRCode.d.cts +3 -3
  101. package/dist/useQRCode.d.ts +3 -3
  102. package/dist/useSignatureHistory.d.cts +4 -4
  103. package/dist/useSignatureHistory.d.ts +4 -4
  104. package/dist/useSplitResize.d.cts +4 -4
  105. package/dist/useSplitResize.d.ts +4 -4
  106. package/dist/useTableQuery.cjs +1 -1
  107. package/dist/useTableQuery.d.cts +15 -13
  108. package/dist/useTableQuery.d.ts +15 -13
  109. package/dist/useTableQuery.js +1 -1
  110. package/dist/useWorkflowValidation.d.cts +35 -35
  111. package/dist/useWorkflowValidation.d.ts +35 -35
  112. package/dist/verification.d.cts +3 -3
  113. package/dist/verification.d.ts +3 -3
  114. package/dist/xlsx.js +143 -0
  115. package/dist/xlsx2.cjs +143 -0
  116. package/docs/architecture.en.md +1 -0
  117. package/docs/architecture.md +1 -0
  118. package/docs/guides/api-migration.md +111 -0
  119. package/docs/guides/runtime-performance.md +16 -1
  120. package/docs/guides/waterfall.md +113 -0
  121. package/docs/runtime-review-20261019.md +2 -0
  122. package/licenses/SheetJS.txt +201 -0
  123. package/package.json +13 -9
@@ -22,6 +22,7 @@ The core is currently an internal boundary, not a separately published package.
22
22
  - Full installation registers the public `C_*` names, avoiding collisions between inferred `index.vue` names or a host application's `index` component.
23
23
  - The root entry aggregates all components, including navigation, and preserves full installation. Runtime root imports require the optional `vue-router` peer, even for a non-routing named export. Applications without a router should use component subpaths.
24
24
  - `sortablejs` is needed only for the corresponding drag features. Selective JS loading does not mean ordinary runtime dependencies are selectively installed.
25
+ - SheetJS 0.20.3 is built from the unchanged official archive, verified against its SHA-512, installed build inputs and license. Its runtime ships in separate chunks, removing the consumer's CDN installation requirement. FilePreview loads it with the component; table XLSX export loads it on demand. Base form/table entry budgets remain enforced. See [third-party notices](../THIRD_PARTY_NOTICES.md).
25
26
  - ESM resolves `.d.ts`; CJS resolves `.d.cts`. Each declaration condition matches its JavaScript format.
26
27
  - All public reachable declarations are checked for `naive-ui/es/*` and `naive-ui/lib/*` internal imports, in both formats.
27
28
 
@@ -22,6 +22,7 @@
22
22
  - 全量插件使用公开的 `C_*` 名称注册组件,不以 SFC 的编译推断名注册,避免多个 `index.vue` 互相覆盖或覆盖宿主的 `index` 组件。
23
23
  - 根入口聚合全部组件并保留全量安装语义,包含导航组件;运行时导入根入口需要安装可选 peer `vue-router`,即使只使用根入口中的非路由组件。无需路由的项目优先使用组件子路径。
24
24
  - `sortablejs` 只在启用对应拖拽功能时需要。可选 peer 与 JS 按需加载不意味着普通运行依赖也按需安装。
25
+ - SheetJS 0.20.3 的官方原始归档作为本地构建依赖锁定,经过 SHA-512、构建输入和许可证校验;运行时代码随独立产物分发。消费者安装本库不再访问 SheetJS CDN,基础表单/表格首屏仍不提前加载该代码。`C_FilePreview` 加载时需要它,表格 XLSX 导出按动作加载;不将所有文件预览描述为动作级懒加载。来源与许可证见 [THIRD_PARTY_NOTICES](../THIRD_PARTY_NOTICES.md)。
25
26
  - ESM 使用 `.d.ts`,CJS 使用 `.d.cts`;条件类型入口与相应 JavaScript 格式对应。
26
27
  - 公共可达声明同时检查 ESM / CJS,不能引用 `naive-ui/es/*` 或 `naive-ui/lib/*` 内部路径。
27
28
 
@@ -0,0 +1,111 @@
1
+ # 兼容 API 迁移
2
+
3
+ 现有兼容入口继续工作,本轮不移除属性、事件或导出。新代码使用下表主 API;旧项目按页面逐步迁移,不需要增加业务类型包装或批量重写。
4
+
5
+ | 兼容写法 | 主 API | 迁移要点 |
6
+ | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | ---------------------------------------------------------------- |
7
+ | `C_Date` 的 `singleDate` / `singleDateTime` / `dateRange` / `dateTimeRange` / `smartRange` | `v-model` 与 `mode` | 同步迁移对应 `update:*` 监听;保持原日期格式和模式 |
8
+ | `C_FormSearch :form-params` | `v-model` 或 `:model-value` | 单向输入用 `:model-value`;需要父状态同步才用 `v-model` |
9
+ | `C_Menu :value` / `v-model:value` | `:model-value` / `v-model` | 路由决定的选中值继续单向传入;`@select` 导航逻辑保留 |
10
+ | 全局 `registerRenderer` / `unregisterRenderer` | 应用自己的 `createFormRendererRegistry()` | 安装时传 `formRenderers`,或子路径接入时 `provide` |
11
+ | `TableEditProps` / `TableExpandProps` / `TableSelectionProps` | `defineTableConfig<Row>()` 与 `config.edit` / `expand` / `selection` | 旧类型不代表组件当前 props;按现行配置字段迁移,不做类型断言强转 |
12
+
13
+ ## 日期与查询
14
+
15
+ 日期的模式和值保持对应关系,不要在一个组件上同时传新旧两份模型。`modelValue` 优先于兼容属性;重复监听新旧更新事件会让应用回调执行两次。
16
+
17
+ | 旧模型 | `mode` |
18
+ | ---------------- | --------------- |
19
+ | `singleDate` | `date`,可省略 |
20
+ | `singleDateTime` | `datetime` |
21
+ | `dateRange` | `daterange` |
22
+ | `dateTimeRange` | `datetimerange` |
23
+ | `smartRange` | `smart-range` |
24
+
25
+ ```vue
26
+ <script setup lang="ts">
27
+ import { ref } from 'vue'
28
+ import { C_Date } from '@robot-admin/naive-ui-components/C_Date'
29
+ import { C_FormSearch } from '@robot-admin/naive-ui-components/C_FormSearch'
30
+
31
+ const period = ref<[string, string] | null>(null)
32
+ const query = ref({ keyword: '' })
33
+ </script>
34
+
35
+ <template>
36
+ <C_Date
37
+ v-model="period"
38
+ mode="daterange"
39
+ />
40
+ <C_FormSearch
41
+ v-model="query"
42
+ :form-item-list="[{ type: 'input', prop: 'keyword' }]"
43
+ :config="{ onSearch: params => loadRows(params.keyword) }"
44
+ />
45
+ </template>
46
+ ```
47
+
48
+ `loadRows` 代表应用自己的请求函数。`params` 从初始模型推导,业务不需要手写索引签名。原来仅用于同步父值的 `@change-params` 可在使用 `v-model` 后移除;其中的业务副作用要按原语义保留。请求只由 `config.onSearch` 或 `@search` 中的一处发起。
49
+
50
+ `searchRef.formParams` 是仍受支持的实例读取能力,**不是**被弃用的 `formParams` 输入属性。`C_Time` 的 `defaultStartTime` 等初始值与变更事件也没有被本轮废弃。
51
+
52
+ ## 菜单
53
+
54
+ 受路由控制的菜单只替换输入属性,保持原来的导航归属:
55
+
56
+ ```vue
57
+ <C_Menu :model-value="route.name" :options="menus" @select="navigate" />
58
+ ```
59
+
60
+ 普通本地选择使用 `v-model="selected"`;显式监听则将 `@update:value` 改为 `@update:model-value`。不要为了改用 `v-model` 而给只读的路由计算值添加无意义 setter。
61
+
62
+ ## 应用级表单渲染器
63
+
64
+ 在每次创建应用时创建 registry。SSR、多应用或测试隔离场景不要在共享模块顶层创建同一份可变 registry,除非有意共享。
65
+
66
+ ```ts
67
+ import type { App } from 'vue'
68
+ import {
69
+ createFormRendererRegistry,
70
+ FORM_RENDERER_REGISTRY_KEY,
71
+ type FormRenderer,
72
+ } from '@robot-admin/naive-ui-components/C_Form'
73
+
74
+ export function setupFormRenderer(app: App, inputRenderer: FormRenderer) {
75
+ const registry = createFormRendererRegistry()
76
+ const unregister = registry.register('input', inputRenderer)
77
+ app.provide(FORM_RENDERER_REGISTRY_KEY, registry)
78
+ app.onUnmount(() => {
79
+ unregister()
80
+ })
81
+ return registry
82
+ }
83
+ ```
84
+
85
+ 全量插件接入则使用 `app.use(ComponentLib, { formRenderers: registry })`。旧的全局注册表不会自动复制到应用 registry。动态替换时优先调用 `register` 返回的注销函数:旧注册的注销函数不会误删后续新注册。只有一个表单需要定制时,继续使用组件的 `renderers` 属性即可。
86
+
87
+ ## 检查真实消费代码
88
+
89
+ 工具在**组件库源码仓库**运行,使用该仓库已安装的 TypeScript 与 Vue SFC 编译器,不加载目标项目的构建配置、不执行业务代码、不修改文件,也不新增运行时依赖。它不是已发布 npm 包的 CLI。
90
+
91
+ ```sh
92
+ # 在组件库根目录,先查看报告
93
+ bun scripts/check-legacy-usage.js /path/to/app/src --global-components
94
+
95
+ # CI:出现确定的旧入口时退出 1
96
+ bun scripts/check-legacy-usage.js /path/to/app/src --global-components --strict --json
97
+
98
+ # 只检查显式 import 的项目不加 --global-components
99
+ bun scripts/check-legacy-usage.js /path/to/app/src --strict
100
+
101
+ # 本仓库持续验证主 API 示例,旧兼容测试另行保留
102
+ bun scripts/check-legacy-usage.js tests/consumer/C_CurrentApi.vue --strict
103
+ ```
104
+
105
+ - `--global-components` 仅用于已配置组件库 resolver 或全量注册的项目,同时允许自动导入的 `h`。本地同名声明和其他来源的 import 优先,不按名字硬判。
106
+ - 检查 Vue 模板属性、旧模型/更新事件、静态 `v-bind` 对象、`h` / `createVNode`、JSX、直接旧导出/类型导入;支持包根与组件子入口的命名别名和 namespace。普通业务对象、注释、字符串、实例 `formParams` 不会被当成违规。
107
+ - 动态 props、对象展开/动态键、动态组件、动态 import/require、外部 SFC script 和非 HTML 模板列入 `unverified`。工具不做跨模块转导出追踪、变量别名传播或运行时数据流分析;包装组件、Options API 的注册别名、模板表达式里的函数调用需人工核对。
108
+ - 默认有旧入口时只报告;`--strict` 阻断确定的旧入口。`unverified` 不被伪装为已验证,也不会被自动改写;需要结合报告人工处理。解析错误、无有效源码或无效参数始终退出 2。
109
+ - 默认忽略声明文件、依赖、构建产物和目录中的符号链接。传入实际源码目录;不要把整个兼容回归测试集当成必须零旧入口的消费目录。
110
+
111
+ 迁移后运行应用自己的类型、构建和行为验证,检查清空值、路由选择、请求次数与渲染器隔离。静态零违规不能替代这些验证。
@@ -9,6 +9,7 @@
9
9
  | `C_Transfer` | 左右面板分别按筛选后项数,100 项起 | 完整数据筛选、全选、禁用项、移动顺序、v-model |
10
10
  | `C_Chat` | 消息 200 条起;联系人 100 条起 | 图片、文件、系统消息、重发、联系人事件;实际测量变高行 |
11
11
  | `C_GlobalSearch` | 搜索结果列表 | 完整匹配结果、上下键跨视口定位、Enter 选择、输入法与历史记录 |
12
+ | `C_WaterFall` | 100 项起 | 页面/嵌套滚动、变高测量、原始索引、键盘与 KeepAlive |
12
13
 
13
14
  ```vue
14
15
  <C_Transfer v-model="selectedKeys" :data="people" filterable />
@@ -16,7 +17,7 @@
16
17
  <C_GlobalSearch :options="searchOptions" />
17
18
  ```
18
19
 
19
- 窗口化复用 `vueuc` 的公开 `VVirtualList`,兼容本包声明的 Naive UI 2.35;不依赖 Naive 内部导入,也不提高 Naive peer 下限。只减少渲染的 DOM,数据仍完整保存在内存中,搜索仍检查完整索引。
20
+ 聊天、穿梭框和搜索复用 `vueuc` 的公开 `VVirtualList`,瀑布流使用自己的按列区间索引;均兼容本包声明的 Naive UI 2.35,不依赖 Naive 内部导入。只减少渲染的 DOM,数据仍完整保存在内存中,搜索仍检查完整索引。瀑布流接入、键盘操作与完整 DOM 逃生见[瀑布流指南](./waterfall.md)。
20
21
 
21
22
  穿梭框的三档行高和自定义方式见[穿梭框指南](./transfer.md)。聊天会实测文本、图片和文件行高度,无需调用方预先计算高度。业务 ID 应唯一、稳定;聊天容器应有确定高度,例如外层 `height: 600px`。
22
23
 
@@ -36,3 +37,17 @@
36
37
  - 二维码渲染及每次导出分别保存配置快照。新渲染取消旧 Logo 加载,导出相互独立;卸载取消所有任务并释放 Image 事件。组件销毁期间尚未完成的导出会以 `AbortError` 拒绝,调用方按普通异步错误处理即可。
37
38
 
38
39
  这些改进不代表列表、瀑布流和编辑器可以无限增加数据。大规模业务仍应按实际场景分段加载、回收历史,并测量内存、交互延迟与目标浏览器表现。
40
+
41
+ ## 大表单的脏检查
42
+
43
+ 响应式模型按字段缓存比较结果。修改一个字段后,其他未变字段不重复遍历嵌套内容;总脏状态和完整变更报告共享比较结果。动态字段清理对应缓存,重置/`markAsClean()` 更新干净快照。
44
+
45
+ Date、raw 或浅响应式路径没有完整失效信号,显式字段检查与变更报告继续实时比较。普通值的 Map/Set 保留线性查找;对象键或对象成员按结构匹配,最坏需要平方级候选查找,避免将复杂对象集合用于巨型表单热路径。
46
+
47
+ 完整模型同步、初始快照、提交快照仍有与数据量相关的成本。单个表单承载大量文档、文件或未编辑业务对象时,应按业务区域拆分模型;不能用脏检查优化推导整页渲染或深层监听已无成本。
48
+
49
+ ## 编辑器实例的释放
50
+
51
+ Markdown 卸载时通过 md-editor 的公开 `getEditorView().destroy()` 释放 CodeMirror 的观察器、测量帧与实例资源;已发起的保存和图片上传晚返回时不再写入卸载后的编辑器。富文本通过官方 `createEditor()` 同步持有实例,创建通知尚未发出也能在卸载时销毁,工具栏继续使用官方 Vue 适配器。
52
+
53
+ 这些清理由组件负责,使用侧无需额外获取 SDK 实例或增加卸载代码。宿主自己创建的 Blob URL 仍由宿主撤销;编辑器模块与样式首次加载后的浏览器缓存不属于组件实例清理范围。
@@ -0,0 +1,113 @@
1
+ # 瀑布流与长列表
2
+
3
+ `C_WaterFall` 同时负责瀑布流排布、图片懒加载、卡片测量和长列表窗口化。使用侧提供稳定的数据与加载状态即可,不需要计算可见范围或维护滚动监听。
4
+
5
+ ## 最小接入
6
+
7
+ ```vue
8
+ <script setup lang="ts">
9
+ import { ref } from 'vue'
10
+ import {
11
+ C_WaterFall,
12
+ type WaterFallItem,
13
+ } from '@robot-admin/naive-ui-components/C_WaterFall'
14
+ import '@robot-admin/naive-ui-components/C_WaterFall/style.css'
15
+
16
+ const photos = ref<WaterFallItem[]>([
17
+ {
18
+ id: 'photo-1',
19
+ src: '/photos/1.jpg',
20
+ width: 1200,
21
+ height: 800,
22
+ title: '城市风景',
23
+ },
24
+ {
25
+ id: 'photo-2',
26
+ src: '/photos/2.jpg',
27
+ width: 800,
28
+ height: 1200,
29
+ title: '山间小路',
30
+ },
31
+ ])
32
+
33
+ function openPhoto(item: WaterFallItem, index: number) {
34
+ console.log(item.id, index)
35
+ }
36
+ </script>
37
+
38
+ <template>
39
+ <C_WaterFall
40
+ :items="photos"
41
+ @item-click="openPhoto"
42
+ />
43
+ </template>
44
+ ```
45
+
46
+ - `id` 必须唯一、稳定;追加和排序时保留同一业务项的标识。
47
+ - `width`、`height` 描述图片的原始比例,用于图片未加载、卡片未挂载时估算布局。提供准确比例能减少图片加载后的位移。
48
+ - 默认按容器宽度选择列数;需要固定列数时设置 `:columns="4"`,间距通过 `gap` 调整。
49
+ - 列表不足 100 项时保留完整 DOM;达到 100 项后自动只挂载视口附近的卡片,并保留整列占位高度。
50
+
51
+ ## 页面滚动和局部滚动
52
+
53
+ 不需要传入滚动容器。组件自动监听窗口及上层实际裁剪容器,计算它们的交集;嵌套滚动、窗口滚动和容器尺寸变化都会更新可见范围。
54
+
55
+ ```vue
56
+ <template>
57
+ <div style="height: 560px; overflow-y: auto">
58
+ <C_WaterFall
59
+ :items="photos"
60
+ :columns="3"
61
+ />
62
+ </div>
63
+ </template>
64
+ ```
65
+
66
+ 暴露方法 `scrollToTop()` 将最近具有实际滚动范围的祖先滚动到本组件顶部;没有局部滚动容器时使用页面窗口。没有滚动范围的 `overflow: auto` 内容壳会被跳过;`overflow: clip/hidden` 参与视口裁剪,但不会被当作这个方法的滚动目标。组件卸载或进入 `KeepAlive` 缓存时会释放滚动监听、观察器和待执行帧,重新激活后按当前尺寸与位置恢复。
67
+
68
+ ## 自定义卡片与键盘
69
+
70
+ ```vue
71
+ <C_WaterFall :items="photos">
72
+ <template #item="{ item, index, width, height }">
73
+ <article>
74
+ <img :src="item.src" :alt="item.title" :width="width" :height="height" loading="lazy" />
75
+ <p>{{ index + 1 }}. {{ item.title }}</p>
76
+ </article>
77
+ </template>
78
+ </C_WaterFall>
79
+ ```
80
+
81
+ 卡片实际高度由 `ResizeObserver` 测量,标题换行、自定义内容变高会触发布局更新。同一帧内的图片和卡片测量会合并处理。容器宽度或图片地址变化后,组件不会继续沿用不适配的旧卡片高度。
82
+
83
+ 插槽的 `index` 与 `item-click` 的序号始终对应完整 `items` 数组,滚动裁剪不会将它重置为当前可见列表的序号。
84
+
85
+ 卡片支持 Enter/空格激活、方向键按数据顺序移动、Home/End 到首末项。窗口化时 Tab 会衔接尚未挂载的下一项,卡片内部按钮和输入框保留原生焦点顺序;正在聚焦的卡片不会因滚出视口而被卸载。
86
+
87
+ 窗口外的其他卡片会卸载。编辑草稿、勾选值等业务状态应放在父级数据中,以稳定 `id` 管理。确实依赖每张卡片长期保留内部 DOM 状态、浏览器全文查找或打印时,可以显式关闭窗口化:
88
+
89
+ ```vue
90
+ <C_WaterFall :items="photos" :virtual-scroll="false" />
91
+ ```
92
+
93
+ ## 分页加载
94
+
95
+ ```vue
96
+ <C_WaterFall
97
+ :items="photos"
98
+ infinite
99
+ :loading="loading"
100
+ :no-more="noMore"
101
+ @load-more="loadNextPage"
102
+ />
103
+ ```
104
+
105
+ `loadNextPage` 开始时将 `loading` 设为 `true`,成功后追加数据,最后恢复为 `false`。服务端确认没有后续数据时设置 `noMore`。组件不会替使用侧发请求或推断接口总数。
106
+
107
+ 首屏内容不足以填满视口时,组件可以连续补页;每次连续补页最多 5 次。达到上限仍未填满时会显示“继续加载”,避免空响应或错误分页持续请求;用户也可以滚出、重新进入加载区域继续触发。自定义 footer 插槽可使用 `status`、`paused` 和 `loadMore` 保留同一交互。
108
+
109
+ ## 性能边界
110
+
111
+ 滚动时使用按列索引和二分查找,不逐项扫描完整列表;DOM 数量随可见范围、预渲染缓冲与聚焦项变化,不随总数据量持续增长。布局、数据更新和测量后的重新排布仍需处理数据集,窗口化不会替代服务端分页,也不会降低业务数据本身的内存占用。
112
+
113
+ 回归用固定规模数据校验了 10,000 项下的 DOM 范围,以及 100,000 项下单次范围查询少于 150 次几何字段读取;这些是确定性的复杂度与 DOM 断言,并非对不同设备帧率的承诺。
@@ -2,6 +2,8 @@
2
2
 
3
3
  日期:2026-10-19。本轮接续[表格与组件复查](./component-review-20261019.md),并合并远端 `fdffe29` 中已提交的地图、组织图、预览、上传、甘特及瀑布流修复。功能变更通过 Changeset 登记,源码合入不等于发布新的 npm 版本。
4
4
 
5
+ 后续更新(2026-10-24,0.22.0):下文保留的是当时的验证记录。瀑布流窗口化已补齐,见[当前指南](./guides/waterfall.md);表单增加按字段比较缓存及结构集合快照修复。无锁消费者安装已去除本库的 SheetJS CDN 依赖,并验证最低/最新 peer 组合;普通业务与长期性能边界仍需按真实场景评估。
6
+
5
7
  ## 修改及可验证收益
6
8
 
7
9
  | 路径 | 实际改进 | 验证方式 |
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright (C) 2012-present SheetJS LLC
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.21.0",
6
+ "version": "0.22.0",
7
7
  "description": "基于 Naive UI 的 Vue 3 组件库",
8
8
  "packageManager": "bun@1.3.14",
9
9
  "engines": {
@@ -73,7 +73,9 @@
73
73
  "README.md",
74
74
  "README_EN.md",
75
75
  "CHANGELOG.md",
76
- "SECURITY.md"
76
+ "SECURITY.md",
77
+ "THIRD_PARTY_NOTICES.md",
78
+ "licenses"
77
79
  ],
78
80
  "keywords": [
79
81
  "vue",
@@ -111,7 +113,7 @@
111
113
  "check:quality": "node scripts/check-source-quality.js",
112
114
  "check:consumer-types": "vue-tsc --noEmit -p tests/consumer/tsconfig.json",
113
115
  "check:consumer-contracts": "node scripts/check-consumer-contracts.js",
114
- "verify": "bun run lint:check && bun run type-check && bun run type-check:vue && bun run test && bun run test:components && bun run type-check:components && bun run check:exports && bun run check:package && bun run check:quality && bun run build && bun run check:consumer-size && bun run check:consumer-types && bun run check:consumer-contracts",
116
+ "verify": "bun run lint:check && bun run type-check && bun run type-check:vue && bun run test && bun run test:components && bun run type-check:components && bun run check:exports && bun run check:vendor && bun run check:legacy && bun run check:package && bun run check:quality && bun run build && bun run check:consumer-size && bun run check:consumer-types && bun run check:consumer-contracts",
115
117
  "prepublishOnly": "bun run verify",
116
118
  "release": "changeset publish",
117
119
  "changeset": "changeset",
@@ -126,7 +128,9 @@
126
128
  "format": "prettier --write src/",
127
129
  "test:components": "vitest run --config vitest.config.ts",
128
130
  "type-check:components": "vue-tsc --noEmit -p tests/components/tsconfig.json",
129
- "check:audit:raw": "bun audit --json"
131
+ "check:audit:raw": "bun audit --json",
132
+ "check:vendor": "node scripts/check-vendored-dependencies.js",
133
+ "check:legacy": "bun scripts/check-legacy-usage.js tests/consumer/C_CurrentApi.vue --strict"
130
134
  },
131
135
  "peerDependencies": {
132
136
  "vue": "^3.5.3",
@@ -176,8 +180,7 @@
176
180
  "vue3-puzzle-vcode": "^1.1.7",
177
181
  "vueuc": "^0.4.66",
178
182
  "xgplayer": "3.0.26",
179
- "xgplayer-hls": "3.0.26",
180
- "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
183
+ "xgplayer-hls": "3.0.26"
181
184
  },
182
185
  "devDependencies": {
183
186
  "@changesets/changelog-github": "^0.7.0",
@@ -207,7 +210,7 @@
207
210
  "eslint-plugin-jsdoc": "^62.9.0",
208
211
  "eslint-plugin-oxlint": "^1.80.0",
209
212
  "eslint-plugin-vue": "^10.10.0",
210
- "happy-dom": "^20.14.5",
213
+ "happy-dom": "21.0.4",
211
214
  "husky": "^9.1.7",
212
215
  "lint-staged": "^16.4.0",
213
216
  "naive-ui": "^2.45.3",
@@ -225,12 +228,13 @@
225
228
  "vue": "^3.5.42",
226
229
  "vue-tsc": "^3.3.11",
227
230
  "vue-router": "^5.3.1",
228
- "sortablejs": "1.15.7"
231
+ "sortablejs": "1.15.7",
232
+ "xlsx": "file:vendor/xlsx-0.20.3.tgz"
229
233
  },
230
234
  "overrides": {
231
235
  "@xmldom/xmldom": "0.8.15",
232
236
  "defu": "6.1.7",
233
- "fast-uri": "3.1.8",
237
+ "fast-uri": "3.1.9",
234
238
  "flatted": "3.4.2",
235
239
  "lodash": "4.18.1",
236
240
  "lodash-es": "4.18.1",