Skip to content

Commit ead3528

Browse files
committed
new file: src/index.ts
1 parent 8c4c8b9 commit ead3528

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed

src/index.ts

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import { toReactive } from "@vueuse/core";
2+
import { v4 } from "uuid";
3+
import { computed, isReactive, reactive } from "vue";
4+
export default (
5+
tree: Record<string, unknown>[],
6+
{
7+
branch: keyBranch = "branch",
8+
children: keyChildren = "children",
9+
id: keyId = "id",
10+
index: keyIndex = "index",
11+
next: keyNext = "next",
12+
parent: keyParent = "parent",
13+
prev: keyPrev = "prev",
14+
siblings: keySiblings = "siblings",
15+
} = {},
16+
) => {
17+
const properties: PropertyDescriptorMap = {
18+
[keyBranch]: {
19+
get(this: Record<string, unknown>) {
20+
const ret = [this];
21+
while (ret[0]?.[keyParent])
22+
ret.unshift(ret[0][keyParent] as Record<string, unknown>);
23+
return ret;
24+
},
25+
},
26+
[keyIndex]: {
27+
get(this: Record<string, unknown>) {
28+
return (this[keySiblings] as Record<string, unknown>[]).findIndex(
29+
(sibling) => this[keyId] === sibling[keyId],
30+
);
31+
},
32+
},
33+
[keyNext]: {
34+
get(this: Record<string, unknown>) {
35+
return (this[keySiblings] as Record<string, unknown>[])[
36+
(this[keyIndex] as number) + 1
37+
];
38+
},
39+
},
40+
[keyPrev]: {
41+
get(this: Record<string, unknown>) {
42+
return (this[keySiblings] as Record<string, unknown>[])[
43+
(this[keyIndex] as number) - 1
44+
];
45+
},
46+
},
47+
};
48+
const getLeaves = (
49+
siblings: { configurable?: boolean; value: Record<string, unknown>[] },
50+
parent = {},
51+
) =>
52+
siblings.value.flatMap((value): Record<string, unknown>[] => {
53+
Object.defineProperties(value, {
54+
...properties,
55+
[keyParent]: parent,
56+
[keySiblings]: siblings,
57+
});
58+
return [
59+
value,
60+
...getLeaves(
61+
{
62+
configurable: true,
63+
value: (value[keyChildren] ?? []) as Record<string, unknown>[],
64+
},
65+
{ configurable: true, value },
66+
),
67+
];
68+
}),
69+
leaves = computed(() =>
70+
getLeaves({ value: isReactive(tree) ? tree : reactive(tree) }),
71+
),
72+
objLeaves = toReactive(
73+
computed(() =>
74+
Object.fromEntries(
75+
leaves.value.map((leaf) => [leaf[keyId] as string, leaf]),
76+
),
77+
),
78+
);
79+
return {
80+
add: (pId: string) => {
81+
const the = objLeaves[pId];
82+
if (the) {
83+
const children = the[keyChildren] as
84+
| Record<string, unknown>[]
85+
| undefined,
86+
index = the[keyIndex] as number,
87+
siblings = the[keySiblings] as Record<string, unknown>[];
88+
const id = v4();
89+
switch (true) {
90+
case !!the[keyParent]:
91+
siblings.splice(index + 1, 0, { [keyId]: id });
92+
break;
93+
case !!children:
94+
children.unshift({ [keyId]: id });
95+
break;
96+
default:
97+
siblings.splice(index + 1, 0, { [keyId]: id });
98+
break;
99+
}
100+
return id;
101+
}
102+
return undefined;
103+
},
104+
arrLeaves: toReactive(leaves),
105+
down: (pId: string) => {
106+
const the = objLeaves[pId];
107+
if (the) {
108+
const index = the[keyIndex] as number,
109+
nextIndex = index + 1,
110+
siblings = the[keySiblings] as Record<string, unknown>[];
111+
if (
112+
index < siblings.length - 1 &&
113+
siblings[index] &&
114+
siblings[nextIndex]
115+
)
116+
[siblings[index], siblings[nextIndex]] = [
117+
siblings[nextIndex],
118+
siblings[index],
119+
];
120+
}
121+
},
122+
leaves,
123+
left: (pId: string) => {
124+
const the = objLeaves[pId];
125+
if (the) {
126+
const parent = the[keyParent] as Record<string, unknown> | undefined;
127+
if (parent?.[keyParent]) {
128+
const children = (parent[keyChildren] ?? []) as Record<
129+
string,
130+
unknown
131+
>[],
132+
siblings = parent[keySiblings] as Record<string, unknown>[];
133+
siblings.splice(
134+
(parent[keyIndex] as number) + 1,
135+
0,
136+
...children.splice(the[keyIndex] as number, 1),
137+
);
138+
return parent[keyId] as string;
139+
}
140+
}
141+
return undefined;
142+
},
143+
objLeaves,
144+
remove: (pId: string) => {
145+
const the = objLeaves[pId];
146+
if (the) {
147+
const parent = the[keyParent] as Record<string, unknown> | undefined;
148+
if (parent) {
149+
const [root] = leaves.value,
150+
next = the[keyNext] as Record<string, unknown> | undefined,
151+
prev = the[keyPrev] as Record<string, unknown> | undefined,
152+
id = (next?.[keyId] ??
153+
prev?.[keyId] ??
154+
parent[keyId] ??
155+
root?.[keyId]) as string,
156+
siblings = the[keySiblings] as Record<string, unknown>[];
157+
siblings.splice(the[keyIndex] as number, 1);
158+
return id;
159+
}
160+
}
161+
return undefined;
162+
},
163+
right: (pId: string) => {
164+
const the = objLeaves[pId];
165+
if (the) {
166+
const prev = the[keyPrev] as Record<string, unknown> | undefined;
167+
if (prev) {
168+
const children = (prev[keyChildren] ?? []) as Record<
169+
string,
170+
unknown
171+
>[],
172+
id = prev[keyId] as string,
173+
siblings = the[keySiblings] as Record<string, unknown>[];
174+
prev[keyChildren] = [
175+
...children,
176+
...siblings.splice(the[keyIndex] as number, 1),
177+
];
178+
return id;
179+
}
180+
}
181+
return undefined;
182+
},
183+
up: (pId: string) => {
184+
const the = objLeaves[pId];
185+
if (the) {
186+
const index = the[keyIndex] as number,
187+
prevIndex = index - 1,
188+
siblings = the[keySiblings] as Record<string, unknown>[];
189+
if (index && siblings[index] && siblings[prevIndex])
190+
[siblings[prevIndex], siblings[index]] = [
191+
siblings[index],
192+
siblings[prevIndex],
193+
];
194+
}
195+
},
196+
};
197+
};

0 commit comments

Comments
 (0)