diff --git a/packages/element/src/linearElementEditor.ts b/packages/element/src/linearElementEditor.ts index 33dc7d3bc..ce74950e9 100644 --- a/packages/element/src/linearElementEditor.ts +++ b/packages/element/src/linearElementEditor.ts @@ -1313,14 +1313,14 @@ export class LinearElementEditor { element.points[element.points.length - 1]; // break polygon if deleting start/end point - if (isLineElement(element) && element.loopLock) { + if (isLineElement(element) && element.polygon) { if ( pointIndices.includes(0) || (pointIndices.includes(element.points.length - 1) && // don't disable polygon if cleaning up uncommitted point !isUncommittedPoint) ) { - app.scene.mutateElement(element, { loopLock: false }); + app.scene.mutateElement(element, { polygon: false }); } } @@ -1328,7 +1328,7 @@ export class LinearElementEditor { return !pointIndices.includes(idx); }); - if (isUncommittedPoint && isLineElement(element) && element.loopLock) { + if (isUncommittedPoint && isLineElement(element) && element.polygon) { nextPoints[0] = pointFrom( nextPoints[nextPoints.length - 1][0], nextPoints[nextPoints.length - 1][1], @@ -1357,7 +1357,7 @@ export class LinearElementEditor { ) { const nextPoints = [...element.points, ...addedPoints]; - if (isLineElement(element) && element.loopLock) { + if (isLineElement(element) && element.polygon) { nextPoints[0] = pointFrom( nextPoints[nextPoints.length - 1][0], nextPoints[nextPoints.length - 1][1], @@ -1391,7 +1391,7 @@ export class LinearElementEditor { const { points } = element; // Handle loop lock behavior - if (isLineElement(element) && element.loopLock) { + if (isLineElement(element) && element.polygon) { const firstPointUpdate = pointUpdates.get(0); const lastPointUpdate = pointUpdates.get(points.length - 1); diff --git a/packages/element/src/newElement.ts b/packages/element/src/newElement.ts index 948f52073..17d309899 100644 --- a/packages/element/src/newElement.ts +++ b/packages/element/src/newElement.ts @@ -475,7 +475,7 @@ export const newLinearElement = ( if (isLineElement(element)) { const lineElement: NonDeleted = { ...element, - loopLock: false, + polygon: false, }; return lineElement; diff --git a/packages/element/src/shapes.ts b/packages/element/src/shapes.ts index 4ed71a29e..d64a0ca37 100644 --- a/packages/element/src/shapes.ts +++ b/packages/element/src/shapes.ts @@ -426,7 +426,7 @@ export const toggleLinePolygonState = ( // TODO: satisfies ElementUpdate const ret = { - loopLock: nextPolygonState, + polygon: nextPolygonState, points: updatedPoints, }; diff --git a/packages/element/src/types.ts b/packages/element/src/types.ts index d444eab53..58f773ee9 100644 --- a/packages/element/src/types.ts +++ b/packages/element/src/types.ts @@ -331,7 +331,7 @@ export type ExcalidrawLinearElement = _ExcalidrawElementBase & export type ExcalidrawLineElement = ExcalidrawLinearElement & Readonly<{ type: "line"; - loopLock: boolean; + polygon: boolean; }>; export type FixedSegment = { diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index dea838592..6689e166a 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -136,7 +136,7 @@ export const actionFinalize = register({ if (isLineElement(multiPointElement)) { scene.mutateElement(multiPointElement, { points, - loopLock: true, + polygon: true, }); } else { scene.mutateElement(multiPointElement, { diff --git a/packages/excalidraw/actions/actionLinearEditor.tsx b/packages/excalidraw/actions/actionLinearEditor.tsx index 34984238a..c21a51a6c 100644 --- a/packages/excalidraw/actions/actionLinearEditor.tsx +++ b/packages/excalidraw/actions/actionLinearEditor.tsx @@ -94,8 +94,8 @@ export const actionToggleLinearEditor = register({ }, }); -export const actionToggleLoopLock = register({ - name: "toggleLoopLock", +export const actionTogglePolygon = register({ + name: "togglePolygon", category: DEFAULT_CATEGORIES.elements, icon: polygonIcon, keywords: ["loop"], @@ -108,10 +108,12 @@ export const actionToggleLoopLock = register({ const allLocked = selectedElements.length > 0 && selectedElements.every( - (element) => isLineElement(element) && element.loopLock, + (element) => isLineElement(element) && element.polygon, ); - return allLocked ? "labels.loopLock.unlock" : "labels.loopLock.lock"; + return allLocked + ? "labels.polygon.breakPolygon" + : "labels.polygon.convertToPolygon"; }, trackEvent: { category: "element", @@ -137,10 +139,8 @@ export const actionToggleLoopLock = register({ const targetElements = selectedElements as ExcalidrawLineElement[]; - // Check if we should lock or unlock based on current state - // If all elements are locked, unlock all. Otherwise, lock all. - const allLocked = targetElements.every((element) => element.loopLock); - const newLoopLockState = !allLocked; + // if one element not a polygon, convert all to polygon + const nextPolygonState = targetElements.some((element) => !element.polygon); const targetElementsMap = arrayToMap(targetElements); @@ -151,10 +151,10 @@ export const actionToggleLoopLock = register({ } return newElementWith(element, { - backgroundColor: newLoopLockState + backgroundColor: nextPolygonState ? element.backgroundColor : "transparent", - ...toggleLinePolygonState(element, newLoopLockState), + ...toggleLinePolygonState(element, nextPolygonState), }); }), appState, @@ -174,20 +174,21 @@ export const actionToggleLoopLock = register({ // only show polygon button if every selected element is already // a polygon, effectively showing this button only to allow for // disabling the polygon state - !element.loopLock || + !element.polygon || element.points.length < 3, ) ) { return null; } - // If all are locked, show locked icon. Otherwise show unlocked - const allLocked = selectedElements.every( - (element) => isLineElement(element) && element.loopLock, + const allPolygon = selectedElements.every( + (element) => isLineElement(element) && element.polygon, ); const label = t( - allLocked ? "labels.loopLock.unlock" : "labels.loopLock.lock", + allPolygon + ? "labels.polygon.breakPolygon" + : "labels.polygon.convertToPolygon", ); return ( @@ -195,7 +196,7 @@ export const actionToggleLoopLock = register({ icon={polygonIcon} title={label} aria-label={label} - active={allLocked} + active={allPolygon} onClick={() => updateData(null)} style={{ marginLeft: "auto" }} /> diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 40df8046c..ed079ff6d 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -1439,7 +1439,7 @@ export const actionChangeRoundness = register({ )} onChange={(value) => updateData(value)} > - {renderAction("toggleLoopLock")} + {renderAction("togglePolygon")} ); diff --git a/packages/excalidraw/actions/types.ts b/packages/excalidraw/actions/types.ts index 809234f4d..3051b62f6 100644 --- a/packages/excalidraw/actions/types.ts +++ b/packages/excalidraw/actions/types.ts @@ -143,7 +143,7 @@ export type ActionName = | "wrapSelectionInFrame" | "toggleLassoTool" | "toggleShapeSwitch" - | "toggleLoopLock"; + | "togglePolygon"; export type PanelComponentProps = { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx index 4ea68054f..836889b41 100644 --- a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx +++ b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx @@ -293,7 +293,7 @@ function CommandPaletteInner({ actionManager.actions.decreaseFontSize, actionManager.actions.toggleLinearEditor, actionManager.actions.cropEditor, - actionManager.actions.toggleLoopLock, + actionManager.actions.togglePolygon, actionLink, actionCopyElementLink, actionLinkToElement, @@ -586,10 +586,10 @@ function CommandPaletteInner({ }); setAllCommands(allCommands); - setLastUsed( - allCommands.find((command) => command.label === lastUsed?.label) ?? - null, - ); + // setLastUsed( + // allCommands.find((command) => command.label === lastUsed?.label) ?? + // null, + // ); } }, [ stableDeps, diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 2f90c0c76..22ed507de 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -342,7 +342,7 @@ const restoreElement = ( x, y, ...(isLineElement(element) - ? { loopLock: element.loopLock ?? false } + ? { polygon: element.polygon ?? false } : {}), ...getSizeFromPoints(points), }); diff --git a/packages/excalidraw/locales/en.json b/packages/excalidraw/locales/en.json index 4a369ae04..b585cb314 100644 --- a/packages/excalidraw/locales/en.json +++ b/packages/excalidraw/locales/en.json @@ -141,9 +141,9 @@ "edit": "Edit line", "editArrow": "Edit arrow" }, - "loopLock": { - "unlock": "Break polygon", - "lock": "Convert to polygon" + "polygon": { + "breakPolygon": "Break polygon", + "convertToPolygon": "Convert to polygon" }, "elementLock": { "lock": "Lock", diff --git a/packages/excalidraw/renderer/interactiveScene.ts b/packages/excalidraw/renderer/interactiveScene.ts index 407fb5a11..695028f70 100644 --- a/packages/excalidraw/renderer/interactiveScene.ts +++ b/packages/excalidraw/renderer/interactiveScene.ts @@ -466,7 +466,7 @@ const renderLinearPointHandles = ( (idx !== points.length - 1 || appState.editingLinearElement || !_isLineElement || - !element.loopLock) && + !element.polygon) && pointsEqual( point, idx === points.length - 1 ? points[0] : points[idx - 1],