UNPKG

@extclp/vexip-ui

Version:

A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good

1 lines 10.3 kB
{"version":3,"file":"affix.vue2.mjs","sources":["../../../components/affix/affix.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n computed,\n getCurrentInstance,\n onBeforeUnmount,\n onMounted,\n ref,\n shallowRef,\n watch,\n watchEffect\n} from 'vue'\n\nimport { emitEvent, useNameHelper, useProps } from '@vexip-ui/config'\nimport { affixProps } from './props'\nimport { callIfFunc, isClient, isElement } from '@vexip-ui/utils'\nimport { clearLastScroller, handleLastScroller } from './helpers'\n\nimport type { NativeScrollExposed } from '@/components/native-scroll'\nimport type { ScrollExposed } from '@/components/scroll'\n\nimport type { CSSProperties, ComponentInternalInstance } from 'vue'\n\ntype ScrollType = NativeScrollExposed & ScrollExposed\n\ndefineOptions({ name: 'Affix' })\n\nconst _props = defineProps(affixProps)\nconst props = useProps('affix', _props, {\n offset: 0,\n zIndex: 100,\n position: 'top',\n target: null\n})\n\nconst nh = useNameHelper('affix')\n\nconst instance = getCurrentInstance()!\n\nconst wrapper = shallowRef<HTMLElement>()\nconst target = shallowRef<HTMLElement>()\nconst container = shallowRef<Window | HTMLElement>()\n\nlet isRawViewer = false\nlet scroller: ScrollType | null = null\n\nconst fixed = ref(false)\nconst affixHeight = ref(0)\nconst affixWidth = ref(0)\nconst scrollTop = ref(0)\nconst clientHeight = ref(0)\nconst transform = ref(0)\n\nconst affixStyle = computed<CSSProperties>(() => {\n return {\n height: fixed.value ? `${affixHeight.value}px` : '',\n width: fixed.value ? `${affixWidth.value}px` : ''\n }\n})\nconst fixedStyle = computed<CSSProperties>(() => {\n if (!fixed.value) return {}\n\n let _top = props.offset\n let _bottom = props.offset\n\n if (isElement(container.value)) {\n if (props.target && props.position === 'top') {\n _top += transform.value\n } else {\n _bottom += transform.value\n }\n }\n\n return {\n height: `${affixHeight.value}px`,\n width: `${affixWidth.value}px`,\n top: props.position === 'top' ? `${_top}px` : '',\n bottom: props.position === 'bottom' ? `${_bottom}px` : '',\n zIndex: props.zIndex\n }\n})\n\nwatchEffect(update)\nwatch(fixed, fixed => {\n emitEvent(props.onChange, fixed)\n})\n\ndefineExpose({ update })\n\nonMounted(() => {\n if (props.target) {\n const _target: unknown = callIfFunc(props.target)\n\n if (typeof _target === 'string') {\n target.value = document.querySelector<HTMLElement>(_target) ?? undefined\n\n if (!target.value) {\n throw new Error(`[vexip-ui:Affix] target not exists: ${props.target}`)\n }\n } else {\n target.value = _target as any\n }\n } else {\n target.value = document.documentElement\n }\n\n updateContainer()\n})\n\nonBeforeUnmount(() => {\n removeListener()\n})\n\nfunction update() {\n if (!wrapper.value || !target.value || !container.value) return\n\n const wrapperRect = wrapper.value.getBoundingClientRect()\n const targetRect = target.value.getBoundingClientRect()\n\n affixHeight.value = wrapperRect.height\n affixWidth.value = wrapperRect.width\n scrollTop.value =\n container.value === window\n ? document.documentElement.scrollTop\n : (container.value as unknown as ScrollType).scrollY || 0\n scrollTop.value = document.documentElement.scrollTop\n clientHeight.value = document.documentElement.clientHeight\n\n if (props.position === 'top') {\n if (props.target) {\n transform.value = targetRect.top\n fixed.value = wrapperRect.top < targetRect.top + props.offset\n } else {\n fixed.value = props.offset > wrapperRect.top\n }\n } else {\n if (props.target) {\n transform.value = clientHeight.value - targetRect.bottom\n fixed.value = targetRect.bottom < props.offset + wrapperRect.bottom\n } else {\n fixed.value = clientHeight.value - props.offset < wrapperRect.bottom\n }\n }\n}\n\nfunction handleContainerScroll() {\n handleLastScroller(target)\n update()\n\n emitEvent(props.onScroll, {\n scrollTop: scrollTop.value,\n fixed: fixed.value\n })\n}\n\nfunction updateContainer() {\n removeListener()\n\n if (!isClient) return\n\n if (props.target) {\n container.value = target.value!\n container.value.addEventListener('scroll', handleContainerScroll)\n } else {\n let _container: ComponentInternalInstance | null = instance.parent!\n const refName = 'scroll'\n\n while (_container) {\n const name = _container.type?.name\n\n if (name === 'Scroll' || name === 'NativeScroll') {\n const { exposeProxy, exposed, proxy } = _container\n const _scroller = new Proxy({} as any, {\n get(_, key) {\n return (proxy as any)?.[key] ?? (exposeProxy as any)?.[key] ?? (exposed as any)?.[key]\n }\n })\n const scrollerEl = _scroller?.$el as HTMLElement\n\n if (!scrollerEl.getAttribute('class')?.includes('vxp-native-scroll--horizontal')) {\n scroller = _scroller\n break\n }\n }\n\n const refTemp = _container.refs?.[refName]\n\n if (refTemp) {\n if (isElement(refTemp)) {\n isRawViewer = true\n container.value = refTemp as HTMLElement\n } else {\n scroller = refTemp as ScrollType\n }\n\n break\n }\n\n _container = _container.parent\n }\n\n if (scroller) {\n scroller.addScrollListener(handleContainerScroll)\n container.value = scroller.$el\n } else if (!container.value) {\n isRawViewer = true\n container.value = window\n }\n\n if (isRawViewer && container.value) {\n container.value.addEventListener('scroll', handleContainerScroll)\n }\n }\n}\n\nfunction removeListener() {\n if (scroller) {\n scroller.removeScrollListener(handleContainerScroll)\n scroller = null\n }\n\n if (container.value) {\n container.value.removeEventListener('scroll', handleContainerScroll)\n container.value = undefined\n }\n\n clearLastScroller(target)\n}\n</script>\n\n<template>\n <div ref=\"wrapper\" :class=\"nh.b()\" :style=\"affixStyle\">\n <div :class=\"{ [nh.bm('fixed')]: fixed }\" :style=\"fixedStyle\">\n <slot></slot>\n </div>\n </div>\n</template>\n"],"names":["props","useProps","__props","nh","useNameHelper","instance","getCurrentInstance","wrapper","shallowRef","target","container","isRawViewer","scroller","fixed","ref","affixHeight","affixWidth","scrollTop","clientHeight","transform","affixStyle","computed","fixedStyle","_top","_bottom","isElement","watchEffect","update","watch","emitEvent","__expose","onMounted","_target","callIfFunc","updateContainer","onBeforeUnmount","removeListener","wrapperRect","targetRect","handleContainerScroll","handleLastScroller","isClient","_container","refName","name","_a","exposeProxy","exposed","proxy","_scroller","_","key","_b","refTemp","_c","clearLastScroller"],"mappings":";;;;;;;;;;AA2BM,UAAAA,IAAQC,EAAS,SADRC,GACyB;AAAA,MACtC,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,IAAA,CACT,GAEKC,IAAKC,EAAc,OAAO,GAE1BC,IAAWC,EAAmB,GAE9BC,IAAUC,EAAwB,GAClCC,IAASD,EAAwB,GACjCE,IAAYF,EAAiC;AAEnD,QAAIG,IAAc,IACdC,IAA8B;AAE5B,UAAAC,IAAQC,EAAI,EAAK,GACjBC,IAAcD,EAAI,CAAC,GACnBE,IAAaF,EAAI,CAAC,GAClBG,IAAYH,EAAI,CAAC,GACjBI,IAAeJ,EAAI,CAAC,GACpBK,IAAYL,EAAI,CAAC,GAEjBM,IAAaC,EAAwB,OAClC;AAAA,MACL,QAAQR,EAAM,QAAQ,GAAGE,EAAY,KAAK,OAAO;AAAA,MACjD,OAAOF,EAAM,QAAQ,GAAGG,EAAW,KAAK,OAAO;AAAA,IACjD,EACD,GACKM,IAAaD,EAAwB,MAAM;AAC/C,UAAI,CAACR,EAAM,MAAO,QAAO,CAAC;AAE1B,UAAIU,IAAOvB,EAAM,QACbwB,IAAUxB,EAAM;AAEhB,aAAAyB,EAAUf,EAAU,KAAK,MACvBV,EAAM,UAAUA,EAAM,aAAa,QACrCuB,KAAQJ,EAAU,QAElBK,KAAWL,EAAU,QAIlB;AAAA,QACL,QAAQ,GAAGJ,EAAY,KAAK;AAAA,QAC5B,OAAO,GAAGC,EAAW,KAAK;AAAA,QAC1B,KAAKhB,EAAM,aAAa,QAAQ,GAAGuB,CAAI,OAAO;AAAA,QAC9C,QAAQvB,EAAM,aAAa,WAAW,GAAGwB,CAAO,OAAO;AAAA,QACvD,QAAQxB,EAAM;AAAA,MAChB;AAAA,IAAA,CACD;AAED,IAAA0B,EAAYC,CAAM,GACZC,EAAAf,GAAO,CAAAA,MAAS;AACV,MAAAgB,EAAA7B,EAAM,UAAUa,CAAK;AAAA,IAAA,CAChC,GAEYiB,EAAA,EAAE,QAAAH,GAAQ,GAEvBI,EAAU,MAAM;AACd,UAAI/B,EAAM,QAAQ;AACV,cAAAgC,IAAmBC,GAAWjC,EAAM,MAAM;AAE5C,YAAA,OAAOgC,KAAY;AAGjB,cAFJvB,EAAO,QAAQ,SAAS,cAA2BuB,CAAO,KAAK,QAE3D,CAACvB,EAAO;AACV,kBAAM,IAAI,MAAM,uCAAuCT,EAAM,MAAM,EAAE;AAAA;AAGvE,UAAAS,EAAO,QAAQuB;AAAA,MACjB;AAEA,QAAAvB,EAAO,QAAQ,SAAS;AAGV,MAAAyB,EAAA;AAAA,IAAA,CACjB,GAEDC,EAAgB,MAAM;AACL,MAAAC,EAAA;AAAA,IAAA,CAChB;AAED,aAAST,IAAS;AACZ,UAAA,CAACpB,EAAQ,SAAS,CAACE,EAAO,SAAS,CAACC,EAAU,MAAO;AAEnD,YAAA2B,IAAc9B,EAAQ,MAAM,sBAAsB,GAClD+B,IAAa7B,EAAO,MAAM,sBAAsB;AAEtD,MAAAM,EAAY,QAAQsB,EAAY,QAChCrB,EAAW,QAAQqB,EAAY,OACrBpB,EAAA,QACRP,EAAU,UAAU,SAChB,SAAS,gBAAgB,YACxBA,EAAU,MAAgC,WAAW,GAClDO,EAAA,QAAQ,SAAS,gBAAgB,WAC9BC,EAAA,QAAQ,SAAS,gBAAgB,cAE1ClB,EAAM,aAAa,QACjBA,EAAM,UACRmB,EAAU,QAAQmB,EAAW,KAC7BzB,EAAM,QAAQwB,EAAY,MAAMC,EAAW,MAAMtC,EAAM,UAEjDa,EAAA,QAAQb,EAAM,SAASqC,EAAY,MAGvCrC,EAAM,UACEmB,EAAA,QAAQD,EAAa,QAAQoB,EAAW,QAClDzB,EAAM,QAAQyB,EAAW,SAAStC,EAAM,SAASqC,EAAY,UAE7DxB,EAAM,QAAQK,EAAa,QAAQlB,EAAM,SAASqC,EAAY;AAAA,IAElE;AAGF,aAASE,IAAwB;AAC/B,MAAAC,GAAmB/B,CAAM,GAClBkB,EAAA,GAEPE,EAAU7B,EAAM,UAAU;AAAA,QACxB,WAAWiB,EAAU;AAAA,QACrB,OAAOJ,EAAM;AAAA,MAAA,CACd;AAAA,IAAA;AAGH,aAASqB,IAAkB;;AAGzB,UAFeE,EAAA,GAEX,EAACK;AAEL,YAAIzC,EAAM;AACR,UAAAU,EAAU,QAAQD,EAAO,OACfC,EAAA,MAAM,iBAAiB,UAAU6B,CAAqB;AAAA,aAC3D;AACL,cAAIG,IAA+CrC,EAAS;AAC5D,gBAAMsC,IAAU;AAEhB,iBAAOD,KAAY;AACX,kBAAAE,KAAOC,IAAAH,EAAW,SAAX,gBAAAG,EAAiB;AAE1B,gBAAAD,MAAS,YAAYA,MAAS,gBAAgB;AAChD,oBAAM,EAAE,aAAAE,GAAa,SAAAC,GAAS,OAAAC,EAAU,IAAAN,GAClCO,IAAY,IAAI,MAAM,IAAW;AAAA,gBACrC,IAAIC,IAAGC,GAAK;AACV,0BAAQH,KAAA,gBAAAA,EAAgBG,QAASL,KAAA,gBAAAA,EAAsBK,QAASJ,KAAA,gBAAAA,EAAkBI;AAAA,gBAAG;AAAA,cACvF,CACD;AAGD,kBAAI,GAACC,KAFcH,KAAA,gBAAAA,EAAW,KAEd,aAAa,OAAO,MAA/B,QAAAG,EAAkC,SAAS,mCAAkC;AACrE,gBAAAxC,IAAAqC;AACX;AAAA,cAAA;AAAA,YACF;AAGI,kBAAAI,KAAUC,IAAAZ,EAAW,SAAX,gBAAAY,EAAkBX;AAElC,gBAAIU,GAAS;AACP,cAAA5B,EAAU4B,CAAO,KACL1C,IAAA,IACdD,EAAU,QAAQ2C,KAEPzC,IAAAyC;AAGb;AAAA,YAAA;AAGF,YAAAX,IAAaA,EAAW;AAAA,UAAA;AAG1B,UAAI9B,KACFA,EAAS,kBAAkB2B,CAAqB,GAChD7B,EAAU,QAAQE,EAAS,OACjBF,EAAU,UACNC,IAAA,IACdD,EAAU,QAAQ,SAGhBC,KAAeD,EAAU,SACjBA,EAAA,MAAM,iBAAiB,UAAU6B,CAAqB;AAAA,QAClE;AAAA,IACF;AAGF,aAASH,IAAiB;AACxB,MAAIxB,MACFA,EAAS,qBAAqB2B,CAAqB,GACxC3B,IAAA,OAGTF,EAAU,UACFA,EAAA,MAAM,oBAAoB,UAAU6B,CAAqB,GACnE7B,EAAU,QAAQ,SAGpB6C,GAAkB9C,CAAM;AAAA,IAAA;;;;;;;;;;;;;;;;"}