| 
					
				 | 
			
			
				@@ -1,7 +1,13 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { VERTICAL_ALIGN } from "../constants"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { getNonDeletedElements, isTextElement } from "../element"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  BOUND_TEXT_PADDING, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ROUNDNESS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  TEXT_ALIGN, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  VERTICAL_ALIGN, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} from "../constants"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { getNonDeletedElements, isTextElement, newElement } from "../element"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { mutateElement } from "../element/mutateElement"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  computeContainerDimensionForBoundText, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   getBoundTextElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   measureText, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   redrawTextBoundingBox, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -13,8 +19,11 @@ import { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hasBoundTextElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   isTextBindableContainer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  isUsingAdaptiveRadius, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } from "../element/typeChecks"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ExcalidrawElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ExcalidrawLinearElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ExcalidrawTextContainer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ExcalidrawTextElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } from "../element/types"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -129,18 +138,151 @@ export const actionBindText = register({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       }), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     redrawTextBoundingBox(textElement, container); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const updatedElements = elements.slice(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const textElementIndex = updatedElements.findIndex( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (ele) => ele.id === textElement.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    updatedElements.splice(textElementIndex, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const containerIndex = updatedElements.findIndex( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (ele) => ele.id === container.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      elements: pushTextAboveContainer(elements, container, textElement), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      appState: { ...appState, selectedElementIds: { [container.id]: true } }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      commitToHistory: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const pushTextAboveContainer = ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  elements: readonly ExcalidrawElement[], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  container: ExcalidrawElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  textElement: ExcalidrawTextElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const updatedElements = elements.slice(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const textElementIndex = updatedElements.findIndex( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (ele) => ele.id === textElement.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  updatedElements.splice(textElementIndex, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const containerIndex = updatedElements.findIndex( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (ele) => ele.id === container.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  updatedElements.splice(containerIndex + 1, 0, textElement); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return updatedElements; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const pushContainerBelowText = ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  elements: readonly ExcalidrawElement[], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  container: ExcalidrawElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  textElement: ExcalidrawTextElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const updatedElements = elements.slice(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const containerIndex = updatedElements.findIndex( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (ele) => ele.id === container.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  updatedElements.splice(containerIndex, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const textElementIndex = updatedElements.findIndex( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (ele) => ele.id === textElement.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  updatedElements.splice(textElementIndex, 0, container); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return updatedElements; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+export const actionCreateContainerFromText = register({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  name: "createContainerFromText", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  contextItemLabel: "labels.createContainerFromText", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  trackEvent: { category: "element" }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  predicate: (elements, appState) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const selectedElements = getSelectedElements(elements, appState); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return selectedElements.length === 1 && isTextElement(selectedElements[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  perform: (elements, appState) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const selectedElements = getSelectedElements( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      getNonDeletedElements(elements), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      appState, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    updatedElements.splice(containerIndex + 1, 0, textElement); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const updatedElements = elements.slice(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (selectedElements.length === 1 && isTextElement(selectedElements[0])) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const textElement = selectedElements[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const container = newElement({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        type: "rectangle", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        backgroundColor: appState.currentItemBackgroundColor, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boundElements: [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ...(textElement.boundElements || []), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          { id: textElement.id, type: "text" }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        angle: textElement.angle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        fillStyle: appState.currentItemFillStyle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        strokeColor: appState.currentItemStrokeColor, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roughness: appState.currentItemRoughness, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        strokeWidth: appState.currentItemStrokeWidth, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        strokeStyle: appState.currentItemStrokeStyle, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        roundness: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          appState.currentItemRoundness === "round" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ? { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                type: isUsingAdaptiveRadius("rectangle") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  ? ROUNDNESS.ADAPTIVE_RADIUS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  : ROUNDNESS.PROPORTIONAL_RADIUS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            : null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        opacity: 100, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        locked: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x: textElement.x - BOUND_TEXT_PADDING, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        y: textElement.y - BOUND_TEXT_PADDING, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        width: computeContainerDimensionForBoundText( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          textElement.width, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "rectangle", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        height: computeContainerDimensionForBoundText( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          textElement.height, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          "rectangle", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        groupIds: textElement.groupIds, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // update bindings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (textElement.boundElements?.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const linearElementIds = textElement.boundElements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          .filter((ele) => ele.type === "arrow") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          .map((el) => el.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const linearElements = updatedElements.filter((ele) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          linearElementIds.includes(ele.id), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ) as ExcalidrawLinearElement[]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        linearElements.forEach((ele) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          let startBinding = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          let endBinding = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (ele.startBinding) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            startBinding = { ...ele.startBinding, elementId: container.id }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (ele.endBinding) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            endBinding = { ...ele.endBinding, elementId: container.id }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          mutateElement(ele, { startBinding, endBinding }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      mutateElement(textElement, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        containerId: container.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        verticalAlign: VERTICAL_ALIGN.MIDDLE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        textAlign: TEXT_ALIGN.CENTER, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        boundElements: null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      redrawTextBoundingBox(textElement, container); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elements: pushContainerBelowText( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          [...elements, container], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          container, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          textElement, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        appState: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ...appState, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          selectedElementIds: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            [container.id]: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            [textElement.id]: false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        commitToHistory: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       elements: updatedElements, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      appState: { ...appState, selectedElementIds: { [container.id]: true } }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      appState, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       commitToHistory: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }, 
			 |