function groupSelect(canvas, elems, inRect) {
	/** @param {{position:Point}} data */
	const shapeInRect = data => inRect ? inRect(data.position) : true;

	/** @type {Selected} */
	const selected = {
		shapes: [],
		shapesPaths: [],
		pathEnds: [],
		pathEndsPaths: []
	};

	/**
	 * @param {ShapeOrPathElement} pathEl,  @param {PathEnd} pathEnd, @param {string} highlightClass
	 * @returns {1|2|0}
	 */
	function pathEndInRect(pathEl, pathEnd, highlightClass) {
		if (!pathEnd.shape && shapeInRect(pathEnd.data)) {
			selected.pathEnds.push(pathEnd);
			classAdd(pathEl, highlightClass);
			return 1; // connect to end in rect
		} else if (pathEnd.shape && shapeInRect(pathEnd.shape.shapeEl[ShapeSmbl].data)) {
			return 2; // connect to shape in rect
		}
		return 0; // not in rect
	}

	for (const shapeEl of elems) {
		if (shapeEl[ShapeSmbl]) {
			if (shapeInRect(shapeEl[ShapeSmbl].data)) {
				classAdd(shapeEl, highlightClass);
				selected.shapes.push(shapeEl);
			}
		} else if (shapeEl[PathSmbl]) {
			const isStartIn = pathEndInRect(shapeEl, shapeEl[PathSmbl].data.s, highlightSClass);
			const isEndIn = pathEndInRect(shapeEl, shapeEl[PathSmbl].data.e, highlightEClass);

			if (isStartIn === 1 || isEndIn === 1) {
				selected.pathEndsPaths.push(shapeEl);
			}

			if (isStartIn === 2 || isEndIn === 2) {
				selected.shapesPaths.push(shapeEl);
			}
		}
	}

	groupEvtProc(canvas, selected);
}
Highlight selected shapes and procces group operations (move, del, copy)
@param {CanvasElement} canvas
@param {Iterable<ShapeOrPathElement>} elems
@param {{(position:Point):boolean}=} inRect