selection.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import {
  2. ExcalidrawElement,
  3. NonDeletedExcalidrawElement,
  4. } from "../element/types";
  5. import { getElementAbsoluteCoords, getElementBounds } from "../element";
  6. import { AppState } from "../types";
  7. export const getElementsWithinSelection = (
  8. elements: readonly NonDeletedExcalidrawElement[],
  9. selection: NonDeletedExcalidrawElement,
  10. ) => {
  11. const [
  12. selectionX1,
  13. selectionY1,
  14. selectionX2,
  15. selectionY2,
  16. ] = getElementAbsoluteCoords(selection);
  17. return elements.filter((element) => {
  18. const [elementX1, elementY1, elementX2, elementY2] = getElementBounds(
  19. element,
  20. );
  21. return (
  22. element.type !== "selection" &&
  23. selectionX1 <= elementX1 &&
  24. selectionY1 <= elementY1 &&
  25. selectionX2 >= elementX2 &&
  26. selectionY2 >= elementY2
  27. );
  28. });
  29. };
  30. export const isSomeElementSelected = (
  31. elements: readonly NonDeletedExcalidrawElement[],
  32. appState: AppState,
  33. ): boolean => {
  34. return elements.some((element) => appState.selectedElementIds[element.id]);
  35. };
  36. /**
  37. * Returns common attribute (picked by `getAttribute` callback) of selected
  38. * elements. If elements don't share the same value, returns `null`.
  39. */
  40. export const getCommonAttributeOfSelectedElements = <T>(
  41. elements: readonly NonDeletedExcalidrawElement[],
  42. appState: AppState,
  43. getAttribute: (element: ExcalidrawElement) => T,
  44. ): T | null => {
  45. const attributes = Array.from(
  46. new Set(
  47. getSelectedElements(elements, appState).map((element) =>
  48. getAttribute(element),
  49. ),
  50. ),
  51. );
  52. return attributes.length === 1 ? attributes[0] : null;
  53. };
  54. export const getSelectedElements = (
  55. elements: readonly NonDeletedExcalidrawElement[],
  56. appState: AppState,
  57. ) => {
  58. return elements.filter((element) => appState.selectedElementIds[element.id]);
  59. };
  60. export const getTargetElement = (
  61. elements: readonly NonDeletedExcalidrawElement[],
  62. appState: AppState,
  63. ) => {
  64. return appState.editingElement
  65. ? [appState.editingElement]
  66. : getSelectedElements(elements, appState);
  67. };