HintViewer.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { t } from "../i18n";
  2. import { NonDeletedExcalidrawElement } from "../element/types";
  3. import { getSelectedElements } from "../scene";
  4. import "./HintViewer.scss";
  5. import { AppState } from "../types";
  6. import {
  7. isImageElement,
  8. isLinearElement,
  9. isTextElement,
  10. } from "../element/typeChecks";
  11. import { getShortcutKey } from "../utils";
  12. interface Hint {
  13. appState: AppState;
  14. elements: readonly NonDeletedExcalidrawElement[];
  15. }
  16. const getHints = ({ appState, elements }: Hint) => {
  17. const { elementType, isResizing, isRotating, lastPointerDownWith } = appState;
  18. const multiMode = appState.multiElement !== null;
  19. if (elementType === "arrow" || elementType === "line") {
  20. if (!multiMode) {
  21. return t("hints.linearElement");
  22. }
  23. return t("hints.linearElementMulti");
  24. }
  25. if (elementType === "freedraw") {
  26. return t("hints.freeDraw");
  27. }
  28. if (elementType === "text") {
  29. return t("hints.text");
  30. }
  31. if (appState.elementType === "image" && appState.pendingImageElement) {
  32. return t("hints.placeImage");
  33. }
  34. const selectedElements = getSelectedElements(elements, appState);
  35. if (
  36. isResizing &&
  37. lastPointerDownWith === "mouse" &&
  38. selectedElements.length === 1
  39. ) {
  40. const targetElement = selectedElements[0];
  41. if (isLinearElement(targetElement) && targetElement.points.length === 2) {
  42. return t("hints.lockAngle");
  43. }
  44. return isImageElement(targetElement)
  45. ? t("hints.resizeImage")
  46. : t("hints.resize");
  47. }
  48. if (isRotating && lastPointerDownWith === "mouse") {
  49. return t("hints.rotate");
  50. }
  51. if (selectedElements.length === 1 && isLinearElement(selectedElements[0])) {
  52. if (appState.editingLinearElement) {
  53. return appState.editingLinearElement.activePointIndex
  54. ? t("hints.lineEditor_pointSelected")
  55. : t("hints.lineEditor_nothingSelected");
  56. }
  57. return t("hints.lineEditor_info");
  58. }
  59. if (selectedElements.length === 1 && isTextElement(selectedElements[0])) {
  60. return t("hints.text_selected");
  61. }
  62. if (appState.editingElement && isTextElement(appState.editingElement)) {
  63. return t("hints.text_editing");
  64. }
  65. return null;
  66. };
  67. export const HintViewer = ({ appState, elements }: Hint) => {
  68. let hint = getHints({
  69. appState,
  70. elements,
  71. });
  72. if (!hint) {
  73. return null;
  74. }
  75. hint = getShortcutKey(hint);
  76. return (
  77. <div className="HintViewer">
  78. <span>{hint}</span>
  79. </div>
  80. );
  81. };