Skip to content

Commit 8434ed1

Browse files
committed
feat: add group, ungroup in helper
1 parent fb90fbd commit 8434ed1

File tree

3 files changed

+111
-51
lines changed

3 files changed

+111
-51
lines changed

packages/helper/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@moveable/helper",
3-
"version": "0.1.2",
3+
"version": "0.1.3",
44
"description": "Helper for demo of Moveable",
55
"main": "./dist/helper.cjs.js",
66
"module": "./dist/helper.esm.js",

packages/helper/src/GroupManager.ts

+60-48
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,6 @@ import { GroupArrayChild, GroupSingleChild } from "./groups";
44
import { GroupChild, TargetGroupsObject, TargetGroupsType, TargetList } from "./types";
55

66

7-
function createGroupChildren(
8-
targetGroups: TargetGroupsObject,
9-
parent: GroupArrayChild,
10-
) {
11-
const {
12-
value,
13-
map,
14-
} = parent;
15-
targetGroups.forEach(child => {
16-
if ("groupId" in child) {
17-
const group = new GroupArrayChild(parent);
18-
19-
group.id = child.groupId;
20-
group.depth = parent.depth + 1;
21-
value.push(group);
22-
23-
createGroupChildren(child.children, group);
24-
} else if (isArray(child)) {
25-
const group = new GroupArrayChild(parent);
26-
27-
group.depth = parent.depth + 1;
28-
value.push(group);
29-
30-
createGroupChildren(child, group);
31-
} else {
32-
const element = "current" in child ? child.current : child;
33-
const single = new GroupSingleChild(parent, element!);
34-
35-
single.depth = parent.depth + 1;
36-
value.push(single);
37-
map.set(element!, single);
38-
}
39-
});
40-
41-
value.forEach(child => {
42-
if (child.type === "single") {
43-
map.set(child.value, child);
44-
} else {
45-
child.map.forEach((nextChild, element) => {
46-
map.set(element, nextChild);
47-
});
48-
}
49-
});
50-
return parent;
51-
}
52-
537
export function toTargetList(raw: GroupChild[]): TargetList {
548
function targets(childs: GroupChild[] = []) {
559
const arr: TargetGroupsType = [];
@@ -78,6 +32,8 @@ export function toTargetList(raw: GroupChild[]): TargetList {
7832

7933
export class GroupManager extends GroupArrayChild {
8034
public type = "root" as const;
35+
private _targets: Array<HTMLElement | SVGElement> = [];
36+
8137
constructor(
8238
targetGroups: TargetGroupsType,
8339
targets?: Array<HTMLElement | SVGElement>,
@@ -95,8 +51,7 @@ export class GroupManager extends GroupArrayChild {
9551
const map = this.map;
9652
const value = this.value;
9753

98-
createGroupChildren(targetGroups, this);
99-
54+
this.add(targetGroups);
10055
targets.forEach(target => {
10156
if (map.has(target)) {
10257
return;
@@ -107,6 +62,7 @@ export class GroupManager extends GroupArrayChild {
10762
value.push(single);
10863
map.set(target, single);
10964
});
65+
this._targets = targets;
11066
}
11167
public selectSubChilds(targets: TargetGroupsType, target: HTMLElement | SVGElement) {
11268
const root = this;
@@ -300,6 +256,62 @@ export class GroupManager extends GroupArrayChild {
300256

301257
return value;
302258
}
259+
public group(targets: TargetGroupsType, flatten?: boolean): TargetGroupsType | null {
260+
const commonParent = this.findCommonParent(targets);
261+
const groupChilds = targets.map(target => {
262+
if (isArray(target)) {
263+
return this.findArrayChild(target);
264+
}
265+
return this.toSingleChild(target);
266+
});
267+
const isGroupable = groupChilds.every(child => child?.parent === commonParent);
268+
269+
if (!isGroupable) {
270+
return null;
271+
}
272+
const group = new GroupArrayChild(commonParent);
273+
const nextChilds = commonParent.value.filter(target => groupChilds.indexOf(target) === -1);
274+
275+
nextChilds.unshift(group);
276+
277+
group.add(flatten ? deepFlat(targets) : targets);
278+
commonParent.value = nextChilds;
279+
280+
this.set(this.toTargetGroups(), this._targets);
281+
282+
return group.toTargetGroups();
283+
}
284+
public ungroup(targets: TargetGroupsType) {
285+
if (targets.length === 1 && isArray(targets[0])) {
286+
targets = targets[0];
287+
}
288+
const commonParent = this.findCommonParent(targets);
289+
const groupChilds = targets.map(target => {
290+
if (isArray(target)) {
291+
return this.findArrayChild(target);
292+
}
293+
return this.toSingleChild(target);
294+
});
295+
const isGroupable = commonParent.value.every(child => groupChilds.indexOf(child) > -1);
296+
297+
if (!isGroupable || commonParent === this) {
298+
// has no group
299+
return null;
300+
}
301+
302+
const parent = commonParent.parent;
303+
304+
if (!parent) {
305+
return null;
306+
}
307+
const nextChilds = parent.value.filter(target => target !== commonParent);
308+
309+
nextChilds.push(...commonParent.value);
310+
parent.value = nextChilds;
311+
312+
this.set(this.toTargetGroups(), this._targets);
313+
return commonParent.toTargetGroups();
314+
}
303315
protected _findParentGroup(
304316
element: HTMLElement | SVGElement,
305317
range: Array<HTMLElement | SVGElement>,

packages/helper/src/groups.ts

+50-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { isArray, deepFlat, find } from "@daybrush/utils";
2-
import { GroupChild, TargetGroupsType } from "./types";
2+
import { GroupChild, TargetGroupsObject, TargetGroupsType } from "./types";
33

44
export class Child {
55
public type: "group" | "root" | "single" = "single";
66
public depth = 0;
77
protected _scope: string[] = [];
8-
constructor(public parent?: GroupArrayChild) {}
8+
constructor(public parent?: GroupArrayChild) {
9+
if (parent) {
10+
this.depth = parent.depth + 1;
11+
}
12+
}
913

1014
public get scope(): string[] {
1115
const parent = this.parent;
@@ -285,4 +289,48 @@ export class GroupArrayChild extends Child {
285289
return selected.indexOf(child.value) > -1;
286290
});
287291
}
292+
public add(targets: TargetGroupsObject) {
293+
const {
294+
value,
295+
map,
296+
} = this;
297+
const depth = this.depth;
298+
299+
targets.forEach(child => {
300+
if ("groupId" in child) {
301+
const group = new GroupArrayChild(this);
302+
303+
group.id = child.groupId;
304+
group.depth = depth + 1;
305+
value.push(group);
306+
307+
group.add(child.children);
308+
} else if (isArray(child)) {
309+
const group = new GroupArrayChild(this);
310+
311+
group.depth = depth + 1;
312+
value.push(group);
313+
314+
group.add(child);
315+
} else {
316+
const element = "current" in child ? child.current : child;
317+
const single = new GroupSingleChild(this, element!);
318+
319+
single.depth = depth + 1;
320+
value.push(single);
321+
map.set(element!, single);
322+
}
323+
});
324+
325+
value.forEach(child => {
326+
if (child.type === "single") {
327+
map.set(child.value, child);
328+
} else {
329+
child.map.forEach((nextChild, element) => {
330+
map.set(element, nextChild);
331+
});
332+
}
333+
});
334+
return parent;
335+
}
288336
}

0 commit comments

Comments
 (0)