Skip to content

Commit 88c0113

Browse files
committed
demo: add nested group demo #958
1 parent 863ad42 commit 88c0113

File tree

11 files changed

+241
-54
lines changed

11 files changed

+241
-54
lines changed

.github/workflows/run-e2e.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ jobs:
2121
- name: Install dependencies
2222
if: steps.cache-lerna.outputs.cache-hit != 'true'
2323
run: yarn --frozen-lockfile
24-
- name: Build Helper
25-
run: yarn build
26-
working-directory: ./packages/helper
2724
- name: Run Storybook tests
2825
run: yarn test:ci
2926
working-directory: ./packages/react-moveable

packages/helper/src/GroupManager.ts

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable no-cond-assign */
22
import { deepFlat, isArray } from "@daybrush/utils";
3-
import { GroupArrayChild, GroupSingleChild } from "./groups";
3+
import { ArrayChild, SingleChild } from "./groups";
44
import { GroupChild, TargetGroupsObject, TargetGroupsType, TargetList } from "./types";
55

66

@@ -30,7 +30,7 @@ export function toTargetList(raw: GroupChild[]): TargetList {
3030
};
3131
}
3232

33-
export class GroupManager extends GroupArrayChild {
33+
export class GroupManager extends ArrayChild {
3434
public type = "root" as const;
3535
private _targets: Array<HTMLElement | SVGElement> = [];
3636

@@ -56,7 +56,7 @@ export class GroupManager extends GroupArrayChild {
5656
if (map.has(target)) {
5757
return;
5858
}
59-
const single = new GroupSingleChild(this, target);
59+
const single = new SingleChild(this, target);
6060

6161
single.depth = 1;
6262
value.push(single);
@@ -110,7 +110,6 @@ export class GroupManager extends GroupArrayChild {
110110
removed: Array<HTMLElement | SVGElement>,
111111
continueSelect?: boolean,
112112
) {
113-
114113
const nextTargets = [...targets];
115114
const startSelected = deepFlat(nextTargets);
116115

@@ -144,11 +143,16 @@ export class GroupManager extends GroupArrayChild {
144143

145144
added.forEach(element => {
146145
const parentGroup = this._findParentGroup(element, startSelected);
147-
148146
const nextChild = parentGroup.findContainedChild(element);
149147

150148
if (nextChild?.type === "group") {
151-
nextTargets.push(nextChild.toTargetGroups());
149+
const singleChild = nextChild.getSingleChild();
150+
151+
if (singleChild) {
152+
nextTargets.push(singleChild.value);
153+
} else {
154+
nextTargets.push(nextChild.toTargetGroups());
155+
}
152156
return;
153157
}
154158
nextTargets.push(element);
@@ -215,6 +219,11 @@ export class GroupManager extends GroupArrayChild {
215219
const arrayChild = this.findArrayChild(target);
216220

217221
if (arrayChild) {
222+
const singleChild = arrayChild.getSingleChild();
223+
224+
if (singleChild) {
225+
return singleChild;
226+
}
218227
childs.push(arrayChild);
219228
}
220229
} else {
@@ -223,25 +232,31 @@ export class GroupManager extends GroupArrayChild {
223232
if (single) {
224233
childs.push(single);
225234
} else {
226-
childs.push(new GroupSingleChild(this, target));
235+
childs.push(new SingleChild(this, target));
227236
}
228237
}
229238
});
230239

231240
return childs;
232241
}
233-
public toSingleChild(element: HTMLElement | SVGElement, isAuto: true): GroupSingleChild;
234-
public toSingleChild(element: HTMLElement | SVGElement, isAuto?: boolean): GroupSingleChild | undefined;
235-
public toSingleChild(element: HTMLElement | SVGElement, isAuto?: boolean): GroupSingleChild | undefined {
242+
public findChild(element: HTMLElement | SVGElement, isAuto: true): SingleChild | ArrayChild;
243+
public findChild(
244+
element: HTMLElement | SVGElement,
245+
isAuto?: boolean,
246+
): SingleChild | ArrayChild | undefined;
247+
public findChild(
248+
element: HTMLElement | SVGElement,
249+
isAuto?: boolean,
250+
): SingleChild | ArrayChild | undefined {
236251
const value = this.map.get(element);
237252

238253
if (isAuto) {
239-
return value || new GroupSingleChild(this, element);
254+
return value || new SingleChild(this, element);
240255
}
241256
return value;
242257
}
243-
public findArrayChildById(id: string): GroupArrayChild | null {
244-
let value: GroupArrayChild | null = null;
258+
public findArrayChildById(id: string): ArrayChild | null {
259+
let value: ArrayChild | null = null;
245260

246261
this.value.some(function find(child: GroupChild) {
247262
if (child.type !== "single") {
@@ -262,18 +277,20 @@ export class GroupManager extends GroupArrayChild {
262277
if (isArray(target)) {
263278
return this.findArrayChild(target);
264279
}
265-
return this.toSingleChild(target);
280+
return this.findChild(target);
266281
});
267282
const isGroupable = groupChilds.every(child => child?.parent === commonParent);
268283

269284
if (!isGroupable) {
270285
return null;
271286
}
272-
const group = new GroupArrayChild(commonParent);
287+
const group = new ArrayChild(commonParent);
273288
const nextChilds = commonParent.value.filter(target => groupChilds.indexOf(target) === -1);
274289

290+
if (!nextChilds.length) {
291+
return null;
292+
}
275293
nextChilds.unshift(group);
276-
277294
group.add(flatten ? deepFlat(targets) : targets);
278295
commonParent.value = nextChilds;
279296

@@ -290,8 +307,14 @@ export class GroupManager extends GroupArrayChild {
290307
if (isArray(target)) {
291308
return this.findArrayChild(target);
292309
}
293-
return this.toSingleChild(target);
310+
return this.findChild(target);
294311
});
312+
313+
if (commonParent.groupElement) {
314+
return null;
315+
}
316+
317+
// all children is targets
295318
const isGroupable = commonParent.value.every(child => groupChilds.indexOf(child) > -1);
296319

297320
if (!isGroupable || commonParent === this) {
@@ -324,7 +347,7 @@ export class GroupManager extends GroupArrayChild {
324347
if (!single) {
325348
return this;
326349
}
327-
let parent: GroupArrayChild | undefined = single.parent;
350+
let parent: ArrayChild | undefined = single.parent;
328351

329352
while (parent) {
330353
if (range.some(element => parent!.contains(element))) {

packages/helper/src/groups.ts

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ 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?: ArrayChild) {
99
if (parent) {
1010
this.depth = parent.depth + 1;
1111
}
@@ -21,19 +21,21 @@ export class Child {
2121
}
2222
}
2323

24-
export class GroupSingleChild extends Child {
24+
export class SingleChild extends Child {
2525
public type = "single" as const;
26-
constructor(parent: GroupArrayChild, public value: HTMLElement | SVGElement) {
26+
public isGroupElement = false;
27+
constructor(parent: ArrayChild, public value: HTMLElement | SVGElement) {
2728
super(parent);
2829
}
2930
}
3031

3132

32-
export class GroupArrayChild extends Child {
33+
export class ArrayChild extends Child {
3334
public type: "group" | "root" = "group";
3435
public value: GroupChild[] = [];
3536
public id = "";
36-
public map: Map<HTMLElement | SVGElement, GroupSingleChild> = new Map();
37+
public groupElement?: HTMLElement | SVGElement | null = null;
38+
public map: Map<HTMLElement | SVGElement, SingleChild> = new Map();
3739

3840
public compare(groups: TargetGroupsType, checker: -1 | 0 | 1 = 0) {
3941
const elements = deepFlat(groups);
@@ -95,7 +97,7 @@ export class GroupArrayChild extends Child {
9597
return;
9698
}
9799

98-
let parent: GroupArrayChild | undefined = single.parent;
100+
let parent: ArrayChild | undefined = single.parent;
99101

100102
while (parent) {
101103
if (parent.map.size >= length) {
@@ -105,7 +107,7 @@ export class GroupArrayChild extends Child {
105107
}
106108
return;
107109
}
108-
public findCommonParent(targets: TargetGroupsType): GroupArrayChild {
110+
public findCommonParent(targets: TargetGroupsType): ArrayChild {
109111
let depth = Infinity;
110112
let childs = targets.map(target => this.findExactChild(target));
111113

@@ -136,16 +138,16 @@ export class GroupArrayChild extends Child {
136138
break;
137139
}
138140
}
139-
const commonParent = childs.find(child => child) as GroupArrayChild;
141+
const commonParent = childs.find(child => child) as ArrayChild;
140142

141143
return commonParent || this;
142144
}
143145
public findNextChild(
144146
target: HTMLElement | SVGElement,
145147
range: TargetGroupsType = this.toTargetGroups(),
146148
isExact = true,
147-
): GroupArrayChild | null {
148-
let nextChild: GroupArrayChild | null = null;
149+
): ArrayChild | null {
150+
let nextChild: ArrayChild | null = null;
149151

150152
const length = range.length;
151153

@@ -176,7 +178,7 @@ export class GroupArrayChild extends Child {
176178
target: HTMLElement | SVGElement,
177179
selected: Array<HTMLElement | SVGElement>,
178180
range: TargetGroupsType = this.toTargetGroups(),
179-
): GroupArrayChild | null {
181+
): ArrayChild | null {
180182
// [[1, 2]] => group([1, 2]) exact
181183
// [[[1, 2], 3]] => group([1, 2])
182184
const nextChild = this.findNextChild(target, range, true);
@@ -196,8 +198,8 @@ export class GroupArrayChild extends Child {
196198
public findPureChild(
197199
target: HTMLElement | SVGElement,
198200
range: Array<HTMLElement | SVGElement>,
199-
): GroupArrayChild | null {
200-
let nextGroupChild: GroupArrayChild | null = null;
201+
): ArrayChild | null {
202+
let nextGroupChild: ArrayChild | null = null;
201203

202204
const childSelected = range.filter(element => this.has(element));
203205

@@ -220,14 +222,26 @@ export class GroupArrayChild extends Child {
220222
public findNextPureChild(
221223
target: HTMLElement | SVGElement,
222224
range: Array<HTMLElement | SVGElement>,
223-
): GroupArrayChild | null {
225+
): ArrayChild | null {
224226
const nextChild = this.findNextChild(target);
225227

226228
if (nextChild) {
227229
return nextChild.findPureChild(target, range);
228230
}
229231
return null;
230232
}
233+
public getSingleChild(): SingleChild | null {
234+
const groupElement = this.groupElement;
235+
236+
if (groupElement) {
237+
const singleChild = this.parent?.value.find(t => t.value === groupElement);
238+
239+
if (singleChild) {
240+
return singleChild as SingleChild;
241+
}
242+
}
243+
return null;
244+
}
231245
public toTargetGroups(): TargetGroupsType {
232246
return this.value.map(child => {
233247
if (child.type === "single") {
@@ -237,7 +251,7 @@ export class GroupArrayChild extends Child {
237251
}
238252
});
239253
}
240-
public findArrayChild(targets: TargetGroupsType): GroupArrayChild | null {
254+
public findArrayChild(targets: TargetGroupsType): ArrayChild | null {
241255
const {
242256
value,
243257
} = this;
@@ -268,7 +282,7 @@ export class GroupArrayChild extends Child {
268282
if (result && targets.length === value.length) {
269283
return this;
270284
} else {
271-
let childResult: GroupArrayChild | null = null;
285+
let childResult: ArrayChild | null = null;
272286

273287
value.some(child => {
274288
if (child.type === "group") {
@@ -287,36 +301,39 @@ export class GroupArrayChild extends Child {
287301
return child.compare(selected, -1);
288302
}
289303
return selected.indexOf(child.value) > -1;
304+
}).map(child => {
305+
if (child.type !== "single") {
306+
const singleChild = child.getSingleChild();
307+
308+
if (singleChild) {
309+
return singleChild;
310+
}
311+
}
312+
return child;
290313
});
291314
}
292315
public add(targets: TargetGroupsObject) {
293316
const {
294317
value,
295318
map,
296319
} = this;
297-
const depth = this.depth;
298320

299321
targets.forEach(child => {
300322
if ("groupId" in child) {
301-
const group = new GroupArrayChild(this);
323+
const group = new ArrayChild(this);
302324

303325
group.id = child.groupId;
304-
group.depth = depth + 1;
305326
value.push(group);
306-
307327
group.add(child.children);
308328
} else if (isArray(child)) {
309-
const group = new GroupArrayChild(this);
329+
const group = new ArrayChild(this);
310330

311-
group.depth = depth + 1;
312331
value.push(group);
313-
314332
group.add(child);
315333
} else {
316334
const element = "current" in child ? child.current : child;
317-
const single = new GroupSingleChild(this, element!);
335+
const single = new SingleChild(this, element!);
318336

319-
single.depth = depth + 1;
320337
value.push(single);
321338
map.set(element!, single);
322339
}
@@ -331,6 +348,32 @@ export class GroupArrayChild extends Child {
331348
});
332349
}
333350
});
351+
352+
value.forEach(child => {
353+
if (child.type !== "single") {
354+
return;
355+
}
356+
// single
357+
const singleElement = child.value;
358+
const groupChild = value.find(child2 => {
359+
if (child2.type === "single") {
360+
return;
361+
}
362+
const firstElement = [...child2.map.keys()][0];
363+
364+
if (!firstElement) {
365+
return;
366+
}
367+
368+
return singleElement.contains(firstElement);
369+
});
370+
371+
(child as SingleChild).isGroupElement = !!groupChild;
372+
373+
if (groupChild) {
374+
(groupChild as ArrayChild).groupElement = child.value;
375+
}
376+
});
334377
return parent;
335378
}
336379
}

packages/helper/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { GroupArrayChild, GroupSingleChild } from "./groups";
1+
import { ArrayChild, SingleChild } from "./groups";
22

33
export type TargetGroupWithId = { groupId: string; children: TargetGroupsObject };
44
export type TargetRef = { current: HTMLElement | SVGElement | null };
55
export type TargetGroupsObject
66
= Array<HTMLElement | SVGElement | TargetRef | TargetGroupsObject | TargetGroupWithId>;
77
export type TargetGroupsType = Array<HTMLElement | SVGElement | TargetGroupsType>;
8-
export type GroupChild = GroupSingleChild | GroupArrayChild;
8+
export type GroupChild = SingleChild | ArrayChild;
99

1010
export interface TargetList {
1111
raw(): GroupChild[];

0 commit comments

Comments
 (0)