{"version":3,"file":"StackedObject.mjs","sources":["../../../../src/shapes/Object/StackedObject.ts"],"sourcesContent":["import type { ObjectEvents } from '../../EventTypeDefs';\nimport type { Group } from '../Group';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { StaticCanvas } from '../../canvas/StaticCanvas';\nimport { ObjectGeometry } from './ObjectGeometry';\nimport type { FabricObject } from './FabricObject';\n\ntype TAncestor = StackedObject | Canvas | StaticCanvas;\ntype TCollection = Group | Canvas | StaticCanvas;\n\nexport type Ancestors =\n  | [StackedObject | Group]\n  | [StackedObject | Group, ...Group[]]\n  | Group[];\n\nexport type AncestryComparison = {\n  /**\n   * common ancestors of `this` and`other`(may include`this` | `other`)\n   */\n  common: Ancestors;\n  /**\n   * ancestors that are of `this` only\n   */\n  fork: Ancestors;\n  /**\n   * ancestors that are of `other` only\n   */\n  otherFork: Ancestors;\n};\n\nexport class StackedObject<\n  EventSpec extends ObjectEvents = ObjectEvents\n> extends ObjectGeometry<EventSpec> {\n  /**\n   * A reference to the parent of the object\n   * Used to keep the original parent ref when the object has been added to an ActiveSelection, hence loosing the `group` ref\n   */\n  declare parent?: Group;\n\n  /**\n   * Checks if object is descendant of target\n   * Should be used instead of {@link Group.contains} or {@link StaticCanvas.contains} for performance reasons\n   * @param {TAncestor} target\n   * @returns {boolean}\n   */\n  isDescendantOf(target: TAncestor): boolean {\n    const { parent, group } = this;\n    return (\n      parent === target ||\n      group === target ||\n      this.canvas === target ||\n      // walk up\n      (!!parent && parent.isDescendantOf(target)) ||\n      (!!group && group !== parent && group.isDescendantOf(target))\n    );\n  }\n\n  /**\n   * @returns {Ancestors} ancestors (excluding `ActiveSelection`) from bottom to top\n   */\n  getAncestors(): Ancestors {\n    const ancestors: TAncestor[] = [];\n    // eslint-disable-next-line @typescript-eslint/no-this-alias\n    let parent: TAncestor | undefined = this;\n    do {\n      parent = parent instanceof StackedObject ? parent.parent : undefined;\n      parent && ancestors.push(parent);\n    } while (parent);\n    return ancestors as Ancestors;\n  }\n\n  /**\n   * Compare ancestors\n   *\n   * @param {StackedObject} other\n   * @returns {AncestryComparison} an object that represent the ancestry situation.\n   */\n  findCommonAncestors<T extends this>(other: T): AncestryComparison {\n    if (this === other) {\n      return {\n        fork: [],\n        otherFork: [],\n        common: [this, ...this.getAncestors()],\n      } as AncestryComparison;\n    }\n    const ancestors = this.getAncestors();\n    const otherAncestors = other.getAncestors();\n    //  if `this` has no ancestors and `this` is top ancestor of `other` we must handle the following case\n    if (\n      ancestors.length === 0 &&\n      otherAncestors.length > 0 &&\n      this === otherAncestors[otherAncestors.length - 1]\n    ) {\n      return {\n        fork: [],\n        otherFork: [\n          other,\n          ...otherAncestors.slice(0, otherAncestors.length - 1),\n        ],\n        common: [this],\n      } as AncestryComparison;\n    }\n    //  compare ancestors\n    for (let i = 0, ancestor; i < ancestors.length; i++) {\n      ancestor = ancestors[i];\n      if (ancestor === other) {\n        return {\n          fork: [this, ...ancestors.slice(0, i)],\n          otherFork: [],\n          common: ancestors.slice(i),\n        } as AncestryComparison;\n      }\n      for (let j = 0; j < otherAncestors.length; j++) {\n        if (this === otherAncestors[j]) {\n          return {\n            fork: [],\n            otherFork: [other, ...otherAncestors.slice(0, j)],\n            common: [this, ...ancestors],\n          } as AncestryComparison;\n        }\n        if (ancestor === otherAncestors[j]) {\n          return {\n            fork: [this, ...ancestors.slice(0, i)],\n            otherFork: [other, ...otherAncestors.slice(0, j)],\n            common: ancestors.slice(i),\n          } as AncestryComparison;\n        }\n      }\n    }\n    // nothing shared\n    return {\n      fork: [this, ...ancestors],\n      otherFork: [other, ...otherAncestors],\n      common: [],\n    } as AncestryComparison;\n  }\n\n  /**\n   *\n   * @param {StackedObject} other\n   * @returns {boolean}\n   */\n  hasCommonAncestors<T extends this>(other: T): boolean {\n    const commonAncestors = this.findCommonAncestors(other);\n    return commonAncestors && !!commonAncestors.common.length;\n  }\n\n  /**\n   *\n   * @param {FabricObject} other object to compare against\n   * @returns {boolean | undefined} if objects do not share a common ancestor or they are strictly equal it is impossible to determine which is in front of the other; in such cases the function returns `undefined`\n   */\n  isInFrontOf<T extends this>(other: T): boolean | undefined {\n    if (this === other) {\n      return undefined;\n    }\n    const ancestorData = this.findCommonAncestors(other);\n\n    if (ancestorData.fork.includes(other as any)) {\n      return true;\n    }\n    if (ancestorData.otherFork.includes(this as any)) {\n      return false;\n    }\n    // if there isn't a common ancestor, we take the canvas.\n    // if there is no canvas, there is nothing to compare\n    const firstCommonAncestor = ancestorData.common[0] || this.canvas;\n    if (!firstCommonAncestor) {\n      return undefined;\n    }\n    const headOfFork = ancestorData.fork.pop(),\n      headOfOtherFork = ancestorData.otherFork.pop(),\n      thisIndex = (firstCommonAncestor as TCollection)._objects.indexOf(\n        headOfFork as any\n      ),\n      otherIndex = (firstCommonAncestor as TCollection)._objects.indexOf(\n        headOfOtherFork as any\n      );\n    return thisIndex > -1 && thisIndex > otherIndex;\n  }\n}\n"],"names":["StackedObject","ObjectGeometry","isDescendantOf","target","parent","group","canvas","getAncestors","ancestors","undefined","push","findCommonAncestors","other","fork","otherFork","common","otherAncestors","length","slice","i","ancestor","j","hasCommonAncestors","commonAncestors","isInFrontOf","ancestorData","includes","firstCommonAncestor","headOfFork","pop","headOfOtherFork","thisIndex","_objects","indexOf","otherIndex"],"mappings":"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"}