Compare commits

..

5 Commits

Author SHA1 Message Date
zsviczian
60a3584e86 change css back to original 2023-10-07 10:38:46 +02:00
zsviczian
fa0e653236 lint 2023-10-07 10:37:37 +02:00
zsviczian
16de3d9243 add svgContainer offset 2023-10-07 10:35:06 +02:00
zsviczian
c65d6506f7 fix lasertool offset 2023-10-07 08:49:32 +02:00
David Luzar
a249f332a2 fix: ensure we do not stop laser update prematurely (#7100) 2023-10-06 12:00:35 +02:00
6 changed files with 39 additions and 57 deletions

View File

@@ -30,7 +30,6 @@ All `props` are *optional*.
| [`generateIdForFile`](#generateidforfile) | `function` | _ | Allows you to override `id` generation for files added on canvas |
| [`validateEmbeddable`](#validateEmbeddable) | string[] | `boolean | RegExp | RegExp[] | ((link: string) => boolean | undefined)` | \_ | use for custom src url validation |
| [`renderEmbeddable`](/docs/@excalidraw/excalidraw/api/props/render-props#renderEmbeddable) | `function` | \_ | Render function that can override the built-in `<iframe>` |
| [`activeTool`](#activeTool) | `object` | - | Set the active editor tool (forced) |
### Storing custom data on Excalidraw elements
@@ -237,19 +236,4 @@ validateEmbeddable?: boolean | string[] | RegExp | RegExp[] | ((link: string) =>
This is an optional property. By default we support a handful of well-known sites. You may allow additional sites or disallow the default ones by supplying a custom validator. If you pass `true`, all URLs will be allowed. You can also supply a list of hostnames, RegExp (or list of RegExp objects), or a function. If the function returns `undefined`, the built-in validator will be used.
Supplying a list of hostnames (with or without `www.`) is the preferred way to allow a specific list of domains.
### activeTool
```ts
activeTool?:
| {
type: ToolType;
}
| {
type: "custom";
customType: string;
};
```
Tool to be force-set as active. As long as the prop is set, the editor active tool will be set to this. Useful only in specific circumstances such as when UI is disabled and the editor should be limited to just one tool (such as a laser pointer).
Supplying a list of hostnames (with or without `www.`) is the preferred way to allow a specific list of domains.

View File

@@ -1903,13 +1903,6 @@ class App extends React.Component<AppProps, AppState> {
this.refreshDeviceState(this.excalidrawContainerRef.current);
}
if (
this.props.activeTool &&
this.props.activeTool.type !== this.state.activeTool.type
) {
this.setActiveTool(this.props.activeTool);
}
if (
prevState.scrollX !== this.state.scrollX ||
prevState.scrollY !== this.state.scrollY
@@ -3143,7 +3136,11 @@ class App extends React.Component<AppProps, AppState> {
| { type: "custom"; customType: string },
) => {
const nextActiveTool = updateActiveTool(this.state, tool);
if (nextActiveTool.type === "hand") {
setCursor(this.interactiveCanvas, CURSOR_TYPE.GRAB);
} else if (!isHoldingSpace) {
setCursorForShape(this.interactiveCanvas, this.state);
}
if (isToolIcon(document.activeElement)) {
this.focusContainer();
}
@@ -3160,10 +3157,8 @@ class App extends React.Component<AppProps, AppState> {
originSnapOffset: null,
activeEmbeddable: null,
} as const;
let nextState: AppState;
if (nextActiveTool.type !== "selection") {
nextState = {
return {
...prevState,
activeTool: nextActiveTool,
selectedElementIds: makeNextSelectedElementIds({}, prevState),
@@ -3172,21 +3167,12 @@ class App extends React.Component<AppProps, AppState> {
multiElement: null,
...commonResets,
};
} else {
nextState = {
...prevState,
activeTool: nextActiveTool,
...commonResets,
};
}
if (nextActiveTool.type === "hand") {
setCursor(this.interactiveCanvas, CURSOR_TYPE.GRAB);
} else if (!isHoldingSpace) {
setCursorForShape(this.interactiveCanvas, nextState);
}
return nextState;
return {
...prevState,
activeTool: nextActiveTool,
...commonResets,
};
});
};

View File

@@ -91,7 +91,7 @@ export class LaserPathManager {
private collaboratorsState: Map<string, CollabolatorState> = new Map();
private rafId: number | undefined;
private lastUpdate = 0;
private isDrawing = false;
private container: SVGSVGElement | undefined;
constructor(private app: App) {
@@ -100,12 +100,19 @@ export class LaserPathManager {
destroy() {
this.stop();
this.lastUpdate = 0;
this.isDrawing = false;
this.ownState = instantiateCollabolatorState();
this.collaboratorsState = new Map();
}
startPath(x: number, y: number) {
if (this.container) {
this.container.style.top = "0px";
this.container.style.left = "0px";
const { x, y } = this.container.getBoundingClientRect();
this.container.style.top = `${-y}px`;
this.container.style.left = `${-x}px`;
}
this.ownState.currentPath = instantiatePath();
this.ownState.currentPath.addPoint([x, y, performance.now()]);
this.updatePath(this.ownState);
@@ -127,7 +134,7 @@ export class LaserPathManager {
}
private updatePath(state: CollabolatorState) {
this.lastUpdate = performance.now();
this.isDrawing = true;
if (!this.isRunning) {
this.start();
@@ -160,7 +167,7 @@ export class LaserPathManager {
this.updateCollabolatorsState();
if (performance.now() - this.lastUpdate < DECAY_TIME * 2) {
if (this.isDrawing) {
this.update();
} else {
this.isRunning = false;
@@ -250,6 +257,8 @@ export class LaserPathManager {
return;
}
let somePathsExist = false;
for (const [key, state] of this.collaboratorsState.entries()) {
if (!this.app.state.collaborators.has(key)) {
state.svg.remove();
@@ -269,6 +278,10 @@ export class LaserPathManager {
paths += ` ${this.draw(state.currentPath)}`;
}
if (paths.trim()) {
somePathsExist = true;
}
state.svg.setAttribute("d", paths);
state.svg.setAttribute("fill", getClientColor(key));
}
@@ -287,7 +300,17 @@ export class LaserPathManager {
paths += ` ${this.draw(this.ownState.currentPath)}`;
}
paths = paths.trim();
if (paths) {
somePathsExist = true;
}
this.ownState.svg.setAttribute("d", paths);
this.ownState.svg.setAttribute("fill", "red");
if (!somePathsExist) {
this.isDrawing = false;
}
}
}

View File

@@ -6,7 +6,6 @@
position: fixed;
top: 0;
left: 0;
z-index: 2;
.LaserToolOverlayCanvas {

View File

@@ -44,7 +44,6 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
children,
validateEmbeddable,
renderEmbeddable,
activeTool,
} = props;
const canvasActions = props.UIOptions?.canvasActions;
@@ -120,7 +119,6 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
onScrollChange={onScrollChange}
validateEmbeddable={validateEmbeddable}
renderEmbeddable={renderEmbeddable}
activeTool={activeTool}
>
{children}
</App>

View File

@@ -445,14 +445,6 @@ export interface ExcalidrawProps {
element: NonDeleted<ExcalidrawEmbeddableElement>,
appState: AppState,
) => JSX.Element | null;
activeTool?:
| {
type: ToolType;
}
| {
type: "custom";
customType: string;
};
}
export type SceneData = {