@will-ui/vue 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/components/btn/Btn.d.ts +4 -7
  2. package/dist/components/btn/Btn.js +1 -0
  3. package/dist/components/btn/Btn.js.map +1 -1
  4. package/dist/components/cascade/Cascade.d.ts +1 -1
  5. package/dist/components/choose/Choose.d.ts +4 -2
  6. package/dist/components/choose2/Choose2.d.ts +1 -1
  7. package/dist/components/confirm/index.d.ts +3 -4
  8. package/dist/components/confirm/index.js.map +1 -1
  9. package/dist/components/copy/Copy.d.ts +8 -8
  10. package/dist/components/copy/Copy.js +3 -2
  11. package/dist/components/copy/Copy.js.map +1 -1
  12. package/dist/components/cornerEars/CornerEars.d.ts +4 -7
  13. package/dist/components/cornerEars/CornerEars.js +1 -0
  14. package/dist/components/cornerEars/CornerEars.js.map +1 -1
  15. package/dist/components/date/DatePanel.d.ts +4 -0
  16. package/dist/components/date/DatePanel.js +2 -2
  17. package/dist/components/date/DatePanel.js.map +1 -1
  18. package/dist/components/date/DatePicker.d.ts +1 -1
  19. package/dist/components/date/DatePicker.js +4 -4
  20. package/dist/components/date/DatePicker.js.map +1 -1
  21. package/dist/components/date/Days.d.ts +2 -4
  22. package/dist/components/date/Days.js +1 -3
  23. package/dist/components/date/Days.js.map +1 -1
  24. package/dist/components/date/Months.d.ts +2 -4
  25. package/dist/components/date/Months.js +1 -3
  26. package/dist/components/date/Months.js.map +1 -1
  27. package/dist/components/date/QuickDate.d.ts +2 -12
  28. package/dist/components/date/QuickDate.js +1 -1
  29. package/dist/components/date/QuickDate.js.map +1 -1
  30. package/dist/components/date/Years.d.ts +3 -6
  31. package/dist/components/date/Years.js +1 -8
  32. package/dist/components/date/Years.js.map +1 -1
  33. package/dist/components/form/_use/formRules.d.ts +1 -1
  34. package/dist/components/form/_use/formRules.js.map +1 -1
  35. package/dist/components/formItem/FormItem.js.map +1 -1
  36. package/dist/components/image/Image.d.ts +5 -7
  37. package/dist/components/image/Image.js +3 -2
  38. package/dist/components/image/Image.js.map +1 -1
  39. package/dist/components/index.js +9 -9
  40. package/dist/components/modal/Modal.d.ts +1 -1
  41. package/dist/components/modal/Modal.js +29 -24
  42. package/dist/components/modal/Modal.js.map +1 -1
  43. package/dist/components/notice/src/_util/index.d.ts +1 -1
  44. package/dist/components/notice/src/_util/index.js.map +1 -1
  45. package/dist/components/number/Number copy.d.ts +1 -1
  46. package/dist/components/number/Number.d.ts +1 -1
  47. package/dist/components/pagination/src/Pagination.d.ts +6 -4
  48. package/dist/components/picture/Picture.d.ts +5 -7
  49. package/dist/components/picture/Picture.js +6 -5
  50. package/dist/components/picture/Picture.js.map +1 -1
  51. package/dist/components/picture/PictureViewport.js +22 -32
  52. package/dist/components/picture/PictureViewport.js.map +1 -1
  53. package/dist/components/progress/Progress.d.ts +1 -1
  54. package/dist/components/scrollbar/Scrollbar.js +61 -78
  55. package/dist/components/scrollbar/Scrollbar.js.map +1 -1
  56. package/dist/components/sheet/Sheet.d.ts +3 -1
  57. package/dist/components/sheet/_cell.js +16 -27
  58. package/dist/components/sheet/_cell.js.map +1 -1
  59. package/dist/components/slider/Slider.d.ts +2 -2
  60. package/dist/components/slider/Slider.js +24 -41
  61. package/dist/components/slider/Slider.js.map +1 -1
  62. package/dist/components/tab/Tab.d.ts +3 -3
  63. package/dist/components/tab/Tab.js +6 -0
  64. package/dist/components/tab/Tab.js.map +1 -1
  65. package/dist/components/textarea/Textarea.d.ts +5 -13
  66. package/dist/components/textarea/Textarea.js +3 -2
  67. package/dist/components/textarea/Textarea.js.map +1 -1
  68. package/dist/components/time/Dial.js.map +1 -1
  69. package/dist/components/time/Dial.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/time/TimePicker.d.ts +14 -2
  71. package/dist/components/tree-choose/TreeChoose.d.ts +1 -1
  72. package/dist/components/tree-choose/TreeChoose.js.map +1 -1
  73. package/dist/components/virtual/Virtual.d.ts +5 -5
  74. package/dist/components/virtual/Virtual.js +6 -0
  75. package/dist/components/virtual/Virtual.js.map +1 -1
  76. package/dist/index.d.ts +20 -15
  77. package/dist/index.js +6 -5
  78. package/dist/use/index.d.ts +2 -0
  79. package/dist/use/useChildComponentsCollector.d.ts +5 -0
  80. package/dist/use/useChildComponentsCollector.js.map +1 -1
  81. package/dist/use/usePercentDrag.d.ts +1 -1
  82. package/dist/use/usePercentDrag.js +19 -29
  83. package/dist/use/usePercentDrag.js.map +1 -1
  84. package/dist/use/usePointerDrag.d.ts +50 -0
  85. package/dist/use/usePointerDrag.js +143 -0
  86. package/dist/use/usePointerDrag.js.map +1 -0
  87. package/dist/use/useUII18n.d.ts +10 -0
  88. package/dist/use/useUII18n.js.map +1 -1
  89. package/dist/use/useUpload.js +1 -1
  90. package/dist/use/useUpload.js.map +1 -1
  91. package/package.json +79 -88
  92. package/dist/use/useDrag.d.ts +0 -17
