react-marquee-slider-vertical
Version:
The marquee slider of your wildest dreams. Only for React.js ⛺
170 lines • 10.2 kB
JavaScript
;
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importStar(require("react"));
var styled_components_1 = __importStar(require("styled-components"));
var Child_1 = __importDefault(require("./Child"));
var util_1 = require("./util");
var Container = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n justify-content: center;\n flex-wrap: nowrap;\n"], ["\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n justify-content: center;\n flex-wrap: nowrap;\n"])));
var marqueeAnim = styled_components_1.keyframes(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n 0% {\n transform: translate(0, 0);\n }\n\n 100% {\n transform: translate(0, 100%);\n }\n"], ["\n 0% {\n transform: translate(0, 0);\n }\n\n 100% {\n transform: translate(0, 100%);\n }\n"])));
var Mirror = styled_components_1.default.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n min-width: 100%;\n flex-shrink: 0;\n animation-name: ", ";\n animation-direction: ", ";\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n animation-play-state: ", ";\n"], ["\n min-width: 100%;\n flex-shrink: 0;\n animation-name: ", ";\n animation-direction: ", ";\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n animation-play-state: ", ";\n"])), marqueeAnim, function (props) { return (props.direction === "rtl" ? "reverse" : "normal"); }, function (props) { return (props.paused ? "paused" : "running"); });
var NESTED_UPDATE_LIMIT = 50;
// Let's try to prevent rerenders as much as possible
var Marquee = react_1.default.memo(function (_a) {
var children = _a.children, direction = _a.direction, velocity = _a.velocity, scatterRandomly = _a.scatterRandomly, resetAfterTries = _a.resetAfterTries, onInit = _a.onInit, onFinish = _a.onFinish;
var _b = react_1.useState(0), retryAfterExceedingUpdateDepthTrigger = _b[0], setRetryAfterExceedingUpdateDepthTrigger = _b[1];
var _c = react_1.useState(0), animationDuration = _c[0], setAnimationDuration = _c[1];
var _d = react_1.useState(0), nestedUpdateCount = _d[0], setNestedUpdateCount = _d[1];
var _e = react_1.useState(0), totalTries = _e[0], setTotalTries = _e[1];
var _f = react_1.useState({ width: 0, height: 0 }), containerSize = _f[0], setContainerSize = _f[1];
var _g = react_1.useState([]), childrenPosition = _g[0], setChildrenPosition = _g[1];
var containerRef = react_1.useRef(null);
var marqueeRef = react_1.useRef(null);
var isInitRender = react_1.useRef(true);
react_1.useEffect(function () {
if (isInitRender.current) {
onInit();
isInitRender.current = false;
}
}, [onInit]);
react_1.useEffect(function () {
if (scatterRandomly) {
setContainerSize({
width: containerRef.current.clientWidth,
height: containerRef.current.clientHeight,
});
}
}, [scatterRandomly]);
react_1.useEffect(function () {
// Don't change the state if
if (!isNaN(velocity) && velocity > 0) {
setAnimationDuration(containerRef.current.clientHeight / velocity);
}
}, [velocity]);
react_1.useEffect(function () {
if (scatterRandomly && nestedUpdateCount < NESTED_UPDATE_LIMIT) {
var siblings = marqueeRef.current.childNodes;
if (siblings.length > 0) {
var containerRect = containerRef.current.getBoundingClientRect();
var childRect = siblings[siblings.length - 1].getBoundingClientRect();
if (util_1.outOfContainerBounds(childRect, containerRect)) {
setChildrenPosition(function (state) { return state.slice(0, -1); });
setNestedUpdateCount(nestedUpdateCount + 1);
setTotalTries(totalTries + 1);
}
else {
var hasOverlaps = false;
for (var i = 0; i + 1 < siblings.length; i++) {
var rect1 = siblings[i].getBoundingClientRect();
var rect2 = siblings[siblings.length - 1].getBoundingClientRect();
if (util_1.doesOverlap(rect1, rect2, containerRect)) {
hasOverlaps = true;
setChildrenPosition(function (state) { return state.slice(0, -1); });
setNestedUpdateCount(nestedUpdateCount + 1);
setTotalTries(totalTries + 1);
}
}
if (!hasOverlaps &&
siblings.length === childrenPosition.length &&
childrenPosition.length === children.length) {
onFinish({ totalTries: totalTries });
}
}
}
if (containerSize.width > 0 &&
containerSize.height > 0 &&
childrenPosition.length < children.length) {
setChildrenPosition(function (state) { return __spreadArray(__spreadArray([], state), [
{
x: util_1.randomIntFromInterval(0, containerSize.width),
y: util_1.randomIntFromInterval(0, containerSize.height),
},
]); });
setNestedUpdateCount(nestedUpdateCount + 1);
setTotalTries(totalTries + 1);
}
// reset
if (totalTries > 0 && totalTries % resetAfterTries === 0) {
setChildrenPosition([]);
}
}
}, [nestedUpdateCount, childrenPosition, containerSize, scatterRandomly]);
react_1.useEffect(function () {
if (nestedUpdateCount >= NESTED_UPDATE_LIMIT) {
var resetRenderTimer_1 = setTimeout(function () {
setNestedUpdateCount(0);
setRetryAfterExceedingUpdateDepthTrigger(retryAfterExceedingUpdateDepthTrigger + 1);
});
return function () { return clearTimeout(resetRenderTimer_1); };
}
}, [nestedUpdateCount, retryAfterExceedingUpdateDepthTrigger]);
var renderChild = function (child, index, isOriginal) {
var pos;
if (childrenPosition[index] !== undefined) {
pos = childrenPosition[index];
}
return (react_1.default.createElement(Child_1.default, __assign({ key: (isOriginal ? "child-original" : "child-clone") + "-" + index }, pos, { scatterRandomly: scatterRandomly }), child));
};
var filteredChildren = children.filter(function (child, index) {
return scatterRandomly ? childrenPosition[index] !== undefined : true;
});
var animatedStyle = { animationDuration: animationDuration + "s" };
return (react_1.default.createElement(Container, { ref: containerRef },
react_1.default.createElement(Mirror, { style: __assign(__assign({}, animatedStyle), (velocity === 0 ? { transform: "translateY(0)" } : {})), direction: direction, paused: velocity === 0 }, filteredChildren.map(function (c, i) { return renderChild(c, i, false); })),
react_1.default.createElement(Mirror, { ref: marqueeRef, style: __assign(__assign({}, animatedStyle), (velocity === 0 ? { transform: "translateY(0)" } : {})), direction: direction, paused: velocity === 0 }, filteredChildren.map(function (c, i) { return renderChild(c, i, true); })),
react_1.default.createElement(Mirror, { style: __assign(__assign({}, animatedStyle), (velocity === 0 ? { transform: "translateY(0)" } : {})), direction: direction, paused: velocity === 0 }, filteredChildren.map(function (c, i) { return renderChild(c, i, false); }))));
});
Marquee.defaultProps = {
direction: "rtl",
velocity: 30,
scatterRandomly: false,
// the more elements, the higher you should put this.
// change in hundred or thousand steps even
resetAfterTries: 100,
onInit: function () { },
onFinish: function () { },
};
exports.default = Marquee;
var templateObject_1, templateObject_2, templateObject_3;
//# sourceMappingURL=Marquee.js.map