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
parent
33c1a06b6c
commit
d2098c3d0c
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
||||
|
|
|
@ -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]
|
||||
}
|
22
yarn.lock
22
yarn.lock
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue