From 8434ed19853a158739b3e9b936d63825c6824c96 Mon Sep 17 00:00:00 2001 From: Daybrush Date: Wed, 21 Jun 2023 04:31:33 +0900 Subject: [PATCH] feat: add group, ungroup in helper --- packages/helper/package.json | 2 +- packages/helper/src/GroupManager.ts | 108 +++++++++++++++------------- packages/helper/src/groups.ts | 52 +++++++++++++- 3 files changed, 111 insertions(+), 51 deletions(-) diff --git a/packages/helper/package.json b/packages/helper/package.json index 55efa8baa..5cf99c6b5 100644 --- a/packages/helper/package.json +++ b/packages/helper/package.json @@ -1,6 +1,6 @@ { "name": "@moveable/helper", - "version": "0.1.2", + "version": "0.1.3", "description": "Helper for demo of Moveable", "main": "./dist/helper.cjs.js", "module": "./dist/helper.esm.js", diff --git a/packages/helper/src/GroupManager.ts b/packages/helper/src/GroupManager.ts index 3ef0f5e03..6cae204f7 100644 --- a/packages/helper/src/GroupManager.ts +++ b/packages/helper/src/GroupManager.ts @@ -4,52 +4,6 @@ import { GroupArrayChild, GroupSingleChild } from "./groups"; import { GroupChild, TargetGroupsObject, TargetGroupsType, TargetList } from "./types"; -function createGroupChildren( - targetGroups: TargetGroupsObject, - parent: GroupArrayChild, -) { - const { - value, - map, - } = parent; - targetGroups.forEach(child => { - if ("groupId" in child) { - const group = new GroupArrayChild(parent); - - group.id = child.groupId; - group.depth = parent.depth + 1; - value.push(group); - - createGroupChildren(child.children, group); - } else if (isArray(child)) { - const group = new GroupArrayChild(parent); - - group.depth = parent.depth + 1; - value.push(group); - - createGroupChildren(child, group); - } else { - const element = "current" in child ? child.current : child; - const single = new GroupSingleChild(parent, element!); - - single.depth = parent.depth + 1; - value.push(single); - map.set(element!, single); - } - }); - - value.forEach(child => { - if (child.type === "single") { - map.set(child.value, child); - } else { - child.map.forEach((nextChild, element) => { - map.set(element, nextChild); - }); - } - }); - return parent; -} - export function toTargetList(raw: GroupChild[]): TargetList { function targets(childs: GroupChild[] = []) { const arr: TargetGroupsType = []; @@ -78,6 +32,8 @@ export function toTargetList(raw: GroupChild[]): TargetList { export class GroupManager extends GroupArrayChild { public type = "root" as const; + private _targets: Array = []; + constructor( targetGroups: TargetGroupsType, targets?: Array, @@ -95,8 +51,7 @@ export class GroupManager extends GroupArrayChild { const map = this.map; const value = this.value; - createGroupChildren(targetGroups, this); - + this.add(targetGroups); targets.forEach(target => { if (map.has(target)) { return; @@ -107,6 +62,7 @@ export class GroupManager extends GroupArrayChild { value.push(single); map.set(target, single); }); + this._targets = targets; } public selectSubChilds(targets: TargetGroupsType, target: HTMLElement | SVGElement) { const root = this; @@ -300,6 +256,62 @@ export class GroupManager extends GroupArrayChild { return value; } + public group(targets: TargetGroupsType, flatten?: boolean): TargetGroupsType | null { + const commonParent = this.findCommonParent(targets); + const groupChilds = targets.map(target => { + if (isArray(target)) { + return this.findArrayChild(target); + } + return this.toSingleChild(target); + }); + const isGroupable = groupChilds.every(child => child?.parent === commonParent); + + if (!isGroupable) { + return null; + } + const group = new GroupArrayChild(commonParent); + const nextChilds = commonParent.value.filter(target => groupChilds.indexOf(target) === -1); + + nextChilds.unshift(group); + + group.add(flatten ? deepFlat(targets) : targets); + commonParent.value = nextChilds; + + this.set(this.toTargetGroups(), this._targets); + + return group.toTargetGroups(); + } + public ungroup(targets: TargetGroupsType) { + if (targets.length === 1 && isArray(targets[0])) { + targets = targets[0]; + } + const commonParent = this.findCommonParent(targets); + const groupChilds = targets.map(target => { + if (isArray(target)) { + return this.findArrayChild(target); + } + return this.toSingleChild(target); + }); + const isGroupable = commonParent.value.every(child => groupChilds.indexOf(child) > -1); + + if (!isGroupable || commonParent === this) { + // has no group + return null; + } + + const parent = commonParent.parent; + + if (!parent) { + return null; + } + const nextChilds = parent.value.filter(target => target !== commonParent); + + nextChilds.push(...commonParent.value); + parent.value = nextChilds; + + this.set(this.toTargetGroups(), this._targets); + return commonParent.toTargetGroups(); + } protected _findParentGroup( element: HTMLElement | SVGElement, range: Array, diff --git a/packages/helper/src/groups.ts b/packages/helper/src/groups.ts index 15745ab84..1e17f8365 100644 --- a/packages/helper/src/groups.ts +++ b/packages/helper/src/groups.ts @@ -1,11 +1,15 @@ import { isArray, deepFlat, find } from "@daybrush/utils"; -import { GroupChild, TargetGroupsType } from "./types"; +import { GroupChild, TargetGroupsObject, TargetGroupsType } from "./types"; export class Child { public type: "group" | "root" | "single" = "single"; public depth = 0; protected _scope: string[] = []; - constructor(public parent?: GroupArrayChild) {} + constructor(public parent?: GroupArrayChild) { + if (parent) { + this.depth = parent.depth + 1; + } + } public get scope(): string[] { const parent = this.parent; @@ -285,4 +289,48 @@ export class GroupArrayChild extends Child { return selected.indexOf(child.value) > -1; }); } + public add(targets: TargetGroupsObject) { + const { + value, + map, + } = this; + const depth = this.depth; + + targets.forEach(child => { + if ("groupId" in child) { + const group = new GroupArrayChild(this); + + group.id = child.groupId; + group.depth = depth + 1; + value.push(group); + + group.add(child.children); + } else if (isArray(child)) { + const group = new GroupArrayChild(this); + + group.depth = depth + 1; + value.push(group); + + group.add(child); + } else { + const element = "current" in child ? child.current : child; + const single = new GroupSingleChild(this, element!); + + single.depth = depth + 1; + value.push(single); + map.set(element!, single); + } + }); + + value.forEach(child => { + if (child.type === "single") { + map.set(child.value, child); + } else { + child.map.forEach((nextChild, element) => { + map.set(element, nextChild); + }); + } + }); + return parent; + } }