thumb2.mjs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 = 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(
  30. () => renderThumbStyle({
  31. size: props.size,
  32. move: props.move,
  33. bar: bar.value
  34. })
  35. );
  36. const offsetRatio = computed(
  37. () => instance.value[bar.value.offset] ** 2 / scrollbar.wrapElement[bar.value.scrollSize] / props.ratio / thumb.value[bar.value.offset]
  38. );
  39. const clickThumbHandler = (e) => {
  40. var _a;
  41. e.stopPropagation();
  42. if (e.ctrlKey || [1, 2].includes(e.button))
  43. return;
  44. (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges();
  45. startDrag(e);
  46. const el = e.currentTarget;
  47. if (!el)
  48. return;
  49. thumbState.value[bar.value.axis] = el[bar.value.offset] - (e[bar.value.client] - el.getBoundingClientRect()[bar.value.direction]);
  50. };
  51. const clickTrackHandler = (e) => {
  52. if (!thumb.value || !instance.value || !scrollbar.wrapElement)
  53. return;
  54. const offset = Math.abs(
  55. e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]
  56. );
  57. const thumbHalf = thumb.value[bar.value.offset] / 2;
  58. const thumbPositionPercentage = (offset - thumbHalf) * 100 * offsetRatio.value / instance.value[bar.value.offset];
  59. scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * scrollbar.wrapElement[bar.value.scrollSize] / 100;
  60. };
  61. const startDrag = (e) => {
  62. e.stopImmediatePropagation();
  63. cursorDown = true;
  64. baseScrollHeight = scrollbar.wrapElement.scrollHeight;
  65. baseScrollWidth = scrollbar.wrapElement.scrollWidth;
  66. document.addEventListener("mousemove", mouseMoveDocumentHandler);
  67. document.addEventListener("mouseup", mouseUpDocumentHandler);
  68. originalOnSelectStart = document.onselectstart;
  69. document.onselectstart = () => false;
  70. };
  71. const mouseMoveDocumentHandler = (e) => {
  72. if (!instance.value || !thumb.value)
  73. return;
  74. if (cursorDown === false)
  75. return;
  76. const prevPage = thumbState.value[bar.value.axis];
  77. if (!prevPage)
  78. return;
  79. const offset = (instance.value.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * -1;
  80. const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
  81. const thumbPositionPercentage = (offset - thumbClickPosition) * 100 * offsetRatio.value / instance.value[bar.value.offset];
  82. if (bar.value.scroll === "scrollLeft") {
  83. scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * baseScrollWidth / 100;
  84. } else {
  85. scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * baseScrollHeight / 100;
  86. }
  87. };
  88. const mouseUpDocumentHandler = () => {
  89. cursorDown = false;
  90. thumbState.value[bar.value.axis] = 0;
  91. document.removeEventListener("mousemove", mouseMoveDocumentHandler);
  92. document.removeEventListener("mouseup", mouseUpDocumentHandler);
  93. restoreOnselectstart();
  94. if (cursorLeave)
  95. visible.value = false;
  96. };
  97. const mouseMoveScrollbarHandler = () => {
  98. cursorLeave = false;
  99. visible.value = !!props.size;
  100. };
  101. const mouseLeaveScrollbarHandler = () => {
  102. cursorLeave = true;
  103. visible.value = cursorDown;
  104. };
  105. onBeforeUnmount(() => {
  106. restoreOnselectstart();
  107. document.removeEventListener("mouseup", mouseUpDocumentHandler);
  108. });
  109. const restoreOnselectstart = () => {
  110. if (document.onselectstart !== originalOnSelectStart)
  111. document.onselectstart = originalOnSelectStart;
  112. };
  113. useEventListener(
  114. toRef(scrollbar, "scrollbarElement"),
  115. "mousemove",
  116. mouseMoveScrollbarHandler
  117. );
  118. useEventListener(
  119. toRef(scrollbar, "scrollbarElement"),
  120. "mouseleave",
  121. mouseLeaveScrollbarHandler
  122. );
  123. return (_ctx, _cache) => {
  124. return openBlock(), createBlock(Transition, {
  125. name: unref(ns).b("fade"),
  126. persisted: ""
  127. }, {
  128. default: withCtx(() => [
  129. withDirectives(createElementVNode(
  130. "div",
  131. {
  132. ref_key: "instance",
  133. ref: instance,
  134. class: normalizeClass([unref(ns).e("bar"), unref(ns).is(bar.value.key)]),
  135. onMousedown: clickTrackHandler,
  136. onClick: _cache[0] || (_cache[0] = withModifiers(() => {
  137. }, ["stop"]))
  138. },
  139. [
  140. createElementVNode(
  141. "div",
  142. {
  143. ref_key: "thumb",
  144. ref: thumb,
  145. class: normalizeClass(unref(ns).e("thumb")),
  146. style: normalizeStyle(thumbStyle.value),
  147. onMousedown: clickThumbHandler
  148. },
  149. null,
  150. 38
  151. )
  152. ],
  153. 34
  154. ), [
  155. [vShow, _ctx.always || visible.value]
  156. ])
  157. ]),
  158. _: 1
  159. }, 8, ["name"]);
  160. };
  161. }
  162. });
  163. var Thumb = /* @__PURE__ */ _export_sfc(_sfc_main, [["__file", "/home/runner/work/element-plus/element-plus/packages/components/scrollbar/src/thumb.vue"]]);
  164. export { Thumb as default };
  165. //# sourceMappingURL=thumb2.mjs.map