From 313783edb38b0c2780382751ba00d89d50fd3b75 Mon Sep 17 00:00:00 2001 From: bashkos Date: Mon, 10 Apr 2017 18:46:47 +0800 Subject: [PATCH 1/2] Scrollbars class names --- README.md | 22 ++++++- package.json | 1 + src/js/ScrollArea.jsx | 13 ++++- src/js/Scrollbar.jsx | 26 +++++++-- test/scrollArea.spec.js | 23 +++++++- test/scrollBar.spec.js | 126 ++++++++++++++++++++++------------------ 6 files changed, 142 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index f44e19a..7af201d 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ For **React 0.13** you need to wrap `` child into a function. ``` #### Version without boundled css styles #### -If you prefer including scrollbar without css styles boundled inline to js file it's possible to import package without them. It's useful when you want to make custom css changes in scrollbars without using `!important` in each line. +If you prefer including scrollbar without css styles boundled inline to js file it's possible to import package without them. It's useful when you want to make custom css changes in scrollbars without using `!important` in each line. ```js var ScrollArea = require('react-scrollbar/no-css'); @@ -93,10 +93,14 @@ then open [http://localhost:8003](http://localhost:8003). contentClassName={String} contentStyle={Object} horizontal={Boolean} + horizontalContainerClassName={String} horizontalContainerStyle={Object} + horizontalScrollbarClassName={String} horizontalScrollbarStyle={Object} vertical={Boolean} + verticalContainerClassName={String} verticalContainerStyle={Object} + verticalScrollbarClassName={String} verticalScrollbarStyle={Object} onScroll={(value) => {}} contentWindow={Object} @@ -139,9 +143,15 @@ Inline styles applied to element with scroll area content. When set to false, horizontal scrollbar will not be available. **Default: true** +#### horizontalContainerClassName +CSS class names added to horizontal scrollbar's container. + #### horizontalContainerStyle Inline styles applied to horizontal scrollbar's container. +#### horizontalScrollbarClassName +CSS class names added to horizontal scrollbar. + #### horizontalScrollbarStyle Inline styles applied to horizontal scrollbar. @@ -149,9 +159,15 @@ Inline styles applied to horizontal scrollbar. When set to false, vertical scrollbar will not be available, regardless of the content height. **Default: true** +#### verticalContainerClassName +CSS class names added to vertical scrollbar's container. + #### verticalContainerStyle Inline styles applied to vertical scrollbar's container. +#### verticalScrollbarClassName +CSS class names added to vertical scrollbar. + #### verticalScrollbarStyle Inline styles applied to vertical scrollbar. @@ -164,7 +180,7 @@ You can override document to make scrollarea works inside iframe. **Default: document** #### smoothScrolling -When set to true, smooth scrolling for both scrollbars is enabled. +When set to true, smooth scrolling for both scrollbars is enabled. **Default: false** #### minScrollSize @@ -237,7 +253,7 @@ It allows to scroll to the right of `ScrollArea` component. It moves horizontal scrollbar. `leftPosition` is a distance between left edge of `scrollArea` container and left edge of `scrollArea` content. # Change log -Every release is documented on the Github [Releases](https://github.com/souhe/reactScrollbar/releases) page. +Every release is documented on the Github [Releases](https://github.com/souhe/reactScrollbar/releases) page. # License MIT diff --git a/package.json b/package.json index 25630e4..b6b2942 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "author": "souhe", "license": "MIT", "dependencies": { + "classnames": "^2.2.5", "config": "^1.24.0", "line-height": "^0.1.1", "react": "^15.4.1", diff --git a/src/js/ScrollArea.jsx b/src/js/ScrollArea.jsx index 45a5957..6101cde 100644 --- a/src/js/ScrollArea.jsx +++ b/src/js/ScrollArea.jsx @@ -3,6 +3,7 @@ import ScrollBar from './Scrollbar'; import {findDOMNode, warnAboutFunctionChild, warnAboutElementChild, positiveOrZero, modifyObjValues} from './utils'; import lineHeight from 'line-height'; import {Motion, spring} from 'react-motion'; +import classNames from 'classnames'; const eventTypes = { wheel: 'wheel', @@ -97,7 +98,9 @@ export default class ScrollArea extends React.Component { position={this.state.topPosition} onMove={this.handleScrollbarMove.bind(this)} onPositionChange={this.handleScrollbarYPositionChange.bind(this)} + containerClassName={this.props.verticalContainerClassName} containerStyle={this.props.verticalContainerStyle} + scrollbarClassName={this.props.verticalScrollbarClassName} scrollbarStyle={this.props.verticalScrollbarStyle} smoothScrolling={withMotion} minScrollSize={this.props.minScrollSize} @@ -113,7 +116,9 @@ export default class ScrollArea extends React.Component { position={this.state.leftPosition} onMove={this.handleScrollbarMove.bind(this)} onPositionChange={this.handleScrollbarXPositionChange.bind(this)} + containerClassName={this.props.horizontalContainerClassName} containerStyle={this.props.horizontalContainerStyle} + scrollbarClassName={this.props.horizontalScrollbarClassName} scrollbarStyle={this.props.horizontalScrollbarStyle} smoothScrolling={withMotion} minScrollSize={this.props.minScrollSize} @@ -128,8 +133,8 @@ export default class ScrollArea extends React.Component { warnAboutElementChild(); } - let classes = 'scrollarea ' + (className || ''); - let contentClasses = 'scrollarea-content ' + (contentClassName || ''); + let classes = classNames('scrollarea', className); + let contentClasses = classNames('scrollarea-content', contentClassName); let contentStyle = { marginTop: -this.state.topPosition, @@ -456,10 +461,14 @@ ScrollArea.propTypes = { contentClassName: React.PropTypes.string, contentStyle: React.PropTypes.object, vertical: React.PropTypes.bool, + verticalContainerClassName: React.PropTypes.string, verticalContainerStyle: React.PropTypes.object, + verticalScrollbarClassName: React.PropTypes.string, verticalScrollbarStyle: React.PropTypes.object, horizontal: React.PropTypes.bool, + horizontalContainerClassName: React.PropTypes.string, horizontalContainerStyle: React.PropTypes.object, + horizontalScrollbarClassName: React.PropTypes.string, horizontalScrollbarStyle: React.PropTypes.object, onScroll: React.PropTypes.func, contentWindow: React.PropTypes.any, diff --git a/src/js/Scrollbar.jsx b/src/js/Scrollbar.jsx index 98258d4..2721032 100644 --- a/src/js/Scrollbar.jsx +++ b/src/js/Scrollbar.jsx @@ -1,6 +1,7 @@ import React from 'react'; import {Motion, spring} from 'react-motion'; import {modifyObjValues} from './utils'; +import classNames from 'classnames'; class ScrollBar extends React.Component { constructor(props){ @@ -59,25 +60,38 @@ class ScrollBar extends React.Component { } render(){ - let {smoothScrolling, isDragging, type, scrollbarStyle, containerStyle} = this.props; - let isVoriziontal = type === 'horizontal'; + let { + smoothScrolling, isDragging, type, + containerClassName, containerStyle, + scrollbarClassName, scrollbarStyle, + } = this.props; + let isHorizontal = type === 'horizontal'; let isVertical = type === 'vertical'; let scrollStyles = this.createScrollStyles(); let springifiedScrollStyles = smoothScrolling ? modifyObjValues(scrollStyles, x => spring(x)) : scrollStyles; - let scrollbarClasses = `scrollbar-container ${isDragging ? 'active' : ''} ${isVoriziontal ? 'horizontal' : ''} ${isVertical ? 'vertical' : ''}`; + const containerClassNames = classNames( + 'scrollbar-container', + { + active: isDragging, + horizontal: isHorizontal, + vertical: isVertical, + }, + containerClassName, + ); + const scrollbarClassNames = classNames('scrollbar', scrollbarClassName); return ( { style =>
this.scrollbarContainer = x } >
@@ -167,7 +181,9 @@ ScrollBar.propTypes = { realSize: React.PropTypes.number, containerSize: React.PropTypes.number, position: React.PropTypes.number, + containerClassName: React.PropTypes.string, containerStyle: React.PropTypes.object, + scrollbarClassName: React.PropTypes.string, scrollbarStyle: React.PropTypes.object, type: React.PropTypes.oneOf(['vertical', 'horizontal']), ownerDocument: React.PropTypes.any, diff --git a/test/scrollArea.spec.js b/test/scrollArea.spec.js index 91ed624..4e6e9a0 100644 --- a/test/scrollArea.spec.js +++ b/test/scrollArea.spec.js @@ -59,7 +59,7 @@ describe('ScrollArea component', () => { expect(content).toEqualJSX(
{}} style={{}} - className="scrollarea-content " + className="scrollarea-content" onTouchStart={() => {}} onTouchMove={() => {}} onTouchEnd={() => {}} @@ -78,7 +78,7 @@ describe('ScrollArea component', () => {
{}} style={{}} tabIndex={100} - className="scrollarea-content " + className="scrollarea-content" onTouchStart={() => {}} onTouchMove={() => {}} onTouchEnd={() => {}} @@ -118,6 +118,25 @@ describe('ScrollArea component', () => { expect(content.props.style).toEqual({ test: 'contentStyle' }); }); + it('Should have proper scrollbars classes', () => { + let {scrollbars} = setupComponentWithMockedSizes({ + vertical: true, + verticalContainerClassName: 'verticalContainerClassName', + verticalScrollbarClassName: 'verticalScrollbarClassName', + horizontal: true, + horizontalContainerClassName: 'horizontalContainerClassName', + horizontalScrollbarClassName: 'horizontalScrollbarClassName', + }); + + let verticalScrollbar = scrollbars.filter(component => component.props.type === 'vertical')[0]; + let horizontalScrollbar = scrollbars.filter(component => component.props.type === 'horizontal')[0]; + + expect(verticalScrollbar.props.containerClassName).toInclude('verticalContainerClassName'); + expect(verticalScrollbar.props.scrollbarClassName).toInclude('verticalScrollbarClassName'); + expect(horizontalScrollbar.props.containerClassName).toInclude('horizontalContainerClassName'); + expect(horizontalScrollbar.props.scrollbarClassName).toInclude('horizontalScrollbarClassName'); + }); + it('Should have proper scrollbars styles', () => { let {content, scrollbars} = setupComponentWithMockedSizes({ vertical: true, diff --git a/test/scrollBar.spec.js b/test/scrollBar.spec.js index f6fe2a4..71f9a8b 100644 --- a/test/scrollBar.spec.js +++ b/test/scrollBar.spec.js @@ -16,7 +16,7 @@ function setupScrollbar(props){ let wrapper = output.props.children(); let content = wrapper.props.children; - + return { wrapper, content, @@ -33,10 +33,10 @@ function getRendererComponentInstance(renderer){ describe('ScrollBar component', () => { it('Vertical should have proper class', () => { let {wrapper} = setupScrollbar({type: 'vertical'}); - + expect(wrapper.props.className).toInclude('vertical'); }); - + it('Vertical should have proper container styles', () => { let {wrapper} = setupScrollbar({ type: 'vertical', @@ -54,13 +54,13 @@ describe('ScrollBar component', () => { expect(content.props.style).toEqual({test: 'scrollbarStyle'}); }); - + it('Horizontal should have proper class', () => { let {wrapper} = setupScrollbar({type: 'horizontal'}); - + expect(wrapper.props.className).toInclude('horizontal'); }); - + it('Horizontal should have proper container styles', () => { let {wrapper} = setupScrollbar({ type: 'horizontal', @@ -78,30 +78,42 @@ describe('ScrollBar component', () => { expect(content.props.style).toEqual({test: 'scrollbarStyle'}); }); - + + it('Scrollbar should have proper container class', () => { + let {wrapper} = setupScrollbar({containerClassName: 'test-class'}); + + expect(wrapper.props.className).toInclude('test-class'); + }); + + it('Scrollbar should have proper element class', () => { + let {content} = setupScrollbar({scrollbarClassName: 'test-class'}); + + expect(content.props.className).toInclude('test-class'); + }); + it('ScrollBar should be in proper position', () => { let {instance} = setupScrollbar({ - realSize: 400, - containerSize: 100, + realSize: 400, + containerSize: 100, position: 20 }); - - expect(instance.state.position).toBe(5); + + expect(instance.state.position).toBe(5); }); - + it('ScrollBar should have proper size', () => { let { instance } = setupScrollbar({ - realSize: 400, + realSize: 400, containerSize: 100 }); - - expect(instance.state.scrollSize).toBe(25); + + expect(instance.state.scrollSize).toBe(25); }); - + it('Should propagate onMove event after move vertical scrollbar', () => { let handleMoveSpy = expect.createSpy(); let {instance} = setupScrollbar({ - realSize: 200, + realSize: 200, containerSize: 100, onMove: handleMoveSpy, onFocus: () => {} @@ -110,15 +122,15 @@ describe('ScrollBar component', () => { let moveEvent = {clientY: 25, preventDefault: () => {}}; instance.handleMouseDown(mouseDownEvent); instance.handleMouseMoveForVertical(moveEvent); - + expect(handleMoveSpy.calls.length).toEqual(1); expect(handleMoveSpy.calls[0].arguments).toEqual([-50 , 0]); }); - + it('Should propagate onMove event after move horizontal scrollbar', () => { let handleMoveSpy = expect.createSpy(); let {instance} = setupScrollbar({ - realSize: 200, + realSize: 200, containerSize: 100, onMove: handleMoveSpy, type: 'horizontal', @@ -128,15 +140,15 @@ describe('ScrollBar component', () => { let moveEvent = {clientX: 25, preventDefault: () => {}}; instance.handleMouseDown(mouseDownEvent); instance.handleMouseMoveForHorizontal(moveEvent); - + expect(handleMoveSpy.calls.length).toEqual(1); expect(handleMoveSpy.calls[0].arguments).toEqual([0, -50]); }); - + it('Should propagate onMove event multiple times', () => { let handleMoveSpy = expect.createSpy(); let {instance} = setupScrollbar({ - realSize: 400, + realSize: 400, containerSize: 100, onMove: handleMoveSpy, onFocus: () => {} @@ -151,65 +163,65 @@ describe('ScrollBar component', () => { instance.handleMouseMoveForVertical(moveEvent); moveEvent.clientY = 40; instance.handleMouseMoveForVertical(moveEvent); - + expect(handleMoveSpy.calls.length).toEqual(4); expect(handleMoveSpy.calls[3].arguments).toEqual([-40 , 0]); }); - + it('Should be possible to set min scrollbar size', () => { let minScrollBarSize = 10; let {instance} = setupScrollbar({ - realSize: 10000, + realSize: 10000, containerSize: 100, type: 'vertical', minScrollSize: minScrollBarSize, onFocus: () => {} - }); - - expect(instance.state.scrollSize).toBe(minScrollBarSize); + }); + + expect(instance.state.scrollSize).toBe(minScrollBarSize); }); - + it('Method calculateFractionalPosition should work properly for realSize: 300, containerSize: 100, position: 0', () => { let {instance} = setupScrollbar(); - + expect(instance.calculateFractionalPosition(300, 100, 0)).toEqual(0); }); - + it('Method calculateFractionalPosition should work properly for realSize: 300, containerSize: 100, position: 200', () => { let {instance} = setupScrollbar(); - + expect(instance.calculateFractionalPosition(300, 100, 200)).toEqual(1); }); - + it('Method calculateFractionalPosition should work properly for realSize: 300, containerSize: 100, position: 200', () => { let {instance} = setupScrollbar(); - + expect(instance.calculateFractionalPosition(300, 100, 100)).toEqual(0.5); }); - + it('Method calculateFractionalPosition should work properly for realSize: 160, containerSize: 80, position: 20', () => { let {instance} = setupScrollbar(); - + expect(instance.calculateFractionalPosition(160, 80, 20)).toEqual(0.25); }); - + it('Position of scrollbar should be proper when minScrollBarSize is set', () => { let {instance} = setupScrollbar({ - position: 9900, + position: 9900, realSize: 10000, containerSize: 100, type: 'vertical', minScrollSize: 10 - }); - + }); + expect(instance.state.position).toBe(90); }); - + it('vertical scrollbar container click should move scrollbar', () => { let handlePositionChangeSpy = expect.createSpy(); let {instance} = setupScrollbar({ position: 0, - realSize: 500, + realSize: 500, containerSize: 100, type: 'vertical', onPositionChange: handlePositionChangeSpy @@ -221,16 +233,16 @@ describe('ScrollBar component', () => { }) }; instance.handleScrollBarContainerClick(mouseDownEvent); - + expect(handlePositionChangeSpy.calls.length).toEqual(1); - expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); + expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); }); - + it('vertical scrollbar container click should move scrollbar when minScrollbar size is set', () => { let handlePositionChangeSpy = expect.createSpy(); let {instance} = setupScrollbar({ position: 0, - realSize: 1000, + realSize: 1000, containerSize: 100, type: 'vertical', onPositionChange: handlePositionChangeSpy, @@ -243,16 +255,16 @@ describe('ScrollBar component', () => { }) }; instance.handleScrollBarContainerClick(mouseDownEvent); - + expect(handlePositionChangeSpy.calls.length).toEqual(1); - expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); + expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); }); - + it('horizontal scrollbar container click should move scrollbar', () => { let handlePositionChangeSpy = expect.createSpy(); let {instance} = setupScrollbar({ position: 0, - realSize: 500, + realSize: 500, containerSize: 100, type: 'horizontal', onPositionChange: handlePositionChangeSpy @@ -264,16 +276,16 @@ describe('ScrollBar component', () => { }) }; instance.handleScrollBarContainerClick(mouseDownEvent); - + expect(handlePositionChangeSpy.calls.length).toEqual(1); - expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); + expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); }); - + it('horizontal scrollbar container click should move scrollbar when minScrollbar size is set', () => { let handlePositionChangeSpy = expect.createSpy(); let {instance} = setupScrollbar({ position: 0, - realSize: 1000, + realSize: 1000, containerSize: 100, type: 'horizontal', onPositionChange: handlePositionChangeSpy, @@ -286,8 +298,8 @@ describe('ScrollBar component', () => { }) }; instance.handleScrollBarContainerClick(mouseDownEvent); - + expect(handlePositionChangeSpy.calls.length).toEqual(1); - expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); + expect(handlePositionChangeSpy.calls[0].arguments).toEqual([200]); }); }); From a41ffbe2b3fcc9796fa45add4f1a4ceacd3a5af9 Mon Sep 17 00:00:00 2001 From: bashkos Date: Wed, 10 May 2017 10:52:55 +0800 Subject: [PATCH 2/2] Remove *.orig files --- src/js/ScrollArea.jsx.orig | 518 ------------------------------------- src/js/Scrollbar.jsx.orig | 219 ---------------- 2 files changed, 737 deletions(-) delete mode 100644 src/js/ScrollArea.jsx.orig delete mode 100644 src/js/Scrollbar.jsx.orig diff --git a/src/js/ScrollArea.jsx.orig b/src/js/ScrollArea.jsx.orig deleted file mode 100644 index bece3e2..0000000 --- a/src/js/ScrollArea.jsx.orig +++ /dev/null @@ -1,518 +0,0 @@ -import React from 'react'; -import ScrollBar from './Scrollbar'; -import {findDOMNode, warnAboutFunctionChild, warnAboutElementChild, positiveOrZero, modifyObjValues} from './utils'; -import lineHeight from 'line-height'; -import {Motion, spring} from 'react-motion'; -<<<<<<< HEAD -import PropTypes from 'prop-types'; -======= -import classNames from 'classnames'; ->>>>>>> 313783edb38b0c2780382751ba00d89d50fd3b75 - -const eventTypes = { - wheel: 'wheel', - api: 'api', - touch: 'touch', - touchEnd: 'touchEnd', - mousemove: 'mousemove', - keyPress: 'keypress' -}; - -export default class ScrollArea extends React.Component { - constructor(props) { - super(props); - this.state = { - topPosition: 0, - leftPosition: 0, - realHeight: 0, - containerHeight: 0, - realWidth: 0, - containerWidth: 0 - }; - - this.scrollArea = { - refresh: () => { - this.setSizesToState(); - }, - scrollTop: () => { - this.scrollTop(); - }, - scrollBottom: () => { - this.scrollBottom(); - }, - scrollYTo: (position) => { - this.scrollYTo(position); - }, - scrollLeft: () => { - this.scrollLeft(); - }, - scrollRight: () => { - this.scrollRight(); - }, - scrollXTo: (position) => { - this.scrollXTo(position); - } - }; - - this.evntsPreviousValues = { - clientX: 0, - clientY: 0, - deltaX: 0, - deltaY: 0 - }; - - this.bindedHandleWindowResize = this.handleWindowResize.bind(this); - } - - getChildContext() { - return { - scrollArea: this.scrollArea - }; - } - - componentDidMount() { - if (this.props.contentWindow) { - this.props.contentWindow.addEventListener("resize", this.bindedHandleWindowResize); - } - this.lineHeightPx = lineHeight(findDOMNode(this.content)); - this.setSizesToState(); - } - - componentWillUnmount() { - if (this.props.contentWindow) { - this.props.contentWindow.removeEventListener("resize", this.bindedHandleWindowResize); - } - } - - componentDidUpdate() { - this.setSizesToState(); - } - - render() { - let {children, className, contentClassName, ownerDocument} = this.props; - let withMotion = this.props.smoothScrolling && - (this.state.eventType === eventTypes.wheel || this.state.eventType === eventTypes.api || this.state.eventType === eventTypes.touchEnd || - this.state.eventType === eventTypes.keyPress); - - let scrollbarY = this.canScrollY() ? ( - - ) : null; - - let scrollbarX = this.canScrollX() ? ( - - ) : null; - - if (typeof children === 'function') { - warnAboutFunctionChild(); - children = children(); - } else { - warnAboutElementChild(); - } - - let classes = classNames('scrollarea', className); - let contentClasses = classNames('scrollarea-content', contentClassName); - - let contentStyle = { - marginTop: -this.state.topPosition, - marginLeft: -this.state.leftPosition - }; - let springifiedContentStyle = withMotion ? modifyObjValues(contentStyle, x => spring(x)) : contentStyle; - - return ( - - { style => -
this.wrapper = x} - className={classes} - style={this.props.style} - onWheel={this.handleWheel.bind(this)} - > -
this.content = x} - style={{ ...this.props.contentStyle, ...style }} - className={contentClasses} - onTouchStart={this.handleTouchStart.bind(this)} - onTouchMove={this.handleTouchMove.bind(this)} - onTouchEnd={this.handleTouchEnd.bind(this)} - onKeyDown={this.handleKeyDown.bind(this)} - tabIndex={this.props.focusableTabIndex} - > - {children} -
- {scrollbarY} - {scrollbarX} -
- } -
- ); - } - - setStateFromEvent(newState, eventType) { - if (this.props.onScroll) { - this.props.onScroll(newState); - } - this.setState({...newState, eventType}); - } - - handleTouchStart(e) { - let {touches} = e; - if (touches.length === 1) { - let {clientX, clientY} = touches[0]; - this.eventPreviousValues = { - ...this.eventPreviousValues, - clientY, - clientX, - timestamp: Date.now() - }; - } - } - - handleTouchMove(e) { - e.preventDefault(); - e.stopPropagation(); - - let {touches} = e; - if (touches.length === 1) { - let {clientX, clientY} = touches[0]; - - let deltaY = this.eventPreviousValues.clientY - clientY; - let deltaX = this.eventPreviousValues.clientX - clientX; - - this.eventPreviousValues = { - ...this.eventPreviousValues, - deltaY, - deltaX, - clientY, - clientX, - timestamp: Date.now() - }; - - this.setStateFromEvent(this.composeNewState(-deltaX, -deltaY)); - } - } - - handleTouchEnd(e) { - let {deltaX, deltaY, timestamp} = this.eventPreviousValues; - if (typeof deltaX === 'undefined') deltaX = 0; - if (typeof deltaY === 'undefined') deltaY = 0; - if (Date.now() - timestamp < 200) { - this.setStateFromEvent(this.composeNewState(-deltaX * 10, -deltaY * 10), eventTypes.touchEnd); - } - - this.eventPreviousValues = { - ...this.eventPreviousValues, - deltaY: 0, - deltaX: 0 - }; - } - - handleScrollbarMove(deltaY, deltaX) { - this.setStateFromEvent(this.composeNewState(deltaX, deltaY)); - } - - handleScrollbarXPositionChange(position) { - this.scrollXTo(position); - } - - handleScrollbarYPositionChange(position) { - this.scrollYTo(position); - } - - handleWheel(e) { - let deltaY = e.deltaY; - let deltaX = e.deltaX; - - if (this.props.swapWheelAxes) { - [deltaY, deltaX] = [deltaX, deltaY]; - } - - /* - * WheelEvent.deltaMode can differ between browsers and must be normalized - * e.deltaMode === 0: The delta values are specified in pixels - * e.deltaMode === 1: The delta values are specified in lines - * https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/deltaMode - */ - if (e.deltaMode === 1) { - deltaY = deltaY * this.lineHeightPx; - deltaX = deltaX * this.lineHeightPx; - } - - deltaY = deltaY * this.props.speed; - deltaX = deltaX * this.props.speed; - - let newState = this.composeNewState(-deltaX, -deltaY); - - if ((newState.topPosition && this.state.topPosition !== newState.topPosition) || - (newState.leftPosition && this.state.leftPosition !== newState.leftPosition) || - this.props.stopScrollPropagation) { - e.preventDefault(); - e.stopPropagation(); - } - - this.setStateFromEvent(newState, eventTypes.wheel); - this.focusContent(); - } - - handleKeyDown(e) { - // only handle if scroll area is in focus - if (e.target.tagName.toLowerCase() !== 'input') { - let deltaY = 0; - let deltaX = 0; - let lineHeight = this.lineHeightPx ? this.lineHeightPx : 10; - - switch (e.keyCode) { - case 33: // page up - deltaY = this.state.containerHeight - lineHeight; - break; - case 34: // page down - deltaY = -this.state.containerHeight + lineHeight; - break; - case 37: // left - deltaX = lineHeight; - break; - case 38: // up - deltaY = lineHeight; - break; - case 39: // right - deltaX = -lineHeight; - break; - case 40: // down - deltaY = -lineHeight; - break; - } - - // only compose new state if key code matches those above - if (deltaY !== 0 || deltaX !== 0) { - let newState = this.composeNewState(deltaX, deltaY); - - e.preventDefault(); - e.stopPropagation(); - - this.setStateFromEvent(newState, eventTypes.keyPress); - } - } - } - - handleWindowResize() { - let newState = this.computeSizes(); - newState = this.getModifiedPositionsIfNeeded(newState); - this.setStateFromEvent(newState); - } - - composeNewState(deltaX, deltaY) { - let newState = this.computeSizes(); - - if (this.canScrollY(newState)) { - newState.topPosition = this.computeTopPosition(deltaY, newState); - } else { - newState.topPosition = 0; - } - if (this.canScrollX(newState)) { - newState.leftPosition = this.computeLeftPosition(deltaX, newState); - } - - return newState; - } - - computeTopPosition(deltaY, sizes) { - let newTopPosition = this.state.topPosition - deltaY; - return this.normalizeTopPosition(newTopPosition, sizes); - } - - computeLeftPosition(deltaX, sizes) { - let newLeftPosition = this.state.leftPosition - deltaX; - return this.normalizeLeftPosition(newLeftPosition, sizes); - } - - normalizeTopPosition(newTopPosition, sizes) { - if (newTopPosition > sizes.realHeight - sizes.containerHeight) { - newTopPosition = sizes.realHeight - sizes.containerHeight; - } - if (newTopPosition < 0) { - newTopPosition = 0; - } - return newTopPosition; - } - - normalizeLeftPosition(newLeftPosition, sizes) { - if (newLeftPosition > sizes.realWidth - sizes.containerWidth) { - newLeftPosition = sizes.realWidth - sizes.containerWidth; - } else if (newLeftPosition < 0) { - newLeftPosition = 0; - } - - return newLeftPosition; - } - - computeSizes() { - let realHeight = this.content.offsetHeight; - let containerHeight = this.wrapper.offsetHeight; - let realWidth = this.content.offsetWidth; - let containerWidth = this.wrapper.offsetWidth; - - return { - realHeight: realHeight, - containerHeight: containerHeight, - realWidth: realWidth, - containerWidth: containerWidth - }; - } - - setSizesToState() { - let sizes = this.computeSizes(); - if (sizes.realHeight !== this.state.realHeight || sizes.realWidth !== this.state.realWidth) { - this.setStateFromEvent(this.getModifiedPositionsIfNeeded(sizes)); - } - } - - scrollTop() { - this.scrollYTo(0); - } - - scrollBottom() { - this.scrollYTo((this.state.realHeight - this.state.containerHeight)); - } - - scrollLeft() { - this.scrollXTo(0); - } - - scrollRight() { - this.scrollXTo((this.state.realWidth - this.state.containerWidth)); - } - - scrollYTo(topPosition) { - if (this.canScrollY()) { - let position = this.normalizeTopPosition(topPosition, this.computeSizes()); - this.setStateFromEvent({topPosition: position}, eventTypes.api); - } - } - - scrollXTo(leftPosition) { - if (this.canScrollX()) { - let position = this.normalizeLeftPosition(leftPosition, this.computeSizes()); - this.setStateFromEvent({leftPosition: position}, eventTypes.api); - } - } - - canScrollY(state = this.state) { - let scrollableY = state.realHeight > state.containerHeight; - return scrollableY && this.props.vertical; - } - - canScrollX(state = this.state) { - let scrollableX = state.realWidth > state.containerWidth; - return scrollableX && this.props.horizontal; - } - - getModifiedPositionsIfNeeded(newState) { - let bottomPosition = newState.realHeight - newState.containerHeight; - if (this.state.topPosition >= bottomPosition) { - newState.topPosition = this.canScrollY(newState) ? positiveOrZero(bottomPosition) : 0; - } - - let rightPosition = newState.realWidth - newState.containerWidth; - if (this.state.leftPosition >= rightPosition) { - newState.leftPosition = this.canScrollX(newState) ? positiveOrZero(rightPosition) : 0; - } - - return newState; - } - - focusContent() { - if(this.content) { - findDOMNode(this.content).focus(); - } - } -} - -ScrollArea.childContextTypes = { - scrollArea: PropTypes.object -}; - -ScrollArea.propTypes = { -<<<<<<< HEAD - className: PropTypes.string, - style: PropTypes.object, - speed: PropTypes.number, - contentClassName: PropTypes.string, - contentStyle: PropTypes.object, - vertical: PropTypes.bool, - verticalContainerStyle: PropTypes.object, - verticalScrollbarStyle: PropTypes.object, - horizontal: PropTypes.bool, - horizontalContainerStyle: PropTypes.object, - horizontalScrollbarStyle: PropTypes.object, - onScroll: PropTypes.func, - contentWindow: PropTypes.any, - ownerDocument: PropTypes.any, - smoothScrolling: PropTypes.bool, - minScrollSize: PropTypes.number, - swapWheelAxes: PropTypes.bool, - stopScrollPropagation: PropTypes.bool, - focusableTabIndex: PropTypes.number -======= - className: React.PropTypes.string, - style: React.PropTypes.object, - speed: React.PropTypes.number, - contentClassName: React.PropTypes.string, - contentStyle: React.PropTypes.object, - vertical: React.PropTypes.bool, - verticalContainerClassName: React.PropTypes.string, - verticalContainerStyle: React.PropTypes.object, - verticalScrollbarClassName: React.PropTypes.string, - verticalScrollbarStyle: React.PropTypes.object, - horizontal: React.PropTypes.bool, - horizontalContainerClassName: React.PropTypes.string, - horizontalContainerStyle: React.PropTypes.object, - horizontalScrollbarClassName: React.PropTypes.string, - horizontalScrollbarStyle: React.PropTypes.object, - onScroll: React.PropTypes.func, - contentWindow: React.PropTypes.any, - ownerDocument: React.PropTypes.any, - smoothScrolling: React.PropTypes.bool, - minScrollSize: React.PropTypes.number, - swapWheelAxes: React.PropTypes.bool, - stopScrollPropagation: React.PropTypes.bool, - focusableTabIndex: React.PropTypes.number ->>>>>>> 313783edb38b0c2780382751ba00d89d50fd3b75 -}; - -ScrollArea.defaultProps = { - speed: 1, - vertical: true, - horizontal: true, - smoothScrolling: false, - swapWheelAxes: false, - contentWindow: (typeof window === "object") ? window : undefined, - ownerDocument: (typeof document === "object") ? document : undefined, - focusableTabIndex: 1 -}; diff --git a/src/js/Scrollbar.jsx.orig b/src/js/Scrollbar.jsx.orig deleted file mode 100644 index db95dbb..0000000 --- a/src/js/Scrollbar.jsx.orig +++ /dev/null @@ -1,219 +0,0 @@ -import React from 'react'; -import {Motion, spring} from 'react-motion'; -import {modifyObjValues} from './utils'; -<<<<<<< HEAD -import PropTypes from 'prop-types'; -======= -import classNames from 'classnames'; ->>>>>>> 313783edb38b0c2780382751ba00d89d50fd3b75 - -class ScrollBar extends React.Component { - constructor(props){ - super(props); - let newState = this.calculateState(props); - this.state = { - position: newState.position, - scrollSize: newState.scrollSize, - isDragging: false, - lastClientPosition: 0 - }; - - if(props.type === 'vertical'){ - this.bindedHandleMouseMove = this.handleMouseMoveForVertical.bind(this); - } else { - this.bindedHandleMouseMove = this.handleMouseMoveForHorizontal.bind(this); - } - - this.bindedHandleMouseUp = this.handleMouseUp.bind(this); - } - - componentDidMount(){ - if (this.props.ownerDocument) { - this.props.ownerDocument.addEventListener("mousemove", this.bindedHandleMouseMove); - this.props.ownerDocument.addEventListener("mouseup", this.bindedHandleMouseUp); - } - } - - componentWillReceiveProps(nextProps){ - this.setState(this.calculateState(nextProps)); - } - - componentWillUnmount(){ - if (this.props.ownerDocument) { - this.props.ownerDocument.removeEventListener("mousemove", this.bindedHandleMouseMove); - this.props.ownerDocument.removeEventListener("mouseup", this.bindedHandleMouseUp); - } - } - - calculateFractionalPosition(realContentSize, containerSize, contentPosition){ - let relativeSize = realContentSize - containerSize; - - return 1 - ((relativeSize - contentPosition) / relativeSize); - } - - calculateState(props){ - let fractionalPosition = this.calculateFractionalPosition(props.realSize, props.containerSize, props.position); - let proportionalToPageScrollSize = props.containerSize * props.containerSize / props.realSize; - let scrollSize = proportionalToPageScrollSize < props.minScrollSize ? props.minScrollSize : proportionalToPageScrollSize; - - let scrollPosition = (props.containerSize - scrollSize) * fractionalPosition; - return { - scrollSize: scrollSize, - position: Math.round(scrollPosition) - }; - } - - render(){ - let { - smoothScrolling, isDragging, type, - containerClassName, containerStyle, - scrollbarClassName, scrollbarStyle, - } = this.props; - let isHorizontal = type === 'horizontal'; - let isVertical = type === 'vertical'; - let scrollStyles = this.createScrollStyles(); - let springifiedScrollStyles = smoothScrolling ? modifyObjValues(scrollStyles, x => spring(x)) : scrollStyles; - - const containerClassNames = classNames( - 'scrollbar-container', - { - active: isDragging, - horizontal: isHorizontal, - vertical: isVertical, - }, - containerClassName, - ); - const scrollbarClassNames = classNames('scrollbar', scrollbarClassName); - - return ( - - { style => -
this.scrollbarContainer = x } - > -
-
- } - - ); - } - - handleScrollBarContainerClick(e) { - e.preventDefault(); - let multiplier = this.computeMultiplier(); - let clientPosition = this.isVertical() ? e.clientY : e.clientX; - let { top, left } = this.scrollbarContainer.getBoundingClientRect(); - let clientScrollPosition = this.isVertical() ? top : left; - - let position = clientPosition - clientScrollPosition; - let proportionalToPageScrollSize = this.props.containerSize * this.props.containerSize / this.props.realSize; - - this.setState({isDragging: true, lastClientPosition: clientPosition }); - this.props.onPositionChange((position - proportionalToPageScrollSize / 2) / multiplier); - } - - handleMouseMoveForHorizontal(e){ - let multiplier = this.computeMultiplier(); - - if(this.state.isDragging){ - e.preventDefault(); - let deltaX = this.state.lastClientPosition - e.clientX; - this.setState({ lastClientPosition: e.clientX }); - this.props.onMove(0, deltaX / multiplier); - } - } - - handleMouseMoveForVertical(e){ - let multiplier = this.computeMultiplier(); - - if(this.state.isDragging){ - e.preventDefault(); - let deltaY = this.state.lastClientPosition - e.clientY; - this.setState({ lastClientPosition: e.clientY }); - this.props.onMove(deltaY / multiplier, 0); - } - } - - handleMouseDown(e){ - e.preventDefault(); - e.stopPropagation(); - let lastClientPosition = this.isVertical() ? e.clientY: e.clientX; - this.setState({isDragging: true, lastClientPosition: lastClientPosition }); - - this.props.onFocus(); - } - - handleMouseUp(e){ - if (this.state.isDragging) { - e.preventDefault(); - this.setState({isDragging: false }); - } - } - - createScrollStyles(){ - if(this.props.type === 'vertical'){ - return { - height: this.state.scrollSize, - marginTop: this.state.position - }; - } else { - return { - width: this.state.scrollSize, - marginLeft: this.state.position - }; - } - } - - computeMultiplier(){ - return (this.props.containerSize) / this.props.realSize; - } - - isVertical(){ - return this.props.type === 'vertical'; - } -} - -ScrollBar.propTypes = { -<<<<<<< HEAD - onMove: PropTypes.func, - onPositionChange: PropTypes.func, - onFocus: PropTypes.func, - realSize: PropTypes.number, - containerSize: PropTypes.number, - position: PropTypes.number, - containerStyle: PropTypes.object, - scrollbarStyle: PropTypes.object, - type: PropTypes.oneOf(['vertical', 'horizontal']), - ownerDocument: PropTypes.any, - smoothScrolling: PropTypes.bool, - minScrollSize: PropTypes.number -======= - onMove: React.PropTypes.func, - onPositionChange: React.PropTypes.func, - onFocus: React.PropTypes.func, - realSize: React.PropTypes.number, - containerSize: React.PropTypes.number, - position: React.PropTypes.number, - containerClassName: React.PropTypes.string, - containerStyle: React.PropTypes.object, - scrollbarClassName: React.PropTypes.string, - scrollbarStyle: React.PropTypes.object, - type: React.PropTypes.oneOf(['vertical', 'horizontal']), - ownerDocument: React.PropTypes.any, - smoothScrolling: React.PropTypes.bool, - minScrollSize: React.PropTypes.number ->>>>>>> 313783edb38b0c2780382751ba00d89d50fd3b75 -}; - -ScrollBar.defaultProps = { - type : 'vertical', - smoothScrolling: false -}; -export default ScrollBar;