feat: add `props.onDuplicate` (#9117)

* feat: add `props.onDuplicate`

* docs

* clarify docs

* fix docs
pull/9124/head
David Luzar 6 days ago committed by GitHub
parent 9e49c9254b
commit c8f4a4cb41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -69,8 +69,20 @@ export const actionDuplicateSelection = register({
}
}
const nextState = duplicateElements(elements, appState);
if (app.props.onDuplicate && nextState.elements) {
const mappedElements = app.props.onDuplicate(
nextState.elements,
elements,
);
if (mappedElements) {
nextState.elements = mappedElements;
}
}
return {
...duplicateElements(elements, appState),
...nextState,
storeAction: StoreAction.CAPTURE,
};
},
@ -92,7 +104,7 @@ export const actionDuplicateSelection = register({
const duplicateElements = (
elements: readonly ExcalidrawElement[],
appState: AppState,
): Partial<ActionResult> => {
): Partial<Exclude<ActionResult, false>> => {
// ---------------------------------------------------------------------------
const groupIdMap = new Map();

@ -3228,7 +3228,14 @@ class App extends React.Component<AppProps, AppState> {
);
const prevElements = this.scene.getElementsIncludingDeleted();
const nextElements = [...prevElements, ...newElements];
let nextElements = [...prevElements, ...newElements];
const mappedNewSceneElements = this.props.onDuplicate?.(
nextElements,
prevElements,
);
nextElements = mappedNewSceneElements || nextElements;
syncMovedIndices(nextElements, arrayToMap(newElements));
@ -8442,7 +8449,17 @@ class App extends React.Component<AppProps, AppState> {
}
}
const nextSceneElements = [...nextElements, ...elementsToAppend];
let nextSceneElements: ExcalidrawElement[] = [
...nextElements,
...elementsToAppend,
];
const mappedNewSceneElements = this.props.onDuplicate?.(
nextSceneElements,
elements,
);
nextSceneElements = mappedNewSceneElements || nextSceneElements;
syncMovedIndices(nextSceneElements, arrayToMap(elementsToAppend));

@ -46,6 +46,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
onPointerDown,
onPointerUp,
onScrollChange,
onDuplicate,
children,
validateEmbeddable,
renderEmbeddable,
@ -136,6 +137,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => {
onPointerDown={onPointerDown}
onPointerUp={onPointerUp}
onScrollChange={onScrollChange}
onDuplicate={onDuplicate}
validateEmbeddable={validateEmbeddable}
renderEmbeddable={renderEmbeddable}
aiEnabled={aiEnabled !== false}

@ -512,6 +512,22 @@ export interface ExcalidrawProps {
data: ClipboardData,
event: ClipboardEvent | null,
) => Promise<boolean> | boolean;
/**
* Called when element(s) are duplicated so you can listen or modify as
* needed.
*
* Called when duplicating via mouse-drag, keyboard, paste, library insert
* etc.
*
* Returned elements will be used in place of the next elements
* (you should return all elements, including deleted, and not mutate
* the element if changes are made)
*/
onDuplicate?: (
nextElements: readonly ExcalidrawElement[],
/** excludes the duplicated elements */
prevElements: readonly ExcalidrawElement[],
) => ExcalidrawElement[] | void;
renderTopRightUI?: (
isMobile: boolean,
appState: UIAppState,

Loading…
Cancel
Save