@rainbow-oh/yee-c 0.6.4 → 0.8.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/cjs/Button/style/index.less +5 -4
- package/dist/cjs/Drawer/drawer.js +1 -1
- package/dist/cjs/Drawer/interface.d.ts +1 -1
- package/dist/cjs/Drawer/style/index.less +1 -0
- package/dist/cjs/Form/form-store.d.ts +2 -1
- package/dist/cjs/Form/form-store.js +32 -17
- package/dist/cjs/List/demo/virtual.d.ts +3 -0
- package/dist/cjs/List/demo/virtual.js +53 -0
- package/dist/cjs/List/hooks/useListKeyboard.d.ts +28 -0
- package/dist/cjs/List/hooks/useListKeyboard.js +188 -0
- package/dist/cjs/List/interface.d.ts +29 -2
- package/dist/cjs/List/list.js +141 -21
- package/dist/cjs/List/style/index.less +24 -0
- package/dist/cjs/Select/demo/columns.d.ts +3 -0
- package/dist/cjs/Select/demo/columns.js +62 -0
- package/dist/cjs/Select/hooks/useSelectKeyboard.d.ts +13 -1
- package/dist/cjs/Select/hooks/useSelectKeyboard.js +81 -10
- package/dist/cjs/Select/interface.d.ts +30 -3
- package/dist/cjs/Select/option.js +4 -3
- package/dist/cjs/Select/options.js +90 -8
- package/dist/cjs/Select/select.js +32 -8
- package/dist/cjs/Select/style/index.less +14 -0
- package/dist/cjs/Selector/interface.d.ts +4 -0
- package/dist/cjs/Selector/selector.js +5 -3
- package/dist/cjs/Table/hooks/useColumns.js +1 -1
- package/dist/cjs/Table/interface.d.ts +1 -1
- package/dist/cjs/Table/style/index.less +35 -11
- package/dist/cjs/Table/table.js +57 -7
- package/dist/cjs/Table/tbody/cell.js +1 -1
- package/dist/cjs/Table/util/header.d.ts +3 -1
- package/dist/cjs/Table/util/header.js +30 -3
- package/dist/cjs/Tree/demo/draggable.js +2 -0
- package/dist/cjs/Tree/interface.d.ts +46 -23
- package/dist/cjs/Tree/tree-node.d.ts +1 -1
- package/dist/cjs/Tree/tree-node.js +30 -23
- package/dist/cjs/Tree/tree.d.ts +13 -12
- package/dist/cjs/Tree/tree.js +452 -227
- package/dist/cjs/Tree/utils/tree-tools.d.ts +43 -10
- package/dist/cjs/Tree/utils/tree-tools.js +129 -91
- package/dist/cjs/locale/context.d.ts +5 -4
- package/dist/cjs/locale/context.js +15 -8
- package/dist/cjs/locale/interface.d.ts +20 -0
- package/dist/cjs/locale/util.d.ts +3 -3
- package/dist/cjs/style/color.css +3 -0
- package/dist/cjs/style/size.css +2 -1
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +6 -2
- package/dist/cjs/utils/isEqual.js +5 -7
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Button/style/index.less +5 -4
- package/dist/esm/Drawer/drawer.js +2 -1
- package/dist/esm/Drawer/interface.d.ts +1 -1
- package/dist/esm/Drawer/style/index.less +1 -0
- package/dist/esm/Form/form-store.d.ts +2 -1
- package/dist/esm/Form/form-store.js +40 -19
- package/dist/esm/List/demo/virtual.d.ts +3 -0
- package/dist/esm/List/demo/virtual.js +22 -0
- package/dist/esm/List/hooks/useListKeyboard.d.ts +28 -0
- package/dist/esm/List/hooks/useListKeyboard.js +173 -0
- package/dist/esm/List/interface.d.ts +29 -2
- package/dist/esm/List/list.js +171 -14
- package/dist/esm/List/style/index.less +24 -0
- package/dist/esm/Select/demo/columns.d.ts +3 -0
- package/dist/esm/Select/demo/columns.js +36 -0
- package/dist/esm/Select/hooks/useSelectKeyboard.d.ts +13 -1
- package/dist/esm/Select/hooks/useSelectKeyboard.js +91 -14
- package/dist/esm/Select/interface.d.ts +30 -3
- package/dist/esm/Select/option.js +6 -2
- package/dist/esm/Select/options.js +114 -32
- package/dist/esm/Select/select.js +40 -11
- package/dist/esm/Select/style/index.less +14 -0
- package/dist/esm/Selector/interface.d.ts +4 -0
- package/dist/esm/Selector/selector.js +10 -4
- package/dist/esm/Table/hooks/useColumns.js +1 -1
- package/dist/esm/Table/interface.d.ts +1 -1
- package/dist/esm/Table/style/index.less +35 -11
- package/dist/esm/Table/table.js +54 -2
- package/dist/esm/Table/tbody/cell.js +1 -1
- package/dist/esm/Table/util/header.d.ts +3 -1
- package/dist/esm/Table/util/header.js +30 -2
- package/dist/esm/Tree/demo/draggable.js +2 -0
- package/dist/esm/Tree/interface.d.ts +46 -23
- package/dist/esm/Tree/tree-node.d.ts +1 -1
- package/dist/esm/Tree/tree-node.js +26 -31
- package/dist/esm/Tree/tree.d.ts +13 -12
- package/dist/esm/Tree/tree.js +572 -163
- package/dist/esm/Tree/utils/tree-tools.d.ts +43 -10
- package/dist/esm/Tree/utils/tree-tools.js +219 -104
- package/dist/esm/locale/context.d.ts +5 -4
- package/dist/esm/locale/context.js +25 -9
- package/dist/esm/locale/interface.d.ts +20 -0
- package/dist/esm/locale/util.d.ts +3 -3
- package/dist/esm/style/color.css +3 -0
- package/dist/esm/style/size.css +2 -1
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +6 -2
- package/dist/esm/utils/isEqual.js +5 -7
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +4 -4
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Button/style/index.less +5 -4
- package/src/Drawer/drawer.tsx +1 -1
- package/src/Drawer/interface.ts +1 -0
- package/src/Drawer/style/index.less +1 -0
- package/src/Form/form-store.ts +42 -15
- package/src/List/demo/virtual.tsx +20 -0
- package/src/List/hooks/useListKeyboard.ts +235 -0
- package/src/List/index.en-US.md +6 -0
- package/src/List/index.zh-CN.md +6 -0
- package/src/List/interface.ts +29 -2
- package/src/List/list.tsx +157 -19
- package/src/List/style/index.less +24 -0
- package/src/Select/demo/columns.tsx +35 -0
- package/src/Select/hooks/useSelectKeyboard.ts +112 -15
- package/src/Select/index.en-US.md +4 -0
- package/src/Select/index.zh-CN.md +4 -0
- package/src/Select/interface.ts +31 -4
- package/src/Select/option.tsx +9 -3
- package/src/Select/options.tsx +119 -26
- package/src/Select/select.tsx +41 -8
- package/src/Select/style/index.less +14 -0
- package/src/Selector/interface.ts +4 -0
- package/src/Selector/selector.tsx +8 -3
- package/src/Table/hooks/useColumns.ts +1 -1
- package/src/Table/interface.ts +1 -1
- package/src/Table/style/index.less +35 -11
- package/src/Table/table.tsx +60 -1
- package/src/Table/tbody/cell.tsx +1 -1
- package/src/Table/util/header.ts +48 -2
- package/src/Tree/demo/draggable.tsx +2 -0
- package/src/Tree/interface.ts +46 -23
- package/src/Tree/tree-node.tsx +26 -29
- package/src/Tree/tree.tsx +573 -274
- package/src/Tree/utils/tree-tools.ts +231 -125
- package/src/locale/_README.md +22 -13
- package/src/locale/context.tsx +33 -16
- package/src/locale/interface.ts +24 -0
- package/src/locale/util.ts +6 -6
- package/src/style/color.css +3 -0
- package/src/style/size.css +2 -1
- package/src/utils/isEqual.ts +5 -7
- package/src/version.ts +1 -1
|
@@ -4,6 +4,17 @@ export interface MoveInfo {
|
|
|
4
4
|
dragKey: string | number;
|
|
5
5
|
dropKey: string | number;
|
|
6
6
|
position: DragPosition;
|
|
7
|
+
/**
|
|
8
|
+
* Full key path from root to the dragged node (inclusive).
|
|
9
|
+
* When provided, enables precise matching even with non-unique keys.
|
|
10
|
+
* Example: ['root', 'parent', 'child']
|
|
11
|
+
*/
|
|
12
|
+
dragPath?: Array<string | number>;
|
|
13
|
+
/**
|
|
14
|
+
* Full key path from root to the drop target node (inclusive).
|
|
15
|
+
* When provided, enables precise matching even with non-unique keys.
|
|
16
|
+
*/
|
|
17
|
+
dropPath?: Array<string | number>;
|
|
7
18
|
}
|
|
8
19
|
/**
|
|
9
20
|
* Reorder the nested dataSource immutably after a drag.
|
|
@@ -13,6 +24,10 @@ export interface MoveInfo {
|
|
|
13
24
|
* nodes are reused by reference (data may carry non-cloneable values like
|
|
14
25
|
* React elements / functions in `icon`).
|
|
15
26
|
*
|
|
27
|
+
* When `dragPath` / `dropPath` are provided in `info`, matching is done by
|
|
28
|
+
* walking the exact path (supports non-unique keys). Otherwise falls back to
|
|
29
|
+
* first-match by key (backward compatible).
|
|
30
|
+
*
|
|
16
31
|
* Returns a brand-new root array; returns the input unchanged if dragKey is
|
|
17
32
|
* not found or drag and drop resolve to the same location.
|
|
18
33
|
*/
|
|
@@ -20,20 +35,38 @@ export declare function moveTreeNode<T extends Record<string, unknown>>(tree: T
|
|
|
20
35
|
key: keyof T;
|
|
21
36
|
children: keyof T;
|
|
22
37
|
}): T[];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Flatten tree into a flat array with rich metadata.
|
|
40
|
+
*
|
|
41
|
+
* Key design decisions:
|
|
42
|
+
* - Uses `uid` (built from the key path) as the internal identifier, because
|
|
43
|
+
* user-provided `key` values may NOT be globally unique across the tree.
|
|
44
|
+
* - The returned Map is keyed by `uid` for O(1) lookups.
|
|
45
|
+
* - `childUids` is collected bottom-up in a single pass (O(n) total) instead
|
|
46
|
+
* of per-node recursive enumeration (which was O(n²)).
|
|
47
|
+
*/
|
|
27
48
|
export declare function tree2array<T extends Record<string, unknown>>(tree: T | T[], fieldNames: {
|
|
28
49
|
key: keyof T;
|
|
29
50
|
label: keyof T;
|
|
30
51
|
children: keyof T;
|
|
31
52
|
}): [TreeNode<T>[], Map<string, TreeNode<T>>];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Check whether array `a` contains every element in `b`.
|
|
55
|
+
*/
|
|
56
|
+
export declare function containsAll<T>(a: Set<T>, b: Array<T>): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Remove all elements in `b` from `a`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function removeAll<T>(a: Set<T>, b: Array<T>): Set<T>;
|
|
61
|
+
/**
|
|
62
|
+
* Compute new checked uids when a node is toggled.
|
|
63
|
+
* Uses Set-based operations for O(1) membership checks.
|
|
64
|
+
* Disabled nodes are NOT affected by parent/child propagation — their checked
|
|
65
|
+
* state remains unchanged unless they are the directly toggled node.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getCheckedKeys({ checked, keys, uid, map, }: {
|
|
35
68
|
checked: boolean;
|
|
36
|
-
keys:
|
|
37
|
-
|
|
69
|
+
keys: Set<string>;
|
|
70
|
+
uid: string;
|
|
38
71
|
map: Map<string, TreeNode<unknown>>;
|
|
39
|
-
}):
|
|
72
|
+
}): Set<string>;
|
|
@@ -19,6 +19,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
|
|
|
19
19
|
* nodes are reused by reference (data may carry non-cloneable values like
|
|
20
20
|
* React elements / functions in `icon`).
|
|
21
21
|
*
|
|
22
|
+
* When `dragPath` / `dropPath` are provided in `info`, matching is done by
|
|
23
|
+
* walking the exact path (supports non-unique keys). Otherwise falls back to
|
|
24
|
+
* first-match by key (backward compatible).
|
|
25
|
+
*
|
|
22
26
|
* Returns a brand-new root array; returns the input unchanged if dragKey is
|
|
23
27
|
* not found or drag and drop resolve to the same location.
|
|
24
28
|
*/
|
|
@@ -28,12 +32,28 @@ export function moveTreeNode(tree, info, fieldNames) {
|
|
|
28
32
|
C = fieldNames.children;
|
|
29
33
|
var dragKey = info.dragKey,
|
|
30
34
|
dropKey = info.dropKey,
|
|
31
|
-
position = info.position
|
|
35
|
+
position = info.position,
|
|
36
|
+
dragPath = info.dragPath,
|
|
37
|
+
dropPath = info.dropPath;
|
|
32
38
|
var root = Array.isArray(tree) ? tree : [tree];
|
|
33
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Match a node: when a path is provided, match by comparing node key against
|
|
42
|
+
* the expected key at the current depth; otherwise match by key equality.
|
|
43
|
+
*/
|
|
44
|
+
var matchNode = function matchNode(node, targetKey, path, depth) {
|
|
45
|
+
if (path) {
|
|
46
|
+
return String(node[K]) === String(path[depth]);
|
|
47
|
+
}
|
|
48
|
+
return node[K] === targetKey;
|
|
49
|
+
};
|
|
50
|
+
var isTargetDepth = function isTargetDepth(path, depth) {
|
|
51
|
+
if (!path) return true; // no path constraint, match at any depth
|
|
52
|
+
return depth === path.length - 1;
|
|
53
|
+
};
|
|
54
|
+
|
|
34
55
|
// Phase 1: detach the drag node subtree (immutably).
|
|
35
|
-
|
|
36
|
-
var detach = function detach(nodes) {
|
|
56
|
+
var detach = function detach(nodes, depth) {
|
|
37
57
|
var found = null;
|
|
38
58
|
var next = [];
|
|
39
59
|
var _iterator = _createForOfIteratorHelper(nodes),
|
|
@@ -41,18 +61,22 @@ export function moveTreeNode(tree, info, fieldNames) {
|
|
|
41
61
|
try {
|
|
42
62
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
43
63
|
var n = _step.value;
|
|
44
|
-
if (n
|
|
45
|
-
found = n;
|
|
64
|
+
if (!found && matchNode(n, dragKey, dragPath, depth) && isTargetDepth(dragPath, depth)) {
|
|
65
|
+
found = n;
|
|
46
66
|
continue;
|
|
47
67
|
}
|
|
48
68
|
var kids = n[C];
|
|
49
|
-
if (Array.isArray(kids)) {
|
|
50
|
-
|
|
69
|
+
if (!found && dragPath && Array.isArray(kids) && !matchNode(n, dragKey, dragPath, depth)) {
|
|
70
|
+
// A path lets us skip branches that cannot contain the drag node.
|
|
71
|
+
next.push(n);
|
|
72
|
+
} else if (!found && Array.isArray(kids)) {
|
|
73
|
+
// On the drag path (or no path constraint), recurse
|
|
74
|
+
var r = detach(kids, depth + 1);
|
|
51
75
|
if (r.found) {
|
|
52
76
|
found = r.found;
|
|
53
77
|
next.push(_objectSpread(_objectSpread({}, n), {}, _defineProperty({}, C, r.nodes)));
|
|
54
78
|
} else {
|
|
55
|
-
next.push(n);
|
|
79
|
+
next.push(n);
|
|
56
80
|
}
|
|
57
81
|
} else {
|
|
58
82
|
next.push(n);
|
|
@@ -68,15 +92,13 @@ export function moveTreeNode(tree, info, fieldNames) {
|
|
|
68
92
|
nodes: next
|
|
69
93
|
};
|
|
70
94
|
};
|
|
71
|
-
var _detach = detach(root),
|
|
95
|
+
var _detach = detach(root, 0),
|
|
72
96
|
dragNode = _detach.found,
|
|
73
97
|
withoutDrag = _detach.nodes;
|
|
74
|
-
if (!dragNode) return root;
|
|
98
|
+
if (!dragNode) return root;
|
|
75
99
|
|
|
76
|
-
// Phase 2: insert per position
|
|
77
|
-
|
|
78
|
-
// follow the matched subtree must still be copied (by reference) or they'd be lost.
|
|
79
|
-
var insert = function insert(nodes) {
|
|
100
|
+
// Phase 2: insert per position.
|
|
101
|
+
var insert = function insert(nodes, depth) {
|
|
80
102
|
var next = [];
|
|
81
103
|
var inserted = false;
|
|
82
104
|
var _iterator2 = _createForOfIteratorHelper(nodes),
|
|
@@ -84,28 +106,31 @@ export function moveTreeNode(tree, info, fieldNames) {
|
|
|
84
106
|
try {
|
|
85
107
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
86
108
|
var n = _step2.value;
|
|
87
|
-
|
|
109
|
+
var isTarget = !inserted && matchNode(n, dropKey, dropPath, depth) && isTargetDepth(dropPath, depth);
|
|
110
|
+
if (isTarget && position === 'inside') {
|
|
88
111
|
var oldKids = Array.isArray(n[C]) ? n[C] : [];
|
|
89
112
|
next.push(_objectSpread(_objectSpread({}, n), {}, _defineProperty({}, C, [].concat(_toConsumableArray(oldKids), [dragNode]))));
|
|
90
113
|
inserted = true;
|
|
91
114
|
continue;
|
|
92
115
|
}
|
|
93
|
-
if (
|
|
116
|
+
if (isTarget && position === 'before') {
|
|
94
117
|
next.push(dragNode, n);
|
|
95
118
|
inserted = true;
|
|
96
119
|
continue;
|
|
97
120
|
}
|
|
98
|
-
if (
|
|
121
|
+
if (isTarget && position === 'after') {
|
|
99
122
|
next.push(n, dragNode);
|
|
100
123
|
inserted = true;
|
|
101
124
|
continue;
|
|
102
125
|
}
|
|
103
126
|
var kids = n[C];
|
|
104
127
|
if (inserted || !Array.isArray(kids)) {
|
|
105
|
-
|
|
128
|
+
next.push(n);
|
|
129
|
+
} else if (dropPath && !matchNode(n, dropKey, dropPath, depth)) {
|
|
130
|
+
// Not on the drop path at this level, skip recursion
|
|
106
131
|
next.push(n);
|
|
107
132
|
} else {
|
|
108
|
-
var r = insert(kids);
|
|
133
|
+
var r = insert(kids, depth + 1);
|
|
109
134
|
if (r.inserted) {
|
|
110
135
|
next.push(_objectSpread(_objectSpread({}, n), {}, _defineProperty({}, C, r.nodes)));
|
|
111
136
|
inserted = true;
|
|
@@ -124,28 +149,22 @@ export function moveTreeNode(tree, info, fieldNames) {
|
|
|
124
149
|
nodes: next
|
|
125
150
|
};
|
|
126
151
|
};
|
|
127
|
-
var _insert = insert(withoutDrag),
|
|
152
|
+
var _insert = insert(withoutDrag, 0),
|
|
128
153
|
inserted = _insert.inserted,
|
|
129
154
|
result = _insert.nodes;
|
|
130
|
-
// If the drop target wasn't found, nothing should change — return the
|
|
131
|
-
// original (drag node stays put) rather than silently dropping it.
|
|
132
155
|
return inserted ? result : root;
|
|
133
156
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
return keys;
|
|
148
|
-
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Flatten tree into a flat array with rich metadata.
|
|
160
|
+
*
|
|
161
|
+
* Key design decisions:
|
|
162
|
+
* - Uses `uid` (built from the key path) as the internal identifier, because
|
|
163
|
+
* user-provided `key` values may NOT be globally unique across the tree.
|
|
164
|
+
* - The returned Map is keyed by `uid` for O(1) lookups.
|
|
165
|
+
* - `childUids` is collected bottom-up in a single pass (O(n) total) instead
|
|
166
|
+
* of per-node recursive enumeration (which was O(n²)).
|
|
167
|
+
*/
|
|
149
168
|
export function tree2array(tree, fieldNames) {
|
|
150
169
|
if (!tree || Array.isArray(tree) && tree.length === 0) return [[], new Map()];
|
|
151
170
|
var data = Array.isArray(tree) ? tree : [tree];
|
|
@@ -154,118 +173,214 @@ export function tree2array(tree, fieldNames) {
|
|
|
154
173
|
var key = fieldNames.key,
|
|
155
174
|
label = fieldNames.label,
|
|
156
175
|
children = fieldNames.children;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Walk returns the list of descendant uids so the parent can collect them
|
|
179
|
+
* without a second traversal.
|
|
180
|
+
* Pushes nodes in PRE-ORDER (parent before children) so that visibleItems
|
|
181
|
+
* filtering can work in a single forward pass.
|
|
182
|
+
*/
|
|
157
183
|
function walk(_ref) {
|
|
158
|
-
var
|
|
159
|
-
|
|
184
|
+
var node = _ref.data,
|
|
185
|
+
pUid = _ref.pUid,
|
|
160
186
|
depth = _ref.depth,
|
|
161
187
|
path = _ref.path,
|
|
162
188
|
isLast = _ref.isLast,
|
|
163
189
|
lines = _ref.lines;
|
|
164
|
-
var
|
|
165
|
-
var _label =
|
|
166
|
-
var _children =
|
|
167
|
-
var nextPath = [].concat(_toConsumableArray(path), [
|
|
168
|
-
var uid =
|
|
169
|
-
var isParent =
|
|
190
|
+
var rawKey = node[key];
|
|
191
|
+
var _label = node[label];
|
|
192
|
+
var _children = node[children];
|
|
193
|
+
var nextPath = [].concat(_toConsumableArray(path), [rawKey]);
|
|
194
|
+
var uid = pUid ? "".concat(pUid, "\0").concat(String(rawKey)) : String(rawKey);
|
|
195
|
+
var isParent = Array.isArray(_children) && _children.length > 0;
|
|
196
|
+
|
|
197
|
+
// Push parent FIRST (pre-order) so visibleItems can rely on forward scan
|
|
170
198
|
var wrapperData = {
|
|
171
199
|
uid: uid,
|
|
172
|
-
key:
|
|
200
|
+
key: rawKey,
|
|
173
201
|
label: _label,
|
|
202
|
+
title: node.title,
|
|
174
203
|
path: path,
|
|
175
|
-
|
|
204
|
+
pUid: pUid,
|
|
176
205
|
depth: depth,
|
|
177
206
|
isLeaf: !isParent,
|
|
178
207
|
isLast: isLast,
|
|
179
208
|
lines: lines,
|
|
180
|
-
disabled:
|
|
181
|
-
icon:
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
disabled: node.disabled,
|
|
210
|
+
icon: node.icon,
|
|
211
|
+
childUids: undefined,
|
|
212
|
+
// will be filled after recursion
|
|
213
|
+
original: node
|
|
184
214
|
};
|
|
185
215
|
res.push(wrapperData);
|
|
186
|
-
map.set(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
216
|
+
map.set(uid, wrapperData);
|
|
217
|
+
|
|
218
|
+
// Recurse children to collect their uids bottom-up
|
|
219
|
+
var childTotal = isParent ? _children.length : 0;
|
|
220
|
+
var allDescendantUids = [];
|
|
221
|
+
if (isParent) {
|
|
222
|
+
_children.forEach(function (child, index) {
|
|
223
|
+
var childIsLast = index + 1 === childTotal;
|
|
224
|
+
var descendantUids = walk({
|
|
225
|
+
data: child,
|
|
226
|
+
pUid: uid,
|
|
227
|
+
depth: depth + 1,
|
|
228
|
+
path: nextPath,
|
|
229
|
+
isLast: childIsLast,
|
|
230
|
+
lines: isLast ? lines : [].concat(_toConsumableArray(lines), [depth])
|
|
231
|
+
});
|
|
232
|
+
allDescendantUids.push.apply(allDescendantUids, _toConsumableArray(descendantUids));
|
|
196
233
|
});
|
|
197
|
-
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Now fill in childUids
|
|
237
|
+
if (allDescendantUids.length > 0) {
|
|
238
|
+
wrapperData.childUids = allDescendantUids;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Return this uid + all descendant uids to the caller
|
|
242
|
+
return [uid].concat(allDescendantUids);
|
|
198
243
|
}
|
|
199
|
-
var
|
|
244
|
+
var rootTotal = data.length;
|
|
200
245
|
data.forEach(function (node, index) {
|
|
201
|
-
|
|
246
|
+
walk({
|
|
202
247
|
data: node,
|
|
203
|
-
|
|
248
|
+
pUid: null,
|
|
204
249
|
depth: 0,
|
|
205
250
|
path: [],
|
|
206
|
-
isLast: index + 1 ===
|
|
207
|
-
lines: index + 1 ===
|
|
251
|
+
isLast: index + 1 === rootTotal,
|
|
252
|
+
lines: index + 1 === rootTotal ? [] : [0]
|
|
208
253
|
});
|
|
209
254
|
});
|
|
210
255
|
return [res, map];
|
|
211
256
|
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Check whether array `a` contains every element in `b`.
|
|
260
|
+
*/
|
|
212
261
|
export function containsAll(a, b) {
|
|
213
|
-
if (b.length
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
262
|
+
if (!b || b.length === 0) return true;
|
|
216
263
|
return b.every(function (i) {
|
|
217
|
-
return a.
|
|
264
|
+
return a.has(i);
|
|
218
265
|
});
|
|
219
266
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Remove all elements in `b` from `a`.
|
|
270
|
+
*/
|
|
271
|
+
export function removeAll(a, b) {
|
|
272
|
+
var result = new Set();
|
|
273
|
+
a.forEach(function (item) {
|
|
274
|
+
return result.add(item);
|
|
225
275
|
});
|
|
276
|
+
var _iterator3 = _createForOfIteratorHelper(b),
|
|
277
|
+
_step3;
|
|
278
|
+
try {
|
|
279
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
280
|
+
var item = _step3.value;
|
|
281
|
+
result.delete(item);
|
|
282
|
+
}
|
|
283
|
+
} catch (err) {
|
|
284
|
+
_iterator3.e(err);
|
|
285
|
+
} finally {
|
|
286
|
+
_iterator3.f();
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
226
289
|
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Compute new checked uids when a node is toggled.
|
|
293
|
+
* Uses Set-based operations for O(1) membership checks.
|
|
294
|
+
* Disabled nodes are NOT affected by parent/child propagation — their checked
|
|
295
|
+
* state remains unchanged unless they are the directly toggled node.
|
|
296
|
+
*/
|
|
227
297
|
export function getCheckedKeys(_ref2) {
|
|
228
298
|
var checked = _ref2.checked,
|
|
229
299
|
keys = _ref2.keys,
|
|
230
|
-
|
|
300
|
+
uid = _ref2.uid,
|
|
231
301
|
map = _ref2.map;
|
|
232
|
-
var
|
|
233
|
-
|
|
234
|
-
var
|
|
235
|
-
var
|
|
302
|
+
var item = map.get(uid);
|
|
303
|
+
if (!item) return keys;
|
|
304
|
+
var childUids = item.childUids || [];
|
|
305
|
+
var newKeys = new Set();
|
|
306
|
+
keys.forEach(function (k) {
|
|
307
|
+
return newKeys.add(k);
|
|
308
|
+
});
|
|
236
309
|
if (checked) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
310
|
+
// Add this node + non-disabled descendants
|
|
311
|
+
newKeys.add(uid);
|
|
312
|
+
var _iterator4 = _createForOfIteratorHelper(childUids),
|
|
313
|
+
_step4;
|
|
314
|
+
try {
|
|
315
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
316
|
+
var cuid = _step4.value;
|
|
317
|
+
var child = map.get(cuid);
|
|
318
|
+
if (child && !child.disabled) {
|
|
319
|
+
newKeys.add(cuid);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Walk up: if all non-disabled children of an ancestor are checked, check the ancestor
|
|
324
|
+
} catch (err) {
|
|
325
|
+
_iterator4.e(err);
|
|
326
|
+
} finally {
|
|
327
|
+
_iterator4.f();
|
|
328
|
+
}
|
|
329
|
+
var pUid = item.pUid;
|
|
330
|
+
while (pUid) {
|
|
331
|
+
var parent = map.get(pUid);
|
|
240
332
|
if (parent) {
|
|
241
|
-
if (
|
|
242
|
-
|
|
333
|
+
if (parent.disabled) {
|
|
334
|
+
// Stop propagation at disabled ancestors
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
if (!newKeys.has(parent.uid) && parent.childUids) {
|
|
338
|
+
// Check if all non-disabled children are checked
|
|
339
|
+
var allNonDisabledChecked = parent.childUids.every(function (cuid) {
|
|
340
|
+
var child = map.get(cuid);
|
|
341
|
+
return child && child.disabled || newKeys.has(cuid);
|
|
342
|
+
});
|
|
343
|
+
if (allNonDisabledChecked) {
|
|
344
|
+
newKeys.add(parent.uid);
|
|
345
|
+
}
|
|
243
346
|
}
|
|
244
|
-
|
|
347
|
+
pUid = parent.pUid;
|
|
245
348
|
} else {
|
|
246
|
-
|
|
349
|
+
pUid = null;
|
|
247
350
|
}
|
|
248
351
|
}
|
|
249
352
|
} else {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
});
|
|
353
|
+
// Remove this node + non-disabled descendants
|
|
354
|
+
newKeys.delete(uid);
|
|
355
|
+
var _iterator5 = _createForOfIteratorHelper(childUids),
|
|
356
|
+
_step5;
|
|
357
|
+
try {
|
|
358
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
359
|
+
var _cuid = _step5.value;
|
|
360
|
+
var _child = map.get(_cuid);
|
|
361
|
+
if (_child && !_child.disabled) {
|
|
362
|
+
newKeys.delete(_cuid);
|
|
261
363
|
}
|
|
262
|
-
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Walk up: uncheck non-disabled ancestors
|
|
367
|
+
} catch (err) {
|
|
368
|
+
_iterator5.e(err);
|
|
369
|
+
} finally {
|
|
370
|
+
_iterator5.f();
|
|
371
|
+
}
|
|
372
|
+
var _pUid = item.pUid;
|
|
373
|
+
while (_pUid) {
|
|
374
|
+
var _parent = map.get(_pUid);
|
|
375
|
+
if (_parent) {
|
|
376
|
+
if (_parent.disabled) {
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
newKeys.delete(_parent.uid);
|
|
380
|
+
_pUid = _parent.pUid;
|
|
263
381
|
} else {
|
|
264
|
-
|
|
382
|
+
_pUid = null;
|
|
265
383
|
}
|
|
266
|
-
};
|
|
267
|
-
while (pKey) {
|
|
268
|
-
_loop();
|
|
269
384
|
}
|
|
270
385
|
}
|
|
271
386
|
return newKeys;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { Locale, TFunction } from './interface';
|
|
2
|
+
import type { Locale, LocaleConfigInput, TFunction } from './interface';
|
|
3
3
|
interface LocaleContextType {
|
|
4
4
|
locale: Locale;
|
|
5
5
|
lang: string;
|
|
6
|
-
setLocale: (locale:
|
|
6
|
+
setLocale: (locale: LocaleConfigInput) => void;
|
|
7
7
|
t: TFunction;
|
|
8
8
|
}
|
|
9
9
|
export declare const LocaleContext: React.Context<LocaleContextType>;
|
|
10
10
|
interface LocaleProviderProps {
|
|
11
11
|
children: React.ReactNode;
|
|
12
|
-
/** Initial locale
|
|
13
|
-
|
|
12
|
+
/** Initial locale: a language code, or a full/partial locale object.
|
|
13
|
+
* Partial objects are merged onto the matching built-in pack. */
|
|
14
|
+
defaultLocale?: LocaleConfigInput;
|
|
14
15
|
/** Async locale loader function */
|
|
15
16
|
loadLocale?: (lang: string) => Promise<Locale>;
|
|
16
17
|
/** Whether to auto-fallback to default for missing fields */
|
|
@@ -10,9 +10,9 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
|
|
|
10
10
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
11
11
|
// locale/context.tsx
|
|
12
12
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
13
|
-
import { DEFAULT_LOCALE, LOCALE_CONFIGS } from "./constants";
|
|
13
|
+
import { DEFAULT_LOCALE, DEFAULT_LOCALE_CONFIG, LOCALE_CONFIGS } from "./constants";
|
|
14
14
|
import defaultLocaleData from "./lang/en_US";
|
|
15
|
-
import { isValidLocale, translate } from "./util";
|
|
15
|
+
import { deepMerge, isValidLocale, translate } from "./util";
|
|
16
16
|
|
|
17
17
|
// ============ Default value (fallback when no Provider) ============
|
|
18
18
|
|
|
@@ -33,6 +33,25 @@ var createDefaultValue = function createDefaultValue() {
|
|
|
33
33
|
};
|
|
34
34
|
var defaultValue = createDefaultValue();
|
|
35
35
|
|
|
36
|
+
// ============ Locale input resolution ============
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a locale input (a language code, or a possibly-partial locale
|
|
40
|
+
* object) into a full `Locale` pack. Partial objects are deep-merged onto the
|
|
41
|
+
* built-in pack matching their `locale` field, so only the overridden keys
|
|
42
|
+
* change and everything else is inherited.
|
|
43
|
+
*/
|
|
44
|
+
function resolveLocaleConfigInput(input) {
|
|
45
|
+
if (typeof input === 'string') {
|
|
46
|
+
return LOCALE_CONFIGS[input] || defaultLocaleData;
|
|
47
|
+
}
|
|
48
|
+
if (input && typeof input.locale === 'string') {
|
|
49
|
+
var base = LOCALE_CONFIGS[input.locale] || DEFAULT_LOCALE_CONFIG;
|
|
50
|
+
return deepMerge(base, input);
|
|
51
|
+
}
|
|
52
|
+
return defaultLocaleData;
|
|
53
|
+
}
|
|
54
|
+
|
|
36
55
|
// ============ Context definition ============
|
|
37
56
|
|
|
38
57
|
export var LocaleContext = /*#__PURE__*/createContext(defaultValue);
|
|
@@ -48,11 +67,7 @@ export function LocaleProvider(_ref) {
|
|
|
48
67
|
fallbackToDefault = _ref$fallbackToDefaul === void 0 ? true : _ref$fallbackToDefaul;
|
|
49
68
|
// State management
|
|
50
69
|
var _useState = useState(function () {
|
|
51
|
-
|
|
52
|
-
// Prefer sync lookup from static locale packs
|
|
53
|
-
return LOCALE_CONFIGS[initialLocale] || defaultLocaleData;
|
|
54
|
-
}
|
|
55
|
-
return isValidLocale(initialLocale) ? initialLocale : defaultLocaleData;
|
|
70
|
+
return resolveLocaleConfigInput(initialLocale);
|
|
56
71
|
}),
|
|
57
72
|
_useState2 = _slicedToArray(_useState, 2),
|
|
58
73
|
locale = _useState2[0],
|
|
@@ -152,8 +167,9 @@ export function LocaleProvider(_ref) {
|
|
|
152
167
|
}
|
|
153
168
|
// Otherwise use async loading
|
|
154
169
|
loadAndSetLocale(target);
|
|
155
|
-
} else if (
|
|
156
|
-
|
|
170
|
+
} else if (target && typeof target.locale === 'string') {
|
|
171
|
+
// Full or partial object: merge onto the matching built-in pack
|
|
172
|
+
setLocaleState(resolveLocaleConfigInput(target));
|
|
157
173
|
setLang(target.locale);
|
|
158
174
|
}
|
|
159
175
|
}, [loadAndSetLocale]);
|
|
@@ -126,4 +126,24 @@ type ExtractParams<T extends string> = T extends `${infer Pre}{${infer P}}${infe
|
|
|
126
126
|
} : Record<string, never>;
|
|
127
127
|
export type LocaleParams<K extends LocaleKey> = ExtractParams<K extends keyof Locale ? Locale[K] : K extends `${infer A}.${infer B}` ? A extends keyof Locale ? B extends keyof Locale[A] ? Locale[A][B] : never : never : never>;
|
|
128
128
|
export type TFunction = <K extends LocaleKey>(key: K, params?: LocaleParams<K>) => string;
|
|
129
|
+
/**
|
|
130
|
+
* Recursively-optional version of T. Every level is optional; arrays are kept
|
|
131
|
+
* as-is (replaced wholesale rather than element-merged).
|
|
132
|
+
*
|
|
133
|
+
* Used so a locale override only needs to specify the keys it changes:
|
|
134
|
+
* `{ datepicker: { now: 'Now' } }` is a valid `DeepPartial<Locale>`.
|
|
135
|
+
*/
|
|
136
|
+
export type DeepPartial<T> = T extends (...args: any[]) => any ? T : T extends object ? T extends readonly any[] ? T : {
|
|
137
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
138
|
+
} : T;
|
|
139
|
+
/**
|
|
140
|
+
* Locale input accepted by `LocaleProvider` / `useLocale().setLocale`:
|
|
141
|
+
* - a language code string (`'zh_CN'`), resolved from the built-in packs, or
|
|
142
|
+
* - a (possibly partial) locale object. A partial object MUST carry `locale`
|
|
143
|
+
* so the provider knows which built-in pack to merge the overrides onto;
|
|
144
|
+
* only the keys you specify are overridden, everything else is inherited.
|
|
145
|
+
*/
|
|
146
|
+
export type LocaleConfigInput = string | (DeepPartial<Locale> & {
|
|
147
|
+
locale: string;
|
|
148
|
+
});
|
|
129
149
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Locale } from './interface';
|
|
1
|
+
import type { DeepPartial, Locale } from './interface';
|
|
2
2
|
/**
|
|
3
3
|
* Deep get object value
|
|
4
4
|
* get(obj, 'a.b.c') => obj.a.b.c
|
|
@@ -16,11 +16,11 @@ export declare function isValidLocale(obj: any): obj is Locale;
|
|
|
16
16
|
* Deep merge two objects
|
|
17
17
|
* Used to merge custom config with default config
|
|
18
18
|
*/
|
|
19
|
-
export declare function deepMerge<T extends Record<string, any>>(target: T, source:
|
|
19
|
+
export declare function deepMerge<T extends Record<string, any>>(target: T, source: DeepPartial<NoInfer<T>>): T;
|
|
20
20
|
/**
|
|
21
21
|
* Ensure locale pack completeness, fill missing fields with default values
|
|
22
22
|
*/
|
|
23
|
-
export declare function normalizeLocale(locale:
|
|
23
|
+
export declare function normalizeLocale(locale: DeepPartial<Locale>): Locale;
|
|
24
24
|
/**
|
|
25
25
|
* Get translation text from locale, supports fallback
|
|
26
26
|
* @param locale Current locale pack
|