Skip to content

Commit

Permalink
chore: fix ssr render (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ authored Dec 22, 2021
1 parent 01580cf commit 4f5f960
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 36 deletions.
37 changes: 14 additions & 23 deletions src/Circle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import * as React from 'react';
import classNames from 'classnames';
import { useTransitionDuration, defaultProps } from './common';
import type { ProgressProps, GapPositionType } from './interface';

let gradientSeed = 0;
import useId from './hooks/useId';

function stripPercentToNumber(percent: string) {
return +percent.replace('%', '');
}

function toArray(symArray: any) {
return Array.isArray(symArray) ? symArray : [symArray];
function toArray<T>(value: T | T[]): T[] {
const mergedValue = value ?? [];
return Array.isArray(mergedValue) ? mergedValue : [mergedValue];
}

function getPathStyles(
offset: number,
percent: number,
strokeColor: string,
strokeColor: string | Record<string, string>,
strokeWidth: number,
gapDegree = 0,
gapPosition: GapPositionType,
Expand Down Expand Up @@ -65,6 +65,7 @@ function getPathStyles(
}

const Circle: React.FC<ProgressProps> = ({
id,
prefixCls,
strokeWidth,
trailWidth,
Expand All @@ -78,10 +79,10 @@ const Circle: React.FC<ProgressProps> = ({
percent,
...restProps
}) => {
const gradientId = React.useMemo(() => {
gradientSeed += 1;
return gradientSeed;
}, []);
const mergedId = useId(id);

const gradientId = `${mergedId}-gradient`;

const { pathString, pathStyle } = getPathStyles(
0,
100,
Expand All @@ -92,20 +93,15 @@ const Circle: React.FC<ProgressProps> = ({
);
const percentList = toArray(percent);
const strokeColorList = toArray(strokeColor);
const gradient = strokeColorList.find(
(color) => Object.prototype.toString.call(color) === '[object Object]',
);
const gradient = strokeColorList.find((color) => color && typeof color === 'object');

const [paths] = useTransitionDuration(percentList);

const getStokeList = () => {
let stackPtg = 0;
return percentList.map((ptg, index) => {
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
const stroke =
Object.prototype.toString.call(color) === '[object Object]'
? `url(#${prefixCls}-gradient-${gradientId})`
: '';
const stroke = color && typeof color === 'object' ? `url(#${gradientId})` : '';
const pathStyles = getPathStyles(stackPtg, ptg, color, strokeWidth, gapDegree, gapPosition);
stackPtg += ptg;
return (
Expand All @@ -130,17 +126,12 @@ const Circle: React.FC<ProgressProps> = ({
className={classNames(`${prefixCls}-circle`, className)}
viewBox="0 0 100 100"
style={style}
id={id}
{...restProps}
>
{gradient && (
<defs>
<linearGradient
id={`${prefixCls}-gradient-${gradientId}`}
x1="100%"
y1="0%"
x2="0%"
y2="0%"
>
<linearGradient id={gradientId} x1="100%" y1="0%" x2="0%" y2="0%">
{Object.keys(gradient)
.sort((a, b) => stripPercentToNumber(a) - stripPercentToNumber(b))
.map((key, index) => (
Expand Down
32 changes: 32 additions & 0 deletions src/hooks/useId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as React from 'react';
import canUseDom from 'rc-util/lib/Dom/canUseDom';

let uuid = 0;

/** Is client side and not jsdom */
export const isBrowserClient = process.env.NODE_ENV !== 'test' && canUseDom();

/** Get unique id for accessibility usage */
function getUUID(): number | string {
let retId: string | number;

// Test never reach
/* istanbul ignore if */
if (isBrowserClient) {
retId = uuid;
uuid += 1;
} else {
retId = 'TEST_OR_SSR';
}

return retId;
}

export default (id?: string) => {
// Inner id for accessibility usage. Only work in client side
const [innerId, setInnerId] = React.useState<string>();
React.useEffect(() => {
setInnerId(`rc_progress_${getUUID()}`);
}, []);
return id || innerId;
};
5 changes: 2 additions & 3 deletions src/interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';

export interface ProgressProps {
id?: string;
strokeWidth?: number;
trailWidth?: number;
className?: string;
Expand All @@ -15,7 +14,7 @@ export interface ProgressProps {
transition?: string;
}

export type StrokeColorType = string | string[] | object;
export type StrokeColorType = string | string[] | Record<string, string>;

export type GapPositionType = 'top' | 'right' | 'bottom' | 'left';

Expand Down
97 changes: 97 additions & 0 deletions tests/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,103 @@ Array [
]
`;

exports[`Progress Circle should gradient works and circles have different gradient IDs 1`] = `
<div>
<svg
class="rc-progress-circle"
viewBox="0 0 100 100"
>
<defs>
<linearGradient
id="rc_progress_TEST_OR_SSR-gradient"
x1="100%"
x2="0%"
y1="0%"
y2="0%"
>
<stop
offset="0%"
stop-color="#108ee9"
/>
<stop
offset="100%"
stop-color="#87d068"
/>
</linearGradient>
</defs>
<path
class="rc-progress-circle-trail"
d="M 50,50 m 0,-47
a 47,47 0 1 1 0,94
a 47,47 0 1 1 0,-94"
fill-opacity="0"
stroke="#D9D9D9"
stroke-linecap="round"
stroke-width="1"
style="stroke: #D9D9D9; stroke-dasharray: 295.3097094374406px 295.3097094374406px; stroke-dashoffset: -0px; transition: stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s;"
/>
<path
class="rc-progress-circle-path"
d="M 50,50 m 0,-47
a 47,47 0 1 1 0,94
a 47,47 0 1 1 0,-94"
fill-opacity="0"
opacity="1"
stroke="url(#rc_progress_TEST_OR_SSR-gradient)"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray: 265.77873849369655px 295.3097094374406px; stroke-dashoffset: -0px; transition: stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s; transition-duration: 0s, 0s;"
/>
</svg>
<svg
class="rc-progress-circle"
viewBox="0 0 100 100"
>
<defs>
<linearGradient
id="rc_progress_TEST_OR_SSR-gradient"
x1="100%"
x2="0%"
y1="0%"
y2="0%"
>
<stop
offset="0%"
stop-color="#108ee9"
/>
<stop
offset="100%"
stop-color="#87d068"
/>
</linearGradient>
</defs>
<path
class="rc-progress-circle-trail"
d="M 50,50 m 0,-47
a 47,47 0 1 1 0,94
a 47,47 0 1 1 0,-94"
fill-opacity="0"
stroke="#D9D9D9"
stroke-linecap="round"
stroke-width="1"
style="stroke: #D9D9D9; stroke-dasharray: 295.3097094374406px 295.3097094374406px; stroke-dashoffset: -0px; transition: stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s;"
/>
<path
class="rc-progress-circle-path"
d="M 50,50 m 0,-47
a 47,47 0 1 1 0,94
a 47,47 0 1 1 0,-94"
fill-opacity="0"
opacity="1"
stroke="url(#rc_progress_TEST_OR_SSR-gradient)"
stroke-linecap="round"
stroke-width="6"
style="stroke-dasharray: 265.77873849369655px 295.3097094374406px; stroke-dashoffset: -0px; transition: stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s, opacity .3s ease 0s; transition-duration: 0s, 0s;"
/>
</svg>
</div>
`;

exports[`Progress Circle should show right gapPosition 1`] = `
Array [
<Circle
Expand Down
14 changes: 4 additions & 10 deletions tests/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ describe('Progress', () => {
});

it('should gradient works and circles have different gradient IDs', () => {
const c = mount(
<>
const wrapper = mount(
<div>
<Circle
percent={90}
strokeWidth="6"
Expand All @@ -79,16 +79,10 @@ describe('Progress', () => {
'100%': '#87d068',
}}
/>
</>,
</div>,
);

const gradientDefs = c.find('defs');
const idFirst = gradientDefs.at(0).props().children.props.id;
const idSecond = gradientDefs.at(1).props().children.props.id;
const idRE = /^rc-progress-gradient-\d{1,}$/;
expect(idFirst).toMatch(idRE);
expect(idSecond).toMatch(idRE);
expect(idFirst === idSecond).toBeFalsy();
expect(wrapper.render()).toMatchSnapshot();
});

it('should show right gapPosition', () => {
Expand Down

1 comment on commit 4f5f960

@vercel
Copy link

@vercel vercel bot commented on 4f5f960 Dec 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.