mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: introduce frames (#6123)
Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
4d7d96eb7b
commit
81ebf82979
78 changed files with 4563 additions and 480 deletions
|
@ -10,6 +10,7 @@ import {
|
|||
import { ToolButton } from "../components/ToolButton";
|
||||
import { getNonDeletedElements } from "../element";
|
||||
import { ExcalidrawElement } from "../element/types";
|
||||
import { updateFrameMembershipOfSelectedElements } from "../frame";
|
||||
import { t } from "../i18n";
|
||||
import { KEYS } from "../keys";
|
||||
import { getSelectedElements, isSomeElementSelected } from "../scene";
|
||||
|
@ -17,10 +18,20 @@ import { AppState } from "../types";
|
|||
import { arrayToMap, getShortcutKey } from "../utils";
|
||||
import { register } from "./register";
|
||||
|
||||
const enableActionGroup = (
|
||||
const alignActionsPredicate = (
|
||||
elements: readonly ExcalidrawElement[],
|
||||
appState: AppState,
|
||||
) => getSelectedElements(getNonDeletedElements(elements), appState).length > 1;
|
||||
) => {
|
||||
const selectedElements = getSelectedElements(
|
||||
getNonDeletedElements(elements),
|
||||
appState,
|
||||
);
|
||||
return (
|
||||
selectedElements.length > 1 &&
|
||||
// TODO enable aligning frames when implemented properly
|
||||
!selectedElements.some((el) => el.type === "frame")
|
||||
);
|
||||
};
|
||||
|
||||
const alignSelectedElements = (
|
||||
elements: readonly ExcalidrawElement[],
|
||||
|
@ -36,14 +47,16 @@ const alignSelectedElements = (
|
|||
|
||||
const updatedElementsMap = arrayToMap(updatedElements);
|
||||
|
||||
return elements.map(
|
||||
(element) => updatedElementsMap.get(element.id) || element,
|
||||
return updateFrameMembershipOfSelectedElements(
|
||||
elements.map((element) => updatedElementsMap.get(element.id) || element),
|
||||
appState,
|
||||
);
|
||||
};
|
||||
|
||||
export const actionAlignTop = register({
|
||||
name: "alignTop",
|
||||
trackEvent: { category: "element" },
|
||||
predicate: alignActionsPredicate,
|
||||
perform: (elements, appState) => {
|
||||
return {
|
||||
appState,
|
||||
|
@ -58,7 +71,7 @@ export const actionAlignTop = register({
|
|||
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === KEYS.ARROW_UP,
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
hidden={!enableActionGroup(elements, appState)}
|
||||
hidden={!alignActionsPredicate(elements, appState)}
|
||||
type="button"
|
||||
icon={AlignTopIcon}
|
||||
onClick={() => updateData(null)}
|
||||
|
@ -74,6 +87,7 @@ export const actionAlignTop = register({
|
|||
export const actionAlignBottom = register({
|
||||
name: "alignBottom",
|
||||
trackEvent: { category: "element" },
|
||||
predicate: alignActionsPredicate,
|
||||
perform: (elements, appState) => {
|
||||
return {
|
||||
appState,
|
||||
|
@ -88,7 +102,7 @@ export const actionAlignBottom = register({
|
|||
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === KEYS.ARROW_DOWN,
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
hidden={!enableActionGroup(elements, appState)}
|
||||
hidden={!alignActionsPredicate(elements, appState)}
|
||||
type="button"
|
||||
icon={AlignBottomIcon}
|
||||
onClick={() => updateData(null)}
|
||||
|
@ -104,6 +118,7 @@ export const actionAlignBottom = register({
|
|||
export const actionAlignLeft = register({
|
||||
name: "alignLeft",
|
||||
trackEvent: { category: "element" },
|
||||
predicate: alignActionsPredicate,
|
||||
perform: (elements, appState) => {
|
||||
return {
|
||||
appState,
|
||||
|
@ -118,7 +133,7 @@ export const actionAlignLeft = register({
|
|||
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === KEYS.ARROW_LEFT,
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
hidden={!enableActionGroup(elements, appState)}
|
||||
hidden={!alignActionsPredicate(elements, appState)}
|
||||
type="button"
|
||||
icon={AlignLeftIcon}
|
||||
onClick={() => updateData(null)}
|
||||
|
@ -134,7 +149,7 @@ export const actionAlignLeft = register({
|
|||
export const actionAlignRight = register({
|
||||
name: "alignRight",
|
||||
trackEvent: { category: "element" },
|
||||
|
||||
predicate: alignActionsPredicate,
|
||||
perform: (elements, appState) => {
|
||||
return {
|
||||
appState,
|
||||
|
@ -149,7 +164,7 @@ export const actionAlignRight = register({
|
|||
event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === KEYS.ARROW_RIGHT,
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
hidden={!enableActionGroup(elements, appState)}
|
||||
hidden={!alignActionsPredicate(elements, appState)}
|
||||
type="button"
|
||||
icon={AlignRightIcon}
|
||||
onClick={() => updateData(null)}
|
||||
|
@ -165,7 +180,7 @@ export const actionAlignRight = register({
|
|||
export const actionAlignVerticallyCentered = register({
|
||||
name: "alignVerticallyCentered",
|
||||
trackEvent: { category: "element" },
|
||||
|
||||
predicate: alignActionsPredicate,
|
||||
perform: (elements, appState) => {
|
||||
return {
|
||||
appState,
|
||||
|
@ -178,7 +193,7 @@ export const actionAlignVerticallyCentered = register({
|
|||
},
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
hidden={!enableActionGroup(elements, appState)}
|
||||
hidden={!alignActionsPredicate(elements, appState)}
|
||||
type="button"
|
||||
icon={CenterVerticallyIcon}
|
||||
onClick={() => updateData(null)}
|
||||
|
@ -192,6 +207,7 @@ export const actionAlignVerticallyCentered = register({
|
|||
export const actionAlignHorizontallyCentered = register({
|
||||
name: "alignHorizontallyCentered",
|
||||
trackEvent: { category: "element" },
|
||||
predicate: alignActionsPredicate,
|
||||
perform: (elements, appState) => {
|
||||
return {
|
||||
appState,
|
||||
|
@ -204,7 +220,7 @@ export const actionAlignHorizontallyCentered = register({
|
|||
},
|
||||
PanelComponent: ({ elements, appState, updateData }) => (
|
||||
<ToolButton
|
||||
hidden={!enableActionGroup(elements, appState)}
|
||||
hidden={!alignActionsPredicate(elements, appState)}
|
||||
type="button"
|
||||
icon={CenterHorizontallyIcon}
|
||||
onClick={() => updateData(null)}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue