Browse Source

Merge branch 'master' into next-merge-master

pull/38057/head
MadCcc 2 years ago
parent
commit
a431983aad
  1. 3
      components/spin/__tests__/delay.test.tsx
  2. 14
      components/spin/__tests__/index.test.tsx
  3. 121
      components/spin/index.tsx
  4. 2
      components/table/demo/row-selection-and-operation.md
  5. 2
      components/table/demo/row-selection-custom.md
  6. 2
      docker-compose.yml
  7. 1
      package.json

3
components/spin/__tests__/delay.test.tsx

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
// eslint-disable-next-line import/no-named-as-default
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import debounce from 'lodash/debounce'; import debounce from 'lodash/debounce';
import Spin from '..'; import Spin from '..';
@ -32,7 +31,7 @@ describe('delay spinning', () => {
jest.useRealTimers(); jest.useRealTimers();
}); });
it('should cancel debounce function when unmount', async () => { it('should cancel debounce function when unmount', () => {
const debouncedFn = jest.fn(); const debouncedFn = jest.fn();
const cancel = jest.fn(); const cancel = jest.fn();
(debouncedFn as any).cancel = cancel; (debouncedFn as any).cancel = cancel;

14
components/spin/__tests__/index.test.tsx

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
// eslint-disable-next-line import/no-named-as-default
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import { waitFakeTimer } from '../../../tests/utils';
import Spin from '..'; import Spin from '..';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest'; import rtlTest from '../../../tests/shared/rtlTest';
@ -15,10 +15,8 @@ describe('Spin', () => {
<div>content</div> <div>content</div>
</Spin>, </Spin>,
); );
expect((container.querySelector('.ant-spin-nested-loading')! as HTMLElement).style.length).toBe( expect(container.querySelector<HTMLElement>('.ant-spin-nested-loading')?.style.length).toBe(0);
0, expect(container.querySelector<HTMLElement>('.ant-spin')?.style.background).toBe('red');
);
expect((container.querySelector('.ant-spin')! as HTMLElement).style.background).toBe('red');
}); });
it("should render custom indicator when it's set", () => { it("should render custom indicator when it's set", () => {
@ -27,11 +25,15 @@ describe('Spin', () => {
expect(asFragment().firstChild).toMatchSnapshot(); expect(asFragment().firstChild).toMatchSnapshot();
}); });
it('should be controlled by spinning', () => { it('should be controlled by spinning', async () => {
jest.useFakeTimers();
const { container, rerender } = render(<Spin spinning={false} />); const { container, rerender } = render(<Spin spinning={false} />);
expect(container.querySelector('.ant-spin-spinning')).toBeFalsy(); expect(container.querySelector('.ant-spin-spinning')).toBeFalsy();
rerender(<Spin spinning />); rerender(<Spin spinning />);
await waitFakeTimer();
expect(container.querySelector('.ant-spin-spinning')).toBeTruthy(); expect(container.querySelector('.ant-spin-spinning')).toBeTruthy();
jest.clearAllTimers();
jest.useRealTimers();
}); });
it('if indicator set null should not be render default indicator', () => { it('if indicator set null should not be render default indicator', () => {

121
components/spin/index.tsx

@ -35,11 +35,6 @@ export type SpinFCType = React.FC<SpinProps> & {
setDefaultIndicator: (indicator: React.ReactNode) => void; setDefaultIndicator: (indicator: React.ReactNode) => void;
}; };
export interface SpinState {
spinning?: boolean;
notCssAnimationSupported?: boolean;
}
// Render indicator // Render indicator
let defaultIndicator: React.ReactNode = null; let defaultIndicator: React.ReactNode = null;
@ -59,8 +54,8 @@ function renderIndicator(prefixCls: string, props: SpinClassProps): React.ReactN
} }
if (isValidElement(defaultIndicator)) { if (isValidElement(defaultIndicator)) {
return cloneElement(defaultIndicator as SpinIndicator, { return cloneElement(defaultIndicator, {
className: classNames((defaultIndicator as SpinIndicator).props.className, dotClassName), className: classNames(defaultIndicator.props.className, dotClassName),
}); });
} }
@ -78,80 +73,38 @@ function shouldDelay(spinning?: boolean, delay?: number): boolean {
return !!spinning && !!delay && !isNaN(Number(delay)); return !!spinning && !!delay && !isNaN(Number(delay));
} }
class Spin extends React.Component<SpinClassProps, SpinState> { const Spin: React.FC<SpinClassProps> = props => {
static defaultProps = { const {
spinning: true, spinPrefixCls: prefixCls,
size: 'default' as SpinSize, spinning: customSpinning = true,
wrapperClassName: '', delay,
}; className,
size = 'default',
originalUpdateSpinning: () => void; tip,
wrapperClassName,
style,
children,
hashId,
...restProps
} = props;
constructor(props: SpinClassProps) { const [spinning, setSpinning] = React.useState<boolean>(
super(props); () => customSpinning && !shouldDelay(customSpinning, delay),
);
const { spinning, delay } = props; React.useEffect(() => {
const shouldBeDelayed = shouldDelay(spinning, delay); const updateSpinning = debounce<() => void>(() => {
this.state = { setSpinning(customSpinning);
spinning: spinning && !shouldBeDelayed, }, delay);
updateSpinning();
return () => {
updateSpinning?.cancel?.();
}; };
this.originalUpdateSpinning = this.updateSpinning; }, [delay, customSpinning]);
this.debouncifyUpdateSpinning(props);
}
componentDidMount() {
this.updateSpinning();
}
componentDidUpdate() {
this.debouncifyUpdateSpinning();
this.updateSpinning();
}
componentWillUnmount() {
this.cancelExistingSpin();
}
debouncifyUpdateSpinning = (props?: SpinClassProps) => {
const { delay } = props || this.props;
if (delay) {
this.cancelExistingSpin();
this.updateSpinning = debounce(this.originalUpdateSpinning, delay);
}
};
updateSpinning = () => {
const { spinning } = this.props;
const { spinning: currentSpinning } = this.state;
if (currentSpinning !== spinning) {
this.setState({ spinning });
}
};
cancelExistingSpin() {
const { updateSpinning } = this;
if (updateSpinning && (updateSpinning as any).cancel) {
(updateSpinning as any).cancel();
}
}
isNestedPattern() {
return !!(this.props && typeof this.props.children !== 'undefined');
}
renderSpin = ({ direction }: ConfigConsumerProps) => { const isNestedPattern = () => typeof children !== 'undefined';
const {
spinPrefixCls: prefixCls,
hashId,
className,
size,
tip,
wrapperClassName,
style,
...restProps
} = this.props;
const { spinning } = this.state;
const renderSpin = ({ direction }: ConfigConsumerProps) => {
const spinClassName = classNames( const spinClassName = classNames(
prefixCls, prefixCls,
{ {
@ -166,7 +119,7 @@ class Spin extends React.Component<SpinClassProps, SpinState> {
); );
// fix https://fb.me/react-unknown-prop // fix https://fb.me/react-unknown-prop
const divProps = omit(restProps, ['spinning', 'delay', 'indicator', 'prefixCls']); const divProps = omit(restProps, ['indicator', 'prefixCls']);
const spinElement = ( const spinElement = (
<div <div
@ -176,11 +129,12 @@ class Spin extends React.Component<SpinClassProps, SpinState> {
aria-live="polite" aria-live="polite"
aria-busy={spinning} aria-busy={spinning}
> >
{renderIndicator(prefixCls, this.props)} {renderIndicator(prefixCls, props)}
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null} {tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null}
</div> </div>
); );
if (this.isNestedPattern()) {
if (isNestedPattern()) {
const containerClassName = classNames(`${prefixCls}-container`, { const containerClassName = classNames(`${prefixCls}-container`, {
[`${prefixCls}-blur`]: spinning, [`${prefixCls}-blur`]: spinning,
}); });
@ -191,18 +145,15 @@ class Spin extends React.Component<SpinClassProps, SpinState> {
> >
{spinning && <div key="loading">{spinElement}</div>} {spinning && <div key="loading">{spinElement}</div>}
<div className={containerClassName} key="container"> <div className={containerClassName} key="container">
{this.props.children} {children}
</div> </div>
</div> </div>
); );
} }
return spinElement; return spinElement;
}; };
return <ConfigConsumer>{renderSpin}</ConfigConsumer>;
render() { };
return <ConfigConsumer>{this.renderSpin}</ConfigConsumer>;
}
}
const SpinFC: SpinFCType = props => { const SpinFC: SpinFCType = props => {
const { prefixCls: customizePrefixCls } = props; const { prefixCls: customizePrefixCls } = props;

2
components/table/demo/row-selection-and-operation.md

@ -64,7 +64,7 @@ const App: React.FC = () => {
}; };
const onSelectChange = (newSelectedRowKeys: React.Key[]) => { const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
console.log('selectedRowKeys changed: ', selectedRowKeys); console.log('selectedRowKeys changed: ', newSelectedRowKeys);
setSelectedRowKeys(newSelectedRowKeys); setSelectedRowKeys(newSelectedRowKeys);
}; };

2
components/table/demo/row-selection-custom.md

@ -55,7 +55,7 @@ const App: React.FC = () => {
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onSelectChange = (newSelectedRowKeys: React.Key[]) => { const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
console.log('selectedRowKeys changed: ', selectedRowKeys); console.log('selectedRowKeys changed: ', newSelectedRowKeys);
setSelectedRowKeys(newSelectedRowKeys); setSelectedRowKeys(newSelectedRowKeys);
}; };

2
docker-compose.yml

@ -14,4 +14,4 @@ services:
- './jest-puppeteer.config.js:/app/jest-puppeteer.config.js' - './jest-puppeteer.config.js:/app/jest-puppeteer.config.js'
- './imageSnapshots:/app/imageSnapshots' - './imageSnapshots:/app/imageSnapshots'
- './imageDiffSnapshots:/app/imageDiffSnapshots' - './imageDiffSnapshots:/app/imageDiffSnapshots'
entrypoint: "jest --config .jest.image.js --no-cache -i" entrypoint: "npm run test-image:docker"

1
package.json

@ -92,6 +92,7 @@
"tsc": "tsc --noEmit", "tsc": "tsc --noEmit",
"site:test": "jest --config .jest.site.js --cache=false --force-exit", "site:test": "jest --config .jest.site.js --cache=false --force-exit",
"test-image": "npm run dist && docker-compose run tests", "test-image": "npm run dist && docker-compose run tests",
"test-image:docker": "node node_modules/puppeteer/install.js && jest --config .jest.image.js --no-cache -i",
"argos": "node ./scripts/argos-upload.js", "argos": "node ./scripts/argos-upload.js",
"version": "node ./scripts/generate-version", "version": "node ./scripts/generate-version",
"install-react-16": "npm i --no-save --legacy-peer-deps react@16 react-dom@16", "install-react-16": "npm i --no-save --legacy-peer-deps react@16 react-dom@16",

Loading…
Cancel
Save