{"version":3,"file":"XTextbase.min.mjs","sources":["../../../../src/shapes/canvasx/XTextbase.ts"],"sourcesContent":["import { TClassProperties, TOriginX, TOriginY } from '../../typedefs';\nimport { IText } from '../IText/IText';\nimport { classRegistry } from '../../ClassRegistry';\nimport { createTextboxDefaultControls } from '../../controls/X_commonControls';\nimport { EventName, Origin } from './types';\nimport { Textbox } from '../Textbox';\n\nimport { WidgetType } from './type/widget.type';\nimport { WidgetTextboxInterface, EntityKeys } from './type/widget.entity.textbox';\n\n\nimport { Point } from '../../Point';\nimport { XConnector } from './XConnector';\nimport { FabricObject } from '../Object/Object';\n\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 textboxDefaultValues: Partial<TClassProperties<XTextbase>> = {\n  minWidth: 20,\n  dynamicMinWidth: 2,\n  // _wordJoiners: /[ \\t\\r]/,\n  splitByGrapheme: false,\n  cornerColor: 'white',\n  cornerSize: 10,\n  cornerStyle: 'circle',\n  transparentCorners: false,\n  cornerStrokeColor: 'gray',\n  connectors: [],\n};\n\nclass Connector {\n  connectorId: string;\n  connectorType: string;\n  point: Point;\n}\n\nexport const XTextbaseProps: Partial<TClassProperties<XTextbase>> = {};\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 XTextbase\n  extends Textbox\n  implements WidgetTextboxInterface {\n  static type: WidgetType = 'XTextbase';\n  static objType: WidgetType = 'XTextbase';\n  /**\n   * Minimum width of textbox, in pixels.\n   * @type Number\n   * @default\n   */\n  declare minWidth: number;\n\n  declare tempTop: number;\n\n  declare hasNoText: boolean;\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  declare oneLine: boolean;\n\n  declare fromCopy: boolean;\n  declare originX: TOriginX;\n  declare originY: TOriginY;\n  declare connectors: Connector[];\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 = [...IText.textLayoutProperties, 'width'];\n\n  static ownDefaults: Record<string, any> = textboxDefaultValues;\n\n\n\n  static getDefaults() {\n    return {\n      ...super.getDefaults(),\n      controls: createTextboxDefaultControls(),\n      ...XTextbase.ownDefaults,\n    };\n  }\n\n\n\n  constructor(text: string, options: any) {\n\n    options.oneLine = options.oneLine || true;\n    options.connectors = options.connectors || [];\n    options.originX = options.originX || 'center';\n    options.originY = options.originY || 'center';\n    options.minWidth = options.minWidth || 20;\n    options.dynamicMinWidth = options.dynamicMinWidth || 2;\n    options.splitByGrapheme = options.splitByGrapheme || false;\n    options.fixedScaleChange = options.fixedScaleChange || false;\n    options.boardId = options.boardId || '';\n\n    options.userId = options.userId || '';\n    options.zIndex = options.zIndex || 0;\n    options.version = options.version || '';\n    options.updatedAt = options.updatedAt || Date.now();\n    options.lastEditedByName = options.lastEditedByName || '';\n    options.createdByName = options.createdByName || '';\n    options.objType = 'XTextbase';\n\n\n    super(text, options);\n    this.initializeEvent();\n    delete options.height;\n    Object.assign(this, options);\n\n\n    // this.resetResizeControls();\n  }\n  updatedBy: string;\n  updatedByName: string;\n\n  createdByName: string;\n  maxHeight: number;\n  fixedScaleChange: boolean;\n  boardId: string;\n  objType: WidgetType;\n  userId: string;\n  zIndex: number;\n  version: string;\n  updatedAt: number;\n\n  createdAt: number;\n  createdBy: string;\n  /* boardx extend function */\n\n  updateConnector(point: any, connector: XConnector, type: string) {\n    const controlPoint = this.calculateControlPoint(\n      new Point(point.x, point.y)\n    );\n\n    //recalculate the startpoint or endpoint of the connector, and also the ControlPoint\n    if (type === 'from') {\n      connector.update({\n        fromPoint: point,\n        control1: controlPoint,\n      });\n    }\n    if (type === 'to') {\n      connector.update({\n        toPoint: point,\n        control2: controlPoint,\n      });\n    }\n  }\n\n  moveOrScaleHandler(e: any) {\n    //if there is a connector, move the connector\n    if (this.connectors?.length === 0) return;\n    this.connectors?.forEach((connector: any) => {\n      const pointConnector = connector.point;\n\n      //get canvas point of the connector point\n      const point = new Point(pointConnector.x, pointConnector.y);\n      //@ts-ignore\n      const transformedPoint = this.transformPointToCanvas(point);\n\n      //use the connectorId to find the connector and then update the connector\n      //@ts-ignore\n      const connectorObj = this.canvas?.findById(connector.connectorId);\n\n      if (!connectorObj) return;\n\n      if (\n        this.id === connectorObj.fromObjectId &&\n        connector.connectorType === 'from'\n      ) {\n        this.updateConnector(transformedPoint, connectorObj, 'from');\n      }\n\n      if (\n        this.id === connectorObj.toObjectId &&\n        connector.connectorType === 'to'\n      ) {\n        this.updateConnector(transformedPoint, connectorObj, 'to');\n      }\n    });\n  }\n\n  calculateControlPoint(connectingPoint: Point): Point {\n    const boundingBox = this.getBoundingRect();\n    let left = boundingBox.left;\n    let top = boundingBox.top;\n\n    const width = boundingBox.width;\n    const height = boundingBox.height;\n\n    const right = left + width;\n    const bottom = top + height;\n\n    const connectingX = connectingPoint.x;\n    const connectingY = connectingPoint.y;\n\n    let controlX: number = 0;\n    let controlY: number = 0;\n\n    // Find the nearest border and calculate the control point outside the bounding box\n    const distances = [\n      { side: 'left', distance: Math.abs(connectingX - left) },\n      { side: 'right', distance: Math.abs(connectingX - right) },\n      { side: 'top', distance: Math.abs(connectingY - top) },\n      { side: 'bottom', distance: Math.abs(connectingY - bottom) },\n    ];\n\n    const nearestBorder = distances.reduce((min, current) =>\n      current.distance < min.distance ? current : min\n    );\n\n    switch (nearestBorder.side) {\n      case 'left':\n        controlX = left - 220 * this.scaleX;\n        controlY = connectingY;\n        break;\n      case 'right':\n        controlX = right + 220 * this.scaleX;\n        controlY = connectingY;\n        break;\n      case 'top':\n        controlX = connectingX;\n        controlY = top - 220 * this.scaleY;\n        break;\n      case 'bottom':\n        controlX = connectingX;\n        controlY = bottom + 220 * this.scaleY;\n        break;\n    }\n\n    return new Point(controlX, controlY);\n  }\n\n\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: any = {};\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: any, 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: number = 0,\n      nextLineIndex = lineIndex + 1,\n      nextOffset: any,\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 as any) {\n      for (const p2 in obj[p1] as any) {\n        if (Number(p2) >= offset && (!shouldLimit || Number(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   * 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: any, 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  /**\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  _splitTextIntoLines(text: string) {\n    const newText = super._splitTextIntoLines(text);\n    // Check if text contains Chinese characters\n    if (/[\\u3400-\\u9FBF]/.test(this.text)) {\n      this.splitByGrapheme = true;\n    }\n\n    if (!this.fromCopy) {\n      if (\n        (this.objType === 'XText' || this.objType === 'XTextbase') &&\n        this.textLines &&\n        this.textLines.length > 1 &&\n        this.isEditing\n      ) {\n        this.oneLine = false;\n      } else {\n        this.oneLine = true;\n      }\n    } else {\n      this.oneLine = false;\n    }\n    if (\n      (this.objType === 'XText' || this.objType === 'XTextbase') &&\n      newText &&\n      newText.lines &&\n      this.oneLine &&\n      this.isEditing\n    ) {\n      if (newText.lines[0].length > 1) {\n        this.width =\n          this._measureWord(newText.lines[0], 0, 0) > this.width\n            ? this._measureWord(newText.lines[0], 0, 0) + 10\n            : this.width;\n      }\n    }\n    const graphemeLines = this._wrapText(newText.lines, this.width);\n    const 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  controlMousedownProcess(transformData: any, rx: any, ry: any) {\n    return;\n  }\n\n  getObject() {\n    const entityKeys: string[] = EntityKeys;\n    const result: Record<string, any> = {};\n\n    entityKeys.forEach((key) => {\n      if (key in this) {\n        result[key] = (this as any)[key];\n      }\n    });\n\n    return result;\n  }\n\n\n  // toObject(propertiesToInclude: Array<any>): object {\n  //   return super.toObject(\n  //     ['minWidth', 'splitByGrapheme'].concat(propertiesToInclude)\n  //   );\n  // }\n  /**extend function for fronted */\n  checkTextboxChange() { }\n  initializeEvent() {\n    const self = this;\n    const canvas = this.canvas;\n\n    self.on(EventName.EDITINGENTERED, () => {\n      // Set originX based on textAlign\n      // self.originX = self.textAlign as TOriginX;\n\n      // Adjust left position to maintain visual consistency\n      // if (self.textAlign === TextAlign.LEFT) {\n      //   self.left -= (self.width * self.scaleX) / 2;\n      // }\n\n      // if (self.textAlign === TextAlign.RIGHT) {\n      //   // Corrected adjustment: Subtract instead of Add\n      //   self.left -= (self.width * self.scaleX) / 2;\n      // }\n\n      if (self.objType === 'XTextbase') {\n        self.originY = 'top';\n\n        self.top -= (self.height * self.scaleY) / 2;\n\n        self.tempTop = self.top;\n\n        if (self.text === 'Type here...') {\n          self.selectAll();\n\n          self.text = '';\n\n          self.dirty = true;\n\n          self.fill = 'rgb(0, 0, 0)';\n\n          canvas?.requestRenderAll();\n        }\n      }\n    });\n\n    self.on(EventName.EDITINGEXITED, () => {\n      // Revert originX and originY to center\n      self.originX = Origin.Center;\n      self.originY = Origin.Center;\n\n      // // Reverse the left adjustment based on textAlign\n      // if (self.textAlign === TextAlign.LEFT) {\n      //   self.left += (self.width * self.scaleX) / 2;\n      // }\n\n      // if (self.textAlign === TextAlign.RIGHT) {\n      //   // Reverse the corrected adjustment: Add back\n      //   self.left += (self.width * self.scaleX) / 2;\n      // }\n\n      if (self.objType === 'XTextbase') {\n        self.top = self.tempTop + (self.height * self.scaleY) / 2;\n        self.tempTop = self.top;\n      }\n    });\n\n\n    this.on('moving', (e: any) => {\n      this.moveOrScaleHandler(e);\n    });\n\n    this.on('scaling', (e: any) => {\n      this.moveOrScaleHandler(e);\n    });\n    self.on(EventName.MODIFIED, () => {\n      self.checkTextboxChange();\n\n      // canvas.requestRenderAll();\n    });\n    self.on(EventName.CHANGED, () => {\n      if (self.styles[0]) {\n        self.styles = {};\n\n        // self.canvas.requestRenderAll();\n      }\n    });\n\n\n    // Other event listeners remain unchanged...\n  }\n\n\n\n\n\n  drawObject(ctx: CanvasRenderingContext2D) {\n    super.drawObject(ctx);\n    // console.log('!@@ drawObject', this.canvas?.dockingWidget, this);\n    //@ts-ignore\n    if (this == this.canvas?.dockingWidget) {\n      this.renderDockingControls(ctx);\n    }\n  }\n\n  renderDockingControls(ctx: CanvasRenderingContext2D) {\n    console.log('!!@renderDockingControls');\n    const self = this;\n    const canvas = self.canvas;\n    const controls = self.controls;\n\n    let cornerColor = 'white';\n\n    if (!canvas) return;\n\n    for (const controlKey in controls) {\n      const control = controls[controlKey];\n      if (\n        !(\n          controlKey === 'mbaStart' ||\n          controlKey === 'mlaStart' ||\n          controlKey === 'mraStart' ||\n          controlKey === 'mtaStart'\n        )\n      )\n        continue;\n\n      if (\n        //@ts-ignore\n        this.canvas!.hoveringControl &&\n        //@ts-ignore\n        this.canvas!.hoveringControl === controlKey\n      ) {\n        cornerColor = '#F21D6B';\n      } else {\n        cornerColor = 'white';\n      }\n\n      //render 4 controls, mbaStart, mlaStart, mraStart, mtaStart\n\n      this._renderControl(\n        ctx,\n        control.x * self.width,\n        control.y * self.height,\n        { cornerStyle: 'circle', cornerColor },\n        self\n      );\n    }\n  }\n\n  _renderControl(\n    ctx: any,\n    left: number,\n    top: number,\n    styleOverride: any,\n    fabricObject: FabricObject\n  ) {\n    console.log('!!@  _renderControl', left, top);\n    let color = styleOverride.cornerColor || 'white';\n\n    ctx.save();\n    ctx.fillStyle = color;\n    ctx.strokeStyle = 'gray';\n    ctx.beginPath();\n    ctx.arc(left, top, 6, 0, Math.PI * 2, false);\n    ctx.closePath();\n    ctx.fill();\n    ctx.stroke();\n    ctx.restore();\n  }\n\n\n\n  resetResizeControls() {\n    const self = this;\n    const textAlign = self.textAlign;\n\n    if (\n      self.objType === 'XTextbase' &&\n      (textAlign === 'left' || textAlign === 'center')\n    ) {\n      self.setControlVisible('ml', false);\n      self.setControlVisible('mr', true);\n    }\n\n    if (self.objType === 'XText' && textAlign === 'right') {\n      self.setControlVisible('ml', true);\n      self.setControlVisible('mr', false);\n    }\n    if (self.canvas) self.canvas.requestRenderAll();\n  }\n}\n\nclassRegistry.setClass(XTextbase);\n// classRegistry.getSVGClass(Textbox);\n"],"names":["textboxDefaultValues","minWidth","dynamicMinWidth","splitByGrapheme","cornerColor","cornerSize","cornerStyle","transparentCorners","cornerStrokeColor","connectors","XTextbase","Textbox","getDefaults","_objectSpread","super","controls","createTextboxDefaultControls","ownDefaults","constructor","text","options","oneLine","originX","originY","fixedScaleChange","boardId","userId","zIndex","version","updatedAt","Date","now","lastEditedByName","createdByName","objType","_defineProperty","this","initializeEvent","height","Object","assign","updateConnector","point","connector","type","controlPoint","calculateControlPoint","Point","x","y","update","fromPoint","control1","toPoint","control2","moveOrScaleHandler","e","_this$connectors","_this$connectors2","length","forEach","_this$canvas","pointConnector","transformedPoint","transformPointToCanvas","connectorObj","canvas","findById","connectorId","id","fromObjectId","connectorType","toObjectId","connectingPoint","boundingBox","getBoundingRect","left","top","right","width","bottom","connectingX","connectingY","controlX","controlY","side","distance","Math","abs","reduce","min","current","scaleX","scaleY","_generateStyleMap","textInfo","realLineCount","realLineCharCount","charCount","map","i","graphemeLines","graphemeText","_reSpaceAndTab","test","line","offset","styleHas","property","lineIndex","_styleMap","isWrapping","isEmptyStyles","styles","nextOffset","nextLineIndex","shouldLimit","mapNextLine","obj","p1","p2","Number","p3","_measureWord","word","prevGrapheme","charOffset","arguments","undefined","len","_getGraphemeBox","kernedWidth","wordSplit","value","split","_wordJoiners","isEndOfWrapping","missingNewlineOffset","_splitTextIntoLines","newText","fromCopy","textLines","isEditing","lines","_wrapText","Array","join","getMinWidth","max","controlMousedownProcess","transformData","rx","ry","getObject","result","EntityKeys","key","checkTextboxChange","self","on","EventName","EDITINGENTERED","tempTop","selectAll","dirty","fill","requestRenderAll","EDITINGEXITED","Origin","Center","MODIFIED","CHANGED","drawObject","ctx","_this$canvas2","dockingWidget","renderDockingControls","console","log","controlKey","control","hoveringControl","_renderControl","styleOverride","fabricObject","color","save","fillStyle","strokeStyle","beginPath","arc","PI","closePath","stroke","restore","resetResizeControls","textAlign","setControlVisible","IText","textLayoutProperties","classRegistry","setClass"],"mappings":"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"}