{"version":3,"file":"X_ShapeNotes.min.mjs","sources":["../../../../src/shapes/canvasx/X_ShapeNotes.ts"],"sourcesContent":["import { TClassProperties } from '../../typedefs';\nimport { Textbox, TextboxProps } from '../Textbox';\nimport { classRegistry } from '../../ClassRegistry';\nimport { createRectNotesDefaultControls } from '../../controls/commonControls';\nimport { Shadow } from '../../Shadow';\n\nexport type { ITextProps, SerializedITextProps } from '../IText/IText';\n\n// @TODO: Many things here are configuration related and shouldn't be on the class nor prototype\n// regexes, list of properties that are not suppose to change by instances, magic consts.\n// this will be a separated effort\nexport const shapeNotesDefaultValues: Partial<TClassProperties<ShapeNotes>> = {\n  minWidth: 20,\n  dynamicMinWidth: 2,\n  lockScalingFlip: true,\n  noScaleCache: false,\n  _wordJoiners: /[ \\t\\r]/,\n  splitByGrapheme: true,\n  objType: 'WBShapeNotes',\n  height: 138,\n  textAlign: 'center',\n  centeredScaling: false,\n  verticalAlign: 'middle',\n  cornerStrokeColor: 'gray',\n  cornerStyle: 'circle',\n  cornerColor: 'white',\n  transparentCorners: false,\n};\n\nexport interface ShapeNotesProps extends TextboxProps {\n  icon: number;\n  id: string;\n}\n\n/**\n * Textbox class, based on IText, allows the user to resize the text rectangle\n * and wraps lines automatically. Textboxes have their Y scaling locked, the\n * user can only change width. Height is adjusted automatically based on the\n * wrapping of lines.\n */\nexport class ShapeNotes extends Textbox {\n  /**selectable\n   * Minimum width of textbox, in pixels.\n   * @type Number\n   * @default\n   */\n  declare minWidth: number;\n  declare lineWidth: number;\n\n  declare __skipDimension: Boolean;\n\n  declare objType: string;\n\n  declare locked: boolean;\n\n  declare whiteboardId: string;\n\n  declare userId: string;\n\n  declare timestamp: Date;\n\n  declare verticalAlign: string;\n\n  declare zIndex: number;\n\n  declare lines: object[];\n\n  declare relationship: object[];\n\n  declare icon: string;\n  declare maxHeight: number;\n\n  public extendPropeties = [\n    'objType',\n    'whiteboardId',\n    'userId',\n    'timestamp',\n    'zIndex',\n    'locked',\n    'verticalAlign',\n    'lines',\n    'id',\n    'zIndex',\n    'relationship',\n    'icon',\n  ];\n  /**\n   * Minimum calculated width of a textbox, in pixels.\n   * fixed to 2 so that an empty textbox cannot go to 0\n   * and is still selectable without text.\n   * @type Number\n   * @default\n   */\n  declare dynamicMinWidth: number;\n\n  /**\n   * Use this boolean property in order to split strings that have no white space concept.\n   * this is a cheap way to help with chinese/japanese\n   * @type Boolean\n   * @since 2.6.0\n   */\n  declare splitByGrapheme: boolean;\n\n  static textLayoutProperties = [...Textbox.textLayoutProperties, 'width'];\n\n  static ownDefaults: Record<string, any> = shapeNotesDefaultValues;\n\n  static getDefaults() {\n    return {\n      ...super.getDefaults(),\n      controls: createRectNotesDefaultControls(),\n      ...ShapeNotes.ownDefaults,\n    };\n  }\n\n  constructor(text: string, options: Partial<ShapeNotesProps>) {\n    super(text, options);\n  }\n\n  /**\n   * Unlike superclass's version of this function, Textbox does not update\n   * its width.\n   * @private\n   * @override\n   */\n  initDimensions() {\n    if (this.__skipDimension) {\n      return;\n    }\n\n    this.clearContextTop();\n    this._clearCache();\n\n    const newLines = this._splitText();\n\n    if (this.isEditing) {\n      this.initDelayedCursor();\n\n      const preHeight = this.height;\n      const total = this._getTotalLineHeights() + this.getTopOffset();\n      this.height = Math.max(this.maxHeight, total);\n      const yOffset = this.height - preHeight;\n      this.top += yOffset / 2;\n    } else if (this._textLines && this._textLines.length > 0) {\n      if (this.height === this.maxHeight) {\n        /**\n         * scaling\n         * total height of _textLines < maxHeight\n         */\n        let lineHeights = 0;\n        const tmp = [];\n        for (let i = 0, len = this._textLines.length; i < len; i++) {\n          const heightOfLine = this.getHeightOfLine(i);\n          lineHeights += heightOfLine;\n          if (lineHeights <= this.height - this.getTopOffset()) {\n            tmp.push(this._textLines[i]);\n          }\n        }\n        if (tmp.length > 0) {\n          const preLines = this._textLines.length;\n          this._textLines = tmp;\n          if (tmp.length !== preLines) {\n            // need add ellipsis at last line\n            const lastIndex = this._textLines.length - 1,\n              lastLine = this._textLines[lastIndex];\n            lastLine.pop();\n            lastLine.pop();\n            lastLine.pop();\n            lastLine.push('.');\n            lastLine.push('.');\n            lastLine.push('.');\n          }\n        }\n      } else if (this.height > this.maxHeight) {\n        /**\n         * height > maxHeight\n         * exit editing and _textlines total height > maxHeight\n         */\n        // console.log('### exit editing & initDimensions');\n      }\n    }\n\n    // clear dynamicMinWidth as it will be different after we re-wrap line\n    this.dynamicMinWidth = 0;\n    // wrap lines\n    this._styleMap = this._generateStyleMap(newLines);\n    // if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap\n    if (this.dynamicMinWidth > this.width) {\n      this._set('width', this.dynamicMinWidth);\n    }\n    if (this.textAlign.indexOf('justify') !== -1) {\n      // once text is measured we need to make space fatter to make justified text.\n      this.enlargeSpaces();\n    }\n\n    return this.height;\n  }\n  // /**\n  //  * Generate an object that translates the style object so that it is\n  //  * broken up by visual lines (new lines and automatic wrapping).\n  //  * The original text styles object is broken up by actual lines (new lines only),\n  //  * which is only sufficient for Text / IText\n  //  * @private\n  //  */\n  // _generateStyleMap(textInfo:;any) {\n  //   let realLineCount = 0,\n  //     realLineCharCount = 0,\n  //     charCount = 0;\n  //   const map = {};\n\n  //   for (let i = 0; i < textInfo.graphemeLines.length; i++) {\n  //     if (textInfo.graphemeText[charCount] === '\\n' && i > 0) {\n  //       realLineCharCount = 0;\n  //       charCount++;\n  //       realLineCount++;\n  //     } else if (\n  //       !this.splitByGrapheme &&\n  //       this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) &&\n  //       i > 0\n  //     ) {\n  //       // this case deals with space's that are removed from end of lines when wrapping\n  //       realLineCharCount++;\n  //       charCount++;\n  //     }\n\n  //     map[i] = { line: realLineCount, offset: realLineCharCount };\n\n  //     charCount += textInfo.graphemeLines[i].length;\n  //     realLineCharCount += textInfo.graphemeLines[i].length;\n  //   }\n\n  //   return map;\n  // }\n\n  // /**\n  //  * Returns true if object has a style property or has it on a specified line\n  //  * @param {Number} lineIndex\n  //  * @return {Boolean}\n  //  */\n  // styleHas(property, lineIndex: number): boolean {\n  //   if (this._styleMap && !this.isWrapping) {\n  //     const map = this._styleMap[lineIndex];\n  //     if (map) {\n  //       lineIndex = map.line;\n  //     }\n  //   }\n  //   return super.styleHas(property, lineIndex);\n  // }\n\n  // /**\n  //  * Returns true if object has no styling or no styling in a line\n  //  * @param {Number} lineIndex , lineIndex is on wrapped lines.\n  //  * @return {Boolean}\n  //  */\n  // isEmptyStyles(lineIndex: number): boolean {\n  //   if (!this.styles) {\n  //     return true;\n  //   }\n  //   let offset = 0,\n  //     nextLineIndex = lineIndex + 1,\n  //     nextOffset,\n  //     shouldLimit = false;\n  //   const map = this._styleMap[lineIndex],\n  //     mapNextLine = this._styleMap[lineIndex + 1];\n  //   if (map) {\n  //     lineIndex = map.line;\n  //     offset = map.offset;\n  //   }\n  //   if (mapNextLine) {\n  //     nextLineIndex = mapNextLine.line;\n  //     shouldLimit = nextLineIndex === lineIndex;\n  //     nextOffset = mapNextLine.offset;\n  //   }\n  //   const obj =\n  //     typeof lineIndex === 'undefined'\n  //       ? this.styles\n  //       : { line: this.styles[lineIndex] };\n  //   for (const p1 in obj) {\n  //     for (const p2 in obj[p1]) {\n  //       if (p2 >= offset && (!shouldLimit || p2 < nextOffset)) {\n  //         // eslint-disable-next-line no-unused-vars\n  //         for (const p3 in obj[p1][p2]) {\n  //           return false;\n  //         }\n  //       }\n  //     }\n  //   }\n  //   return true;\n  // }\n\n  // /**\n  //  * @param {Number} lineIndex\n  //  * @param {Number} charIndex\n  //  * @private\n  //  */\n  // _getStyleDeclaration(lineIndex: number, charIndex: number) {\n  //   if (this._styleMap && !this.isWrapping) {\n  //     const map = this._styleMap[lineIndex];\n  //     if (!map) {\n  //       return null;\n  //     }\n  //     lineIndex = map.line;\n  //     charIndex = map.offset + charIndex;\n  //   }\n  //   return super._getStyleDeclaration(lineIndex, charIndex);\n  // }\n\n  /**\n   * @param {Number} lineIndex\n   * @param {Number} charIndex\n   * @param {Object} style\n   * @private\n   */\n  _setStyleDeclaration(lineIndex: number, charIndex: number, style: object) {\n    const map = this._styleMap[lineIndex];\n    lineIndex = map.line;\n    charIndex = map.offset + charIndex;\n\n    this.styles[lineIndex][charIndex] = style;\n  }\n\n  /**\n   * @param {Number} lineIndex\n   * @param {Number} charIndex\n   * @private\n   */\n  _deleteStyleDeclaration(lineIndex: number, charIndex: number) {\n    const map = this._styleMap[lineIndex];\n    lineIndex = map.line;\n    charIndex = map.offset + charIndex;\n    delete this.styles[lineIndex][charIndex];\n  }\n\n  /**\n   * probably broken need a fix\n   * Returns the real style line that correspond to the wrapped lineIndex line\n   * Used just to verify if the line does exist or not.\n   * @param {Number} lineIndex\n   * @returns {Boolean} if the line exists or not\n   * @private\n   */\n  _getLineStyle(lineIndex: number): boolean {\n    const map = this._styleMap[lineIndex];\n    return !!this.styles[map.line];\n  }\n\n  /**\n   * Set the line style to an empty object so that is initialized\n   * @param {Number} lineIndex\n   * @param {Object} style\n   * @private\n   */\n  _setLineStyle(lineIndex: number) {\n    const map = this._styleMap[lineIndex];\n    this.styles[map.line] = {};\n  }\n\n  // /**\n  //  * Wraps text using the 'width' property of Textbox. First this function\n  //  * splits text on newlines, so we preserve newlines entered by the user.\n  //  * Then it wraps each line using the width of the Textbox by calling\n  //  * _wrapLine().\n  //  * @param {Array} lines The string array of text that is split into lines\n  //  * @param {Number} desiredWidth width you want to wrap to\n  //  * @returns {Array} Array of lines\n  //  */\n  // _wrapText(lines: Array<any>, desiredWidth: number): Array<any> {\n  //   const wrapped = [];\n  //   this.isWrapping = true;\n  //   for (let i = 0; i < lines.length; i++) {\n  //     wrapped.push(...this._wrapLine(lines[i], i, desiredWidth));\n  //   }\n  //   this.isWrapping = false;\n  //   return wrapped;\n  // }\n\n  // /**\n  //  * Helper function to measure a string of text, given its lineIndex and charIndex offset\n  //  * It gets called when charBounds are not available yet.\n  //  * Override if necessary\n  //  * Use with {@link Textbox#wordSplit}\n  //  *\n  //  * @param {CanvasRenderingContext2D} ctx\n  //  * @param {String} text\n  //  * @param {number} lineIndex\n  //  * @param {number} charOffset\n  //  * @returns {number}\n  //  */\n  // _measureWord(word, lineIndex: number, charOffset = 0): number {\n  //   let width = 0,\n  //     prevGrapheme;\n  //   const skipLeft = true;\n  //   for (let i = 0, len = word.length; i < len; i++) {\n  //     const box = this._getGraphemeBox(\n  //       word[i],\n  //       lineIndex,\n  //       i + charOffset,\n  //       prevGrapheme,\n  //       skipLeft\n  //     );\n  //     width += box.kernedWidth;\n  //     prevGrapheme = word[i];\n  //   }\n  //   return width;\n  // }\n\n  /**\n   * Override this method to customize word splitting\n   * Use with {@link Textbox#_measureWord}\n   * @param {string} value\n   * @returns {string[]} array of words\n   */\n  wordSplit(value: string): string[] {\n    return value.split(this._wordJoiners);\n  }\n\n  /**\n   * Wraps a line of text using the width of the Textbox and a context.\n   * @param {Array} line The grapheme array that represent the line\n   * @param {Number} lineIndex\n   * @param {Number} desiredWidth width you want to wrap the line to\n   * @param {Number} reservedSpace space to remove from wrapping for custom functionalities\n   * @returns {Array} Array of line(s) into which the given text is wrapped\n   * to.\n   */\n  /** This is the method of char split */\n  graphemeSplitForRectNotes(textstring: string): string[] {\n    const graphemes = [];\n    const words = textstring.split(/\\b/);\n    for (let i = 0; i < words.length; i++) {\n      // 检查单词是否全为拉丁字母，长度不大于16\n      if (/^[a-zA-Z]{1,16}$/.test(words[i])) {\n        graphemes.push(words[i]);\n      } else {\n        for (let j = 0; j < words[i].length; j++) {\n          graphemes.push(words[i][j]);\n        }\n      }\n    }\n    return graphemes;\n  }\n\n  // _wrapLine(\n  //   _line: any,\n  //   lineIndex: number,\n  //   desiredWidth: number,\n  //   reservedSpace = 0\n  // ): Array<any> {\n  //   const additionalSpace = this._getWidthOfCharSpacing(),\n  //     splitByGrapheme = this.splitByGrapheme,\n  //     graphemeLines = [],\n  //     words = splitByGrapheme\n  //       ? this.graphemeSplitForRectNotes(_line)\n  //       : this.wordSplit(_line),\n  //     infix = splitByGrapheme ? '' : ' ';\n\n  //   let lineWidth = 0,\n  //     line: any[] = [],\n  //     // spaces in different languages?\n  //     offset = 0,\n  //     infixWidth = 0,\n  //     largestWordWidth = 0,\n  //     lineJustStarted = true;\n  //   // fix a difference between split and graphemeSplit\n  //   if (words.length === 0) {\n  //     words.push([]);\n  //   }\n  //   desiredWidth -= reservedSpace;\n  //   // measure words\n  //   const data = words.map((word) => {\n  //     // if using splitByGrapheme words are already in graphemes.\n  //     word = splitByGrapheme ? word : this.graphemeSplitForRectNotes(word);\n  //     const width = this._measureWord(word, lineIndex, offset);\n  //     largestWordWidth = Math.max(width, largestWordWidth);\n  //     offset += word.length + 1;\n  //     return { word: word, width: width };\n  //   });\n  //   const maxWidth = Math.max(\n  //     desiredWidth,\n  //     largestWordWidth,\n  //     this.dynamicMinWidth\n  //   );\n  //   // layout words\n  //   offset = 0;\n  //   let i;\n  //   for (i = 0; i < words.length; i++) {\n  //     const word = data[i].word;\n  //     const wordWidth = data[i].width;\n  //     offset += word.length;\n\n  //     lineWidth += infixWidth + wordWidth - additionalSpace;\n  //     if (lineWidth > maxWidth && !lineJustStarted) {\n  //       graphemeLines.push(line);\n  //       line = [];\n  //       lineWidth = wordWidth;\n  //       lineJustStarted = true;\n  //     } else {\n  //       lineWidth += additionalSpace;\n  //     }\n\n  //     if (!lineJustStarted && !splitByGrapheme) {\n  //       line.push(infix);\n  //     }\n  //     if (word.length > 1) {\n  //       line = line.concat(word.split(''));\n  //     } else {\n  //       line = line.concat(word);\n  //     }\n\n  //     infixWidth = splitByGrapheme\n  //       ? 0\n  //       : this._measureWord([infix], lineIndex, offset);\n  //     offset++;\n  //     lineJustStarted = false;\n  //   }\n\n  //   i && graphemeLines.push(line);\n\n  //   if (largestWordWidth + reservedSpace > this.dynamicMinWidth) {\n  //     this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace;\n  //   }\n  //   return graphemeLines;\n  // }\n\n  /**\n   * Detect if the text line is ended with an hard break\n   * text and itext do not have wrapping, return false\n   * @param {Number} lineIndex text to split\n   * @return {Boolean}\n   */\n  isEndOfWrapping(lineIndex: number): boolean {\n    if (!this._styleMap[lineIndex + 1]) {\n      // is last line, return true;\n      return true;\n    }\n    if (this._styleMap[lineIndex + 1].line !== this._styleMap[lineIndex].line) {\n      // this is last line before a line break, return true;\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * Detect if a line has a linebreak and so we need to account for it when moving\n   * and counting style.\n   * @return Number\n   */\n  missingNewlineOffset(lineIndex: number) {\n    if (this.splitByGrapheme) {\n      return this.isEndOfWrapping(lineIndex) ? 1 : 0;\n    }\n    return 1;\n  }\n\n  /**\n   * Gets lines of text to render in the Textbox. This function calculates\n   * text wrapping on the fly every time it is called.\n   * @param {String} text text to split\n   * @returns {Array} Array of lines in the Textbox.\n   * @override\n   */\n  textSplitTextIntoLines(text: string) {\n    const lines = text.split(this._reNewline),\n      newLines = new Array<string[]>(lines.length),\n      newLine = ['\\n'];\n    let newText: string[] = [];\n    for (let i = 0; i < lines.length; i++) {\n      newLines[i] = this.graphemeSplit(lines[i]);\n      newText = newText.concat(newLines[i], newLine);\n    }\n    newText.pop();\n    return {\n      _unwrappedLines: newLines,\n      lines: lines,\n      graphemeText: newText,\n      graphemeLines: newLines,\n    };\n  }\n  _splitTextIntoLines(text: string) {\n    const width = this.width - this.getLeftOffset();\n\n    const newText = this.textSplitTextIntoLines(text),\n      graphemeLines = this._wrapText(newText.lines, width),\n      lines = new Array(graphemeLines.length);\n    for (let i = 0; i < graphemeLines.length; i++) {\n      lines[i] = graphemeLines[i].join('');\n    }\n    newText.lines = lines;\n    newText.graphemeLines = graphemeLines;\n    return newText;\n  }\n\n  getMinWidth() {\n    return Math.max(this.minWidth, this.dynamicMinWidth);\n  }\n\n  // _removeExtraneousStyles() {\n  //   const linesToKeep = {};\n  //   for (const prop in this._styleMap) {\n  //     if (this._textLines[prop]) {\n  //       linesToKeep[this._styleMap[prop].line] = 1;\n  //     }\n  //   }\n  //   for (const prop in this.styles) {\n  //     if (!linesToKeep[prop]) {\n  //       delete this.styles[prop];\n  //     }\n  //   }\n  // }\n\n  getObject() {\n    const object = {};\n    const keys = [\n      'id',\n      'angle',\n      'backgroundColor',\n      'fill',\n      'fontFamily',\n      'fontSize',\n      'height',\n      'width',\n      'left',\n      'lines', // the arrows array [{…}]\n      'lockUniScaling',\n      'locked',\n      'lockMovementX', // boolean, lock the verticle movement\n      'lockMovementY', // boolean, lock the horizontal movement\n      'lockScalingFlip', // boolean,  make it can not be inverted by pulling the width to the negative side\n      'fontWeight',\n      'lineHeight',\n      'objType',\n      'originX',\n      'originY',\n      'panelObj', // the parent panel string\n      'relationship', // relationship with panel for transform  [1.43, 0, 0, 1.43, 7.031931057304291, 16.531768328466796]\n      'scaleX',\n      'scaleY',\n      'selectable',\n      'text',\n      'textAlign',\n      'top',\n      'userNo',\n      'userId',\n      'whiteboardId',\n      'zIndex',\n      'version',\n      'isPanel',\n      'editable',\n      'path',\n      'strokeWidth',\n      'strokeUniform', // set up to true then strokewidth doesn't change when scaling\n      'stroke', // border color\n      'selectable', // boolean, When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). But events still fire on it.\n      'icon',\n      'lineWidth',\n      'fixedLineWidth',\n      'aCoords',\n      'shapeScaleX',\n      'shapeScaleY',\n      'verticalAlign',\n      'maxHeight',\n      'shadow',\n      'subObjs',\n    ];\n    keys.forEach((key) => {\n      //@ts-ignore\n      object[key] = this[key];\n    });\n    return object;\n  }\n\n  // /**\n  //  * Returns object representation of an instance\n  //  * @method toObject\n  //  * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output\n  //  * @return {Object} object representation of an instance\n  //  */\n  // toObject(propertiesToInclude: Array<any>): object {\n  //   return super.toObject(\n  //     [...this.extendPropeties, 'minWidth', 'splitByGrapheme'].concat(\n  //       propertiesToInclude\n  //     )\n  //   );\n  // }\n  /**boardx custom function */\n  getObjectsIntersected() {\n    //@ts-ignore\n    const objects = this.canvas._getIntersectedObjects(this);\n    objects.filter((obj: any) => {\n      return obj.id !== this.id && obj.objType !== 'WBArrow';\n    });\n    return objects;\n  }\n\n  setLockedShadow(locked: boolean) {\n    if (locked) {\n      this.shadow = new Shadow({\n        blur: 2,\n        offsetX: 0,\n        offsetY: 0,\n        color: 'rgba(0, 0, 0, 0.5)',\n      });\n    } else {\n      this.shadow = new Shadow({\n        blur: 8,\n        offsetX: 0,\n        offsetY: 4,\n        color: 'rgba(0,0,0,0.04)',\n      });\n    }\n  }\n\n  /* caculate cusor positon in the middle of the textbox */\n  getCenteredTop(rectHeight: number) {\n    const textHeight = this.height;\n    return (rectHeight - textHeight) / 2;\n  }\n\n  _renderBackground(ctx: any) {\n    if (!this.backgroundColor) {\n      return;\n    }\n    const dim = this._getNonTransformedDimensions();\n    ctx.fillStyle = this.backgroundColor;\n\n    //ctx.shadowBlur = 20;\n    // ctx.shadowOffsetX = 2 * this.scaleX * canvas.getZoom();\n    // ctx.shadowOffsetY = 6 * this.scaleY * canvas.getZoom();\n    //ctx.shadowColor = 'rgba(0,0,0,0.1)';\n    // ctx.shadowColor = 'rgba(0,0,0,1)';\n\n    //ctx.fillRect(-dim.x / 2, -dim.y / 2, dim.x, dim.y);\n\n    // if there is background color no other shadows\n    // should be casted\n    //this._removeShadow(ctx);\n    /*\n      0: rect\n      1: diamond\n      2: rounded rect\n      3: circle\n      4: hexagon\n      5: triangle\n      6: parallelogramIcon\n      7: star\n      8: cross\n      9: leftside right triangle\n      10: rightside right triangle\n      11: topside semicirle circle\n      12: top-left quarter circle\n      13: Constallation Rect\n      14: Constellation Round\n    */\n\n    const shapeArray = [\n      'M-50,-50L50,-50 50,50 -50,50z', // 0: rect\n      'm-50,0 l50,-50 50,50 -50,50 -50,-50z', // 1: diamond\n      'M-50,-35 Q-50,-50 -35,-50 L35,-50 Q50,-50 50,-35 L50,35 Q50,50 35,50 L-35,50 Q-50,50 -50,35 Z', // 2: rounded rect\n      'M-50,0a50,50 0 1,0 100,0a50,50 0 1,0 -100,0', // 3: circle\n      'm -43.476 -25.4636 l 43.476 -24.5364 l 43.7551 25.2641 l 0 50.5157 l -43.7551 24.2202 l -43.7551 -25.2654 l 0 -50.5157 z', // 4: hexagon\n      'm-50,50l50,-100l50,100l-100,0z', // 5: triangle\n      'm-50,50l20,-100l80,0l-20,100l-80,0z', // 6: parallelogramIcon\n      'm-50,-10l38,0l12,-38l12,38l38,0l-30,23l12,38l-30,-24l-30,24l12,-38l-30,-23z', // 7: star\n      'm-50,-15l33,0l0,-33l34,0l0,33l33,0l0,34l-33,0l0,33l-34,0l0,-33l-33,0l0,-34z', // 8: cross\n      'm50,50l-100,0l0,-100l100,100z', // 9: leftside right triangle\n      'm-50,50l100,0l0,-100l-100,100z', // 10: rightside right triangle\n      'm50,25l-100,-0.00205c3.5,-27.5 25,-48 50,-48c25,0 46.5,20.5 50,48z', // 11: topside semicirle circle\n      'm-50,50c7,-55 47,-96 97,-97l0,65l0,32l-97,-0.00392z', // 12: top-left quarter circle\n      'm20,0l25,23l0,24l-100,0l0,-100l100,0l0,23l-25,24l-0.15,0.14l0.15,0.14l-0.00001,0z', // 13: Constallation Rect\n      'm20,1c0.002,0.002 0.004,0.004 0.01,0.001c0.007,0.01 0.015,0.02 0.02,0.03l0,0l0.001,0.0004l0.005,0.003l0.04,0.03l0.3,0.2l2.5,2l20,15c-7,15 -23,26 -42,26c-25,0 -45,-20 -45,-45c0,-25 20,-45 45,-45c19,0 35,10 42,25c-11,9 -17,14 -20,16c-1.5,1 -2,1.5 -2.5,2c-0.2,0.15 -0.3,0.2 -0.35,0.3c-0.02,0.02 -0.04,0.04 -0.05,0.06c-0.006,0.01 -0.02,0.03 -0.03,0.06c-0.005,0.015 -0.02,0.04 -0.03,0.07c-0.005,0.015 -0.01,0.04 -0.007,0.07c0.002,0.02 0.007,0.04 0.015,0.06c0.003,0.006 0.006,0.012 0.009,0.018c0.003,0.004 0.006,0.009 0.009,0.014c0.003,0.005 0.009,0.01 0.01,0.015c0.004,0.005 0.01,0.015 0.012,0.017z', // 14: Constellation Round\n    ];\n\n    ctx.save();\n\n    // Ensure the fill and stroke styles are set as expected\n    ctx.fillStyle = this.backgroundColor;\n    ctx.strokeStyle = this.stroke || 'black'; // Default stroke color\n    ctx.lineWidth = this.lineWidth || 1; // Default line width\n\n    // Define the transformation matrix\n    const scale = Math.min(this.width / 100, this.height / 100); // Keeping aspect ratio intact\n    const dx = (this.width - 100 * scale) / 2; // Center horizontally\n    const dy = (this.height - 100 * scale) / 2; // Center vertically\n\n    const m = new DOMMatrix();\n    m.a = scale; // Scale horizontally\n    m.d = scale; // Scale vertically\n    m.e = dx; // Translate horizontally\n    m.f = dy; // Translate vertically\n\n    // Create the path from SVG path data\n    const path = new Path2D();\n    //@ts-ignore\n    const svgPath = new Path2D(shapeArray[this.icon]); // Get the SVG path from your array based on this.icon\n    path.addPath(svgPath, m);\n\n    // Draw the path\n    ctx.stroke(path);\n    ctx.fill(path);\n\n    ctx.restore();\n  }\n  getTopOffset() {\n    let tOffset = 0;\n    switch (this.icon) {\n      case '0':\n      case '2':\n        tOffset = 40;\n        break;\n      case '1':\n      case '3':\n      case '5':\n        tOffset = this.height / 2;\n        break;\n      case '4':\n        tOffset = this.height / 3;\n        break;\n      default:\n    }\n    return tOffset;\n  }\n  getLeftOffset() {\n    let lOffset = 0;\n    switch (this.icon) {\n      case '0':\n      case '2':\n      case '4':\n        lOffset = 40;\n        break;\n      case '1':\n      case '3':\n      case '5':\n        lOffset = this.width / 2;\n        break;\n      default:\n    }\n    return lOffset;\n  }\n  _getTopOffset() {\n    switch (this.verticalAlign) {\n      case 'middle':\n        return -this._getTotalLineHeight() / 2;\n      case 'bottom':\n        return this.height / 2 - this._getTotalLineHeight();\n      default:\n        return -this.height / 2;\n    }\n  }\n  _getTotalLineHeight() {\n    return this._textLines.reduce(\n      (total, _line, index) => total + this.getHeightOfLine(index),\n      0\n    );\n  }\n\n  _renderText(ctx: any) {\n    ctx.shadowOffsetX = ctx.shadowOffsetY = ctx.shadowBlur = 0;\n    ctx.shadowColor = '';\n\n    if (this.paintFirst === 'stroke') {\n      this._renderTextStroke(ctx);\n      this._renderTextFill(ctx);\n    } else {\n      this._renderTextFill(ctx);\n      this._renderTextStroke(ctx);\n    }\n  }\n  calcTextHeight(): number {\n    let lineHeight;\n    let height = 0;\n    for (let i = 0, len = this._textLines.length; i < len; i++) {\n      lineHeight = this.getHeightOfLine(i);\n      height += i === len - 1 ? lineHeight / this.lineHeight : lineHeight;\n    }\n\n    const desiredHeight = this.height * (100 / 138);\n\n    if (height > desiredHeight) {\n      this.set('fontSize', this.fontSize - 2);\n      //@ts-ignore\n      this._splitTextIntoLines(this.text);\n      height = this.maxHeight;\n      return Math.max(height, this.height);\n    }\n    if (\n      height < this.maxHeight &&\n      this.maxHeight - height > 60 &&\n      this.fontSize < 24\n    ) {\n      this.fontSize += 2;\n      //@ts-ignore\n      this._splitTextIntoLines(this.text.trim());\n\n      return Math.max(height, this.height);\n    }\n\n    this.height = this.maxHeight;\n    return Math.max(height, this.height);\n  }\n  _renderTextCommon(ctx: any, method: any) {\n    ctx.save();\n    let lineHeights = 0;\n    const left = this._getLeftOffset();\n    const top = this._getTopOffset();\n    const filler: any = method === 'fillText' ? this.fill : this.stroke;\n    const offsets = this._applyPatternGradientTransform(ctx, filler);\n\n    for (let i = 0, len = this._textLines.length; i < len; i++) {\n      const heightOfLine = this.getHeightOfLine(i);\n      const maxHeight = heightOfLine / this.lineHeight;\n      const leftOffset = this._getLineLeftOffset(i);\n      this._renderTextLine(\n        method,\n        ctx,\n        this._textLines[i],\n        left + leftOffset - offsets.offsetX,\n        top + lineHeights + maxHeight - offsets.offsetY,\n        i\n      );\n      lineHeights += heightOfLine;\n    }\n    ctx.restore();\n  }\n  // renderEmoji(ctx) {\n  //   if (this.emoji === undefined) {\n  //     return;\n  //   }\n\n  //   let width = 0;\n  //   const imageList = [\n  //     this.canvas.emoji_thumb,\n  //     this.canvas.emoji_love,\n  //     this.canvas.emoji_smile,\n  //     this.canvas.emoji_shock,\n  //     this.canvas.emoji_question,\n  //   ];\n  //   const imageListArray = [];\n  //   const emojiList = [];\n  //   for (let i = 0; i < 5; i++) {\n  //     if (this.emoji[i] !== 0) {\n  //       imageListArray.push(imageList[i]);\n  //       emojiList.push(this.emoji[i]);\n  //       width += 26.6;\n  //     }\n  //   }\n\n  //   if (emojiList.length === 0) return;\n\n  //   const x = this.width / 2 - width;\n  //   const y = this.height / 2 - 18;\n  //   ctx.font = '10px Inter ';\n  //   ctx.lineJoin = 'round';\n  //   ctx.save();\n  //   ctx.translate(x - 10, y);\n  //   this.drawRoundRectPath(ctx, width, 15, 2);\n  //   ctx.fillStyle = 'rgba(255, 255, 255, 1)';\n  //   ctx.fill();\n  //   ctx.restore();\n\n  //   //ctx.strokeRect(x - 10, y, width, 16);\n  //   //ctx.fillRect(x - 10 + 10 / 2, y + 10 / 2, width - 10, 16 - 10);\n  //   ctx.fillStyle = '#000';\n  //   const isEmojiThumbExist = !(this.canvas.emoji_thumb === undefined);\n  //   if (isEmojiThumbExist) {\n  //     let modifier = 0;\n  //     for (let i = 0; i < imageListArray.length; i++) {\n  //       const imageX = this.width / 2 - 33.6 + modifier + 2;\n  //       const imageY = this.height / 2 - 15;\n  //       const imageW = 10;\n  //       const imageH = 10;\n  //       ctx.drawImage(imageListArray[i], imageX, imageY, imageW, imageH);\n  //       ctx.fillText(\n  //         emojiList[i].toString(),\n  //         this.width / 2 - 20.6 + modifier + 1,\n  //         y + 12\n  //       );\n  //       modifier -= 23.6;\n  //     }\n  //   }\n  // }\n\n  _getTotalLineHeights() {\n    return this._textLines.reduce(\n      (total, _line, index) => total + this.getHeightOfLine(index),\n      0\n    );\n  }\n\n  _getSVGLeftTopOffsets() {\n    return {\n      textLeft: -this.width / 2,\n      textTop: this._getTopOffset(),\n      lineTop: this.getHeightOfLine(0),\n    };\n  }\n  getWidgetMenuList() {\n    if (this.locked) {\n      return ['objectLock'];\n    }\n    return [\n      'more',\n      'fontSize',\n      'textAlign',\n      'changeFont',\n      'backgroundColor',\n      'fontColor',\n      'borderLineIcon',\n      'fontWeight',\n      'objectLock',\n      'shapeBorderColor',\n      'lineWidth',\n      'borderLineIcon',\n      'delete',\n      'aiassist',\n    ];\n  }\n  getWidgetMenuLength() {\n    if (this.locked) return 50;\n    return 420;\n  }\n  getContextMenuList() {\n    let menuList;\n    if (this.locked) {\n      menuList = [\n        'Export board',\n        'Exporting selected area',\n        'Create Share Back',\n        'Bring forward',\n        'Bring to front',\n        'Send backward',\n        'Send to back',\n        'Copy as image',\n        'Copy As Text',\n      ];\n    } else {\n      menuList = [\n        'Export board',\n        'Exporting selected area',\n        'Create Share Back',\n        'Bring forward',\n        'Bring to front',\n        'Send backward',\n        'Send to back',\n        'Duplicate',\n        'Copy',\n        'Copy as image',\n        'Copy As Text',\n        'Paste',\n        'Cut',\n        'Edit',\n        'Delete',\n      ];\n    }\n    menuList.push('Select All');\n    if (this.locked) {\n      menuList.push('Unlock');\n    } else {\n      menuList.push('Lock');\n    }\n    // const notLockedPanel = this.isPanel && !this.locked;\n    // if (notLockedPanel) {\n    //   menuList.push('Switch to non-panel');\n    // } else {\n    //   menuList.push('Switch to panel');\n    // }\n    return menuList;\n  }\n}\n\nclassRegistry.setClass(ShapeNotes);\n"],"names":["shapeNotesDefaultValues","minWidth","dynamicMinWidth","lockScalingFlip","noScaleCache","_wordJoiners","splitByGrapheme","objType","height","textAlign","centeredScaling","verticalAlign","cornerStrokeColor","cornerStyle","cornerColor","transparentCorners","ShapeNotes","Textbox","getDefaults","_objectSpread","super","controls","createRectNotesDefaultControls","ownDefaults","constructor","text","options","_defineProperty","this","initDimensions","__skipDimension","clearContextTop","_clearCache","newLines","_splitText","isEditing","initDelayedCursor","preHeight","total","_getTotalLineHeights","getTopOffset","Math","max","maxHeight","yOffset","top","_textLines","length","lineHeights","tmp","i","len","getHeightOfLine","push","preLines","lastIndex","lastLine","pop","_styleMap","_generateStyleMap","width","_set","indexOf","enlargeSpaces","_setStyleDeclaration","lineIndex","charIndex","style","map","line","offset","styles","_deleteStyleDeclaration","_getLineStyle","_setLineStyle","wordSplit","value","split","graphemeSplitForRectNotes","textstring","graphemes","words","test","j","isEndOfWrapping","missingNewlineOffset","textSplitTextIntoLines","lines","_reNewline","Array","newLine","newText","graphemeSplit","concat","_unwrappedLines","graphemeText","graphemeLines","_splitTextIntoLines","getLeftOffset","_wrapText","join","getMinWidth","getObject","object","forEach","key","getObjectsIntersected","objects","canvas","_getIntersectedObjects","filter","obj","id","setLockedShadow","locked","shadow","Shadow","blur","offsetX","offsetY","color","getCenteredTop","rectHeight","_renderBackground","ctx","backgroundColor","_getNonTransformedDimensions","fillStyle","save","strokeStyle","stroke","lineWidth","scale","min","dx","dy","m","DOMMatrix","a","d","e","f","path","Path2D","svgPath","icon","addPath","fill","restore","tOffset","lOffset","_getTopOffset","_getTotalLineHeight","reduce","_line","index","_renderText","shadowOffsetX","shadowOffsetY","shadowBlur","shadowColor","paintFirst","_renderTextStroke","_renderTextFill","calcTextHeight","lineHeight","set","fontSize","trim","_renderTextCommon","method","left","_getLeftOffset","filler","offsets","_applyPatternGradientTransform","heightOfLine","leftOffset","_getLineLeftOffset","_renderTextLine","_getSVGLeftTopOffsets","textLeft","textTop","lineTop","getWidgetMenuList","getWidgetMenuLength","getContextMenuList","menuList","textLayoutProperties","classRegistry","setClass"],"mappings":"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"}