Skip to content

Commit 1d715f7

Browse files
author
Jerry Bruwes
committed
new file: src/index.ts
1 parent 8931155 commit 1d715f7

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed

src/index.ts

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

0 commit comments

Comments
 (0)