import { defineComponent, ref, computed, onMounted, nextTick, watch, onActivated, onDeactivated, withDirectives, createVNode, mergeProps, vShow, Teleport } from "vue";
import { useEventListener, useRect } from "../../../../node_modules/@vant/use/dist/index.esm.mjs";
import { useTouch } from "../../../../node_modules/vant/es/composables/use-touch.mjs";
import stdin_default$1 from "../../../../node_modules/vant/es/icon/index.mjs";
import { createNamespace } from "../../../../node_modules/vant/es/utils/create.mjs";
import { makeStringProp, makeNumberProp } from "../../../../node_modules/vant/es/utils/props.mjs";
import { windowHeight, windowWidth } from "../../../../node_modules/vant/es/utils/dom.mjs";
import { addUnit } from "../../../../node_modules/vant/es/utils/format.mjs";
import { pick } from "../../../../node_modules/vant/es/utils/basic.mjs";
import { closest } from "../../../../node_modules/vant/es/utils/closest.mjs";
const floatingBubbleProps = {
  gapX: makeNumberProp(24),
  gapY: makeNumberProp(24),
  icon: String,
  axis: makeStringProp("y"),
  magnetic: String,
  offset: {
    type: Object,
    default: () => ({
      x: -1,
      y: -1
    })
  },
  teleport: {
    type: [String, Object],
    default: "body"
  }
};
const [name, bem] = createNamespace("floating-bubble");
var stdin_default = defineComponent({
  name,
  inheritAttrs: false,
  props: floatingBubbleProps,
  emits: ["click", "update:offset", "offsetChange"],
  setup(props, { slots, emit, attrs }) {
    const rootRef = ref();
    const state = ref({
      x: 0,
      y: 0,
      width: 0,
      height: 0
    });
    const boundary = computed(() => ({
      top: props.gapY,
      right: windowWidth.value - state.value.width - props.gapX,
      bottom: windowHeight.value - state.value.height - props.gapY,
      left: props.gapX
    }));
    const dragging = ref(false);
    let initialized = false;
    const rootStyle = computed(() => {
      const style = {};
      const x = addUnit(state.value.x);
      const y = addUnit(state.value.y);
      style.transform = `translate3d(${x}, ${y}, 0)`;
      if (dragging.value || !initialized) {
        style.transition = "none";
      }
      return style;
    });
    const updateState = () => {
      if (!show.value) return;
      const { width, height } = useRect(rootRef.value);
      const { offset } = props;
      state.value = {
        x: offset.x > -1 ? offset.x : windowWidth.value - width - props.gapX,
        y: offset.y > -1 ? offset.y : windowHeight.value - height - props.gapY,
        width,
        height
      };
    };
    const touch = useTouch();
    let prevX = 0;
    let prevY = 0;
    const onTouchStart = (e) => {
      touch.start(e);
      dragging.value = true;
      prevX = state.value.x;
      prevY = state.value.y;
    };
    const onTouchMove = (e) => {
      e.preventDefault();
      touch.move(e);
      if (props.axis === "lock") return;
      if (!touch.isTap.value) {
        if (props.axis === "x" || props.axis === "xy") {
          let nextX = prevX + touch.deltaX.value;
          if (nextX < boundary.value.left) nextX = boundary.value.left;
          if (nextX > boundary.value.right) nextX = boundary.value.right;
          state.value.x = nextX;
        }
        if (props.axis === "y" || props.axis === "xy") {
          let nextY = prevY + touch.deltaY.value;
          if (nextY < boundary.value.top) nextY = boundary.value.top;
          if (nextY > boundary.value.bottom) nextY = boundary.value.bottom;
          state.value.y = nextY;
        }
        const offset = pick(state.value, ["x", "y"]);
        emit("update:offset", offset);
      }
    };
    useEventListener("touchmove", onTouchMove, {
      target: rootRef
    });
    const onTouchEnd = () => {
      dragging.value = false;
      nextTick(() => {
        if (props.magnetic === "x") {
          const nextX = closest(
            [boundary.value.left, boundary.value.right],
            state.value.x
          );
          state.value.x = nextX;
        }
        if (props.magnetic === "y") {
          const nextY = closest(
            [boundary.value.top, boundary.value.bottom],
            state.value.y
          );
          state.value.y = nextY;
        }
        if (!touch.isTap.value) {
          const offset = pick(state.value, ["x", "y"]);
          emit("update:offset", offset);
          if (prevX !== offset.x || prevY !== offset.y) {
            emit("offsetChange", offset);
          }
        }
      });
    };
    const onClick = (e) => {
      if (touch.isTap.value) emit("click", e);
      else e.stopPropagation();
    };
    onMounted(() => {
      updateState();
      nextTick(() => {
        initialized = true;
      });
    });
    watch(
      [
        windowWidth,
        windowHeight,
        () => props.gapX,
        () => props.gapY,
        () => props.offset
      ],
      updateState,
      {
        deep: true
      }
    );
    const show = ref(true);
    onActivated(() => {
      show.value = true;
    });
    onDeactivated(() => {
      if (props.teleport) {
        show.value = false;
      }
    });
    return () => {
      const Content = withDirectives(
        createVNode(
          "div",
          mergeProps(
            {
              class: bem(),
              ref: rootRef,
              onTouchstartPassive: onTouchStart,
              onTouchend: onTouchEnd,
              onTouchcancel: onTouchEnd,
              onClickCapture: onClick,
              style: rootStyle.value
            },
            attrs
          ),
          [
            slots.default ? slots.default() : createVNode(
              stdin_default$1,
              {
                name: props.icon,
                class: bem("icon")
              },
              null
            )
          ]
        ),
        [[vShow, show.value]]
      );
      return props.teleport ? createVNode(
        Teleport,
        {
          to: props.teleport
        },
        {
          default: () => [Content]
        }
      ) : Content;
    };
  }
});
export {
  stdin_default as default,
  floatingBubbleProps
};
