selection.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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. elements.some((element) => appState.selectedElementIds[element.id]);
  35. /**
  36. * Returns common attribute (picked by `getAttribute` callback) of selected
  37. * elements. If elements don't share the same value, returns `null`.
  38. */
  39. export const getCommonAttributeOfSelectedElements = <T>(
  40. elements: readonly NonDeletedExcalidrawElement[],
  41. appState: AppState,
  42. getAttribute: (element: ExcalidrawElement) => T,
  43. ): T | null => {
  44. const attributes = Array.from(
  45. new Set(
  46. getSelectedElements(elements, appState).map((element) =>
  47. getAttribute(element),
  48. ),
  49. ),
  50. );
  51. return attributes.length === 1 ? attributes[0] : null;
  52. };
  53. export const getSelectedElements = (
  54. elements: readonly NonDeletedExcalidrawElement[],
  55. appState: AppState,
  56. ) => elements.filter((element) => appState.selectedElementIds[element.id]);
  57. export const getTargetElements = (
  58. elements: readonly NonDeletedExcalidrawElement[],
  59. appState: AppState,
  60. ) =>
  61. appState.editingElement
  62. ? [appState.editingElement]
  63. : getSelectedElements(elements, appState);