@jc-times/business-ui 0.2.43
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.
- package/AGENTS.md +6 -0
- package/CHANGELOG.md +267 -0
- package/README.md +55 -0
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/bin/business-ui-gate.mjs +171 -0
- package/dist/Alert.js +47 -0
- package/dist/AsyncDirectoryPicker.js +134 -0
- package/dist/AsyncSearchPicker.js +155 -0
- package/dist/AutoComplete.js +34 -0
- package/dist/Badge.js +14 -0
- package/dist/Button.js +54 -0
- package/dist/Cascader.js +141 -0
- package/dist/Combobox.js +106 -0
- package/dist/ConfirmDialog.js +48 -0
- package/dist/DataTableHorizontalScrollbar.js +38 -0
- package/dist/DataTableIcons.js +37 -0
- package/dist/DataTableMergedRows.js +45 -0
- package/dist/DataTableTheme.js +135 -0
- package/dist/DateInput.js +223 -0
- package/dist/DropdownMenu.js +130 -0
- package/dist/EmptyState.js +27 -0
- package/dist/ExplainableButton.js +68 -0
- package/dist/FileDropzone.js +70 -0
- package/dist/FilePreparationDialog.js +33 -0
- package/dist/FloatingControls.js +120 -0
- package/dist/FormField.js +143 -0
- package/dist/MetricCard.js +38 -0
- package/dist/ModalShell.js +139 -0
- package/dist/MultiSelect.js +137 -0
- package/dist/NumericInput.js +97 -0
- package/dist/OverlayContainer.js +9 -0
- package/dist/PageHeader.js +36 -0
- package/dist/Pagination.js +115 -0
- package/dist/PreparedFileDropzone.js +30 -0
- package/dist/RecoverableAsyncState.js +35 -0
- package/dist/RovingTabs.js +54 -0
- package/dist/SectionCard.js +35 -0
- package/dist/SegmentedControl.js +46 -0
- package/dist/Select.js +73 -0
- package/dist/Skeleton.js +25 -0
- package/dist/SortableList.js +55 -0
- package/dist/StructuredAddressInput.js +157 -0
- package/dist/Toast.js +100 -0
- package/dist/ToggleSwitch.js +34 -0
- package/dist/TreeSelect.js +444 -0
- package/dist/amount-format.js +20 -0
- package/dist/business-ui.js +44 -0
- package/dist/chinese-address-regions.js +15 -0
- package/dist/classNames.js +6 -0
- package/dist/data-table.js +257 -0
- package/dist/document-render-budget.js +22 -0
- package/dist/document-viewer/ContinuousPdfViewer.js +145 -0
- package/dist/document-viewer/DocumentViewer.js +123 -0
- package/dist/document-viewer/DocumentViewerViewport.js +36 -0
- package/dist/document-viewer/ImagePage.js +39 -0
- package/dist/document-viewer/PdfCanvasPage.js +26 -0
- package/dist/document-viewer/PdfThumbnailRail.js +116 -0
- package/dist/document-viewer/PdfToolbar.js +61 -0
- package/dist/document-viewer/PdfWorkspace.js +42 -0
- package/dist/document-viewer/pdf-render-budget.js +7 -0
- package/dist/document-viewer/usePdfCanvas.js +69 -0
- package/dist/document-viewer/usePdfViewport.js +48 -0
- package/dist/document-viewer-v2/DocumentViewerV2.js +171 -0
- package/dist/document-viewer-v2/HeadlessPdfViewer.js +420 -0
- package/dist/document-viewer-v2/HeadlessSearch.js +66 -0
- package/dist/document-viewer-v2.js +13 -0
- package/dist/document-viewer.js +12 -0
- package/dist/pdfium-viewer.js +18 -0
- package/dist/styles.css +2 -0
- package/dist/types/Alert.d.ts +11 -0
- package/dist/types/AmountFormat.d.ts +15 -0
- package/dist/types/AsyncDirectoryPicker.d.ts +32 -0
- package/dist/types/AsyncSearchPicker.d.ts +26 -0
- package/dist/types/AutoComplete.d.ts +9 -0
- package/dist/types/Badge.d.ts +13 -0
- package/dist/types/Button.d.ts +36 -0
- package/dist/types/Cascader.d.ts +57 -0
- package/dist/types/ChineseAddressRegions.d.ts +4 -0
- package/dist/types/Combobox.d.ts +37 -0
- package/dist/types/ConfirmDialog.d.ts +20 -0
- package/dist/types/DataTable.d.ts +68 -0
- package/dist/types/DataTableHorizontalScrollbar.d.ts +8 -0
- package/dist/types/DataTableIcons.d.ts +19 -0
- package/dist/types/DataTableMergedRows.d.ts +11 -0
- package/dist/types/DataTableTheme.d.ts +4 -0
- package/dist/types/DateInput.d.ts +25 -0
- package/dist/types/DocumentRenderBudget.d.ts +9 -0
- package/dist/types/DocumentViewer.d.ts +11 -0
- package/dist/types/DocumentViewerV2.d.ts +10 -0
- package/dist/types/DropdownMenu.d.ts +73 -0
- package/dist/types/EmptyState.d.ts +9 -0
- package/dist/types/ExplainableButton.d.ts +7 -0
- package/dist/types/FileDropzone.d.ts +20 -0
- package/dist/types/FilePreparationDialog.d.ts +12 -0
- package/dist/types/FloatingControls.d.ts +39 -0
- package/dist/types/FormField.d.ts +35 -0
- package/dist/types/MetricCard.d.ts +17 -0
- package/dist/types/ModalShell.d.ts +33 -0
- package/dist/types/MultiSelect.d.ts +12 -0
- package/dist/types/NumericInput.d.ts +54 -0
- package/dist/types/OverlayContainer.d.ts +2 -0
- package/dist/types/PageHeader.d.ts +23 -0
- package/dist/types/Pagination.d.ts +14 -0
- package/dist/types/PdfiumViewer.d.ts +5 -0
- package/dist/types/PreparedFileDropzone.d.ts +7 -0
- package/dist/types/RecoverableAsyncState.d.ts +11 -0
- package/dist/types/RovingTabs.d.ts +21 -0
- package/dist/types/SectionCard.d.ts +18 -0
- package/dist/types/SegmentedControl.d.ts +26 -0
- package/dist/types/Select.d.ts +31 -0
- package/dist/types/Skeleton.d.ts +11 -0
- package/dist/types/SortableList.d.ts +17 -0
- package/dist/types/StructuredAddressInput.d.ts +57 -0
- package/dist/types/Toast.d.ts +22 -0
- package/dist/types/ToggleSwitch.d.ts +15 -0
- package/dist/types/TreeSelect.d.ts +58 -0
- package/dist/types/classNames.d.ts +1 -0
- package/dist/types/document-viewer/ContinuousPdfViewer.d.ts +16 -0
- package/dist/types/document-viewer/DocumentViewer.d.ts +31 -0
- package/dist/types/document-viewer/DocumentViewerViewport.d.ts +23 -0
- package/dist/types/document-viewer/ImagePage.d.ts +9 -0
- package/dist/types/document-viewer/PdfCanvasPage.d.ts +7 -0
- package/dist/types/document-viewer/PdfThumbnailRail.d.ts +12 -0
- package/dist/types/document-viewer/PdfToolbar.d.ts +13 -0
- package/dist/types/document-viewer/PdfWorkspace.d.ts +5 -0
- package/dist/types/document-viewer/pdf-render-budget.d.ts +2 -0
- package/dist/types/document-viewer/usePdfCanvas.d.ts +22 -0
- package/dist/types/document-viewer/usePdfViewport.d.ts +14 -0
- package/dist/types/document-viewer-v2/DocumentViewerV2.d.ts +50 -0
- package/dist/types/document-viewer-v2/HeadlessPdfViewer.d.ts +39 -0
- package/dist/types/document-viewer-v2/HeadlessSearch.d.ts +9 -0
- package/dist/types/index.d.ts +41 -0
- package/dist/types/useDebouncedValue.d.ts +2 -0
- package/dist/types/useFilePreparation.d.ts +28 -0
- package/dist/types/useModalFocusTrap.d.ts +3 -0
- package/dist/useDebouncedValue.js +16 -0
- package/dist/useFilePreparation.js +51 -0
- package/dist/useModalFocusTrap.js +71 -0
- package/docs/agent-guide.md +145 -0
- package/docs/api.md +220 -0
- package/docs/cascader.md +56 -0
- package/docs/component-strategy.md +94 -0
- package/docs/data-table.md +123 -0
- package/docs/dependencies.md +57 -0
- package/docs/document-viewer-v2.md +259 -0
- package/docs/document-viewer.md +28 -0
- package/docs/file-preparation.md +11 -0
- package/docs/maturity-migration.md +62 -0
- package/docs/modal-shell-migration.md +43 -0
- package/docs/mrt-poc.md +205 -0
- package/docs/release.md +32 -0
- package/docs/viewport-qa.md +99 -0
- package/licenses/rc-cascader-MIT.txt +21 -0
- package/package.json +163 -0
package/docs/api.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# 公共 API
|
|
2
|
+
|
|
3
|
+
先按 [Agent 使用指南](agent-guide.md) 选型;本文集中说明公共行为和示例。完整参数及导出以实际安装版本的类型声明为准。
|
|
4
|
+
|
|
5
|
+
## 性能与目录缓存契约
|
|
6
|
+
|
|
7
|
+
- AsyncDirectoryPicker 新增 `cacheSize`:每个 owner 默认缓存 50 个查询,命中提升最近使用顺序,满容量淘汰最久未用项;0 禁用缓存,ownerKey 改变仍清空。`cacheTtlMs` 默认五分钟,0 绕过缓存;`refreshKey` 变化清空缓存并取消旧请求。
|
|
8
|
+
- TextInput 在 value 更新时保持外部 ref 挂接;替换 ref 和卸载仍正常解绑。
|
|
9
|
+
- AsyncSearchPicker 与 TreeSelect 隔离行内容重绘;保留当前全量 DOM 和树默认展开行为。消费方保持 items、回调和树数据引用稳定可避免无关更新。
|
|
10
|
+
- StructuredAddressInput 按 regions 引用复用路径、搜索文本和顺序索引。更新数据时提供新的 regions 引用;搜索排名、limit 和公开辅助函数行为保持兼容。
|
|
11
|
+
|
|
12
|
+
## 信息与布局
|
|
13
|
+
|
|
14
|
+
- `Badge`:原生 `span` 展示组件,`tone` 为 `neutral | info | success | warning | danger`,`size` 为 `small | medium`;透传 span 属性并 forward ref。组件只呈现调用方给出的内容,不包含订单、任务或 ERP 状态映射,也不隐式增加 live-region 语义。在 flex/截断容器内 Badge 保持自身尺寸并按文字基线对齐,长文本的截断策略仍由外层内容容器决定。
|
|
15
|
+
- `MetricCard`:用 `label`、`value`、可选 `description`、装饰性 `icon` 与五档 `tone` 呈现单项指标;根节点是由可见 label 命名的 `article`,透传 article 属性并 forward ref。数值格式化、趋势计算、单位和业务文案均由调用方完成。
|
|
16
|
+
- `PageHeader`:用 `eyebrow`、必填 `title`、可选 `description` 和 `actions` 组成页面标题区,固定输出页面级 `h1`;`titleId` 可用于页内关联。根节点是原生 `header`,支持原生属性与 ref,窄屏时操作区自动换行。`copyProps` 与 `actionsProps` 为既有 `.ui-page-header-copy` / `.ui-page-header-actions` 槽透传原生 div 属性,便于消费方挂接稳定的 class、data 与可访问属性;不传 `actions` 时不输出空操作区。
|
|
17
|
+
- `SectionCard`:必填 `title` 和 `children`,可选 `description`、`actions`、`headingId` 与 `headingLevel`(2–6)。根节点是由可见标题自动命名的 `section`,因此不仅是样式包装;消费方应按页面大纲选择标题层级。显式 `aria-label` / `aria-labelledby` 会覆盖自动区域名称。
|
|
18
|
+
|
|
19
|
+
四个组件使用同一 `className` 合并顺序(组件类在前、消费方类在后),不创建状态、Effect、订阅或布局测量,也不引入额外运行时依赖。大量指标的聚合、虚拟化和数据刷新属于消费方职责。
|
|
20
|
+
|
|
21
|
+
## 弹窗与确认
|
|
22
|
+
|
|
23
|
+
`ModalShell`(别名 `Dialog`)通过条件挂载控制显示,没有 `open` 属性;必须提供 `titleId`、`title`、`closeLabel`、`onClose` 和正文。它内建焦点陷阱、背景滚动锁、栈顶 Escape 处理和关闭后的焦点归还。`initialFocus` 与 `returnFocus` 接受元素或 React ref;`returnFocus={false}` 可显式关闭归还。`closeOnEscape`、`closeOnBackdrop` 和 `closeDisabled` 分别控制关闭策略。`rootRef` 保持兼容,消费方通常不再需要额外调用 `useModalFocusTrap`。
|
|
24
|
+
|
|
25
|
+
面板稳定输出 `.ui-modal-header`、`.ui-modal-content` 和可选的 `.ui-modal-footer` 直接子节点。`children` 只属于独立滚动的正文区;固定操作区使用 `footer` / `footerClassName`。`contentClassName` 与 `contentProps` 用于定制正文区,其中 `contentProps` 接受 ref、data、ARIA、事件及其他原生 div 属性。手机端弹窗全屏并适配安全区;短横屏压缩头部留白,正文保持独立滚动。迁移规则见 [`modal-shell-migration.md`](modal-shell-migration.md)。
|
|
26
|
+
|
|
27
|
+
`ConfirmDialog` 用于不依附锚点的确认流程。它是受控弹窗,支持普通/危险确认、`busy`、安全的默认取消焦点、Escape 与焦点归还。`Popconfirm` 只用于依附触发器的轻量确认。
|
|
28
|
+
|
|
29
|
+
## 表单与选择
|
|
30
|
+
|
|
31
|
+
- `Button`:执行提交、打开、确认等动作;当 `iconOnly` 为 `true` 时,TypeScript 强制要求 `aria-label`。
|
|
32
|
+
- `LinkButton`:导航或下载使用的真实 `<a>`,必须提供 `href`,支持 `download`、按钮视觉变体和禁用语义;图标链接同样必须提供 `aria-label`。禁用时移除 `href`、退出 Tab 顺序并阻止点击向父级冒泡,同时保留禁用链接的可访问语义。
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<LinkButton href="/api/contracts/42/file" download="合同-42.pdf">下载合同(PDF)</LinkButton>
|
|
36
|
+
<LinkButton href={preparedBlobUrl} download="处理后的合同.pdf" iconOnly aria-label="下载处理后的合同">↓</LinkButton>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
原生 `download` 只保证同源 URL、`blob:` 与 `data:` URL 的下载提示;跨域响应可能直接导航,并受服务端 `Content-Disposition` 影响。需要自定义鉴权请求头、异步生成或客户端转换时,由业务层完成请求与错误处理,成功后向 `LinkButton` 提供同源签名地址或 Blob URL,并在不再使用时释放 Blob URL。下载或新窗口行为应写入可见文案或可访问名称,不能只靠装饰图标表达。
|
|
40
|
+
|
|
41
|
+
- `TextInput`:`startAdornment` / `endAdornment` 接受 ReactNode,用于搜索图标、清除按钮、金额单位和百分号。未提供装饰时保持原有 input-only DOM;提供装饰时 ref、className 和原生属性仍落在 input,外框统一呈现 focus/invalid/disabled 状态。点击非交互装饰会聚焦输入框;交互装饰需自行提供可访问名称,并随输入框同步禁用。
|
|
42
|
+
- `Select`:`triggerRef` 暴露触发按钮;`triggerProps` 透传触发器的 ARIA、data 与事件属性;`portalContainer` 和 `placement` 控制安全的浮层挂载与方向。原生 `SelectInput` 在触屏使用 44px 最小点击高度;自定义 `Select` 在 600px 以下以安全区底部抽屉呈现,并限制候选区高度、内部滚动与滚动链。
|
|
43
|
+
- `Combobox` / `AutoComplete`:`inputRef`、`inputProps` 透传输入框 ARIA、data、`inputMode`、`autoComplete` 与原生事件;`placement` 与 `portalContainer` 控制浮层。
|
|
44
|
+
- `ToggleSwitch`:除受控 `checked/onChange` 外接受原生 checkbox 属性并 forward ref,可使用 `id`、`name`、`value`、`required`、`form`、ARIA 与 data 属性参与原生表单。
|
|
45
|
+
- `DateInput`:forward ref(也可用 `inputRef`)并保留非冲突原生输入属性;既有 `className` 继续作用于组合控件外层,输入框类名使用 `inputClassName`。日历支持方向键、Home/End(移到月首/月末)、PageUp/PageDown;详细日期限制与键盘行为见 [成熟度迁移](maturity-migration.md)。
|
|
46
|
+
- `TreeSelect`:接收业务无关的扁平 `items`(`id`、`label`、可选 `parentId/order/disabled`),内部构造任意层级树并处理孤儿、重复 ID、自环和环状父子关系。支持受控/非受控 value、open、query、expandedIds,搜索时保留完整祖先路径;输入框使用 combobox + tree 语义并实现方向键、Home/End、左右展开收起、Enter 和 Escape。组件只提交既有节点 ID,不接受自由文本值。
|
|
47
|
+
- `StructuredAddressInput`:接收 `AddressRegion[]`,默认只显示地区级联与详细地址,海外使用顶级“海外”选项。旧调用可显式设 `showModeSelector={true}` 恢复模式切换,切换器复用公共 Select。`@jc-times/business-ui/chinese-address-regions` 独立导出固定版本的中国省市区、顶级“海外”、数据版本和海外 ID,使消费方可在地址页面按需加载;业务地址字符串的解析与拼接仍由消费方负责。
|
|
48
|
+
- `FileDropzone`:唯一的公共文件选择表面,整块区域可点击、键盘 Enter/Space 打开,也可直接拖入;支持 `accept`、单/多选、禁用、输入 ref、重复选择清空以及拒绝文件回调。组件只提交 `File[]`,支持 `maxFileSize`(字节)、`maxFiles`(单批数量)和 `onRejections`(type/size/count);上传请求、服务端校验和业务错误由消费方处理;children 中不要嵌套按钮或其他交互控件。
|
|
49
|
+
|
|
50
|
+
TextInput(含装饰组合外框)、原生 SelectInput 与默认 Button 的桌面高度均显式为 `--ui-control-height`(默认 40px)且采用 border-box;触屏环境的最小操作高度为 `--ui-touch-height`(默认 44px)。
|
|
51
|
+
|
|
52
|
+
## 异步搜索与菜单
|
|
53
|
+
|
|
54
|
+
`AsyncSearchPicker<T>` 不发请求也不保存业务 DTO。调用方受控提供 `query`、`items`、`status`、`onSearch` 和 `onSelect`,并通过 `getKey/getText/renderItem` 映射数据。组件统一处理最少字符提示、loading/error/empty、显式查询按钮、上下键、Enter、Escape、busy 与 disabled;候选区会响应 `visualViewport` 的软键盘高度变化并保持键盘选中项可见。取消请求和数据生命周期仍由调用方负责。
|
|
55
|
+
|
|
56
|
+
`DropdownMenu`(别名 `Menu`)提供真正的 menu 语义和 React Aria 键盘行为,支持禁用、危险项、分组、分隔与子菜单,并在关闭后归还焦点。普通操作项输出 `menuitem`;传 `selectionMode="single" | "multiple"` 后,`selectedKeys` / `defaultSelectedKeys` 与 `onSelectionChange` 分别驱动 `menuitemradio` / `menuitemcheckbox` 和 `aria-checked`。类型层禁止在未开启选择模式时传 selected keys。
|
|
57
|
+
|
|
58
|
+
每个操作项或子菜单可传 `current`(例如 `"page"`)输出 `aria-current`;`startIcon`、`endSlot`、`selectedIcon` 分别承载装饰图标、只读尾部状态与选中图标,不能在槽内放交互控件。`triggerRef` / `triggerProps`、`menuRef` / `menuProps` 与每项的 `itemRef` / `itemProps` 提供 ref、ARIA、data 和 React Aria 事件透传。`menuLabel` 可在菜单名称与触发器名称不同时提供独立的可访问名称。
|
|
59
|
+
|
|
60
|
+
触屏设备上菜单项最小高度为 `--ui-touch-height`,窄屏和短横屏中菜单限制在视口内并内部滚动。`Popover` 只承载补充信息或小型表单,不应代替操作菜单。
|
|
61
|
+
|
|
62
|
+
## 数据表移动端契约
|
|
63
|
+
|
|
64
|
+
从0.2.31起,`DataTable` 通过MRT渲染,保留旧参数及移动布局;新增 `options` 配置形式、`useDataTable` / `DataTableView`、`DataTableTheme` 和 `DataTableMergedRows`,见 [DataTable迁移](data-table.md)。独立 `data-table` 入口不能从旧安装版本导入。
|
|
65
|
+
|
|
66
|
+
合同业务展示、搜索记忆与列设置组合见 [MRT样例](mrt-poc.md)。`productDisplay` 属于合同包装参数,不是公共DataTable旧参数。
|
|
67
|
+
|
|
68
|
+
`DataTable` 默认 `mobileLayout="scroll"`,保持 0.2.4 及更早版本的横向滚动行为。真实调用需要标签化卡片行时可显式传 `mobileLayout="cards"`;在 600px 及以下,表头保持对辅助技术可用但视觉隐藏,单元格通过 `mobileLabel` 或字符串表头生成的 `data-label` 呈现标签。复杂表头应显式提供 `mobileLabel`。卡片布局允许长文本换行,并为选择列、尾部操作列和空状态提供独立布局。`rootRef` / `rootProps` 与 `tableRef` / `tableProps` 可用于稳定挂接原生属性,不需要依赖结构位置选择器。
|
|
69
|
+
|
|
70
|
+
长页面或宽表格可显式传 `stickyHorizontalScrollbar`,让底部横向滚动条在内容溢出时吸附于可视区域并与原生表格滚动同步;通过 `horizontalScrollbarLabel` 提供当前业务表格的可访问名称。该能力默认关闭,也适用于完整 `options` 入口和 `DataTableView`。
|
|
71
|
+
|
|
72
|
+
`Pagination` 在 360px 及以下自动只保留上一页、当前页摘要和下一页,调用方仍可用 `compact` 在更宽视口显式简化。`ToastProvider` 的连续通知栈限制在动态视口与底部安全区内,超出时内部滚动;长文案和操作按钮会在窄屏换行。
|
|
73
|
+
|
|
74
|
+
## 状态工具
|
|
75
|
+
|
|
76
|
+
`useDebouncedValue<T>(value, delay)` 返回输入值的延迟稳定副本。初始值立即返回;值或延迟变化会重启计时器;卸载会清理待执行计时器;非有限值和非正延迟按 `0` 处理。它不延迟输入框自身的 `onChange`,也不负责发请求、取消请求或处理响应竞态。
|
|
77
|
+
|
|
78
|
+
## TextInput 输入装饰(0.2.13)
|
|
79
|
+
|
|
80
|
+
`TextInput` 的 `startAdornment` / `endAdornment` 可承载搜索图标、清除按钮、货币符号、单位和百分号;`NumericInput` 与 `ScaledNumericInput` 自动继承同一 API。
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<TextInput label="搜索" value={query} onChange={event => setQuery(event.currentTarget.value)}
|
|
84
|
+
startAdornment={<Search aria-hidden="true" />}
|
|
85
|
+
endAdornment={query ? <Button size="compact" iconOnly aria-label="清除搜索"
|
|
86
|
+
onClick={() => setQuery("")}><X /></Button> : undefined} />
|
|
87
|
+
<NumericInput label="税率" value={rate} onValueCommit={setRate}
|
|
88
|
+
endAdornment={<span aria-hidden="true">%</span>} />
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
- 不传装饰时继续直接输出原生 input,保持既有 DOM 与样式;传入装饰后由组合外框统一呈现边框、焦点和错误状态,`ref`、`className` 与原生输入属性仍作用于 input。
|
|
92
|
+
- 点击非交互装饰会聚焦输入框。装饰中的按钮、链接和表单控件保留自身交互;图标或单位等重复信息应使用 `aria-hidden="true"`,图标按钮必须提供可访问名称。
|
|
93
|
+
- 禁用输入时,消费方应同时禁用装饰中的交互控件。组合控件保持默认 40px 高度,粗指针触屏最小高度为 44px;不要为单位或清除按钮设置另一套控件高度。
|
|
94
|
+
|
|
95
|
+
## NumericInput / ScaledNumericInput(0.2.8)
|
|
96
|
+
|
|
97
|
+
选择两层 API:`NumericInput` 用字符串保留十进制精度;`ScaledNumericInput` 用安全整数保存最小单位。两者均为受控组件,通过 `onValueCommit` 在失焦或回车时更新状态;输入中间态留在组件,必要时使用 `onDraftChange` 观察。不要用 draft 执行金额计算。
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<NumericInput label="数量" value={quantity} onValueCommit={setQuantity}
|
|
101
|
+
decimalPlaces={3} min="0" required />
|
|
102
|
+
<ScaledNumericInput label="单价" value={minorUnits} onValueCommit={setMinorUnits}
|
|
103
|
+
scale={100} min={0} selectAllOnFocus selectAllOnClick />
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- `NumericInput`: `value: string`、`onValueCommit(string)` 必填;`decimalPlaces=2`(0–100);`min/max` 为可在该精度表示的十进制字符串。允许负数,需非负时设 `min="0"`。
|
|
107
|
+
- `ScaledNumericInput`: `value: number | null`、`onValueCommit(number | null)` 必填;`scale=100`,仅接受安全整数范围内的正十次幂;精度由 scale 推导。`min/max` 与 value 均为存储单位的安全整数,默认上下界为 ±Number.MAX_SAFE_INTEGER。若需超出安全整数范围,用 NumericInput 字符串 API。
|
|
108
|
+
- 接受空值、正负号、小数点、尾随小数点、前导零和粘贴千分位。编辑时不截断超出精度的小数;提交采用十进制四舍五入(负数中点远离零),再限幅,去除前导/尾随零。空值或孤立符号提交为空字符串/`null`,不自动转换为零。
|
|
109
|
+
- `useGrouping=true` 仅在非编辑态展示千分位;小数点固定为 `.`,分组为 `,`,不提供 locale 解析。`selectAllOnFocus=false` 与 `selectAllOnClick=false` 分别配置全选行为。默认 `inputMode="decimal"`。
|
|
110
|
+
- 透传 TextInput 的 label、required、helpText、error、disabled、readOnly、ARIA、className、containerClassName、ref 和原生输入事件/属性(组件管理 type/value/defaultValue/min/max)。原生 `onChange` 观察输入事件,不能替代 `onValueCommit`。Enter 在组合输入结束后触发失焦提交并阻止表单默认提交,消费者可在 onKeyDown 中 preventDefault 取消。只读和禁用不提交。
|
|
111
|
+
- 编辑期间外部 value 更新不覆盖当前草稿;结束编辑后外部 value 始终为显示真值,消费者须在 commit 回调更新 value。原生 FormData 的值是当前显示文本(可能含分组),提交业务数据请使用受控状态。
|
|
112
|
+
- 样式完全复用 `.ui-input`/`.ui-form-field` 与 `--ui-*` 语义令牌,无新增应用主题。非十次幂换算、业务校验、货币符号及中文大写转换由消费方负责。
|
|
113
|
+
|
|
114
|
+
合同迁移:将本地 GroupedDecimalInput 的数量包装改为 NumericInput(decimalPlaces=3、min="0");将 ScaledDecimalInput 的含税单价/税率包装改为 ScaledNumericInput(scale=100、min=0,税率 max=10000)。把原提交回调映射到 onValueCommit;若业务将空值视为零,在应用包装中显式使用 `next ?? 0`。侧栏继续保存/显示阿拉伯数字,Word 写入时的中文金融大写转换保留在业务写入器。
|
|
115
|
+
|
|
116
|
+
消费项目选择支持所需能力的已发布精确版本并提交锁文件;有 npm 锁文件的项目也需按自身规则同步。替换完成后移除本地原生 input 实现、缩减 bareInput 门禁基线,并完成数量、金额、税率及 Word 写入的桌面/手机回归。本次公共库变更不等于消费方已完成迁移。
|
|
117
|
+
|
|
118
|
+
数字输入的成熟组件参考及尺寸约束见 [设计策略](component-strategy.md):与 TextInput/SelectInput 共用默认 40px、触屏最小 44px 的尺寸令牌,以及宽度、内边距、字体和圆角;消费方调整密度时须统一调整同行控件。
|
|
119
|
+
|
|
120
|
+
## 金额显示与格式化
|
|
121
|
+
|
|
122
|
+
`NumericInput` / `ScaledNumericInput` 接受 `moneyFormat={{ symbol: "¥", unit: "元", display: "symbol" }}`。display 默认为 symbol,unit 使用后缀,number 不显示货币文字。金额默认两位小数(受 decimalPlaces 限制);编辑草稿和提交值仍为数值。`minimumFractionDigits` 只影响非编辑态的最少小数位,不改变空值和提交精度。
|
|
123
|
+
|
|
124
|
+
服务端文档使用 `@jc-times/business-ui/amount-format` 的 `formatScaledMoney(3750000, { symbol: "¥", unit: "元" })` 得到 `¥37,500.00`。该子入口不引入 React,以安全整数最小单位保持精确金额,不负责汇率换算。
|
|
125
|
+
|
|
126
|
+
## 分段选择与拖动排序
|
|
127
|
+
|
|
128
|
+
- `SegmentedControl`:少量互斥选项,使用原生 radio 语义;见[分段控制器参数与示例](#分段控制器-segmentedcontrol)。
|
|
129
|
+
- `SortableList<T>`:items、getKey、getTextValue、renderItem、onReorder 和 aria-label 必填;支持 disabled、className、dragLabel。getKey 必须稳定且唯一,onReorder 返回新顺序,消费方更新受控 items 并持久化。使用 React Aria 的鼠标、触屏及键盘排序交互。
|
|
130
|
+
|
|
131
|
+
## 专题契约
|
|
132
|
+
|
|
133
|
+
- [成熟度迁移](maturity-migration.md):日期约束、MultiSelect、TreeSelect 多选、目录 TTL/刷新、服务端表格排序/选择/列显隐及通知队列。
|
|
134
|
+
- [弹窗插槽迁移](modal-shell-migration.md):固定 footer、正文滚动、ref 与样式迁移。
|
|
135
|
+
- [上传前处理](file-preparation.md):PreparedFileDropzone、useFilePreparation 与 FilePreparationDialog。
|
|
136
|
+
- [文档查看器](document-viewer.md):PDF.js/图片入口及资源生命周期。
|
|
137
|
+
- [文档与图片查看器 V2](document-viewer-v2.md):URL/Buffer 使用 PDFium;未发布候选增加 `renderer="headless"` 原生 React 叠层、受控页码与单页模式,并兼容图片、已有 PDF.js 对象、全部 V1 参数及组合导出,使用前核验安装版本。
|
|
138
|
+
|
|
139
|
+
## 分段控制器 SegmentedControl
|
|
140
|
+
|
|
141
|
+
适用于日/周/月、列表/卡片、字段状态等少量互斥选项。实际内容面板页签继续使用 RovingTabList/RovingTabPanel。
|
|
142
|
+
|
|
143
|
+
- 受控字符串泛型:`value`、`onChange(value)`、`options`(唯一 value、ReactNode label、可选 icon/disabled/aria-label)。不提供隐式默认选择;选项变化后由调用方维护有效 value。
|
|
144
|
+
- 必须提供组的 `aria-label`;只显示图标时将 label 设为 null,并提供选项的 `aria-label`。label 可组合文字、计数或说明,不放按钮、链接等交互元素。
|
|
145
|
+
- `variant="solid" | "soft"`:默认 solid 保留原实色样式;soft 使用浅底和浮起的选中项。
|
|
146
|
+
- `block` 默认 true,撑满容器并等宽;false 按内容收缩,仍受父容器宽度限制。`orientation="horizontal" | "vertical"` 默认 horizontal;`shape="default" | "round"` 默认 default。
|
|
147
|
+
- `size="compact" | "default" | "touch"`,默认 default;沿用 32/40/44px 尺寸体系,soft 另含轨道内边距,粗指针下每项点击高度至少 44px。
|
|
148
|
+
- 可传 name、disabled、className。未传 name 时每组生成独立名称;传 name 时参与原生 FormData,同一表单内不同组不要共用 name。
|
|
149
|
+
- 原生方向键切换并跳过禁用项,Space 选中;整组 disabled 不可操作。长标签窄屏省略但保留完整可访问名称。
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { useState } from "react";
|
|
153
|
+
import { LayoutGrid, List } from "lucide-react";
|
|
154
|
+
import { SegmentedControl } from "@jc-times/business-ui";
|
|
155
|
+
import "@jc-times/business-ui/styles.css";
|
|
156
|
+
|
|
157
|
+
type View = "list" | "grid";
|
|
158
|
+
|
|
159
|
+
export function ViewSelector() {
|
|
160
|
+
const [view, setView] = useState<View>("list");
|
|
161
|
+
return <SegmentedControl<View> aria-label="显示方式" variant="soft" block={false}
|
|
162
|
+
value={view} onChange={setView}
|
|
163
|
+
options={[
|
|
164
|
+
{ value: "list", label: "列表", icon: <List/> },
|
|
165
|
+
{ value: "grid", label: "卡片", icon: <LayoutGrid/> },
|
|
166
|
+
]}/>;
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
新增外观参数为本地待发布能力;旧版仅有受控字符串、禁用、name 和 size,消费前核对安装包声明。
|
|
171
|
+
|
|
172
|
+
### 外观与组合
|
|
173
|
+
|
|
174
|
+
| 需求 | 配置 | 行为 |
|
|
175
|
+
| --- | --- | --- |
|
|
176
|
+
| 保持原有字段单选外观 | 不传新增参数 | solid、block=true、horizontal、default 形状 |
|
|
177
|
+
| 工具栏中的浅底视图切换 | variant="soft"、block={false} | 按内容收缩,选中项使用 surface 背景 |
|
|
178
|
+
| 整行等宽 | block 或省略 block | 横向选项等分可用宽度 |
|
|
179
|
+
| 胶囊 | shape="round" | 轨道与选项使用圆角形状 |
|
|
180
|
+
| 纵向 | orientation="vertical" | 每项独占一行,组内选项同宽 |
|
|
181
|
+
| 仅显示图标 | option.label=null、icon、option["aria-label"] | 图标不参与读屏命名,由选项 aria-label 提供名称 |
|
|
182
|
+
| 自定义文字与计数 | option.label 为 ReactNode | 消费方组合非交互内容;长文字可能截断 |
|
|
183
|
+
| 单项禁用 / 整组禁用 | option.disabled / disabled | 原生 radio 禁用,键盘跳过禁用项 |
|
|
184
|
+
|
|
185
|
+
以下示例放在持有 `view` / `setView` 的 React 组件中:
|
|
186
|
+
|
|
187
|
+
```tsx
|
|
188
|
+
<SegmentedControl<View> aria-label="显示方式" variant="soft" shape="round" block={false}
|
|
189
|
+
value={view} onChange={setView}
|
|
190
|
+
options={[
|
|
191
|
+
{ value: "list", label: null, icon: <List/>, "aria-label": "列表" },
|
|
192
|
+
{ value: "grid", label: null, icon: <LayoutGrid/>, "aria-label": "卡片" },
|
|
193
|
+
]}/>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 状态、表单与兼容边界
|
|
197
|
+
|
|
198
|
+
- 只支持字符串 value 和对象数组 options;没有 `defaultValue`、数字值、字符串数组简写或非受控模式。参数名称和默认值以本包为准,不直接套用其他组件库的 Segmented API。
|
|
199
|
+
- `onChange` 在用户选择新项时通知,调用方必须更新 value。空 options 或 value 不在选项中时不会自动选中首项,也不会自动触发回调。
|
|
200
|
+
- 选择视图模式仍是 radio 语义;需要 tab/tabpanel 关联及页签焦点模型时,使用 `RovingTabList` + `RovingTabPanel`。
|
|
201
|
+
- 原生 FormData 只包含提供 name 且已选中、未禁用的 radio;业务状态提交仍可直接读取 value。表单 reset 不会替调用方重置受控状态。
|
|
202
|
+
- 组 aria-label 与选项名称分别提供;纯图标选项的 aria-label 不产生可见提示。若文字被截断会影响辨认,优先减少选项或改用纵向布局/Select。
|
|
203
|
+
- className 作用于组容器;颜色通过 `--ui-*` 主题令牌统一配置。当前未提供 ref、任意原生属性透传、选项 tooltip 或选中滑块动画。
|
|
204
|
+
|
|
205
|
+
维护时在视觉矩阵「表单控件 → 视图切换」查看组合效果;完整变体验证页为 `e2e/segmented.html`,验收要求见[多视口验收](viewport-qa.md)。
|
|
206
|
+
|
|
207
|
+
## Cascader 通用级联选择
|
|
208
|
+
|
|
209
|
+
RC Cascader 内核,支持单多选、路径搜索、独立/联动勾选及按需加载。完整公共约定、部门 ID 适配与地址迁移见 [级联选择](cascader.md)。
|
|
210
|
+
|
|
211
|
+
### Headless PDF 0.2.33
|
|
212
|
+
|
|
213
|
+
features.search/textSelection/pinchZoom 均默认开启。zoom/rotation 可受控,onZoomChange/onRotationChange 回传视口变化;showToolbar=false 可使用外部工具栏。pageRotation(page) 提供逐页额外角度,focusTarget={page,y,token} 定位归一化纵向位置。交互叠层标记 data-pdf-business-control,源身份变化时更新 source.id。
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
### PDFium 专用构建入口(0.2.34)
|
|
217
|
+
|
|
218
|
+
只使用原生 PDF 叠层的页面可从 `@jc-times/business-ui/pdfium-viewer` 导入 `PdfiumViewer`,参数与 Headless 模式一致,但省略 `renderer`。该入口不引入 PDF.js 兼容渲染或完整查看器外壳,适用于独立公开查看页面;引擎仍按需加载。通过 `engineOptions.wasmUrl` 提供本地资源的绝对 URL,保证 Blob worker 可解析;同一 `source.kind/id` 维持会话,文件版本改变时必须改变 `id`。
|
|
219
|
+
|
|
220
|
+
PDFium 专用入口支持 `initialZoom="fit-width"`(0.2.37):无受控 zoom 时由官方插件适配页面宽度;旧默认 100% 保持不变。
|
package/docs/cascader.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 通用级联选择
|
|
2
|
+
|
|
3
|
+
当前本地新增能力;消费方必须先核对安装版本导出,不能将本地源码视为已发布。
|
|
4
|
+
|
|
5
|
+
`Cascader` 使用固定 `@rc-component/cascader@1.25.0` 内核,外观使用 `--ui-*` 令牌。桌面多列浮层,600px 以下底部面板,列过多时面板内部横向滚动;手机软键盘仍需真实设备验收。浮层归属最近 ModalShell,Escape 先关闭选择面板。
|
|
6
|
+
|
|
7
|
+
## 单选与多选
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Cascader } from "@jc-times/business-ui";
|
|
11
|
+
|
|
12
|
+
<Cascader label="所在地区" options={options} value={path} onValueChange={setPath} />
|
|
13
|
+
<Cascader label="部门" options={options} multiple value={paths} onValueChange={setPaths} />
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- `options`:`{ value: string; label: string; children?: CascaderOption[]; disabled?: boolean; isLeaf?: boolean }[]`。同一层 value 唯一;使用 ID 索引适配器时要求全局唯一。
|
|
17
|
+
- 单选 `value: string[]`,多选 `value: string[][]`;`onValueChange` 第二参数为对应节点路径或路径数组。清空统一为 `[]`。
|
|
18
|
+
- 单选默认只提交叶子;`changeOnSelect` 允许选择中间层。
|
|
19
|
+
- 多选默认 `checkStrictly=true`,父子独立勾选;设为 false 启用父子联动。点击父级文字展开,点击复选框选中。
|
|
20
|
+
- `searchable` 默认开启;路径搜索忽略空格和 `/`,最多显示 50 项。不是远程搜索,也不宣称大列表虚拟化。
|
|
21
|
+
- `loadData(path)` 用于按需加载,调用方更新 options 并处理网络错误与取消;提供 loadData 时默认关闭搜索。若显式启用搜索,只能查找已经加载的节点。
|
|
22
|
+
- 点击标签或通过 Tab 聚焦不会自动展开;点击选择框、输入搜索词或按方向键可展开。
|
|
23
|
+
- `open/onOpenChange` 控制浮层;`disabled`、`required`、`label/helpText/error`、`placeholder/emptyText`、`allowClear/clearLabel`、多选 `maxTagCount`(默认 3)用于常规表单。
|
|
24
|
+
- `inputRef/inputProps` 指向真实搜索 input,可传 ARIA、data 属性及原生事件。搜索 input 的值是搜索词,已选路径以可见文本回填;提交使用 onValueChange,不能读取 input.value 或原生 FormData 作为已选路径。
|
|
25
|
+
|
|
26
|
+
## 部门 ID 适配
|
|
27
|
+
|
|
28
|
+
业务接口仍接收部门 ID,路径转换放在消费方。options 和索引应按数据引用 useMemo,避免每次输入重新建树。
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
const options = useMemo(() => buildCascaderOptions(departments), [departments]);
|
|
32
|
+
const pathsById = useMemo(() => indexCascaderPaths(options), [options]);
|
|
33
|
+
// departments: { id, label, parentId?, disabled? }[]
|
|
34
|
+
// 单选可选择任意层级,清空后回调 null。
|
|
35
|
+
<Cascader label="部门" options={options} changeOnSelect
|
|
36
|
+
value={departmentId ? pathsById.get(departmentId) ?? [] : []}
|
|
37
|
+
onValueChange={path => setDepartmentId(path.at(-1) ?? null)} />
|
|
38
|
+
|
|
39
|
+
<Cascader label="参与部门" options={options} multiple
|
|
40
|
+
value={departmentIds.flatMap(id => { const path = pathsById.get(id); return path ? [path] : []; })}
|
|
41
|
+
onValueChange={paths => setDepartmentIds(paths.map(path => path[path.length - 1]))} />
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`buildCascaderOptions` 保持输入顺序,父节点未提供时作为根节点,拒绝重复/空 ID 与循环;`indexCascaderPaths` 要求全局唯一 value。调用方应补齐已选但不在当前候选集中的部门并提供其祖先,避免标签丢失。
|
|
45
|
+
|
|
46
|
+
## 地址与旧树形选择
|
|
47
|
+
|
|
48
|
+
StructuredAddressInput 内部已复用 Cascader,保留 regions、StructuredAddressValue、regionInputRef/Props、详细地址和自由地址接口。点中间地区仍立即提交路径,点叶子后聚焦详细地址;支持清除地区。原先 region input 中显示的摘要改为选择框的可见文本,自动化定位应使用标签与可见文本,保存继续使用 value.regionIds。
|
|
49
|
+
|
|
50
|
+
TreeSelect 保持原有树形体验和 API,不会自动改变已安装消费项目的部门控件;需要多列级联的消费点按上面的适配方式迁移。
|
|
51
|
+
|
|
52
|
+
## 可运行案例
|
|
53
|
+
|
|
54
|
+
运行 `pnpm dev:cascader`,打开 http://127.0.0.1:4187/examples/cascader-demo/ 。源码位于 examples/cascader-demo/main.tsx。案例使用模拟部门与内置全国地区数据,展示任意层级单选、独立/联动多选、结构化/自由地址、弹窗选择、实时摘要与提交快照;不发送接口请求。
|
|
55
|
+
|
|
56
|
+
默认不展示地址类型,国内选省市区,海外选顶级“海外”并在详细地址填写国家/城市/街道。旧数据的 freeform 模式如需保留编辑,可显式 showModeSelector=true(复用公共 Select);默认模式交互统一提交 mode=structured,历史 freeform 数据由消费方迁移到海外路径与 detail。
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# 公共组件参考与采用策略
|
|
2
|
+
|
|
3
|
+
整理日期:2026-09-11
|
|
4
|
+
|
|
5
|
+
组件使用从 [Agent 指南](agent-guide.md) 开始,参数与示例见 [API](api.md)。本文保留设计依据与历史采用记录;当前内核已包含 Radix Dialog/Toast、React Aria Calendar/MultiSelect/SortableList,具体行为见 [成熟度迁移](maturity-migration.md)。下方参考表为早期选型依据,不表示这些内核尚未集成。
|
|
6
|
+
|
|
7
|
+
## 结论
|
|
8
|
+
|
|
9
|
+
公共包采用“自己的语义主题与稳定 API + 按需引入无样式交互内核”的路线。参考成熟项目的行为和设计原则,但不复制源码,也不把完整视觉组件库叠加进来。
|
|
10
|
+
|
|
11
|
+
| 参考项目 | 借鉴或使用内容 | 当前策略 |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| [Ant Design](https://ant.design/components/overview/) | 企业后台的信息层级、即时反馈、短而克制的动效、Alert / Empty / Skeleton 等组件分层 | 作为设计基准,不新增 `antd` 依赖,避免主题、包体和 DOM 结构被绑定 |
|
|
14
|
+
| [Radix Primitives](https://www.radix-ui.com/primitives/docs/overview/accessibility) | Dialog、Popover、Tooltip、Dropdown、Select 的焦点管理、键盘行为与组合式 API | MIT;出现第二个复杂使用场景时按单包引入,并由本包封装稳定 API |
|
|
15
|
+
| [Floating UI](https://floating-ui.com/docs/react) | 浮层的翻转、偏移、碰撞规避、滚动和 resize 跟随 | MIT;日期、Tooltip、Popover 需要处理嵌套滚动容器时优先采用 `@floating-ui/react-dom` |
|
|
16
|
+
| [React Aria](https://react-aria.adobe.com/getting-started) | Calendar、ComboBox、ListBox 等高复杂度控件的无障碍行为与国际化 | Apache-2.0;仅在复杂日期/搜索选择器进入公共包时评估,避免与 Radix 重复引入 |
|
|
17
|
+
|
|
18
|
+
## 2026-09-04 P0 信息与布局组件核验
|
|
19
|
+
|
|
20
|
+
- [Radix Themes Badge](https://www.radix-ui.com/themes/docs/components/badge) 以 `span` 为基础并提供尺寸与色彩变体;本包保留同样轻量的原生语义,但只暴露项目已有语义令牌能稳定表达的 tone,不引入可点击、删除或业务状态行为。
|
|
21
|
+
- [Ant Design Statistic](https://ant.design/components/statistic/) 将标题、数值、前后缀和说明分开;MetricCard 采用稳定的 label/value/description/icon 插槽,但刻意不复制格式化、精度、倒计时等业务或高频更新逻辑。
|
|
22
|
+
- [PatternFly Card](https://www.patternfly.org/components/card/) 与 [Page Header](https://www.patternfly.org/component-groups/content-containers/page-header/) 都把标题、说明、正文和 actions 作为明确结构;SectionCard 与 PageHeader 采用相同信息层级,并在窄屏允许标题和操作区自然换行。
|
|
23
|
+
- [W3C 页面标题与区域指南](https://www.w3.org/WAI/tutorials/page-structure/headings/) 建议标题反映内容层级,并用可见标题关联页面区域;因此 PageHeader 输出 `h1`,SectionCard 提供 2–6 级标题并自动用 `aria-labelledby` 命名 section。
|
|
24
|
+
- [React `useMemo` 指南](https://react.dev/reference/react/useMemo) 只建议为已识别的昂贵计算添加缓存。四个组件只有常量级字符串合并和元素组合,所以不增加手工 memo;通过无内部状态、无 Effect、无测量、纯 CSS 响应式和零新增依赖保持低开销。
|
|
25
|
+
|
|
26
|
+
## 2026-09-11 分段控制器
|
|
27
|
+
|
|
28
|
+
在既有 `SegmentedControl` 上扩展浅底选中、图标、收缩宽度、纵向和胶囊外观,保留默认实色整行行为。沿用原生 radio 的分组、键盘与表单语义,使用本库主题令牌,不新增交互依赖。
|
|
29
|
+
|
|
30
|
+
少量互斥字段、时间粒度或视图模式选择使用分段控制器;开关使用 ToggleSwitch,多项选择使用 Checkbox/MultiSelect,内容页签使用 RovingTabList/RovingTabPanel。选项、业务状态、权限和数据刷新由消费方提供。
|
|
31
|
+
|
|
32
|
+
本次扩展不承诺与其他组件库 API 兼容,也不提供滑块动效、非受控状态或数字值。完整参数、默认值及接入示例统一维护在 [API](api.md#分段控制器-segmentedcontrol),消费时核对实际安装版本。
|
|
33
|
+
|
|
34
|
+
## 动效规范
|
|
35
|
+
|
|
36
|
+
- 动效只解释状态变化、空间层级或操作反馈,不作为装饰。
|
|
37
|
+
- 快速反馈使用 `--ui-motion-fast`(120ms),普通浮层使用 `--ui-motion-normal`(180ms),强层级弹窗使用 `--ui-motion-slow`(240ms)。
|
|
38
|
+
- 进入使用后缓动,退出使用前缓动;优先只动画 `opacity` 和 `transform`。
|
|
39
|
+
- 所有动画必须在 `prefers-reduced-motion: reduce` 下停用。
|
|
40
|
+
- 业务项目可以覆盖时长令牌,但不应自行给同类组件建立另一套缓动曲线。
|
|
41
|
+
|
|
42
|
+
## 公共组件优先级
|
|
43
|
+
|
|
44
|
+
已纳入基础层:Badge、MetricCard、PageHeader、SectionCard、Button、Alert、EmptyState、Skeleton、Dialog、ConfirmDialog、FormField、DateInput、Pagination、RovingTabList/RovingTabPanel、ToggleSwitch、SegmentedControl、AsyncState、Tooltip、Popover、Popconfirm、Select、Combobox、AutoComplete、AsyncSearchPicker、DropdownMenu、Toast 和 DataTable。
|
|
45
|
+
|
|
46
|
+
本轮已集成:
|
|
47
|
+
|
|
48
|
+
1. Tooltip / Popover / Popconfirm:统一浮层定位、碰撞规避、延时、Escape 与焦点行为。
|
|
49
|
+
2. Select / Combobox / AutoComplete:统一键盘导航与移动端触控;Combobox/AutoComplete 支持异步受控输入和大列表虚拟化,AutoComplete 额外允许自由文本。
|
|
50
|
+
3. Toast:统一队列、停留时长、读屏播报;危险错误默认不自动消失。
|
|
51
|
+
4. DataTable:当前候选采用MRT内核,保留旧列/排序/选择契约并提供独立入口和高级配置;通用行合并在库内,查询、服务端分页与业务字段继续留在消费项目。见 [DataTable迁移](data-table.md)。
|
|
52
|
+
5. AsyncSearchPicker:只负责查询输入、显式触发、状态与候选交互;网络请求、取消和 DTO 映射由消费方持有。
|
|
53
|
+
6. DropdownMenu:操作集合必须使用 menu/menuitem 语义和标准键盘模型;Popover 不得冒充菜单。
|
|
54
|
+
7. ConfirmDialog:用于非锚点、强层级确认;锚点附近的轻量确认继续使用 Popconfirm。
|
|
55
|
+
8. TreeSelect:以 WAI-ARIA combobox + tree 交互为基准,支持业务方提供任意层级节点;不内置部门 DTO、权限状态或远程请求。
|
|
56
|
+
9. StructuredAddressInput:抽象结构化路径、路径搜索、详细地址和自由地址回退;行政区划数据、版本更新、字符串解析与领域字段定位仍属于消费方。
|
|
57
|
+
|
|
58
|
+
服务端排序、批量操作插槽与列显隐已提供,详见成熟度迁移。Notification 历史中心等后续能力仍须由真实场景驱动。
|
|
59
|
+
|
|
60
|
+
## 不进入公共包
|
|
61
|
+
|
|
62
|
+
- Ant Design ProTable、ProForm 一类“组件即页面”的高层封装。
|
|
63
|
+
- 合同审批、客户状态、ERP 字段等业务语义。
|
|
64
|
+
- 为单项目存在的视觉特效或布局外壳。
|
|
65
|
+
- 为同一交互重复引入多套 headless primitive,造成焦点与 Portal 规则冲突;现有混合内核由公共包统一封装。
|
|
66
|
+
|
|
67
|
+
## 消费项目门禁
|
|
68
|
+
|
|
69
|
+
`business-ui-gate` 除基础按钮/输入和手写 dialog 外,也把原生 `role="menu"/"menuitem"` 计为 `handwrittenMenu`,把原生 `role="combobox"/"listbox"/"option"` 计为 `handwrittenCombobox`。消费项目应使用 DropdownMenu、Select、Combobox/AutoComplete 或 AsyncSearchPicker;确有历史实现时只能通过审核后的 baseline 暂存,不应关闭对应门禁。
|
|
70
|
+
|
|
71
|
+
门禁还会把从 `@jc-times/business-ui` 导入的 ModalShell/Dialog 中“未提供 `footer` 属性却直接放置原生 `<footer>` child”的调用计为 `legacyModalFooter`。命名别名与 namespace 导入均受支持;普通业务组件中的 footer 不计数。迁移时把固定操作区移到 `footer`,样式改用 `footerClassName`,不要扩大 baseline 掩盖新调用。
|
|
72
|
+
|
|
73
|
+
## 引入开源依赖门槛
|
|
74
|
+
|
|
75
|
+
必须同时满足:许可证允许内部商业使用;仍在维护;支持 React 18/19;可 tree-shake;SSR 安全;有键盘和读屏行为;能通过语义令牌完全接管视觉;锁定精确版本并记录升级验证。许可证文件随最终制品保留,新增依赖需在变更记录中说明。
|
|
76
|
+
|
|
77
|
+
## 2026-09-06 数字输入参考与统一尺寸契约
|
|
78
|
+
|
|
79
|
+
- 对照 [Ant Design InputNumber](https://ant.design/components/input-number/) 的 stringMode 高精度字符串、formatter/parser 展示与值分离、changeOnBlur 和 focus cursor=all;本包用 NumericInput 字符串、内部草稿、onValueCommit 与明确全选配置承接这些设计原则。
|
|
80
|
+
- 对照 [Base UI Number Field](https://base-ui.com/react/components/number-field) 的 onValueChange/onValueCommitted 分层、空值与可访问名称;本包区分草稿观察和规范化提交,沿用 FormField 标签与错误关联。当前没有增减按钮、箭头步进或拖动调值,不宣称具备完整 spinbutton 行为。
|
|
81
|
+
- 成熟组件库作为行为/API 的评估依据;数字输入的视觉尺寸必须与本包同档控件一致。NumericInput 和 ScaledNumericInput 继续复用 TextInput,不设置独立高度、宽度、字体、padding 或圆角。
|
|
82
|
+
- 默认输入高度共用 --ui-control-height(40px),粗指针触屏最小高度共用 --ui-touch-height(44px);TextInput、SelectInput 与数字输入均为 border-box、width:100%、水平 padding 11px、font:inherit、--ui-radius 圆角。标签/帮助/错误继续使用 FormField 的间距与排版;比较高度时以输入框本体为准,提示文本可自然增加字段总高度。
|
|
83
|
+
- 消费方如需调整密度,统一修改公共尺寸令牌并回归同行控件;不能只对数字输入添加局部高度、字体或内边距。原生 size 属性表示字符宽度,不作为本包 small/medium/large 的视觉规格。
|
|
84
|
+
- 验证沿用 control-size-styles.test.mjs 尺寸/触屏门禁、NumericInput.test.tsx 的公共样式与表单属性契约,以及视觉矩阵同排对照。后续出现步进/国际化需求时再评估扩展或引入交互内核。
|
|
85
|
+
|
|
86
|
+
## 2026-09-06 输入装饰参考与采用决定
|
|
87
|
+
|
|
88
|
+
- 对照 Ant Design Input 的 prefix/suffix 与 allowClear、MUI InputAdornment 的 position,以及 Base UI Field/Input 的组合思路,采用 TextInput 起止 ReactNode 插槽;公共包只管理组合外框、输入焦点和共享状态,不接管搜索请求、数值格式或业务单位。
|
|
89
|
+
- 无装饰调用保持既有原生 input DOM;有装饰调用增加稳定外框,并让 ref、className、事件和原生属性继续落在 input。非交互装饰点击聚焦输入,按钮和链接保留自身行为。
|
|
90
|
+
- TextInput、NumericInput 与 ScaledNumericInput 使用同一组合样式:默认 40px、粗指针最小 44px、border-box、语义令牌、圆角和焦点环一致。紧凑清除按钮适配在外框内部,消费方不得用局部高度覆盖单位场景。
|
|
91
|
+
|
|
92
|
+
## 2026-09-11 Cascader 内核采用
|
|
93
|
+
|
|
94
|
+
新增固定 @rc-component/cascader@1.25.0(MIT),公共包装提供业务主题、表单元信息、空值归一、最近弹窗 portal、窄屏底部面板与默认独立多选。StructuredAddressInput 复用通用组件;TreeSelect 保留兼容。无 antd 依赖;依赖外置,发行包保留 RC 许可证。当前为本地实现,消费接入与发布独立验证。
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# DataTable:MRT 公共表格与迁移
|
|
2
|
+
|
|
3
|
+
0.2.31采用MRT替代原表格渲染内核;消费服务需单独升级验收。实际安装版本必须包含本文列出的导出;不能用旧版本直接导入新增入口。
|
|
4
|
+
|
|
5
|
+
## 导入与按需加载
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { DataTable } from '@jc-times/business-ui/data-table';
|
|
9
|
+
import '@jc-times/business-ui/styles.css';
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
主入口仍导出DataTable以兼容旧调用。独立 `data-table` 入口导出DataTable、useDataTable、DataTableView、DataTableTheme、DataTableMergedRows及相关类型。组件库采用ESM并将MRT/MUI作为外部依赖交给业务构建器处理;这些依赖已列为正式dependencies。
|
|
13
|
+
|
|
14
|
+
页面懒加载仍由消费服务负责。推荐把完整列表页面或业务表格包装作为动态import边界;仅换成独立入口不等于浏览器自动延迟加载。样式仍为共享CSS。构建验证已确认仅导入Button的消费产物不包含MRT/MUI实现,但使用DataTable的页面必然需要表格依赖。
|
|
15
|
+
|
|
16
|
+
## 旧参数兼容
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
<DataTable rows={rows} columns={columns} getRowId={row => row.id}
|
|
20
|
+
selectedRowIds={selectedIds} onSelectedRowIdsChange={setSelectedIds}/>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
旧DataTableProps和DataTableColumn保留:columns使用id/header/cell,排序使用sortValue或服务端sortable;sort/defaultSort/onSortChange、跨页选择、禁选、hiddenColumnIds、加载/空态、caption、ref与原生属性保持兼容。mobileLayout仍支持scroll/cards。
|
|
24
|
+
|
|
25
|
+
此入口已通过MRT_Table渲染表格,兼容层保留旧排序语义及memo行渲染。为避免旧页面行为改变,不自动增加工具栏、筛选或分页;也不自动把旧cell返回的ReactNode当作可搜索原始值。需要完整MRT交互时改用下述options入口。
|
|
26
|
+
|
|
27
|
+
## 完整表格配置
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { DataTable, type DataTableOptions } from '@jc-times/business-ui/data-table';
|
|
31
|
+
type Order = { id: string; customer: string; amount: number };
|
|
32
|
+
|
|
33
|
+
const options: DataTableOptions<Order> = {
|
|
34
|
+
data: orders,
|
|
35
|
+
columns: [
|
|
36
|
+
{ accessorKey: 'id', header: '编号' },
|
|
37
|
+
{ accessorKey: 'customer', header: '客户' },
|
|
38
|
+
{ accessorKey: 'amount', header: '金额' },
|
|
39
|
+
],
|
|
40
|
+
getRowId: row => row.id,
|
|
41
|
+
enableColumnOrdering: true,
|
|
42
|
+
enableColumnResizing: true,
|
|
43
|
+
enableColumnPinning: true,
|
|
44
|
+
enableRowSelection: true,
|
|
45
|
+
};
|
|
46
|
+
<DataTable options={options}/>;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
表格列较多且页面本身纵向滚动较长时,可显式开启底部吸附横向滚动条。它仅在内容确实超出表格容器时显示,并与 MRT 原生滚动容器双向同步;固定列仍通过 MRT 的 `columnPinning` 配置:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
<DataTable options={options} stickyHorizontalScrollbar
|
|
53
|
+
horizontalScrollbarLabel="订单表横向滚动" />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`horizontalScrollbarLabel` 应描述当前业务表格,供键盘和辅助技术用户辨认。该能力同样可传给 `DataTableView`;默认关闭,以避免改变既有页面的滚动布局。
|
|
57
|
+
|
|
58
|
+
options与旧rows/columns参数是两种互斥调用形式,不要混传。DataTableOptions、DataTableColumnDef、DataTableInstance分别对应MRT的options/column/instance类型;目前公开此底层契约,没有假称跨组件库兼容。默认中文文案和公共Lucide图标,可由options覆盖。
|
|
59
|
+
|
|
60
|
+
需要从工具栏、列设置等多个位置操作实例时:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
const table = useDataTable(options); // 在React组件内部调用
|
|
64
|
+
return <DataTableView table={table}/>;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
DataTableView与DataTable的配置入口共用MRT渲染和DataTableTheme;主题使用--ui-*,嵌套浮层继承OverlayContainer。独立放在表格外的MRT工具栏控件可用DataTableTheme包裹。ModalShell中的Escape层级仍由业务组合协调,参考合同样例;公共表格不会替业务关闭弹窗。
|
|
68
|
+
|
|
69
|
+
## 合并行与展开明细
|
|
70
|
+
|
|
71
|
+
模式由业务服务选择,不固化合同/产品字段,也不要求最终用户看到切换器。
|
|
72
|
+
|
|
73
|
+
- 展开:options.renderDetailPanel渲染调用方提供的明细,沿用MRT展开状态。
|
|
74
|
+
- 合并:options使用layoutMode='semantic'、enableRowVirtualization=false,在muiTableBodyProps中调用DataTableMergedRows。按主记录分页,每条明细生成真实tr,其他可见列使用rowSpan跨行。
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
const table = useDataTable({
|
|
78
|
+
...options,
|
|
79
|
+
layoutMode: 'semantic',
|
|
80
|
+
enableRowVirtualization: false,
|
|
81
|
+
muiTableBodyProps: ({ table }) => ({ children:
|
|
82
|
+
<DataTableMergedRows table={table}
|
|
83
|
+
getDetails={row => row.lines}
|
|
84
|
+
detailColumnIds={['product', 'quantity']}
|
|
85
|
+
getDetailValue={(line, id) => id === 'product' ? line?.name ?? '暂无产品' : line?.quantity ?? '—'}/>
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
上述示意要求业务Row包含lines,并在columns定义product/quantity这两个明细列。getDetails返回只读数组,getDetailValue接受空明细null。主行用getRowId稳定标识;列的排序、筛选应基于主记录定义,明细列应关闭没有明确语义的排序/筛选。隐藏所有明细列时每主记录一行。合并不支持跨主记录、任意colSpan、分组/树形/行固定组合;不与虚拟化同时使用。
|
|
91
|
+
|
|
92
|
+
合同样例已通过公共DataTableMergedRows生成合并行;合同字段、金额区间弹层、搜索记忆及列设置布局仍由业务包装组合,详见 [合同样例](mrt-poc.md)。这些业务特定能力不会作为DataTable旧参数静默启用。
|
|
93
|
+
|
|
94
|
+
## 迁移与验收
|
|
95
|
+
|
|
96
|
+
1. 旧页面可保留DataTable旧参数,先验证布局、排序、选择及加载状态。
|
|
97
|
+
2. 复杂页面改用options或useDataTable/DataTableView,明确服务端查询和分页,不同时使用旧排序参数。
|
|
98
|
+
3. 为重型页面设置动态import边界,验证仅使用按钮的页面不含MRT/MUI代码。
|
|
99
|
+
4. 长页面可启用stickyHorizontalScrollbar;确认无溢出时隐藏,拖动吸附滚动条和原生滚动区时位置同步。
|
|
100
|
+
5. 合并模式按主记录分页;虚拟化只减少DOM,不减少全量数据筛选开销。
|
|
101
|
+
6. 发布新版本后,消费服务精确升级并验证真实接口、权限、用户隔离和设备;本地完成不等于生产已替换。
|
|
102
|
+
|
|
103
|
+
不修改业务数据,不自动迁移所有服务,不提供旧包版本的新能力。MRT3.2.1和MUI7.3.11及配套依赖已固定在package.json/锁文件中。
|
|
104
|
+
|
|
105
|
+
## 按需打包回归与项目管理复验(2026-09-12)
|
|
106
|
+
|
|
107
|
+
构建现使用preserveModules保留组件边界。原合并产物中工厂调用等初始化代码会阻止整段未用组件被删除;仅保留ESM导出和sideEffects声明不足以确保合并模块内部纯度。修复后消费构建可跳过完整未使用模块,不在业务端改写包代码。
|
|
108
|
+
|
|
109
|
+
`pnpm test:tree-shaking` 在 `pnpm build` 后对真实dist产物构建Button、TextInput、DateInput、DataTable四个消费者。前两者必须没有日期/MRT/MUI实现;后两者为正向对照。该检查已纳入pnpm verify。门禁统计传递模块,不仅检查包文件名或入口长度。
|
|
110
|
+
|
|
111
|
+
读取项目管理0.1.103当前工作树(依赖正式business-ui0.2.30),以相同Vite配置、同一业务入口构建隔离产物,未修改其package/lockfile/源码、未写其dist:
|
|
112
|
+
|
|
113
|
+
| 入口静态依赖闭包 | 正式0.2.30 | 本地候选 |
|
|
114
|
+
| --- | ---: | ---: |
|
|
115
|
+
| JS gzip | 178.51 KiB | 83.31 KiB |
|
|
116
|
+
| CSS gzip | 17.17 KiB | 17.17 KiB |
|
|
117
|
+
| 日期组件/Calendar模块 | 17 | 0 |
|
|
118
|
+
| MRT模块 | 0 | 0 |
|
|
119
|
+
|
|
120
|
+
证据在本库忽略产物 `artifacts/project-ui-check/results.json`。这是候选dist别名复验,不是消费服务正式安装、完整验收或部署。项目门禁JS80 KiB、CSS14.5 KiB仍失败;不得提高预算或把日期泄漏修复记作整项发布阻塞解除。剩余首屏代码与共享CSS需另行按真实使用拆分。MRT替代带来的路由体积也需在消费方完整门禁中验收。
|
|
121
|
+
|
|
122
|
+
公共库136项测试、14项MRT浏览器回归、类型/公共库/矩阵/样例构建和按需打包门禁通过。本地候选已可打包;对应公共库版本为0.2.31,不能覆盖已经发布的0.2.30。
|
|
123
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 依赖维护与升级
|
|
2
|
+
|
|
3
|
+
核查日期:2026-09-12。以下为当前工作树的未发布候选;正式 0.2.31 不包含本次升级。版本来自 npm 官方 registry 的 `latest` 标签,并排除 prerelease。直接依赖使用精确版本,传递依赖遵守上游范围,不用全局 override 强行跨主版本。
|
|
4
|
+
|
|
5
|
+
## 版本清单
|
|
6
|
+
|
|
7
|
+
| 依赖 | 当前候选 | 上游最新稳定版 | 结论 |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| lucide-react | 1.45.0 | 1.45.0 | 升级;消费 peer 仍允许已有 0.x |
|
|
10
|
+
| react / react-dom | 19.3.0 | 19.3.0 | 默认开发版本;继续验证 18.3.1 |
|
|
11
|
+
| @types/react / @types/react-dom | 19.3.0 | 19.3.0 | 与开发版本配套 |
|
|
12
|
+
| material-react-table | 3.2.1 | 3.2.1 | 已是最新 |
|
|
13
|
+
| @mui/material / @mui/icons-material | 7.3.11 | 9.4.0 | 最新兼容分支,原因见下文 |
|
|
14
|
+
| @mui/x-date-pickers | 9.13.0 | 9.13.0 | 升级;支持 MUI 7.3+ |
|
|
15
|
+
| @emotion/react | 11.14.0 | 11.14.0 | 已是最新 |
|
|
16
|
+
| @emotion/styled | 11.14.1 | 11.14.1 | 升级 |
|
|
17
|
+
| @embedpdf/react-pdf-viewer | 2.15.0 | 2.15.0 | 已是最新 |
|
|
18
|
+
| @embedpdf/core / engines / plugin-document-manager / plugin-viewport / plugin-scroll / plugin-render / plugin-zoom / plugin-rotate / plugin-thumbnail | 2.15.0 | 2.15.0 | Headless 原生模式使用的精确版本依赖;仅选择该模式时加载 |
|
|
19
|
+
| pdfjs-dist | 6.3.289 | 6.3.289 | 升级;可选 peer 有迁移要求 |
|
|
20
|
+
| @internationalized/date | 3.12.4 | 3.12.4 | 已是最新 |
|
|
21
|
+
| @radix-ui/react-dialog / react-popover | 1.1.23 | 1.1.23 | 已是最新 |
|
|
22
|
+
| @radix-ui/react-select | 2.3.7 | 2.3.7 | 已是最新 |
|
|
23
|
+
| @radix-ui/react-toast | 1.2.23 | 1.2.23 | 已是最新 |
|
|
24
|
+
| @radix-ui/react-tooltip | 1.2.16 | 1.2.16 | 已是最新 |
|
|
25
|
+
| @rc-component/cascader | 1.25.0 | 1.25.0 | 已是最新 |
|
|
26
|
+
| react-aria-components | 1.21.1 | 1.21.1 | 升级 |
|
|
27
|
+
| cn-division | 2026.0.1 | 2026.0.1 | 升级 |
|
|
28
|
+
| @playwright/test | 1.63.0 | 1.63.0 | 已是最新 |
|
|
29
|
+
| @testing-library/jest-dom | 7.0.1 | 7.0.1 | 升级 |
|
|
30
|
+
| @testing-library/react | 16.3.3 | 16.3.3 | 固定最新版本 |
|
|
31
|
+
| jsdom | 30.0.1 | 30.0.1 | 升级;本地 Node 24.19 |
|
|
32
|
+
| typescript | 6.0.3 | 7.0.2 | 最新兼容分支,原因见下文 |
|
|
33
|
+
| vite | 8.3.0 | 8.3.0 | 升级至 Rolldown/Oxc 构建链 |
|
|
34
|
+
| vitest | 5.0.0 | 5.0.0 | 升级 |
|
|
35
|
+
| dayjs | 1.11.23 | 1.11.23 | 仅新增为日期筛选回归的开发依赖 |
|
|
36
|
+
|
|
37
|
+
## 兼容例外
|
|
38
|
+
|
|
39
|
+
**MUI 7.3.11。** MRT 3.2.1 的 peer 声明为 `@mui/material >=6`,安装器允许 MUI 9,但其内部编辑字段、选择框及部分控件仍使用 `InputProps`、`SelectProps`、`inputProps` 等旧 API。[MUI 9 迁移指南](https://mui.com/material-ui/migration/upgrade-to-v9/) 已删除这些 API。不能把宽松 peer 范围当成完成适配的证据;待 MRT 正式迁移后再升级,避免自行维护第三方分支。MUI X 是独立版本线,9.13.0 支持 MUI 7.3+,无需与 Material 同主版本。
|
|
40
|
+
|
|
41
|
+
**TypeScript 6.0.3。** 实测 7.0.2 的主入口只暴露版本信息,不再提供门禁 CLI 依赖的 `createSourceFile`、`ScriptTarget` 等传统 Compiler API,导致四项门禁测试失败。其新 API 位于 `unstable/*`;本库暂保留提供稳定 Compiler API 的最新 6.x。不要在消费项目用 TypeScript 7 执行当前 `business-ui-gate`;先保留 6.x 工具环境或等待门禁解析器迁移。类型构建显式设置 `rootDir: src`,CSS 副作用导入有类型声明。
|
|
42
|
+
|
|
43
|
+
## 消费与按需加载
|
|
44
|
+
|
|
45
|
+
- PDF.js 4→6 是跨主版本变更:消费旧查看器的项目须同步更新 `pdfjs-dist`、worker 和文档对象类型,详见 [查看器迁移](document-viewer.md)。本次未修改或部署消费服务。
|
|
46
|
+
- Lucide 1.x 已本地验证;peer 范围保留 `>=0.468.0 <2`。消费者继续使用具名导入,避免导入完整图标字典。
|
|
47
|
+
- 不要求消费项目跟随升级 React 19。CI 保留 React 18/19 两条验证线;开发/测试环境采用 Node 24.15+。
|
|
48
|
+
- 公共库继续保留组件模块边界;Button/TextInput 消费构建中日期与 MRT/MUI 实现模块均为零。MRT 的日期实现由其自身静态依赖引入,不因安装 Day.js 测试依赖就进入轻量组件入口。
|
|
49
|
+
- 新增日期选择/清除的桌面和手机浏览器回归,使用 `LocalizationProvider` 和消费方提供的 adapter;日期适配器不是公共库强制运行依赖。
|
|
50
|
+
|
|
51
|
+
## 已知上游开发警告
|
|
52
|
+
|
|
53
|
+
React 19 开发模式下,Cascader 的传递依赖 `@rc-component/select@1.11.0` 仍读取 `InputComponent.ref`,触发弃用警告;两者已是上游最新稳定版。禁用的 SortableList 在 React Aria 中触发缺少拖动按钮提示。现有交互回归通过,但不能宣称控制台完全无警告;未屏蔽警告或修改第三方源码。
|
|
54
|
+
|
|
55
|
+
2026-09-12 本地验证:React 18.3.1 / 19.3.0 均通过 136 项单测、类型检查、库构建、按需打包门禁和视觉矩阵构建。React 19 的 38 项公共浏览器回归及新增 2 项日期回归、React 18 的完整 40 项浏览器回归通过;React 19 的 MRT 14 项浏览器回归和样例构建通过。日期回归 fixture 另经严格 TypeScript 检查。尚未提交、执行远端 CI 或发布,消费服务未升级。
|
|
56
|
+
|
|
57
|
+
后续运行 `pnpm verify`、`pnpm test:browser`、`pnpm test:mrt`,并检查 `pnpm pack` 的声明、子入口和文档清单。最新版本可从 [npm 官方 registry](https://registry.npmjs.org/) 重新核查,具体迁移参考 [Vite 8](https://vite.dev/guide/migration) 与 [MUI X 9](https://mui.com/x/migration/migration-pickers-v8/)。
|