diff --git a/package-lock.json b/package-lock.json index a5a2e9ef4158c..787cf33c5035f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11566,6 +11566,12 @@ "integrity": "sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==", "dev": true }, + "@types/clipboard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/clipboard/-/clipboard-2.0.1.tgz", + "integrity": "sha512-gJJX9Jjdt3bIAePQRRjYWG20dIhAgEqonguyHxXuqALxsoDsDLimihqrSg8fXgVTJ4KZCzkfglKtwsh/8dLfbA==", + "dev": true + }, "@types/color-convert": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz", diff --git a/package.json b/package.json index 8050fb330f500..7056b6182131f 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "@testing-library/react": "11.2.2", "@testing-library/react-native": "7.1.0", "@types/classnames": "2.2.10", + "@types/clipboard": "2.0.1", "@types/eslint": "6.8.0", "@types/estree": "0.0.44", "@types/highlight-words-core": "1.2.0", diff --git a/packages/compose/README.md b/packages/compose/README.md index 7a6be1782b195..258b0c9311e73 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -166,9 +166,9 @@ Copies the text to the clipboard when the element is clicked. _Parameters_ -- _ref_ `Object`: Reference with the element. +- _ref_ `import('react').RefObject>`: Reference with the element. - _text_ `string|Function`: The text to copy. -- _timeout_ `number`: Optional timeout to reset the returned state. 4 seconds by default. +- _timeout_ `[number]`: Optional timeout to reset the returned state. 4 seconds by default. _Returns_ @@ -180,12 +180,12 @@ Copies the given text to the clipboard when the element is clicked. _Parameters_ -- _text_ `text|Function`: The text to copy. Use a function if not already available and expensive to compute. +- _text_ `string | (() => string)`: The text to copy. Use a function if not already available and expensive to compute. - _onSuccess_ `Function`: Called when to text is copied. _Returns_ -- `RefObject`: A ref to assign to the target element. +- `import('react').Ref`: A ref to assign to the target element. # **useDebounce** @@ -398,12 +398,12 @@ callback will be called multiple times for the same node. _Parameters_ -- _callback_ `Function`: Callback with ref as argument. -- _dependencies_ `Array`: Dependencies of the callback. +- _callback_ `( node: TElement ) => ( () => void ) | undefined`: Callback with ref as argument. +- _dependencies_ `DependencyList`: Dependencies of the callback. _Returns_ -- `Function`: Ref callback. +- `RefCallback< TElement | null >`: Ref callback. # **useResizeObserver** diff --git a/packages/compose/src/hooks/use-copy-on-click/index.js b/packages/compose/src/hooks/use-copy-on-click/index.js index 33a14c0224add..238e2bc35573d 100644 --- a/packages/compose/src/hooks/use-copy-on-click/index.js +++ b/packages/compose/src/hooks/use-copy-on-click/index.js @@ -9,32 +9,40 @@ import Clipboard from 'clipboard'; import { useRef, useEffect, useState } from '@wordpress/element'; import deprecated from '@wordpress/deprecated'; +/* eslint-disable jsdoc/no-undefined-types */ /** * Copies the text to the clipboard when the element is clicked. * * @deprecated * - * @param {Object} ref Reference with the element. - * @param {string|Function} text The text to copy. - * @param {number} timeout Optional timeout to reset the returned + * @param {import('react').RefObject>} ref Reference with the element. + * @param {string|Function} text The text to copy. + * @param {number} [timeout] Optional timeout to reset the returned * state. 4 seconds by default. * * @return {boolean} Whether or not the text has been copied. Resets after the * timeout. */ export default function useCopyOnClick( ref, text, timeout = 4000 ) { + /* eslint-enable jsdoc/no-undefined-types */ deprecated( 'wp.compose.useCopyOnClick', { since: '10.3', plugin: 'Gutenberg', alternative: 'wp.compose.useCopyToClipboard', } ); + /** @type {import('react').MutableRefObject} */ const clipboard = useRef(); const [ hasCopied, setHasCopied ] = useState( false ); useEffect( () => { + /** @type {number | undefined} */ let timeoutId; + if ( ! ref.current ) { + return; + } + // Clipboard listens to click events. clipboard.current = new Clipboard( ref.current, { text: () => ( typeof text === 'function' ? text() : text ), @@ -48,7 +56,7 @@ export default function useCopyOnClick( ref, text, timeout = 4000 ) { // Handle ClipboardJS focus bug, see https://github.com/zenorocha/clipboard.js/issues/680 if ( trigger ) { - trigger.focus(); + /** @type {HTMLElement} */ ( trigger ).focus(); } if ( timeout ) { @@ -59,7 +67,9 @@ export default function useCopyOnClick( ref, text, timeout = 4000 ) { } ); return () => { - clipboard.current.destroy(); + if ( clipboard.current ) { + clipboard.current.destroy(); + } clearTimeout( timeoutId ); }; }, [ text, timeout, setHasCopied ] ); diff --git a/packages/compose/src/hooks/use-copy-to-clipboard/index.js b/packages/compose/src/hooks/use-copy-to-clipboard/index.js index b9cbf38fa3e99..aee08641b9a87 100644 --- a/packages/compose/src/hooks/use-copy-to-clipboard/index.js +++ b/packages/compose/src/hooks/use-copy-to-clipboard/index.js @@ -13,8 +13,11 @@ import { useRef } from '@wordpress/element'; */ import useRefEffect from '../use-ref-effect'; -/** @typedef {import('@wordpress/element').RefObject} RefObject */ - +/** + * @template T + * @param {T} value + * @return {import('react').RefObject} The updated ref + */ function useUpdatedRef( value ) { const ref = useRef( value ); ref.current = value; @@ -24,24 +27,24 @@ function useUpdatedRef( value ) { /** * Copies the given text to the clipboard when the element is clicked. * - * @param {text|Function} text The text to copy. Use a function if not + * @param {string | (() => string)} text The text to copy. Use a function if not * already available and expensive to compute. - * @param {Function} onSuccess Called when to text is copied. + * @param {Function} onSuccess Called when to text is copied. * - * @return {RefObject} A ref to assign to the target element. + * @return {import('react').Ref} A ref to assign to the target element. */ export default function useCopyToClipboard( text, onSuccess ) { // Store the dependencies as refs and continuesly update them so they're // fresh when the callback is called. const textRef = useUpdatedRef( text ); - const onSuccesRef = useUpdatedRef( onSuccess ); + const onSuccessRef = useUpdatedRef( onSuccess ); return useRefEffect( ( node ) => { // Clipboard listens to click events. const clipboard = new Clipboard( node, { text() { return typeof textRef.current === 'function' ? textRef.current() - : textRef.current; + : textRef.current || ''; }, } ); @@ -54,8 +57,8 @@ export default function useCopyToClipboard( text, onSuccess ) { // https://github.com/zenorocha/clipboard.js/issues/680 node.focus(); - if ( onSuccesRef.current ) { - onSuccesRef.current(); + if ( onSuccessRef.current ) { + onSuccessRef.current(); } } ); diff --git a/packages/compose/src/hooks/use-ref-effect/index.js b/packages/compose/src/hooks/use-ref-effect/index.ts similarity index 64% rename from packages/compose/src/hooks/use-ref-effect/index.js rename to packages/compose/src/hooks/use-ref-effect/index.ts index 26673a1ad4dde..2b90c964e394e 100644 --- a/packages/compose/src/hooks/use-ref-effect/index.js +++ b/packages/compose/src/hooks/use-ref-effect/index.ts @@ -1,3 +1,9 @@ +/** + * External dependencies + */ +// eslint-disable-next-line no-restricted-imports +import type { DependencyList, RefCallback } from 'react'; + /** * WordPress dependencies */ @@ -17,14 +23,17 @@ import { useCallback, useRef } from '@wordpress/element'; * to be removed. It *is* necessary if you add dependencies because the ref * callback will be called multiple times for the same node. * - * @param {Function} callback Callback with ref as argument. - * @param {Array} dependencies Dependencies of the callback. + * @param callback Callback with ref as argument. + * @param dependencies Dependencies of the callback. * - * @return {Function} Ref callback. + * @return Ref callback. */ -export default function useRefEffect( callback, dependencies ) { - const cleanup = useRef(); - return useCallback( ( node ) => { +export default function useRefEffect< TElement = Node >( + callback: ( node: TElement ) => ( () => void ) | undefined, + dependencies: DependencyList +): RefCallback< TElement | null > { + const cleanup = useRef< ( () => void ) | undefined >(); + return useCallback( ( node: TElement | null ) => { if ( node ) { cleanup.current = callback( node ); } else if ( cleanup.current ) { diff --git a/packages/compose/tsconfig.json b/packages/compose/tsconfig.json index bf723fc3f3eda..c94a7202dde65 100644 --- a/packages/compose/tsconfig.json +++ b/packages/compose/tsconfig.json @@ -18,7 +18,10 @@ "src/hooks/use-async-list/**/*", "src/hooks/use-constrained-tabbing/**/*", "src/hooks/use-debounce/**/*", + "src/hooks/use-copy-on-click/**/*", + "src/hooks/use-copy-to-clipboard/**/*", "src/hooks/use-focus-return/**/*", + "src/hooks/use-ref-effect/**/*", "src/hooks/use-instance-id/**/*", "src/hooks/use-isomorphic-layout-effect/**/*", "src/hooks/use-keyboard-shortcut/**/*", diff --git a/packages/docgen/CHANGELOG.md b/packages/docgen/CHANGELOG.md index 8e15f8ced64cf..9f67b954644e1 100644 --- a/packages/docgen/CHANGELOG.md +++ b/packages/docgen/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Fix getting param annotations for default exported functions. ([#31603](https://github.com/WordPress/gutenberg/pull/31603)) + ## 1.17.0 (2021-04-29) ### New Features diff --git a/packages/docgen/lib/get-type-annotation.js b/packages/docgen/lib/get-type-annotation.js index c6ef900fb2b87..e3fc4a4f9529e 100644 --- a/packages/docgen/lib/get-type-annotation.js +++ b/packages/docgen/lib/get-type-annotation.js @@ -43,7 +43,9 @@ function getFunctionTypeAnnotation( typeAnnotation, returnIndicator ) { typeAnnotation.typeAnnotation.typeAnnotation ); - return `( ${ params } )${ returnIndicator }${ returnType }`; + const paramsWithParens = params.length ? `( ${ params } )` : `()`; + + return `${ paramsWithParens }${ returnIndicator }${ returnType }`; } /** @@ -376,6 +378,10 @@ function getTypeAnnotation( typeAnnotation ) { */ function getFunctionToken( token ) { let resolvedToken = token; + if ( babelTypes.isExportDefaultDeclaration( resolvedToken ) ) { + resolvedToken = resolvedToken.declaration; + } + if ( babelTypes.isExportNamedDeclaration( resolvedToken ) ) { resolvedToken = resolvedToken.declaration; }