@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 11.2 kB
Source Map (JSON)
{"version":3,"file":"affix.vue2.mjs","sources":["../../../components/affix/affix.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport {\r\n computed,\r\n getCurrentInstance,\r\n onBeforeUnmount,\r\n onMounted,\r\n ref,\r\n shallowRef,\r\n watch,\r\n watchEffect,\r\n} from 'vue'\r\n\r\nimport { emitEvent, useNameHelper, useProps } from '@vexip-ui/config'\r\nimport { affixProps } from './props'\r\nimport { callIfFunc, isClient, isElement } from '@vexip-ui/utils'\r\nimport { clearLastScroller, handleLastScroller } from './helpers'\r\n\r\nimport type { NativeScrollExposed } from '@/components/native-scroll'\r\nimport type { ScrollExposed } from '@/components/scroll'\r\n\r\nimport type { CSSProperties, ComponentInternalInstance } from 'vue'\r\n\r\ntype ScrollType = NativeScrollExposed & ScrollExposed\r\n\r\ndefineOptions({ name: 'Affix' })\r\n\r\nconst _props = defineProps(affixProps)\r\nconst props = useProps('affix', _props, {\r\n offset: 0,\r\n zIndex: 100,\r\n position: 'top',\r\n target: null,\r\n})\r\n\r\nconst nh = useNameHelper('affix')\r\n\r\nconst instance = getCurrentInstance()!\r\n\r\nconst wrapper = shallowRef<HTMLElement>()\r\nconst target = shallowRef<HTMLElement>()\r\nconst container = shallowRef<Window | HTMLElement>()\r\n\r\nlet isRawViewer = false\r\nlet scroller: ScrollType | null = null\r\n\r\nconst fixed = ref(false)\r\nconst affixHeight = ref(0)\r\nconst affixWidth = ref(0)\r\nconst scrollTop = ref(0)\r\nconst clientHeight = ref(0)\r\nconst transform = ref(0)\r\n\r\nconst affixStyle = computed<CSSProperties>(() => {\r\n return {\r\n height: fixed.value ? `${affixHeight.value}px` : '',\r\n width: fixed.value ? `${affixWidth.value}px` : '',\r\n }\r\n})\r\nconst fixedStyle = computed<CSSProperties>(() => {\r\n if (!fixed.value) return {}\r\n\r\n let _top = props.offset\r\n let _bottom = props.offset\r\n\r\n if (isElement(container.value)) {\r\n if (props.target && props.position === 'top') {\r\n _top += transform.value\r\n } else {\r\n _bottom += transform.value\r\n }\r\n }\r\n\r\n return {\r\n height: `${affixHeight.value}px`,\r\n width: `${affixWidth.value}px`,\r\n top: props.position === 'top' ? `${_top}px` : '',\r\n bottom: props.position === 'bottom' ? `${_bottom}px` : '',\r\n zIndex: props.zIndex,\r\n }\r\n})\r\n\r\nwatchEffect(update)\r\nwatch(fixed, fixed => {\r\n emitEvent(props.onChange, fixed)\r\n})\r\n\r\ndefineExpose({ update })\r\n\r\nonMounted(() => {\r\n if (props.target) {\r\n const _target: unknown = callIfFunc(props.target)\r\n\r\n if (typeof _target === 'string') {\r\n target.value = document.querySelector<HTMLElement>(_target) ?? undefined\r\n\r\n if (!target.value) {\r\n throw new Error(`[vexip-ui:Affix] target not exists: ${props.target}`)\r\n }\r\n } else {\r\n target.value = _target as any\r\n }\r\n } else {\r\n target.value = document.documentElement\r\n }\r\n\r\n updateContainer()\r\n})\r\n\r\nonBeforeUnmount(() => {\r\n removeListener()\r\n})\r\n\r\nfunction update() {\r\n if (!wrapper.value || !target.value || !container.value) return\r\n\r\n const wrapperRect = wrapper.value.getBoundingClientRect()\r\n const targetRect = target.value.getBoundingClientRect()\r\n\r\n affixHeight.value = wrapperRect.height\r\n affixWidth.value = wrapperRect.width\r\n scrollTop.value =\r\n container.value === window\r\n ? document.documentElement.scrollTop\r\n : (container.value as unknown as ScrollType).scrollY || 0\r\n scrollTop.value = document.documentElement.scrollTop\r\n clientHeight.value = document.documentElement.clientHeight\r\n\r\n if (props.position === 'top') {\r\n if (props.target) {\r\n transform.value = targetRect.top\r\n fixed.value = wrapperRect.top < targetRect.top + props.offset\r\n } else {\r\n fixed.value = props.offset > wrapperRect.top\r\n }\r\n } else {\r\n if (props.target) {\r\n transform.value = clientHeight.value - targetRect.bottom\r\n fixed.value = targetRect.bottom < props.offset + wrapperRect.bottom\r\n } else {\r\n fixed.value = clientHeight.value - props.offset < wrapperRect.bottom\r\n }\r\n }\r\n}\r\n\r\nfunction handleContainerScroll() {\r\n handleLastScroller(target)\r\n update()\r\n\r\n emitEvent(props.onScroll, {\r\n scrollTop: scrollTop.value,\r\n fixed: fixed.value,\r\n })\r\n}\r\n\r\nfunction updateContainer() {\r\n removeListener()\r\n\r\n if (!isClient) return\r\n\r\n if (props.target) {\r\n container.value = target.value!\r\n container.value.addEventListener('scroll', handleContainerScroll)\r\n } else {\r\n let _container: ComponentInternalInstance | null = instance.parent!\r\n const refName = 'scroll'\r\n\r\n while (_container) {\r\n const name = _container.type?.name\r\n\r\n if (name === 'Scroll' || name === 'NativeScroll') {\r\n const { exposeProxy, exposed, proxy } = _container\r\n const _scroller = new Proxy({} as any, {\r\n get(_, key) {\r\n return (proxy as any)?.[key] ?? (exposeProxy as any)?.[key] ?? (exposed as any)?.[key]\r\n },\r\n })\r\n const scrollerEl = _scroller?.$el as HTMLElement\r\n\r\n if (!scrollerEl.getAttribute('class')?.includes('vxp-native-scroll--horizontal')) {\r\n scroller = _scroller\r\n break\r\n }\r\n }\r\n\r\n const refTemp = _container.refs?.[refName]\r\n\r\n if (refTemp) {\r\n if (isElement(refTemp)) {\r\n isRawViewer = true\r\n container.value = refTemp as HTMLElement\r\n } else {\r\n scroller = refTemp as ScrollType\r\n }\r\n\r\n break\r\n }\r\n\r\n _container = _container.parent\r\n }\r\n\r\n if (scroller) {\r\n scroller.addScrollListener(handleContainerScroll)\r\n container.value = scroller.$el\r\n } else if (!container.value) {\r\n isRawViewer = true\r\n container.value = window\r\n }\r\n\r\n if (isRawViewer && container.value) {\r\n container.value.addEventListener('scroll', handleContainerScroll)\r\n }\r\n }\r\n}\r\n\r\nfunction removeListener() {\r\n if (scroller) {\r\n scroller.removeScrollListener(handleContainerScroll)\r\n scroller = null\r\n }\r\n\r\n if (container.value) {\r\n container.value.removeEventListener('scroll', handleContainerScroll)\r\n container.value = undefined\r\n }\r\n\r\n clearLastScroller(target)\r\n}\r\n</script>\r\n\r\n<template>\r\n <div ref=\"wrapper\" :class=\"nh.b()\" :style=\"affixStyle\">\r\n <div :class=\"{ [nh.bm('fixed')]: fixed }\" :style=\"fixedStyle\">\r\n <slot></slot>\r\n </div>\r\n </div>\r\n</template>\r\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","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_renderSlot","_ctx"],"mappings":"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"}