1 | import { JSX } from './jsx/jsx-namespace';
|
2 | import { isArray, isNil } from '@antv/util';
|
3 |
|
4 | function cloneElement(element, props) {
|
5 | if (!element) return element;
|
6 | return {
|
7 | ...element,
|
8 | props: {
|
9 | ...element.props,
|
10 | ...props,
|
11 | },
|
12 | };
|
13 | }
|
14 |
|
15 | function map(children: any, fn: any) {
|
16 | if (!children) {
|
17 | return fn(children);
|
18 | }
|
19 | if (isArray(children)) {
|
20 | return children.map((child) => {
|
21 | return map(child, fn);
|
22 | });
|
23 | }
|
24 | return fn(children);
|
25 | }
|
26 |
|
27 | function compareArray(
|
28 | nextElements: JSX.Element[],
|
29 | lastElements: JSX.Element[],
|
30 | callback: Function
|
31 | ) {
|
32 | const keyed = {};
|
33 | const nextLength = nextElements.length;
|
34 | const lastLength = lastElements.length;
|
35 | for (let i = 0, len = lastLength; i < len; i++) {
|
36 | const element = lastElements[i];
|
37 | if (element && !isNil(element.key)) {
|
38 | const { key } = element;
|
39 | keyed[key] = element;
|
40 | }
|
41 | }
|
42 |
|
43 |
|
44 | for (let i = 0, len = Math.max(nextLength, lastLength); i < len; i++) {
|
45 | const element = nextElements[i];
|
46 | if (!element) {
|
47 | compare(element, lastElements[i], callback);
|
48 | continue;
|
49 | }
|
50 | const { key } = element;
|
51 |
|
52 | if (!isNil(element.key)) {
|
53 | const lastElement = keyed[key];
|
54 | if (lastElement) delete keyed[key];
|
55 | compare(element, lastElement, callback);
|
56 | continue;
|
57 | }
|
58 | compare(element, lastElements[i], callback);
|
59 | }
|
60 |
|
61 | Object.keys(keyed).forEach((key) => {
|
62 | compare(null, keyed[key], callback);
|
63 | });
|
64 | }
|
65 |
|
66 |
|
67 | function compare(nextElement: JSX.Element, lastElement: JSX.Element, callback: Function) {
|
68 |
|
69 | if (!nextElement || !lastElement) {
|
70 | callback(nextElement, lastElement);
|
71 | return;
|
72 | }
|
73 |
|
74 | if (isArray(nextElement) || isArray(lastElement)) {
|
75 | const nextElementArray = isArray(nextElement) ? nextElement : [nextElement];
|
76 | const lastElementArray = isArray(lastElement) ? lastElement : [lastElement];
|
77 | compareArray(nextElementArray, lastElementArray, callback);
|
78 | return;
|
79 | }
|
80 |
|
81 | callback(nextElement, lastElement);
|
82 | }
|
83 |
|
84 | function toArray(element: JSX.Element): JSX.Element[] | null {
|
85 | if (!element) {
|
86 | return element as null;
|
87 | }
|
88 | if (!isArray(element)) {
|
89 | return [element];
|
90 | }
|
91 | let newArray = [];
|
92 | for (let i = 0, len = element.length; i < len; i++) {
|
93 | const item = element[i];
|
94 | if (isArray(item)) {
|
95 |
|
96 | newArray = newArray.concat(toArray(item));
|
97 | } else {
|
98 | newArray.push(item);
|
99 | }
|
100 | }
|
101 | return newArray;
|
102 | }
|
103 |
|
104 | const Children = {
|
105 | cloneElement,
|
106 | map,
|
107 | toArray,
|
108 | compare,
|
109 | };
|
110 |
|
111 | export default Children;
|