Skip to content

Commit 9faf157

Browse files
author
Jerry Bruwes
committed
new file: index.ts
1 parent 137030e commit 9faf157

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed

index.ts

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

0 commit comments

Comments
 (0)