import { defineComponent, ref, computed, watch, createVNode } from "vue";
import { useEventListener } from "../../../@vant/use/dist/index.esm.mjs";
import { useLockScroll } from "../composables/use-lock-scroll.mjs";
import { useTouch } from "../composables/use-touch.mjs";
import { useSyncPropRef } from "../composables/use-sync-prop-ref.mjs";
import { truthProp, makeNumericProp, makeArrayProp } from "../utils/props.mjs";
import { createNamespace } from "../utils/create.mjs";
import { windowHeight, preventDefault } from "../utils/dom.mjs";
import { addUnit } from "../utils/format.mjs";
import { closest } from "../utils/closest.mjs";
const floatingPanelProps = {
  height: makeNumericProp(0),
  anchors: makeArrayProp(),
  duration: makeNumericProp(0.3),
  magnetic: truthProp,
  draggable: truthProp,
  contentDraggable: truthProp,
  lockScroll: Boolean,
  safeAreaInsetBottom: truthProp
};
const [name, bem] = createNamespace("floating-panel");
var stdin_default = defineComponent({
  name,
  props: floatingPanelProps,
  emits: ["heightChange", "update:height"],
  setup(props, {
    emit,
    slots
  }) {
    const DAMP = 0.2;
    const rootRef = ref();
    const contentRef = ref();
    const height = useSyncPropRef(() => +props.height, (value) => emit("update:height", value));
    const boundary = computed(() => {
      var _a, _b;
      return {
        min: (_a = props.anchors[0]) != null ? _a : 100,
        max: (_b = props.anchors[props.anchors.length - 1]) != null ? _b : Math.round(windowHeight.value * 0.6)
      };
    });
    const anchors = computed(() => props.anchors.length >= 2 ? props.anchors : [boundary.value.min, boundary.value.max]);
    const dragging = ref(false);
    const rootStyle = computed(() => ({
      height: addUnit(boundary.value.max),
      transform: `translateY(calc(100% + ${addUnit(-height.value)}))`,
      transition: !dragging.value ? `transform ${props.duration}s cubic-bezier(0.18, 0.89, 0.32, 1.28)` : "none"
    }));
    const ease = (moveY) => {
      const absDistance = Math.abs(moveY);
      const {
        min,
        max
      } = boundary.value;
      if (absDistance > max) {
        return -(max + (absDistance - max) * DAMP);
      }
      if (absDistance < min) {
        return -(min - (min - absDistance) * DAMP);
      }
      return moveY;
    };
    let startY;
    let maxScroll = -1;
    const touch = useTouch();
    const onTouchstart = (e) => {
      if (!props.draggable) return;
      touch.start(e);
      dragging.value = true;
      startY = -height.value;
      maxScroll = -1;
    };
    const onTouchmove = (e) => {
      var _a;
      if (!props.draggable) return;
      touch.move(e);
      const target = e.target;
      if (contentRef.value === target || ((_a = contentRef.value) == null ? void 0 : _a.contains(target))) {
        const {
          scrollTop
        } = contentRef.value;
        maxScroll = Math.max(maxScroll, scrollTop);
        if (!props.contentDraggable) return;
        if (-startY < boundary.value.max) {
          preventDefault(e, true);
        } else if (!(scrollTop <= 0 && touch.deltaY.value > 0) || maxScroll > 0) {
          return;
        }
      }
      const moveY = touch.deltaY.value + startY;
      height.value = -ease(moveY);
    };
    const onTouchend = () => {
      maxScroll = -1;
      if (!dragging.value) {
        return;
      }
      dragging.value = false;
      if (!props.draggable) {
        return;
      }
      if (props.magnetic) {
        height.value = closest(anchors.value, height.value);
      } else {
        const {
          min,
          max
        } = boundary.value;
        height.value = Math.max(min, Math.min(max, height.value));
      }
      if (height.value !== -startY) {
        emit("heightChange", {
          height: height.value
        });
      }
    };
    watch(boundary, () => {
      height.value = closest(anchors.value, height.value);
    }, {
      immediate: true
    });
    useLockScroll(rootRef, () => props.lockScroll || dragging.value);
    useEventListener("touchmove", onTouchmove, {
      target: rootRef
    });
    const renderHeader = () => {
      if (slots.header) {
        return slots.header();
      }
      if (!props.draggable) {
        return null;
      }
      return createVNode("div", {
        "class": bem("header")
      }, [createVNode("div", {
        "class": bem("header-bar")
      }, null)]);
    };
    return () => {
      var _a;
      return createVNode("div", {
        "class": [bem(), {
          "van-safe-area-bottom": props.safeAreaInsetBottom
        }],
        "ref": rootRef,
        "style": rootStyle.value,
        "onTouchstartPassive": onTouchstart,
        "onTouchend": onTouchend,
        "onTouchcancel": onTouchend
      }, [renderHeader(), createVNode("div", {
        "class": bem("content"),
        "ref": contentRef,
        "style": {
          paddingBottom: addUnit(boundary.value.max - height.value)
        }
      }, [(_a = slots.default) == null ? void 0 : _a.call(slots)])]);
    };
  }
});
export {
  stdin_default as default,
  floatingPanelProps
};
