152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { ref, computed, defineComponent, createVNode as _createVNode } from "vue";
 | 
						|
import { isDef, truthProp, numericProp, windowHeight, makeStringProp, makeNumericProp, createNamespace, HAPTICS_FEEDBACK } from "../utils/index.mjs";
 | 
						|
import { useId } from "../composables/use-id.mjs";
 | 
						|
import { useExpose } from "../composables/use-expose.mjs";
 | 
						|
import { useRect, useChildren, useClickAway, useScrollParent, useEventListener } from "@vant/use";
 | 
						|
const [name, bem] = createNamespace("dropdown-menu");
 | 
						|
const dropdownMenuProps = {
 | 
						|
  overlay: truthProp,
 | 
						|
  zIndex: numericProp,
 | 
						|
  duration: makeNumericProp(0.2),
 | 
						|
  direction: makeStringProp("down"),
 | 
						|
  activeColor: String,
 | 
						|
  autoLocate: Boolean,
 | 
						|
  closeOnClickOutside: truthProp,
 | 
						|
  closeOnClickOverlay: truthProp,
 | 
						|
  swipeThreshold: numericProp
 | 
						|
};
 | 
						|
const DROPDOWN_KEY = Symbol(name);
 | 
						|
var stdin_default = defineComponent({
 | 
						|
  name,
 | 
						|
  props: dropdownMenuProps,
 | 
						|
  setup(props, {
 | 
						|
    slots
 | 
						|
  }) {
 | 
						|
    const id = useId();
 | 
						|
    const root = ref();
 | 
						|
    const barRef = ref();
 | 
						|
    const offset = ref(0);
 | 
						|
    const {
 | 
						|
      children,
 | 
						|
      linkChildren
 | 
						|
    } = useChildren(DROPDOWN_KEY);
 | 
						|
    const scrollParent = useScrollParent(root);
 | 
						|
    const opened = computed(() => children.some((item) => item.state.showWrapper));
 | 
						|
    const scrollable = computed(() => props.swipeThreshold && children.length > +props.swipeThreshold);
 | 
						|
    const barStyle = computed(() => {
 | 
						|
      if (opened.value && isDef(props.zIndex)) {
 | 
						|
        return {
 | 
						|
          zIndex: +props.zIndex + 1
 | 
						|
        };
 | 
						|
      }
 | 
						|
    });
 | 
						|
    const close = () => {
 | 
						|
      children.forEach((item) => {
 | 
						|
        item.toggle(false);
 | 
						|
      });
 | 
						|
    };
 | 
						|
    const onClickAway = () => {
 | 
						|
      if (props.closeOnClickOutside) {
 | 
						|
        close();
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const updateOffset = () => {
 | 
						|
      if (barRef.value) {
 | 
						|
        const rect = useRect(barRef);
 | 
						|
        if (props.direction === "down") {
 | 
						|
          offset.value = rect.bottom;
 | 
						|
        } else {
 | 
						|
          offset.value = windowHeight.value - rect.top;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onScroll = () => {
 | 
						|
      if (opened.value) {
 | 
						|
        updateOffset();
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const toggleItem = (active) => {
 | 
						|
      children.forEach((item, index) => {
 | 
						|
        if (index === active) {
 | 
						|
          item.toggle();
 | 
						|
        } else if (item.state.showPopup) {
 | 
						|
          item.toggle(false, {
 | 
						|
            immediate: true
 | 
						|
          });
 | 
						|
        }
 | 
						|
      });
 | 
						|
    };
 | 
						|
    const renderTitle = (item, index) => {
 | 
						|
      const {
 | 
						|
        showPopup
 | 
						|
      } = item.state;
 | 
						|
      const {
 | 
						|
        disabled,
 | 
						|
        titleClass
 | 
						|
      } = item;
 | 
						|
      return _createVNode("div", {
 | 
						|
        "id": `${id}-${index}`,
 | 
						|
        "role": "button",
 | 
						|
        "tabindex": disabled ? void 0 : 0,
 | 
						|
        "data-allow-mismatch": "attribute",
 | 
						|
        "class": [bem("item", {
 | 
						|
          disabled,
 | 
						|
          grow: scrollable.value
 | 
						|
        }), {
 | 
						|
          [HAPTICS_FEEDBACK]: !disabled
 | 
						|
        }],
 | 
						|
        "onClick": () => {
 | 
						|
          if (!disabled) {
 | 
						|
            toggleItem(index);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }, [_createVNode("span", {
 | 
						|
        "class": [bem("title", {
 | 
						|
          down: showPopup === (props.direction === "down"),
 | 
						|
          active: showPopup
 | 
						|
        }), titleClass],
 | 
						|
        "style": {
 | 
						|
          color: showPopup ? props.activeColor : ""
 | 
						|
        }
 | 
						|
      }, [_createVNode("div", {
 | 
						|
        "class": "van-ellipsis"
 | 
						|
      }, [item.renderTitle()])])]);
 | 
						|
    };
 | 
						|
    useExpose({
 | 
						|
      close,
 | 
						|
      opened
 | 
						|
    });
 | 
						|
    linkChildren({
 | 
						|
      id,
 | 
						|
      props,
 | 
						|
      offset,
 | 
						|
      opened,
 | 
						|
      updateOffset
 | 
						|
    });
 | 
						|
    useClickAway(root, onClickAway);
 | 
						|
    useEventListener("scroll", onScroll, {
 | 
						|
      target: scrollParent,
 | 
						|
      passive: true
 | 
						|
    });
 | 
						|
    return () => {
 | 
						|
      var _a;
 | 
						|
      return _createVNode("div", {
 | 
						|
        "ref": root,
 | 
						|
        "class": bem()
 | 
						|
      }, [_createVNode("div", {
 | 
						|
        "ref": barRef,
 | 
						|
        "style": barStyle.value,
 | 
						|
        "class": bem("bar", {
 | 
						|
          opened: opened.value,
 | 
						|
          scrollable: scrollable.value
 | 
						|
        })
 | 
						|
      }, [children.map(renderTitle)]), (_a = slots.default) == null ? void 0 : _a.call(slots)]);
 | 
						|
    };
 | 
						|
  }
 | 
						|
});
 | 
						|
export {
 | 
						|
  DROPDOWN_KEY,
 | 
						|
  stdin_default as default,
 | 
						|
  dropdownMenuProps
 | 
						|
};
 |