Browse Source

Add shortcuts (#85)

* Add yarn.lock to .gitignore

* Extract available shapes to one place

* Add event listeners for shapes shortcuts

* fixup! Add event listeners for shapes shortcuts

* Underline first letter of shapes

to indicate interactivity

* fixup! Extract available shapes to one place

* fixup! Add event listeners for shapes shortcuts
Alex Bratsos 5 years ago
parent
commit
58d81280c9
3 changed files with 64 additions and 28 deletions
  1. 3 0
      .gitignore
  2. 53 28
      src/index.tsx
  3. 8 0
      src/styles.css

+ 3 - 0
.gitignore

@@ -11,6 +11,9 @@ build
 # Dependency directories
 # Dependency directories
 node_modules/
 node_modules/
 
 
+# lock file
+yarn.lock
+
 # Editors
 # Editors
 .vscode/
 .vscode/
 
 

+ 53 - 28
src/index.tsx

@@ -118,6 +118,9 @@ function hitTest(element: ExcalidrawElement, x: number, y: number): boolean {
     const y2 = getElementAbsoluteY2(element);
     const y2 = getElementAbsoluteY2(element);
 
 
     return x >= x1 && x <= x2 && y >= y1 && y <= y2;
     return x >= x1 && x <= x2 && y >= y1 && y <= y2;
+  } else if (element.type === "selection") {
+    console.warn("This should not happen, we need to investigate why it does.");
+    return false;
   } else {
   } else {
     throw new Error("Unimplemented type " + element.type);
     throw new Error("Unimplemented type " + element.type);
   }
   }
@@ -571,6 +574,40 @@ const KEYS = {
   BACKSPACE: "Backspace"
   BACKSPACE: "Backspace"
 };
 };
 
 
+const SHAPES = [
+  {
+    label: "Rectange",
+    value: "rectangle"
+  },
+  {
+    label: "Ellipse",
+    value: "ellipse"
+  },
+  {
+    label: "Arrow",
+    value: "arrow"
+  },
+  {
+    label: "Text",
+    value: "text"
+  },
+  {
+    label: "Selection",
+    value: "selection"
+  }
+];
+
+const shapesShortcutKeys = SHAPES.map(shape => shape.label[0].toLowerCase());
+
+function findElementByKey(key: string) {
+  const defaultElement = "selection";
+  return SHAPES.reduce((element, shape) => {
+    if (shape.value[0] !== key) return element;
+
+    return shape.value;
+  }, defaultElement);
+}
+
 function isArrowKey(keyCode: string) {
 function isArrowKey(keyCode: string) {
   return (
   return (
     keyCode === KEYS.ARROW_LEFT ||
     keyCode === KEYS.ARROW_LEFT ||
@@ -643,32 +680,11 @@ class App extends React.Component<{}, AppState> {
       });
       });
       this.forceUpdate();
       this.forceUpdate();
       event.preventDefault();
       event.preventDefault();
+    } else if (shapesShortcutKeys.includes(event.key.toLowerCase())) {
+      this.setState({ elementType: findElementByKey(event.key) });
     }
     }
   };
   };
 
 
-  private renderOption({
-    type,
-    children
-  }: {
-    type: string;
-    children: React.ReactNode;
-  }) {
-    return (
-      <label>
-        <input
-          type="radio"
-          checked={this.state.elementType === type}
-          onChange={() => {
-            this.setState({ elementType: type });
-            clearSelection();
-            this.forceUpdate();
-          }}
-        />
-        {children}
-      </label>
-    );
-  }
-
   public render() {
   public render() {
     return (
     return (
       <div
       <div
@@ -713,11 +729,20 @@ class App extends React.Component<{}, AppState> {
       >
       >
         <fieldset>
         <fieldset>
           <legend>Shapes</legend>
           <legend>Shapes</legend>
-          {this.renderOption({ type: "rectangle", children: "Rectangle" })}
-          {this.renderOption({ type: "ellipse", children: "Ellipse" })}
-          {this.renderOption({ type: "arrow", children: "Arrow" })}
-          {this.renderOption({ type: "text", children: "Text" })}
-          {this.renderOption({ type: "selection", children: "Selection" })}
+          {SHAPES.map(({ value, label }) => (
+            <label>
+              <input
+                type="radio"
+                checked={this.state.elementType === value}
+                onChange={() => {
+                  this.setState({ elementType: value });
+                  clearSelection();
+                  this.forceUpdate();
+                }}
+              />
+              <span>{label}</span>
+            </label>
+          ))}
         </fieldset>
         </fieldset>
 
 
         <canvas
         <canvas

+ 8 - 0
src/styles.css

@@ -18,6 +18,14 @@ label {
   margin-right: 10px;
   margin-right: 10px;
 }
 }
 
 
+label span {
+  display: inline-block;
+}
+
+label span::first-letter {
+  text-decoration: underline;
+}
+
 input[type="number"] {
 input[type="number"] {
   width: 30px;
   width: 30px;
 }
 }