diff --git a/package.json b/package.json index 10359d3b..579e6747 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "build": "dumi build", "compile": "father build", "coverage": "npm test -- --coverage", - "lint": "eslint src/ --ext .tsx,.ts & eslint tests/ --ext .js", + "lint": "eslint src/ --ext .tsx,.ts & eslint tests/ --ext .tsx,.ts", "prepare": "husky install", "prepublishOnly": "npm run compile && np --yolo --no-publish", "start": "dumi dev", @@ -38,7 +38,6 @@ ] }, "dependencies": { - "@babel/runtime": "^7.18.3", "react-is": "^18.2.0" }, "devDependencies": { @@ -52,7 +51,6 @@ "@types/responselike": "^1.0.0", "@types/warning": "^3.0.0", "@umijs/fabric": "^3.0.0", - "create-react-class": "^15.6.3", "cross-env": "^7.0.2", "dumi": "^2.1.3", "eslint": "^8.54.0", diff --git a/src/Children/mapSelf.js b/src/Children/mapSelf.js deleted file mode 100644 index 1c998e6c..00000000 --- a/src/Children/mapSelf.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; - -function mirror(o) { - return o; -} - -export default function mapSelf(children) { - // return ReactFragment - return React.Children.map(children, mirror); -} diff --git a/src/ContainerRender.js b/src/ContainerRender.js deleted file mode 100644 index f4e0bba2..00000000 --- a/src/ContainerRender.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; - -/** - * @deprecated Since we do not need support React15 any more. - * Will remove in next major version. - */ -export default class ContainerRender extends React.Component { - static defaultProps = { - autoMount: true, - autoDestroy: true, - forceRender: false, - }; - - componentDidMount() { - if (this.props.autoMount) { - this.renderComponent(); - } - } - - componentDidUpdate() { - if (this.props.autoMount) { - this.renderComponent(); - } - } - - componentWillUnmount() { - if (this.props.autoDestroy) { - this.removeContainer(); - } - } - - removeContainer = () => { - if (this.container) { - ReactDOM.unmountComponentAtNode(this.container); - this.container.parentNode.removeChild(this.container); - this.container = null; - } - }; - - renderComponent = (props, ready) => { - const { - visible, - getComponent, - forceRender, - getContainer, - parent, - } = this.props; - if (visible || parent._component || forceRender) { - if (!this.container) { - this.container = getContainer(); - } - ReactDOM.unstable_renderSubtreeIntoContainer( - parent, - getComponent(props), - this.container, - function callback() { - if (ready) { - ready.call(this); - } - }, - ); - } - }; - - render() { - return this.props.children({ - renderComponent: this.renderComponent, - removeContainer: this.removeContainer, - }); - } -} diff --git a/src/Dom/addEventListener.js b/src/Dom/addEventListener.js deleted file mode 100644 index 4e94d78e..00000000 --- a/src/Dom/addEventListener.js +++ /dev/null @@ -1,20 +0,0 @@ -import ReactDOM from 'react-dom'; - -export default function addEventListenerWrap(target, eventType, cb, option) { - /* eslint camelcase: 2 */ - const callback = ReactDOM.unstable_batchedUpdates - ? function run(e) { - ReactDOM.unstable_batchedUpdates(cb, e); - } - : cb; - if (target?.addEventListener) { - target.addEventListener(eventType, callback, option); - } - return { - remove: () => { - if (target?.removeEventListener) { - target.removeEventListener(eventType, callback, option); - } - }, - }; -} diff --git a/src/Dom/class.js b/src/Dom/class.js deleted file mode 100644 index b72c70b3..00000000 --- a/src/Dom/class.js +++ /dev/null @@ -1,28 +0,0 @@ -export function hasClass(node, className) { - if (node.classList) { - return node.classList.contains(className); - } - const originClass = node.className; - return ` ${originClass} `.indexOf(` ${className} `) > -1; -} - -export function addClass(node, className) { - if (node.classList) { - node.classList.add(className); - } else { - if (!hasClass(node, className)) { - node.className = `${node.className} ${className}`; - } - } -} - -export function removeClass(node, className) { - if (node.classList) { - node.classList.remove(className); - } else { - if (hasClass(node, className)) { - const originClass = node.className; - node.className = ` ${originClass} `.replace(` ${className} `, ' '); - } - } -} diff --git a/src/Dom/css.js b/src/Dom/css.js deleted file mode 100644 index 1948dc8e..00000000 --- a/src/Dom/css.js +++ /dev/null @@ -1,113 +0,0 @@ -/* eslint-disable no-nested-ternary */ -const PIXEL_PATTERN = /margin|padding|width|height|max|min|offset/; - -const removePixel = { - left: true, - top: true, -}; -const floatMap = { - cssFloat: 1, - styleFloat: 1, - float: 1, -}; - -function getComputedStyle(node) { - return node.nodeType === 1 ? - node.ownerDocument.defaultView.getComputedStyle(node, null) : {}; -} - -function getStyleValue(node, type, value) { - type = type.toLowerCase(); - if (value === 'auto') { - if (type === 'height') { - return node.offsetHeight; - } - if (type === 'width') { - return node.offsetWidth; - } - } - if (!(type in removePixel)) { - removePixel[type] = PIXEL_PATTERN.test(type); - } - return removePixel[type] ? (parseFloat(value) || 0) : value; -} - -export function get(node, name) { - const length = arguments.length; - const style = getComputedStyle(node); - - name = floatMap[name] ? 'cssFloat' in node.style ? 'cssFloat' : 'styleFloat' : name; - - return (length === 1) ? style : getStyleValue(node, name, style[name] || node.style[name]); -} - -export function set(node, name, value) { - const length = arguments.length; - name = floatMap[name] ? 'cssFloat' in node.style ? 'cssFloat' : 'styleFloat' : name; - if (length === 3) { - if (typeof value === 'number' && PIXEL_PATTERN.test(name)) { - value = `${value}px`; - } - node.style[name] = value; // Number - return value; - } - for (const x in name) { - if (name.hasOwnProperty(x)) { - set(node, x, name[x]); - } - } - return getComputedStyle(node); -} - -export function getOuterWidth(el) { - if (el === document.body) { - return document.documentElement.clientWidth; - } - return el.offsetWidth; -} - -export function getOuterHeight(el) { - if (el === document.body) { - return window.innerHeight || document.documentElement.clientHeight; - } - return el.offsetHeight; -} - -export function getDocSize() { - const width = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); - const height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight); - - return { - width, - height, - }; -} - -export function getClientSize() { - const width = document.documentElement.clientWidth; - const height = window.innerHeight || document.documentElement.clientHeight; - return { - width, - height, - }; -} - -export function getScroll() { - return { - scrollLeft: Math.max(document.documentElement.scrollLeft, document.body.scrollLeft), - scrollTop: Math.max(document.documentElement.scrollTop, document.body.scrollTop), - }; -} - -export function getOffset(node) { - const box = node.getBoundingClientRect(); - const docElem = document.documentElement; - - // < ie8 不支持 win.pageXOffset, 则使用 docElem.scrollLeft - return { - left: box.left + (window.pageXOffset || docElem.scrollLeft) - - (docElem.clientLeft || document.body.clientLeft || 0), - top: box.top + (window.pageYOffset || docElem.scrollTop) - - (docElem.clientTop || document.body.clientTop || 0), - }; -} diff --git a/src/Dom/support.js b/src/Dom/support.js deleted file mode 100644 index 8f5d192d..00000000 --- a/src/Dom/support.js +++ /dev/null @@ -1,26 +0,0 @@ -import canUseDOM from './canUseDom'; -const animationEndEventNames = { - WebkitAnimation: 'webkitAnimationEnd', - OAnimation: 'oAnimationEnd', - animation: 'animationend', -}; -const transitionEventNames = { - WebkitTransition: 'webkitTransitionEnd', - OTransition: 'oTransitionEnd', - transition: 'transitionend', -}; - -function supportEnd(names) { - const el = document.createElement('div'); - for (const name in names) { - if (names.hasOwnProperty(name) && el.style[name] !== undefined) { - return { - end: names[name], - }; - } - } - return false; -} - -export const animation = canUseDOM() && supportEnd(animationEndEventNames); -export const transition = canUseDOM() && supportEnd(transitionEventNames); diff --git a/src/PortalWrapper.tsx b/src/PortalWrapper.tsx index 1d0ad022..a1fe81c6 100644 --- a/src/PortalWrapper.tsx +++ b/src/PortalWrapper.tsx @@ -1,9 +1,9 @@ /* eslint-disable no-underscore-dangle,react/require-default-props */ import * as React from 'react'; import raf from './raf'; -import Portal, { PortalRef } from './Portal'; +import Portal from './Portal'; +import type { PortalRef } from './Portal'; import canUseDom from './Dom/canUseDom'; -import switchScrollingEffect from './switchScrollingEffect'; import setStyle from './setStyle'; import ScrollLocker from './Dom/scrollLocker'; @@ -59,7 +59,7 @@ export interface PortalWrapperProps { class PortalWrapper extends React.Component { container?: HTMLElement; - componentRef: React.RefObject = React.createRef(); + componentRef = React.createRef(); rafId?: number; @@ -73,8 +73,8 @@ class PortalWrapper extends React.Component { } renderComponent?: (info: { - afterClose: Function; - onClose: Function; + afterClose: (...params: any[]) => void; + onClose: (...params: any[]) => void; visible: boolean; }) => void; @@ -206,7 +206,6 @@ class PortalWrapper extends React.Component { */ switchScrollingEffect = () => { if (openCount === 1 && !Object.keys(cacheOverflow).length) { - switchScrollingEffect(); // Must be set after switchScrollingEffect cacheOverflow = setStyle({ overflow: 'hidden', @@ -216,7 +215,6 @@ class PortalWrapper extends React.Component { } else if (!openCount) { setStyle(cacheOverflow); cacheOverflow = {}; - switchScrollingEffect(true); } }; diff --git a/src/PureRenderMixin.js b/src/PureRenderMixin.js deleted file mode 100644 index 61f5879d..00000000 --- a/src/PureRenderMixin.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright 2013-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule ReactComponentWithPureRenderMixin - */ - -import isEqual from './isEqual'; - -function shallowCompare(instance, nextProps, nextState) { - return ( - !isEqual(instance.props, nextProps, true) || - !isEqual(instance.state, nextState, true) - ); -} - -/** - * If your React component's render function is "pure", e.g. it will render the - * same result given the same props and state, provide this mixin for a - * considerable performance boost. - * - * Most React components have pure render functions. - * - * Example: - * - * var ReactComponentWithPureRenderMixin = - * require('ReactComponentWithPureRenderMixin'); - * React.createClass({ - * mixins: [ReactComponentWithPureRenderMixin], - * - * render: function() { - * return
foo
; - * } - * }); - * - * Note: This only checks shallow equality for props and state. If these contain - * complex data structures this mixin may have false-negatives for deeper - * differences. Only mixin to components which have simple props and state, or - * use `forceUpdate()` when you know deep data structures have changed. - * - * See https://facebook.github.io/react/docs/pure-render-mixin.html - */ -const ReactComponentWithPureRenderMixin = { - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - }, -}; - -export default ReactComponentWithPureRenderMixin; diff --git a/src/createChainedFunction.js b/src/createChainedFunction.js deleted file mode 100644 index 3d1fd45a..00000000 --- a/src/createChainedFunction.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Safe chained function - * - * Will only create a new function if needed, - * otherwise will pass back existing functions or null. - * - * @returns {function|null} - */ -export default function createChainedFunction() { - const args = [].slice.call(arguments, 0); - if (args.length === 1) { - return args[0]; - } - - return function chainedFunction() { - for (let i = 0; i < args.length; i++) { - if (args[i] && args[i].apply) { - args[i].apply(this, arguments); - } - } - }; -} diff --git a/src/debug/diff.js b/src/debug/diff.js deleted file mode 100644 index c31679a3..00000000 --- a/src/debug/diff.js +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint no-proto: 0 */ - -function createArray() { - const arr = []; - arr.__proto__ = new Array; - arr.__proto__.format = function toString() { - return this.map(obj => ({ - ...obj, - path: obj.path.join(' > '), - })); - }; - arr.__proto__.toString = function toString() { - return JSON.stringify(this.format(), null, 2); - }; - return arr; -} - -export default function diff(obj1, obj2, depth = 10, path = [], diffList = createArray()) { - if (depth <= 0) return diffList; - - const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]); - keys.forEach((key) => { - const value1 = obj1[key]; - const value2 = obj2[key]; - - // Same value - if (value1 === value2) return; - - const type1 = typeof value1; - const type2 = typeof value2; - - // Diff type - if (type1 !== type2) { - diffList.push({ - path: path.concat(key), - value1, - value2, - }); - return; - } - - // NaN - if (Number.isNaN(value1) && Number.isNaN(value2)) { - return; - } - - // Object & Array - if (type1 === 'object' && value1 !== null && value2 !== null) { - diff(value1, value2, depth - 1, path.concat(key), diffList); - return; - } - - // Rest - diffList.push({ - path: path.concat(key), - value1, - value2, - }); - }); - - return diffList; -} diff --git a/src/deprecated.js b/src/deprecated.js deleted file mode 100644 index b05755f8..00000000 --- a/src/deprecated.js +++ /dev/null @@ -1,8 +0,0 @@ -export default function deprecated(props, instead, component) { - if (typeof window !== 'undefined' && window.console && window.console.error) { - window.console.error( - `Warning: ${props} is deprecated at [ ${component} ], ` + - `use [ ${instead} ] instead of it.`, - ); - } -} diff --git a/src/getContainerRenderMixin.jsx b/src/getContainerRenderMixin.jsx deleted file mode 100644 index 21f7bc8b..00000000 --- a/src/getContainerRenderMixin.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import ReactDOM from 'react-dom'; - -function defaultGetContainer() { - const container = document.createElement('div'); - document.body.appendChild(container); - return container; -} - -export default function getContainerRenderMixin(config) { - const { - autoMount = true, - autoDestroy = true, - isVisible, - isForceRender, - getComponent, - getContainer = defaultGetContainer, - } = config; - - let mixin; - - function renderComponent(instance, componentArg, ready) { - if ( - !isVisible || instance._component || isVisible(instance) || - (isForceRender && isForceRender(instance)) - ) { - if (!instance._container) { - instance._container = getContainer(instance); - } - let component; - if (instance.getComponent) { - component = instance.getComponent(componentArg); - } else { - component = getComponent(instance, componentArg); - } - ReactDOM.unstable_renderSubtreeIntoContainer(instance, - component, instance._container, - function callback() { - instance._component = this; - if (ready) { - ready.call(this); - } - }); - } - } - - if (autoMount) { - mixin = { - ...mixin, - componentDidMount() { - renderComponent(this); - }, - componentDidUpdate() { - renderComponent(this); - }, - }; - } - - if (!autoMount || !autoDestroy) { - mixin = { - ...mixin, - renderComponent(componentArg, ready) { - renderComponent(this, componentArg, ready); - }, - }; - } - - function removeContainer(instance) { - if (instance._container) { - const container = instance._container; - ReactDOM.unmountComponentAtNode(container); - container.parentNode.removeChild(container); - instance._container = null; - } - } - - if (autoDestroy) { - mixin = { - ...mixin, - componentWillUnmount() { - removeContainer(this); - }, - }; - } else { - mixin = { - ...mixin, - removeContainer() { - removeContainer(this); - }, - }; - } - - return mixin; -} diff --git a/src/guid.js b/src/guid.js deleted file mode 100644 index 9c7e5812..00000000 --- a/src/guid.js +++ /dev/null @@ -1,4 +0,0 @@ -let seed = 0; -export default function guid() { - return `${Date.now()}_${seed++}`; -} diff --git a/src/hooks/useEvent.ts b/src/hooks/useEvent.ts index 2087b8e2..f9bb7dce 100644 --- a/src/hooks/useEvent.ts +++ b/src/hooks/useEvent.ts @@ -1,6 +1,8 @@ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable react-hooks/exhaustive-deps */ import * as React from 'react'; -export default function useEvent(callback: T): T { +function useEvent(callback: T): T { const fnRef = React.useRef(); fnRef.current = callback; @@ -11,3 +13,5 @@ export default function useEvent(callback: T): T { return memoFn; } + +export default useEvent; diff --git a/src/hooks/useLayoutEffect.ts b/src/hooks/useLayoutEffect.ts index e4c2e726..a7bc05bd 100644 --- a/src/hooks/useLayoutEffect.ts +++ b/src/hooks/useLayoutEffect.ts @@ -36,6 +36,7 @@ export const useLayoutUpdateEffect: typeof React.useEffect = ( if (!firstMount) { return callback(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, deps); }; diff --git a/src/proxyObject.ts b/src/proxyObject.ts index 5c8d1b49..71697760 100644 --- a/src/proxyObject.ts +++ b/src/proxyObject.ts @@ -3,7 +3,7 @@ */ export default function proxyObject< Obj extends object, - ExtendObj extends object + ExtendObj extends object, >(obj: Obj, extendProps: ExtendObj): Obj & ExtendObj { if (typeof Proxy !== 'undefined' && obj) { return new Proxy(obj, { diff --git a/src/ref.ts b/src/ref.ts index a972dff3..9297a4be 100644 --- a/src/ref.ts +++ b/src/ref.ts @@ -30,6 +30,7 @@ export const composeRef = (...refs: React.Ref[]): React.Ref => { export const useComposeRef = (...refs: React.Ref[]): React.Ref => { return useMemo( () => composeRef(...refs), + // eslint-disable-next-line react-hooks/exhaustive-deps refs, (prev, next) => prev.length !== next.length || prev.every((ref, i) => ref !== next[i]), diff --git a/src/setStyle.ts b/src/setStyle.ts index 03bef362..029654c5 100644 --- a/src/setStyle.ts +++ b/src/setStyle.ts @@ -1,4 +1,4 @@ -import * as React from 'react'; +import type React from 'react'; export interface SetStyleOptions { element?: HTMLElement; diff --git a/src/switchScrollingEffect.js b/src/switchScrollingEffect.js deleted file mode 100644 index 1263ee7f..00000000 --- a/src/switchScrollingEffect.js +++ /dev/null @@ -1,48 +0,0 @@ -import getScrollBarSize from './getScrollBarSize'; -import setStyle from './setStyle'; - -function isBodyOverflowing() { - return ( - document.body.scrollHeight > - (window.innerHeight || document.documentElement.clientHeight) && - window.innerWidth > document.body.offsetWidth - ); -} - -let cacheStyle = {}; - -export default close => { - if (!isBodyOverflowing() && !close) { - return; - } - - // https://github.com/ant-design/ant-design/issues/19729 - const scrollingEffectClassName = 'ant-scrolling-effect'; - const scrollingEffectClassNameReg = new RegExp( - `${scrollingEffectClassName}`, - 'g', - ); - const bodyClassName = document.body.className; - - if (close) { - if (!scrollingEffectClassNameReg.test(bodyClassName)) return; - setStyle(cacheStyle); - cacheStyle = {}; - document.body.className = bodyClassName - .replace(scrollingEffectClassNameReg, '') - .trim(); - return; - } - - const scrollBarSize = getScrollBarSize(); - if (scrollBarSize) { - cacheStyle = setStyle({ - position: 'relative', - width: `calc(100% - ${scrollBarSize}px)`, - }); - if (!scrollingEffectClassNameReg.test(bodyClassName)) { - const addClassName = `${bodyClassName} ${scrollingEffectClassName}`; - document.body.className = addClassName.trim(); - } - } -}; diff --git a/src/test/domHook.ts b/src/test/domHook.ts index 7c5041d7..12532fe7 100644 --- a/src/test/domHook.ts +++ b/src/test/domHook.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable no-param-reassign */ const NO_EXIST = { __NOT_EXIST: true }; @@ -12,14 +13,17 @@ export function spyElementPrototypes( const originDescriptors = {}; propNames.forEach(propName => { - const originDescriptor = Object.getOwnPropertyDescriptor(elementClass.prototype, propName); + const originDescriptor = Object.getOwnPropertyDescriptor( + elementClass.prototype, + propName, + ); originDescriptors[propName] = originDescriptor || NO_EXIST; const spyProp = properties[propName]; if (typeof spyProp === 'function') { // If is a function - elementClass.prototype[propName] = function spyFunc(...args) { + elementClass.prototype[propName] = function spyFunc(...args: any[]) { return spyProp.call(this, originDescriptor, ...args); }; } else { @@ -52,14 +56,22 @@ export function spyElementPrototypes( } else if (typeof originDescriptor === 'function') { elementClass.prototype[propName] = originDescriptor; } else { - Object.defineProperty(elementClass.prototype, propName, originDescriptor); + Object.defineProperty( + elementClass.prototype, + propName, + originDescriptor, + ); } }); }, }; } -export function spyElementPrototype(Element: ElementClass, propName: string, property: Property) { +export function spyElementPrototype( + Element: ElementClass, + propName: string, + property: Property, +) { return spyElementPrototypes(Element, { [propName]: property, }); diff --git a/src/unsafeLifecyclesPolyfill.js b/src/unsafeLifecyclesPolyfill.js deleted file mode 100644 index 3df87980..00000000 --- a/src/unsafeLifecyclesPolyfill.js +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; - -const unsafeLifecyclesPolyfill = Component => { - const { prototype } = Component; - - if (!prototype || !prototype.isReactComponent) { - throw new Error('Can only polyfill class components'); - } - - // only handle componentWillReceiveProps - if (typeof prototype.componentWillReceiveProps !== 'function') { - return Component; - } - - // In React 16.9, React.Profiler was introduced together with UNSAFE_componentWillReceiveProps - // https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#performance-measurements-with-reactprofiler - if (!React.Profiler) { - return Component; - } - - // Here polyfill get started - prototype.UNSAFE_componentWillReceiveProps = prototype.componentWillReceiveProps; - delete prototype.componentWillReceiveProps; - - return Component; -}; - -export default unsafeLifecyclesPolyfill; diff --git a/src/utils/set.ts b/src/utils/set.ts index 22f8917e..39ddac39 100644 --- a/src/utils/set.ts +++ b/src/utils/set.ts @@ -9,18 +9,18 @@ function internalSet( removeIfUndefined: boolean, ): Output { if (!paths.length) { - return (value as unknown) as Output; + return value as unknown as Output; } const [path, ...restPath] = paths; let clone: Output; if (!entity && typeof path === 'number') { - clone = ([] as unknown) as Output; + clone = [] as unknown as Output; } else if (Array.isArray(entity)) { - clone = ([...entity] as unknown) as Output; + clone = [...entity] as unknown as Output; } else { - clone = ({ ...entity } as unknown) as Output; + clone = { ...entity } as unknown as Output; } // Delete prop if `removeIfUndefined` and value is undefined @@ -46,7 +46,7 @@ export default function set( value === undefined && !get(entity, paths.slice(0, -1)) ) { - return (entity as unknown) as Output; + return entity as unknown as Output; } return internalSet(entity, paths, value, removeIfUndefined); diff --git a/src/warn.js b/src/warn.js deleted file mode 100644 index 75fc7b0f..00000000 --- a/src/warn.js +++ /dev/null @@ -1,8 +0,0 @@ -/** @deprecated Use `warning` instead. This will be removed in next major version */ -export default function warn(msg) { - if (process.env.NODE_ENV !== 'production') { - if (typeof console !== 'undefined' && console.warn) { - console.warn(msg); - } - } -} diff --git a/tests/Portal.test.tsx b/tests/Portal.test.tsx index 45c24bd3..6c84fecc 100644 --- a/tests/Portal.test.tsx +++ b/tests/Portal.test.tsx @@ -192,12 +192,12 @@ describe('Portal', () => { it('should restore to original place in StrictMode', () => { const parentContainer = document.createElement('div'); - const domContainer = document.createElement('div'); - parentContainer.appendChild(domContainer); + const curDomContainer = document.createElement('div'); + parentContainer.appendChild(curDomContainer); let mountCount = 0; let unmountCount = 0; - const Demo = () => { + const Demo: React.FC = () => { useEffect(() => { mountCount += 1; return () => { @@ -205,7 +205,7 @@ describe('Portal', () => { }; }, []); - return domContainer}>Contents; + return curDomContainer}>Contents; }; render(, { wrapper: StrictMode }); diff --git a/tests/composeProps.test.js b/tests/composeProps.test.ts similarity index 84% rename from tests/composeProps.test.js rename to tests/composeProps.test.ts index 8fb76dee..5f4e8c6a 100644 --- a/tests/composeProps.test.js +++ b/tests/composeProps.test.ts @@ -6,7 +6,12 @@ describe('composeProps', () => { const aBlur = jest.fn(); const bChange = jest.fn(); const bDemo = jest.fn(); - const sourceProps = { value: '11', onChange: aChange, onBlur: aBlur }; + const sourceProps = { + value: '11', + onChange: aChange, + onBlur: aBlur, + onDemo: undefined, + }; const patchProps = { onChange: bChange, onDemo: bDemo, placeholder: 'x' }; const props = composeProps(sourceProps, patchProps, true); @@ -30,7 +35,12 @@ describe('composeProps', () => { const aBlur = jest.fn(); const bChange = jest.fn(); const bDemo = jest.fn(); - const sourceProps = { value: '11', onChange: aChange, onBlur: aBlur }; + const sourceProps = { + value: '11', + onChange: aChange, + onBlur: aBlur, + onDemo: undefined, + }; const patchProps = { onChange: bChange, onDemo: bDemo, placeholder: 'x' }; const props = composeProps(sourceProps, patchProps); diff --git a/tests/debug.test.js b/tests/debug.test.js deleted file mode 100644 index d3bc4292..00000000 --- a/tests/debug.test.js +++ /dev/null @@ -1,52 +0,0 @@ -import diff from '../src/debug/diff'; - -describe('debug', () => { - describe('diff', () => { - const base = { - a: 1, - b: [2, 3], - c: { - d: 4, - }, - }; - - it('same', () => { - const target = { - a: 1, - b: [2, 3], - c: { - d: 4, - }, - }; - - expect(diff(base, target)).toEqual([]); - }); - - it('props', () => { - const target = { - a: 2, - b: [3, 4], - c: { - d: 5, - }, - }; - - expect(diff(base, target)).toEqual([ - { path: ['a'], value1: 1, value2: 2 }, - { path: ['b', '0'], value1: 2, value2: 3 }, - { path: ['b', '1'], value1: 3, value2: 4 }, - { path: ['c', 'd'], value1: 4, value2: 5 }, - ]); - }); - - it('toString', () => { - const diffList = diff({ a: 1 }, {}); - expect(diffList.toString()).toEqual(`[ - { - "path": "a", - "value1": 1 - } -]`); - }); - }); -}); diff --git a/tests/domHook.test.js b/tests/domHook.test.ts similarity index 84% rename from tests/domHook.test.js rename to tests/domHook.test.ts index 8f3388b4..6dcc417b 100644 --- a/tests/domHook.test.js +++ b/tests/domHook.test.ts @@ -2,7 +2,12 @@ import { spyElementPrototype } from '../src/test/domHook'; describe('domHook', () => { - function spyTest(name, propName, hookProp, assetFunc) { + function spyTest( + name: string, + propName: string, + hookProp: (() => string) | { get?: () => string }, + assetFunc: (test?: any) => void, + ) { it(name, () => { class Test { func() {} diff --git a/tests/hooks-17.test.js b/tests/hooks-17.test.tsx similarity index 89% rename from tests/hooks-17.test.js rename to tests/hooks-17.test.tsx index 4ede72b9..1c84e57e 100644 --- a/tests/hooks-17.test.js +++ b/tests/hooks-17.test.tsx @@ -17,12 +17,12 @@ jest.mock('react', () => { describe('hooks-17', () => { describe('useId', () => { - const Demo = ({ id } = {}) => { + const Demo: React.FC<{ id?: string }> = ({ id }) => { const mergedId = useId(id); return
; }; - function matchId(container, id) { + function matchId(container: HTMLElement, id: string) { const ele = container.querySelector('.target'); return expect(ele.id).toEqual(id); } @@ -48,10 +48,7 @@ describe('hooks-17', () => { , - { - hydrate: true, - container: holder, - }, + { hydrate: true, container: holder }, ); matchId(container, 'rc_unique_1'); diff --git a/tests/hooks.test.js b/tests/hooks.test.tsx similarity index 85% rename from tests/hooks.test.js rename to tests/hooks.test.tsx index 3b19f7ab..2d05e8c7 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.tsx @@ -25,9 +25,11 @@ jest.mock('react', () => { describe('hooks', () => { it('useMemo', () => { - const FC = ({ open, data }) => { + const FC: React.FC> = props => { + const { open, data } = props; const memoData = useMemo( () => data, + // eslint-disable-next-line react-hooks/exhaustive-deps [open, data], (prev, next) => next[0] && prev[1] !== next[1], ); @@ -48,8 +50,15 @@ describe('hooks', () => { }); describe('useMergedState', () => { - const FC = ({ value, defaultValue }) => { - const [val, setVal] = useMergedState(null, { value, defaultValue }); + const FC: React.FC<{ + value?: string; + defaultValue?: string | (() => string); + }> = props => { + const { value, defaultValue } = props; + const [val, setVal] = useMergedState(null, { + value, + defaultValue, + }); return ( <> { }); it('postState', () => { - const Demo = () => { + const Demo: React.FC = () => { const [val] = useMergedState(1, { postState: v => v * 2 }); - return
{val}
; }; @@ -141,10 +149,16 @@ describe('hooks', () => { }); describe('not trigger onChange if props change', () => { - function test(name, postWrapper = node => node) { + function test( + name: string, + postWrapper = (node?: React.ReactNode) => node, + ) { it(name, () => { - const Demo = ({ value, onChange }) => { - const [mergedValue, setValue] = useMergedState(0, { + const Demo: React.FC<{ + onChange: (value: number) => void; + }> = props => { + const { onChange } = props; + const [mergedValue, setValue] = useMergedState(0, { onChange, }); @@ -196,11 +210,11 @@ describe('hooks', () => { it('uncontrolled to controlled', () => { const onChange = jest.fn(); - const Demo = ({ value }) => { - const [mergedValue, setMergedValue] = useMergedState(() => 233, { - value, - onChange, - }); + const Demo: React.FC> = ({ value }) => { + const [mergedValue, setMergedValue] = useMergedState( + () => 233, + { value, onChange }, + ); return ( { it('not trigger onChange if set same value', () => { const onChange = jest.fn(); - const Test = ({ value }) => { - const [mergedValue, setMergedValue] = useMergedState(undefined, { - value, - onChange, - }); + const Test: React.FC> = ({ value }) => { + const [mergedValue, setMergedValue] = useMergedState( + undefined, + { value, onChange }, + ); return ( { @@ -267,11 +281,11 @@ describe('hooks', () => { it('should alway use option value', () => { const onChange = jest.fn(); - const Test = ({ value }) => { - const [mergedValue, setMergedValue] = useMergedState(undefined, { - value, - onChange, - }); + const Test: React.FC> = ({ value }) => { + const [mergedValue, setMergedValue] = useMergedState( + undefined, + { value, onChange }, + ); return ( { @@ -292,8 +306,8 @@ describe('hooks', () => { it('render once', () => { let count = 0; - const Demo = () => { - const [] = useMergedState(); + const Demo: React.FC = () => { + const [] = useMergedState(undefined); count += 1; return null; }; @@ -304,9 +318,10 @@ describe('hooks', () => { }); describe('useLayoutEffect', () => { - const FC = ({ defaultValue }) => { - const [val, setVal] = React.useState(defaultValue); - const [val2, setVal2] = React.useState(); + const FC: React.FC> = props => { + const { defaultValue } = props; + const [val, setVal] = React.useState(defaultValue); + const [val2, setVal2] = React.useState(); useLayoutEffect(() => { setVal2(`${val}a`); }, [val]); @@ -346,10 +361,11 @@ describe('hooks', () => { }); it('can get mount state', () => { - const Demo = () => { - const timesRef = React.useRef(0); - const [, forceUpdate] = React.useState(0); + const Demo: React.FC = () => { + const timesRef = React.useRef(0); + const [, forceUpdate] = React.useState(0); + // eslint-disable-next-line react-hooks/exhaustive-deps useLayoutEffect(firstMount => { if (timesRef.current === 0) { expect(firstMount).toBeTruthy(); @@ -374,8 +390,8 @@ describe('hooks', () => { it('not throw', done => { const errorSpy = jest.spyOn(console, 'error'); - const Demo = () => { - const [val, setValue] = useState(0); + const Demo: React.FC = () => { + const [val, setValue] = useState(0); React.useEffect( () => () => { @@ -420,8 +436,8 @@ describe('hooks', () => { it.skip('throw', done => { const errorSpy = jest.spyOn(console, 'error'); - const Demo = () => { - const [_, setValue] = useState(0); + const Demo: React.FC = () => { + const [, setValue] = useState(0); React.useEffect( () => () => { @@ -446,12 +462,12 @@ describe('hooks', () => { }); describe('useId', () => { - const Demo = ({ id } = {}) => { + const Demo: React.FC> = ({ id }) => { const mergedId = useId(id); return
; }; - function matchId(container, id) { + function matchId(container: HTMLElement, id: string) { const ele = container.querySelector('.target'); return expect(ele.id).toEqual(id); } @@ -511,7 +527,7 @@ describe('hooks', () => { it('should not warn useLayoutEffect in SSR', () => { const errorSpy = jest.spyOn(console, 'error'); - const Demo = () => { + const Demo: React.FC = () => { useMobile(); return null; }; diff --git a/tests/index.test.js b/tests/index.test.js deleted file mode 100644 index 10566188..00000000 --- a/tests/index.test.js +++ /dev/null @@ -1,53 +0,0 @@ -/* eslint-disable react/prefer-es6-class, react/no-render-return-value, react/no-deprecated */ -import React from 'react'; -import ReactDOM from 'react-dom'; -import createReactClass from 'create-react-class'; - -import createChainedFunction from '../src/createChainedFunction'; -import PureRenderMixin from '../src/PureRenderMixin'; - -describe('rc-util', () => { - it('createChainedFunction works', () => { - const ret = []; - - function f1() { - ret.push(1); - } - - function f2() { - ret.push(2); - } - - function f3() { - ret.push(3); - } - - createChainedFunction(f1, f2, f3, null)(); - expect(ret).toEqual([1, 2, 3]); - }); - - // Note: Seems useless but not remove in case some code still use it - it('PureRenderMixin works', () => { - const div = document.createElement('div'); - document.body.appendChild(div); - let count = 0; - const C = createReactClass({ - mixins: [PureRenderMixin], - getInitialState() { - return { - a: 1, - }; - }, - render() { - count += 1; - return {this.state.a}; - }, - }); - const c = ReactDOM.render(, div); - c.setState({ - a: 1, - }); - expect(count).toBe(1); - }); -}); -/* eslint-enable */ diff --git a/tests/raf.test.js b/tests/raf.test.ts similarity index 100% rename from tests/raf.test.js rename to tests/raf.test.ts diff --git a/tests/setStyle.test.ts b/tests/setStyle.test.ts index 2f25c832..632e5bc8 100644 --- a/tests/setStyle.test.ts +++ b/tests/setStyle.test.ts @@ -1,4 +1,4 @@ -import { CSSProperties } from 'react'; +import type { CSSProperties } from 'react'; import setStyle from '../src/setStyle'; describe('setStyle', () => { diff --git a/tests/style.test.js b/tests/style.test.ts similarity index 100% rename from tests/style.test.js rename to tests/style.test.ts diff --git a/tests/switchScrollingEffect.test.ts b/tests/switchScrollingEffect.test.ts deleted file mode 100644 index 4cdb3910..00000000 --- a/tests/switchScrollingEffect.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import switchScrollingEffect from '../src/switchScrollingEffect'; -import { spyElementPrototypes } from '../src/test/domHook'; -import getScrollBarSize from '../src/getScrollBarSize'; - -jest.mock('../src/getScrollBarSize', () => - jest.fn().mockImplementation(() => 20), -); - -/** - * Jest dom default window innerWidth is 1024, innerHeight is 768 - * Jest silently eats 'calc' - * https://github.com/jsdom/jsdom/issues/1332 - */ - -describe('switchScrollingEffect', () => { - beforeEach(() => { - // reset - document.body.className = ''; - document.body.setAttribute('style', ''); - }); - - it('switchScrollingEffect correct', () => { - switchScrollingEffect(); - - expect(document.body.style.cssText).toBe(''); - - const bodyMock = spyElementPrototypes(HTMLBodyElement, { - scrollHeight: { - get: () => 5000, - }, - offsetWidth: { - get: () => 748, - }, - }); - - switchScrollingEffect(); - - expect(document.body.style.cssText).toBe( - 'position: relative; width: calc(100% - 20px);', - ); - expect(document.body.className).toBe('ant-scrolling-effect'); - - // when closed - switchScrollingEffect(true); - expect(document.body.style.cssText).toBe(''); - expect(document.body.className).toBe(''); - - bodyMock.mockRestore(); - }); -}); diff --git a/tests/toArray.test.js b/tests/toArray.test.tsx similarity index 89% rename from tests/toArray.test.js rename to tests/toArray.test.tsx index 7cf23236..fb3a9613 100644 --- a/tests/toArray.test.js +++ b/tests/toArray.test.tsx @@ -3,15 +3,14 @@ import { render } from '@testing-library/react'; import toArray from '../src/Children/toArray'; describe('toArray', () => { - class UL extends React.Component { + class UL extends React.Component> { render() { return
    {this.props.children}
; } } it('basic', () => { - const ulRef = React.createRef(); - + const ulRef = React.createRef
    (); render(
    • 1
    • @@ -26,7 +25,7 @@ describe('toArray', () => { }); it('Array', () => { - const ulRef = React.createRef(); + const ulRef = React.createRef
        (); render(
          @@ -41,7 +40,7 @@ describe('toArray', () => { }); it('Fragment', () => { - const ulRef = React.createRef(); + const ulRef = React.createRef
            (); render(
              @@ -65,7 +64,7 @@ describe('toArray', () => { }); it('keep empty', () => { - const ulRef = React.createRef(); + const ulRef = React.createRef
                (); render(
                  diff --git a/tests/utils.test.js b/tests/utils.test.ts similarity index 96% rename from tests/utils.test.js rename to tests/utils.test.ts index e12a0c0f..dc0f439d 100644 --- a/tests/utils.test.js +++ b/tests/utils.test.ts @@ -172,6 +172,7 @@ describe('utils', () => { a: 1, b: { c: 3, + looper: undefined, }, }; looper.b.looper = looper; @@ -195,7 +196,10 @@ describe('utils', () => { it('shallow copy', () => { const ori = { - list: [{ a: 1 }, { a: 2 }], + list: [ + { a: 1, b: undefined }, + { a: 2, b: undefined }, + ], }; const cloneList = [...ori.list]; @@ -213,7 +217,9 @@ describe('utils', () => { it('skip class object', () => { class User { - constructor(name, age) { + name: string; + age: number; + constructor(name: string, age: number) { this.name = name; this.age = age; } diff --git a/tests/warning.test.js b/tests/warning.test.ts similarity index 74% rename from tests/warning.test.js rename to tests/warning.test.ts index a9b64ed1..aeebc2c0 100644 --- a/tests/warning.test.js +++ b/tests/warning.test.ts @@ -1,7 +1,4 @@ -import { render } from '@testing-library/react'; -import React from 'react'; import { warning } from '../src'; -import unsafeLifecyclesPolyfill from '../src/unsafeLifecyclesPolyfill'; const { resetWarned, noteOnce } = warning; @@ -52,24 +49,6 @@ describe('warning', () => { warnSpy.mockRestore(); }); - // https://github.com/ant-design/ant-design/issues/9792 - it('should not warning React componentWillReceiveProps', () => { - const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}); - class App extends React.Component { - state = {}; - - render() { - return null; - } - } - const FixedWarningApp = unsafeLifecyclesPolyfill(App); - render(); - expect(warnSpy).not.toHaveBeenCalledWith( - expect.stringContaining('componentWillReceiveProps has been renamed'), - ); - warnSpy.mockRestore(); - }); - describe('preMessage', () => { it('modify message', () => { const errSpy = jest.spyOn(console, 'error').mockImplementation(() => {});