You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 line
17 KiB

{"ast":null,"code":"import \"core-js/modules/es.array.push.js\";\nimport { defineComponent, ref, computed, onMounted, watch, provide, openBlock, createElementBlock, normalizeClass, unref, normalizeStyle, createCommentVNode, createElementVNode, renderSlot } from 'vue';\nimport { useEventListener } from '@vueuse/core';\nimport '../../../hooks/index.mjs';\nimport '../../../utils/index.mjs';\nimport { anchorProps, anchorEmits } from './anchor.mjs';\nimport { anchorKey } from './constants.mjs';\nimport _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';\nimport { useNamespace } from '../../../hooks/use-namespace/index.mjs';\nimport { getElement } from '../../../utils/dom/element.mjs';\nimport { getScrollElement, animateScrollTo, getScrollTop } from '../../../utils/dom/scroll.mjs';\nimport { getOffsetTopDistance } from '../../../utils/dom/position.mjs';\nimport { throttleByRaf } from '../../../utils/throttleByRaf.mjs';\nimport { isUndefined, isWindow } from '../../../utils/types.mjs';\nconst __default__ = defineComponent({\n name: \"ElAnchor\"\n});\nconst _sfc_main = /* @__PURE__ */defineComponent({\n ...__default__,\n props: anchorProps,\n emits: anchorEmits,\n setup(__props, {\n expose,\n emit\n }) {\n const props = __props;\n const currentAnchor = ref(\"\");\n const anchorRef = ref(null);\n const markerRef = ref(null);\n const containerEl = ref();\n const links = {};\n let isScrolling = false;\n let currentScrollTop = 0;\n const ns = useNamespace(\"anchor\");\n const cls = computed(() => [ns.b(), props.type === \"underline\" ? ns.m(\"underline\") : \"\", ns.m(props.direction)]);\n const addLink = state => {\n links[state.href] = state.el;\n };\n const removeLink = href => {\n delete links[href];\n };\n const setCurrentAnchor = href => {\n const activeHref = currentAnchor.value;\n if (activeHref !== href) {\n currentAnchor.value = href;\n emit(\"change\", href);\n }\n };\n let clearAnimate = null;\n const scrollToAnchor = href => {\n if (!containerEl.value) return;\n const target = getElement(href);\n if (!target) return;\n if (clearAnimate) clearAnimate();\n isScrolling = true;\n const scrollEle = getScrollElement(target, containerEl.value);\n const distance = getOffsetTopDistance(target, scrollEle);\n const max = scrollEle.scrollHeight - scrollEle.clientHeight;\n const to = Math.min(distance - props.offset, max);\n clearAnimate = animateScrollTo(containerEl.value, currentScrollTop, to, props.duration, () => {\n setTimeout(() => {\n isScrolling = false;\n }, 20);\n });\n };\n const scrollTo = href => {\n if (href) {\n setCurrentAnchor(href);\n scrollToAnchor(href);\n }\n };\n const handleClick = (e, href) => {\n emit(\"click\", e, href);\n scrollTo(href);\n };\n const handleScroll = throttleByRaf(() => {\n if (containerEl.value) {\n currentScrollTop = getScrollTop(containerEl.value);\n }\n const currentHref = getCurrentHref();\n if (isScrolling || isUndefined(currentHref)) return;\n setCurrentAnchor(currentHref);\n });\n const getCurrentHref = () => {\n if (!containerEl.value) return;\n const scrollTop = getScrollTop(containerEl.value);\n const anchorTopList = [];\n for (const href of Object.keys(links)) {\n const target = getElement(href);\n if (!target) continue;\n const scrollEle = getScrollElement(target, containerEl.value);\n const distance = getOffsetTopDistance(target, scrollEle);\n anchorTopList.push({\n top: distance - props.offset - props.bound,\n href\n });\n }\n anchorTopList.sort((prev, next) => prev.top - next.top);\n for (let i = 0; i < anchorTopList.length; i++) {\n const item = anchorTopList[i];\n const next = anchorTopList[i + 1];\n if (i === 0 && scrollTop === 0) {\n return \"\";\n }\n if (item.top <= scrollTop && (!next || next.top > scrollTop)) {\n return item.href;\n }\n }\n };\n const getContainer = () => {\n const el = getElement(props.container);\n if (!el || isWindow(el)) {\n containerEl.value = window;\n } else {\n containerEl.value = el;\n }\n };\n useEventListener(containerEl, \"scroll\", handleScroll);\n const markerStyle = computed(() => {\n if (!anchorRef.value || !markerRef.value || !currentAnchor.value) return {};\n const currentLinkEl = links[currentAnchor.value];\n if (!currentLinkEl) return {};\n const anchorRect = anchorRef.value.getBoundingClientRect();\n const markerRect = markerRef.value.getBoundingClientRect();\n const linkRect = currentLinkEl.getBoundingClientRect();\n if (props.direction === \"horizontal\") {\n const left = linkRect.left - anchorRect.left;\n return {\n left: `${left}px`,\n width: `${linkRect.width}px`,\n opacity: 1\n };\n } else {\n const top = linkRect.top - anchorRect.top + (linkRect.height - markerRect.height) / 2;\n return {\n top: `${top}px`,\n opacity: 1\n };\n }\n });\n onMounted(() => {\n getContainer();\n const hash = decodeURIComponent(window.location.hash);\n const target = getElement(hash);\n if (target) {\n scrollTo(hash);\n } else {\n handleScroll();\n }\n });\n watch(() => props.container, () => {\n getContainer();\n });\n provide(anchorKey, {\n ns,\n direction: props.direction,\n currentAnchor,\n addLink,\n removeLink,\n handleClick\n });\n expose({\n scrollTo\n });\n return (_ctx, _cache) => {\n return openBlock(), createElementBlock(\"div\", {\n ref_key: \"anchorRef\",\n ref: anchorRef,\n class: normalizeClass(unref(cls))\n }, [_ctx.marker ? (openBlock(), createElementBlock(\"div\", {\n key: 0,\n ref_key: \"markerRef\",\n ref: markerRef,\n class: normalizeClass(unref(ns).e(\"marker\")),\n style: normalizeStyle(unref(markerStyle))\n }, null, 6)) : createCommentVNode(\"v-if\", true), createElementVNode(\"div\", {\n class: normalizeClass(unref(ns).e(\"list\"))\n }, [renderSlot(_ctx.$slots, \"default\")], 2)], 2);\n };\n }\n});\nvar Anchor = /* @__PURE__ */_export_sfc(_sfc_main, [[\"__file\", \"anchor.vue\"]]);\nexport { Anchor as default };","map":{"version":3,"names":["name","currentAnchor","ref","anchorRef","markerRef","containerEl","links","isScrolling","currentScrollTop","ns","useNamespace","cls","computed","b","props","type","m","direction","addLink","state","href","el","removeLink","setCurrentAnchor","activeHref","value","emit","clearAnimate","scrollToAnchor","target","getElement","scrollEle","getScrollElement","distance","getOffsetTopDistance","max","scrollHeight","clientHeight","to","Math","min","offset","animateScrollTo","duration","setTimeout","scrollTo","handleClick","e","handleScroll","throttleByRaf","getScrollTop","currentHref","getCurrentHref","isUndefined","scrollTop","anchorTopList","Object","keys","push","top","bound","sort","prev","next","i","length","item","getContainer","container","isWindow","window","useEventListener","markerStyle","currentLinkEl","anchorRect","getBoundingClientRect","markerRect","linkRect","left","width","opacity","height","onMounted","hash","decodeURIComponent","location","watch","provide","anchorKey","expose","_ctx","_cache"],"sources":["../../../../../../packages/components/anchor/src/anchor.vue"],"sourcesContent":["<template>\n <div ref=\"anchorRef\" :class=\"cls\">\n <div\n v-if=\"marker\"\n ref=\"markerRef\"\n :class=\"ns.e('marker')\"\n :style=\"markerStyle\"\n />\n <div :class=\"ns.e('list')\">\n <slot />\n </div>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, onMounted, provide, ref, watch } from 'vue'\nimport { useEventListener } from '@vueuse/core'\nimport { useNamespace } from '@element-plus/hooks'\nimport {\n animateScrollTo,\n getElement,\n getOffsetTopDistance,\n getScrollElement,\n getScrollTop,\n isUndefined,\n isWindow,\n throttleByRaf,\n} from '@element-plus/utils'\nimport { anchorEmits, anchorProps } from './anchor'\nimport { anchorKey } from './constants'\n\nimport type { AnchorLinkState } from './constants'\n\ndefineOptions({\n name: 'ElAnchor',\n})\n\nconst props = defineProps(anchorProps)\nconst emit = defineEmits(anchorEmits)\n\nconst currentAnchor = ref('')\nconst anchorRef = ref<HTMLElement | null>(null)\nconst markerRef = ref<HTMLElement | null>(null)\nconst containerEl = ref<HTMLElement | Window>()\n\nconst links: Record<string, HTMLElement> = {}\nlet isScrolling = false\nlet currentScrollTop = 0\n\nconst ns = useNamespace('anchor')\n\nconst cls = computed(() => [\n ns.b(),\n props.type === 'underline' ? ns.m('underline') : '',\n ns.m(props.direction),\n])\n\nconst addLink = (state: AnchorLinkState) => {\n links[state.href] = state.el\n}\n\nconst removeLink = (href: string) => {\n delete links[href]\n}\n\nconst setCurrentAnchor = (href: string) => {\n const activeHref = currentAnchor.value\n if (activeHref !== href) {\n currentAnchor.value = href\n emit('change', href)\n }\n}\n\nlet clearAnimate: (() => void) | null = null\n\nconst scrollToAnchor = (href: string) => {\n if (!containerEl.value) return\n const target = getElement(href)\n if (!target) return\n if (clearAnimate) clearAnimate()\n isScrolling = true\n const scrollEle = getScrollElement(target, containerEl.value)\n const distance = getOffsetTopDistance(target, scrollEle)\n const max = scrollEle.scrollHeight - scrollEle.clientHeight\n const to = Math.min(distance - props.offset, max)\n clearAnimate = animateScrollTo(\n containerEl.value,\n currentScrollTop,\n to,\n props.duration,\n () => {\n // make sure it is executed after throttleByRaf's handleScroll\n setTimeout(() => {\n isScrolling = false\n }, 20)\n }\n )\n}\n\nconst scrollTo = (href?: string) => {\n if (href) {\n setCurrentAnchor(href)\n scrollToAnchor(href)\n }\n}\n\nconst handleClick = (e: MouseEvent, href?: string) => {\n emit('click', e, href)\n scrollTo(href)\n}\n\nconst handleScroll = throttleByRaf(() => {\n if (containerEl.value) {\n currentScrollTop = getScrollTop(containerEl.value)\n }\n const currentHref = getCurrentHref()\n if (isScrolling || isUndefined(currentHref)) return\n setCurrentAnchor(currentHref)\n})\n\nconst getCurrentHref = () => {\n if (!containerEl.value) return\n const scrollTop = getScrollTop(containerEl.value)\n const anchorTopList: { top: number; href: string }[] = []\n\n for (const href of Object.keys(links)) {\n const target = getElement(href)\n if (!target) continue\n const scrollEle = getScrollElement(target, containerEl.value)\n const distance = getOffsetTopDistance(target, scrollEle)\n anchorTopList.push({\n top: distance - props.offset - props.bound,\n href,\n })\n }\n anchorTopList.sort((prev, next) => prev.top - next.top)\n\n for (let i = 0; i < anchorTopList.length; i++) {\n const item = anchorTopList[i]\n const next = anchorTopList[i + 1]\n\n if (i === 0 && scrollTop === 0) {\n return ''\n }\n if (item.top <= scrollTop && (!next || next.top > scrollTop)) {\n return item.href\n }\n }\n}\n\nconst getContainer = () => {\n const el = getElement(props.container)\n if (!el || isWindow(el)) {\n containerEl.value = window\n } else {\n containerEl.value = el\n }\n}\n\nuseEventListener(containerEl, 'scroll', handleScroll)\n\nconst markerStyle = computed(() => {\n if (!anchorRef.value || !markerRef.value || !currentAnchor.value) return {}\n const currentLinkEl = links[currentAnchor.value]\n if (!currentLinkEl) return {}\n const anchorRect = anchorRef.value.getBoundingClientRect()\n const markerRect = markerRef.value.getBoundingClientRect()\n const linkRect = currentLinkEl.getBoundingClientRect()\n\n if (props.direction === 'horizontal') {\n const left = linkRect.left - anchorRect.left\n return {\n left: `${left}px`,\n width: `${linkRect.width}px`,\n opacity: 1,\n }\n } else {\n const top =\n linkRect.top - anchorRect.top + (linkRect.height - markerRect.height) / 2\n return {\n top: `${top}px`,\n opacity: 1,\n }\n }\n})\n\nonMounted(() => {\n getContainer()\n const hash = decodeURIComponent(window.location.hash)\n const target = getElement(hash)\n if (target) {\n scrollTo(hash)\n } else {\n handleScroll()\n }\n})\n\nwatch(\n () => props.container,\n () => {\n getContainer()\n }\n)\n\nprovide(anchorKey, {\n ns,\n direction: props.direction,\n currentAnchor,\n addLink,\n removeLink,\n handleClick,\n})\n\ndefineExpose({\n scrollTo,\n})\n</script>\n"],"mappings":"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","ignoreList":[]},"metadata":{},"sourceType":"module","externalDependencies":[]}