@jc-times/business-ui 0.2.55 → 0.3.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.
- package/AGENTS.md +6 -6
- package/CHANGELOG.md +311 -307
- package/README.md +48 -48
- package/THIRD_PARTY_NOTICES.md +18 -18
- package/bin/business-ui-gate.mjs +171 -171
- package/dist/form-controls.js +4 -0
- package/dist/types/form-controls.d.ts +8 -0
- package/dist/vendor/embedpdf-zoom-react.js +1 -1
- package/docs/agent-guide.md +170 -168
- package/docs/api.md +252 -248
- package/docs/cascader.md +58 -58
- package/docs/component-strategy.md +93 -93
- package/docs/data-table.md +127 -127
- package/docs/document-viewer-v2.md +265 -265
- package/docs/modal-shell-migration.md +43 -43
- package/docs/mrt-poc.md +1 -1
- package/docs/sortable-list.md +42 -42
- package/docs/user-profile.md +17 -17
- package/docs/viewport-qa.md +126 -126
- package/licenses/rc-cascader-MIT.txt +21 -21
- package/package.json +5 -1
package/docs/api.md
CHANGED
|
@@ -1,249 +1,253 @@
|
|
|
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
|
-
- `UserProfilePopover`:展示人员标签与点击后打开的只读资料卡。必填 `name`;可选 `code`、`department`、`tag`、`avatarUrl`、`avatarColor`,以及 `codeLabel`、`departmentLabel`。默认触发器是可聚焦按钮;`trigger` 可换成自定义单个可转发 ref 的交互元素。支持 `side`、`align`、`open`、`defaultOpen`、`onOpenChange` 和弹层 `className`;沿用 Popover 的 Escape、失焦关闭和视口避让。资料卡宽度随视口在 300–560px 间变化,并受可用空间限制;可用 `--ui-user-profile-width` 调整。组件不加载人员资料、不推断身份或权限,缺失的字段不显示。
|
|
16
|
-
|
|
17
|
-
详细用法见[人员资料卡](user-profile.md)。
|
|
18
|
-
|
|
19
|
-
```tsx
|
|
20
|
-
<UserProfilePopover name="章晨露" code="ZhangChenLu"
|
|
21
|
-
department="示例集团 / 项目管理部 / 运营组" tag="内部成员"
|
|
22
|
-
avatarColor="#e94b50" />
|
|
23
|
-
```
|
|
24
|
-
- `MetricCard`:用 `label`、`value`、可选 `description`、装饰性 `icon` 与五档 `tone` 呈现单项指标;根节点是由可见 label 命名的 `article`,透传 article 属性并 forward ref。数值格式化、趋势计算、单位和业务文案均由调用方完成。
|
|
25
|
-
- `PageHeader`:用 `eyebrow`、必填 `title`、可选 `description` 和 `actions` 组成页面标题区,固定输出页面级 `h1`;`titleId` 可用于页内关联。根节点是原生 `header`,支持原生属性与 ref,窄屏时操作区自动换行。`copyProps` 与 `actionsProps` 为既有 `.ui-page-header-copy` / `.ui-page-header-actions` 槽透传原生 div 属性,便于消费方挂接稳定的 class、data 与可访问属性;不传 `actions` 时不输出空操作区。
|
|
26
|
-
- `SectionCard`:必填 `title` 和 `children`,可选 `description`、`actions`、`headingId` 与 `headingLevel`(2–6)。根节点是由可见标题自动命名的 `section`,因此不仅是样式包装;消费方应按页面大纲选择标题层级。显式 `aria-label` / `aria-labelledby` 会覆盖自动区域名称。
|
|
27
|
-
|
|
28
|
-
四个组件使用同一 `className` 合并顺序(组件类在前、消费方类在后),不创建状态、Effect、订阅或布局测量,也不引入额外运行时依赖。大量指标的聚合、虚拟化和数据刷新属于消费方职责。
|
|
29
|
-
|
|
30
|
-
## 弹窗与确认
|
|
31
|
-
|
|
32
|
-
`ModalShell`(别名 `Dialog`)通过条件挂载控制显示,没有 `open` 属性;必须提供 `titleId`、`title`、`closeLabel`、`onClose` 和正文。它内建焦点陷阱、背景滚动锁、栈顶 Escape 处理和关闭后的焦点归还。`initialFocus` 与 `returnFocus` 接受元素或 React ref;`returnFocus={false}` 可显式关闭归还。`closeOnEscape`、`closeOnBackdrop` 和 `closeDisabled` 分别控制关闭策略。`rootRef` 保持兼容,消费方通常不再需要额外调用 `useModalFocusTrap`。
|
|
33
|
-
|
|
34
|
-
面板稳定输出 `.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)。
|
|
35
|
-
|
|
36
|
-
`ConfirmDialog` 用于不依附锚点的确认流程。它是受控弹窗,支持普通/危险确认、`busy`、安全的默认取消焦点、Escape 与焦点归还。`Popconfirm` 只用于依附触发器的轻量确认。
|
|
37
|
-
|
|
38
|
-
## 表单与选择
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
- `
|
|
55
|
-
- `
|
|
56
|
-
- `
|
|
57
|
-
- `
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
`
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
`
|
|
86
|
-
|
|
87
|
-
##
|
|
88
|
-
|
|
89
|
-
`
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- `
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
- [
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
|
188
|
-
|
|
|
189
|
-
|
|
|
190
|
-
|
|
|
191
|
-
|
|
|
192
|
-
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
PDFium
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
+
- `UserProfilePopover`:展示人员标签与点击后打开的只读资料卡。必填 `name`;可选 `code`、`department`、`tag`、`avatarUrl`、`avatarColor`,以及 `codeLabel`、`departmentLabel`。默认触发器是可聚焦按钮;`trigger` 可换成自定义单个可转发 ref 的交互元素。支持 `side`、`align`、`open`、`defaultOpen`、`onOpenChange` 和弹层 `className`;沿用 Popover 的 Escape、失焦关闭和视口避让。资料卡宽度随视口在 300–560px 间变化,并受可用空间限制;可用 `--ui-user-profile-width` 调整。组件不加载人员资料、不推断身份或权限,缺失的字段不显示。
|
|
16
|
+
|
|
17
|
+
详细用法见[人员资料卡](user-profile.md)。
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<UserProfilePopover name="章晨露" code="ZhangChenLu"
|
|
21
|
+
department="示例集团 / 项目管理部 / 运营组" tag="内部成员"
|
|
22
|
+
avatarColor="#e94b50" />
|
|
23
|
+
```
|
|
24
|
+
- `MetricCard`:用 `label`、`value`、可选 `description`、装饰性 `icon` 与五档 `tone` 呈现单项指标;根节点是由可见 label 命名的 `article`,透传 article 属性并 forward ref。数值格式化、趋势计算、单位和业务文案均由调用方完成。
|
|
25
|
+
- `PageHeader`:用 `eyebrow`、必填 `title`、可选 `description` 和 `actions` 组成页面标题区,固定输出页面级 `h1`;`titleId` 可用于页内关联。根节点是原生 `header`,支持原生属性与 ref,窄屏时操作区自动换行。`copyProps` 与 `actionsProps` 为既有 `.ui-page-header-copy` / `.ui-page-header-actions` 槽透传原生 div 属性,便于消费方挂接稳定的 class、data 与可访问属性;不传 `actions` 时不输出空操作区。
|
|
26
|
+
- `SectionCard`:必填 `title` 和 `children`,可选 `description`、`actions`、`headingId` 与 `headingLevel`(2–6)。根节点是由可见标题自动命名的 `section`,因此不仅是样式包装;消费方应按页面大纲选择标题层级。显式 `aria-label` / `aria-labelledby` 会覆盖自动区域名称。
|
|
27
|
+
|
|
28
|
+
四个组件使用同一 `className` 合并顺序(组件类在前、消费方类在后),不创建状态、Effect、订阅或布局测量,也不引入额外运行时依赖。大量指标的聚合、虚拟化和数据刷新属于消费方职责。
|
|
29
|
+
|
|
30
|
+
## 弹窗与确认
|
|
31
|
+
|
|
32
|
+
`ModalShell`(别名 `Dialog`)通过条件挂载控制显示,没有 `open` 属性;必须提供 `titleId`、`title`、`closeLabel`、`onClose` 和正文。它内建焦点陷阱、背景滚动锁、栈顶 Escape 处理和关闭后的焦点归还。`initialFocus` 与 `returnFocus` 接受元素或 React ref;`returnFocus={false}` 可显式关闭归还。`closeOnEscape`、`closeOnBackdrop` 和 `closeDisabled` 分别控制关闭策略。`rootRef` 保持兼容,消费方通常不再需要额外调用 `useModalFocusTrap`。
|
|
33
|
+
|
|
34
|
+
面板稳定输出 `.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)。
|
|
35
|
+
|
|
36
|
+
`ConfirmDialog` 用于不依附锚点的确认流程。它是受控弹窗,支持普通/危险确认、`busy`、安全的默认取消焦点、Escape 与焦点归还。`Popconfirm` 只用于依附触发器的轻量确认。
|
|
37
|
+
|
|
38
|
+
## 表单与选择
|
|
39
|
+
|
|
40
|
+
### 轻量表单入口
|
|
41
|
+
|
|
42
|
+
登录、注册和其他独立基础表单可从 `@jc-times/business-ui/form-controls` 导入 `Alert`、`Button`、`LinkButton`、`FormField`、`TextInput`、`TextArea`、`SelectInput` 与 `Checkbox`,并同时导入 `@jc-times/business-ui/styles.css`。该入口避免目录、日期、表格与文档查看器的依赖图;组件参数和行为与主入口的同名导出一致。
|
|
43
|
+
|
|
44
|
+
- `Button`:执行提交、打开、确认等动作;当 `iconOnly` 为 `true` 时,TypeScript 强制要求 `aria-label`。
|
|
45
|
+
- `LinkButton`:导航或下载使用的真实 `<a>`,必须提供 `href`,支持 `download`、按钮视觉变体和禁用语义;图标链接同样必须提供 `aria-label`。禁用时移除 `href`、退出 Tab 顺序并阻止点击向父级冒泡,同时保留禁用链接的可访问语义。
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<LinkButton href="/api/contracts/42/file" download="合同-42.pdf">下载合同(PDF)</LinkButton>
|
|
49
|
+
<LinkButton href={preparedBlobUrl} download="处理后的合同.pdf" iconOnly aria-label="下载处理后的合同">↓</LinkButton>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
原生 `download` 只保证同源 URL、`blob:` 与 `data:` URL 的下载提示;跨域响应可能直接导航,并受服务端 `Content-Disposition` 影响。需要自定义鉴权请求头、异步生成或客户端转换时,由业务层完成请求与错误处理,成功后向 `LinkButton` 提供同源签名地址或 Blob URL,并在不再使用时释放 Blob URL。下载或新窗口行为应写入可见文案或可访问名称,不能只靠装饰图标表达。
|
|
53
|
+
|
|
54
|
+
- `TextInput`:`startAdornment` / `endAdornment` 接受 ReactNode,用于搜索图标、清除按钮、金额单位和百分号。未提供装饰时保持原有 input-only DOM;提供装饰时 ref、className 和原生属性仍落在 input,外框统一呈现 focus/invalid/disabled 状态。点击非交互装饰会聚焦输入框;交互装饰需自行提供可访问名称,并随输入框同步禁用。
|
|
55
|
+
- `Select`:`triggerRef` 暴露触发按钮;`triggerProps` 透传触发器的 ARIA、data 与事件属性;`portalContainer` 和 `placement` 控制安全的浮层挂载与方向。原生 `SelectInput` 在触屏使用 44px 最小点击高度;自定义 `Select` 在 600px 以下以安全区底部抽屉呈现,并限制候选区高度、内部滚动与滚动链。
|
|
56
|
+
- `Combobox` / `AutoComplete`:`inputRef`、`inputProps` 透传输入框 ARIA、data、`inputMode`、`autoComplete` 与原生事件;`placement` 与 `portalContainer` 控制浮层。
|
|
57
|
+
- `ToggleSwitch`:除受控 `checked/onChange` 外接受原生 checkbox 属性并 forward ref,可使用 `id`、`name`、`value`、`required`、`form`、ARIA 与 data 属性参与原生表单。
|
|
58
|
+
- `DateInput`:forward ref(也可用 `inputRef`)并保留非冲突原生输入属性;既有 `className` 继续作用于组合控件外层,输入框类名使用 `inputClassName`。日历支持方向键、Home/End(移到月首/月末)、PageUp/PageDown;详细日期限制与键盘行为见 [成熟度迁移](maturity-migration.md)。
|
|
59
|
+
- `TreeSelect`:接收业务无关的扁平 `items`(`id`、`label`、可选 `parentId/order/disabled`),内部构造任意层级树并处理孤儿、重复 ID、自环和环状父子关系。支持受控/非受控 value、open、query、expandedIds,搜索时保留完整祖先路径;输入框使用 combobox + tree 语义并实现方向键、Home/End、左右展开收起、Enter 和 Escape。组件只提交既有节点 ID,不接受自由文本值。
|
|
60
|
+
- `StructuredAddressInput`:接收 `AddressRegion[]`,默认只显示地区级联与详细地址,海外使用顶级“海外”选项。旧调用可显式设 `showModeSelector={true}` 恢复模式切换,切换器复用公共 Select。`@jc-times/business-ui/chinese-address-regions` 独立导出固定版本的中国省市区、顶级“海外”、数据版本和海外 ID,使消费方可在地址页面按需加载;业务地址字符串的解析与拼接仍由消费方负责。
|
|
61
|
+
- `FileDropzone`:唯一的公共文件选择表面,整块区域可点击、键盘 Enter/Space 打开,也可直接拖入;支持 `accept`、单/多选、禁用、输入 ref、重复选择清空以及拒绝文件回调。组件只提交 `File[]`,支持 `maxFileSize`(字节)、`maxFiles`(单批数量)和 `onRejections`(type/size/count);上传请求、服务端校验和业务错误由消费方处理;children 中不要嵌套按钮或其他交互控件。
|
|
62
|
+
|
|
63
|
+
TextInput(含装饰组合外框)、原生 SelectInput 与默认 Button 的桌面高度均显式为 `--ui-control-height`(默认 40px)且采用 border-box;触屏环境的最小操作高度为 `--ui-touch-height`(默认 44px)。
|
|
64
|
+
|
|
65
|
+
## 异步搜索与菜单
|
|
66
|
+
|
|
67
|
+
`AsyncSearchPicker<T>` 不发请求也不保存业务 DTO。调用方受控提供 `query`、`items`、`status`、`onSearch` 和 `onSelect`,并通过 `getKey/getText/renderItem` 映射数据。组件统一处理最少字符提示、loading/error/empty、显式查询按钮、上下键、Enter、Escape、busy 与 disabled;候选区会响应 `visualViewport` 的软键盘高度变化并保持键盘选中项可见。取消请求和数据生命周期仍由调用方负责。
|
|
68
|
+
|
|
69
|
+
`DropdownMenu`(别名 `Menu`)提供真正的 menu 语义和 React Aria 键盘行为,支持禁用、危险项、分组、分隔与子菜单,并在关闭后归还焦点。普通操作项输出 `menuitem`;传 `selectionMode="single" | "multiple"` 后,`selectedKeys` / `defaultSelectedKeys` 与 `onSelectionChange` 分别驱动 `menuitemradio` / `menuitemcheckbox` 和 `aria-checked`。类型层禁止在未开启选择模式时传 selected keys。
|
|
70
|
+
|
|
71
|
+
每个操作项或子菜单可传 `current`(例如 `"page"`)输出 `aria-current`;`startIcon`、`endSlot`、`selectedIcon` 分别承载装饰图标、只读尾部状态与选中图标,不能在槽内放交互控件。`triggerRef` / `triggerProps`、`menuRef` / `menuProps` 与每项的 `itemRef` / `itemProps` 提供 ref、ARIA、data 和 React Aria 事件透传。`menuLabel` 可在菜单名称与触发器名称不同时提供独立的可访问名称。
|
|
72
|
+
|
|
73
|
+
触屏设备上菜单项最小高度为 `--ui-touch-height`,窄屏和短横屏中菜单限制在视口内并内部滚动。`Popover` 只承载补充信息或小型表单,不应代替操作菜单。
|
|
74
|
+
|
|
75
|
+
## 数据表移动端契约
|
|
76
|
+
|
|
77
|
+
从0.2.31起,`DataTable` 通过MRT渲染,保留旧参数及移动布局;新增 `options` 配置形式、`useDataTable` / `DataTableView`、`DataTableTheme` 和 `DataTableMergedRows`,见 [DataTable迁移](data-table.md)。独立 `data-table` 入口不能从旧安装版本导入。
|
|
78
|
+
|
|
79
|
+
合同业务展示、搜索记忆与列设置组合见 [MRT样例](mrt-poc.md)。`productDisplay` 属于合同包装参数,不是公共DataTable旧参数。
|
|
80
|
+
|
|
81
|
+
`DataTable` 默认 `mobileLayout="scroll"`,保持 0.2.4 及更早版本的横向滚动行为。真实调用需要标签化卡片行时可显式传 `mobileLayout="cards"`;在 600px 及以下,表头保持对辅助技术可用但视觉隐藏,单元格通过 `mobileLabel` 或字符串表头生成的 `data-label` 呈现标签。复杂表头应显式提供 `mobileLabel`。卡片布局允许长文本换行,并为选择列、尾部操作列和空状态提供独立布局。`rootRef` / `rootProps` 与 `tableRef` / `tableProps` 可用于稳定挂接原生属性,不需要依赖结构位置选择器。
|
|
82
|
+
|
|
83
|
+
长页面或宽表格可显式传 `stickyHorizontalScrollbar`,让底部横向滚动条在内容溢出时吸附于可视区域并与原生表格滚动同步;通过 `horizontalScrollbarLabel` 提供当前业务表格的可访问名称。该能力默认关闭,也适用于完整 `options` 入口和 `DataTableView`。
|
|
84
|
+
|
|
85
|
+
`Pagination` 在 360px 及以下自动只保留上一页、当前页摘要和下一页,调用方仍可用 `compact` 在更宽视口显式简化。`ToastProvider` 的连续通知栈限制在动态视口与底部安全区内,超出时内部滚动;长文案和操作按钮会在窄屏换行。
|
|
86
|
+
|
|
87
|
+
## 状态工具
|
|
88
|
+
|
|
89
|
+
`useDebouncedValue<T>(value, delay)` 返回输入值的延迟稳定副本。初始值立即返回;值或延迟变化会重启计时器;卸载会清理待执行计时器;非有限值和非正延迟按 `0` 处理。它不延迟输入框自身的 `onChange`,也不负责发请求、取消请求或处理响应竞态。
|
|
90
|
+
|
|
91
|
+
## TextInput 输入装饰(0.2.13)
|
|
92
|
+
|
|
93
|
+
`TextInput` 的 `startAdornment` / `endAdornment` 可承载搜索图标、清除按钮、货币符号、单位和百分号;`NumericInput` 与 `ScaledNumericInput` 自动继承同一 API。
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
<TextInput label="搜索" value={query} onChange={event => setQuery(event.currentTarget.value)}
|
|
97
|
+
startAdornment={<Search aria-hidden="true" />}
|
|
98
|
+
endAdornment={query ? <Button size="compact" iconOnly aria-label="清除搜索"
|
|
99
|
+
onClick={() => setQuery("")}><X /></Button> : undefined} />
|
|
100
|
+
<NumericInput label="税率" value={rate} onValueCommit={setRate}
|
|
101
|
+
endAdornment={<span aria-hidden="true">%</span>} />
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- 不传装饰时继续直接输出原生 input,保持既有 DOM 与样式;传入装饰后由组合外框统一呈现边框、焦点和错误状态,`ref`、`className` 与原生输入属性仍作用于 input。
|
|
105
|
+
- 点击非交互装饰会聚焦输入框。装饰中的按钮、链接和表单控件保留自身交互;图标或单位等重复信息应使用 `aria-hidden="true"`,图标按钮必须提供可访问名称。
|
|
106
|
+
- 禁用输入时,消费方应同时禁用装饰中的交互控件。组合控件保持默认 40px 高度,粗指针触屏最小高度为 44px;不要为单位或清除按钮设置另一套控件高度。
|
|
107
|
+
|
|
108
|
+
## NumericInput / ScaledNumericInput(0.2.8)
|
|
109
|
+
|
|
110
|
+
选择两层 API:`NumericInput` 用字符串保留十进制精度;`ScaledNumericInput` 用安全整数保存最小单位。两者均为受控组件,通过 `onValueCommit` 在失焦或回车时更新状态;输入中间态留在组件,必要时使用 `onDraftChange` 观察。不要用 draft 执行金额计算。
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<NumericInput label="数量" value={quantity} onValueCommit={setQuantity}
|
|
114
|
+
decimalPlaces={3} min="0" required />
|
|
115
|
+
<ScaledNumericInput label="单价" value={minorUnits} onValueCommit={setMinorUnits}
|
|
116
|
+
scale={100} min={0} selectAllOnFocus selectAllOnClick />
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- `NumericInput`: `value: string`、`onValueCommit(string)` 必填;`decimalPlaces=2`(0–100);`min/max` 为可在该精度表示的十进制字符串。允许负数,需非负时设 `min="0"`。
|
|
120
|
+
- `ScaledNumericInput`: `value: number | null`、`onValueCommit(number | null)` 必填;`scale=100`,仅接受安全整数范围内的正十次幂;精度由 scale 推导。`min/max` 与 value 均为存储单位的安全整数,默认上下界为 ±Number.MAX_SAFE_INTEGER。若需超出安全整数范围,用 NumericInput 字符串 API。
|
|
121
|
+
- 接受空值、正负号、小数点、尾随小数点、前导零和粘贴千分位。编辑时不截断超出精度的小数;提交采用十进制四舍五入(负数中点远离零),再限幅,去除前导/尾随零。空值或孤立符号提交为空字符串/`null`,不自动转换为零。
|
|
122
|
+
- `useGrouping=true` 仅在非编辑态展示千分位;小数点固定为 `.`,分组为 `,`,不提供 locale 解析。`selectAllOnFocus=false` 与 `selectAllOnClick=false` 分别配置全选行为。默认 `inputMode="decimal"`。
|
|
123
|
+
- 透传 TextInput 的 label、required、helpText、error、disabled、readOnly、ARIA、className、containerClassName、ref 和原生输入事件/属性(组件管理 type/value/defaultValue/min/max)。原生 `onChange` 观察输入事件,不能替代 `onValueCommit`。Enter 在组合输入结束后触发失焦提交并阻止表单默认提交,消费者可在 onKeyDown 中 preventDefault 取消。只读和禁用不提交。
|
|
124
|
+
- 编辑期间外部 value 更新不覆盖当前草稿;结束编辑后外部 value 始终为显示真值,消费者须在 commit 回调更新 value。原生 FormData 的值是当前显示文本(可能含分组),提交业务数据请使用受控状态。
|
|
125
|
+
- 样式完全复用 `.ui-input`/`.ui-form-field` 与 `--ui-*` 语义令牌,无新增应用主题。非十次幂换算、业务校验、货币符号及中文大写转换由消费方负责。
|
|
126
|
+
|
|
127
|
+
合同迁移:将本地 GroupedDecimalInput 的数量包装改为 NumericInput(decimalPlaces=3、min="0");将 ScaledDecimalInput 的含税单价/税率包装改为 ScaledNumericInput(scale=100、min=0,税率 max=10000)。把原提交回调映射到 onValueCommit;若业务将空值视为零,在应用包装中显式使用 `next ?? 0`。侧栏继续保存/显示阿拉伯数字,Word 写入时的中文金融大写转换保留在业务写入器。
|
|
128
|
+
|
|
129
|
+
消费项目选择支持所需能力的已发布精确版本并提交锁文件;有 npm 锁文件的项目也需按自身规则同步。替换完成后移除本地原生 input 实现、缩减 bareInput 门禁基线,并完成数量、金额、税率及 Word 写入的桌面/手机回归。本次公共库变更不等于消费方已完成迁移。
|
|
130
|
+
|
|
131
|
+
数字输入的成熟组件参考及尺寸约束见 [设计策略](component-strategy.md):与 TextInput/SelectInput 共用默认 40px、触屏最小 44px 的尺寸令牌,以及宽度、内边距、字体和圆角;消费方调整密度时须统一调整同行控件。
|
|
132
|
+
|
|
133
|
+
## 金额显示与格式化
|
|
134
|
+
|
|
135
|
+
`NumericInput` / `ScaledNumericInput` 接受 `moneyFormat={{ symbol: "¥", unit: "元", display: "symbol" }}`。display 默认为 symbol,unit 使用后缀,number 不显示货币文字。金额默认两位小数(受 decimalPlaces 限制);编辑草稿和提交值仍为数值。`minimumFractionDigits` 只影响非编辑态的最少小数位,不改变空值和提交精度。
|
|
136
|
+
|
|
137
|
+
服务端文档使用 `@jc-times/business-ui/amount-format` 的 `formatScaledMoney(3750000, { symbol: "¥", unit: "元" })` 得到 `¥37,500.00`。该子入口不引入 React,以安全整数最小单位保持精确金额,不负责汇率换算。
|
|
138
|
+
|
|
139
|
+
## 分段选择与拖动排序
|
|
140
|
+
|
|
141
|
+
- `SegmentedControl`:少量互斥选项,使用原生 radio 语义;见[分段控制器参数与示例](#分段控制器-segmentedcontrol)。
|
|
142
|
+
- `SortableList<T>`:items、getKey、getTextValue、renderItem、onReorder 和 aria-label 必填;支持 disabled、className、dragLabel。getKey 必须稳定且唯一,onReorder 返回新顺序,消费方更新受控 items 并持久化。使用 React Aria 的鼠标、触屏及键盘排序交互。
|
|
143
|
+
|
|
144
|
+
## 专题契约
|
|
145
|
+
|
|
146
|
+
- [成熟度迁移](maturity-migration.md):日期约束、MultiSelect、TreeSelect 多选、目录 TTL/刷新、服务端表格排序/选择/列显隐及通知队列。
|
|
147
|
+
- [弹窗插槽迁移](modal-shell-migration.md):固定 footer、正文滚动、ref 与样式迁移。
|
|
148
|
+
- [上传前处理](file-preparation.md):PreparedFileDropzone、useFilePreparation 与 FilePreparationDialog。
|
|
149
|
+
- [文档查看器](document-viewer.md):PDF.js/图片入口及资源生命周期。
|
|
150
|
+
- [文档与图片查看器 V2](document-viewer-v2.md):URL/Buffer 使用 PDFium;未发布候选增加 `renderer="headless"` 原生 React 叠层、受控页码与单页模式,并兼容图片、已有 PDF.js 对象、全部 V1 参数及组合导出,使用前核验安装版本。
|
|
151
|
+
|
|
152
|
+
## 分段控制器 SegmentedControl
|
|
153
|
+
|
|
154
|
+
适用于日/周/月、列表/卡片、字段状态等少量互斥选项。实际内容面板页签继续使用 RovingTabList/RovingTabPanel。
|
|
155
|
+
|
|
156
|
+
- 受控字符串泛型:`value`、`onChange(value)`、`options`(唯一 value、ReactNode label、可选 icon/disabled/aria-label)。不提供隐式默认选择;选项变化后由调用方维护有效 value。
|
|
157
|
+
- 必须提供组的 `aria-label`;只显示图标时将 label 设为 null,并提供选项的 `aria-label`。label 可组合文字、计数或说明,不放按钮、链接等交互元素。
|
|
158
|
+
- `variant="solid" | "soft"`:默认 solid 保留原实色样式;soft 使用浅底和浮起的选中项。
|
|
159
|
+
- `block` 默认 true,撑满容器并等宽;false 按内容收缩,仍受父容器宽度限制。`orientation="horizontal" | "vertical"` 默认 horizontal;`shape="default" | "round"` 默认 default。
|
|
160
|
+
- `size="compact" | "default" | "touch"`,默认 default;沿用 32/40/44px 尺寸体系,soft 另含轨道内边距,粗指针下每项点击高度至少 44px。
|
|
161
|
+
- 可传 name、disabled、className。未传 name 时每组生成独立名称;传 name 时参与原生 FormData,同一表单内不同组不要共用 name。
|
|
162
|
+
- 原生方向键切换并跳过禁用项,Space 选中;整组 disabled 不可操作。长标签窄屏省略但保留完整可访问名称。
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import { useState } from "react";
|
|
166
|
+
import { LayoutGrid, List } from "lucide-react";
|
|
167
|
+
import { SegmentedControl } from "@jc-times/business-ui";
|
|
168
|
+
import "@jc-times/business-ui/styles.css";
|
|
169
|
+
|
|
170
|
+
type View = "list" | "grid";
|
|
171
|
+
|
|
172
|
+
export function ViewSelector() {
|
|
173
|
+
const [view, setView] = useState<View>("list");
|
|
174
|
+
return <SegmentedControl<View> aria-label="显示方式" variant="soft" block={false}
|
|
175
|
+
value={view} onChange={setView}
|
|
176
|
+
options={[
|
|
177
|
+
{ value: "list", label: "列表", icon: <List/> },
|
|
178
|
+
{ value: "grid", label: "卡片", icon: <LayoutGrid/> },
|
|
179
|
+
]}/>;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
新增外观参数为本地待发布能力;旧版仅有受控字符串、禁用、name 和 size,消费前核对安装包声明。
|
|
184
|
+
|
|
185
|
+
### 外观与组合
|
|
186
|
+
|
|
187
|
+
| 需求 | 配置 | 行为 |
|
|
188
|
+
| --- | --- | --- |
|
|
189
|
+
| 保持原有字段单选外观 | 不传新增参数 | solid、block=true、horizontal、default 形状 |
|
|
190
|
+
| 工具栏中的浅底视图切换 | variant="soft"、block={false} | 按内容收缩,选中项使用 surface 背景 |
|
|
191
|
+
| 整行等宽 | block 或省略 block | 横向选项等分可用宽度 |
|
|
192
|
+
| 胶囊 | shape="round" | 轨道与选项使用圆角形状 |
|
|
193
|
+
| 纵向 | orientation="vertical" | 每项独占一行,组内选项同宽 |
|
|
194
|
+
| 仅显示图标 | option.label=null、icon、option["aria-label"] | 图标不参与读屏命名,由选项 aria-label 提供名称 |
|
|
195
|
+
| 自定义文字与计数 | option.label 为 ReactNode | 消费方组合非交互内容;长文字可能截断 |
|
|
196
|
+
| 单项禁用 / 整组禁用 | option.disabled / disabled | 原生 radio 禁用,键盘跳过禁用项 |
|
|
197
|
+
|
|
198
|
+
以下示例放在持有 `view` / `setView` 的 React 组件中:
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
<SegmentedControl<View> aria-label="显示方式" variant="soft" shape="round" block={false}
|
|
202
|
+
value={view} onChange={setView}
|
|
203
|
+
options={[
|
|
204
|
+
{ value: "list", label: null, icon: <List/>, "aria-label": "列表" },
|
|
205
|
+
{ value: "grid", label: null, icon: <LayoutGrid/>, "aria-label": "卡片" },
|
|
206
|
+
]}/>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 状态、表单与兼容边界
|
|
210
|
+
|
|
211
|
+
- 只支持字符串 value 和对象数组 options;没有 `defaultValue`、数字值、字符串数组简写或非受控模式。参数名称和默认值以本包为准,不直接套用其他组件库的 Segmented API。
|
|
212
|
+
- `onChange` 在用户选择新项时通知,调用方必须更新 value。空 options 或 value 不在选项中时不会自动选中首项,也不会自动触发回调。
|
|
213
|
+
- 选择视图模式仍是 radio 语义;需要 tab/tabpanel 关联及页签焦点模型时,使用 `RovingTabList` + `RovingTabPanel`。
|
|
214
|
+
- 原生 FormData 只包含提供 name 且已选中、未禁用的 radio;业务状态提交仍可直接读取 value。表单 reset 不会替调用方重置受控状态。
|
|
215
|
+
- 组 aria-label 与选项名称分别提供;纯图标选项的 aria-label 不产生可见提示。若文字被截断会影响辨认,优先减少选项或改用纵向布局/Select。
|
|
216
|
+
- className 作用于组容器;颜色通过 `--ui-*` 主题令牌统一配置。当前未提供 ref、任意原生属性透传、选项 tooltip 或选中滑块动画。
|
|
217
|
+
|
|
218
|
+
维护时在视觉矩阵「表单控件 → 视图切换」查看组合效果;完整变体验证页为 `e2e/segmented.html`,验收要求见[多视口验收](viewport-qa.md)。
|
|
219
|
+
|
|
220
|
+
## Cascader 通用级联选择
|
|
221
|
+
|
|
222
|
+
RC Cascader 内核,支持单多选、路径搜索、独立/联动勾选及按需加载。完整公共约定、部门 ID 适配与地址迁移见 [级联选择](cascader.md)。
|
|
223
|
+
|
|
224
|
+
### Headless PDF 0.2.33
|
|
225
|
+
|
|
226
|
+
features.search/textSelection/pinchZoom 均默认开启。zoom/rotation 可受控,onZoomChange/onRotationChange 回传视口变化;showToolbar=false 可使用外部工具栏。pageRotation(page) 提供逐页额外角度,focusTarget={page,y,token} 定位归一化纵向位置。交互叠层标记 data-pdf-business-control,源身份变化时更新 source.id。
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
### PDFium 专用构建入口(0.2.34)
|
|
230
|
+
|
|
231
|
+
只使用原生 PDF 叠层的页面可从 `@jc-times/business-ui/pdfium-viewer` 导入 `PdfiumViewer`,参数与 Headless 模式一致,但省略 `renderer`。该入口不引入 PDF.js 兼容渲染或完整查看器外壳,适用于独立公开查看页面;引擎仍按需加载。通过 `engineOptions.wasmUrl` 提供本地资源的绝对 URL,保证 Blob worker 可解析;同一 `source.kind/id` 维持会话,文件版本改变时必须改变 `id`。
|
|
232
|
+
|
|
233
|
+
PDFium 专用入口支持 `initialZoom="fit-width"`(0.2.37):无受控 zoom 时由官方插件适配页面宽度;旧默认 100% 保持不变。
|
|
234
|
+
|
|
235
|
+
### PDFium 0.2.44
|
|
236
|
+
PdfiumViewer 支持 defaultRailCollapsed:传 true 默认收起页面侧栏,用户仍可打开。省略保留按视口初始化的行为。双指缩放逐帧提交到 PDFium 的范围和精度约束,松手保持最后比例;Ctrl/Meta+滚轮继续使用官方手势。
|
|
237
|
+
|
|
238
|
+
### PDFium 0.2.46 — 2026-09-14
|
|
239
|
+
保留官方 ZoomGestureWrapper 的触屏和 Ctrl/Meta+滚轮 CSS 位图预览,结束后只提交一次引擎缩放。移除0.2.44的逐帧触屏实现。修复可见页码回报被当作外部跳页命令导致的缩放后跳页。官方2.15.0预览缺少边界参数,通过精确 pnpm patch 补齐 minZoom/maxZoom 并对齐提交精度;消费方无需自行打补丁,库构建仅内联该 React 手势入口,PDFium/插件状态仍保持外部单例。补丁责任人为公共文档组件维护者,2026-10-14复核;上游具备等价能力并通过同组回归后删除补丁。
|
|
240
|
+
|
|
241
|
+
### SortableList 目标项接收(0.2.49)
|
|
242
|
+
|
|
243
|
+
可选 `onDropOnItem(moving, target)` 启用同一列表内拖到目标项;`canDropOnItem(moving, target)` 决定哪些目标可接收。组件保留前后排序、鼠标/触屏/键盘交互、目标高亮与取消行为,不接收外部拖入的数据,不自行变更分组或请求接口。输入均来自当前受控 items;自投、缺失来源、目标或禁用状态不回调。消费方在回调中用当前文档所有者与业务规则重新核验,再更新分组与持久化。
|
|
244
|
+
|
|
241
245
|
### SortableList 空列表与移动上下文(0.2.54)
|
|
242
|
-
|
|
243
|
-
新增 `listId`、`onDropOnList(moving, context)`、`canDropOnList(moving)`、`renderEmptyState()`;现有 onDropOnItem/onDropBetweenItems 末尾追加含 sourceListId/targetListId 的 context,旧回调兼容。disabled 切换保留卡片内部状态。接口、边界与示例见 [拖动专题](sortable-list.md)。
|
|
244
|
-
|
|
245
|
-
### SortableList 跨区块移动(0.2.50)
|
|
246
|
-
同一业务编辑范围用 `useSortableTransferScope<T>(ownerKey)` 创建并共享 `transferScope`;嵌套列表必须使用同一种 T,范围内每个列表拥有的 key 不重复。ownerKey 改变即隔离旧拖动。`onDropBetweenItems(moving,target,position)` / `canDropBetweenItems` 处理跨列表的 before/after,`onDropOnItem` 处理放入容器,原 `onReorder` 保留同列表排序。消费者一次性更新来源和目标,拖动过程中不移除来源。来源自动保留占位(可用 draggingLabel 修改文案)、目标沿用 React Aria 插入线和目标高亮。未共享同一对象的列表和外部拖入不接受;来源/目标失效、禁用、重复目标键不提交。来源清理和目标注册由组件持有。
|
|
247
|
-
|
|
248
|
-
## MultilineAutoComplete (0.2.51)
|
|
249
|
-
Controlled value/onChange, items/onSelect, label or aria-label, placeholder, disabled/loading, onFocus/onBlur, helpText and portalContainer. Composes React Aria Autocomplete, TextField/TextArea, Popover and ListBox. Async items open while focused; selection is explicit. Free text and unmatched Enter newlines are retained. Network cancellation and domain mapping belong to the consumer.
|
|
246
|
+
|
|
247
|
+
新增 `listId`、`onDropOnList(moving, context)`、`canDropOnList(moving)`、`renderEmptyState()`;现有 onDropOnItem/onDropBetweenItems 末尾追加含 sourceListId/targetListId 的 context,旧回调兼容。disabled 切换保留卡片内部状态。接口、边界与示例见 [拖动专题](sortable-list.md)。
|
|
248
|
+
|
|
249
|
+
### SortableList 跨区块移动(0.2.50)
|
|
250
|
+
同一业务编辑范围用 `useSortableTransferScope<T>(ownerKey)` 创建并共享 `transferScope`;嵌套列表必须使用同一种 T,范围内每个列表拥有的 key 不重复。ownerKey 改变即隔离旧拖动。`onDropBetweenItems(moving,target,position)` / `canDropBetweenItems` 处理跨列表的 before/after,`onDropOnItem` 处理放入容器,原 `onReorder` 保留同列表排序。消费者一次性更新来源和目标,拖动过程中不移除来源。来源自动保留占位(可用 draggingLabel 修改文案)、目标沿用 React Aria 插入线和目标高亮。未共享同一对象的列表和外部拖入不接受;来源/目标失效、禁用、重复目标键不提交。来源清理和目标注册由组件持有。
|
|
251
|
+
|
|
252
|
+
## MultilineAutoComplete (0.2.51)
|
|
253
|
+
Controlled value/onChange, items/onSelect, label or aria-label, placeholder, disabled/loading, onFocus/onBlur, helpText and portalContainer. Composes React Aria Autocomplete, TextField/TextArea, Popover and ListBox. Async items open while focused; selection is explicit. Free text and unmatched Enter newlines are retained. Network cancellation and domain mapping belong to the consumer.
|