thumb2.mjs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { defineComponent, inject, ref, computed, onBeforeUnmount, toRef, openBlock, createBlock, Transition, unref, withCtx, withDirectives, createElementVNode, normalizeClass, withModifiers, normalizeStyle, vShow } from 'vue';
  2. import { useEventListener, isClient } from '@vueuse/core';
  3. import { scrollbarContextKey } from './constants.mjs';
  4. import { BAR_MAP, renderThumbStyle } from './util.mjs';
  5. import { thumbProps } from './thumb.mjs';
  6. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  7. import { useNamespace } from '../../../hooks/use-namespace/index.mjs';
  8. import { throwError } from '../../../utils/error.mjs';
  9. const COMPONENT_NAME = "Thumb";
  10. const _sfc_main = /* @__PURE__ */ defineComponent({
  11. __name: "thumb",
  12. props: thumbProps,
  13. setup(__props) {
  14. const props = __props;
  15. const scrollbar = inject(scrollbarContextKey);
  16. const ns = useNamespace("scrollbar");
  17. if (!scrollbar)
  18. throwError(COMPONENT_NAME, "can not inject scrollbar context");
  19. const instance = ref();
  20. const thumb = ref();
  21. const thumbState = ref({});
  22. const visible = ref(false);
  23. let cursorDown = false;
  24. let cursorLeave = false;
  25. let baseScrollHeight = 0;
  26. let baseScrollWidth = 0;
  27. let originalOnSelectStart = isClient ? document.onselectstart : null;
  28. const bar = computed(() => BAR_MAP[props.vertical ? "vertical" : "horizontal"]);
  29. const thumbStyle = computed(() => renderThumbStyle({
  30. size: props.size,
  31. move: props.move,
  32. bar: bar.value
  33. }));
  34. const offsetRatio = computed(() => instance.value[bar.value.offset] ** 2 / scrollbar.wrapElement[bar.value.scrollSize] / props.ratio / thumb.value[bar.value.offset]);
  35. const clickThumbHandler = (e) => {
  36. var _a;
  37. e.stopPropagation();
  38. if (e.ctrlKey || [1, 2].includes(e.button))
  39. return;
  40. (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
  41. startDrag(e);
  42. const el = e.currentTarget;
  43. if (!el)
  44. return;
  45. thumbState.value[bar.value.axis] = el[bar.value.offset] - (e[bar.value.client] - el.getBoundingClientRect()[bar.value.direction]);
  46. };
  47. const clickTrackHandler = (e) => {
  48. if (!thumb.value || !instance.value || !scrollbar.wrapElement)
  49. return;
  50. const offset = Math.abs(e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]);
  51. const thumbHalf = thumb.value[bar.value.offset] / 2;
  52. const thumbPositionPercentage = (offset - thumbHalf) * 100 * offsetRatio.value / instance.value[bar.value.offset];
  53. scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * scrollbar.wrapElement[bar.value.scrollSize] / 100;
  54. };
  55. const startDrag = (e) => {
  56. e.stopImmediatePropagation();
  57. cursorDown = true;
  58. baseScrollHeight = scrollbar.wrapElement.scrollHeight;
  59. baseScrollWidth = scrollbar.wrapElement.scrollWidth;
  60. document.addEventListener("mousemove", mouseMoveDocumentHandler);
  61. document.addEventListener("mouseup", mouseUpDocumentHandler);
  62. originalOnSelectStart = document.onselectstart;
  63. document.onselectstart = () => false;
  64. };
  65. const mouseMoveDocumentHandler = (e) => {
  66. if (!instance.value || !thumb.value)
  67. return;
  68. if (cursorDown === false)
  69. return;
  70. const prevPage = thumbState.value[bar.value.axis];
  71. if (!prevPage)
  72. return;
  73. const offset = (instance.value.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * -1;
  74. const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
  75. const thumbPositionPercentage = (offset - thumbClickPosition) * 100 * offsetRatio.value / instance.value[bar.value.offset];
  76. if (bar.value.scroll === "scrollLeft") {
  77. scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * baseScrollWidth / 100;
  78. } else {
  79. scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * baseScrollHeight / 100;
  80. }
  81. };
  82. const mouseUpDocumentHandler = () => {
  83. cursorDown = false;
  84. thumbState.value[bar.value.axis] = 0;
  85. document.removeEventListener("mousemove", mouseMoveDocumentHandler);
  86. document.removeEventListener("mouseup", mouseUpDocumentHandler);
  87. restoreOnselectstart();
  88. if (cursorLeave)
  89. visible.value = false;
  90. };
  91. const mouseMoveScrollbarHandler = () => {
  92. cursorLeave = false;
  93. visible.value = !!props.size;
  94. };
  95. const mouseLeaveScrollbarHandler = () => {
  96. cursorLeave = true;
  97. visible.value = cursorDown;
  98. };
  99. onBeforeUnmount(() => {
  100. restoreOnselectstart();
  101. document.removeEventListener("mouseup", mouseUpDocumentHandler);
  102. });
  103. const restoreOnselectstart = () => {
  104. if (document.onselectstart !== originalOnSelectStart)
  105. document.onselectstart = originalOnSelectStart;
  106. };
  107. useEventListener(toRef(scrollbar, "scrollbarElement"), "mousemove", mouseMoveScrollbarHandler);
  108. useEventListener(toRef(scrollbar, "scrollbarElement"), "mouseleave", mouseLeaveScrollbarHandler);
  109. return (_ctx, _cache) => {
  110. return openBlock(), createBlock(Transition, {
  111. name: unref(ns).b("fade"),
  112. persisted: ""
  113. }, {
  114. default: withCtx(() => [
  115. withDirectives(createElementVNode("div", {
  116. ref_key: "instance",
  117. ref: instance,
  118. class: normalizeClass([unref(ns).e("bar"), unref(ns).is(unref(bar).key)]),
  119. onMousedown: clickTrackHandler,
  120. onClick: withModifiers(() => {
  121. }, ["stop"])
  122. }, [
  123. createElementVNode("div", {
  124. ref_key: "thumb",
  125. ref: thumb,
  126. class: normalizeClass(unref(ns).e("thumb")),
  127. style: normalizeStyle(unref(thumbStyle)),
  128. onMousedown: clickThumbHandler
  129. }, null, 38)
  130. ], 42, ["onClick"]), [
  131. [vShow, _ctx.always || visible.value]
  132. ])
  133. ]),
  134. _: 1
  135. }, 8, ["name"]);
  136. };
  137. }
  138. });
  139. var Thumb = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "thumb.vue"]]);
  140. export { Thumb as default };
  141. //# sourceMappingURL=thumb2.mjs.map