import { featureDefinitions as d } from "../motion/features/definitions.es.js";
import { createBox as v } from "../projection/geometry/models.es.js";
import { initPrefersReducedMotion as g } from "../utils/reduced-motion/index.es.js";
import { hasReducedMotionListener as C, prefersReducedMotion as M } from "../utils/reduced-motion/state.es.js";
import { visualElementStore as S } from "./store.es.js";
import { isControllingVariants as b, isVariantNode as T } from "./utils/is-controlling-variants.es.js";
import { updateMotionValuesFromProps as P } from "./utils/motion-values.es.js";
import { resolveVariantFromProps as w } from "./utils/resolve-variants.es.js";
import { KeyframeResolver as F } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/animation/keyframes/KeyframesResolver.es.js";
import { time as B } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/frameloop/sync-time.es.js";
import { frame as p, cancelFrame as c } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/frameloop/frame.es.js";
import { isMotionValue as h } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/value/utils/is-motion-value.es.js";
import { warnOnce as N } from "../../../../../../motion-utils@12.23.6/node_modules/motion-utils/dist/es/warn-once.es.js";
import { transformProps as R } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/render/utils/keys-transform.es.js";
import { motionValue as E } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/value/index.es.js";
import { isNumericalString as x } from "../../../../../../motion-utils@12.23.6/node_modules/motion-utils/dist/es/is-numerical-string.es.js";
import { isZeroValueString as A } from "../../../../../../motion-utils@12.23.6/node_modules/motion-utils/dist/es/is-zero-value-string.es.js";
import { findValueType as j } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/value/types/utils/find.es.js";
import { complex as y } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/value/types/complex/index.es.js";
import { getAnimatableNone as I } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/value/types/utils/animatable-none.es.js";
import { SubscriptionManager as U } from "../../../../../../motion-utils@12.23.6/node_modules/motion-utils/dist/es/subscription-manager.es.js";
import { microtask as D } from "../../../../../../motion-dom@12.23.23/node_modules/motion-dom/dist/es/frameloop/microtask.es.js";
const f = [
  "AnimationStart",
  "AnimationComplete",
  "Update",
  "BeforeLayoutMeasure",
  "LayoutMeasure",
  "LayoutAnimationStart",
  "LayoutAnimationComplete"
];
class ht {
  /**
   * This method takes React props and returns found MotionValues. For example, HTML
   * MotionValues will be found within the style prop, whereas for Three.js within attribute arrays.
   *
   * This isn't an abstract method as it needs calling in the constructor, but it is
   * intended to be one.
   */
  scrapeMotionValuesFromProps(t, e, i) {
    return {};
  }
  constructor({ parent: t, props: e, presenceContext: i, reducedMotionConfig: s, blockInitialAnimation: r, visualState: n }, m = {}) {
    this.current = null, this.children = /* @__PURE__ */ new Set(), this.isVariantNode = !1, this.isControllingVariants = !1, this.shouldReduceMotion = null, this.values = /* @__PURE__ */ new Map(), this.KeyframeResolver = F, this.features = {}, this.valueSubscriptions = /* @__PURE__ */ new Map(), this.prevMotionValues = {}, this.events = {}, this.propEventSubscriptions = {}, this.notifyUpdate = () => this.notify("Update", this.latestValues), this.render = () => {
      this.current && (this.triggerBuild(), this.renderInstance(this.current, this.renderState, this.props.style, this.projection));
    }, this.renderScheduledAt = 0, this.scheduleRender = () => {
      const o = B.now();
      this.renderScheduledAt < o && (this.renderScheduledAt = o, p.render(this.render, !1, !0));
    };
    const { latestValues: a, renderState: V } = n;
    this.latestValues = a, this.baseTarget = { ...a }, this.initialValues = e.initial ? { ...a } : {}, this.renderState = V, this.parent = t, this.props = e, this.presenceContext = i, this.depth = t ? t.depth + 1 : 0, this.reducedMotionConfig = s, this.options = m, this.blockInitialAnimation = !!r, this.isControllingVariants = b(e), this.isVariantNode = T(e), this.isVariantNode && (this.variantChildren = /* @__PURE__ */ new Set()), this.manuallyAnimateOnMount = !!(t && t.current);
    const { willChange: O, ...u } = this.scrapeMotionValuesFromProps(e, {}, this);
    for (const o in u) {
      const l = u[o];
      a[o] !== void 0 && h(l) && l.set(a[o]);
    }
  }
  mount(t) {
    var e;
    this.current = t, S.set(t, this), this.projection && !this.projection.instance && this.projection.mount(t), this.parent && this.isVariantNode && !this.isControllingVariants && (this.removeFromVariantTree = this.parent.addVariantChild(this)), this.values.forEach((i, s) => this.bindToMotionValue(s, i)), C.current || g(), this.shouldReduceMotion = this.reducedMotionConfig === "never" ? !1 : this.reducedMotionConfig === "always" ? !0 : M.current, process.env.NODE_ENV !== "production" && N(this.shouldReduceMotion !== !0, "You have Reduced Motion enabled on your device. Animations may not appear as expected.", "reduced-motion-disabled"), (e = this.parent) == null || e.addChild(this), this.update(this.props, this.presenceContext);
  }
  unmount() {
    var t;
    this.projection && this.projection.unmount(), c(this.notifyUpdate), c(this.render), this.valueSubscriptions.forEach((e) => e()), this.valueSubscriptions.clear(), this.removeFromVariantTree && this.removeFromVariantTree(), (t = this.parent) == null || t.removeChild(this);
    for (const e in this.events)
      this.events[e].clear();
    for (const e in this.features) {
      const i = this.features[e];
      i && (i.unmount(), i.isMounted = !1);
    }
    this.current = null;
  }
  addChild(t) {
    this.children.add(t), this.enteringChildren ?? (this.enteringChildren = /* @__PURE__ */ new Set()), this.enteringChildren.add(t);
  }
  removeChild(t) {
    this.children.delete(t), this.enteringChildren && this.enteringChildren.delete(t);
  }
  bindToMotionValue(t, e) {
    this.valueSubscriptions.has(t) && this.valueSubscriptions.get(t)();
    const i = R.has(t);
    i && this.onBindTransform && this.onBindTransform();
    const s = e.on("change", (n) => {
      this.latestValues[t] = n, this.props.onUpdate && p.preRender(this.notifyUpdate), i && this.projection && (this.projection.isTransformDirty = !0), this.scheduleRender();
    });
    let r;
    window.MotionCheckAppearSync && (r = window.MotionCheckAppearSync(this, t, e)), this.valueSubscriptions.set(t, () => {
      s(), r && r(), e.owner && e.stop();
    });
  }
  sortNodePosition(t) {
    return !this.current || !this.sortInstanceNodePosition || this.type !== t.type ? 0 : this.sortInstanceNodePosition(this.current, t.current);
  }
  updateFeatures() {
    let t = "animation";
    for (t in d) {
      const e = d[t];
      if (!e)
        continue;
      const { isEnabled: i, Feature: s } = e;
      if (!this.features[t] && s && i(this.props) && (this.features[t] = new s(this)), this.features[t]) {
        const r = this.features[t];
        r.isMounted ? r.update() : (r.mount(), r.isMounted = !0);
      }
    }
  }
  triggerBuild() {
    this.build(this.renderState, this.latestValues, this.props);
  }
  /**
   * Measure the current viewport box with or without transforms.
   * Only measures axis-aligned boxes, rotate and skew must be manually
   * removed with a re-render to work.
   */
  measureViewportBox() {
    return this.current ? this.measureInstanceViewportBox(this.current, this.props) : v();
  }
  getStaticValue(t) {
    return this.latestValues[t];
  }
  setStaticValue(t, e) {
    this.latestValues[t] = e;
  }
  /**
   * Update the provided props. Ensure any newly-added motion values are
   * added to our map, old ones removed, and listeners updated.
   */
  update(t, e) {
    (t.transformTemplate || this.props.transformTemplate) && this.scheduleRender(), this.prevProps = this.props, this.props = t, this.prevPresenceContext = this.presenceContext, this.presenceContext = e;
    for (let i = 0; i < f.length; i++) {
      const s = f[i];
      this.propEventSubscriptions[s] && (this.propEventSubscriptions[s](), delete this.propEventSubscriptions[s]);
      const r = "on" + s, n = t[r];
      n && (this.propEventSubscriptions[s] = this.on(s, n));
    }
    this.prevMotionValues = P(this, this.scrapeMotionValuesFromProps(t, this.prevProps, this), this.prevMotionValues), this.handleChildMotionValue && this.handleChildMotionValue();
  }
  getProps() {
    return this.props;
  }
  /**
   * Returns the variant definition with a given name.
   */
  getVariant(t) {
    return this.props.variants ? this.props.variants[t] : void 0;
  }
  /**
   * Returns the defined default transition on this component.
   */
  getDefaultTransition() {
    return this.props.transition;
  }
  getTransformPagePoint() {
    return this.props.transformPagePoint;
  }
  getClosestVariantNode() {
    return this.isVariantNode ? this : this.parent ? this.parent.getClosestVariantNode() : void 0;
  }
  /**
   * Add a child visual element to our set of children.
   */
  addVariantChild(t) {
    const e = this.getClosestVariantNode();
    if (e)
      return e.variantChildren && e.variantChildren.add(t), () => e.variantChildren.delete(t);
  }
  /**
   * Add a motion value and bind it to this visual element.
   */
  addValue(t, e) {
    const i = this.values.get(t);
    e !== i && (i && this.removeValue(t), this.bindToMotionValue(t, e), this.values.set(t, e), this.latestValues[t] = e.get());
  }
  /**
   * Remove a motion value and unbind any active subscriptions.
   */
  removeValue(t) {
    this.values.delete(t);
    const e = this.valueSubscriptions.get(t);
    e && (e(), this.valueSubscriptions.delete(t)), delete this.latestValues[t], this.removeValueFromRenderState(t, this.renderState);
  }
  /**
   * Check whether we have a motion value for this key
   */
  hasValue(t) {
    return this.values.has(t);
  }
  getValue(t, e) {
    if (this.props.values && this.props.values[t])
      return this.props.values[t];
    let i = this.values.get(t);
    return i === void 0 && e !== void 0 && (i = E(e === null ? void 0 : e, { owner: this }), this.addValue(t, i)), i;
  }
  /**
   * If we're trying to animate to a previously unencountered value,
   * we need to check for it in our state and as a last resort read it
   * directly from the instance (which might have performance implications).
   */
  readValue(t, e) {
    let i = this.latestValues[t] !== void 0 || !this.current ? this.latestValues[t] : this.getBaseTargetFromProps(this.props, t) ?? this.readValueFromInstance(this.current, t, this.options);
    return i != null && (typeof i == "string" && (x(i) || A(i)) ? i = parseFloat(i) : !j(i) && y.test(e) && (i = I(t, e)), this.setBaseTarget(t, h(i) ? i.get() : i)), h(i) ? i.get() : i;
  }
  /**
   * Set the base target to later animate back to. This is currently
   * only hydrated on creation and when we first read a value.
   */
  setBaseTarget(t, e) {
    this.baseTarget[t] = e;
  }
  /**
   * Find the base target for a value thats been removed from all animation
   * props.
   */
  getBaseTarget(t) {
    var r;
    const { initial: e } = this.props;
    let i;
    if (typeof e == "string" || typeof e == "object") {
      const n = w(this.props, e, (r = this.presenceContext) == null ? void 0 : r.custom);
      n && (i = n[t]);
    }
    if (e && i !== void 0)
      return i;
    const s = this.getBaseTargetFromProps(this.props, t);
    return s !== void 0 && !h(s) ? s : this.initialValues[t] !== void 0 && i === void 0 ? void 0 : this.baseTarget[t];
  }
  on(t, e) {
    return this.events[t] || (this.events[t] = new U()), this.events[t].add(e);
  }
  notify(t, ...e) {
    this.events[t] && this.events[t].notify(...e);
  }
  scheduleRenderMicrotask() {
    D.render(this.render);
  }
}
export {
  ht as VisualElement
};
//# sourceMappingURL=VisualElement.es.js.map
