1- import React , { forwardRef , useRef , useState , useEffect } from 'react' ;
2- import propTypes from 'prop-types' ;
3-
1+ import React , {
2+ forwardRef ,
3+ useCallback ,
4+ useEffect ,
5+ useRef ,
6+ useState
7+ } from 'react' ;
48import styled , { css } from 'styled-components' ;
59
6- import { StyledCutout } from '../Cutout/Cutout' ;
710import { blockSizes } from '../common/system' ;
11+ import { StyledCutout } from '../Cutout/Cutout' ;
12+ import { CommonStyledProps } from '../types' ;
13+
14+ type ProgressProps = {
15+ hideValue ?: boolean ;
16+ shadow ?: boolean ;
17+ value ?: number ;
18+ variant ?: 'default' | 'tile' ;
19+ } & React . HTMLAttributes < HTMLDivElement > &
20+ CommonStyledProps ;
821
922const Wrapper = styled . div `
1023 display: inline-block;
@@ -42,7 +55,7 @@ const WhiteBar = styled.div`
4255 color: ${ ( { theme } ) => theme . materialText } ;
4356` ;
4457
45- const BlueBar = styled . div `
58+ const BlueBar = styled . div < Required < Pick < ProgressProps , 'value' > > > `
4659 position: absolute;
4760 top: 2px;
4861 left: 2px;
@@ -79,53 +92,45 @@ const Tile = styled.span`
7992 border-style: solid;
8093` ;
8194
82- const Progress = forwardRef ( function Progress ( props , ref ) {
83- const { value, variant, shadow, hideValue, ...otherProps } = props ;
95+ const Progress = forwardRef < HTMLDivElement , ProgressProps > ( function Progress (
96+ {
97+ hideValue = false ,
98+ shadow = true ,
99+ value = 0 ,
100+ variant = 'default' ,
101+ ...otherProps
102+ } ,
103+ ref
104+ ) {
84105 const displayValue = hideValue ? null : `${ value } %` ;
85106
86- const progressProps = { } ;
87- if ( value !== undefined ) {
88- progressProps [ 'aria-valuenow' ] = Math . round ( value ) ;
89- }
90-
91- const tilesWrapperRef = useRef ( ) ;
92- const savedCallback = useRef ( ) ;
93- const [ tilesNumber , setTilesNumber ] = useState ( 0 ) ;
107+ const tilesWrapperRef = useRef < HTMLDivElement | null > ( null ) ;
108+ const [ tiles , setTiles ] = useState ( [ ] ) ;
94109
95110 // TODO debounce this function
96- function updateTilesNumber ( ) {
97- if ( tilesWrapperRef . current ) {
98- const progressWidth =
99- tilesWrapperRef . current . getBoundingClientRect ( ) . width ;
100- const newTilesNumber = Math . round (
101- ( ( value / 100 ) * progressWidth ) / tileWidth
102- ) ;
103- setTilesNumber ( newTilesNumber ) ;
111+ const updateTilesNumber = useCallback ( ( ) => {
112+ if ( ! tilesWrapperRef . current ) {
113+ return ;
104114 }
105- }
106- useEffect ( ( ) => {
107- savedCallback . current = updateTilesNumber ;
108- } ) ;
115+ const progressWidth = tilesWrapperRef . current . getBoundingClientRect ( ) . width ;
116+ const newTilesNumber = Math . round (
117+ ( ( value / 100 ) * progressWidth ) / tileWidth
118+ ) ;
119+ setTiles ( Array . from ( { length : newTilesNumber } ) ) ;
120+ } , [ value ] ) ;
121+
109122 useEffect ( ( ) => {
110- function update ( ) {
111- savedCallback . current ( ) ;
112- }
123+ updateTilesNumber ( ) ;
113124
114- // then listen on window resize to recalculate number of tiles
115- window . addEventListener ( 'resize' , update ) ;
116- return ( ) => window . removeEventListener ( 'resize' , update ) ;
117- } , [ ] ) ;
125+ window . addEventListener ( 'resize' , updateTilesNumber ) ;
126+ return ( ) => window . removeEventListener ( 'resize' , updateTilesNumber ) ;
127+ } , [ updateTilesNumber ] ) ;
118128
119- // recalculate number of tiles when value changes
120- useEffect ( ( ) => {
121- savedCallback . current ( ) ;
122- } , [ value ] ) ;
123129 return (
124130 < Wrapper
125- // TODO what to do with ref from forwardRef ?
131+ aria-valuenow = { value !== undefined ? Math . round ( value ) : undefined }
126132 ref = { ref }
127133 role = 'progressbar'
128- { ...progressProps }
129134 { ...otherProps }
130135 >
131136 < ProgressCutout shadow = { shadow } >
@@ -138,30 +143,14 @@ const Progress = forwardRef(function Progress(props, ref) {
138143 </ >
139144 ) : (
140145 < TilesWrapper ref = { tilesWrapperRef } data-testid = 'tileProgress' >
141- { Array ( tilesNumber )
142- . fill ( null )
143- . map ( ( _ , index ) => (
144- < Tile key = { index } />
145- ) ) }
146+ { tiles . map ( ( _ , index ) => (
147+ < Tile key = { index } />
148+ ) ) }
146149 </ TilesWrapper >
147150 ) }
148151 </ ProgressCutout >
149152 </ Wrapper >
150153 ) ;
151154} ) ;
152155
153- Progress . defaultProps = {
154- value : 0 ,
155- shadow : true ,
156- variant : 'default' ,
157- hideValue : false
158- } ;
159-
160- Progress . propTypes = {
161- value : propTypes . number ,
162- shadow : propTypes . bool ,
163- variant : propTypes . oneOf ( [ 'default' , 'tile' ] ) ,
164- hideValue : propTypes . bool
165- } ;
166-
167- export default Progress ;
156+ export { Progress , ProgressProps } ;
0 commit comments