175 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { ref, reactive, computed, defineComponent, createVNode as _createVNode } from "vue";
 | 
						|
import { clamp, isDef, numericProp, preventDefault, callInterceptor, createNamespace, makeNumericProp } from "../utils/index.mjs";
 | 
						|
import { useRect, useClickAway, useEventListener } from "@vant/use";
 | 
						|
import { useTouch } from "../composables/use-touch.mjs";
 | 
						|
import { useExpose } from "../composables/use-expose.mjs";
 | 
						|
const [name, bem] = createNamespace("swipe-cell");
 | 
						|
const swipeCellProps = {
 | 
						|
  name: makeNumericProp(""),
 | 
						|
  disabled: Boolean,
 | 
						|
  leftWidth: numericProp,
 | 
						|
  rightWidth: numericProp,
 | 
						|
  beforeClose: Function,
 | 
						|
  stopPropagation: Boolean
 | 
						|
};
 | 
						|
var stdin_default = defineComponent({
 | 
						|
  name,
 | 
						|
  props: swipeCellProps,
 | 
						|
  emits: ["open", "close", "click"],
 | 
						|
  setup(props, {
 | 
						|
    emit,
 | 
						|
    slots
 | 
						|
  }) {
 | 
						|
    let opened;
 | 
						|
    let lockClick;
 | 
						|
    let startOffset;
 | 
						|
    let isInBeforeClosing;
 | 
						|
    const root = ref();
 | 
						|
    const leftRef = ref();
 | 
						|
    const rightRef = ref();
 | 
						|
    const state = reactive({
 | 
						|
      offset: 0,
 | 
						|
      dragging: false
 | 
						|
    });
 | 
						|
    const touch = useTouch();
 | 
						|
    const getWidthByRef = (ref2) => ref2.value ? useRect(ref2).width : 0;
 | 
						|
    const leftWidth = computed(() => isDef(props.leftWidth) ? +props.leftWidth : getWidthByRef(leftRef));
 | 
						|
    const rightWidth = computed(() => isDef(props.rightWidth) ? +props.rightWidth : getWidthByRef(rightRef));
 | 
						|
    const open = (side) => {
 | 
						|
      state.offset = side === "left" ? leftWidth.value : -rightWidth.value;
 | 
						|
      if (!opened) {
 | 
						|
        opened = true;
 | 
						|
        emit("open", {
 | 
						|
          name: props.name,
 | 
						|
          position: side
 | 
						|
        });
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const close = (position) => {
 | 
						|
      state.offset = 0;
 | 
						|
      if (opened) {
 | 
						|
        opened = false;
 | 
						|
        emit("close", {
 | 
						|
          name: props.name,
 | 
						|
          position
 | 
						|
        });
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const toggle = (side) => {
 | 
						|
      const offset = Math.abs(state.offset);
 | 
						|
      const THRESHOLD = 0.15;
 | 
						|
      const threshold = opened ? 1 - THRESHOLD : THRESHOLD;
 | 
						|
      const width = side === "left" ? leftWidth.value : rightWidth.value;
 | 
						|
      if (width && offset > width * threshold) {
 | 
						|
        open(side);
 | 
						|
      } else {
 | 
						|
        close(side);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onTouchStart = (event) => {
 | 
						|
      if (!props.disabled) {
 | 
						|
        startOffset = state.offset;
 | 
						|
        touch.start(event);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onTouchMove = (event) => {
 | 
						|
      if (props.disabled) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      const {
 | 
						|
        deltaX
 | 
						|
      } = touch;
 | 
						|
      touch.move(event);
 | 
						|
      if (touch.isHorizontal()) {
 | 
						|
        lockClick = true;
 | 
						|
        state.dragging = true;
 | 
						|
        const isEdge = !opened || deltaX.value * startOffset < 0;
 | 
						|
        if (isEdge) {
 | 
						|
          preventDefault(event, props.stopPropagation);
 | 
						|
        }
 | 
						|
        state.offset = clamp(deltaX.value + startOffset, -rightWidth.value, leftWidth.value);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onTouchEnd = () => {
 | 
						|
      if (state.dragging) {
 | 
						|
        state.dragging = false;
 | 
						|
        toggle(state.offset > 0 ? "left" : "right");
 | 
						|
        setTimeout(() => {
 | 
						|
          lockClick = false;
 | 
						|
        }, 0);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onClick = (position = "outside", event) => {
 | 
						|
      if (isInBeforeClosing) return;
 | 
						|
      emit("click", position);
 | 
						|
      if (opened && !lockClick) {
 | 
						|
        isInBeforeClosing = true;
 | 
						|
        callInterceptor(props.beforeClose, {
 | 
						|
          args: [{
 | 
						|
            event,
 | 
						|
            name: props.name,
 | 
						|
            position
 | 
						|
          }],
 | 
						|
          done: () => {
 | 
						|
            isInBeforeClosing = false;
 | 
						|
            close(position);
 | 
						|
          },
 | 
						|
          canceled: () => isInBeforeClosing = false,
 | 
						|
          error: () => isInBeforeClosing = false
 | 
						|
        });
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const getClickHandler = (position) => (event) => {
 | 
						|
      if (lockClick || opened) {
 | 
						|
        event.stopPropagation();
 | 
						|
      }
 | 
						|
      if (lockClick) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      onClick(position, event);
 | 
						|
    };
 | 
						|
    const renderSideContent = (side, ref2) => {
 | 
						|
      const contentSlot = slots[side];
 | 
						|
      if (contentSlot) {
 | 
						|
        return _createVNode("div", {
 | 
						|
          "ref": ref2,
 | 
						|
          "class": bem(side),
 | 
						|
          "onClick": getClickHandler(side)
 | 
						|
        }, [contentSlot()]);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    useExpose({
 | 
						|
      open,
 | 
						|
      close
 | 
						|
    });
 | 
						|
    useClickAway(root, (event) => onClick("outside", event), {
 | 
						|
      eventName: "touchstart"
 | 
						|
    });
 | 
						|
    useEventListener("touchmove", onTouchMove, {
 | 
						|
      target: root
 | 
						|
    });
 | 
						|
    return () => {
 | 
						|
      var _a;
 | 
						|
      const wrapperStyle = {
 | 
						|
        transform: `translate3d(${state.offset}px, 0, 0)`,
 | 
						|
        transitionDuration: state.dragging ? "0s" : ".6s"
 | 
						|
      };
 | 
						|
      return _createVNode("div", {
 | 
						|
        "ref": root,
 | 
						|
        "class": bem(),
 | 
						|
        "onClick": getClickHandler("cell"),
 | 
						|
        "onTouchstartPassive": onTouchStart,
 | 
						|
        "onTouchend": onTouchEnd,
 | 
						|
        "onTouchcancel": onTouchEnd
 | 
						|
      }, [_createVNode("div", {
 | 
						|
        "class": bem("wrapper"),
 | 
						|
        "style": wrapperStyle
 | 
						|
      }, [renderSideContent("left", leftRef), (_a = slots.default) == null ? void 0 : _a.call(slots), renderSideContent("right", rightRef)])]);
 | 
						|
    };
 | 
						|
  }
 | 
						|
});
 | 
						|
export {
 | 
						|
  stdin_default as default,
 | 
						|
  swipeCellProps
 | 
						|
};
 |