UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

387 lines (386 loc) • 15.3 kB
/** * DevExtreme (esm/renovation/ui/scroll_view/animated_scrollbar.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; import _extends from "@babel/runtime/helpers/esm/extends"; var _excluded = ["activeStateEnabled", "bottomPocketSize", "bounceEnabled", "containerSize", "contentSize", "contentTranslateOffsetChange", "defaultPocketState", "direction", "forceGeneratePockets", "forceUpdateScrollbarLocation", "forceVisibility", "hoverStateEnabled", "inertiaEnabled", "isScrollableHovered", "onAnimatorCancel", "onAnimatorStart", "onBounce", "onPullDown", "onReachBottom", "onRelease", "pocketState", "pocketStateChange", "pullDownEnabled", "reachBottomEnabled", "rtlEnabled", "scrollByThumb", "scrollLocation", "scrollLocationChange", "scrollableOffset", "showScrollbar", "topPocketSize"]; import { createComponentVNode } from "inferno"; import { BaseInfernoComponent } from "@devextreme/vdom"; import { isDefined } from "../../../core/utils/type"; import devices from "../../../core/devices"; import { Scrollbar } from "./scrollbar"; import { requestAnimationFrame, cancelAnimationFrame } from "../../../animation/frame"; import { ScrollbarProps } from "./scrollbar_props"; import { ScrollableSimulatedProps } from "./scrollable_simulated_props"; import { ScrollableProps } from "./scrollable_props"; export var OUT_BOUNDS_ACCELERATION = .5; var isSluggishPlatform = "android" === devices.real().platform; export var ACCELERATION = isSluggishPlatform ? .95 : .92; export var MIN_VELOCITY_LIMIT = 1; export var BOUNCE_MIN_VELOCITY_LIMIT = MIN_VELOCITY_LIMIT / 5; var FRAME_DURATION = 17; var BOUNCE_DURATION = isSluggishPlatform ? 300 : 400; var BOUNCE_FRAMES = BOUNCE_DURATION / FRAME_DURATION; export var BOUNCE_ACCELERATION_SUM = (1 - ACCELERATION ** BOUNCE_FRAMES) / (1 - ACCELERATION); export var viewFunction = viewModel => { var { cancel: cancel, props: { bottomPocketSize: bottomPocketSize, bounceEnabled: bounceEnabled, containerSize: containerSize, contentSize: contentSize, contentTranslateOffsetChange: contentTranslateOffsetChange, direction: direction, forceGeneratePockets: forceGeneratePockets, forceUpdateScrollbarLocation: forceUpdateScrollbarLocation, isScrollableHovered: isScrollableHovered, onPullDown: onPullDown, onReachBottom: onReachBottom, onRelease: onRelease, pocketState: pocketState, pocketStateChange: pocketStateChange, pullDownEnabled: pullDownEnabled, reachBottomEnabled: reachBottomEnabled, rtlEnabled: rtlEnabled, scrollByThumb: scrollByThumb, scrollLocation: scrollLocation, scrollLocationChange: scrollLocationChange, scrollableOffset: scrollableOffset, showScrollbar: showScrollbar, topPocketSize: topPocketSize }, scrollbarRef: scrollbarRef, start: start } = viewModel; return createComponentVNode(2, Scrollbar, { direction: direction, onAnimatorStart: start, onAnimatorCancel: cancel, scrollableOffset: scrollableOffset, contentSize: contentSize, containerSize: containerSize, isScrollableHovered: isScrollableHovered, scrollLocation: scrollLocation, scrollLocationChange: scrollLocationChange, contentTranslateOffsetChange: contentTranslateOffsetChange, scrollByThumb: scrollByThumb, bounceEnabled: bounceEnabled, showScrollbar: showScrollbar, forceUpdateScrollbarLocation: forceUpdateScrollbarLocation, rtlEnabled: rtlEnabled, forceGeneratePockets: forceGeneratePockets, topPocketSize: topPocketSize, bottomPocketSize: bottomPocketSize, onPullDown: onPullDown, onRelease: onRelease, onReachBottom: onReachBottom, pullDownEnabled: pullDownEnabled, reachBottomEnabled: reachBottomEnabled, pocketState: pocketState, pocketStateChange: pocketStateChange }, null, scrollbarRef) }; export var AnimatedScrollbarProps = _extends({}, ScrollbarProps); var AnimatedScrollbarPropsType = { activeStateEnabled: AnimatedScrollbarProps.activeStateEnabled, containerSize: AnimatedScrollbarProps.containerSize, contentSize: AnimatedScrollbarProps.contentSize, topPocketSize: AnimatedScrollbarProps.topPocketSize, bottomPocketSize: AnimatedScrollbarProps.bottomPocketSize, scrollableOffset: AnimatedScrollbarProps.scrollableOffset, isScrollableHovered: AnimatedScrollbarProps.isScrollableHovered, forceVisibility: AnimatedScrollbarProps.forceVisibility, forceUpdateScrollbarLocation: AnimatedScrollbarProps.forceUpdateScrollbarLocation, scrollLocation: AnimatedScrollbarProps.scrollLocation, onAnimatorCancel: AnimatedScrollbarProps.onAnimatorCancel, onPullDown: AnimatedScrollbarProps.onPullDown, onReachBottom: AnimatedScrollbarProps.onReachBottom, onRelease: AnimatedScrollbarProps.onRelease, defaultPocketState: AnimatedScrollbarProps.defaultPocketState, direction: ScrollableProps.direction, showScrollbar: ScrollableProps.showScrollbar, scrollByThumb: ScrollableProps.scrollByThumb, pullDownEnabled: ScrollableProps.pullDownEnabled, reachBottomEnabled: ScrollableProps.reachBottomEnabled, forceGeneratePockets: ScrollableProps.forceGeneratePockets, inertiaEnabled: ScrollableSimulatedProps.inertiaEnabled, bounceEnabled: ScrollableSimulatedProps.bounceEnabled }; import { createRef as infernoCreateRef } from "inferno"; export class AnimatedScrollbar extends BaseInfernoComponent { constructor(props) { super(props); this._currentState = null; this.scrollbarRef = infernoCreateRef(); this.stepAnimationFrame = 0; this.finished = true; this.stopped = false; this.velocity = 0; this.animator = "inertia"; this.state = { pocketState: void 0 !== this.props.pocketState ? this.props.pocketState : this.props.defaultPocketState }; this.start = this.start.bind(this); this.cancel = this.cancel.bind(this); this.stepCore = this.stepCore.bind(this); this.getStepAnimationFrame = this.getStepAnimationFrame.bind(this); this.step = this.step.bind(this); this.setupBounce = this.setupBounce.bind(this); this.complete = this.complete.bind(this); this.stop = this.stop.bind(this); this.suppressInertia = this.suppressInertia.bind(this); this.crossBoundOnNextStep = this.crossBoundOnNextStep.bind(this); this.inBounds = this.inBounds.bind(this); this.getMaxOffset = this.getMaxOffset.bind(this); this.scrollStep = this.scrollStep.bind(this); this.moveTo = this.moveTo.bind(this); this.stopComplete = this.stopComplete.bind(this); this.scrollComplete = this.scrollComplete.bind(this); this.boundLocation = this.boundLocation.bind(this); this.getMinOffset = this.getMinOffset.bind(this); this.validateEvent = this.validateEvent.bind(this); this.isThumb = this.isThumb.bind(this); this.reachedMin = this.reachedMin.bind(this); this.reachedMax = this.reachedMax.bind(this); this.initHandler = this.initHandler.bind(this); this.startHandler = this.startHandler.bind(this); this.moveHandler = this.moveHandler.bind(this); this.endHandler = this.endHandler.bind(this); this.stopHandler = this.stopHandler.bind(this); this.scrollByHandler = this.scrollByHandler.bind(this); this.releaseHandler = this.releaseHandler.bind(this) } get __state_pocketState() { var state = this._currentState || this.state; return void 0 !== this.props.pocketState ? this.props.pocketState : state.pocketState } set_pocketState(value) { this.setState(state => { var _this$props$pocketSta, _this$props; this._currentState = state; var newValue = value(); null === (_this$props$pocketSta = (_this$props = this.props).pocketStateChange) || void 0 === _this$props$pocketSta ? void 0 : _this$props$pocketSta.call(_this$props, newValue); this._currentState = null; return { pocketState: newValue } }) } start(animatorName, receivedVelocity, thumbScrolling, crossThumbScrolling) { this.animator = animatorName; if (this.isBounceAnimator) { var _this$props$onBounce, _this$props2; null === (_this$props$onBounce = (_this$props2 = this.props).onBounce) || void 0 === _this$props$onBounce ? void 0 : _this$props$onBounce.call(_this$props2); this.setupBounce() } else { if (!thumbScrolling && crossThumbScrolling) { this.velocity = 0 } else { this.velocity = receivedVelocity || 0 } this.suppressInertia(thumbScrolling) } this.stopped = false; this.finished = false; this.stepCore() } cancel() { this.stopped = true; cancelAnimationFrame(this.stepAnimationFrame) } stepCore() { if (this.stopped) { this.stop(); return } if (this.isFinished) { this.finished = true; this.complete(); return } this.step(); this.stepAnimationFrame = this.getStepAnimationFrame() } getStepAnimationFrame() { return requestAnimationFrame(this.stepCore) } step() { if (!this.props.bounceEnabled && !this.inBounds()) { this.velocity = 0 } this.scrollStep(this.velocity); this.velocity *= this.acceleration } setupBounce() { var bounceDistance = this.boundLocation() - this.props.scrollLocation; this.velocity = bounceDistance / BOUNCE_ACCELERATION_SUM } complete() { if (this.isBounceAnimator) { this.moveTo(this.boundLocation()) } this.scrollComplete() } get isBounceAnimator() { return "bounce" === this.animator } get isFinished() { if (this.isBounceAnimator) { return this.crossBoundOnNextStep() || Math.abs(this.velocity) <= BOUNCE_MIN_VELOCITY_LIMIT } return Math.abs(this.velocity) <= MIN_VELOCITY_LIMIT } get inProgress() { return !(this.stopped || this.finished) } get acceleration() { var _this$scrollbarRef; if (!isDefined(null === (_this$scrollbarRef = this.scrollbarRef) || void 0 === _this$scrollbarRef ? void 0 : _this$scrollbarRef.current)) { return 0 } return this.inBounds() || this.isBounceAnimator ? ACCELERATION : OUT_BOUNDS_ACCELERATION } stop() { this.stopComplete() } suppressInertia(thumbScrolling) { if (!this.props.inertiaEnabled || thumbScrolling) { this.velocity = 0 } } crossBoundOnNextStep() { var location = this.props.scrollLocation; var nextLocation = location + this.velocity; var minOffset = this.getMinOffset(); var maxOffset = this.getMaxOffset(); return location < minOffset && nextLocation >= minOffset || location > maxOffset && nextLocation <= maxOffset } inBounds() { var scrollbar = this.scrollbarRef.current; if (!isDefined(scrollbar)) { return false } return scrollbar.inBounds() } getMaxOffset() { return this.scrollbar.getMaxOffset() } scrollStep(delta) { this.scrollbar.scrollStep(delta) } moveTo(location) { this.scrollbar.moveTo(location) } stopComplete() { this.scrollbar.stopComplete() } scrollComplete() { this.scrollbar.scrollComplete() } get scrollbar() { return this.scrollbarRef.current } get restAttributes() { var _this$props$pocketSta2 = _extends({}, this.props, { pocketState: this.__state_pocketState }), restProps = _objectWithoutPropertiesLoose(_this$props$pocketSta2, _excluded); return restProps } boundLocation(value) { return this.scrollbar.boundLocation(value) } getMinOffset() { return this.scrollbar.getMinOffset() } validateEvent(e) { return this.scrollbar.validateEvent(e) } isThumb(element) { return this.scrollbar.isThumb(element) } reachedMin() { return this.scrollbar.reachedMin() } reachedMax() { return this.scrollbar.reachedMax() } initHandler(e, crossThumbScrolling) { this.scrollbar.initHandler(e, crossThumbScrolling) } startHandler() { this.scrollbar.startHandler() } moveHandler(delta) { this.scrollbar.moveHandler(delta) } endHandler(velocity) { this.scrollbar.endHandler(velocity) } stopHandler() { this.scrollbar.stopHandler() } scrollByHandler(delta) { this.scrollbar.scrollByHandler(delta) } releaseHandler() { this.scrollbar.releaseHandler() } render() { var props = this.props; return viewFunction({ props: _extends({}, props, { pocketState: this.__state_pocketState }), scrollbarRef: this.scrollbarRef, start: this.start, cancel: this.cancel, stepCore: this.stepCore, getStepAnimationFrame: this.getStepAnimationFrame, step: this.step, setupBounce: this.setupBounce, complete: this.complete, isBounceAnimator: this.isBounceAnimator, isFinished: this.isFinished, inProgress: this.inProgress, acceleration: this.acceleration, stop: this.stop, suppressInertia: this.suppressInertia, crossBoundOnNextStep: this.crossBoundOnNextStep, inBounds: this.inBounds, getMaxOffset: this.getMaxOffset, scrollStep: this.scrollStep, moveTo: this.moveTo, stopComplete: this.stopComplete, scrollComplete: this.scrollComplete, scrollbar: this.scrollbar, restAttributes: this.restAttributes }) } } AnimatedScrollbar.defaultProps = _extends({}, AnimatedScrollbarPropsType);