mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-04 12:54:23 +01:00 
			
		
		
		
	feat: expose applyTo options, don't commit empty text element (#9744)
				
					
				
			* Expose applyTo options, skip re-draw for empty text * Don't commit empty text elements
This commit is contained in:
		@@ -27,6 +27,8 @@ import {
 | 
			
		||||
  isImageElement,
 | 
			
		||||
} from "./index";
 | 
			
		||||
 | 
			
		||||
import type { ApplyToOptions } from "./delta";
 | 
			
		||||
 | 
			
		||||
import type {
 | 
			
		||||
  ExcalidrawElement,
 | 
			
		||||
  OrderedExcalidrawElement,
 | 
			
		||||
@@ -570,9 +572,15 @@ export class StoreDelta {
 | 
			
		||||
    delta: StoreDelta,
 | 
			
		||||
    elements: SceneElementsMap,
 | 
			
		||||
    appState: AppState,
 | 
			
		||||
    options: ApplyToOptions = {
 | 
			
		||||
      excludedProperties: new Set(),
 | 
			
		||||
    },
 | 
			
		||||
  ): [SceneElementsMap, AppState, boolean] {
 | 
			
		||||
    const [nextElements, elementsContainVisibleChange] =
 | 
			
		||||
      delta.elements.applyTo(elements);
 | 
			
		||||
    const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
 | 
			
		||||
      elements,
 | 
			
		||||
      StoreSnapshot.empty().elements,
 | 
			
		||||
      options,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const [nextAppState, appStateContainsVisibleChange] =
 | 
			
		||||
      delta.appState.applyTo(appState, nextElements);
 | 
			
		||||
 
 | 
			
		||||
@@ -4925,7 +4925,17 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		||||
      }),
 | 
			
		||||
      onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
 | 
			
		||||
        const isDeleted = !nextOriginalText.trim();
 | 
			
		||||
        updateElement(nextOriginalText, isDeleted);
 | 
			
		||||
 | 
			
		||||
        if (isDeleted && !isExistingElement) {
 | 
			
		||||
          // let's just remove the element from the scene, as it's an empty just created text element
 | 
			
		||||
          this.scene.replaceAllElements(
 | 
			
		||||
            this.scene
 | 
			
		||||
              .getElementsIncludingDeleted()
 | 
			
		||||
              .filter((x) => x.id !== element.id),
 | 
			
		||||
          );
 | 
			
		||||
        } else {
 | 
			
		||||
          updateElement(nextOriginalText, isDeleted);
 | 
			
		||||
        }
 | 
			
		||||
        // select the created text element only if submitting via keyboard
 | 
			
		||||
        // (when submitting via click it should act as signal to deselect)
 | 
			
		||||
        if (!isDeleted && viaKeyboard) {
 | 
			
		||||
@@ -4954,9 +4964,10 @@ class App extends React.Component<AppProps, AppState> {
 | 
			
		||||
            element,
 | 
			
		||||
          ]);
 | 
			
		||||
        }
 | 
			
		||||
        if (!isDeleted || isExistingElement) {
 | 
			
		||||
          this.store.scheduleCapture();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // we need to record either way, whether the text element was added or removed
 | 
			
		||||
        // since we need to sync this delta to other clients, otherwise it would end up with inconsistencies
 | 
			
		||||
        this.store.scheduleCapture();
 | 
			
		||||
 | 
			
		||||
        flushSync(() => {
 | 
			
		||||
          this.setState({
 | 
			
		||||
 
 | 
			
		||||
@@ -704,7 +704,7 @@ describe("textWysiwyg", () => {
 | 
			
		||||
        rectangle.x + rectangle.width / 2,
 | 
			
		||||
        rectangle.y + rectangle.height / 2,
 | 
			
		||||
      );
 | 
			
		||||
      expect(h.elements.length).toBe(3);
 | 
			
		||||
      expect(h.elements.length).toBe(2);
 | 
			
		||||
 | 
			
		||||
      text = h.elements[1] as ExcalidrawTextElementWithContainer;
 | 
			
		||||
      expect(text.type).toBe("text");
 | 
			
		||||
@@ -1198,7 +1198,7 @@ describe("textWysiwyg", () => {
 | 
			
		||||
      updateTextEditor(editor, "   ");
 | 
			
		||||
      Keyboard.exitTextEditor(editor);
 | 
			
		||||
      expect(rectangle.boundElements).toStrictEqual([]);
 | 
			
		||||
      expect(h.elements[1].isDeleted).toBe(true);
 | 
			
		||||
      expect(h.elements[1]).toBeUndefined();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should restore original container height and clear cache once text is unbind", async () => {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user