| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 | import { createVNode as _createVNode } from "vue";import { ref, watch, computed, nextTick, Teleport, onMounted, defineComponent } from "vue";import { isDef, isHidden, truthProp, numericProp, getScrollTop, preventDefault, makeNumberProp, createNamespace, getRootScrollTop, setRootScrollTop } from "../utils/index.mjs";import { useRect, useChildren, useScrollParent, useEventListener } from "@vant/use";import { useTouch } from "../composables/use-touch.mjs";import { useExpose } from "../composables/use-expose.mjs";function genAlphabet() {  const charCodeOfA = "A".charCodeAt(0);  const indexList = Array(26).fill("").map((_, i) => String.fromCharCode(charCodeOfA + i));  return indexList;}const [name, bem] = createNamespace("index-bar");const indexBarProps = {  sticky: truthProp,  zIndex: numericProp,  teleport: [String, Object],  highlightColor: String,  stickyOffsetTop: makeNumberProp(0),  indexList: {    type: Array,    default: genAlphabet  }};const INDEX_BAR_KEY = Symbol(name);var stdin_default = defineComponent({  name,  props: indexBarProps,  emits: ["select", "change"],  setup(props, {    emit,    slots  }) {    const root = ref();    const sidebar = ref();    const activeAnchor = ref("");    const touch = useTouch();    const scrollParent = useScrollParent(root);    const {      children,      linkChildren    } = useChildren(INDEX_BAR_KEY);    let selectActiveIndex;    linkChildren({      props    });    const sidebarStyle = computed(() => {      if (isDef(props.zIndex)) {        return {          zIndex: +props.zIndex + 1        };      }    });    const highlightStyle = computed(() => {      if (props.highlightColor) {        return {          color: props.highlightColor        };      }    });    const getActiveAnchor = (scrollTop, rects) => {      for (let i = children.length - 1; i >= 0; i--) {        const prevHeight = i > 0 ? rects[i - 1].height : 0;        const reachTop = props.sticky ? prevHeight + props.stickyOffsetTop : 0;        if (scrollTop + reachTop >= rects[i].top) {          return i;        }      }      return -1;    };    const getMatchAnchor = (index) => children.find((item) => String(item.index) === index);    const onScroll = () => {      if (isHidden(root)) {        return;      }      const {        sticky,        indexList      } = props;      const scrollTop = getScrollTop(scrollParent.value);      const scrollParentRect = useRect(scrollParent);      const rects = children.map((item) => item.getRect(scrollParent.value, scrollParentRect));      let active = -1;      if (selectActiveIndex) {        const match = getMatchAnchor(selectActiveIndex);        if (match) {          const rect = match.getRect(scrollParent.value, scrollParentRect);          active = getActiveAnchor(rect.top, rects);        }      } else {        active = getActiveAnchor(scrollTop, rects);      }      activeAnchor.value = indexList[active];      if (sticky) {        children.forEach((item, index) => {          const {            state,            $el          } = item;          if (index === active || index === active - 1) {            const rect = $el.getBoundingClientRect();            state.left = rect.left;            state.width = rect.width;          } else {            state.left = null;            state.width = null;          }          if (index === active) {            state.active = true;            state.top = Math.max(props.stickyOffsetTop, rects[index].top - scrollTop) + scrollParentRect.top;          } else if (index === active - 1 && selectActiveIndex === "") {            const activeItemTop = rects[active].top - scrollTop;            state.active = activeItemTop > 0;            state.top = activeItemTop + scrollParentRect.top - rects[index].height;          } else {            state.active = false;          }        });      }      selectActiveIndex = "";    };    const init = () => {      nextTick(onScroll);    };    useEventListener("scroll", onScroll, {      target: scrollParent,      passive: true    });    onMounted(init);    watch(() => props.indexList, init);    watch(activeAnchor, (value) => {      if (value) {        emit("change", value);      }    });    const renderIndexes = () => props.indexList.map((index) => {      const active = index === activeAnchor.value;      return _createVNode("span", {        "class": bem("index", {          active        }),        "style": active ? highlightStyle.value : void 0,        "data-index": index      }, [index]);    });    const scrollTo = (index) => {      selectActiveIndex = String(index);      const match = getMatchAnchor(selectActiveIndex);      if (match) {        const scrollTop = getScrollTop(scrollParent.value);        const scrollParentRect = useRect(scrollParent);        const {          offsetHeight        } = document.documentElement;        match.$el.scrollIntoView();        if (scrollTop === offsetHeight - scrollParentRect.height) {          onScroll();          return;        }        if (props.sticky && props.stickyOffsetTop) {          setRootScrollTop(getRootScrollTop() - props.stickyOffsetTop);        }        emit("select", match.index);      }    };    const scrollToElement = (element) => {      const {        index      } = element.dataset;      if (index) {        scrollTo(index);      }    };    const onClickSidebar = (event) => {      scrollToElement(event.target);    };    let touchActiveIndex;    const onTouchMove = (event) => {      touch.move(event);      if (touch.isVertical()) {        preventDefault(event);        const {          clientX,          clientY        } = event.touches[0];        const target = document.elementFromPoint(clientX, clientY);        if (target) {          const {            index          } = target.dataset;          if (index && touchActiveIndex !== index) {            touchActiveIndex = index;            scrollToElement(target);          }        }      }    };    const renderSidebar = () => _createVNode("div", {      "ref": sidebar,      "class": bem("sidebar"),      "style": sidebarStyle.value,      "onClick": onClickSidebar,      "onTouchstartPassive": touch.start    }, [renderIndexes()]);    useExpose({      scrollTo    });    useEventListener("touchmove", onTouchMove, {      target: sidebar    });    return () => {      var _a;      return _createVNode("div", {        "ref": root,        "class": bem()      }, [props.teleport ? _createVNode(Teleport, {        "to": props.teleport      }, {        default: () => [renderSidebar()]      }) : renderSidebar(), (_a = slots.default) == null ? void 0 : _a.call(slots)]);    };  }});export {  INDEX_BAR_KEY,  stdin_default as default};
 |