-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: progress: add progress component to octuple (#420)
* feat: progress: add progress component to octuple consolidates reset component and clear fix mixins, fixes tree import type * chore: progress: export progress * chore: progress: fix import typo * chore: progress: address pr feedback * chore: progress: remove redundant uid helper * chore: progress: add support for custom labels and simplify title value logic
- Loading branch information
1 parent
aba0df7
commit aa1ad1d
Showing
33 changed files
with
38,952 additions
and
12,289 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, { FC } from 'react'; | ||
import OcCircle, { VIEW_BOX_SIZE } from './Internal/OcCircle'; | ||
import { CircleProps } from './Progress.types'; | ||
import { getSuccessPercent, validProgress } from './Utils'; | ||
import { mergeClasses } from '../../shared/utilities'; | ||
|
||
import styles from './progress.module.scss'; | ||
|
||
const DEFAULT_CIRCLE_SIZE: number = 120; | ||
const DEFAULT_GAP_DEGREE: number = 75; | ||
const DEFAULT_STROKE_WIDTH_DIVISOR: number = 1.6; | ||
const FAlLBACK_STROKE_WIDTH: number = 4; | ||
const FONT_SIZE_FLOAT: number = 0.15; | ||
|
||
function getPercentage({ percent, success }: CircleProps): number[] { | ||
const realSuccessPercent = validProgress(getSuccessPercent({ success })); | ||
return [ | ||
realSuccessPercent, | ||
validProgress(validProgress(percent) - realSuccessPercent), | ||
]; | ||
} | ||
|
||
function getStrokeColor({ | ||
success = {}, | ||
strokeColor, | ||
}: Partial<CircleProps>): (string | Record<string, string>)[] { | ||
const { strokeColor: successColor } = success; | ||
return [successColor || 'var(--success-color)', strokeColor || null!]; | ||
} | ||
|
||
const Circle: FC<CircleProps> = (props) => { | ||
const { | ||
children, | ||
gapDegree, | ||
gapPosition, | ||
strokeLinecap = 'butt', | ||
strokeWidth = VIEW_BOX_SIZE / DEFAULT_STROKE_WIDTH_DIVISOR, | ||
success, | ||
trailColor = null, | ||
type, | ||
width, | ||
} = props; | ||
|
||
const circleSize: number = width || DEFAULT_CIRCLE_SIZE; | ||
const circleStyle: React.CSSProperties = { | ||
width: circleSize, | ||
height: circleSize, | ||
fontSize: circleSize * FONT_SIZE_FLOAT + FAlLBACK_STROKE_WIDTH, | ||
}; | ||
const circleWidth: number = strokeWidth || FAlLBACK_STROKE_WIDTH; | ||
const gapPos: 'top' | 'bottom' | 'left' | 'right' = | ||
gapPosition || (type === 'dashboard' && 'bottom') || undefined; | ||
|
||
const getGapDegree = (): number => { | ||
// Support gapDeg = 0 when type = 'dashboard' | ||
if (gapDegree || gapDegree === 0) { | ||
return gapDegree; | ||
} | ||
if (type === 'dashboard') { | ||
return DEFAULT_GAP_DEGREE; | ||
} | ||
return undefined; | ||
}; | ||
|
||
const isGradient: boolean = | ||
Object.prototype.toString.call(props.strokeColor) === '[object Object]'; | ||
const strokeColor: (string | Record<string, string>)[] = getStrokeColor({ | ||
success, | ||
strokeColor: props.strokeColor, | ||
}); | ||
|
||
const wrapperClassNames: string = mergeClasses([ | ||
styles.progressInner, | ||
{ [styles.progressCircleGradient]: isGradient }, | ||
]); | ||
|
||
return ( | ||
<div className={wrapperClassNames} style={circleStyle}> | ||
<OcCircle | ||
gapDegree={getGapDegree()} | ||
gapPosition={gapPos} | ||
percent={getPercentage(props)} | ||
strokeColor={strokeColor} | ||
strokeLinecap={strokeLinecap} | ||
strokeWidth={circleWidth} | ||
trailColor={trailColor} | ||
trailWidth={circleWidth} | ||
/> | ||
{children} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Circle; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { useRef, useEffect } from 'react'; | ||
|
||
export const MAX_PERCENT: number = 100; | ||
|
||
export const useTransitionDuration = (): SVGPathElement[] => { | ||
const pathsRef: React.MutableRefObject<SVGPathElement[]> = useRef< | ||
SVGPathElement[] | ||
>([]); | ||
const prevTimeStamp: React.MutableRefObject<any> = useRef(null); | ||
|
||
useEffect(() => { | ||
const now: number = Date.now(); | ||
let updated: boolean = false; | ||
|
||
pathsRef.current.forEach((path: SVGPathElement) => { | ||
if (!path) { | ||
return; | ||
} | ||
|
||
updated = true; | ||
const pathStyle: CSSStyleDeclaration = path.style; | ||
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s'; | ||
|
||
if ( | ||
prevTimeStamp.current && | ||
now - prevTimeStamp.current < MAX_PERCENT | ||
) { | ||
pathStyle.transitionDuration = '0s, 0s'; | ||
} | ||
}); | ||
|
||
if (updated) { | ||
prevTimeStamp.current = Date.now(); | ||
} | ||
}); | ||
|
||
return pathsRef.current; | ||
}; |
Oops, something went wrong.