@@ -1 +1 @@
1
- {"version":3,"file":"PictureViewport.js","names":["computed","defineComponent","onBeforeUnmount","onMounted","ref","shallowRef","watch","createVNode","_createVNode","createPictureViewport","PICTURE_VIEWPORT_ZOOM_STEP","useVisibleResize","PictureViewport","name","props","src","type","String","required","interact","Boolean","default","controller","Object","undefined","setup","expose","rootRef","wrapRef","imgRef","transformCss","useTransition","ready","dragging","canPan","natural","w","h","localApi","api","dragLast","unsub","syncFromApi","a","value","consumeTransition","getTransform","bindSubscribe","subscribe","measureViewport","el","width","height","getBoundingClientRect","setViewportSize","onImgLoad","img","naturalWidth","naturalHeight","setNaturalSize","prev","prepareImageChange","pointerFromCenter","clientX","clientY","x","y","r","left","top","onWheel","e","preventDefault","stopPropagation","factor","deltaY","p","zoomAt","onPointerDown","button","currentTarget","setPointerCapture","pointerId","onPointerMove","dx","dy","panBy","onPointerUp","releasePointerCapture","complete","methods","reset","fit","withTransition","oneToOne","zoomBy","rotateBy","delta","flip","axis","getFlipEl","getApi","rootClass","transform"],"sources":["../../../components/picture/PictureViewport.tsx"],"sourcesContent":["import {\r\n computed,\r\n defineComponent,\r\n onBeforeUnmount,\r\n onMounted,\r\n ref,\r\n shallowRef,\r\n watch,\r\n type PropType,\r\n} from 'vue'\r\nimport {\r\n createPictureViewport,\r\n PICTURE_VIEWPORT_ZOOM_STEP,\r\n type UsePictureViewport,\r\n} from '../../use/usePictureViewport'\r\nimport useVisibleResize from '../../use/useVisibleResize'\r\n\r\nexport type PictureViewportMethods = {\r\n reset: () => void\r\n fit: (withTransition?: boolean) => void\r\n oneToOne: () => void\r\n zoomBy: (factor: number) => void\r\n rotateBy: (delta: number) => void\r\n flip: (axis: 'x' | 'y') => void\r\n getFlipEl: () => HTMLElement | undefined\r\n getApi: () => UsePictureViewport\r\n}\r\n\r\nconst PictureViewport = defineComponent({\r\n name: 'PictureViewport',\r\n props: {\r\n src: { type: String, required: true },\r\n /** FLIP 结束后才为 true */\r\n interact: { type: Boolean, default: false },\r\n /** 与 Picture 共享,切图时保留缩放/旋转/翻转 */\r\n controller: {\r\n type: Object as PropType<UsePictureViewport>,\r\n default: undefined,\r\n },\r\n },\r\n setup(props, { expose }) {\r\n const rootRef = ref<HTMLElement>()\r\n const wrapRef = ref<HTMLElement>()\r\n const imgRef = ref<HTMLImageElement>()\r\n const transformCss = ref('translate(0px, 0px) rotate(0deg) scale(1, 1)')\r\n const useTransition = ref(false)\r\n const ready = ref(false)\r\n const dragging = ref(false)\r\n const canPan = ref(false)\r\n const natural = shallowRef({ w: 0, h: 0 })\r\n\r\n const localApi = createPictureViewport()\r\n const api = () => props.controller ?? localApi\r\n let dragLast: { x: number; y: number } | null = null\r\n let unsub: (() => void) | undefined\r\n\r\n const syncFromApi = () => {\r\n const a = api()\r\n useTransition.value = a.consumeTransition()\r\n transformCss.value = a.getTransform()\r\n canPan.value = a.canPan()\r\n }\r\n\r\n function bindSubscribe() {\r\n unsub?.()\r\n unsub = api().subscribe(syncFromApi)\r\n syncFromApi()\r\n }\r\n\r\n bindSubscribe()\r\n watch(\r\n () => props.controller,\r\n () => bindSubscribe(),\r\n )\r\n\r\n function measureViewport() {\r\n const el = rootRef.value\r\n if (!el) return\r\n const { width, height } = el.getBoundingClientRect()\r\n if (width < 1 || height < 1) return\r\n api().setViewportSize(width, height)\r\n syncFromApi()\r\n }\r\n\r\n useVisibleResize(rootRef, () => {\r\n measureViewport()\r\n })\r\n\r\n function onImgLoad() {\r\n const img = imgRef.value\r\n if (!img) return\r\n const w = img.naturalWidth\r\n const h = img.naturalHeight\r\n if (w < 1 || h < 1) return\r\n natural.value = { w, h }\r\n measureViewport()\r\n api().setNaturalSize(w, h)\r\n ready.value = true\r\n syncFromApi()\r\n }\r\n\r\n watch(\r\n () => props.src,\r\n (src, prev) => {\r\n if (prev == null || prev === src) return\r\n ready.value = false\r\n api().prepareImageChange()\r\n syncFromApi()\r\n },\r\n )\r\n\r\n function pointerFromCenter(clientX: number, clientY: number) {\r\n const el = rootRef.value\r\n if (!el) return { x: 0, y: 0 }\r\n const r = el.getBoundingClientRect()\r\n return {\r\n x: clientX - (r.left + r.width / 2),\r\n y: clientY - (r.top + r.height / 2),\r\n }\r\n }\r\n\r\n function onWheel(e: WheelEvent) {\r\n if (!props.interact || !ready.value) return\r\n e.preventDefault()\r\n e.stopPropagation()\r\n const factor =\r\n e.deltaY < 0\r\n ? PICTURE_VIEWPORT_ZOOM_STEP\r\n : 1 / PICTURE_VIEWPORT_ZOOM_STEP\r\n const p = pointerFromCenter(e.clientX, e.clientY)\r\n api().zoomAt(p.x, p.y, factor)\r\n }\r\n\r\n function onPointerDown(e: PointerEvent) {\r\n if (!props.interact || !ready.value) return\r\n if (e.button !== 0) return\r\n if (!api().canPan()) return\r\n e.preventDefault()\r\n dragging.value = true\r\n dragLast = { x: e.clientX, y: e.clientY }\r\n ;(e.currentTarget as HTMLElement).setPointerCapture?.(e.pointerId)\r\n }\r\n\r\n function onPointerMove(e: PointerEvent) {\r\n if (!dragging.value || !dragLast) return\r\n const dx = e.clientX - dragLast.x\r\n const dy = e.clientY - dragLast.y\r\n dragLast = { x: e.clientX, y: e.clientY }\r\n api().panBy(dx, dy)\r\n }\r\n\r\n function onPointerUp(e: PointerEvent) {\r\n if (!dragging.value) return\r\n dragging.value = false\r\n dragLast = null\r\n try {\r\n ;(e.currentTarget as HTMLElement).releasePointerCapture?.(e.pointerId)\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n measureViewport()\r\n if (imgRef.value?.complete) onImgLoad()\r\n })\r\n\r\n onBeforeUnmount(() => {\r\n unsub?.()\r\n })\r\n\r\n const methods: PictureViewportMethods = {\r\n reset: () => {\r\n api().reset()\r\n syncFromApi()\r\n },\r\n fit: (withTransition = true) => {\r\n api().fit(withTransition)\r\n syncFromApi()\r\n },\r\n oneToOne: () => {\r\n api().oneToOne(true)\r\n syncFromApi()\r\n },\r\n zoomBy: (factor) => {\r\n api().zoomBy(factor)\r\n syncFromApi()\r\n },\r\n rotateBy: (delta) => {\r\n api().rotateBy(delta)\r\n syncFromApi()\r\n },\r\n flip: (axis) => {\r\n api().flip(axis)\r\n syncFromApi()\r\n },\r\n getFlipEl: () => wrapRef.value,\r\n getApi: () => api(),\r\n }\r\n\r\n expose(methods)\r\n\r\n const rootClass = computed(() => [\r\n 'w-picture-viewer__viewport',\r\n {\r\n 'is-panning': props.interact && canPan.value,\r\n 'is-dragging': dragging.value,\r\n },\r\n ])\r\n\r\n return () => (\r\n <div\r\n ref={rootRef}\r\n class={rootClass.value}\r\n onWheel={onWheel}\r\n onPointerdown={onPointerDown}\r\n onPointermove={onPointerMove}\r\n onPointerup={onPointerUp}\r\n onPointercancel={onPointerUp}>\r\n <div ref={wrapRef} class=\"w-picture-viewer__img-wrap\">\r\n <div\r\n class={[\r\n 'w-picture-viewer__transform',\r\n { 'is-transition': useTransition.value },\r\n ]}\r\n style={\r\n ready.value ? { transform: transformCss.value } : undefined\r\n }>\r\n <img\r\n ref={imgRef}\r\n class={[\r\n 'w-picture-viewer__img',\r\n { 'is-fit-css': !ready.value },\r\n ]}\r\n src={props.src}\r\n alt=\"\"\r\n draggable={false}\r\n width={ready.value && natural.value.w ? natural.value.w : undefined}\r\n height={\r\n ready.value && natural.value.h ? natural.value.h : undefined\r\n }\r\n onLoad={onImgLoad}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n },\r\n})\r\n\r\nexport default PictureViewport\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"PictureViewport.js","names":["computed","defineComponent","onBeforeUnmount","onMounted","ref","shallowRef","watch","createVNode","_createVNode","createPictureViewport","PICTURE_VIEWPORT_ZOOM_STEP","usePointerDrag","useVisibleResize","PictureViewport","name","props","src","type","String","required","interact","Boolean","default","controller","Object","undefined","setup","expose","rootRef","wrapRef","imgRef","transformCss","useTransition","ready","canPan","natural","w","h","localApi","api","unsub","syncFromApi","a","value","consumeTransition","getTransform","bindSubscribe","subscribe","measureViewport","el","width","height","getBoundingClientRect","setViewportSize","onImgLoad","img","naturalWidth","naturalHeight","setNaturalSize","prev","prepareImageChange","pointerFromCenter","clientX","clientY","x","y","r","left","top","onWheel","e","preventDefault","stopPropagation","factor","deltaY","p","zoomAt","dragging","onPointerDown","onPointerMove","onPointerUp","events","bind","disabled","onStart","ctx","button","data","lastX","lastY","onMove","dx","dy","panBy","complete","methods","reset","fit","withTransition","oneToOne","zoomBy","rotateBy","delta","flip","axis","getFlipEl","getApi","rootClass","transform"],"sources":["../../../components/picture/PictureViewport.tsx"],"sourcesContent":["import {\r\n computed,\r\n defineComponent,\r\n onBeforeUnmount,\r\n onMounted,\r\n ref,\r\n shallowRef,\r\n watch,\r\n type PropType,\r\n} from 'vue'\r\nimport {\r\n createPictureViewport,\r\n PICTURE_VIEWPORT_ZOOM_STEP,\r\n type UsePictureViewport,\r\n} from '../../use/usePictureViewport'\r\nimport usePointerDrag from '../../use/usePointerDrag'\r\nimport useVisibleResize from '../../use/useVisibleResize'\r\n\r\nexport type PictureViewportMethods = {\r\n reset: () => void\r\n fit: (withTransition?: boolean) => void\r\n oneToOne: () => void\r\n zoomBy: (factor: number) => void\r\n rotateBy: (delta: number) => void\r\n flip: (axis: 'x' | 'y') => void\r\n getFlipEl: () => HTMLElement | undefined\r\n getApi: () => UsePictureViewport\r\n}\r\n\r\nconst PictureViewport = defineComponent({\r\n name: 'PictureViewport',\r\n props: {\r\n src: { type: String, required: true },\r\n /** FLIP 结束后才为 true */\r\n interact: { type: Boolean, default: false },\r\n /** 与 Picture 共享,切图时保留缩放/旋转/翻转 */\r\n controller: {\r\n type: Object as PropType<UsePictureViewport>,\r\n default: undefined,\r\n },\r\n },\r\n setup(props, { expose }) {\r\n const rootRef = ref<HTMLElement>()\r\n const wrapRef = ref<HTMLElement>()\r\n const imgRef = ref<HTMLImageElement>()\r\n const transformCss = ref('translate(0px, 0px) rotate(0deg) scale(1, 1)')\r\n const useTransition = ref(false)\r\n const ready = ref(false)\r\n const canPan = ref(false)\r\n const natural = shallowRef({ w: 0, h: 0 })\r\n\r\n const localApi = createPictureViewport()\r\n const api = () => props.controller ?? localApi\r\n let unsub: (() => void) | undefined\r\n\r\n const syncFromApi = () => {\r\n const a = api()\r\n useTransition.value = a.consumeTransition()\r\n transformCss.value = a.getTransform()\r\n canPan.value = a.canPan()\r\n }\r\n\r\n function bindSubscribe() {\r\n unsub?.()\r\n unsub = api().subscribe(syncFromApi)\r\n syncFromApi()\r\n }\r\n\r\n bindSubscribe()\r\n watch(\r\n () => props.controller,\r\n () => bindSubscribe(),\r\n )\r\n\r\n function measureViewport() {\r\n const el = rootRef.value\r\n if (!el) return\r\n const { width, height } = el.getBoundingClientRect()\r\n if (width < 1 || height < 1) return\r\n api().setViewportSize(width, height)\r\n syncFromApi()\r\n }\r\n\r\n useVisibleResize(rootRef, () => {\r\n measureViewport()\r\n })\r\n\r\n function onImgLoad() {\r\n const img = imgRef.value\r\n if (!img) return\r\n const w = img.naturalWidth\r\n const h = img.naturalHeight\r\n if (w < 1 || h < 1) return\r\n natural.value = { w, h }\r\n measureViewport()\r\n api().setNaturalSize(w, h)\r\n ready.value = true\r\n syncFromApi()\r\n }\r\n\r\n watch(\r\n () => props.src,\r\n (src, prev) => {\r\n if (prev == null || prev === src) return\r\n ready.value = false\r\n api().prepareImageChange()\r\n syncFromApi()\r\n },\r\n )\r\n\r\n function pointerFromCenter(clientX: number, clientY: number) {\r\n const el = rootRef.value\r\n if (!el) return { x: 0, y: 0 }\r\n const r = el.getBoundingClientRect()\r\n return {\r\n x: clientX - (r.left + r.width / 2),\r\n y: clientY - (r.top + r.height / 2),\r\n }\r\n }\r\n\r\n function onWheel(e: WheelEvent) {\r\n if (!props.interact || !ready.value) return\r\n e.preventDefault()\r\n e.stopPropagation()\r\n const factor =\r\n e.deltaY < 0\r\n ? PICTURE_VIEWPORT_ZOOM_STEP\r\n : 1 / PICTURE_VIEWPORT_ZOOM_STEP\r\n const p = pointerFromCenter(e.clientX, e.clientY)\r\n api().zoomAt(p.x, p.y, factor)\r\n }\r\n\r\n // 平移用「相对上一帧」增量,与原先 dragLast 一致(非相对 start)\r\n const {\r\n dragging,\r\n onPointerDown,\r\n onPointerMove,\r\n onPointerUp,\r\n } = usePointerDrag({\r\n events: 'pointer',\r\n bind: 'capture',\r\n disabled: () => !props.interact || !ready.value,\r\n onStart: (e, ctx) => {\r\n if (e.button !== 0) return false\r\n if (!api().canPan()) return false\r\n e.preventDefault()\r\n ctx.data.lastX = e.clientX\r\n ctx.data.lastY = e.clientY\r\n },\r\n onMove: (e, ctx) => {\r\n const lastX = ctx.data.lastX as number\r\n const lastY = ctx.data.lastY as number\r\n const dx = e.clientX - lastX\r\n const dy = e.clientY - lastY\r\n ctx.data.lastX = e.clientX\r\n ctx.data.lastY = e.clientY\r\n api().panBy(dx, dy)\r\n },\r\n })\r\n\r\n onMounted(() => {\r\n measureViewport()\r\n if (imgRef.value?.complete) onImgLoad()\r\n })\r\n\r\n onBeforeUnmount(() => {\r\n unsub?.()\r\n })\r\n\r\n const methods: PictureViewportMethods = {\r\n reset: () => {\r\n api().reset()\r\n syncFromApi()\r\n },\r\n fit: (withTransition = true) => {\r\n api().fit(withTransition)\r\n syncFromApi()\r\n },\r\n oneToOne: () => {\r\n api().oneToOne(true)\r\n syncFromApi()\r\n },\r\n zoomBy: (factor) => {\r\n api().zoomBy(factor)\r\n syncFromApi()\r\n },\r\n rotateBy: (delta) => {\r\n api().rotateBy(delta)\r\n syncFromApi()\r\n },\r\n flip: (axis) => {\r\n api().flip(axis)\r\n syncFromApi()\r\n },\r\n getFlipEl: () => wrapRef.value,\r\n getApi: () => api(),\r\n }\r\n\r\n expose(methods)\r\n\r\n const rootClass = computed(() => [\r\n 'w-picture-viewer__viewport',\r\n {\r\n 'is-panning': props.interact && canPan.value,\r\n 'is-dragging': dragging.value,\r\n },\r\n ])\r\n\r\n return () => (\r\n <div\r\n ref={rootRef}\r\n class={rootClass.value}\r\n onWheel={onWheel}\r\n onPointerdown={onPointerDown}\r\n onPointermove={onPointerMove}\r\n onPointerup={onPointerUp}\r\n onPointercancel={onPointerUp}>\r\n <div ref={wrapRef} class=\"w-picture-viewer__img-wrap\">\r\n <div\r\n class={[\r\n 'w-picture-viewer__transform',\r\n { 'is-transition': useTransition.value },\r\n ]}\r\n style={\r\n ready.value ? { transform: transformCss.value } : undefined\r\n }>\r\n <img\r\n ref={imgRef}\r\n class={[\r\n 'w-picture-viewer__img',\r\n { 'is-fit-css': !ready.value },\r\n ]}\r\n src={props.src}\r\n alt=\"\"\r\n draggable={false}\r\n width={ready.value && natural.value.w ? natural.value.w : undefined}\r\n height={\r\n ready.value && natural.value.h ? natural.value.h : undefined\r\n }\r\n onLoad={onImgLoad}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n },\r\n})\r\n\r\nexport default PictureViewport\r\n"],"mappings":"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"}
@@ -79,8 +79,8 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
79
79
  }>> & Readonly<{
80
80
  onChange?: (value: number) => any;
81
81
  "onUpdate:modelValue"?: (value: number) => any;
82
- "onDrag-start"?: (value: number) => any;
83
82
  onDragging?: (value: number) => any;
83
+ "onDrag-start"?: (value: number) => any;
84
84
  "onDrag-end"?: (value: number) => any;
85
85
  }>, {
86
86
  size: number;
@@ -1,5 +1,6 @@
1
1
  import { isInvisible } from "../../util/dom.js";
2
2
  import useVisibleResize from "../../use/useVisibleResize.js";
3
+ import usePointerDrag from "../../use/usePointerDrag.js";
3
4
  import { computed, createVNode, defineComponent, nextTick, onMounted, onUnmounted, ref, watch } from "vue";
4
5
  //#region components/scrollbar/Scrollbar.tsx
5
6
  function toCssSize(v) {
@@ -68,12 +69,6 @@ var Scrollbar_default = /* @__PURE__ */ defineComponent({
68
69
  const contentWidth = ref(0);
69
70
  const vTrackHeight = ref(0);
70
71
  const hTrackWidth = ref(0);
71
- const isDraggingV = ref(false);
72
- const isDraggingH = ref(false);
73
- const dragStartY = ref(0);
74
- const dragStartX = ref(0);
75
- const dragStartScrollTop = ref(0);
76
- const dragStartScrollLeft = ref(0);
77
72
  const justDragged = ref(false);
78
73
  const isProgrammaticScroll = ref(false);
79
74
  const lastIsTop = ref(false);
@@ -299,78 +294,66 @@ var Scrollbar_default = /* @__PURE__ */ defineComponent({
299
294
  const targetScrollLeft = leftPercent !== void 0 ? Math.max(0, Math.min(leftPercent / 100 * maxScrollLeft, maxScrollLeft)) : scrollLeft.value;
300
295
  scrollTo(targetScrollTop, targetScrollLeft);
301
296
  };
302
- const handleVThumbMouseDown = (e) => {
303
- e.preventDefault();
304
- e.stopPropagation();
305
- isDraggingV.value = true;
306
- dragStartY.value = e.clientY;
307
- dragStartScrollTop.value = scrollTop.value;
308
- if (containerRef.value) containerRef.value.style.scrollBehavior = "auto";
309
- document.addEventListener("mousemove", handleVThumbMouseMove);
310
- document.addEventListener("mouseup", handleVThumbMouseUp);
311
- document.body.style.userSelect = "none";
312
- document.body.style.cursor = "grabbing";
313
- };
314
- const handleVThumbMouseMove = (e) => {
315
- if (!isDraggingV.value || !containerRef.value) return;
316
- e.preventDefault();
317
- const deltaY = e.clientY - dragStartY.value;
318
- const maxScroll = contentHeight.value - containerHeight.value;
319
- if (maxScroll <= 0 || vTrackHeight.value <= 0) return;
320
- const maxThumbMove = vTrackHeight.value - vThumbHeight.value;
321
- const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1;
322
- const newScrollTop = dragStartScrollTop.value + deltaY * scrollRatio;
323
- const clampedScrollTop = Math.max(0, Math.min(newScrollTop, maxScroll));
324
- containerRef.value.scrollTop = clampedScrollTop;
325
- };
326
- const handleVThumbMouseUp = () => {
327
- isDraggingV.value = false;
328
- if (containerRef.value) containerRef.value.style.scrollBehavior = "";
329
- document.removeEventListener("mousemove", handleVThumbMouseMove);
330
- document.removeEventListener("mouseup", handleVThumbMouseUp);
331
- document.body.style.userSelect = "";
332
- document.body.style.cursor = "";
333
- justDragged.value = true;
334
- setTimeout(() => {
335
- justDragged.value = false;
336
- }, 0);
337
- };
338
- const handleHThumbMouseDown = (e) => {
339
- e.preventDefault();
340
- e.stopPropagation();
341
- isDraggingH.value = true;
342
- dragStartX.value = e.clientX;
343
- dragStartScrollLeft.value = scrollLeft.value;
344
- if (containerRef.value) containerRef.value.style.scrollBehavior = "auto";
345
- document.addEventListener("mousemove", handleHThumbMouseMove);
346
- document.addEventListener("mouseup", handleHThumbMouseUp);
347
- document.body.style.userSelect = "none";
348
- document.body.style.cursor = "grabbing";
349
- };
350
- const handleHThumbMouseMove = (e) => {
351
- if (!isDraggingH.value || !containerRef.value) return;
352
- e.preventDefault();
353
- const deltaX = e.clientX - dragStartX.value;
354
- const maxScroll = contentWidth.value - containerWidth.value;
355
- if (maxScroll <= 0 || hTrackWidth.value <= 0) return;
356
- const maxThumbMove = hTrackWidth.value - hThumbWidth.value;
357
- const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1;
358
- const newScrollLeft = dragStartScrollLeft.value + deltaX * scrollRatio;
359
- const clampedScrollLeft = Math.max(0, Math.min(newScrollLeft, maxScroll));
360
- containerRef.value.scrollLeft = clampedScrollLeft;
361
- };
362
- const handleHThumbMouseUp = () => {
363
- isDraggingH.value = false;
364
- if (containerRef.value) containerRef.value.style.scrollBehavior = "";
365
- document.removeEventListener("mousemove", handleHThumbMouseMove);
366
- document.removeEventListener("mouseup", handleHThumbMouseUp);
367
- document.body.style.userSelect = "";
368
- document.body.style.cursor = "";
369
- justDragged.value = true;
370
- setTimeout(() => {
371
- justDragged.value = false;
372
- }, 0);
373
- };
297
+ const { dragging: isDraggingV, onMouseDown: handleVThumbMouseDown } = usePointerDrag({
298
+ events: "mouse",
299
+ bind: "document",
300
+ cursor: "grabbing",
301
+ lockUserSelect: true,
302
+ onStart: (e, ctx) => {
303
+ e.preventDefault();
304
+ e.stopPropagation();
305
+ ctx.data.scrollStart = scrollTop.value;
306
+ if (containerRef.value) containerRef.value.style.scrollBehavior = "auto";
307
+ },
308
+ onMove: (e, ctx) => {
309
+ if (!containerRef.value) return;
310
+ e.preventDefault();
311
+ const deltaY = e.clientY - ctx.startY;
312
+ const maxScroll = contentHeight.value - containerHeight.value;
313
+ if (maxScroll <= 0 || vTrackHeight.value <= 0) return;
314
+ const maxThumbMove = vTrackHeight.value - vThumbHeight.value;
315
+ const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1;
316
+ const newScrollTop = ctx.data.scrollStart + deltaY * scrollRatio;
317
+ containerRef.value.scrollTop = Math.max(0, Math.min(newScrollTop, maxScroll));
318
+ },
319
+ onEnd: () => {
320
+ if (containerRef.value) containerRef.value.style.scrollBehavior = "";
321
+ justDragged.value = true;
322
+ setTimeout(() => {
323
+ justDragged.value = false;
324
+ }, 0);
325
+ }
326
+ });
327
+ const { dragging: isDraggingH, onMouseDown: handleHThumbMouseDown } = usePointerDrag({
328
+ events: "mouse",
329
+ bind: "document",
330
+ cursor: "grabbing",
331
+ lockUserSelect: true,
332
+ onStart: (e, ctx) => {
333
+ e.preventDefault();
334
+ e.stopPropagation();
335
+ ctx.data.scrollStart = scrollLeft.value;
336
+ if (containerRef.value) containerRef.value.style.scrollBehavior = "auto";
337
+ },
338
+ onMove: (e, ctx) => {
339
+ if (!containerRef.value) return;
340
+ e.preventDefault();
341
+ const deltaX = e.clientX - ctx.startX;
342
+ const maxScroll = contentWidth.value - containerWidth.value;
343
+ if (maxScroll <= 0 || hTrackWidth.value <= 0) return;
344
+ const maxThumbMove = hTrackWidth.value - hThumbWidth.value;
345
+ const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1;
346
+ const newScrollLeft = ctx.data.scrollStart + deltaX * scrollRatio;
347
+ containerRef.value.scrollLeft = Math.max(0, Math.min(newScrollLeft, maxScroll));
348
+ },
349
+ onEnd: () => {
350
+ if (containerRef.value) containerRef.value.style.scrollBehavior = "";
351
+ justDragged.value = true;
352
+ setTimeout(() => {
353
+ justDragged.value = false;
354
+ }, 0);
355
+ }
356
+ });
374
357
  const handleVTrackClick = (e) => {
375
358
  if (!containerRef.value || isDraggingV.value || justDragged.value) return;
376
359
  const trackRect = vTrackRef.value?.getBoundingClientRect();
@@ -1 +1 @@
1
- {"version":3,"file":"Scrollbar.js","names":["defineComponent","ref","computed","watch","onMounted","onUnmounted","nextTick","createVNode","_createVNode","useVisibleResize","isInvisible","toCssSize","v","undefined","name","props","direction","type","String","default","scrollStep","Number","visible","Boolean","minHeight","maxHeight","height","smooth","minThumbSize","bottomOffset","emits","setup","slots","emit","expose","containerRef","contentRef","vTrackRef","vThumbRef","hTrackRef","hThumbRef","scrollTop","scrollLeft","containerHeight","contentHeight","containerWidth","contentWidth","vTrackHeight","hTrackWidth","isDraggingV","isDraggingH","dragStartY","dragStartX","dragStartScrollTop","dragStartScrollLeft","justDragged","isProgrammaticScroll","lastIsTop","lastIsBottom","resolveWheelDelta","e","dx","deltaX","dy","deltaY","deltaMode","WheelEvent","DOM_DELTA_LINE","DOM_DELTA_PAGE","el","value","clientWidth","clientHeight","vThumbHeight","ratio","thumbH","Math","min","max","hThumbWidth","thumbW","vThumbTop","maxScroll","maxThumbMove","result","hThumbLeft","showVertical","showHorizontal","updateSize","scrollHeight","scrollWidth","computedStyle","getComputedStyle","paddingTop","parseFloat","paddingBottom","newVTrackHeight","paddingLeft","paddingRight","newHTrackWidth","handleScroll","target","isTop","maxScrollTop","maxScrollLeft","threshold","isBottom","distance","scrollTopPercent","round","scrollLeftPercent","scrollBottom","scrollRight","wheelSmoothRestoreTimer","pauseCssSmoothForWheel","style","scrollBehavior","clearTimeout","window","setTimeout","handleWheel","dir","eps","maxTop","maxLeft","canY","canX","stopPropagation","DOM_DELTA_PIXEL","preventDefault","scrollTo","top","left","behavior","scrollOptions","lastScrollTop","lastScrollLeft","stableFrames","checkScrollComplete","currentScrollTop","currentScrollLeft","requestAnimationFrame","scrollToTop","scrollToBottom","scrollToElement","element","scrollIntoView","block","scrollToPercent","topPercent","leftPercent","targetScrollTop","targetScrollLeft","handleVThumbMouseDown","clientY","document","addEventListener","handleVThumbMouseMove","handleVThumbMouseUp","body","userSelect","cursor","scrollRatio","newScrollTop","clampedScrollTop","removeEventListener","handleHThumbMouseDown","clientX","handleHThumbMouseMove","handleHThumbMouseUp","newScrollLeft","clampedScrollLeft","handleVTrackClick","trackRect","getBoundingClientRect","clickY","thumbCenter","handleHTrackClick","clickX","touchStartY","touchStartX","touchStartScrollTop","touchStartScrollLeft","handleTouchStart","touch","touches","handleTouchMove","handleTouchEnd","passive","exposeMethods","getScrollPosition","width"],"sources":["../../../components/scrollbar/Scrollbar.tsx"],"sourcesContent":["import {\r\n defineComponent,\r\n ref,\r\n computed,\r\n watch,\r\n onMounted,\r\n onUnmounted,\r\n nextTick,\r\n} from \"vue\"\r\nimport type { PropType } from \"vue\"\r\nimport useVisibleResize from \"../../use/useVisibleResize\"\r\nimport { isInvisible } from \"../../util\"\r\n\r\nfunction toCssSize(\r\n v: string | number | undefined\r\n): string | number | undefined {\r\n if (v === undefined) return undefined\r\n return typeof v === \"number\" ? `${v}px` : v\r\n}\r\n\r\nexport default defineComponent({\r\n name: \"Scrollbar\",\r\n props: {\r\n // 滚动方向:y(垂直), x(水平), both(双向)\r\n direction: {\r\n type: String as PropType<\"y\" | \"x\" | \"both\">,\r\n default: \"y\",\r\n },\r\n // 点击轨道的步长(px);滚轮在像素模式下跟随系统,LINE 模式才用此步长\r\n scrollStep: {\r\n type: Number,\r\n default: 60,\r\n },\r\n // 是否显示滚动条\r\n visible: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n // 容器最小高度\r\n minHeight: {\r\n type: [String, Number],\r\n default: undefined,\r\n },\r\n // 容器最大高度\r\n maxHeight: {\r\n type: [String, Number],\r\n default: undefined,\r\n },\r\n // 容器高度\r\n height: {\r\n type: [String, Number],\r\n default: undefined,\r\n },\r\n // 是否启用平滑滚动\r\n smooth: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n // 滑块最小尺寸(单位:px),默认 30px,防止内容过长时滑块过小难以拖拽\r\n minThumbSize: {\r\n type: Number,\r\n default: 30,\r\n },\r\n // 触底偏移量(单位:px),当距离底部还有多少像素时触发触底事件,默认 0\r\n bottomOffset: {\r\n type: Number,\r\n default: 0,\r\n },\r\n },\r\n emits: [\"scroll\", \"scroll-start\", \"scroll-end\", \"reach-top\", \"reach-bottom\"],\r\n setup(props, { slots, emit, expose }) {\r\n // 容器引用\r\n const containerRef = ref<HTMLElement | null>(null)\r\n // 内容引用\r\n const contentRef = ref<HTMLElement | null>(null)\r\n // 垂直滚动条引用\r\n const vTrackRef = ref<HTMLElement | null>(null)\r\n const vThumbRef = ref<HTMLElement | null>(null)\r\n // 水平滚动条引用\r\n const hTrackRef = ref<HTMLElement | null>(null)\r\n const hThumbRef = ref<HTMLElement | null>(null)\r\n\r\n // 滚动状态\r\n const scrollTop = ref(0)\r\n const scrollLeft = ref(0)\r\n const containerHeight = ref(0)\r\n const contentHeight = ref(0)\r\n const containerWidth = ref(0)\r\n const contentWidth = ref(0)\r\n\r\n // 轨道实际尺寸(通过测量得到)\r\n const vTrackHeight = ref(0)\r\n const hTrackWidth = ref(0)\r\n\r\n // 拖拽状态\r\n const isDraggingV = ref(false)\r\n const isDraggingH = ref(false)\r\n const dragStartY = ref(0)\r\n const dragStartX = ref(0)\r\n const dragStartScrollTop = ref(0)\r\n const dragStartScrollLeft = ref(0)\r\n\r\n // 刚结束拖拽的标志(用于防止 mouseup 后触发 click 事件)\r\n const justDragged = ref(false)\r\n\r\n // 是否是编程式滚动(外部调用方法触发的滚动)\r\n const isProgrammaticScroll = ref(false)\r\n\r\n // 触顶/触底状态(用于避免重复触发)\r\n const lastIsTop = ref(false)\r\n const lastIsBottom = ref(false)\r\n\r\n /**\r\n * 将 wheel 增量转为实际滚动像素。\r\n * 像素模式保留原生 delta(交给浏览器惯性,保证丝滑);\r\n * LINE/PAGE 才映射为 scrollStep / 一页高度。\r\n */\r\n const resolveWheelDelta = (e: WheelEvent) => {\r\n let dx = e.deltaX\r\n let dy = e.deltaY\r\n if (e.deltaMode === WheelEvent.DOM_DELTA_LINE) {\r\n dx *= props.scrollStep\r\n dy *= props.scrollStep\r\n } else if (e.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\r\n const el = containerRef.value\r\n dx *= el?.clientWidth ?? 0\r\n dy *= el?.clientHeight ?? 0\r\n }\r\n return { dx, dy }\r\n }\r\n\r\n // 计算垂直滚动条滑块高度\r\n const vThumbHeight = computed(() => {\r\n if (contentHeight.value <= containerHeight.value) return 0\r\n\r\n // 滑块高度比例 = 可视区域 / 内容总高度\r\n const ratio = containerHeight.value / contentHeight.value\r\n\r\n // 滑块实际高度 = 轨道高度 × 比例\r\n const thumbH = vTrackHeight.value * ratio\r\n\r\n // 最小 minThumbSize px,最大不超过轨道高度\r\n return Math.min(Math.max(props.minThumbSize, thumbH), vTrackHeight.value)\r\n })\r\n\r\n // 计算水平滚动条滑块宽度\r\n const hThumbWidth = computed(() => {\r\n if (contentWidth.value <= containerWidth.value) return 0\r\n\r\n // 滑块宽度比例 = 可视区域 / 内容总宽度\r\n const ratio = containerWidth.value / contentWidth.value\r\n\r\n // 滑块实际宽度 = 轨道宽度 × 比例\r\n const thumbW = hTrackWidth.value * ratio\r\n\r\n // 最小 minThumbSize px,最大不超过轨道宽度\r\n return Math.min(Math.max(props.minThumbSize, thumbW), hTrackWidth.value)\r\n })\r\n\r\n // 计算垂直滚动条滑块位置\r\n const vThumbTop = computed(() => {\r\n if (contentHeight.value <= containerHeight.value) return 0\r\n const maxScroll = contentHeight.value - containerHeight.value\r\n if (maxScroll <= 0 || vTrackHeight.value <= 0) return 0\r\n\r\n const ratio = scrollTop.value / maxScroll\r\n\r\n // 滑块可移动的最大距离 = 轨道可用高度 - 滑块高度\r\n const maxThumbMove = vTrackHeight.value - vThumbHeight.value\r\n\r\n // 滑块位置(相对于轨道内容区域)\r\n const result = ratio * maxThumbMove\r\n\r\n // 确保在合理范围内\r\n return Math.max(0, Math.min(result, maxThumbMove))\r\n })\r\n\r\n // 计算水平滚动条滑块位置\r\n const hThumbLeft = computed(() => {\r\n if (contentWidth.value <= containerWidth.value) return 0\r\n const maxScroll = contentWidth.value - containerWidth.value\r\n if (maxScroll <= 0 || hTrackWidth.value <= 0) return 0\r\n\r\n const ratio = scrollLeft.value / maxScroll\r\n\r\n // 滑块可移动的最大距离 = 轨道可用宽度 - 滑块宽度\r\n const maxThumbMove = hTrackWidth.value - hThumbWidth.value\r\n\r\n // 滑块位置(相对于轨道内容区域)\r\n const result = ratio * maxThumbMove\r\n\r\n // 确保在合理范围内\r\n return Math.max(0, Math.min(result, maxThumbMove))\r\n })\r\n\r\n // 判断是否需要显示垂直滚动条\r\n const showVertical = computed(() => {\r\n return (\r\n props.visible &&\r\n (props.direction === \"y\" || props.direction === \"both\") &&\r\n contentHeight.value > containerHeight.value\r\n )\r\n })\r\n\r\n // 判断是否需要显示水平滚动条\r\n const showHorizontal = computed(() => {\r\n return (\r\n props.visible &&\r\n (props.direction === \"x\" || props.direction === \"both\") &&\r\n contentWidth.value > containerWidth.value\r\n )\r\n })\r\n\r\n // 更新尺寸信息\r\n const updateSize = () => {\r\n if (!containerRef.value || !contentRef.value) return\r\n if (isInvisible(containerRef.value)) return\r\n\r\n containerHeight.value = containerRef.value.clientHeight\r\n contentHeight.value = contentRef.value.scrollHeight\r\n containerWidth.value = containerRef.value.clientWidth\r\n contentWidth.value = contentRef.value.scrollWidth\r\n\r\n // 测量轨道实际尺寸(使用 offsetHeight/clientWidth 减去 padding,获取实际可移动区域)\r\n if (vTrackRef.value) {\r\n const computedStyle = getComputedStyle(vTrackRef.value)\r\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0\r\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0\r\n const newVTrackHeight =\r\n vTrackRef.value.clientHeight - paddingTop - paddingBottom\r\n if (newVTrackHeight > 0) {\r\n vTrackHeight.value = newVTrackHeight\r\n }\r\n }\r\n if (hTrackRef.value) {\r\n const computedStyle = getComputedStyle(hTrackRef.value)\r\n const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0\r\n const paddingRight = parseFloat(computedStyle.paddingRight) || 0\r\n const newHTrackWidth =\r\n hTrackRef.value.clientWidth - paddingLeft - paddingRight\r\n if (newHTrackWidth > 0) {\r\n hTrackWidth.value = newHTrackWidth\r\n }\r\n }\r\n }\r\n\r\n useVisibleResize(containerRef, updateSize)\r\n useVisibleResize(contentRef, updateSize)\r\n watch([showVertical, showHorizontal], () => {\r\n nextTick(updateSize)\r\n })\r\n\r\n // 处理滚动事件\r\n const handleScroll = (e: Event) => {\r\n const target = e.target as HTMLElement\r\n\r\n // 更新滚动位置(总是更新,包括拖拽时)\r\n scrollTop.value = target.scrollTop\r\n scrollLeft.value = target.scrollLeft\r\n\r\n // 检测触顶\r\n const isTop = target.scrollTop <= 0\r\n if (isTop && !lastIsTop.value) {\r\n emit(\"reach-top\")\r\n }\r\n lastIsTop.value = isTop\r\n\r\n // 检测触底(考虑偏移量)\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n const threshold = maxScrollTop - props.bottomOffset\r\n const isBottom = maxScrollTop > 0 && target.scrollTop >= threshold\r\n if (isBottom && !lastIsBottom.value) {\r\n emit(\"reach-bottom\", { distance: maxScrollTop - target.scrollTop })\r\n }\r\n lastIsBottom.value = isBottom\r\n\r\n // 计算滚动百分比(0-100)\r\n const scrollTopPercent =\r\n maxScrollTop > 0\r\n ? Math.round((target.scrollTop / maxScrollTop) * 100)\r\n : 0\r\n const scrollLeftPercent =\r\n maxScrollLeft > 0\r\n ? Math.round((target.scrollLeft / maxScrollLeft) * 100)\r\n : 0\r\n\r\n // 如果是编程式滚动,不触发 scroll 事件\r\n if (!isProgrammaticScroll.value) {\r\n emit(\"scroll\", {\r\n scrollTop: target.scrollTop,\r\n scrollLeft: target.scrollLeft,\r\n // 距离底部的距离(垂直)\r\n scrollBottom: maxScrollTop - target.scrollTop,\r\n // 距离右侧的距离(水平)\r\n scrollRight: maxScrollLeft - target.scrollLeft,\r\n // 滚动百分比(0-100)\r\n scrollTopPercent,\r\n scrollLeftPercent,\r\n target,\r\n })\r\n }\r\n }\r\n\r\n // 连续像素流期间临时关掉 CSS smooth,避免跟浏览器惯性打架\r\n let wheelSmoothRestoreTimer: number | null = null\r\n const pauseCssSmoothForWheel = (el: HTMLElement) => {\r\n el.style.scrollBehavior = \"auto\"\r\n if (wheelSmoothRestoreTimer) clearTimeout(wheelSmoothRestoreTimer)\r\n wheelSmoothRestoreTimer = window.setTimeout(() => {\r\n if (props.smooth) el.style.scrollBehavior = \"\"\r\n wheelSmoothRestoreTimer = null\r\n }, 150)\r\n }\r\n\r\n /**\r\n * 滚轮:\r\n * - 本层还能顺着滚 → stopPropagation,避免外层 Scrollbar 抢走\r\n * - 像素模式 → 不 preventDefault,保留系统惯性(触摸板 / 现代鼠标)\r\n * - LINE/PAGE → preventDefault + 按 scrollStep / 页高步进\r\n * - 已到边界 → 不拦截,交给外层链式滚动\r\n */\r\n const handleWheel = (e: WheelEvent) => {\r\n const el = containerRef.value\r\n if (!el) return\r\n\r\n const { dx, dy } = resolveWheelDelta(e)\r\n const dir = props.direction\r\n const eps = 0.5\r\n\r\n const maxTop = el.scrollHeight - el.clientHeight\r\n const maxLeft = el.scrollWidth - el.clientWidth\r\n const canY =\r\n (dir === \"y\" || dir === \"both\") &&\r\n maxTop > 0 &&\r\n dy !== 0 &&\r\n ((dy > 0 && el.scrollTop < maxTop - eps) ||\r\n (dy < 0 && el.scrollTop > eps))\r\n const canX =\r\n (dir === \"x\" || dir === \"both\") &&\r\n maxLeft > 0 &&\r\n dx !== 0 &&\r\n ((dx > 0 && el.scrollLeft < maxLeft - eps) ||\r\n (dx < 0 && el.scrollLeft > eps))\r\n\r\n if (!canY && !canX) return\r\n\r\n // 挡住外层 Scrollbar 的 wheel 监听,否则嵌套时内层滚不动\r\n e.stopPropagation()\r\n pauseCssSmoothForWheel(el)\r\n\r\n // 像素模式交给浏览器(含惯性);scrollStep 主要作用于轨道点击与 LINE 模式\r\n if (e.deltaMode === WheelEvent.DOM_DELTA_PIXEL) return\r\n\r\n e.preventDefault()\r\n if (canY) {\r\n el.scrollTop = Math.max(0, Math.min(maxTop, el.scrollTop + dy))\r\n }\r\n if (canX) {\r\n el.scrollLeft = Math.max(0, Math.min(maxLeft, el.scrollLeft + dx))\r\n }\r\n }\r\n\r\n // 滚动到指定位置\r\n const scrollTo = (top?: number, left?: number) => {\r\n if (!containerRef.value) return\r\n\r\n // 设置编程式滚动标志\r\n isProgrammaticScroll.value = true\r\n\r\n const behavior = props.smooth ? \"smooth\" : \"auto\"\r\n\r\n // 将 top 和 left 合并到一个调用中,避免覆盖\r\n const scrollOptions: ScrollToOptions = { behavior }\r\n if (top !== undefined) scrollOptions.top = top\r\n if (left !== undefined) scrollOptions.left = left\r\n\r\n containerRef.value.scrollTo(scrollOptions)\r\n\r\n // 使用 requestAnimationFrame 检测滚动是否完成\r\n // 只有当滚动位置不再变化时才重置标志\r\n let lastScrollTop = containerRef.value.scrollTop\r\n let lastScrollLeft = containerRef.value.scrollLeft\r\n let stableFrames = 0\r\n\r\n const checkScrollComplete = () => {\r\n const currentScrollTop = containerRef.value?.scrollTop ?? lastScrollTop\r\n const currentScrollLeft = containerRef.value?.scrollLeft ?? lastScrollLeft\r\n\r\n if (currentScrollTop === lastScrollTop && currentScrollLeft === lastScrollLeft) {\r\n stableFrames++\r\n // 连续 3 帧位置不变,认为滚动已完成\r\n if (stableFrames >= 3) {\r\n isProgrammaticScroll.value = false\r\n return\r\n }\r\n } else {\r\n stableFrames = 0\r\n lastScrollTop = currentScrollTop\r\n lastScrollLeft = currentScrollLeft\r\n }\r\n\r\n // 最多检查 100 帧(约 1.6 秒),防止无限循环\r\n if (stableFrames < 100) {\r\n requestAnimationFrame(checkScrollComplete)\r\n } else {\r\n isProgrammaticScroll.value = false\r\n }\r\n }\r\n\r\n requestAnimationFrame(checkScrollComplete)\r\n }\r\n\r\n // 滚动到顶部\r\n const scrollToTop = () => {\r\n scrollTo(0)\r\n }\r\n\r\n // 滚动到底部\r\n const scrollToBottom = () => {\r\n if (!containerRef.value) return\r\n scrollTo(contentRef.value?.scrollHeight || 0)\r\n }\r\n\r\n // 滚动到指定元素\r\n const scrollToElement = (element: HTMLElement) => {\r\n // 设置编程式滚动标志\r\n isProgrammaticScroll.value = true\r\n\r\n element.scrollIntoView({\r\n behavior: props.smooth ? \"smooth\" : \"auto\",\r\n block: \"nearest\",\r\n })\r\n\r\n // 使用 requestAnimationFrame 检测滚动是否完成\r\n if (!containerRef.value) {\r\n setTimeout(() => { isProgrammaticScroll.value = false }, 100)\r\n return\r\n }\r\n\r\n let lastScrollTop = containerRef.value.scrollTop\r\n let lastScrollLeft = containerRef.value.scrollLeft\r\n let stableFrames = 0\r\n\r\n const checkScrollComplete = () => {\r\n const currentScrollTop = containerRef.value?.scrollTop ?? lastScrollTop\r\n const currentScrollLeft = containerRef.value?.scrollLeft ?? lastScrollLeft\r\n\r\n if (currentScrollTop === lastScrollTop && currentScrollLeft === lastScrollLeft) {\r\n stableFrames++\r\n if (stableFrames >= 3) {\r\n isProgrammaticScroll.value = false\r\n return\r\n }\r\n } else {\r\n stableFrames = 0\r\n lastScrollTop = currentScrollTop\r\n lastScrollLeft = currentScrollLeft\r\n }\r\n\r\n if (stableFrames < 100) {\r\n requestAnimationFrame(checkScrollComplete)\r\n } else {\r\n isProgrammaticScroll.value = false\r\n }\r\n }\r\n\r\n requestAnimationFrame(checkScrollComplete)\r\n }\r\n\r\n // 按百分比滚动到指定位置\r\n const scrollToPercent = (topPercent: number, leftPercent?: number) => {\r\n if (!containerRef.value) return\r\n\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n\r\n // 计算目标滚动位置\r\n const targetScrollTop = Math.max(\r\n 0,\r\n Math.min((topPercent / 100) * maxScrollTop, maxScrollTop)\r\n )\r\n const targetScrollLeft = leftPercent !== undefined\r\n ? Math.max(0, Math.min((leftPercent / 100) * maxScrollLeft, maxScrollLeft))\r\n : scrollLeft.value\r\n\r\n scrollTo(targetScrollTop, targetScrollLeft)\r\n }\r\n\r\n // 垂直滚动条拖拽开始\r\n const handleVThumbMouseDown = (e: MouseEvent) => {\r\n e.preventDefault()\r\n e.stopPropagation()\r\n isDraggingV.value = true\r\n dragStartY.value = e.clientY\r\n dragStartScrollTop.value = scrollTop.value\r\n\r\n // 拖拽时禁用平滑滚动,避免延迟感\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = \"auto\"\r\n }\r\n\r\n // 添加全局事件监听\r\n document.addEventListener(\"mousemove\", handleVThumbMouseMove)\r\n document.addEventListener(\"mouseup\", handleVThumbMouseUp)\r\n\r\n // 防止文本选择\r\n document.body.style.userSelect = \"none\"\r\n document.body.style.cursor = \"grabbing\"\r\n }\r\n\r\n // 垂直滚动条拖拽移动\r\n const handleVThumbMouseMove = (e: MouseEvent) => {\r\n if (!isDraggingV.value || !containerRef.value) return\r\n e.preventDefault()\r\n\r\n const deltaY = e.clientY - dragStartY.value\r\n const maxScroll = contentHeight.value - containerHeight.value\r\n\r\n // 防止除以零\r\n if (maxScroll <= 0 || vTrackHeight.value <= 0) return\r\n\r\n // 滑块可移动的最大距离 = 轨道高度 - 滑块高度\r\n const maxThumbMove = vTrackHeight.value - vThumbHeight.value\r\n\r\n // 计算滚动比例:每像素拖动对应的滚动距离\r\n const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1\r\n\r\n // 计算新的滚动位置\r\n const newScrollTop = dragStartScrollTop.value + deltaY * scrollRatio\r\n const clampedScrollTop = Math.max(0, Math.min(newScrollTop, maxScroll))\r\n\r\n // 直接设置滚动位置,Vue 会通过 scroll 事件自动更新滑块位置\r\n containerRef.value.scrollTop = clampedScrollTop\r\n }\r\n\r\n // 垂直滚动条拖拽结束\r\n const handleVThumbMouseUp = () => {\r\n isDraggingV.value = false\r\n\r\n // 恢复平滑滚动设置\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = \"\"\r\n }\r\n\r\n document.removeEventListener(\"mousemove\", handleVThumbMouseMove)\r\n document.removeEventListener(\"mouseup\", handleVThumbMouseUp)\r\n\r\n // 恢复样式\r\n document.body.style.userSelect = \"\"\r\n document.body.style.cursor = \"\"\r\n\r\n // 设置标志位,防止触发轨道 click 事件\r\n justDragged.value = true\r\n setTimeout(() => {\r\n justDragged.value = false\r\n }, 0)\r\n }\r\n\r\n // 水平滚动条拖拽开始\r\n const handleHThumbMouseDown = (e: MouseEvent) => {\r\n e.preventDefault()\r\n e.stopPropagation()\r\n isDraggingH.value = true\r\n dragStartX.value = e.clientX\r\n dragStartScrollLeft.value = scrollLeft.value\r\n\r\n // 拖拽时禁用平滑滚动,避免延迟感\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = \"auto\"\r\n }\r\n\r\n document.addEventListener(\"mousemove\", handleHThumbMouseMove)\r\n document.addEventListener(\"mouseup\", handleHThumbMouseUp)\r\n\r\n // 防止文本选择\r\n document.body.style.userSelect = \"none\"\r\n document.body.style.cursor = \"grabbing\"\r\n }\r\n\r\n // 水平滚动条拖拽移动\r\n const handleHThumbMouseMove = (e: MouseEvent) => {\r\n if (!isDraggingH.value || !containerRef.value) return\r\n e.preventDefault()\r\n\r\n const deltaX = e.clientX - dragStartX.value\r\n const maxScroll = contentWidth.value - containerWidth.value\r\n\r\n // 防止除以零\r\n if (maxScroll <= 0 || hTrackWidth.value <= 0) return\r\n\r\n // 滑块可移动的最大距离 = 轨道宽度 - 滑块宽度\r\n const maxThumbMove = hTrackWidth.value - hThumbWidth.value\r\n\r\n // 计算滚动比例:每像素拖动对应的滚动距离\r\n const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1\r\n\r\n // 计算新的滚动位置\r\n const newScrollLeft = dragStartScrollLeft.value + deltaX * scrollRatio\r\n const clampedScrollLeft = Math.max(0, Math.min(newScrollLeft, maxScroll))\r\n\r\n // 直接设置滚动位置,Vue 会通过 scroll 事件自动更新滑块位置\r\n containerRef.value.scrollLeft = clampedScrollLeft\r\n }\r\n\r\n // 水平滚动条拖拽结束\r\n const handleHThumbMouseUp = () => {\r\n isDraggingH.value = false\r\n\r\n // 恢复平滑滚动设置\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = \"\"\r\n }\r\n\r\n document.removeEventListener(\"mousemove\", handleHThumbMouseMove)\r\n document.removeEventListener(\"mouseup\", handleHThumbMouseUp)\r\n\r\n // 恢复样式\r\n document.body.style.userSelect = \"\"\r\n document.body.style.cursor = \"\"\r\n\r\n // 设置标志位,防止触发轨道 click 事件\r\n justDragged.value = true\r\n setTimeout(() => {\r\n justDragged.value = false\r\n }, 0)\r\n }\r\n\r\n // 点击垂直轨道\r\n const handleVTrackClick = (e: MouseEvent) => {\r\n if (!containerRef.value || isDraggingV.value || justDragged.value) return\r\n\r\n const trackRect = vTrackRef.value?.getBoundingClientRect()\r\n if (!trackRect) return\r\n\r\n // 计算点击位置相对于轨道顶部的位置\r\n const clickY = e.clientY - trackRect.top\r\n // 滑块中心位置\r\n const thumbCenter = vThumbTop.value + vThumbHeight.value / 2\r\n const maxScroll = contentHeight.value - containerHeight.value\r\n\r\n // 根据点击位置决定滚动方向\r\n let newScrollTop = scrollTop.value\r\n if (clickY < thumbCenter) {\r\n // 点击滑块上方,向上滚动\r\n newScrollTop = scrollTop.value - props.scrollStep\r\n } else {\r\n // 点击滑块下方,向下滚动\r\n newScrollTop = scrollTop.value + props.scrollStep\r\n }\r\n\r\n // 立即滚动,不使用平滑动画\r\n containerRef.value.scrollTop = Math.max(\r\n 0,\r\n Math.min(newScrollTop, maxScroll)\r\n )\r\n }\r\n\r\n // 点击水平轨道\r\n const handleHTrackClick = (e: MouseEvent) => {\r\n if (!containerRef.value || isDraggingH.value || justDragged.value) return\r\n\r\n const trackRect = hTrackRef.value?.getBoundingClientRect()\r\n if (!trackRect) return\r\n\r\n // 计算点击位置相对于轨道左侧的位置\r\n const clickX = e.clientX - trackRect.left\r\n // 滑块中心位置\r\n const thumbCenter = hThumbLeft.value + hThumbWidth.value / 2\r\n const maxScroll = contentWidth.value - containerWidth.value\r\n\r\n // 根据点击位置决定滚动方向\r\n let newScrollLeft = scrollLeft.value\r\n if (clickX < thumbCenter) {\r\n // 点击滑块左侧,向左滚动\r\n newScrollLeft = scrollLeft.value - props.scrollStep\r\n } else {\r\n // 点击滑块右侧,向右滚动\r\n newScrollLeft = scrollLeft.value + props.scrollStep\r\n }\r\n\r\n // 立即滚动,不使用平滑动画\r\n containerRef.value.scrollLeft = Math.max(\r\n 0,\r\n Math.min(newScrollLeft, maxScroll)\r\n )\r\n }\r\n\r\n // 触摸事件处理(移动端支持)\r\n const touchStartY = ref(0)\r\n const touchStartX = ref(0)\r\n const touchStartScrollTop = ref(0)\r\n const touchStartScrollLeft = ref(0)\r\n\r\n const handleTouchStart = (e: TouchEvent) => {\r\n const touch = e.touches[0]\r\n touchStartY.value = touch.clientY\r\n touchStartX.value = touch.clientX\r\n touchStartScrollTop.value = scrollTop.value\r\n touchStartScrollLeft.value = scrollLeft.value\r\n\r\n emit(\"scroll-start\")\r\n }\r\n\r\n const handleTouchMove = (e: TouchEvent) => {\r\n if (!containerRef.value) return\r\n\r\n const touch = e.touches[0]\r\n const deltaY = touchStartY.value - touch.clientY\r\n const deltaX = touchStartX.value - touch.clientX\r\n\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n\r\n const newScrollTop = touchStartScrollTop.value + deltaY\r\n const newScrollLeft = touchStartScrollLeft.value + deltaX\r\n\r\n // 使用 scrollTo,这会触发 scroll 事件,handleScroll 会更新状态\r\n scrollTo(\r\n Math.max(0, Math.min(newScrollTop, maxScrollTop)),\r\n Math.max(0, Math.min(newScrollLeft, maxScrollLeft))\r\n )\r\n }\r\n\r\n const handleTouchEnd = () => {\r\n emit(\"scroll-end\")\r\n }\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n updateSize()\r\n\r\n // 再次延迟测量,确保轨道已渲染\r\n setTimeout(() => {\r\n updateSize()\r\n }, 100)\r\n\r\n // 需 preventDefault 才能接管离散滚轮步长,故 passive: false\r\n if (containerRef.value) {\r\n containerRef.value.addEventListener(\"wheel\", handleWheel, {\r\n passive: false,\r\n })\r\n }\r\n })\r\n })\r\n\r\n // 清理事件监听器\r\n onUnmounted(() => {\r\n if (containerRef.value) {\r\n containerRef.value.removeEventListener(\"wheel\", handleWheel)\r\n }\r\n\r\n if (wheelSmoothRestoreTimer) {\r\n clearTimeout(wheelSmoothRestoreTimer)\r\n wheelSmoothRestoreTimer = null\r\n }\r\n })\r\n\r\n // 暴露方法给父组件\r\n const exposeMethods = {\r\n scrollTo,\r\n scrollToTop,\r\n scrollToBottom,\r\n scrollToElement,\r\n scrollToPercent,\r\n updateSize,\r\n getScrollPosition: () => {\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n \r\n return {\r\n scrollTop: scrollTop.value,\r\n scrollLeft: scrollLeft.value,\r\n // 滚动百分比(0-100)\r\n scrollTopPercent: maxScrollTop > 0\r\n ? Math.round((scrollTop.value / maxScrollTop) * 100)\r\n : 0,\r\n scrollLeftPercent: maxScrollLeft > 0\r\n ? Math.round((scrollLeft.value / maxScrollLeft) * 100)\r\n : 0,\r\n }\r\n },\r\n }\r\n\r\n // 暴露方法\r\n expose(exposeMethods)\r\n\r\n return () => (\r\n <div\r\n class={[\r\n \"w-scrollbar\",\r\n // 将 direction 映射为 CSS class\r\n `w-scrollbar-${props.direction}`,\r\n {\r\n \"w-scrollbar-smooth\": props.smooth,\r\n },\r\n ]}\r\n style={{\r\n minHeight: toCssSize(props.minHeight),\r\n maxHeight: toCssSize(props.maxHeight),\r\n height: toCssSize(props.height),\r\n }}>\r\n {/* 滚动容器 */}\r\n <div\r\n ref={containerRef}\r\n class=\"w-scrollbar-container\"\r\n onScroll={handleScroll}\r\n onTouchstart={handleTouchStart}\r\n onTouchmove={handleTouchMove}\r\n onTouchend={handleTouchEnd}>\r\n <div ref={contentRef} class=\"w-scrollbar-content\">\r\n {slots.default?.()}\r\n </div>\r\n </div>\r\n\r\n {/* 垂直滚动条 */}\r\n {showVertical.value && (\r\n <div\r\n ref={vTrackRef}\r\n class=\"w-scrollbar-track w-scrollbar-track-y\"\r\n onClick={handleVTrackClick}>\r\n <div\r\n ref={vThumbRef}\r\n class={[\r\n \"w-scrollbar-thumb w-scrollbar-thumb-y\",\r\n { \"w-scrollbar-thumb-dragging\": isDraggingV.value },\r\n ]}\r\n style={{\r\n height: `${vThumbHeight.value}px`,\r\n top: `${vThumbTop.value}px`,\r\n }}\r\n onMousedown={handleVThumbMouseDown}\r\n onTouchstart={handleVThumbMouseDown as any}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 水平滚动条 */}\r\n {showHorizontal.value && (\r\n <div\r\n ref={hTrackRef}\r\n class=\"w-scrollbar-track w-scrollbar-track-x\"\r\n onClick={handleHTrackClick}>\r\n <div\r\n ref={hThumbRef}\r\n class={[\r\n \"w-scrollbar-thumb w-scrollbar-thumb-x\",\r\n { \"w-scrollbar-thumb-dragging\": isDraggingH.value },\r\n ]}\r\n style={{\r\n width: `${hThumbWidth.value}px`,\r\n left: `${hThumbLeft.value}px`,\r\n }}\r\n onMousedown={handleHThumbMouseDown}\r\n onTouchstart={handleHThumbMouseDown as any}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n },\r\n})\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"Scrollbar.js","names":["defineComponent","ref","computed","watch","onMounted","onUnmounted","nextTick","createVNode","_createVNode","useVisibleResize","usePointerDrag","isInvisible","toCssSize","v","undefined","name","props","direction","type","String","default","scrollStep","Number","visible","Boolean","minHeight","maxHeight","height","smooth","minThumbSize","bottomOffset","emits","setup","slots","emit","expose","containerRef","contentRef","vTrackRef","vThumbRef","hTrackRef","hThumbRef","scrollTop","scrollLeft","containerHeight","contentHeight","containerWidth","contentWidth","vTrackHeight","hTrackWidth","justDragged","isProgrammaticScroll","lastIsTop","lastIsBottom","resolveWheelDelta","e","dx","deltaX","dy","deltaY","deltaMode","WheelEvent","DOM_DELTA_LINE","DOM_DELTA_PAGE","el","value","clientWidth","clientHeight","vThumbHeight","ratio","thumbH","Math","min","max","hThumbWidth","thumbW","vThumbTop","maxScroll","maxThumbMove","result","hThumbLeft","showVertical","showHorizontal","updateSize","scrollHeight","scrollWidth","computedStyle","getComputedStyle","paddingTop","parseFloat","paddingBottom","newVTrackHeight","paddingLeft","paddingRight","newHTrackWidth","handleScroll","target","isTop","maxScrollTop","maxScrollLeft","threshold","isBottom","distance","scrollTopPercent","round","scrollLeftPercent","scrollBottom","scrollRight","wheelSmoothRestoreTimer","pauseCssSmoothForWheel","style","scrollBehavior","clearTimeout","window","setTimeout","handleWheel","dir","eps","maxTop","maxLeft","canY","canX","stopPropagation","DOM_DELTA_PIXEL","preventDefault","scrollTo","top","left","behavior","scrollOptions","lastScrollTop","lastScrollLeft","stableFrames","checkScrollComplete","currentScrollTop","currentScrollLeft","requestAnimationFrame","scrollToTop","scrollToBottom","scrollToElement","element","scrollIntoView","block","scrollToPercent","topPercent","leftPercent","targetScrollTop","targetScrollLeft","dragging","isDraggingV","onMouseDown","handleVThumbMouseDown","events","bind","cursor","lockUserSelect","onStart","ctx","data","scrollStart","onMove","clientY","startY","scrollRatio","newScrollTop","onEnd","isDraggingH","handleHThumbMouseDown","clientX","startX","newScrollLeft","handleVTrackClick","trackRect","getBoundingClientRect","clickY","thumbCenter","handleHTrackClick","clickX","touchStartY","touchStartX","touchStartScrollTop","touchStartScrollLeft","handleTouchStart","touch","touches","handleTouchMove","handleTouchEnd","addEventListener","passive","removeEventListener","exposeMethods","getScrollPosition","width"],"sources":["../../../components/scrollbar/Scrollbar.tsx"],"sourcesContent":["import {\r\n defineComponent,\r\n ref,\r\n computed,\r\n watch,\r\n onMounted,\r\n onUnmounted,\r\n nextTick,\r\n} from \"vue\"\r\nimport type { PropType } from \"vue\"\r\nimport useVisibleResize from \"../../use/useVisibleResize\"\r\nimport usePointerDrag from \"../../use/usePointerDrag\"\r\nimport { isInvisible } from \"../../util\"\r\n\r\nfunction toCssSize(\r\n v: string | number | undefined\r\n): string | number | undefined {\r\n if (v === undefined) return undefined\r\n return typeof v === \"number\" ? `${v}px` : v\r\n}\r\n\r\nexport default defineComponent({\r\n name: \"Scrollbar\",\r\n props: {\r\n // 滚动方向:y(垂直), x(水平), both(双向)\r\n direction: {\r\n type: String as PropType<\"y\" | \"x\" | \"both\">,\r\n default: \"y\",\r\n },\r\n // 点击轨道的步长(px);滚轮在像素模式下跟随系统,LINE 模式才用此步长\r\n scrollStep: {\r\n type: Number,\r\n default: 60,\r\n },\r\n // 是否显示滚动条\r\n visible: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n // 容器最小高度\r\n minHeight: {\r\n type: [String, Number],\r\n default: undefined,\r\n },\r\n // 容器最大高度\r\n maxHeight: {\r\n type: [String, Number],\r\n default: undefined,\r\n },\r\n // 容器高度\r\n height: {\r\n type: [String, Number],\r\n default: undefined,\r\n },\r\n // 是否启用平滑滚动\r\n smooth: {\r\n type: Boolean,\r\n default: true,\r\n },\r\n // 滑块最小尺寸(单位:px),默认 30px,防止内容过长时滑块过小难以拖拽\r\n minThumbSize: {\r\n type: Number,\r\n default: 30,\r\n },\r\n // 触底偏移量(单位:px),当距离底部还有多少像素时触发触底事件,默认 0\r\n bottomOffset: {\r\n type: Number,\r\n default: 0,\r\n },\r\n },\r\n emits: [\"scroll\", \"scroll-start\", \"scroll-end\", \"reach-top\", \"reach-bottom\"],\r\n setup(props, { slots, emit, expose }) {\r\n // 容器引用\r\n const containerRef = ref<HTMLElement | null>(null)\r\n // 内容引用\r\n const contentRef = ref<HTMLElement | null>(null)\r\n // 垂直滚动条引用\r\n const vTrackRef = ref<HTMLElement | null>(null)\r\n const vThumbRef = ref<HTMLElement | null>(null)\r\n // 水平滚动条引用\r\n const hTrackRef = ref<HTMLElement | null>(null)\r\n const hThumbRef = ref<HTMLElement | null>(null)\r\n\r\n // 滚动状态\r\n const scrollTop = ref(0)\r\n const scrollLeft = ref(0)\r\n const containerHeight = ref(0)\r\n const contentHeight = ref(0)\r\n const containerWidth = ref(0)\r\n const contentWidth = ref(0)\r\n\r\n // 轨道实际尺寸(通过测量得到)\r\n const vTrackHeight = ref(0)\r\n const hTrackWidth = ref(0)\r\n\r\n // 刚结束拖拽的标志(用于防止 mouseup 后触发 click 事件)\r\n const justDragged = ref(false)\r\n\r\n // 是否是编程式滚动(外部调用方法触发的滚动)\r\n const isProgrammaticScroll = ref(false)\r\n\r\n // 触顶/触底状态(用于避免重复触发)\r\n const lastIsTop = ref(false)\r\n const lastIsBottom = ref(false)\r\n\r\n /**\r\n * 将 wheel 增量转为实际滚动像素。\r\n * 像素模式保留原生 delta(交给浏览器惯性,保证丝滑);\r\n * LINE/PAGE 才映射为 scrollStep / 一页高度。\r\n */\r\n const resolveWheelDelta = (e: WheelEvent) => {\r\n let dx = e.deltaX\r\n let dy = e.deltaY\r\n if (e.deltaMode === WheelEvent.DOM_DELTA_LINE) {\r\n dx *= props.scrollStep\r\n dy *= props.scrollStep\r\n } else if (e.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\r\n const el = containerRef.value\r\n dx *= el?.clientWidth ?? 0\r\n dy *= el?.clientHeight ?? 0\r\n }\r\n return { dx, dy }\r\n }\r\n\r\n // 计算垂直滚动条滑块高度\r\n const vThumbHeight = computed(() => {\r\n if (contentHeight.value <= containerHeight.value) return 0\r\n\r\n // 滑块高度比例 = 可视区域 / 内容总高度\r\n const ratio = containerHeight.value / contentHeight.value\r\n\r\n // 滑块实际高度 = 轨道高度 × 比例\r\n const thumbH = vTrackHeight.value * ratio\r\n\r\n // 最小 minThumbSize px,最大不超过轨道高度\r\n return Math.min(Math.max(props.minThumbSize, thumbH), vTrackHeight.value)\r\n })\r\n\r\n // 计算水平滚动条滑块宽度\r\n const hThumbWidth = computed(() => {\r\n if (contentWidth.value <= containerWidth.value) return 0\r\n\r\n // 滑块宽度比例 = 可视区域 / 内容总宽度\r\n const ratio = containerWidth.value / contentWidth.value\r\n\r\n // 滑块实际宽度 = 轨道宽度 × 比例\r\n const thumbW = hTrackWidth.value * ratio\r\n\r\n // 最小 minThumbSize px,最大不超过轨道宽度\r\n return Math.min(Math.max(props.minThumbSize, thumbW), hTrackWidth.value)\r\n })\r\n\r\n // 计算垂直滚动条滑块位置\r\n const vThumbTop = computed(() => {\r\n if (contentHeight.value <= containerHeight.value) return 0\r\n const maxScroll = contentHeight.value - containerHeight.value\r\n if (maxScroll <= 0 || vTrackHeight.value <= 0) return 0\r\n\r\n const ratio = scrollTop.value / maxScroll\r\n\r\n // 滑块可移动的最大距离 = 轨道可用高度 - 滑块高度\r\n const maxThumbMove = vTrackHeight.value - vThumbHeight.value\r\n\r\n // 滑块位置(相对于轨道内容区域)\r\n const result = ratio * maxThumbMove\r\n\r\n // 确保在合理范围内\r\n return Math.max(0, Math.min(result, maxThumbMove))\r\n })\r\n\r\n // 计算水平滚动条滑块位置\r\n const hThumbLeft = computed(() => {\r\n if (contentWidth.value <= containerWidth.value) return 0\r\n const maxScroll = contentWidth.value - containerWidth.value\r\n if (maxScroll <= 0 || hTrackWidth.value <= 0) return 0\r\n\r\n const ratio = scrollLeft.value / maxScroll\r\n\r\n // 滑块可移动的最大距离 = 轨道可用宽度 - 滑块宽度\r\n const maxThumbMove = hTrackWidth.value - hThumbWidth.value\r\n\r\n // 滑块位置(相对于轨道内容区域)\r\n const result = ratio * maxThumbMove\r\n\r\n // 确保在合理范围内\r\n return Math.max(0, Math.min(result, maxThumbMove))\r\n })\r\n\r\n // 判断是否需要显示垂直滚动条\r\n const showVertical = computed(() => {\r\n return (\r\n props.visible &&\r\n (props.direction === \"y\" || props.direction === \"both\") &&\r\n contentHeight.value > containerHeight.value\r\n )\r\n })\r\n\r\n // 判断是否需要显示水平滚动条\r\n const showHorizontal = computed(() => {\r\n return (\r\n props.visible &&\r\n (props.direction === \"x\" || props.direction === \"both\") &&\r\n contentWidth.value > containerWidth.value\r\n )\r\n })\r\n\r\n // 更新尺寸信息\r\n const updateSize = () => {\r\n if (!containerRef.value || !contentRef.value) return\r\n if (isInvisible(containerRef.value)) return\r\n\r\n containerHeight.value = containerRef.value.clientHeight\r\n contentHeight.value = contentRef.value.scrollHeight\r\n containerWidth.value = containerRef.value.clientWidth\r\n contentWidth.value = contentRef.value.scrollWidth\r\n\r\n // 测量轨道实际尺寸(使用 offsetHeight/clientWidth 减去 padding,获取实际可移动区域)\r\n if (vTrackRef.value) {\r\n const computedStyle = getComputedStyle(vTrackRef.value)\r\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0\r\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0\r\n const newVTrackHeight =\r\n vTrackRef.value.clientHeight - paddingTop - paddingBottom\r\n if (newVTrackHeight > 0) {\r\n vTrackHeight.value = newVTrackHeight\r\n }\r\n }\r\n if (hTrackRef.value) {\r\n const computedStyle = getComputedStyle(hTrackRef.value)\r\n const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0\r\n const paddingRight = parseFloat(computedStyle.paddingRight) || 0\r\n const newHTrackWidth =\r\n hTrackRef.value.clientWidth - paddingLeft - paddingRight\r\n if (newHTrackWidth > 0) {\r\n hTrackWidth.value = newHTrackWidth\r\n }\r\n }\r\n }\r\n\r\n useVisibleResize(containerRef, updateSize)\r\n useVisibleResize(contentRef, updateSize)\r\n watch([showVertical, showHorizontal], () => {\r\n nextTick(updateSize)\r\n })\r\n\r\n // 处理滚动事件\r\n const handleScroll = (e: Event) => {\r\n const target = e.target as HTMLElement\r\n\r\n // 更新滚动位置(总是更新,包括拖拽时)\r\n scrollTop.value = target.scrollTop\r\n scrollLeft.value = target.scrollLeft\r\n\r\n // 检测触顶\r\n const isTop = target.scrollTop <= 0\r\n if (isTop && !lastIsTop.value) {\r\n emit(\"reach-top\")\r\n }\r\n lastIsTop.value = isTop\r\n\r\n // 检测触底(考虑偏移量)\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n const threshold = maxScrollTop - props.bottomOffset\r\n const isBottom = maxScrollTop > 0 && target.scrollTop >= threshold\r\n if (isBottom && !lastIsBottom.value) {\r\n emit(\"reach-bottom\", { distance: maxScrollTop - target.scrollTop })\r\n }\r\n lastIsBottom.value = isBottom\r\n\r\n // 计算滚动百分比(0-100)\r\n const scrollTopPercent =\r\n maxScrollTop > 0\r\n ? Math.round((target.scrollTop / maxScrollTop) * 100)\r\n : 0\r\n const scrollLeftPercent =\r\n maxScrollLeft > 0\r\n ? Math.round((target.scrollLeft / maxScrollLeft) * 100)\r\n : 0\r\n\r\n // 如果是编程式滚动,不触发 scroll 事件\r\n if (!isProgrammaticScroll.value) {\r\n emit(\"scroll\", {\r\n scrollTop: target.scrollTop,\r\n scrollLeft: target.scrollLeft,\r\n // 距离底部的距离(垂直)\r\n scrollBottom: maxScrollTop - target.scrollTop,\r\n // 距离右侧的距离(水平)\r\n scrollRight: maxScrollLeft - target.scrollLeft,\r\n // 滚动百分比(0-100)\r\n scrollTopPercent,\r\n scrollLeftPercent,\r\n target,\r\n })\r\n }\r\n }\r\n\r\n // 连续像素流期间临时关掉 CSS smooth,避免跟浏览器惯性打架\r\n let wheelSmoothRestoreTimer: number | null = null\r\n const pauseCssSmoothForWheel = (el: HTMLElement) => {\r\n el.style.scrollBehavior = \"auto\"\r\n if (wheelSmoothRestoreTimer) clearTimeout(wheelSmoothRestoreTimer)\r\n wheelSmoothRestoreTimer = window.setTimeout(() => {\r\n if (props.smooth) el.style.scrollBehavior = \"\"\r\n wheelSmoothRestoreTimer = null\r\n }, 150)\r\n }\r\n\r\n /**\r\n * 滚轮:\r\n * - 本层还能顺着滚 → stopPropagation,避免外层 Scrollbar 抢走\r\n * - 像素模式 → 不 preventDefault,保留系统惯性(触摸板 / 现代鼠标)\r\n * - LINE/PAGE → preventDefault + 按 scrollStep / 页高步进\r\n * - 已到边界 → 不拦截,交给外层链式滚动\r\n */\r\n const handleWheel = (e: WheelEvent) => {\r\n const el = containerRef.value\r\n if (!el) return\r\n\r\n const { dx, dy } = resolveWheelDelta(e)\r\n const dir = props.direction\r\n const eps = 0.5\r\n\r\n const maxTop = el.scrollHeight - el.clientHeight\r\n const maxLeft = el.scrollWidth - el.clientWidth\r\n const canY =\r\n (dir === \"y\" || dir === \"both\") &&\r\n maxTop > 0 &&\r\n dy !== 0 &&\r\n ((dy > 0 && el.scrollTop < maxTop - eps) ||\r\n (dy < 0 && el.scrollTop > eps))\r\n const canX =\r\n (dir === \"x\" || dir === \"both\") &&\r\n maxLeft > 0 &&\r\n dx !== 0 &&\r\n ((dx > 0 && el.scrollLeft < maxLeft - eps) ||\r\n (dx < 0 && el.scrollLeft > eps))\r\n\r\n if (!canY && !canX) return\r\n\r\n // 挡住外层 Scrollbar 的 wheel 监听,否则嵌套时内层滚不动\r\n e.stopPropagation()\r\n pauseCssSmoothForWheel(el)\r\n\r\n // 像素模式交给浏览器(含惯性);scrollStep 主要作用于轨道点击与 LINE 模式\r\n if (e.deltaMode === WheelEvent.DOM_DELTA_PIXEL) return\r\n\r\n e.preventDefault()\r\n if (canY) {\r\n el.scrollTop = Math.max(0, Math.min(maxTop, el.scrollTop + dy))\r\n }\r\n if (canX) {\r\n el.scrollLeft = Math.max(0, Math.min(maxLeft, el.scrollLeft + dx))\r\n }\r\n }\r\n\r\n // 滚动到指定位置\r\n const scrollTo = (top?: number, left?: number) => {\r\n if (!containerRef.value) return\r\n\r\n // 设置编程式滚动标志\r\n isProgrammaticScroll.value = true\r\n\r\n const behavior = props.smooth ? \"smooth\" : \"auto\"\r\n\r\n // 将 top 和 left 合并到一个调用中,避免覆盖\r\n const scrollOptions: ScrollToOptions = { behavior }\r\n if (top !== undefined) scrollOptions.top = top\r\n if (left !== undefined) scrollOptions.left = left\r\n\r\n containerRef.value.scrollTo(scrollOptions)\r\n\r\n // 使用 requestAnimationFrame 检测滚动是否完成\r\n // 只有当滚动位置不再变化时才重置标志\r\n let lastScrollTop = containerRef.value.scrollTop\r\n let lastScrollLeft = containerRef.value.scrollLeft\r\n let stableFrames = 0\r\n\r\n const checkScrollComplete = () => {\r\n const currentScrollTop = containerRef.value?.scrollTop ?? lastScrollTop\r\n const currentScrollLeft = containerRef.value?.scrollLeft ?? lastScrollLeft\r\n\r\n if (currentScrollTop === lastScrollTop && currentScrollLeft === lastScrollLeft) {\r\n stableFrames++\r\n // 连续 3 帧位置不变,认为滚动已完成\r\n if (stableFrames >= 3) {\r\n isProgrammaticScroll.value = false\r\n return\r\n }\r\n } else {\r\n stableFrames = 0\r\n lastScrollTop = currentScrollTop\r\n lastScrollLeft = currentScrollLeft\r\n }\r\n\r\n // 最多检查 100 帧(约 1.6 秒),防止无限循环\r\n if (stableFrames < 100) {\r\n requestAnimationFrame(checkScrollComplete)\r\n } else {\r\n isProgrammaticScroll.value = false\r\n }\r\n }\r\n\r\n requestAnimationFrame(checkScrollComplete)\r\n }\r\n\r\n // 滚动到顶部\r\n const scrollToTop = () => {\r\n scrollTo(0)\r\n }\r\n\r\n // 滚动到底部\r\n const scrollToBottom = () => {\r\n if (!containerRef.value) return\r\n scrollTo(contentRef.value?.scrollHeight || 0)\r\n }\r\n\r\n // 滚动到指定元素\r\n const scrollToElement = (element: HTMLElement) => {\r\n // 设置编程式滚动标志\r\n isProgrammaticScroll.value = true\r\n\r\n element.scrollIntoView({\r\n behavior: props.smooth ? \"smooth\" : \"auto\",\r\n block: \"nearest\",\r\n })\r\n\r\n // 使用 requestAnimationFrame 检测滚动是否完成\r\n if (!containerRef.value) {\r\n setTimeout(() => { isProgrammaticScroll.value = false }, 100)\r\n return\r\n }\r\n\r\n let lastScrollTop = containerRef.value.scrollTop\r\n let lastScrollLeft = containerRef.value.scrollLeft\r\n let stableFrames = 0\r\n\r\n const checkScrollComplete = () => {\r\n const currentScrollTop = containerRef.value?.scrollTop ?? lastScrollTop\r\n const currentScrollLeft = containerRef.value?.scrollLeft ?? lastScrollLeft\r\n\r\n if (currentScrollTop === lastScrollTop && currentScrollLeft === lastScrollLeft) {\r\n stableFrames++\r\n if (stableFrames >= 3) {\r\n isProgrammaticScroll.value = false\r\n return\r\n }\r\n } else {\r\n stableFrames = 0\r\n lastScrollTop = currentScrollTop\r\n lastScrollLeft = currentScrollLeft\r\n }\r\n\r\n if (stableFrames < 100) {\r\n requestAnimationFrame(checkScrollComplete)\r\n } else {\r\n isProgrammaticScroll.value = false\r\n }\r\n }\r\n\r\n requestAnimationFrame(checkScrollComplete)\r\n }\r\n\r\n // 按百分比滚动到指定位置\r\n const scrollToPercent = (topPercent: number, leftPercent?: number) => {\r\n if (!containerRef.value) return\r\n\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n\r\n // 计算目标滚动位置\r\n const targetScrollTop = Math.max(\r\n 0,\r\n Math.min((topPercent / 100) * maxScrollTop, maxScrollTop)\r\n )\r\n const targetScrollLeft = leftPercent !== undefined\r\n ? Math.max(0, Math.min((leftPercent / 100) * maxScrollLeft, maxScrollLeft))\r\n : scrollLeft.value\r\n\r\n scrollTo(targetScrollTop, targetScrollLeft)\r\n }\r\n\r\n const { dragging: isDraggingV, onMouseDown: handleVThumbMouseDown } =\r\n usePointerDrag({\r\n events: 'mouse',\r\n bind: 'document',\r\n cursor: 'grabbing',\r\n lockUserSelect: true,\r\n onStart: (e, ctx) => {\r\n e.preventDefault()\r\n e.stopPropagation()\r\n ctx.data.scrollStart = scrollTop.value\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = 'auto'\r\n }\r\n },\r\n onMove: (e, ctx) => {\r\n if (!containerRef.value) return\r\n e.preventDefault()\r\n const deltaY = e.clientY - ctx.startY\r\n const maxScroll = contentHeight.value - containerHeight.value\r\n if (maxScroll <= 0 || vTrackHeight.value <= 0) return\r\n const maxThumbMove = vTrackHeight.value - vThumbHeight.value\r\n const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1\r\n const newScrollTop =\r\n (ctx.data.scrollStart as number) + deltaY * scrollRatio\r\n containerRef.value.scrollTop = Math.max(\r\n 0,\r\n Math.min(newScrollTop, maxScroll),\r\n )\r\n },\r\n onEnd: () => {\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = ''\r\n }\r\n justDragged.value = true\r\n setTimeout(() => {\r\n justDragged.value = false\r\n }, 0)\r\n },\r\n })\r\n\r\n const { dragging: isDraggingH, onMouseDown: handleHThumbMouseDown } =\r\n usePointerDrag({\r\n events: 'mouse',\r\n bind: 'document',\r\n cursor: 'grabbing',\r\n lockUserSelect: true,\r\n onStart: (e, ctx) => {\r\n e.preventDefault()\r\n e.stopPropagation()\r\n ctx.data.scrollStart = scrollLeft.value\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = 'auto'\r\n }\r\n },\r\n onMove: (e, ctx) => {\r\n if (!containerRef.value) return\r\n e.preventDefault()\r\n const deltaX = e.clientX - ctx.startX\r\n const maxScroll = contentWidth.value - containerWidth.value\r\n if (maxScroll <= 0 || hTrackWidth.value <= 0) return\r\n const maxThumbMove = hTrackWidth.value - hThumbWidth.value\r\n const scrollRatio = maxThumbMove > 0 ? maxScroll / maxThumbMove : 1\r\n const newScrollLeft =\r\n (ctx.data.scrollStart as number) + deltaX * scrollRatio\r\n containerRef.value.scrollLeft = Math.max(\r\n 0,\r\n Math.min(newScrollLeft, maxScroll),\r\n )\r\n },\r\n onEnd: () => {\r\n if (containerRef.value) {\r\n containerRef.value.style.scrollBehavior = ''\r\n }\r\n justDragged.value = true\r\n setTimeout(() => {\r\n justDragged.value = false\r\n }, 0)\r\n },\r\n })\r\n\r\n // 点击垂直轨道\r\n const handleVTrackClick = (e: MouseEvent) => {\r\n if (!containerRef.value || isDraggingV.value || justDragged.value) return\r\n\r\n const trackRect = vTrackRef.value?.getBoundingClientRect()\r\n if (!trackRect) return\r\n\r\n // 计算点击位置相对于轨道顶部的位置\r\n const clickY = e.clientY - trackRect.top\r\n // 滑块中心位置\r\n const thumbCenter = vThumbTop.value + vThumbHeight.value / 2\r\n const maxScroll = contentHeight.value - containerHeight.value\r\n\r\n // 根据点击位置决定滚动方向\r\n let newScrollTop = scrollTop.value\r\n if (clickY < thumbCenter) {\r\n // 点击滑块上方,向上滚动\r\n newScrollTop = scrollTop.value - props.scrollStep\r\n } else {\r\n // 点击滑块下方,向下滚动\r\n newScrollTop = scrollTop.value + props.scrollStep\r\n }\r\n\r\n // 立即滚动,不使用平滑动画\r\n containerRef.value.scrollTop = Math.max(\r\n 0,\r\n Math.min(newScrollTop, maxScroll)\r\n )\r\n }\r\n\r\n // 点击水平轨道\r\n const handleHTrackClick = (e: MouseEvent) => {\r\n if (!containerRef.value || isDraggingH.value || justDragged.value) return\r\n\r\n const trackRect = hTrackRef.value?.getBoundingClientRect()\r\n if (!trackRect) return\r\n\r\n // 计算点击位置相对于轨道左侧的位置\r\n const clickX = e.clientX - trackRect.left\r\n // 滑块中心位置\r\n const thumbCenter = hThumbLeft.value + hThumbWidth.value / 2\r\n const maxScroll = contentWidth.value - containerWidth.value\r\n\r\n // 根据点击位置决定滚动方向\r\n let newScrollLeft = scrollLeft.value\r\n if (clickX < thumbCenter) {\r\n // 点击滑块左侧,向左滚动\r\n newScrollLeft = scrollLeft.value - props.scrollStep\r\n } else {\r\n // 点击滑块右侧,向右滚动\r\n newScrollLeft = scrollLeft.value + props.scrollStep\r\n }\r\n\r\n // 立即滚动,不使用平滑动画\r\n containerRef.value.scrollLeft = Math.max(\r\n 0,\r\n Math.min(newScrollLeft, maxScroll)\r\n )\r\n }\r\n\r\n // 触摸事件处理(移动端支持)\r\n const touchStartY = ref(0)\r\n const touchStartX = ref(0)\r\n const touchStartScrollTop = ref(0)\r\n const touchStartScrollLeft = ref(0)\r\n\r\n const handleTouchStart = (e: TouchEvent) => {\r\n const touch = e.touches[0]\r\n touchStartY.value = touch.clientY\r\n touchStartX.value = touch.clientX\r\n touchStartScrollTop.value = scrollTop.value\r\n touchStartScrollLeft.value = scrollLeft.value\r\n\r\n emit(\"scroll-start\")\r\n }\r\n\r\n const handleTouchMove = (e: TouchEvent) => {\r\n if (!containerRef.value) return\r\n\r\n const touch = e.touches[0]\r\n const deltaY = touchStartY.value - touch.clientY\r\n const deltaX = touchStartX.value - touch.clientX\r\n\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n\r\n const newScrollTop = touchStartScrollTop.value + deltaY\r\n const newScrollLeft = touchStartScrollLeft.value + deltaX\r\n\r\n // 使用 scrollTo,这会触发 scroll 事件,handleScroll 会更新状态\r\n scrollTo(\r\n Math.max(0, Math.min(newScrollTop, maxScrollTop)),\r\n Math.max(0, Math.min(newScrollLeft, maxScrollLeft))\r\n )\r\n }\r\n\r\n const handleTouchEnd = () => {\r\n emit(\"scroll-end\")\r\n }\r\n\r\n onMounted(() => {\r\n nextTick(() => {\r\n updateSize()\r\n\r\n // 再次延迟测量,确保轨道已渲染\r\n setTimeout(() => {\r\n updateSize()\r\n }, 100)\r\n\r\n // 需 preventDefault 才能接管离散滚轮步长,故 passive: false\r\n if (containerRef.value) {\r\n containerRef.value.addEventListener(\"wheel\", handleWheel, {\r\n passive: false,\r\n })\r\n }\r\n })\r\n })\r\n\r\n // 清理事件监听器\r\n onUnmounted(() => {\r\n if (containerRef.value) {\r\n containerRef.value.removeEventListener(\"wheel\", handleWheel)\r\n }\r\n\r\n if (wheelSmoothRestoreTimer) {\r\n clearTimeout(wheelSmoothRestoreTimer)\r\n wheelSmoothRestoreTimer = null\r\n }\r\n })\r\n\r\n // 暴露方法给父组件\r\n const exposeMethods = {\r\n scrollTo,\r\n scrollToTop,\r\n scrollToBottom,\r\n scrollToElement,\r\n scrollToPercent,\r\n updateSize,\r\n getScrollPosition: () => {\r\n const maxScrollTop = contentHeight.value - containerHeight.value\r\n const maxScrollLeft = contentWidth.value - containerWidth.value\r\n \r\n return {\r\n scrollTop: scrollTop.value,\r\n scrollLeft: scrollLeft.value,\r\n // 滚动百分比(0-100)\r\n scrollTopPercent: maxScrollTop > 0\r\n ? Math.round((scrollTop.value / maxScrollTop) * 100)\r\n : 0,\r\n scrollLeftPercent: maxScrollLeft > 0\r\n ? Math.round((scrollLeft.value / maxScrollLeft) * 100)\r\n : 0,\r\n }\r\n },\r\n }\r\n\r\n // 暴露方法\r\n expose(exposeMethods)\r\n\r\n return () => (\r\n <div\r\n class={[\r\n \"w-scrollbar\",\r\n // 将 direction 映射为 CSS class\r\n `w-scrollbar-${props.direction}`,\r\n {\r\n \"w-scrollbar-smooth\": props.smooth,\r\n },\r\n ]}\r\n style={{\r\n minHeight: toCssSize(props.minHeight),\r\n maxHeight: toCssSize(props.maxHeight),\r\n height: toCssSize(props.height),\r\n }}>\r\n {/* 滚动容器 */}\r\n <div\r\n ref={containerRef}\r\n class=\"w-scrollbar-container\"\r\n onScroll={handleScroll}\r\n onTouchstart={handleTouchStart}\r\n onTouchmove={handleTouchMove}\r\n onTouchend={handleTouchEnd}>\r\n <div ref={contentRef} class=\"w-scrollbar-content\">\r\n {slots.default?.()}\r\n </div>\r\n </div>\r\n\r\n {/* 垂直滚动条 */}\r\n {showVertical.value && (\r\n <div\r\n ref={vTrackRef}\r\n class=\"w-scrollbar-track w-scrollbar-track-y\"\r\n onClick={handleVTrackClick}>\r\n <div\r\n ref={vThumbRef}\r\n class={[\r\n \"w-scrollbar-thumb w-scrollbar-thumb-y\",\r\n { \"w-scrollbar-thumb-dragging\": isDraggingV.value },\r\n ]}\r\n style={{\r\n height: `${vThumbHeight.value}px`,\r\n top: `${vThumbTop.value}px`,\r\n }}\r\n onMousedown={handleVThumbMouseDown}\r\n onTouchstart={handleVThumbMouseDown as any}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* 水平滚动条 */}\r\n {showHorizontal.value && (\r\n <div\r\n ref={hTrackRef}\r\n class=\"w-scrollbar-track w-scrollbar-track-x\"\r\n onClick={handleHTrackClick}>\r\n <div\r\n ref={hThumbRef}\r\n class={[\r\n \"w-scrollbar-thumb w-scrollbar-thumb-x\",\r\n { \"w-scrollbar-thumb-dragging\": isDraggingH.value },\r\n ]}\r\n style={{\r\n width: `${hThumbWidth.value}px`,\r\n left: `${hThumbLeft.value}px`,\r\n }}\r\n onMousedown={handleHThumbMouseDown}\r\n onTouchstart={handleHThumbMouseDown as any}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n )\r\n },\r\n})\r\n"],"mappings":"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"}
@@ -1443,6 +1443,8 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
1443
1443
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
1444
1444
  }, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
1445
1445
  }, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
1446
- Virtual: import('..').VirtualComponent;
1446
+ Virtual: new <T = any>() => import('..').VirtualListMethods & {
1447
+ $props: import('..').VirtualJSXProps<T>;
1448
+ };
1447
1449
  }, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
1448
1450
  export default _default;
@@ -1,5 +1,6 @@
1
1
  import Icon_default from "../icon/Icon.js";
2
- import { computed, createVNode, defineComponent, inject, normalizeClass, normalizeStyle, onMounted, reactive, ref } from "vue";
2
+ import usePointerDrag from "../../use/usePointerDrag.js";
3
+ import { computed, createVNode, defineComponent, inject, normalizeClass, normalizeStyle, ref } from "vue";
3
4
  //#region components/sheet/_cell.tsx
4
5
  var _cell_default = /* @__PURE__ */ defineComponent({
5
6
  components: { Icon: Icon_default },
@@ -35,14 +36,6 @@ var _cell_default = /* @__PURE__ */ defineComponent({
35
36
  },
36
37
  setup(props, { slots }) {
37
38
  const tdRoot = ref(null);
38
- const start = reactive({
39
- x: 0,
40
- y: 0
41
- });
42
- const end = reactive({
43
- x: 0,
44
- y: 0
45
- });
46
39
  const beforeResize = inject("beforeResize");
47
40
  const inResizing = inject("inResizing");
48
41
  const afterResize = inject("afterResize");
@@ -74,32 +67,28 @@ var _cell_default = /* @__PURE__ */ defineComponent({
74
67
  style: _s
75
68
  };
76
69
  });
77
- function toResize(e) {
78
- end.x = e.clientX;
79
- inResizing(props.colIndex, end.x - start.x);
80
- }
81
- function handleMouseup(e) {
82
- afterResize(props.colIndex, e.clientX - start.x);
83
- start.x = 0;
84
- end.x = 0;
85
- document.removeEventListener("mousemove", toResize);
86
- document.removeEventListener("mouseup", handleMouseup);
87
- }
70
+ const { onMouseDown: onResizeMouseDown } = usePointerDrag({
71
+ events: "mouse",
72
+ bind: "document",
73
+ onStart: (e) => {
74
+ beforeResize(tdRoot.value);
75
+ },
76
+ onMove: (e, ctx) => {
77
+ inResizing(props.colIndex, e.clientX - ctx.startX);
78
+ },
79
+ onEnd: (e, ctx) => {
80
+ if (e) afterResize(props.colIndex, e.clientX - ctx.startX);
81
+ }
82
+ });
88
83
  function toSort() {
89
84
  updateSorter(props.col?.field);
90
85
  }
91
- onMounted(() => {});
92
86
  return () => {
93
87
  let line = null;
94
88
  let sorter = null;
95
89
  if (props.resizeWidth) line = createVNode("span", {
96
90
  class: "w-cell-resize-line",
97
- onMousedown: (e) => {
98
- start.x = e.clientX;
99
- beforeResize(tdRoot.value);
100
- document.addEventListener("mousemove", toResize);
101
- document.addEventListener("mouseup", handleMouseup);
102
- },
91
+ onMousedown: onResizeMouseDown,
103
92
  onClick: (e) => {
104
93
  e.preventDefault();
105
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"_cell.js","names":["ref","computed","defineComponent","inject","reactive","onMounted","normalizeClass","normalizeStyle","createVNode","_createVNode","Icon","components","props","isInThead","Boolean","sorter","type","Number","default","undefined","tag","String","align","isNarrow","notBold","resizeWidth","colIndex","colSpan","rowSpan","col","Object","cellClass","Array","setup","slots","tdRoot","start","x","y","end","beforeResize","inResizing","afterResize","currentSorter","updateSorter","_style","width","restStyle","style","cellProps","_s","value","o","colspan","rowspan","class","toResize","e","clientX","handleMouseup","document","removeEventListener","toSort","field","line","lineProps","onMousedown","addEventListener","onClick","preventDefault","stopPropagation"],"sources":["../../../components/sheet/_cell.tsx"],"sourcesContent":["import {\r\n ref,\r\n computed,\r\n defineComponent,\r\n inject,\r\n ComputedRef,\r\n reactive,\r\n onMounted,\r\n onUpdated,\r\n nextTick,\r\n normalizeClass,\r\n normalizeStyle,\r\n} from \"vue\"\r\nimport Icon from \"../icon/index\"\r\nimport number from \"../number\"\r\nexport default defineComponent({\r\n components: { Icon },\r\n props: {\r\n isInThead: Boolean,\r\n\r\n sorter: { type: [Boolean, Number], default: undefined },\r\n tag: { type: String, default: \"td\" },\r\n align: { type: String }, //center\r\n isNarrow: Boolean,\r\n notBold: Boolean,\r\n resizeWidth: Boolean,\r\n colIndex: Number,\r\n colSpan: { type: Number, default: 1 },\r\n rowSpan: { type: Number, default: 1 },\r\n col: { type: Object },\r\n cellClass: { type: [Object, Array, String] },\r\n },\r\n setup(props, { slots }) {\r\n const tdRoot = ref(null)\r\n const start = reactive({ x: 0, y: 0 })\r\n const end = reactive({ x: 0, y: 0 })\r\n const beforeResize = inject(\"beforeResize\") as Function\r\n const inResizing = inject(\"inResizing\") as Function\r\n const afterResize = inject(\"afterResize\") as Function\r\n const currentSorter = inject(\"currentSorter\") as any\r\n const updateSorter = inject(\"updateSorter\") as Function\r\n const _style = computed(() => {\r\n if (!props.isInThead) {\r\n const { width, ...restStyle } = props.col?.style ?? {}\r\n return restStyle\r\n }\r\n })\r\n const cellProps = computed(() => {\r\n const _s = normalizeStyle(_style.value)\r\n let o: any = {\r\n ref: tdRoot,\r\n colspan: props.colSpan,\r\n rowspan: props.rowSpan,\r\n \"data-col-index\": props.colIndex,\r\n class: [\r\n \"w-cell\",\r\n {\r\n \"w-cell--center\": props.align === \"center\",\r\n \"w-cell--right\": props.align === \"right\",\r\n \"w-cell--narrow\": props.isNarrow,\r\n \"w-cell--not-bold\": props.notBold,\r\n },\r\n normalizeClass(props.cellClass),\r\n ],\r\n style: _s,\r\n }\r\n return o\r\n })\r\n function toResize(e: MouseEvent) {\r\n end.x = e.clientX\r\n inResizing(props.colIndex, end.x - start.x)\r\n }\r\n function handleMouseup(e: MouseEvent) {\r\n afterResize(props.colIndex, e.clientX - start.x)\r\n start.x = 0\r\n end.x = 0\r\n document.removeEventListener(\"mousemove\", toResize)\r\n document.removeEventListener(\"mouseup\", handleMouseup)\r\n }\r\n function toSort() {\r\n updateSorter(props.col?.field)\r\n }\r\n onMounted(() => {})\r\n\r\n return () => {\r\n let line: any = null\r\n let sorter: any = null\r\n if (props.resizeWidth) {\r\n const lineProps = {\r\n class: \"w-cell-resize-line\",\r\n onMousedown: (e: MouseEvent) => {\r\n start.x = e.clientX\r\n beforeResize(tdRoot.value)\r\n\r\n document.addEventListener(\"mousemove\", toResize)\r\n document.addEventListener(\"mouseup\", handleMouseup)\r\n },\r\n onClick: (e: MouseEvent) => {\r\n e.preventDefault()\r\n },\r\n }\r\n line = <span {...lineProps}></span>\r\n }\r\n if (props.sorter !== undefined) {\r\n sorter = (\r\n <div\r\n class=\"w-cell-sorter\"\r\n onClick={(e) => {\r\n toSort()\r\n e.preventDefault()\r\n e.stopPropagation()\r\n }}>\r\n <Icon\r\n name=\"w-icon-sort-down\"\r\n class={[\r\n \"w-cell-sorter-icon w-cell-sorter-up\",\r\n {\r\n \"w-cell-sorter--0\":\r\n currentSorter.field === props.col?.field &&\r\n currentSorter.sorter === 0,\r\n },\r\n ]}\r\n />\r\n <Icon\r\n name=\"w-icon-sort-down\"\r\n class={[\r\n \"w-cell-sorter-icon w-cell-sorter-down \",\r\n {\r\n \"w-cell-sorter--1\":\r\n currentSorter.field === props.col?.field &&\r\n currentSorter.sorter === 1,\r\n },\r\n ]}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <props.tag {...cellProps.value}>\r\n {slots.default?.()}\r\n {line}\r\n {sorter}\r\n </props.tag>\r\n )\r\n }\r\n },\r\n})\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"_cell.js","names":["ref","computed","defineComponent","inject","normalizeClass","normalizeStyle","createVNode","_createVNode","Icon","usePointerDrag","components","props","isInThead","Boolean","sorter","type","Number","default","undefined","tag","String","align","isNarrow","notBold","resizeWidth","colIndex","colSpan","rowSpan","col","Object","cellClass","Array","setup","slots","tdRoot","beforeResize","inResizing","afterResize","currentSorter","updateSorter","_style","width","restStyle","style","cellProps","_s","value","o","colspan","rowspan","class","onMouseDown","onResizeMouseDown","events","bind","onStart","e","onMove","ctx","clientX","startX","onEnd","toSort","field","line","lineProps","onMousedown","onClick","preventDefault","stopPropagation"],"sources":["../../../components/sheet/_cell.tsx"],"sourcesContent":["import {\r\n ref,\r\n computed,\r\n defineComponent,\r\n inject,\r\n normalizeClass,\r\n normalizeStyle,\r\n} from \"vue\"\r\nimport Icon from \"../icon/index\"\r\nimport usePointerDrag from \"../../use/usePointerDrag\"\r\nimport number from \"../number\"\r\nexport default defineComponent({\r\n components: { Icon },\r\n props: {\r\n isInThead: Boolean,\r\n\r\n sorter: { type: [Boolean, Number], default: undefined },\r\n tag: { type: String, default: \"td\" },\r\n align: { type: String }, //center\r\n isNarrow: Boolean,\r\n notBold: Boolean,\r\n resizeWidth: Boolean,\r\n colIndex: Number,\r\n colSpan: { type: Number, default: 1 },\r\n rowSpan: { type: Number, default: 1 },\r\n col: { type: Object },\r\n cellClass: { type: [Object, Array, String] },\r\n },\r\n setup(props, { slots }) {\r\n const tdRoot = ref(null)\r\n const beforeResize = inject(\"beforeResize\") as Function\r\n const inResizing = inject(\"inResizing\") as Function\r\n const afterResize = inject(\"afterResize\") as Function\r\n const currentSorter = inject(\"currentSorter\") as any\r\n const updateSorter = inject(\"updateSorter\") as Function\r\n const _style = computed(() => {\r\n if (!props.isInThead) {\r\n const { width, ...restStyle } = props.col?.style ?? {}\r\n return restStyle\r\n }\r\n })\r\n const cellProps = computed(() => {\r\n const _s = normalizeStyle(_style.value)\r\n let o: any = {\r\n ref: tdRoot,\r\n colspan: props.colSpan,\r\n rowspan: props.rowSpan,\r\n \"data-col-index\": props.colIndex,\r\n class: [\r\n \"w-cell\",\r\n {\r\n \"w-cell--center\": props.align === \"center\",\r\n \"w-cell--right\": props.align === \"right\",\r\n \"w-cell--narrow\": props.isNarrow,\r\n \"w-cell--not-bold\": props.notBold,\r\n },\r\n normalizeClass(props.cellClass),\r\n ],\r\n style: _s,\r\n }\r\n return o\r\n })\r\n\r\n const { onMouseDown: onResizeMouseDown } = usePointerDrag({\r\n events: \"mouse\",\r\n bind: \"document\",\r\n onStart: (e) => {\r\n beforeResize(tdRoot.value)\r\n },\r\n onMove: (e, ctx) => {\r\n inResizing(props.colIndex, e.clientX - ctx.startX)\r\n },\r\n onEnd: (e, ctx) => {\r\n if (e) afterResize(props.colIndex, e.clientX - ctx.startX)\r\n },\r\n })\r\n\r\n function toSort() {\r\n updateSorter(props.col?.field)\r\n }\r\n\r\n return () => {\r\n let line: any = null\r\n let sorter: any = null\r\n if (props.resizeWidth) {\r\n const lineProps = {\r\n class: \"w-cell-resize-line\",\r\n onMousedown: onResizeMouseDown,\r\n onClick: (e: MouseEvent) => {\r\n e.preventDefault()\r\n },\r\n }\r\n line = <span {...lineProps}></span>\r\n }\r\n if (props.sorter !== undefined) {\r\n sorter = (\r\n <div\r\n class=\"w-cell-sorter\"\r\n onClick={(e) => {\r\n toSort()\r\n e.preventDefault()\r\n e.stopPropagation()\r\n }}>\r\n <Icon\r\n name=\"w-icon-sort-down\"\r\n class={[\r\n \"w-cell-sorter-icon w-cell-sorter-up\",\r\n {\r\n \"w-cell-sorter--0\":\r\n currentSorter.field === props.col?.field &&\r\n currentSorter.sorter === 0,\r\n },\r\n ]}\r\n />\r\n <Icon\r\n name=\"w-icon-sort-down\"\r\n class={[\r\n \"w-cell-sorter-icon w-cell-sorter-down \",\r\n {\r\n \"w-cell-sorter--1\":\r\n currentSorter.field === props.col?.field &&\r\n currentSorter.sorter === 1,\r\n },\r\n ]}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n return (\r\n <props.tag {...cellProps.value}>\r\n {slots.default?.()}\r\n {line}\r\n {sorter}\r\n </props.tag>\r\n )\r\n }\r\n },\r\n})\r\n"],"mappings":"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"}