You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
success/packages/excalidraw/element/textWysiwyg.tsx

687 lines
21 KiB
TypeScript

import { CODES, KEYS } from "../keys";
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
import {
isWritableElement,
getFontString,
getFontFamilyString,
isTestEnv,
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
} from "../utils";
import Scene from "../scene/Scene";
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
import {
isArrowElement,
isBoundToContainer,
isTextElement,
} from "./typeChecks";
import { CLASSES } from "../constants";
import type {
ExcalidrawElement,
ExcalidrawLinearElement,
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
ExcalidrawTextElementWithContainer,
ExcalidrawTextElement,
} from "./types";
import type { AppState } from "../types";
import { bumpVersion, mutateElement } from "./mutateElement";
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
import {
getBoundTextElementId,
getContainerElement,
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
getTextElementAngle,
getTextWidth,
normalizeText,
redrawTextBoundingBox,
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
wrapText,
getBoundTextMaxHeight,
getBoundTextMaxWidth,
computeContainerDimensionForBoundText,
computeBoundTextPosition,
getBoundTextElement,
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
} from "./textElement";
import {
actionDecreaseFontSize,
actionIncreaseFontSize,
} from "../actions/actionProperties";
import { actionZoomIn, actionZoomOut } from "../actions/actionCanvas";
import type App from "../components/App";
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
import { LinearElementEditor } from "./linearElementEditor";
import { parseClipboard } from "../clipboard";
import {
originalContainerCache,
updateOriginalContainerCache,
} from "./containerCache";
const getTransform = (
width: number,
height: number,
angle: number,
appState: AppState,
maxWidth: number,
maxHeight: number,
) => {
const { zoom } = appState;
const degree = (180 * angle) / Math.PI;
let translateX = (width * (zoom.value - 1)) / 2;
let translateY = (height * (zoom.value - 1)) / 2;
if (width > maxWidth && zoom.value !== 1) {
translateX = (maxWidth * (zoom.value - 1)) / 2;
}
if (height > maxHeight && zoom.value !== 1) {
translateY = (maxHeight * (zoom.value - 1)) / 2;
}
return `translate(${translateX}px, ${translateY}px) scale(${zoom.value}) rotate(${degree}deg)`;
};
export const textWysiwyg = ({
id,
onChange,
onSubmit,
getViewportCoords,
element,
canvas,
excalidrawContainer,
app,
}: {
id: ExcalidrawElement["id"];
feat: text wrapping (#7999) * resize single elements from the side * fix lint * do not resize texts from the sides (for we want to wrap/unwrap) * omit side handles for frames too * upgrade types * enable resizing from the sides for multiple elements as well * fix lint * maintain aspect ratio when elements are not of the same angle * lint * always resize proportionally for multiple elements * increase side resizing padding * code cleanup * adaptive handles * do not resize for linear elements with only two points * prioritize point dragging over edge resizing * lint * allow free resizing for multiple elements at degree 0 * always resize from the sides * reduce hit threshold * make small multiple elements movable * lint * show side handles on touch screen and mobile devices * differentiate touchscreens * keep proportional with text in multi-element resizing * update snapshot * update multi elements resizing logic * lint * reduce side resizing padding * bound texts do not scale in normal cases * lint * test sides for texts * wrap text * do not update text size when changing its alignment * keep text wrapped/unwrapped when editing * change wrapped size to auto size from context menu * fix test * lint * increase min width for wrapped texts * wrap wrapped text in container * unwrap when binding text to container * rename `wrapped` to `autoResize` * fix lint * revert: use `center` align when wrapping text in container * update snaps * fix lint * simplify logic on autoResize * lint and test * snapshots * remove unnecessary code * snapshots * fix: defaults not set correctly * tests for wrapping texts when resized * tests for text wrapping when edited * fix autoResize refactor * include autoResize flag check * refactor * feat: rename action label & change contextmenu position * fix: update version on `autoResize` action * fix infinite loop when editing text in a container * simplify * always maintain `width` if `!autoResize` * maintain `x` if `!autoResize` * maintain `y` pos after fontSize change if `!autoResize` * refactor * when editing, do not wrap text in textWysiwyg * simplify text editor * make test more readable * comment * rename action to match file name * revert function signature change * only update in app --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
9 months ago
/**
* textWysiwyg only deals with `originalText`
*
* Note: `text`, which can be wrapped and therefore different from `originalText`,
* is derived from `originalText`
*/
onChange?: (nextOriginalText: string) => void;
onSubmit: (data: { viaKeyboard: boolean; nextOriginalText: string }) => void;
getViewportCoords: (x: number, y: number) => [number, number];
element: ExcalidrawTextElement;
canvas: HTMLCanvasElement;
excalidrawContainer: HTMLDivElement | null;
app: App;
}) => {
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
const textPropertiesUpdated = (
updatedTextElement: ExcalidrawTextElement,
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
editable: HTMLTextAreaElement,
) => {
if (!editable.style.fontFamily || !editable.style.fontSize) {
return false;
}
const currentFont = editable.style.fontFamily.replace(/"/g, "");
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
if (
getFontFamilyString({ fontFamily: updatedTextElement.fontFamily }) !==
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
currentFont
) {
return true;
}
if (`${updatedTextElement.fontSize}px` !== editable.style.fontSize) {
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
return true;
}
return false;
};
const updateWysiwygStyle = () => {
const appState = app.state;
const updatedTextElement =
Scene.getScene(element)?.getElement<ExcalidrawTextElement>(id);
if (!updatedTextElement) {
return;
}
const { textAlign, verticalAlign } = updatedTextElement;
const elementsMap = app.scene.getNonDeletedElementsMap();
if (updatedTextElement && isTextElement(updatedTextElement)) {
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
let coordX = updatedTextElement.x;
let coordY = updatedTextElement.y;
const container = getContainerElement(
updatedTextElement,
app.scene.getNonDeletedElementsMap(),
);
let maxWidth = updatedTextElement.width;
let maxHeight = updatedTextElement.height;
let textElementWidth = updatedTextElement.width;
const textElementHeight = updatedTextElement.height;
if (container && updatedTextElement.containerId) {
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
if (isArrowElement(container)) {
const boundTextCoords =
LinearElementEditor.getBoundTextElementPosition(
container,
updatedTextElement as ExcalidrawTextElementWithContainer,
elementsMap,
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
);
coordX = boundTextCoords.x;
coordY = boundTextCoords.y;
}
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
const propertiesUpdated = textPropertiesUpdated(
updatedTextElement,
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
editable,
);
let originalContainerData;
if (propertiesUpdated) {
originalContainerData = updateOriginalContainerCache(
container.id,
container.height,
);
} else {
originalContainerData = originalContainerCache[container.id];
if (!originalContainerData) {
originalContainerData = updateOriginalContainerCache(
container.id,
container.height,
);
}
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
}
maxWidth = getBoundTextMaxWidth(container, updatedTextElement);
maxHeight = getBoundTextMaxHeight(
container,
updatedTextElement as ExcalidrawTextElementWithContainer,
);
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
// autogrow container height if text exceeds
if (!isArrowElement(container) && textElementHeight > maxHeight) {
const targetContainerHeight = computeContainerDimensionForBoundText(
textElementHeight,
container.type,
);
mutateElement(container, { height: targetContainerHeight });
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
return;
} else if (
// autoshrink container height until original container height
// is reached when text is removed
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
!isArrowElement(container) &&
container.height > originalContainerData.height &&
textElementHeight < maxHeight
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
) {
const targetContainerHeight = computeContainerDimensionForBoundText(
textElementHeight,
container.type,
);
mutateElement(container, { height: targetContainerHeight });
} else {
const { y } = computeBoundTextPosition(
container,
updatedTextElement as ExcalidrawTextElementWithContainer,
elementsMap,
);
coordY = y;
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
}
}
const [viewportX, viewportY] = getViewportCoords(coordX, coordY);
const initialSelectionStart = editable.selectionStart;
const initialSelectionEnd = editable.selectionEnd;
const initialLength = editable.value.length;
// restore cursor position after value updated so it doesn't
// go to the end of text when container auto expanded
if (
initialSelectionStart === initialSelectionEnd &&
initialSelectionEnd !== initialLength
) {
// get diff between length and selection end and shift
// the cursor by "diff" times to position correctly
const diff = initialLength - initialSelectionEnd;
editable.selectionStart = editable.value.length - diff;
editable.selectionEnd = editable.value.length - diff;
}
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
if (!container) {
maxWidth = (appState.width - 8 - viewportX) / appState.zoom.value;
textElementWidth = Math.min(textElementWidth, maxWidth);
} else {
textElementWidth += 0.5;
}
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
// Make sure text editor height doesn't go beyond viewport
const editorMaxHeight =
(appState.height - viewportY) / appState.zoom.value;
Object.assign(editable.style, {
font: getFontString(updatedTextElement),
// must be defined *after* font ¯\_(ツ)_/¯
lineHeight: updatedTextElement.lineHeight,
width: `${textElementWidth}px`,
height: `${textElementHeight}px`,
left: `${viewportX}px`,
top: `${viewportY}px`,
transform: getTransform(
textElementWidth,
textElementHeight,
getTextElementAngle(updatedTextElement, container),
appState,
maxWidth,
editorMaxHeight,
),
textAlign,
verticalAlign,
color: updatedTextElement.strokeColor,
opacity: updatedTextElement.opacity / 100,
filter: "var(--theme-filter)",
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
maxHeight: `${editorMaxHeight}px`,
});
editable.scrollTop = 0;
// For some reason updating font attribute doesn't set font family
// hence updating font family explicitly for test environment
if (isTestEnv()) {
editable.style.fontFamily = getFontFamilyString(updatedTextElement);
}
feat: text wrapping (#7999) * resize single elements from the side * fix lint * do not resize texts from the sides (for we want to wrap/unwrap) * omit side handles for frames too * upgrade types * enable resizing from the sides for multiple elements as well * fix lint * maintain aspect ratio when elements are not of the same angle * lint * always resize proportionally for multiple elements * increase side resizing padding * code cleanup * adaptive handles * do not resize for linear elements with only two points * prioritize point dragging over edge resizing * lint * allow free resizing for multiple elements at degree 0 * always resize from the sides * reduce hit threshold * make small multiple elements movable * lint * show side handles on touch screen and mobile devices * differentiate touchscreens * keep proportional with text in multi-element resizing * update snapshot * update multi elements resizing logic * lint * reduce side resizing padding * bound texts do not scale in normal cases * lint * test sides for texts * wrap text * do not update text size when changing its alignment * keep text wrapped/unwrapped when editing * change wrapped size to auto size from context menu * fix test * lint * increase min width for wrapped texts * wrap wrapped text in container * unwrap when binding text to container * rename `wrapped` to `autoResize` * fix lint * revert: use `center` align when wrapping text in container * update snaps * fix lint * simplify logic on autoResize * lint and test * snapshots * remove unnecessary code * snapshots * fix: defaults not set correctly * tests for wrapping texts when resized * tests for text wrapping when edited * fix autoResize refactor * include autoResize flag check * refactor * feat: rename action label & change contextmenu position * fix: update version on `autoResize` action * fix infinite loop when editing text in a container * simplify * always maintain `width` if `!autoResize` * maintain `x` if `!autoResize` * maintain `y` pos after fontSize change if `!autoResize` * refactor * when editing, do not wrap text in textWysiwyg * simplify text editor * make test more readable * comment * rename action to match file name * revert function signature change * only update in app --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
9 months ago
mutateElement(updatedTextElement, { x: coordX, y: coordY });
}
};
const editable = document.createElement("textarea");
editable.dir = "auto";
editable.tabIndex = 0;
editable.dataset.type = "wysiwyg";
// prevent line wrapping on Safari
editable.wrap = "off";
feat: Allow publishing libraries from UI (#4115) * feat: Allow publishing libraries from UI * Add status for each library item and show publish only for unpublished libs * Add publish library dialog * Pass the data to publish the library * pass lib blob * Handle old and new libraries when importing * Better error handling * Show publish success when library submitted for review * don't close library when publish success dialog open * Support multiple libs deletion and publish * Set status to published once library submitted for review * Save to LS after library published * unique key for publish and delete * fix layout shift when hover and also highlight selected library items * design improvements * migrate old library to the new one * fix * fix tests * use i18n * Support submit type in toolbutton * Use html5 form validation, add asteriks for required fields, add twitter handle, mark github handle optional * Add twitter handle in form state * revert html5 validation as fetch is giving some issues :/ * clarify types around LibraryItems * Add website optional field * event.preventDefault to make htm5 form validationw work * improve png generation by drawing a bounding box rect and aligining pngs to support multiple libs png * remove ts-ignore * add placeholders for fields * decrease clickable area for checkbox by 0.5em * add checkbox background color * rename `items` to `elements` * improve checkbox hit area * show selected library items in publish dialog * decrease dimensions by 3px to improve jerky experience when opening/closing library menu * Don't close publish dialog when clicked outside * Show selected library actions only when any library item selected and use icons instead of button * rename library to libraryItems in excalidrawLib and added migration * change icon and swap bg/color * use blue brand color for hover/selected states * prompt for confirmation when deleting library items * separate unpublished items from published * factor `LibraryMenu` into own file * i18n and minor fixes for unpublished items * fix not rendering empty cells when library empty * don't render published section if empty and unpublished is not * Add edit name functionality for library items * fix * edit lib name with onchange/blur * bump library version * prefer response error message * add library urls to ENV vars * mark lib item name as required * Use input only for lib item name * better error validation for lib items * fix label styling for lib items * design and i18n fixes * Save publish dialog data to local storage and clear once published * Add a note about MIT License * Add note for guidelines * Add tooltip for publish button * Show spinner in submit button when submission is in progress * assign id for older lib items when installed and set status as published for all lib when installed * update export icon and support export library for selected items * move LibraryMenuItems into its own component as its best to keep one comp per file * fix spec * Refactoring the library actions for reusablility * show only load when items not present * close on click outside in publish dialog * ad dialog description and tweak copy * vertically center input labels * align input styles * move author name input to other usernames * rename param * inline to simplify * fix to not inline `undefined` class names * fix version & include only latest lib schema in library export type * await response callback * refactor types * refactor * i18n * align casing & tweaks * move ls logic to publishLibrary * support removal of item inside publish dialog * fix labels for trash icon when items selected * replace window.confirm for removal libs with confirm dialog * fix input/textarea styling * move library item menu scss to its own file * use blue for load and cyan for publish * reduce margin for submit and make submit => Submit * Make library items header sticky * move publish icon to left so there is no jerkiness when unpublish items selected * update url * fix grid gap between lib items * Mark older items imported from initial data as unpublished * add text to publish button on non-mobile * add items counter * fix test * show personal and excal libs sections and personal goes first * show toast on adding to library via contextMenu * Animate plus icon and not the pending item * fix snap * use i18n when no item in publish dialog * tweak style of new lib item * show empty cells for both sections and set status as published for installed libs * fix * push selected item first in unpublished section * set status as published for imported from webiste but unpublished for json * Add items to the begining of library * add `created` library item attr * fix test * use `defaultValue` instead of `value` * fix dark theme styles * fix toggle button not closing library * close library menu on Escape * tweak publish dialog item remove style * fix remove icon in publish dialog Co-authored-by: dwelle <luzar.david@gmail.com>
3 years ago
editable.classList.add("excalidraw-wysiwyg");
Rotation support (#1099) * rotate rectanble with fixed angle * rotate dashed rectangle with fixed angle * fix rotate handler rect * fix canvas size with rotation * angle in element base * fix bug in calculating canvas size * trial only for rectangle * hitTest for rectangle rotation * properly resize rotated rectangle * fix canvas size calculation * giving up... workaround for now * **experimental** handler to rotate rectangle * remove rotation on copy for debugging * update snapshots * better rotation handler with atan2 * rotate when drawImage * add rotation handler * hitTest for any shapes * fix hitTest for curved lines * rotate text element * rotation locking * hint messaage for rotating * show proper handlers on mobile (a workaround, there should be a better way) * refactor hitTest * support exporting png * support exporting svg * fix rotating curved line * refactor drawElementFromCanvas with getElementAbsoluteCoords * fix export png and svg * adjust resize positions for lines (N, E, S, W) * do not make handlers big on mobile * Update src/locales/en.json Alright! Co-Authored-By: Lipis <lipiridis@gmail.com> * do not show rotation/resizing hints on mobile * proper calculation for N and W positions * simplify calculation * use "rotation" as property name for clarification (may increase bundle size) * update snapshots excluding rotation handle * refactor with adjustPositionWithRotation * refactor with adjustXYWithRotation * forgot to rename rotation * rename internal function * initialize element angle on restore * rotate wysiwyg editor * fix shift-rotate around 270deg * improve rotation locking * refactor adjustXYWithRotation * avoid rotation degree becomes >=360 * refactor with generateHandler Co-authored-by: Lipis <lipiridis@gmail.com> Co-authored-by: dwelle <luzar.david@gmail.com>
5 years ago
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
let whiteSpace = "pre";
let wordBreak = "normal";
feat: text wrapping (#7999) * resize single elements from the side * fix lint * do not resize texts from the sides (for we want to wrap/unwrap) * omit side handles for frames too * upgrade types * enable resizing from the sides for multiple elements as well * fix lint * maintain aspect ratio when elements are not of the same angle * lint * always resize proportionally for multiple elements * increase side resizing padding * code cleanup * adaptive handles * do not resize for linear elements with only two points * prioritize point dragging over edge resizing * lint * allow free resizing for multiple elements at degree 0 * always resize from the sides * reduce hit threshold * make small multiple elements movable * lint * show side handles on touch screen and mobile devices * differentiate touchscreens * keep proportional with text in multi-element resizing * update snapshot * update multi elements resizing logic * lint * reduce side resizing padding * bound texts do not scale in normal cases * lint * test sides for texts * wrap text * do not update text size when changing its alignment * keep text wrapped/unwrapped when editing * change wrapped size to auto size from context menu * fix test * lint * increase min width for wrapped texts * wrap wrapped text in container * unwrap when binding text to container * rename `wrapped` to `autoResize` * fix lint * revert: use `center` align when wrapping text in container * update snaps * fix lint * simplify logic on autoResize * lint and test * snapshots * remove unnecessary code * snapshots * fix: defaults not set correctly * tests for wrapping texts when resized * tests for text wrapping when edited * fix autoResize refactor * include autoResize flag check * refactor * feat: rename action label & change contextmenu position * fix: update version on `autoResize` action * fix infinite loop when editing text in a container * simplify * always maintain `width` if `!autoResize` * maintain `x` if `!autoResize` * maintain `y` pos after fontSize change if `!autoResize` * refactor * when editing, do not wrap text in textWysiwyg * simplify text editor * make test more readable * comment * rename action to match file name * revert function signature change * only update in app --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
9 months ago
if (isBoundToContainer(element) || !element.autoResize) {
whiteSpace = "pre-wrap";
wordBreak = "break-word";
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
}
Object.assign(editable.style, {
position: "absolute",
display: "inline-block",
minHeight: "1em",
backfaceVisibility: "hidden",
margin: 0,
padding: 0,
border: 0,
outline: 0,
resize: "none",
background: "transparent",
overflow: "hidden",
// must be specified because in dark mode canvas creates a stacking context
zIndex: "var(--zIndex-wysiwyg)",
wordBreak,
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
// prevent line wrapping (`whitespace: nowrap` doesn't work on FF)
whiteSpace,
overflowWrap: "break-word",
feat: Support labels for arrow 🔥 (#5723) * feat: support arrow with text * render arrow -> clear rect-> render text * move bound text when linear elements move * fix centering cursor when linear element rotated * fix y coord when new line added and container has 3 points * update text position when 2nd point moved * support adding label on top of 2nd point when 3 points are present * change linear element editor shortcut to cmd+enter and fix tests * scale bound text points when resizing via bounding box * ohh yeah rotation works :) * fix coords when updating text properties * calculate new position after rotation always from original position * rotate the bound text by same angle as parent * don't rotate text and make sure dimensions and coords are always calculated from original point * hardcoding the text width for now * Move the linear element when bound text hit * Rotation working yaay * consider text element angle when editing * refactor * update x2 coords if needed when text updated * simplify * consider bound text to be part of bounding box when hit * show bounding box correctly when multiple element selected * fix typo * support rotating multiple elements * support multiple element resizing * shift bound text to mid point when odd points * Always render linear element handles inside editor after element rendered so point is visible for bound text * Delete bound text when point attached to it deleted * move bound to mid segement mid point when points are even * shift bound text when points nearby deleted and handle segment deletion * Resize working :) * more resize fixes * don't update cache-its breaking delete points, look for better soln * update mid point cache for bound elements when updated * introduce wrapping when resizing * wrap when resize for 2 pointer linear elements * support adding text for linear elements with more than 3 points * export to svg working :) * clip from nearest enclosing element with non transparent color if present when exporting and fill with correct color in canvas * fix snap * use visible elements * Make export to svg work with Mask :) * remove id * mask canvas linear element area where label is added * decide the position of bound text during render * fix coords when editing * fix multiple resize * update cache when bound text version changes * fix masking when rotated * render text in correct position in preview * remove unnecessary code * fix masking when rotating linear element * fix masking with zoom * fix mask in preview for export * fix offsets in export view * fix coords on svg export * fix mask when element rotated in svg * enable double-click to enter text * fix hint * Position cursor correctly and text dimensiosn when height of element is negative * don't allow 2 pointer linear element with bound text width to go beyond min width * code cleanup * fix freedraw * Add padding * don't show vertical align action for linear element containers * Add specs for getBoundTextElementPosition * more specs * move some utils to linearElementEditor.ts * remove only :p * check absoulte coods in test * Add test to hide vertical align for linear eleemnt with bound text * improve export preview * support labels only for arrows * spec * fix large texts * fix tests * fix zooming * enter line editor with cmd+double click * Allow points to move beyond min width/height for 2 pointer arrow with bound text * fix hint for line editing * attempt to fix arrow getting deselected * fix hint and shortcut * Add padding of 5px when creating bound text and add spec * Wrap bound text when arrow binding containers moved * Add spec * remove * set boundTextElementVersion to null if not present * dont use cache when version mismatch * Add a padding of 5px vertically when creating text * Add box sizing content box * Set bound elements when text element created to fix the padding * fix zooming in editor * fix zoom in export * remove globalCompositeOperation and use clearRect instead of fillRect
2 years ago
boxSizing: "content-box",
});
editable.value = element.originalText;
updateWysiwygStyle();
if (onChange) {
editable.onpaste = async (event) => {
const clipboardData = await parseClipboard(event, true);
if (!clipboardData.text) {
return;
}
const data = normalizeText(clipboardData.text);
if (!data) {
return;
}
const container = getContainerElement(
element,
app.scene.getNonDeletedElementsMap(),
);
const font = getFontString({
fontSize: app.state.currentItemFontSize,
fontFamily: app.state.currentItemFontFamily,
});
if (container) {
const boundTextElement = getBoundTextElement(
container,
app.scene.getNonDeletedElementsMap(),
);
const wrappedText = wrapText(
`${editable.value}${data}`,
font,
getBoundTextMaxWidth(container, boundTextElement),
);
const width = getTextWidth(wrappedText, font);
editable.style.width = `${width}px`;
}
};
editable.oninput = () => {
onChange(normalizeText(editable.value));
};
}
editable.onkeydown = (event) => {
if (!event.shiftKey && actionZoomIn.keyTest(event)) {
event.preventDefault();
app.actionManager.executeAction(actionZoomIn);
updateWysiwygStyle();
} else if (!event.shiftKey && actionZoomOut.keyTest(event)) {
event.preventDefault();
app.actionManager.executeAction(actionZoomOut);
updateWysiwygStyle();
} else if (actionDecreaseFontSize.keyTest(event)) {
app.actionManager.executeAction(actionDecreaseFontSize);
} else if (actionIncreaseFontSize.keyTest(event)) {
app.actionManager.executeAction(actionIncreaseFontSize);
} else if (event.key === KEYS.ESCAPE) {
event.preventDefault();
submittedViaKeyboard = true;
handleSubmit();
} else if (event.key === KEYS.ENTER && event[KEYS.CTRL_OR_CMD]) {
event.preventDefault();
if (event.isComposing || event.keyCode === 229) {
return;
}
submittedViaKeyboard = true;
handleSubmit();
} else if (
event.key === KEYS.TAB ||
(event[KEYS.CTRL_OR_CMD] &&
(event.code === CODES.BRACKET_LEFT ||
event.code === CODES.BRACKET_RIGHT))
) {
event.preventDefault();
if (event.isComposing) {
return;
} else if (event.shiftKey || event.code === CODES.BRACKET_LEFT) {
outdent();
} else {
indent();
}
// We must send an input event to resize the element
editable.dispatchEvent(new Event("input"));
}
};
const TAB_SIZE = 4;
const TAB = " ".repeat(TAB_SIZE);
const RE_LEADING_TAB = new RegExp(`^ {1,${TAB_SIZE}}`);
const indent = () => {
const { selectionStart, selectionEnd } = editable;
const linesStartIndices = getSelectedLinesStartIndices();
let value = editable.value;
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
linesStartIndices.forEach((startIndex: number) => {
const startValue = value.slice(0, startIndex);
const endValue = value.slice(startIndex);
value = `${startValue}${TAB}${endValue}`;
});
editable.value = value;
editable.selectionStart = selectionStart + TAB_SIZE;
editable.selectionEnd = selectionEnd + TAB_SIZE * linesStartIndices.length;
};
const outdent = () => {
const { selectionStart, selectionEnd } = editable;
const linesStartIndices = getSelectedLinesStartIndices();
const removedTabs: number[] = [];
let value = editable.value;
linesStartIndices.forEach((startIndex) => {
const tabMatch = value
.slice(startIndex, startIndex + TAB_SIZE)
.match(RE_LEADING_TAB);
if (tabMatch) {
const startValue = value.slice(0, startIndex);
const endValue = value.slice(startIndex + tabMatch[0].length);
// Delete a tab from the line
value = `${startValue}${endValue}`;
removedTabs.push(startIndex);
}
});
editable.value = value;
if (removedTabs.length) {
if (selectionStart > removedTabs[removedTabs.length - 1]) {
editable.selectionStart = Math.max(
selectionStart - TAB_SIZE,
removedTabs[removedTabs.length - 1],
);
} else {
// If the cursor is before the first tab removed, ex:
// Line| #1
// Line #2
// Lin|e #3
// we should reset the selectionStart to his initial value.
editable.selectionStart = selectionStart;
}
editable.selectionEnd = Math.max(
editable.selectionStart,
selectionEnd - TAB_SIZE * removedTabs.length,
);
}
};
/**
* @returns indices of start positions of selected lines, in reverse order
*/
const getSelectedLinesStartIndices = () => {
let { selectionStart, selectionEnd, value } = editable;
// chars before selectionStart on the same line
const startOffset = value.slice(0, selectionStart).match(/[^\n]*$/)![0]
.length;
// put caret at the start of the line
selectionStart = selectionStart - startOffset;
const selected = value.slice(selectionStart, selectionEnd);
return selected
.split("\n")
.reduce(
(startIndices, line, idx, lines) =>
startIndices.concat(
idx
? // curr line index is prev line's start + prev line's length + \n
startIndices[idx - 1] + lines[idx - 1].length + 1
: // first selected line
selectionStart,
),
[] as number[],
)
.reverse();
};
const stopEvent = (event: Event) => {
event.preventDefault();
event.stopPropagation();
};
// using a state variable instead of passing it to the handleSubmit callback
// so that we don't need to create separate a callback for event handlers
let submittedViaKeyboard = false;
const handleSubmit = () => {
// cleanup must be run before onSubmit otherwise when app blurs the wysiwyg
// it'd get stuck in an infinite loop of blur→onSubmit after we re-focus the
// wysiwyg on update
cleanup();
const updateElement = Scene.getScene(element)?.getElement(
element.id,
) as ExcalidrawTextElement;
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
if (!updateElement) {
return;
}
const container = getContainerElement(
updateElement,
app.scene.getNonDeletedElementsMap(),
);
if (container) {
if (editable.value.trim()) {
const boundTextElementId = getBoundTextElementId(container);
if (!boundTextElementId || boundTextElementId !== element.id) {
mutateElement(container, {
boundElements: (container.boundElements || []).concat({
type: "text",
id: element.id,
}),
});
} else if (isArrowElement(container)) {
// updating an arrow label may change bounds, prevent stale cache:
bumpVersion(container);
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
}
} else {
mutateElement(container, {
boundElements: container.boundElements?.filter(
(ele) =>
!isTextElement(
ele as ExcalidrawTextElement | ExcalidrawLinearElement,
),
),
});
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
}
redrawTextBoundingBox(
updateElement,
container,
app.scene.getNonDeletedElementsMap(),
);
feat: bind text to shapes when pressing enter and support sticky notes 🎉 (#4343) * feat: Word wrap inside rect and increase height when size exceeded * fixes for auto increase in height * fix height * respect newlines when wrapping text * shift text area when height increases beyond mid rect height until it reaches to the top * select bound text if present when rect selected * mutate y coord after text submit * Add padding of 30px and update dimensions acordingly * Don't allow selecting bound text element directly * support deletion of bound text element when rect deleted * trim text * Support autoshrink and improve algo * calculate approx line height instead of hardcoding * use textContainerId instead of storing textContainer element itself * rename boundTextElement -> boundTextElementId * fix text properties not getting reflected after edit inside rect * Support resizing * remove ts ignore * increase height of container when text height increases while resizing * use original text when editing/resizing so it adjusts based on original text * fix tests * add util isRectangleElement * use isTextElement util everywhere * disable selecting text inside rect when selectAll * Bind text to circle and diamond as well * fix tests * vertically center align the text always * better vertical align * Disable binding arrows for text inside shapes * set min width for text container when text is binded to container * update dimensions of container if its less than min width/ min height * Allow selecting of text container for transparent containers when clicked inside * fix test * preserve whitespaces between long word exceeding width and next word Use word break instead of whitespace no wrap for better readability and support safari * Perf improvements for measuring text width and resizing * Use canvas measureText instead of our algo. This has reduced the perf ~ 10 times * Rewrite wrapText algo to break in words appropriately and for longer words calculate the char width in order unless max width reached. This makes the the number of runs linear (max text length times) which was earlier textLength * textLength-1/2 as I was slicing the chars from end until max width reached for each run * Add a util to calculate getApproxCharsToFitInWidth to calculate min chars to fit in a line * use console.info so eslint doesnt warn :p * cache char width and don't call resize unless min width exceeded * update line height and height correctly when text properties inside container updated * improve vertical centering when text properties updated, not yet perfect though * when double clicked inside a conatiner take the cursor to end of text same as what happens when enter is pressed * Add hint when container selected * Select container when escape key is pressed after submitting text * fix copy/paste when using copy/paste action * fix copy when dragged with alt pressed * fix export to svg/png * fix add to library * Fix copy as png/svg * Don't allow selecting text when using selection tool and support resizing when multiple elements include ones with binded text selectec * fix rotation jump * moove all text utils to textElement.ts * resize text element only after container resized so that width doesnt change when editing * insert the remaining chars for long words once it goes beyond line * fix typo, use string for character type * renaming * fix bugs in word wrap algo * make grouping work * set boundTextElementId only when text present else unset it * rename textContainerId to containerId * fix * fix snap * use originalText in redrawTextBoundingBox so height is calculated properly and center align works after props updated * use boundElementIds and also support binding text in images 🎉 * fix the sw/se ends when resizing from ne/nw * fix y coord when resizing from north * bind when enter is pressed, double click/text tool willl edit the binded text if present else create a new text * bind when clicked on center of container * use pre-wrap instead of normal so it works in ff * use container boundTextElement when container present and trying to edit text * review fixes * make getBoundTextElementId type safe and check for existence when using this function * fix * don't duplicate boundElementIds when text submitted * only remove last trailing space if present which we have added when joining words * set width correctly when resizing to fix alignment issues * make duplication work using cmd/ctrl+d * set X coord correctly during resize * don't allow resize to negative dimensions when text is bounded to container * fix, check last char is space * remove logs * make sure text editor doesn't go beyond viewport and set container dimensions in case it overflows * add a util isTextBindableContainer to check if the container could bind text
3 years ago
}
onSubmit({
viaKeyboard: submittedViaKeyboard,
feat: text wrapping (#7999) * resize single elements from the side * fix lint * do not resize texts from the sides (for we want to wrap/unwrap) * omit side handles for frames too * upgrade types * enable resizing from the sides for multiple elements as well * fix lint * maintain aspect ratio when elements are not of the same angle * lint * always resize proportionally for multiple elements * increase side resizing padding * code cleanup * adaptive handles * do not resize for linear elements with only two points * prioritize point dragging over edge resizing * lint * allow free resizing for multiple elements at degree 0 * always resize from the sides * reduce hit threshold * make small multiple elements movable * lint * show side handles on touch screen and mobile devices * differentiate touchscreens * keep proportional with text in multi-element resizing * update snapshot * update multi elements resizing logic * lint * reduce side resizing padding * bound texts do not scale in normal cases * lint * test sides for texts * wrap text * do not update text size when changing its alignment * keep text wrapped/unwrapped when editing * change wrapped size to auto size from context menu * fix test * lint * increase min width for wrapped texts * wrap wrapped text in container * unwrap when binding text to container * rename `wrapped` to `autoResize` * fix lint * revert: use `center` align when wrapping text in container * update snaps * fix lint * simplify logic on autoResize * lint and test * snapshots * remove unnecessary code * snapshots * fix: defaults not set correctly * tests for wrapping texts when resized * tests for text wrapping when edited * fix autoResize refactor * include autoResize flag check * refactor * feat: rename action label & change contextmenu position * fix: update version on `autoResize` action * fix infinite loop when editing text in a container * simplify * always maintain `width` if `!autoResize` * maintain `x` if `!autoResize` * maintain `y` pos after fontSize change if `!autoResize` * refactor * when editing, do not wrap text in textWysiwyg * simplify text editor * make test more readable * comment * rename action to match file name * revert function signature change * only update in app --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
9 months ago
nextOriginalText: editable.value,
});
};
const cleanup = () => {
if (isDestroyed) {
return;
}
isDestroyed = true;
// remove events to ensure they don't late-fire
editable.onblur = null;
editable.oninput = null;
editable.onkeydown = null;
if (observer) {
observer.disconnect();
}
window.removeEventListener("resize", updateWysiwygStyle);
window.removeEventListener("wheel", stopEvent, true);
window.removeEventListener("pointerdown", onPointerDown);
window.removeEventListener("pointerup", bindBlurEvent);
window.removeEventListener("blur", handleSubmit);
window.removeEventListener("beforeunload", handleSubmit);
unbindUpdate();
editable.remove();
};
const bindBlurEvent = (event?: MouseEvent) => {
window.removeEventListener("pointerup", bindBlurEvent);
// Deferred so that the pointerdown that initiates the wysiwyg doesn't
// trigger the blur on ensuing pointerup.
// Also to handle cases such as picking a color which would trigger a blur
// in that same tick.
const target = event?.target;
const isTargetPickerTrigger =
target instanceof HTMLElement &&
target.classList.contains("active-color");
setTimeout(() => {
editable.onblur = handleSubmit;
if (isTargetPickerTrigger) {
const callback = (
mutationList: MutationRecord[],
observer: MutationObserver,
) => {
const radixIsRemoved = mutationList.find(
(mutation) =>
mutation.removedNodes.length > 0 &&
(mutation.removedNodes[0] as HTMLElement).dataset
?.radixPopperContentWrapper !== undefined,
);
if (radixIsRemoved) {
// should work without this in theory
// and i think it does actually but radix probably somewhere,
// somehow sets the focus elsewhere
setTimeout(() => {
editable.focus();
});
observer.disconnect();
}
};
const observer = new MutationObserver(callback);
observer.observe(document.querySelector(".excalidraw-container")!, {
childList: true,
});
}
// case: clicking on the same property → no change → no update → no focus
if (!isTargetPickerTrigger) {
editable.focus();
}
});
};
// prevent blur when changing properties from the menu
const onPointerDown = (event: MouseEvent) => {
const isTargetPickerTrigger =
event.target instanceof HTMLElement &&
event.target.classList.contains("active-color");
if (
((event.target instanceof HTMLElement ||
event.target instanceof SVGElement) &&
event.target.closest(`.${CLASSES.SHAPE_ACTIONS_MENU}`) &&
!isWritableElement(event.target)) ||
isTargetPickerTrigger
) {
editable.onblur = null;
window.addEventListener("pointerup", bindBlurEvent);
// handle edge-case where pointerup doesn't fire e.g. due to user
// alt-tabbing away
window.addEventListener("blur", handleSubmit);
}
};
// handle updates of textElement properties of editing element
const unbindUpdate = Scene.getScene(element)!.onUpdate(() => {
updateWysiwygStyle();
const isColorPickerActive = !!document.activeElement?.closest(
".color-picker-content",
);
if (!isColorPickerActive) {
editable.focus();
}
});
// ---------------------------------------------------------------------------
let isDestroyed = false;
// select on init (focusing is done separately inside the bindBlurEvent()
// because we need it to happen *after* the blur event from `pointerdown`)
editable.select();
bindBlurEvent();
// reposition wysiwyg in case of canvas is resized. Using ResizeObserver
// is preferred so we catch changes from host, where window may not resize.
let observer: ResizeObserver | null = null;
if (canvas && "ResizeObserver" in window) {
observer = new window.ResizeObserver(() => {
updateWysiwygStyle();
});
observer.observe(canvas);
} else {
window.addEventListener("resize", updateWysiwygStyle);
}
window.addEventListener("pointerdown", onPointerDown);
window.addEventListener("wheel", stopEvent, {
passive: false,
capture: true,
});
window.addEventListener("beforeunload", handleSubmit);
excalidrawContainer
?.querySelector(".excalidraw-textEditorContainer")!
.appendChild(editable);
};