UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

107 lines (106 loc) 3.82 kB
import { computed, signal } from "@preact/signals-core"; import groupBy from "lodash/groupBy"; import { Group } from "../../components/canvas/groups"; import { MultipleSelectionBucket } from "../../services/selection/MultipleSelectionBucket"; import { ESelectionStrategy } from "../../services/selection/types"; import { GroupState } from "./Group"; export class GroupsListStore { constructor(rootStore, graph) { this.rootStore = rootStore; this.graph = graph; this.$groupsMap = signal(new Map()); this.$groups = computed(() => { return Array.from(this.$groupsMap.value.values()); }); this.$blockGroups = computed(() => { return groupBy(this.rootStore.blocksList.$blocks.value, (item) => item.$state.value.group); }); /** * Bucket for managing group selection state */ this.groupSelectionBucket = new MultipleSelectionBucket("group", (payload, defaultAction) => { this.graph.executеDefaultEventAction("groups-selection-change", payload, defaultAction); }, (element) => { return element instanceof Group; }); this.$selectedGroups = computed(() => { return Array.from(this.groupSelectionBucket.$selected.value) .map((id) => this.getGroupState(id)) .filter(Boolean); }); this.groupSelectionBucket.attachToManager(this.rootStore.selectionService); } updateGroupsMap(groups) { this.$groupsMap.value = new Map(groups); } addGroup(group) { this.$groupsMap.value.set(group.id, this.getOrCreateGroupState(group)); this.updateGroupsMap(this.$groupsMap.value); return group.id; } deleteGroups(groups) { const map = new Map(this.$groupsMap.value); groups.forEach((gId) => { const id = typeof gId === "string" ? gId : gId.id; map.delete(id); }); this.updateGroupsMap(map); } updateGroups(groups) { this.updateGroupsMap(groups.reduce((acc, group) => { const state = this.getOrCreateGroupState(group); acc.set(group.id, state); return acc; }, this.$groupsMap.value)); } setGroups(groups) { const groupStates = groups.map((group) => this.getOrCreateGroupState(group)); this.applyGroupsState(groupStates); } getOrCreateGroupState(group) { const groupState = this.$groupsMap.value.get(group.id); if (groupState) { groupState.updateGroup(group); return groupState; } return GroupState.fromTGroup(this, group); } applyGroupsState(groups) { this.updateGroupsMap(groups.map((group) => [group.id, group])); } getGroupState(id) { return this.$groupsMap.value.get(id); } getGroup(id) { return this.getGroupState(id)?.asTGroup(); } reset() { this.applyGroupsState([]); } toJSON() { return this.$groups.value.map((group) => group.asTGroup()); } /** * Updates group selection using the SelectionService * @param ids Group IDs to update selection for * @param selected Whether to select or deselect * @param strategy The selection strategy to apply */ updateGroupsSelection(ids, selected, strategy = ESelectionStrategy.REPLACE) { if (selected) { this.groupSelectionBucket.select(ids, strategy); } else { this.groupSelectionBucket.deselect(ids); } } /** * Resets the selection for groups */ resetSelection() { this.groupSelectionBucket.reset(); } getGroupStates(ids) { return ids.map((id) => this.getGroupState(id)).filter(Boolean); } }