@jc-times/business-ui 0.2.53 → 0.2.55

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.
@@ -1,28 +1,28 @@
1
- # PDF 与图片查看器
2
-
3
- 从独立子入口 `@jc-times/business-ui/document-viewer` 导入,主入口不加载查看器或 PDF.js。
4
- 图片直接传入 URL;PDF 传入已加载的 PDF.js 6.3.289 `PDFDocumentProxy`。
5
- PDF.js 是可选 peer,只看图片不需要运行 PDF 引擎。消费方负责 worker、字体资源、认证、密码和销毁 PDF;组件不发业务 API、不修改或保存原文件。
6
-
7
- 当前未发布候选已从 PDF.js 4.10.38 升级至 6.3.289。消费方升级本候选时必须同步升级 `pdfjs-dist`,并从同一安装包加载 worker(例如 `pdfjs-dist/build/pdf.worker.min.mjs?url`);不要混用旧 worker 或旧 `PDFDocumentProxy` 类型。已发布 0.2.31 仍使用 4.10.38。`document-viewer-v2` 的 EmbedPDF 引擎不受此变更影响。
8
-
9
- ```tsx
10
- import { DocumentViewer } from "@jc-times/business-ui/document-viewer";
11
- import "@jc-times/business-ui/styles.css";
12
-
13
- <DocumentViewer title="图纸" source={{ id: fileVersion, kind: "image",
14
- images: [{ src: imageUrl, alt: "设备正视图" }] }}/>
15
- <DocumentViewer title="文档" source={{ id: fileVersion, kind: "pdf", document: pdf }}/>
16
- ```
17
-
18
- 父容器须有确定高度。默认连续阅读、桌面展开侧栏、900px 以下折叠;缩略图每组最多12页,页码输入支持直接跳转,避免为长文档生成大量下拉选项。图片支持浏览器原生解码格式,如 JPG、PNG、WebP、GIF;HEIC/TIFF 是否可用取决于浏览器,失败会提示。
19
-
20
- 缩放、90°旋转、全屏(不支持原生 API 时使用全窗口模式)、翻页、缩略图及渲染预算统一维护。按 Escape 可退出全窗口模式。改变 `source.id` 重建查看会话,清除页码、缩放、旋转和错误;内容变化时必须更新 id。
21
-
22
- `currentPage/onCurrentPageChange` 可受控;`toolbar/footer` 提供业务信息和操作插槽。
23
- `renderPage({page, zoom, rotation})` 用于业务叠加层。精细组合可以使用同入口的 `DocumentViewerViewport`、`PdfThumbnailRail`、`PdfToolbar`、`usePdfViewport`、`usePdfCanvas`;所有路径复用同一实现。
24
- 印章、权限、水印、审核/签署及下载授权由消费方组合,公共库不理解业务角色。
25
-
26
- `usePdfCanvas` 按画布串行等待取消的渲染完成,卸载或文件切换后不提交旧结果,并返回页级错误。PDF.js 的解析任务生命周期仍属于传入文档的所有者。纯渲染预算从 `document-render-budget` 子入口获取,服务端使用不引入 React。
27
-
28
- 验证:真实混合横竖页 PDF 与图片的桌面/手机浏览器回归,导航、旋转、缩放、侧栏无横向溢出;单元测试覆盖旧渲染取消、卸载、加载错误与图片所有者重置。
1
+ # PDF 与图片查看器
2
+
3
+ 从独立子入口 `@jc-times/business-ui/document-viewer` 导入,主入口不加载查看器或 PDF.js。
4
+ 图片直接传入 URL;PDF 传入已加载的 PDF.js 6.3.289 `PDFDocumentProxy`。
5
+ PDF.js 是可选 peer,只看图片不需要运行 PDF 引擎。消费方负责 worker、字体资源、认证、密码和销毁 PDF;组件不发业务 API、不修改或保存原文件。
6
+
7
+ 当前未发布候选已从 PDF.js 4.10.38 升级至 6.3.289。消费方升级本候选时必须同步升级 `pdfjs-dist`,并从同一安装包加载 worker(例如 `pdfjs-dist/build/pdf.worker.min.mjs?url`);不要混用旧 worker 或旧 `PDFDocumentProxy` 类型。已发布 0.2.31 仍使用 4.10.38。`document-viewer-v2` 的 EmbedPDF 引擎不受此变更影响。
8
+
9
+ ```tsx
10
+ import { DocumentViewer } from "@jc-times/business-ui/document-viewer";
11
+ import "@jc-times/business-ui/styles.css";
12
+
13
+ <DocumentViewer title="图纸" source={{ id: fileVersion, kind: "image",
14
+ images: [{ src: imageUrl, alt: "设备正视图" }] }}/>
15
+ <DocumentViewer title="文档" source={{ id: fileVersion, kind: "pdf", document: pdf }}/>
16
+ ```
17
+
18
+ 父容器须有确定高度。默认连续阅读、桌面展开侧栏、900px 以下折叠;缩略图每组最多12页,页码输入支持直接跳转,避免为长文档生成大量下拉选项。图片支持浏览器原生解码格式,如 JPG、PNG、WebP、GIF;HEIC/TIFF 是否可用取决于浏览器,失败会提示。
19
+
20
+ 缩放、90°旋转、全屏(不支持原生 API 时使用全窗口模式)、翻页、缩略图及渲染预算统一维护。按 Escape 可退出全窗口模式。改变 `source.id` 重建查看会话,清除页码、缩放、旋转和错误;内容变化时必须更新 id。
21
+
22
+ `currentPage/onCurrentPageChange` 可受控;`toolbar/footer` 提供业务信息和操作插槽。
23
+ `renderPage({page, zoom, rotation})` 用于业务叠加层。精细组合可以使用同入口的 `DocumentViewerViewport`、`PdfThumbnailRail`、`PdfToolbar`、`usePdfViewport`、`usePdfCanvas`;所有路径复用同一实现。
24
+ 印章、权限、水印、审核/签署及下载授权由消费方组合,公共库不理解业务角色。
25
+
26
+ `usePdfCanvas` 按画布串行等待取消的渲染完成,卸载或文件切换后不提交旧结果,并返回页级错误。PDF.js 的解析任务生命周期仍属于传入文档的所有者。纯渲染预算从 `document-render-budget` 子入口获取,服务端使用不引入 React。
27
+
28
+ 验证:真实混合横竖页 PDF 与图片的桌面/手机浏览器回归,导航、旋转、缩放、侧栏无横向溢出;单元测试覆盖旧渲染取消、卸载、加载错误与图片所有者重置。
@@ -1,11 +1,11 @@
1
- # 上传前处理
2
-
3
- `PreparedFileDropzone` 在 `FileDropzone` 的类型、数量和大小校验后,逐个调用 `prepareFile(file, signal)`。
4
- 整批处理成功才调用一次 `onFilesSelected`;任一失败均不提交部分结果。处理后的文件再次校验类型和大小。
5
-
6
- - `ownerKey` 必填,包含合同/文档/版本等会改变上传目标的身份。切换身份、禁用或卸载时取消请求;适配器必须把 signal 传到 fetch/解析器。
7
- - `labels` 和 `errorMessage` 由业务适配器提供;公共 `FilePreparationDialog` 统一进度、错误、取消和焦点管理。
8
- - 非文件选择器入口(例如查看器拖放)复用 `useFilePreparation` 和 `FilePreparationDialog`。
9
- - 企业解密、格式识别、密码政策、权限、临时文件清理和服务端强制校验由服务端/应用适配器负责。UI 包不包含密钥,不存储密码,不声称支持任意加密软件。
10
- - 当前合同适配:服务端自动解密已支持的 WWall 版本,Word/Excel/PDF 打开密码提示用户先移除再上传。没有实现前端密码输入解密。
11
- - 未使用本组件的既有 `FileDropzone` 保持同步回调行为。业务提交失败由业务页面处理,不误报成解密失败。
1
+ # 上传前处理
2
+
3
+ `PreparedFileDropzone` 在 `FileDropzone` 的类型、数量和大小校验后,逐个调用 `prepareFile(file, signal)`。
4
+ 整批处理成功才调用一次 `onFilesSelected`;任一失败均不提交部分结果。处理后的文件再次校验类型和大小。
5
+
6
+ - `ownerKey` 必填,包含合同/文档/版本等会改变上传目标的身份。切换身份、禁用或卸载时取消请求;适配器必须把 signal 传到 fetch/解析器。
7
+ - `labels` 和 `errorMessage` 由业务适配器提供;公共 `FilePreparationDialog` 统一进度、错误、取消和焦点管理。
8
+ - 非文件选择器入口(例如查看器拖放)复用 `useFilePreparation` 和 `FilePreparationDialog`。
9
+ - 企业解密、格式识别、密码政策、权限、临时文件清理和服务端强制校验由服务端/应用适配器负责。UI 包不包含密钥,不存储密码,不声称支持任意加密软件。
10
+ - 当前合同适配:服务端自动解密已支持的 WWall 版本,Word/Excel/PDF 打开密码提示用户先移除再上传。没有实现前端密码输入解密。
11
+ - 未使用本组件的既有 `FileDropzone` 保持同步回调行为。业务提交失败由业务页面处理,不误报成解密失败。
@@ -1,62 +1,62 @@
1
- # 公共组件成熟度更新与迁移
2
-
3
- 本轮实现采用已有主题/API + 成熟交互内核:ModalShell 使用 Radix Dialog,DateInput 使用 Radix Popover + React Aria Calendar,Toast 使用 Radix Toast,MultiSelect 使用 React Aria 原生多选 ComboBox/TagGroup。业务接口、文案、字段映射仍由消费方提供。
4
-
5
- ## 浮层
6
-
7
- - ModalShell 的 header/content/footer 和 ref 保持原位置,正文不再执行自研 focus trap。背景由内核屏蔽;初始焦点、返回焦点、只关闭最上层继续受支持。
8
- - 公共下拉、搜索、菜单、日期、树、地址浮层默认进入最近 ModalShell 的 portal 容器,位于滚动正文之外。不要将它们显式 portal 到 modal 外部;第三方浮层需遵循相同边界。
9
- - Escape 先交给内部面板。日期选择/键盘关闭后回到日期输入,外部点击保留外部目标焦点。
10
- - `useModalFocusTrap` 保留给历史消费者;同一个 ModalShell 上再次调用会跳过已托管的焦点管理。新代码直接使用 ModalShell。
11
-
12
- ## 日期
13
-
14
- ```tsx
15
- <DateInput value={date} onValueChange={setDate}
16
- minDate="2026-01-01" maxDate="2026-12-31"
17
- isDateUnavailable={iso => holidays.has(iso)} />
18
- ```
19
-
20
- - `min/max` 的 ISO 字符串别名也生效;`minDate/maxDate` 优先。
21
- - 范围/不可选日检查覆盖手输、日历和“今天”。readOnly 同时禁用面板入口;required 时不允许清除。
22
- - 无效草稿保留并显示错误,不提交;修正后再提交。可用 `onValidationError` 获取错误。`value` 外部更新会重置草稿。
23
- - 年月跳转使用月份输入;Calendar 内核处理方向键、PageUp/Down,Home/End 现在移到月首/月末。
24
- - 日历 DOM 改为标准表格行/格子结构;消费方不要依赖旧 `.ui-date-grid` 或按钮 DOM,使用公共样式。
25
-
26
- ## 选择与目录
27
-
28
- ```tsx
29
- <MultiSelect label="参与人" items={options} values={ids} onValuesChange={setIds} name="members" />
30
- <TreeSelect selectionMode="multiple" items={departments} values={ids} onValuesChange={setIds} />
31
- ```
32
-
33
- - MultiSelect 的键盘、多选及标签删除由 React Aria 管理。面板可能保持打开以便连续选择,Escape/移出后可操作标签。`maxSelected` 限制数量;`selectedItems` 为当前候选集之外的已选 ID 提供名称。空数组表示清空。
34
- - TreeSelect 单选 API 不变;多选使用 values/defaultValues/onValuesChange,不与单选 value 混用。父子节点独立选择,不隐式级联,也不自动选择后端未加载子项。
35
- - TreeSelect 原生表单 `name` 现在提交 ID,多选按同名字段多值提交。若历史系统依赖标签,可暂设 `formValueMode="label"` 后迁移。required 检查已选值,而非搜索草稿;中文输入确认不会提交选项。
36
- - AsyncDirectoryPicker:外部 selectedItem 清空/改变会重置显示和待处理选择;`refreshKey` 变化清空缓存并取消旧请求,正在编辑的查询会重新执行防抖。`cacheTtlMs` 默认五分钟,0 绕过缓存;`cacheSize` 继续默认 50。查询缓存不再合并大小写不同的关键词。
37
-
38
- ## 表格
39
-
40
- ```tsx
41
- <DataTable rows={pageRows} columns={columns} getRowId={row => row.id}
42
- sortMode="server" sort={sort} onSortChange={setSort}
43
- selectedRowIds={selected} onSelectedRowIdsChange={setSelected}
44
- renderSelectionActions={ids => <Button onClick={() => exportRows(ids)}>导出</Button>} />
45
- ```
46
-
47
- - server 模式仅发出排序描述、显示方向,保持 rows 顺序;列通过 sortable=true 开启服务端排序,数据查询由页面负责。
48
- - 全选明确为本页可选行;保留其他页已有 ID,加载中不能全选。默认显示本页/总选中数,可设 selectionSummary=false 隐藏。
49
- - `hiddenColumnIds` 控制列显隐,配置菜单与持久化仍由应用负责。
50
-
51
- ## 通知与文件
52
-
53
- - Toast 的 maxVisible 是可见数量,超出进入 FIFO 队列,不再删除旧错误;等待项出现后才开始计时。相同 ID 更新保留队列位置并重新计时。鼠标悬停、焦点进入、窗口失焦暂停计时;danger 默认手动关闭。应用切换工作上下文时可调用 dismissAll 清队列。
54
- - FileDropzone 新增 maxFileSize(字节)、maxFiles(每次选择/拖入上限)和 onRejections,返回 `{file, reason: 'type'|'size'|'count'}`。旧 onFilesRejected 仍接受 File[],现在也包含数量超限文件。单文件模式拖入多份时不再静默忽略多余文件。
55
- - 文件类型/大小筛选仅改善客户端反馈;上传服务仍负责自身校验。进度/重试属于上传接口生命周期,本次未引入网络上传器。
56
-
57
- ## 验证与发布边界
58
-
59
- - 单元测试覆盖状态、数据、回调和重绘预算;数据测试隔离无布局 jsdom 中的 Popover 定位循环。
60
- - `pnpm test:browser` 使用真实 Chromium,覆盖桌面/手机视口的 Portal 焦点、Escape、日期限制、输入法、树和搜索多选、通知计时及边界截图。
61
- - CI 增加 React 18.3.1 / 19.2.8 和浏览器门禁。手机视口模拟不等于真实手机输入法/软键盘验收。
62
- - 发布包 CSS 标记为副作用,仍按 README 显式导入 styles.css。消费方需要安装新版本并验证自己的主题、表单和业务回调;本库完成不代表消费应用已升级或部署。
1
+ # 公共组件成熟度更新与迁移
2
+
3
+ 本轮实现采用已有主题/API + 成熟交互内核:ModalShell 使用 Radix Dialog,DateInput 使用 Radix Popover + React Aria Calendar,Toast 使用 Radix Toast,MultiSelect 使用 React Aria 原生多选 ComboBox/TagGroup。业务接口、文案、字段映射仍由消费方提供。
4
+
5
+ ## 浮层
6
+
7
+ - ModalShell 的 header/content/footer 和 ref 保持原位置,正文不再执行自研 focus trap。背景由内核屏蔽;初始焦点、返回焦点、只关闭最上层继续受支持。
8
+ - 公共下拉、搜索、菜单、日期、树、地址浮层默认进入最近 ModalShell 的 portal 容器,位于滚动正文之外。不要将它们显式 portal 到 modal 外部;第三方浮层需遵循相同边界。
9
+ - Escape 先交给内部面板。日期选择/键盘关闭后回到日期输入,外部点击保留外部目标焦点。
10
+ - `useModalFocusTrap` 保留给历史消费者;同一个 ModalShell 上再次调用会跳过已托管的焦点管理。新代码直接使用 ModalShell。
11
+
12
+ ## 日期
13
+
14
+ ```tsx
15
+ <DateInput value={date} onValueChange={setDate}
16
+ minDate="2026-01-01" maxDate="2026-12-31"
17
+ isDateUnavailable={iso => holidays.has(iso)} />
18
+ ```
19
+
20
+ - `min/max` 的 ISO 字符串别名也生效;`minDate/maxDate` 优先。
21
+ - 范围/不可选日检查覆盖手输、日历和“今天”。readOnly 同时禁用面板入口;required 时不允许清除。
22
+ - 无效草稿保留并显示错误,不提交;修正后再提交。可用 `onValidationError` 获取错误。`value` 外部更新会重置草稿。
23
+ - 年月跳转使用月份输入;Calendar 内核处理方向键、PageUp/Down,Home/End 现在移到月首/月末。
24
+ - 日历 DOM 改为标准表格行/格子结构;消费方不要依赖旧 `.ui-date-grid` 或按钮 DOM,使用公共样式。
25
+
26
+ ## 选择与目录
27
+
28
+ ```tsx
29
+ <MultiSelect label="参与人" items={options} values={ids} onValuesChange={setIds} name="members" />
30
+ <TreeSelect selectionMode="multiple" items={departments} values={ids} onValuesChange={setIds} />
31
+ ```
32
+
33
+ - MultiSelect 的键盘、多选及标签删除由 React Aria 管理。面板可能保持打开以便连续选择,Escape/移出后可操作标签。`maxSelected` 限制数量;`selectedItems` 为当前候选集之外的已选 ID 提供名称。空数组表示清空。
34
+ - TreeSelect 单选 API 不变;多选使用 values/defaultValues/onValuesChange,不与单选 value 混用。父子节点独立选择,不隐式级联,也不自动选择后端未加载子项。
35
+ - TreeSelect 原生表单 `name` 现在提交 ID,多选按同名字段多值提交。若历史系统依赖标签,可暂设 `formValueMode="label"` 后迁移。required 检查已选值,而非搜索草稿;中文输入确认不会提交选项。
36
+ - AsyncDirectoryPicker:外部 selectedItem 清空/改变会重置显示和待处理选择;`refreshKey` 变化清空缓存并取消旧请求,正在编辑的查询会重新执行防抖。`cacheTtlMs` 默认五分钟,0 绕过缓存;`cacheSize` 继续默认 50。查询缓存不再合并大小写不同的关键词。
37
+
38
+ ## 表格
39
+
40
+ ```tsx
41
+ <DataTable rows={pageRows} columns={columns} getRowId={row => row.id}
42
+ sortMode="server" sort={sort} onSortChange={setSort}
43
+ selectedRowIds={selected} onSelectedRowIdsChange={setSelected}
44
+ renderSelectionActions={ids => <Button onClick={() => exportRows(ids)}>导出</Button>} />
45
+ ```
46
+
47
+ - server 模式仅发出排序描述、显示方向,保持 rows 顺序;列通过 sortable=true 开启服务端排序,数据查询由页面负责。
48
+ - 全选明确为本页可选行;保留其他页已有 ID,加载中不能全选。默认显示本页/总选中数,可设 selectionSummary=false 隐藏。
49
+ - `hiddenColumnIds` 控制列显隐,配置菜单与持久化仍由应用负责。
50
+
51
+ ## 通知与文件
52
+
53
+ - Toast 的 maxVisible 是可见数量,超出进入 FIFO 队列,不再删除旧错误;等待项出现后才开始计时。相同 ID 更新保留队列位置并重新计时。鼠标悬停、焦点进入、窗口失焦暂停计时;danger 默认手动关闭。应用切换工作上下文时可调用 dismissAll 清队列。
54
+ - FileDropzone 新增 maxFileSize(字节)、maxFiles(每次选择/拖入上限)和 onRejections,返回 `{file, reason: 'type'|'size'|'count'}`。旧 onFilesRejected 仍接受 File[],现在也包含数量超限文件。单文件模式拖入多份时不再静默忽略多余文件。
55
+ - 文件类型/大小筛选仅改善客户端反馈;上传服务仍负责自身校验。进度/重试属于上传接口生命周期,本次未引入网络上传器。
56
+
57
+ ## 验证与发布边界
58
+
59
+ - 单元测试覆盖状态、数据、回调和重绘预算;数据测试隔离无布局 jsdom 中的 Popover 定位循环。
60
+ - `pnpm test:browser` 使用真实 Chromium,覆盖桌面/手机视口的 Portal 焦点、Escape、日期限制、输入法、树和搜索多选、通知计时及边界截图。
61
+ - CI 增加 React 18.3.1 / 19.2.8 和浏览器门禁。手机视口模拟不等于真实手机输入法/软键盘验收。
62
+ - 发布包 CSS 标记为副作用,仍按 README 显式导入 styles.css。消费方需要安装新版本并验证自己的主题、表单和业务回调;本库完成不代表消费应用已升级或部署。