Refacto de du composant Distribution

⬆ MAJ de react-spring vers version 8
Quelques changements d'API. Par ailleurs la version 8 exporte deux modules
l'un avec les "render-props" et l'autres avec les "hooks"

🔥 Suppression de @researchgate/react-intersection-observer
Remplacement par un custom hook
pull/706/head
Maxime Quandalle 2019-10-08 17:34:45 +02:00
parent 33c1a06b6c
commit d2098c3d0c
No known key found for this signature in database
GPG Key ID: 428641C03D29CA10
5 changed files with 118 additions and 112 deletions

View File

@ -21,7 +21,6 @@
"dependencies": {
"@babel/polyfill": "^7.4.0",
"@babel/runtime": "^7.3.4",
"@researchgate/react-intersection-observer": "^0.7.3",
"classnames": "^2.2.5",
"color-convert": "^1.9.2",
"core-js": "^3.2.1",
@ -51,7 +50,7 @@
"react-router-dom": "^5.1.1",
"react-select": "^1.2.1",
"react-select-fast-filter-options": "^0.2.3",
"react-spring": "^5.8.0",
"react-spring": "=8.0.27",
"react-syntax-highlighter": "^10.1.1",
"react-transition-group": "^2.2.1",
"react-virtualized": "^9.20.0",

View File

@ -1,114 +1,98 @@
/* @flow */
import Observer from '@researchgate/react-intersection-observer'
import withColours from 'Components/utils/withColours'
import { ThemeColoursContext } from 'Components/utils/withColours'
import Value from 'Components/Value'
import { findRuleByDottedName } from 'Engine/rules'
import React, { useState } from 'react'
import React, { useContext } from 'react'
import emoji from 'react-easy-emoji'
import { connect } from 'react-redux'
import { config, Spring } from 'react-spring'
import { compose } from 'redux'
import { useSelector } from 'react-redux'
import { config, animated, useSpring } from 'react-spring'
import { flatRulesSelector } from 'Selectors/analyseSelectors'
import répartitionSelector from 'Selectors/repartitionSelectors'
import { isIE } from '../utils'
import './Distribution.css'
import './PaySlip'
import RuleLink from './RuleLink'
import type { ThemeColours } from 'Components/utils/withColours'
import type { Répartition } from 'Types/ResultViewTypes.js'
import useDisplayOnIntersecting from 'Components/utils/useDisplayOnIntersecting'
type Props = ?Répartition & {
colours: ThemeColours
}
const ANIMATION_SPRING = config.gentle
function Distribution({
colours: { colour },
rules,
// $FlowFixMe
...distribution
}: Props) {
const [branchesInViewport, setBranchesInViewport] = useState([])
const handleBrancheInViewport = branche => (event, unobserve) => {
if (!event.isIntersecting) {
return
}
unobserve()
setBranchesInViewport(branchesInViewport => [
branche,
...branchesInViewport
])
}
export default function Distribution() {
const distribution = useSelector(répartitionSelector)
if (!Object.values(distribution).length) {
return null
}
const { répartition, cotisationMaximum, total } = distribution
return (
<>
<div className="distribution-chart__container">
{répartition.map(
([brancheDottedName, { partPatronale, partSalariale }]) => {
const branche = findRuleByDottedName(rules, brancheDottedName),
brancheInViewport =
branchesInViewport.indexOf(brancheDottedName) !== -1
const montant = brancheInViewport
? partPatronale + partSalariale
: 0
return (
<Observer
key={brancheDottedName}
threshold={[0.5]}
onChange={handleBrancheInViewport(brancheDottedName)}>
<Spring
config={ANIMATION_SPRING}
to={{
flex: montant / cotisationMaximum,
opacity: montant ? 1 : 0
}}>
{styles => (
<div
className="distribution-chart__item"
style={{
opacity: styles.opacity
}}>
<BranchIcône icône={branche.icons} />
<div className="distribution-chart__item-content">
<p className="distribution-chart__counterparts">
<span className="distribution-chart__branche-name">
<RuleLink {...branche} />
</span>
<br />
<small>{branche.summary}</small>
</p>
<ChartItemBar {...{ styles, colour, montant, total }} />
</div>
</div>
)}
</Spring>
</Observer>
)
}
{distribution.répartition.map(
([brancheDottedName, { partPatronale, partSalariale }]) => (
<DistributionBranch
key={brancheDottedName}
{...{
brancheDottedName,
partPatronale,
partSalariale,
distribution
}}
/>
)
)}
</div>
</>
)
}
export default compose(
withColours,
connect(state => ({
...répartitionSelector(state),
rules: flatRulesSelector(state)
}))
)(Distribution)
const ANIMATION_SPRING = config.gentle
function DistributionBranch({
brancheDottedName,
partPatronale,
partSalariale,
distribution
}) {
const rules = useSelector(flatRulesSelector)
const [intersectionRef, brancheInViewport] = useDisplayOnIntersecting({
threshold: 0.5
})
const colours = useContext(ThemeColoursContext)
const branche = findRuleByDottedName(rules, brancheDottedName)
const montant = brancheInViewport ? partPatronale + partSalariale : 0
const styles = useSpring({
config: ANIMATION_SPRING,
to: {
flex: montant / distribution.cotisationMaximum,
opacity: montant ? 1 : 0
}
})
return (
<animated.div
ref={intersectionRef}
className="distribution-chart__item"
style={{ opacity: styles.opacity }}>
<BranchIcône icône={branche.icons} />
<div className="distribution-chart__item-content">
<p className="distribution-chart__counterparts">
<span className="distribution-chart__branche-name">
<RuleLink {...branche} />
</span>
<br />
<small>{branche.summary}</small>
</p>
<ChartItemBar
{...{
styles,
colour: colours.colour,
montant,
total: distribution.total
}}
/>
</div>
</animated.div>
)
}
let ChartItemBar = ({ styles, colour, montant }) => (
<div className="distribution-chart__bar-container">
<div
<animated.div
className="distribution-chart__bar"
style={{
backgroundColor: colour,

View File

@ -6,8 +6,8 @@ import {
Spring,
Trail,
Transition
} from 'react-spring'
import type { SpringConfig } from 'react-spring'
} from 'react-spring/renderprops'
import type { SpringConfig } from 'react-spring/renderprops'
import type { Node } from 'react'
type Props = {
@ -32,11 +32,11 @@ export const fromBottom = ({
config={config}
from={{ opacity: 0, y: 20 }}
leave={{ opacity: 0, y: -20 }}
to={{ opacity: 1, y: 0 }}>
to={{ opacity: 1, y: 0 }}
items={children}>
{/* eslint-disable-next-line react/display-name */}
{React.Children.map(children, (item, i) => ({ y, ...style }) => (
{item => ({ y, ...style }) => (
<animated.div
key={i}
style={{
transform: y.interpolate(y =>
y !== 0 ? `translate3d(0, ${y}px,0)` : 'none'
@ -46,7 +46,7 @@ export const fromBottom = ({
}}>
{item}
</animated.div>
))}
)}
</Trail>
)
export const fromTop = ({
@ -62,11 +62,11 @@ export const fromTop = ({
config={config}
leave={{ opacity: 0, y: 20 }}
from={{ opacity: 0, y: -20 }}
to={{ opacity: 1, y: 0 }}>
to={{ opacity: 1, y: 0 }}
items={children}>
{/* eslint-disable-next-line react/display-name */}
{React.Children.map(children, (item, i) => ({ y, ...style }) => (
{item => ({ y, ...style }) => (
<animated.div
key={i}
style={{
transform: y.interpolate(y =>
y ? `translate3d(0, ${y}px,0)` : 'none'
@ -76,7 +76,7 @@ export const fromTop = ({
}}>
{item}
</animated.div>
))}
)}
</Trail>
)

View File

@ -0,0 +1,31 @@
import { useEffect, useRef, useState } from 'react'
export default function({ root = null, rootMargin, threshold = 0 }) {
const ref = useRef()
const [wasOnScreen, setWasOnScreen] = useState(false)
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setWasOnScreen(entry.isIntersecting)
observer.unobserve(ref.current)
}
},
{
root,
rootMargin,
threshold
}
)
const node = ref.current
if (ref.current) {
observer.observe(node)
}
return () => {
observer.unobserve(node)
}
}, [root, rootMargin, threshold]) // Empty array ensures that effect is only run on mount and unmount
return [ref, wasOnScreen]
}

View File

@ -744,7 +744,7 @@
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
@ -948,15 +948,6 @@
promise-limit "^2.5.0"
puppeteer "^1.7.0"
"@researchgate/react-intersection-observer@^0.7.3":
version "0.7.4"
resolved "https://registry.yarnpkg.com/@researchgate/react-intersection-observer/-/react-intersection-observer-0.7.4.tgz#9360274611beebd801e3c068294ddf2ab0d4b163"
integrity sha512-4F291saKAP9I25Qe1ePflvm1DLLA43GlBIZfpMFYWofph7CAm+19nT8xwkQqSszg4PwZa5BpkaI4tAEJHtlj3w==
dependencies:
invariant "^2.2.2"
prop-types "^15.6.0"
warning "^3.0.0"
"@sindresorhus/is@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
@ -8175,12 +8166,13 @@ react-side-effect@^1.1.0:
exenv "^1.2.1"
shallowequal "^1.0.1"
react-spring@^5.8.0:
version "5.9.2"
resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-5.9.2.tgz#4c4e048ffce24755eaa60acd2f3fe4a3d686ef16"
integrity sha512-ZDCBm4OaYuuSER3k7EELn9AKGs98HI23qMRL93zUUw6AlyBmqoU+eAfouGRx47gVkZkH+hArJXBHf4UGYpH9Og==
react-spring@=8.0.27:
version "8.0.27"
resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-8.0.27.tgz#97d4dee677f41e0b2adcb696f3839680a3aa356a"
integrity sha512-nDpWBe3ZVezukNRandTeLSPcwwTMjNVu1IDq9qA/AMiUqHuRN4BeSWvKr3eIxxg1vtiYiOLy4FqdfCP5IoP77g==
dependencies:
"@babel/runtime" "^7.0.0"
"@babel/runtime" "^7.3.1"
prop-types "^15.5.8"
react-syntax-highlighter@^10.1.1:
version "10.3.5"