import { KeyframeResolver as M } from "../animation/keyframes/KeyframesResolver.es.js";
import { NativeAnimation as S } from "../animation/NativeAnimation.es.js";
import { acceleratedValues as b } from "../animation/waapi/utils/accelerated-values.es.js";
import { microtask as T } from "../frameloop/microtask.es.js";
import { time as w } from "../frameloop/sync-time.es.js";
import { createBox as P } from "../projection/geometry/models.es.js";
import { motionValue as F } from "../value/index.es.js";
import { complex as A } from "../value/types/complex/index.es.js";
import { getAnimatableNone as B } from "../value/types/utils/animatable-none.es.js";
import { findValueType as R } from "../value/types/utils/find.es.js";
import { isMotionValue as u } from "../value/utils/is-motion-value.es.js";
import { visualElementStore as N } from "./store.es.js";
import { isControllingVariants as E, isVariantNode as x } from "./utils/is-controlling-variants.es.js";
import { transformProps as j } from "./utils/keys-transform.es.js";
import { updateMotionValuesFromProps as y } from "./utils/motion-values.es.js";
import { initPrefersReducedMotion as I } from "./utils/reduced-motion/index.es.js";
import { resolveVariantFromProps as D } from "./utils/resolve-variants.es.js";
import { hasReducedMotionListener as L, prefersReducedMotion as U } from "./utils/reduced-motion/state.es.js";
import { frame as v, cancelFrame as g } from "../frameloop/frame.es.js";
import { warnOnce as O } from "../../../../../../motion-utils@12.36.0/node_modules/motion-utils/dist/es/warn-once.es.js";
import { secondsToMilliseconds as _ } from "../../../../../../motion-utils@12.36.0/node_modules/motion-utils/dist/es/time-conversion.es.js";
import { isNumericalString as H } from "../../../../../../motion-utils@12.36.0/node_modules/motion-utils/dist/es/is-numerical-string.es.js";
import { isZeroValueString as K } from "../../../../../../motion-utils@12.36.0/node_modules/motion-utils/dist/es/is-zero-value-string.es.js";
import { SubscriptionManager as Y } from "../../../../../../motion-utils@12.36.0/node_modules/motion-utils/dist/es/subscription-manager.es.js";
const C = [
  "AnimationStart",
  "AnimationComplete",
  "Update",
  "BeforeLayoutMeasure",
  "LayoutMeasure",
  "LayoutAnimationStart",
  "LayoutAnimationComplete"
];
let l = {};
function ft(m) {
  l = m;
}
function mt() {
  return l;
}
class Vt {
  /**
   * 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, skipAnimations: n, blockInitialAnimation: r, visualState: d }, p = {}) {
    this.current = null, this.children = /* @__PURE__ */ new Set(), this.isVariantNode = !1, this.isControllingVariants = !1, this.shouldReduceMotion = null, this.shouldSkipAnimations = !1, this.values = /* @__PURE__ */ new Map(), this.KeyframeResolver = M, this.features = {}, this.valueSubscriptions = /* @__PURE__ */ new Map(), this.prevMotionValues = {}, this.hasBeenMounted = !1, 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 a = w.now();
      this.renderScheduledAt < a && (this.renderScheduledAt = a, v.render(this.render, !1, !0));
    };
    const { latestValues: o, renderState: c } = d;
    this.latestValues = o, this.baseTarget = { ...o }, this.initialValues = e.initial ? { ...o } : {}, this.renderState = c, this.parent = t, this.props = e, this.presenceContext = i, this.depth = t ? t.depth + 1 : 0, this.reducedMotionConfig = s, this.skipAnimationsConfig = n, this.options = p, this.blockInitialAnimation = !!r, this.isControllingVariants = E(e), this.isVariantNode = x(e), this.isVariantNode && (this.variantChildren = /* @__PURE__ */ new Set()), this.manuallyAnimateOnMount = !!(t && t.current);
    const { willChange: f, ...h } = this.scrapeMotionValuesFromProps(e, {}, this);
    for (const a in h) {
      const V = h[a];
      o[a] !== void 0 && u(V) && V.set(o[a]);
    }
  }
  mount(t) {
    var e, i;
    if (this.hasBeenMounted)
      for (const s in this.initialValues)
        (e = this.values.get(s)) == null || e.jump(this.initialValues[s]), this.latestValues[s] = this.initialValues[s];
    this.current = t, N.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((s, n) => this.bindToMotionValue(n, s)), this.reducedMotionConfig === "never" ? this.shouldReduceMotion = !1 : this.reducedMotionConfig === "always" ? this.shouldReduceMotion = !0 : (L.current || I(), this.shouldReduceMotion = U.current), process.env.NODE_ENV !== "production" && O(this.shouldReduceMotion !== !0, "You have Reduced Motion enabled on your device. Animations may not appear as expected.", "reduced-motion-disabled"), this.shouldSkipAnimations = this.skipAnimationsConfig ?? !1, (i = this.parent) == null || i.addChild(this), this.update(this.props, this.presenceContext), this.hasBeenMounted = !0;
  }
  unmount() {
    var t;
    this.projection && this.projection.unmount(), g(this.notifyUpdate), g(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) {
    if (this.valueSubscriptions.has(t) && this.valueSubscriptions.get(t)(), e.accelerate && b.has(t) && this.current instanceof HTMLElement) {
      const { factory: r, keyframes: d, times: p, ease: o, duration: c } = e.accelerate, f = new S({
        element: this.current,
        name: t,
        keyframes: d,
        times: p,
        ease: o,
        duration: _(c)
      }), h = r(f);
      this.valueSubscriptions.set(t, () => {
        h(), f.cancel();
      });
      return;
    }
    const i = j.has(t);
    i && this.onBindTransform && this.onBindTransform();
    const s = e.on("change", (r) => {
      this.latestValues[t] = r, this.props.onUpdate && v.preRender(this.notifyUpdate), i && this.projection && (this.projection.isTransformDirty = !0), this.scheduleRender();
    });
    let n;
    typeof window < "u" && window.MotionCheckAppearSync && (n = window.MotionCheckAppearSync(this, t, e)), this.valueSubscriptions.set(t, () => {
      s(), n && n(), 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 l) {
      const e = l[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 n = this.features[t];
        n.isMounted ? n.update() : (n.mount(), n.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) : P();
  }
  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 < C.length; i++) {
      const s = C[i];
      this.propEventSubscriptions[s] && (this.propEventSubscriptions[s](), delete this.propEventSubscriptions[s]);
      const n = "on" + s, r = t[n];
      r && (this.propEventSubscriptions[s] = this.on(s, r));
    }
    this.prevMotionValues = y(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 = F(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" && (H(i) || K(i)) ? i = parseFloat(i) : !R(i) && A.test(e) && (i = B(t, e)), this.setBaseTarget(t, u(i) ? i.get() : i)), u(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 n;
    const { initial: e } = this.props;
    let i;
    if (typeof e == "string" || typeof e == "object") {
      const r = D(this.props, e, (n = this.presenceContext) == null ? void 0 : n.custom);
      r && (i = r[t]);
    }
    if (e && i !== void 0)
      return i;
    const s = this.getBaseTargetFromProps(this.props, t);
    return s !== void 0 && !u(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 Y()), this.events[t].add(e);
  }
  notify(t, ...e) {
    this.events[t] && this.events[t].notify(...e);
  }
  scheduleRenderMicrotask() {
    T.render(this.render);
  }
}
export {
  Vt as VisualElement,
  mt as getFeatureDefinitions,
  ft as setFeatureDefinitions
};
//# sourceMappingURL=VisualElement.es.js.map
