@godxjp/ui 20.2.0 → 21.0.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/dist/components/data-display/chat-bubble.d.ts +30 -0
- package/dist/components/data-display/chat-bubble.js +229 -0
- package/dist/components/data-display/descriptions.js +4 -1
- package/dist/components/data-display/index.d.ts +4 -2
- package/dist/components/data-display/index.js +5 -2
- package/dist/components/data-display/popover.js +3 -2
- package/dist/components/data-display/scroll-area.js +26 -1
- package/dist/components/data-display/tree.d.ts +8 -0
- package/dist/components/data-display/tree.js +426 -0
- package/dist/components/data-entry/chat-composer.d.ts +50 -0
- package/dist/components/data-entry/chat-composer.js +163 -0
- package/dist/components/data-entry/chat-suggestion.d.ts +28 -0
- package/dist/components/data-entry/chat-suggestion.js +285 -0
- package/dist/components/data-entry/index.d.ts +4 -0
- package/dist/components/data-entry/index.js +4 -0
- package/dist/components/data-entry/textarea.js +3 -1
- package/dist/components/data-entry/tree-utils.d.ts +10 -48
- package/dist/components/data-entry/tree-utils.js +1 -154
- package/dist/components/layout/org-switcher.js +22 -2
- package/dist/i18n/messages/en.json +50 -0
- package/dist/i18n/messages/ja.json +48 -0
- package/dist/i18n/messages/vi.json +49 -0
- package/dist/lib/tree.d.ts +53 -0
- package/dist/lib/tree.js +155 -0
- package/dist/props/components/data-display.prop.d.ts +187 -1
- package/dist/props/components/data-entry.prop.d.ts +127 -0
- package/dist/props/registry.d.ts +140 -3
- package/dist/props/registry.js +202 -3
- package/dist/styles/control.css +7 -0
- package/dist/styles/data-display-layout.css +309 -55
- package/dist/styles/data-entry-layout.css +64 -0
- package/dist/styles/shell-layout.css +41 -11
- package/dist/tokens/base.css +3 -0
- package/dist/tokens/components/chat-bubble.css +36 -0
- package/dist/tokens/components/chat-composer.css +19 -0
- package/dist/tokens/components/data-display.css +0 -6
- package/dist/tokens/components/descriptions.css +4 -0
- package/dist/tokens/components/shell.css +13 -3
- package/dist/tokens/components/tree.css +27 -0
- package/docs/FRAME-COVERAGE-LEDGER.md +1 -1
- package/docs/FRAME-COVERAGE-REPORT.md +8 -3
- package/docs/data-display/chat-bubble.tsx +397 -0
- package/docs/data-display/timeline.tsx +46 -0
- package/docs/data-display/tree.tsx +394 -0
- package/docs/data-entry/chat-composer.tsx +464 -0
- package/docs/data-entry/chat-suggestion.tsx +301 -0
- package/docs/roadmap/ai-chat-components.md +207 -0
- package/docs/roadmap/antd-parity.md +154 -0
- package/docs/roadmap/badge-tag-chip-count.md +172 -0
- package/docs/roadmap/list-masonry.md +159 -0
- package/docs/roadmap/parity-audit-data-display-feedback.md +567 -0
- package/docs/roadmap/parity-audit-data-entry.md +344 -0
- package/docs/roadmap/parity-audit-layout-navigation-general.md +464 -0
- package/docs/roadmap/parity-backlog.md +79 -0
- package/docs/roadmap/tree-components.md +151 -0
- package/docs/showcase/table-tree-rows.tsx +4 -4
- package/package.json +5 -3
- package/dist/components/data-display/tree-list.d.ts +0 -13
- package/dist/components/data-display/tree-list.js +0 -26
- package/docs/data-display/tree-list.tsx +0 -107
|
@@ -159,6 +159,21 @@
|
|
|
159
159
|
"error": "入力エラー",
|
|
160
160
|
"validating": "確認中",
|
|
161
161
|
"submitFailed": "フォームを送信できませんでした。再試行してください。"
|
|
162
|
+
},
|
|
163
|
+
"chatComposer": {
|
|
164
|
+
"label": "メッセージ",
|
|
165
|
+
"placeholder": "メッセージを入力",
|
|
166
|
+
"send": "メッセージを送信",
|
|
167
|
+
"cancel": "生成を停止",
|
|
168
|
+
"hintEnter": "Enter で送信 · Shift + Enter で改行",
|
|
169
|
+
"hintShiftEnter": "Shift + Enter で送信 · Enter で改行"
|
|
170
|
+
},
|
|
171
|
+
"chatSuggestion": {
|
|
172
|
+
"label": "候補",
|
|
173
|
+
"empty": "一致する候補がありません",
|
|
174
|
+
"count": {
|
|
175
|
+
"other": "候補 {count} 件"
|
|
176
|
+
}
|
|
162
177
|
}
|
|
163
178
|
},
|
|
164
179
|
"feedback": {
|
|
@@ -236,6 +251,11 @@
|
|
|
236
251
|
"deniedDescription": "閲覧するには管理者に権限の付与を依頼してください。",
|
|
237
252
|
"loading": "ロールを読み込み中…",
|
|
238
253
|
"noDetail": "ロールを選択すると詳細が表示されます"
|
|
254
|
+
},
|
|
255
|
+
"orgSwitcher": {
|
|
256
|
+
"hintMove": "移動",
|
|
257
|
+
"hintSelect": "選択",
|
|
258
|
+
"hintClose": "閉じる"
|
|
239
259
|
}
|
|
240
260
|
},
|
|
241
261
|
"dataDisplay": {
|
|
@@ -278,6 +298,13 @@
|
|
|
278
298
|
"progress": {
|
|
279
299
|
"ariaLabel": "進捗",
|
|
280
300
|
"breakdownSeparator": "、"
|
|
301
|
+
},
|
|
302
|
+
"tree": {
|
|
303
|
+
"expand": "展開",
|
|
304
|
+
"collapse": "折りたたむ",
|
|
305
|
+
"loading": "子ノードを読み込み中…",
|
|
306
|
+
"empty": "表示する項目がありません",
|
|
307
|
+
"selected": "選択中"
|
|
281
308
|
}
|
|
282
309
|
},
|
|
283
310
|
"ui": {
|
|
@@ -519,5 +546,26 @@
|
|
|
519
546
|
"textExamples": {
|
|
520
547
|
"preservedText": "プレーンテキスト",
|
|
521
548
|
"sampleText": "最初の行\n 字下げした行\n\n最後の行"
|
|
549
|
+
},
|
|
550
|
+
"chat": {
|
|
551
|
+
"bubble": {
|
|
552
|
+
"typing": "入力中",
|
|
553
|
+
"loading": "メッセージを読み込み中",
|
|
554
|
+
"you": "自分",
|
|
555
|
+
"assistant": "アシスタント",
|
|
556
|
+
"tone": {
|
|
557
|
+
"info": "情報",
|
|
558
|
+
"success": "成功",
|
|
559
|
+
"warning": "警告",
|
|
560
|
+
"destructive": "エラー"
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
"list": {
|
|
564
|
+
"label": "会話",
|
|
565
|
+
"jumpToLatest": "最新へ移動",
|
|
566
|
+
"newMessages": {
|
|
567
|
+
"other": "新着 {count} 件"
|
|
568
|
+
}
|
|
569
|
+
}
|
|
522
570
|
}
|
|
523
571
|
}
|
|
@@ -159,6 +159,22 @@
|
|
|
159
159
|
"error": "Không hợp lệ",
|
|
160
160
|
"validating": "Đang kiểm tra",
|
|
161
161
|
"submitFailed": "Không thể gửi biểu mẫu. Vui lòng thử lại."
|
|
162
|
+
},
|
|
163
|
+
"chatComposer": {
|
|
164
|
+
"label": "Tin nhắn",
|
|
165
|
+
"placeholder": "Nhập tin nhắn",
|
|
166
|
+
"send": "Gửi tin nhắn",
|
|
167
|
+
"cancel": "Dừng tạo câu trả lời",
|
|
168
|
+
"hintEnter": "Enter để gửi · Shift + Enter để xuống dòng",
|
|
169
|
+
"hintShiftEnter": "Shift + Enter để gửi · Enter để xuống dòng"
|
|
170
|
+
},
|
|
171
|
+
"chatSuggestion": {
|
|
172
|
+
"label": "Gợi ý",
|
|
173
|
+
"empty": "Không có gợi ý phù hợp",
|
|
174
|
+
"count": {
|
|
175
|
+
"one": "{count} gợi ý",
|
|
176
|
+
"other": "{count} gợi ý"
|
|
177
|
+
}
|
|
162
178
|
}
|
|
163
179
|
},
|
|
164
180
|
"feedback": {
|
|
@@ -236,6 +252,11 @@
|
|
|
236
252
|
"deniedDescription": "Hãy đề nghị quản trị viên cấp quyền truy cập.",
|
|
237
253
|
"loading": "Đang tải vai trò…",
|
|
238
254
|
"noDetail": "Chọn một vai trò để xem chi tiết"
|
|
255
|
+
},
|
|
256
|
+
"orgSwitcher": {
|
|
257
|
+
"hintMove": "Di chuyển",
|
|
258
|
+
"hintSelect": "Chọn",
|
|
259
|
+
"hintClose": "Đóng"
|
|
239
260
|
}
|
|
240
261
|
},
|
|
241
262
|
"dataDisplay": {
|
|
@@ -278,6 +299,13 @@
|
|
|
278
299
|
"progress": {
|
|
279
300
|
"ariaLabel": "Tiến độ",
|
|
280
301
|
"breakdownSeparator": ", "
|
|
302
|
+
},
|
|
303
|
+
"tree": {
|
|
304
|
+
"expand": "Mở rộng",
|
|
305
|
+
"collapse": "Thu gọn",
|
|
306
|
+
"loading": "Đang tải nút con…",
|
|
307
|
+
"empty": "Không có gì để hiển thị",
|
|
308
|
+
"selected": "Đã chọn"
|
|
281
309
|
}
|
|
282
310
|
},
|
|
283
311
|
"ui": {
|
|
@@ -519,5 +547,26 @@
|
|
|
519
547
|
"textExamples": {
|
|
520
548
|
"preservedText": "Văn bản thuần",
|
|
521
549
|
"sampleText": "Dòng đầu\n Dòng thụt vào\n\nDòng cuối"
|
|
550
|
+
},
|
|
551
|
+
"chat": {
|
|
552
|
+
"bubble": {
|
|
553
|
+
"typing": "Đang nhập…",
|
|
554
|
+
"loading": "Đang tải tin nhắn",
|
|
555
|
+
"you": "Bạn",
|
|
556
|
+
"assistant": "Trợ lý",
|
|
557
|
+
"tone": {
|
|
558
|
+
"info": "Thông tin",
|
|
559
|
+
"success": "Thành công",
|
|
560
|
+
"warning": "Cảnh báo",
|
|
561
|
+
"destructive": "Lỗi"
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
"list": {
|
|
565
|
+
"label": "Cuộc trò chuyện",
|
|
566
|
+
"jumpToLatest": "Đến tin mới nhất",
|
|
567
|
+
"newMessages": {
|
|
568
|
+
"other": "{count} tin nhắn mới"
|
|
569
|
+
}
|
|
570
|
+
}
|
|
522
571
|
}
|
|
523
572
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
/** Normalized tree node — the conventional `treeData` / Cascader `options` shape. */
|
|
3
|
+
export type TreeOption = {
|
|
4
|
+
value: string;
|
|
5
|
+
label: React.ReactNode;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
disableCheckbox?: boolean;
|
|
8
|
+
/** When false with `loadData`, shows expand affordance */
|
|
9
|
+
isLeaf?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Per-node glyph, drawn by `Tree` when `showIcon` is on. Carried through the normalizer so the
|
|
12
|
+
* page tree and the dropdown tree keep ONE node shape; `TreeSelect` simply never reads it.
|
|
13
|
+
*/
|
|
14
|
+
icon?: React.ReactNode;
|
|
15
|
+
children?: TreeOption[];
|
|
16
|
+
};
|
|
17
|
+
export type TreeFieldNames = {
|
|
18
|
+
label?: string;
|
|
19
|
+
value?: string;
|
|
20
|
+
children?: string;
|
|
21
|
+
};
|
|
22
|
+
export type NormalizedTreeOption = TreeOption & {
|
|
23
|
+
children?: NormalizedTreeOption[];
|
|
24
|
+
};
|
|
25
|
+
type RawTreeNode = Record<string, unknown>;
|
|
26
|
+
export declare function reactNodeText(value: React.ReactNode): string;
|
|
27
|
+
export declare function normalizeTreeOptions(nodes: RawTreeNode[] | undefined, fieldNames?: TreeFieldNames): NormalizedTreeOption[];
|
|
28
|
+
export declare function getNodeByPath(options: NormalizedTreeOption[], path: string[]): NormalizedTreeOption[];
|
|
29
|
+
export declare function getOptionsAtPath(options: NormalizedTreeOption[], path: string[]): NormalizedTreeOption[];
|
|
30
|
+
export declare function formatPathLabels(chain: NormalizedTreeOption[], separator?: string): string;
|
|
31
|
+
export type TreePath = {
|
|
32
|
+
path: string[];
|
|
33
|
+
labels: string[];
|
|
34
|
+
};
|
|
35
|
+
export declare function collectLeafPaths(options: NormalizedTreeOption[], prefix?: string[], root?: NormalizedTreeOption[]): TreePath[];
|
|
36
|
+
export declare function collectAllPaths(options: NormalizedTreeOption[], prefix?: string[], root?: NormalizedTreeOption[]): TreePath[];
|
|
37
|
+
export declare function pathKey(path: string[]): string;
|
|
38
|
+
export declare function pathsEqual(a: string[], b: string[]): boolean;
|
|
39
|
+
export declare function filterTreeOptions(options: NormalizedTreeOption[], query: string, filter?: (query: string, path: NormalizedTreeOption[]) => boolean): TreePath[];
|
|
40
|
+
export declare function getDescendantValues(node: NormalizedTreeOption): string[];
|
|
41
|
+
export declare function flattenVisibleTree(options: NormalizedTreeOption[], expandedKeys: Set<string>, depth?: number): {
|
|
42
|
+
node: NormalizedTreeOption;
|
|
43
|
+
depth: number;
|
|
44
|
+
hasChildren: boolean;
|
|
45
|
+
}[];
|
|
46
|
+
export declare function filterVisibleTree(options: NormalizedTreeOption[], query: string): {
|
|
47
|
+
node: NormalizedTreeOption;
|
|
48
|
+
depth: number;
|
|
49
|
+
hasChildren: boolean;
|
|
50
|
+
}[];
|
|
51
|
+
export declare function collectAllExpandableKeys(options: NormalizedTreeOption[]): string[];
|
|
52
|
+
export declare function findNodeByValue(options: NormalizedTreeOption[], value: string): NormalizedTreeOption | undefined;
|
|
53
|
+
export {};
|
package/dist/lib/tree.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
function reactNodeText(value) {
|
|
2
|
+
if (value == null || typeof value === "boolean") return "";
|
|
3
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
|
|
4
|
+
return String(value);
|
|
5
|
+
}
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
return value.map((item) => reactNodeText(item)).join("");
|
|
8
|
+
}
|
|
9
|
+
return "";
|
|
10
|
+
}
|
|
11
|
+
function unknownText(value) {
|
|
12
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint") {
|
|
13
|
+
return String(value);
|
|
14
|
+
}
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
function normalizeTreeOptions(nodes, fieldNames) {
|
|
18
|
+
if (!nodes?.length) return [];
|
|
19
|
+
const labelKey = fieldNames?.label ?? "label";
|
|
20
|
+
const valueKey = fieldNames?.value ?? "value";
|
|
21
|
+
const childrenKey = fieldNames?.children ?? "children";
|
|
22
|
+
return nodes.map((node) => {
|
|
23
|
+
const children = node[childrenKey];
|
|
24
|
+
const value = unknownText(node[valueKey]);
|
|
25
|
+
const label = node[labelKey];
|
|
26
|
+
return {
|
|
27
|
+
value,
|
|
28
|
+
label: label ?? value,
|
|
29
|
+
disabled: Boolean(node.disabled),
|
|
30
|
+
disableCheckbox: Boolean(node.disableCheckbox),
|
|
31
|
+
isLeaf: node.isLeaf,
|
|
32
|
+
icon: node.icon,
|
|
33
|
+
children: Array.isArray(children) ? normalizeTreeOptions(children, fieldNames) : void 0
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function getNodeByPath(options, path) {
|
|
38
|
+
const chain = [];
|
|
39
|
+
let level = options;
|
|
40
|
+
for (const segment of path) {
|
|
41
|
+
const found = level.find((n) => n.value === segment);
|
|
42
|
+
if (!found) break;
|
|
43
|
+
chain.push(found);
|
|
44
|
+
level = found.children ?? [];
|
|
45
|
+
}
|
|
46
|
+
return chain;
|
|
47
|
+
}
|
|
48
|
+
function getOptionsAtPath(options, path) {
|
|
49
|
+
if (!path.length) return options;
|
|
50
|
+
const chain = getNodeByPath(options, path);
|
|
51
|
+
return chain.at(-1)?.children ?? [];
|
|
52
|
+
}
|
|
53
|
+
function formatPathLabels(chain, separator = " / ") {
|
|
54
|
+
return chain.map((n) => reactNodeText(n.label)).join(separator);
|
|
55
|
+
}
|
|
56
|
+
function collectLeafPaths(options, prefix = [], root = options) {
|
|
57
|
+
const out = [];
|
|
58
|
+
for (const node of options) {
|
|
59
|
+
const path = [...prefix, node.value];
|
|
60
|
+
const hasChildren = (node.children?.length ?? 0) > 0;
|
|
61
|
+
if (!hasChildren || node.isLeaf === true) {
|
|
62
|
+
out.push({ path, labels: getNodeByPath(root, path).map((n) => reactNodeText(n.label)) });
|
|
63
|
+
}
|
|
64
|
+
if (hasChildren) out.push(...collectLeafPaths(node.children, path, root));
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function collectAllPaths(options, prefix = [], root = options) {
|
|
69
|
+
const out = [];
|
|
70
|
+
for (const node of options) {
|
|
71
|
+
const path = [...prefix, node.value];
|
|
72
|
+
out.push({ path, labels: getNodeByPath(root, path).map((n) => reactNodeText(n.label)) });
|
|
73
|
+
if (node.children?.length) out.push(...collectAllPaths(node.children, path, root));
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
function pathKey(path) {
|
|
78
|
+
return path.join("\0");
|
|
79
|
+
}
|
|
80
|
+
function pathsEqual(a, b) {
|
|
81
|
+
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
82
|
+
}
|
|
83
|
+
function filterTreeOptions(options, query, filter) {
|
|
84
|
+
const q = query.trim().toLowerCase();
|
|
85
|
+
if (!q) return [];
|
|
86
|
+
const paths = collectLeafPaths(options);
|
|
87
|
+
return paths.filter(({ path }) => {
|
|
88
|
+
const chain = getNodeByPath(options, path);
|
|
89
|
+
if (filter) return filter(query, chain);
|
|
90
|
+
return chain.some((n) => reactNodeText(n.label).toLowerCase().includes(q));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function getDescendantValues(node) {
|
|
94
|
+
const values = [node.value];
|
|
95
|
+
for (const child of node.children ?? []) values.push(...getDescendantValues(child));
|
|
96
|
+
return values;
|
|
97
|
+
}
|
|
98
|
+
function flattenVisibleTree(options, expandedKeys, depth = 0) {
|
|
99
|
+
const out = [];
|
|
100
|
+
for (const node of options) {
|
|
101
|
+
const hasChildren = (node.children?.length ?? 0) > 0 && node.isLeaf !== true;
|
|
102
|
+
out.push({ node, depth, hasChildren });
|
|
103
|
+
if (hasChildren && expandedKeys.has(node.value)) {
|
|
104
|
+
out.push(...flattenVisibleTree(node.children, expandedKeys, depth + 1));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
function filterVisibleTree(options, query) {
|
|
110
|
+
const q = query.trim().toLowerCase();
|
|
111
|
+
if (!q) return flattenVisibleTree(options, new Set(collectAllExpandableKeys(options)));
|
|
112
|
+
function matches(nodes, depth) {
|
|
113
|
+
return nodes.flatMap((node) => {
|
|
114
|
+
const children = node.isLeaf ? [] : matches(node.children ?? [], depth + 1);
|
|
115
|
+
if (!reactNodeText(node.label).toLowerCase().includes(q) && children.length === 0) return [];
|
|
116
|
+
return [{ node, depth, hasChildren: children.length > 0 }, ...children];
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return matches(options, 0);
|
|
120
|
+
}
|
|
121
|
+
function collectAllExpandableKeys(options) {
|
|
122
|
+
const keys = [];
|
|
123
|
+
for (const node of options) {
|
|
124
|
+
if ((node.children?.length ?? 0) > 0 && node.isLeaf !== true) {
|
|
125
|
+
keys.push(node.value);
|
|
126
|
+
keys.push(...collectAllExpandableKeys(node.children));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return keys;
|
|
130
|
+
}
|
|
131
|
+
function findNodeByValue(options, value) {
|
|
132
|
+
for (const node of options) {
|
|
133
|
+
if (node.value === value) return node;
|
|
134
|
+
const nested = node.children ? findNodeByValue(node.children, value) : void 0;
|
|
135
|
+
if (nested) return nested;
|
|
136
|
+
}
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
139
|
+
export {
|
|
140
|
+
collectAllExpandableKeys,
|
|
141
|
+
collectAllPaths,
|
|
142
|
+
collectLeafPaths,
|
|
143
|
+
filterTreeOptions,
|
|
144
|
+
filterVisibleTree,
|
|
145
|
+
findNodeByValue,
|
|
146
|
+
flattenVisibleTree,
|
|
147
|
+
formatPathLabels,
|
|
148
|
+
getDescendantValues,
|
|
149
|
+
getNodeByPath,
|
|
150
|
+
getOptionsAtPath,
|
|
151
|
+
normalizeTreeOptions,
|
|
152
|
+
pathKey,
|
|
153
|
+
pathsEqual,
|
|
154
|
+
reactNodeText
|
|
155
|
+
};
|
|
@@ -28,7 +28,8 @@ export type ProseProp = {
|
|
|
28
28
|
className?: ClassNameProp;
|
|
29
29
|
children?: ChildrenProp;
|
|
30
30
|
};
|
|
31
|
-
import type { ActionProp, ClassNameProp, DescriptionProp, IconProp, TitleProp, ColumnDefProp, GetRowIdProp, OnRowClickProp, OnSelectChangeProp, OnSortChangeProp, OnTableDensityChangeProp, SelectedIdsProp, SortStateProp, TableDensityProp, TablePresetProp, BreakpointProp, DensityProp, ChildrenProp, ToneProp, AvatarShapeProp, HeadingLevelProp, HandlerProp, SizeProp, LabelProp, IdProp, DescriptionsLayoutProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, SortDirectionProp, OnColumnFilterChangeProp, OnRowProp, TableExpandableProp, TableRowSelectionProp, TableScrollProp, TableStickyProp, TableSummaryProp } from "../vocabulary/index.js";
|
|
31
|
+
import type { ActionProp, ClassNameProp, DescriptionProp, IconProp, TitleProp, ColumnDefProp, GetRowIdProp, OnRowClickProp, OnSelectChangeProp, OnSortChangeProp, OnTableDensityChangeProp, SelectedIdsProp, SortStateProp, TableDensityProp, TablePresetProp, BreakpointProp, DensityProp, ChildrenProp, PendingProp, ToneProp, AvatarShapeProp, HeadingLevelProp, HandlerProp, SizeProp, LabelProp, IdProp, DescriptionsLayoutProp, DescriptionsColumnProp, DescriptionsSpanProp, DescriptionsItemsProp, SortDirectionProp, OnColumnFilterChangeProp, OnRowProp, TableExpandableProp, TableRowSelectionProp, TableScrollProp, TableStickyProp, TableSummaryProp, DisabledProp, ValueProp, DefaultValueProp, OnValueChangeProp } from "../vocabulary/index.js";
|
|
32
|
+
import type { TreeFieldNamesProp, TreeOptionProp } from "./data-entry.prop.js";
|
|
32
33
|
/**
|
|
33
34
|
* One key in a `Legend`: a tone, and the words that tone stands for.
|
|
34
35
|
*
|
|
@@ -493,3 +494,188 @@ export type TimelineGridProp = {
|
|
|
493
494
|
className?: ClassNameProp;
|
|
494
495
|
id?: IdProp;
|
|
495
496
|
};
|
|
497
|
+
/**
|
|
498
|
+
* @see Tree — one node of the standalone, on-page tree view.
|
|
499
|
+
*
|
|
500
|
+
* Structurally the same node `TreeSelect`/`Cascader` take (one tree model, two surfaces — the
|
|
501
|
+
* normalizer lives in `src/lib/tree.ts`), plus the per-node glyph the ON-PAGE surface needs and a
|
|
502
|
+
* dropdown does not.
|
|
503
|
+
*/
|
|
504
|
+
export type TreeNodeProp = TreeOptionProp & {
|
|
505
|
+
/** Glyph drawn before the label when `showIcon` is on. Decorative — the label carries the name. */
|
|
506
|
+
icon?: React.ReactNode;
|
|
507
|
+
children?: TreeNodeProp[];
|
|
508
|
+
};
|
|
509
|
+
/**
|
|
510
|
+
* @see Tree — the WAI-ARIA APG "Tree View" on a page (Ant's `Tree` / `DirectoryTree`).
|
|
511
|
+
*
|
|
512
|
+
* `TreeSelect` is the same hierarchy inside a Popover. A flat indented list only LOOKS like a tree
|
|
513
|
+
* (that was `TreeList`, removed in 21.0.0 with `Tree` as its replacement), so reach for `Tree`
|
|
514
|
+
* whenever nodes expand, collapse, or are navigated by keyboard.
|
|
515
|
+
*
|
|
516
|
+
* Ant's key-shaped names are mapped onto this package's controlled vocabulary and NOT re-spelled:
|
|
517
|
+
* selection is `value`/`defaultValue`/`onValueChange`, expansion is
|
|
518
|
+
* `expandedValues`/`defaultExpandedValues`/`onExpandedValuesChange`, checks are
|
|
519
|
+
* `checkedValues`/`defaultCheckedValues`/`onCheckedValuesChange`.
|
|
520
|
+
* @see docs/roadmap/tree-components.md §3
|
|
521
|
+
*/
|
|
522
|
+
export type TreeProp = {
|
|
523
|
+
/** The hierarchy (antd `treeData`). Use `fieldNames` to remap keys off an API response. */
|
|
524
|
+
treeData: readonly TreeNodeProp[];
|
|
525
|
+
/** Remap the data's own key names (antd `fieldNames`). */
|
|
526
|
+
fieldNames?: TreeFieldNamesProp;
|
|
527
|
+
/** Controlled selection. `string` while single, `string[]` once `multiple` is on. */
|
|
528
|
+
value?: ValueProp<string | string[]>;
|
|
529
|
+
/** Uncontrolled initial selection (controlled-triad rule). */
|
|
530
|
+
defaultValue?: DefaultValueProp<string | string[]>;
|
|
531
|
+
/** Selection change. Emits `string | undefined` while single, `string[]` once `multiple` is on. */
|
|
532
|
+
onValueChange?: OnValueChangeProp<string | string[] | undefined>;
|
|
533
|
+
/** Allow more than one selected node (antd `multiple`). Also sets `aria-multiselectable`. */
|
|
534
|
+
multiple?: boolean;
|
|
535
|
+
/** Draw a checkbox on every node (antd `checkable`). Checks are a SEPARATE axis from selection. */
|
|
536
|
+
checkable?: boolean;
|
|
537
|
+
/** Parent and child checks are independent (antd `checkStrictly`) — no cascade, no `mixed`. */
|
|
538
|
+
checkStrictly?: boolean;
|
|
539
|
+
/** Controlled checked nodes (antd `checkedKeys`). */
|
|
540
|
+
checkedValues?: readonly string[];
|
|
541
|
+
/** Uncontrolled initial checked nodes (antd `defaultCheckedKeys`). */
|
|
542
|
+
defaultCheckedValues?: readonly string[];
|
|
543
|
+
/** Checked-set change (antd `onCheck`). Fires for controlled and uncontrolled trees alike. */
|
|
544
|
+
onCheckedValuesChange?: (values: string[]) => void;
|
|
545
|
+
/** Controlled expanded branches (antd `expandedKeys`). */
|
|
546
|
+
expandedValues?: readonly string[];
|
|
547
|
+
/** Uncontrolled initial expanded branches (antd `defaultExpandedKeys`). */
|
|
548
|
+
defaultExpandedValues?: readonly string[];
|
|
549
|
+
/** Expansion change (antd `onExpand`). Fires for controlled and uncontrolled trees alike. */
|
|
550
|
+
onExpandedValuesChange?: (values: string[]) => void;
|
|
551
|
+
/** Start with every branch open (antd `defaultExpandAll`). Seeded once, never re-applied. */
|
|
552
|
+
defaultExpandAll?: boolean;
|
|
553
|
+
/**
|
|
554
|
+
* Lazy children (antd `loadData`). Called ONCE per node the first time a branch with no
|
|
555
|
+
* `children` and `isLeaf !== true` is expanded; push the fetched children into `treeData`.
|
|
556
|
+
*/
|
|
557
|
+
loadData?: (node: TreeNodeProp) => void | Promise<void>;
|
|
558
|
+
/** Render a node's title (antd `titleRender`). */
|
|
559
|
+
titleRender?: (node: TreeNodeProp) => React.ReactNode;
|
|
560
|
+
/** Draw the connector rails between a parent and its children (antd `showLine`). */
|
|
561
|
+
showLine?: boolean;
|
|
562
|
+
/** Draw each node's `icon` (antd `showIcon`). `variant="directory"` supplies folder/file glyphs. */
|
|
563
|
+
showIcon?: boolean;
|
|
564
|
+
/** `directory` is antd's `<DirectoryTree>`: folder/file glyphs and a full-row selected band. */
|
|
565
|
+
variant?: "default" | "directory";
|
|
566
|
+
/** Row height tier — the shared `--control-height` ladder. Default `md`. */
|
|
567
|
+
size?: SizeProp;
|
|
568
|
+
/** Disable the whole tree: nothing selects, checks or expands; nodes stay readable. */
|
|
569
|
+
disabled?: DisabledProp;
|
|
570
|
+
className?: ClassNameProp;
|
|
571
|
+
id?: IdProp;
|
|
572
|
+
/** Accessible name of the `role="tree"` container. Required unless `aria-labelledby` is given. */
|
|
573
|
+
"aria-label"?: string;
|
|
574
|
+
"aria-labelledby"?: string;
|
|
575
|
+
};
|
|
576
|
+
/**
|
|
577
|
+
* @see ChatBubble — which side of the conversation the message sits on. LOGICAL, not physical:
|
|
578
|
+
* `start` is the inline start of the reading direction (left in `ltr`, right in `rtl`), so a feed
|
|
579
|
+
* flips correctly under `dir="rtl"` with no per-locale branch. `start` = the other party,
|
|
580
|
+
* `end` = the reader's own messages, which is the convention every chat client shares.
|
|
581
|
+
*/
|
|
582
|
+
export type ChatBubblePlacementProp = "start" | "end";
|
|
583
|
+
/**
|
|
584
|
+
* @see ChatBubble — STRUCTURAL treatment of the message body, orthogonal to `tone` (which owns
|
|
585
|
+
* colour). Ant Design X's `shadow` is deliberately absent: this design system is a 1px-border
|
|
586
|
+
* system with no drop shadows (docs/TOKENS.md).
|
|
587
|
+
*
|
|
588
|
+
* - `filled` (default) — the quiet `--chat-bubble-background` wash.
|
|
589
|
+
* - `outlined` — transparent body inside a 1px `--chat-bubble-border-color` edge.
|
|
590
|
+
* - `borderless` — no fill and no edge; long assistant prose that should read as page copy.
|
|
591
|
+
*/
|
|
592
|
+
export type ChatBubbleVariantProp = "filled" | "borderless" | "outlined";
|
|
593
|
+
/**
|
|
594
|
+
* @see ChatBubble — status intent for a message that is not ordinary conversation (a failed send,
|
|
595
|
+
* a rate-limit warning, a tool result). A subset of `ToneProp`: `muted` and `neutral` are not
|
|
596
|
+
* offered because a bubble is already the quiet surface, so they would name no distinct state.
|
|
597
|
+
*
|
|
598
|
+
* Never colour alone (WCAG 1.4.1): a toned bubble also renders a localized `sr-only` tone word.
|
|
599
|
+
*/
|
|
600
|
+
export type ChatBubbleToneProp = Extract<ToneProp, "default" | "info" | "success" | "warning" | "destructive">;
|
|
601
|
+
/**
|
|
602
|
+
* @see ChatBubble — the streaming type-on animation. `true` takes the defaults (1 character every
|
|
603
|
+
* 50ms); the object form retunes them per instance.
|
|
604
|
+
*
|
|
605
|
+
* It animates only when `children` is a plain string — a `ReactNode` has no character count to
|
|
606
|
+
* reveal — and it is DROPPED ENTIRELY under `prefers-reduced-motion: reduce`, which renders the
|
|
607
|
+
* full text immediately (WCAG 2.2 SC 2.3.3).
|
|
608
|
+
*/
|
|
609
|
+
export type ChatBubbleTypingProp = boolean | {
|
|
610
|
+
step?: number;
|
|
611
|
+
interval?: number;
|
|
612
|
+
};
|
|
613
|
+
/** @see ChatBubble — one message in a conversation. */
|
|
614
|
+
export type ChatBubbleProp = {
|
|
615
|
+
/** The message. A `ReactNode`; pass a plain string to make `typing` animatable. */
|
|
616
|
+
children?: ChildrenProp;
|
|
617
|
+
/** Which side of the feed the message sits on. Default `start`. */
|
|
618
|
+
placement?: ChatBubblePlacementProp;
|
|
619
|
+
/** Structural treatment of the body. Default `filled`. */
|
|
620
|
+
variant?: ChatBubbleVariantProp;
|
|
621
|
+
/**
|
|
622
|
+
* The author's mark — a real `<Avatar>` node, never a styled div. It is decorative when the
|
|
623
|
+
* `header` already names the author, so mark it `aria-hidden` at the call site.
|
|
624
|
+
*/
|
|
625
|
+
avatar?: ChildrenProp;
|
|
626
|
+
/**
|
|
627
|
+
* Line above the body — the author, and anything that identifies the turn. When it is present
|
|
628
|
+
* the bubble takes its ACCESSIBLE NAME from it, so keep it text.
|
|
629
|
+
*/
|
|
630
|
+
header?: ChildrenProp;
|
|
631
|
+
/** Line below the body — timestamps, per-message actions, token counts. */
|
|
632
|
+
footer?: ChildrenProp;
|
|
633
|
+
/** The reply has been requested and has not arrived: renders `Skeleton`, sets `aria-busy`. */
|
|
634
|
+
loading?: PendingProp;
|
|
635
|
+
/** Stream the text in character by character. Honours `prefers-reduced-motion`. */
|
|
636
|
+
typing?: ChatBubbleTypingProp;
|
|
637
|
+
/** Type step and inner inset. Default `md`. */
|
|
638
|
+
size?: SizeProp;
|
|
639
|
+
/** Status intent. Default `default`. */
|
|
640
|
+
tone?: ChatBubbleToneProp;
|
|
641
|
+
className?: ClassNameProp;
|
|
642
|
+
id?: IdProp;
|
|
643
|
+
};
|
|
644
|
+
/** @see ChatBubbleList — one entry of the feed: a `ChatBubble`'s own props plus its identity. */
|
|
645
|
+
export type ChatMessageProp = Omit<ChatBubbleProp, "children" | "id"> & {
|
|
646
|
+
/** Stable message id. Also the React key and the rendered `<article>`'s DOM id. */
|
|
647
|
+
id: IdProp;
|
|
648
|
+
/** Key into the list's `roles` map — `"user"`, `"assistant"`, `"system"`, or your own. */
|
|
649
|
+
role?: string;
|
|
650
|
+
/** The message body. Named `content` here because `children` is not a data field. */
|
|
651
|
+
content?: ChildrenProp;
|
|
652
|
+
};
|
|
653
|
+
/**
|
|
654
|
+
* @see ChatBubbleList — the message feed.
|
|
655
|
+
*
|
|
656
|
+
* It scrolls inside itself, so it needs a DEFINITE height from the caller (`className="h-96"`, or
|
|
657
|
+
* a flex/grid parent that gives it a track). Without one it grows to its content and nothing ever
|
|
658
|
+
* overflows, which silently disables `autoScroll` and the jump-to-latest affordance.
|
|
659
|
+
*/
|
|
660
|
+
export type ChatBubbleListProp = {
|
|
661
|
+
/** Messages in conversation order, oldest first. */
|
|
662
|
+
items: readonly ChatMessageProp[];
|
|
663
|
+
/**
|
|
664
|
+
* Per-role bubble defaults, merged UNDER each message's own props. This is what keeps a feed
|
|
665
|
+
* consistent: `{ assistant: { placement: "start", variant: "filled" }, user: { placement:
|
|
666
|
+
* "end" } }` is written once instead of on every message.
|
|
667
|
+
*/
|
|
668
|
+
roles?: Record<string, Partial<ChatBubbleProp>>;
|
|
669
|
+
/**
|
|
670
|
+
* Keep the newest message in view while the reader is already at the bottom. Default `true`.
|
|
671
|
+
*
|
|
672
|
+
* It is NOT "scroll to the bottom when content arrives": the moment the reader scrolls up the
|
|
673
|
+
* pin is revoked and a focusable "jump to latest" affordance appears instead, because yanking a
|
|
674
|
+
* reader back mid-sentence is a change of context they did not request (WCAG 3.2.5).
|
|
675
|
+
*/
|
|
676
|
+
autoScroll?: boolean;
|
|
677
|
+
/** Accessible name of the feed. A plain string — it lands on `aria-label`. Defaults via `t()`. */
|
|
678
|
+
label?: Extract<LabelProp, string>;
|
|
679
|
+
className?: ClassNameProp;
|
|
680
|
+
id?: IdProp;
|
|
681
|
+
};
|