Feature: Hint viewer (#666)
* Add Hint viewer - Add hints for arrows and lines - Add hints for resizing elements * Swap priority of multi mode and resize mode in Hint Viewer * Remove dangling locales from public * Add shortcut to hide hints * Change hint texts and show resize hint ONLY during resizing * Remove hints toggling
This commit is contained in:
parent
23d40ae4a5
commit
f70bd0081c
@ -26,6 +26,7 @@ export function getDefaultAppState(): AppState {
|
|||||||
cursorY: 0,
|
cursorY: 0,
|
||||||
scrolledOutside: false,
|
scrolledOutside: false,
|
||||||
name: DEFAULT_PROJECT_NAME,
|
name: DEFAULT_PROJECT_NAME,
|
||||||
|
isResizing: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
src/components/HintViewer.css
Normal file
6
src/components/HintViewer.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.HintViewer {
|
||||||
|
position: absolute;
|
||||||
|
left: 0.5em;
|
||||||
|
bottom: 0.5em;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
55
src/components/HintViewer.tsx
Normal file
55
src/components/HintViewer.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { t } from "../i18n";
|
||||||
|
import { ExcalidrawElement } from "../element/types";
|
||||||
|
|
||||||
|
import "./HintViewer.css";
|
||||||
|
|
||||||
|
interface Hint {
|
||||||
|
elementType: string;
|
||||||
|
multiMode: boolean;
|
||||||
|
isResizing: boolean;
|
||||||
|
elements: readonly ExcalidrawElement[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const getHints = ({ elementType, multiMode, isResizing, elements }: Hint) => {
|
||||||
|
if (elementType === "arrow" || elementType === "line") {
|
||||||
|
if (!multiMode) {
|
||||||
|
return t("hints.linearElement");
|
||||||
|
}
|
||||||
|
return t("hints.linearElementMulti");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isResizing) {
|
||||||
|
const selectedElements = elements.filter(el => el.isSelected);
|
||||||
|
if (
|
||||||
|
selectedElements.length === 1 &&
|
||||||
|
(selectedElements[0].type === "arrow" ||
|
||||||
|
selectedElements[0].type === "line") &&
|
||||||
|
selectedElements[0].points.length > 2
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return t("hints.resize");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HintViewer = ({
|
||||||
|
elementType,
|
||||||
|
multiMode,
|
||||||
|
isResizing,
|
||||||
|
elements,
|
||||||
|
}: Hint) => {
|
||||||
|
const hint = getHints({
|
||||||
|
elementType,
|
||||||
|
multiMode,
|
||||||
|
isResizing,
|
||||||
|
elements,
|
||||||
|
});
|
||||||
|
if (!hint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className="HintViewer">{hint}</div>;
|
||||||
|
};
|
@ -99,6 +99,7 @@ import { LanguageList } from "./components/LanguageList";
|
|||||||
import { Point } from "roughjs/bin/geometry";
|
import { Point } from "roughjs/bin/geometry";
|
||||||
import { t, languages, setLanguage, getLanguage } from "./i18n";
|
import { t, languages, setLanguage, getLanguage } from "./i18n";
|
||||||
import { StoredScenesList } from "./components/StoredScenesList";
|
import { StoredScenesList } from "./components/StoredScenesList";
|
||||||
|
import { HintViewer } from "./components/HintViewer";
|
||||||
|
|
||||||
let { elements } = createScene();
|
let { elements } = createScene();
|
||||||
const { history } = createHistory();
|
const { history } = createHistory();
|
||||||
@ -1186,6 +1187,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isResizingElements && this.state.resizingElement) {
|
if (isResizingElements && this.state.resizingElement) {
|
||||||
|
this.setState({ isResizing: true });
|
||||||
const el = this.state.resizingElement;
|
const el = this.state.resizingElement;
|
||||||
const selectedElements = elements.filter(el => el.isSelected);
|
const selectedElements = elements.filter(el => el.isSelected);
|
||||||
if (selectedElements.length === 1) {
|
if (selectedElements.length === 1) {
|
||||||
@ -1541,6 +1543,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onMouseUp = (e: MouseEvent) => {
|
const onMouseUp = (e: MouseEvent) => {
|
||||||
|
this.setState({ isResizing: false });
|
||||||
const {
|
const {
|
||||||
draggingElement,
|
draggingElement,
|
||||||
resizingElement,
|
resizingElement,
|
||||||
@ -1805,6 +1808,13 @@ export class App extends React.Component<any, AppState> {
|
|||||||
</canvas>
|
</canvas>
|
||||||
</main>
|
</main>
|
||||||
<footer role="contentinfo">
|
<footer role="contentinfo">
|
||||||
|
<HintViewer
|
||||||
|
elementType={this.state.elementType}
|
||||||
|
multiMode={this.state.multiElement !== null}
|
||||||
|
isResizing={this.state.isResizing}
|
||||||
|
elements={elements}
|
||||||
|
/>
|
||||||
|
|
||||||
<LanguageList
|
<LanguageList
|
||||||
onChange={lng => {
|
onChange={lng => {
|
||||||
setLanguage(lng);
|
setLanguage(lng);
|
||||||
|
@ -77,5 +77,10 @@
|
|||||||
"canvasActions": "Canvas actions",
|
"canvasActions": "Canvas actions",
|
||||||
"selectedShapeActions": "Selected shape actions",
|
"selectedShapeActions": "Selected shape actions",
|
||||||
"shapes": "Shapes"
|
"shapes": "Shapes"
|
||||||
|
},
|
||||||
|
"hints": {
|
||||||
|
"linearElement": "Click to start multiple points, drag for single line",
|
||||||
|
"linearElementMulti": "Press Escape or Enter to finish",
|
||||||
|
"resize": "You can constraint proportions by holding SHIFT while resizing"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,5 @@ export type AppState = {
|
|||||||
scrolledOutside: boolean;
|
scrolledOutside: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
selectedId?: string;
|
selectedId?: string;
|
||||||
|
isResizing: boolean;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user