Skip to content

Commit

Permalink
Merge df6d87b into 999ec23
Browse files Browse the repository at this point in the history
  • Loading branch information
lbebber committed Apr 4, 2019
2 parents 999ec23 + df6d87b commit 04ee9a9
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 24 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added
- Better support for the `sticky` prop. Now it allows multiple and interspected sticky rows.

## [2.11.0] - 2019-03-28

### Added
Expand Down
2 changes: 1 addition & 1 deletion react/components/Border.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import React from 'react'

export default () => <div />
export default () => <div className="bb b--muted-3" />
13 changes: 8 additions & 5 deletions react/components/Layout.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React from 'react'
import StickyRows from './StickyRows'

const Layout = ({ children }) => (
<React.Fragment>
{children}
</React.Fragment>
)
const Layout = ({ children }) => {
return (
<StickyRows>
{children}
</StickyRows>
)
}

export default Layout
13 changes: 6 additions & 7 deletions react/components/Row.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@ import React from 'react'
import classNames from 'classnames'
import { Container } from 'vtex.store-components'

const Row = ({ children, fullWidth, sticky, inverted }) => {
const Row = ({
children,
fullWidth,
inverted,
}) => {
const content = (
<div className="w-100 flex items-center">
{children}
</div>
)

return (
<div
className={classNames('w-100 top-0', inverted ? 'bg-base--inverted c-on-base--inverted' : 'bg-base c-on-base', { 'z-999': sticky })}
style={{
// TODO: use `sticky` class once it's available on render
position: sticky ? 'sticky' : 'relative',
}}>
<div className={classNames('w-100', inverted ? 'bg-base--inverted c-on-base--inverted' : 'bg-base c-on-base')}>
{fullWidth ? content : (
<Container className="w-100 flex">
{content}
Expand Down
33 changes: 33 additions & 0 deletions react/components/StickyRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { FunctionComponent } from 'react'
import ReactResizeDetector from 'react-resize-detector'

interface Props {
sticky?: boolean
offset?: number
onResize?(height?: number): void
}

const StickyRow: FunctionComponent<Props> = ({
children,
sticky,
offset = 0,
onResize,
}) => (
<div
style={sticky ? {
position: 'sticky',
top: offset,
zIndex: 999,
} : {}}>

{children}

{sticky && (
<ReactResizeDetector
handleHeight
onResize={(width, height) => onResize && onResize(height)}/>
)}
</div>
)

export default StickyRow
27 changes: 27 additions & 0 deletions react/components/StickyRows.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { FunctionComponent, ReactElement } from 'react'
import useCumulativeHeightState from '../hooks/useCumulativeHeightState'
import StickyRow from './StickyRow'

interface Props {
children: ReactElement | ReactElement[]
}

const StickyRows: FunctionComponent<Props> = ({ children }: Props) => {
const { updateRowHeight, getAccumulatedHeight } = useCumulativeHeightState()

return (
<React.Fragment>
{React.Children.map(children, (child, index) => (
<StickyRow
sticky={child.props.sticky}
onResize={(height: number) => updateRowHeight({ height, index })}
offset={getAccumulatedHeight(index)}
>
{child}
</StickyRow>
))}
</React.Fragment>
)
}

export default StickyRows
62 changes: 62 additions & 0 deletions react/hooks/useCumulativeHeightState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react'

interface State {
[id: string]: number
}

interface UpdateAction {
type: 'update'
payload: {
index: number
height: number
}
}

type Actions = UpdateAction

const reducer = (state: State, action: Actions) => {
switch(action.type) {
case 'update':
return {
...state,
[action.payload.index]: action.payload.height,
}
default:
return state
}
}

const useCumulativeHeightState = () => {
const [state, dispatch]: [State, React.Dispatch<UpdateAction>] = React.useReducer(reducer, {})

const updateRowHeight = ({ height, index }: { height: number, index: number }) => {
if (state[index] === height) {
return
}

dispatch({
payload: {
height,
index,
},
type: 'update',
})
}

const getAccumulatedHeight = (index: number) => {
const sortedIndices = Object.keys(state)
.map(key => parseInt(key, 10))
.sort()

const indices = sortedIndices.slice(0, sortedIndices.indexOf(index))

return indices.reduce((acc, cur) => (state[cur] || 0) + acc ,0)
}

return {
getAccumulatedHeight,
updateRowHeight,
}
}

export default useCumulativeHeightState
8 changes: 6 additions & 2 deletions react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"gen:coveralls": "yarn test:coverage && cat ./coverage/lcov.info | coveralls"
},
"dependencies": {
"@types/react-resize-detector": "^3.1.1",
"classnames": "^2.2.5",
"debounce": "^1.2.0",
"hoist-non-react-statics": "^3.0.1",
Expand All @@ -17,9 +18,12 @@
"react-dom": "^16.3.2",
"react-intl": "^2.4.0",
"react-media": "^1.9.2",
"react-resize-detector": "^3.0.1",
"react-resize-detector": "^4.0.5",
"react-spring": "^8.0.7",
"throttleit": "^1.0.0"
"throttleit": "^1.0.0",
"tslint": "^5.14.0",
"tslint-config-vtex": "^2.1.0",
"typescript": "^3.4.1"
},
"vtexScriptsOverride": {
"srcPath": "."
Expand Down
20 changes: 20 additions & 0 deletions react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"jsx": "react",
"lib": ["es2017", "dom"],
"module": "es6",
"moduleResolution": "node",
"sourceMap": true,
"target": "es2017",
"skipLibCheck": true,
"strict": true,
"types": ["node", "jest", "graphql"]
},
"typeAcquisition": {
"enable": false
},
"include": ["./typings/*.d.ts", "./**/*.tsx"],
"exclude": ["node_modules"]
}
3 changes: 3 additions & 0 deletions react/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "tslint-config-vtex"
}

0 comments on commit 04ee9a9

Please sign in to comment.