UNPKG

@daniel-wrz/react-components-scrollbar

Version:

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

189 lines (184 loc) 7.57 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Scrollbar: () => scrollbar_default }); module.exports = __toCommonJS(src_exports); // src/components/scrollbar/scrollbar.tsx var import_react = __toESM(require("react"), 1); // src/components/scrollbar/scrollbar-logic.ts var InitScrollbarAction = class { content; container; constructor(content, container) { this.container = container; this.content = content; } }; var SetThumbDraggingAction = class { dragging; thumbPosition; constructor(dragging, thumbPosition) { this.dragging = dragging; this.thumbPosition = thumbPosition; } }; var ScrollbarReducer = (state, action) => { switch (action.constructor) { case InitScrollbarAction: { const data = action; return { ...state, thumbHeight: ScrollbarServices.setThumbHeight(data.content, data.container, 20), scrollingFactor: ScrollbarServices.calculateScrollingFactor(data.content, data.container) }; } case SetThumbDraggingAction: { const data = action; return { ...state, thumbIsDraging: data.dragging, thumbPosition: data.thumbPosition }; } default: return state; } }; var ScrollbarServices = { calculateScrollingFactor: (content, container) => { if (content && container) { const { scrollHeight: contentTotalHeight } = content; const { clientHeight: containerHeight } = container; return contentTotalHeight / containerHeight; } return 0; }, setThumbHeight: (content, container, minThum) => { if (content && container) { const { scrollHeight: contentTotalHeight } = content; const { clientHeight: containerHeight } = container; const value = containerHeight / contentTotalHeight * containerHeight; if (value === containerHeight) return 0; return Math.max(value, minThum); } return 0; } }; // src/components/scrollbar/scrollbar.tsx var Scrollbar = ({ children }) => { const containerRef = (0, import_react.useRef)(null); const contentRef = (0, import_react.useRef)(null); const thumbRef = (0, import_react.useRef)(null); const trackRef = (0, import_react.useRef)(null); const observer = (0, import_react.useRef)(null); const [state, dispatch] = (0, import_react.useReducer)(ScrollbarReducer, { thumbHeight: 0, thumbIsDraging: false, scrollingFactor: 0 }); const calculateThumb = () => dispatch(new InitScrollbarAction(contentRef.current, containerRef.current)); const handleThumbMousedown = (e) => { if (!state.thumbIsDraging && thumbRef.current) { e.preventDefault(); e.stopPropagation(); const top = parseInt(thumbRef.current.style.top || "0", 10); dispatch(new SetThumbDraggingAction(true, e.clientY - top)); } }; const handleScrollingContent = (0, import_react.useCallback)(() => { const container = containerRef.current; const content = contentRef.current; const thumb = thumbRef.current; if (content && thumb && container) { const { clientHeight: containerHeight } = container; const { clientHeight: thumbHeight } = thumb; const position = content.scrollTop / state.scrollingFactor; const v = Math.min(position, containerHeight - thumbHeight); thumb.style.top = `${v}px`; } }, [state.scrollingFactor]); const stopScrolling = (0, import_react.useCallback)((e) => { dispatch(new SetThumbDraggingAction(false, 0)); }, []); const startDragingThumb = (0, import_react.useCallback)((e) => { if (state.thumbIsDraging) { e.preventDefault(); e.stopPropagation(); const content = contentRef.current; const container = containerRef.current; const thumb = thumbRef.current; if (state.thumbIsDraging && thumb && content && container) { const { clientHeight: containerHeight } = container; const { clientHeight: thumbHeight } = thumb; const delta = e.clientY - state.thumbPosition; const v = Math.min(Math.max(delta, 0), containerHeight - thumbHeight); content.scrollTop = v * state.scrollingFactor; } } }, [state.thumbIsDraging]); (0, import_react.useEffect)(() => { var _a, _b; if (contentRef.current) { const content = contentRef.current; observer.current = new ResizeObserver(() => { calculateThumb(); }); observer.current.observe(content); (_a = thumbRef.current) == null ? void 0 : _a.addEventListener("mousedown", handleThumbMousedown); (_b = contentRef.current) == null ? void 0 : _b.addEventListener("scroll", handleScrollingContent); return () => { var _a2, _b2, _c; (_a2 = observer.current) == null ? void 0 : _a2.unobserve(content); (_b2 = thumbRef.current) == null ? void 0 : _b2.removeEventListener("mousedown", handleThumbMousedown); (_c = contentRef.current) == null ? void 0 : _c.removeEventListener("scroll", handleScrollingContent); }; } }, [handleScrollingContent]); (0, import_react.useEffect)(() => { document.addEventListener("mouseup", stopScrolling); document.addEventListener("mousemove", startDragingThumb); return () => { document.removeEventListener("mousemove", startDragingThumb); document.removeEventListener("mouseup", stopScrolling); }; }, [startDragingThumb, stopScrolling]); return /* @__PURE__ */ import_react.default.createElement("div", { className: "s-container", ref: containerRef }, /* @__PURE__ */ import_react.default.createElement("div", { className: "s-content", ref: contentRef }, children), /* @__PURE__ */ import_react.default.createElement("div", { className: "s-scrollbar " + (state.thumbHeight === 0 ? "s-hide" : "") }, /* @__PURE__ */ import_react.default.createElement("div", { className: "s-track", ref: trackRef }, /* @__PURE__ */ import_react.default.createElement( "div", { className: "s-thumb", ref: thumbRef, style: { height: `${state.thumbHeight}px` } } )))); }; var scrollbar_default = Scrollbar; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Scrollbar });