From 939b9caa550322f8ab594b8c16d64fd846ec2ab7 Mon Sep 17 00:00:00 2001 From: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com> Date: Thu, 8 Jul 2021 08:40:29 -0700 Subject: [PATCH] components: Add useCx (#33172) * components: Add useCx * Add tests * Add JSDoc * Add story for useCx --- package-lock.json | 1 + packages/components/package.json | 1 + packages/components/src/utils/hooks/index.js | 1 + .../src/utils/hooks/stories/use-cx.js | 79 +++++++++++++++++++ .../components/src/utils/hooks/test/use-cx.js | 64 +++++++++++++++ packages/components/src/utils/hooks/use-cx.ts | 65 +++++++++++++++ 6 files changed, 211 insertions(+) create mode 100644 packages/components/src/utils/hooks/stories/use-cx.js create mode 100644 packages/components/src/utils/hooks/test/use-cx.js create mode 100644 packages/components/src/utils/hooks/use-cx.ts diff --git a/package-lock.json b/package-lock.json index 6787845515c1c..b8102539013a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14615,6 +14615,7 @@ "@emotion/css": "^11.1.3", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.3.0", + "@emotion/utils": "1.0.0", "@wordpress/a11y": "file:packages/a11y", "@wordpress/compose": "file:packages/compose", "@wordpress/date": "file:packages/date", diff --git a/packages/components/package.json b/packages/components/package.json index d96ff912be264..603a19b922bfb 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -34,6 +34,7 @@ "@emotion/css": "^11.1.3", "@emotion/react": "^11.1.5", "@emotion/styled": "^11.3.0", + "@emotion/utils": "1.0.0", "@wordpress/a11y": "file:../a11y", "@wordpress/compose": "file:../compose", "@wordpress/date": "file:../date", diff --git a/packages/components/src/utils/hooks/index.js b/packages/components/src/utils/hooks/index.js index 187718e5e70a9..bc7c1f9fb4b21 100644 --- a/packages/components/src/utils/hooks/index.js +++ b/packages/components/src/utils/hooks/index.js @@ -2,3 +2,4 @@ export { default as useControlledState } from './use-controlled-state'; export { default as useJumpStep } from './use-jump-step'; export { default as useUpdateEffect } from './use-update-effect'; export { useControlledValue } from './use-controlled-value'; +export { useCx } from './use-cx'; diff --git a/packages/components/src/utils/hooks/stories/use-cx.js b/packages/components/src/utils/hooks/stories/use-cx.js new file mode 100644 index 0000000000000..96532565b0389 --- /dev/null +++ b/packages/components/src/utils/hooks/stories/use-cx.js @@ -0,0 +1,79 @@ +/** + * Internal dependencies + */ +import { useCx } from '..'; +import StyleProvider from '../../../style-provider'; + +/** + * WordPress dependencies + */ +import { useState, createPortal } from '@wordpress/element'; +/** + * External dependencies + */ +import { css } from '@emotion/react'; + +export default { + title: 'Components (Experimental)/useCx', +}; + +const IFrame = ( { children } ) => { + const [ iframeDocument, setIframeDocument ] = useState(); + + const handleRef = ( node ) => { + if ( ! node ) { + return null; + } + + function setIfReady() { + const { contentDocument } = node; + const { readyState } = contentDocument; + + if ( readyState !== 'interactive' && readyState !== 'complete' ) { + return false; + } + + setIframeDocument( contentDocument ); + } + + if ( setIfReady() ) { + return; + } + + node.addEventListener( 'load', () => { + // iframe isn't immediately ready in Firefox + setIfReady(); + } ); + }; + + return ( + + ); +}; + +const Example = ( { args, children } ) => { + const cx = useCx(); + const classes = cx( ...args ); + return { children }; +}; + +export const _default = () => { + const redText = css` + color: red; + `; + return ( + + ); +}; diff --git a/packages/components/src/utils/hooks/test/use-cx.js b/packages/components/src/utils/hooks/test/use-cx.js new file mode 100644 index 0000000000000..181e0beeca2a4 --- /dev/null +++ b/packages/components/src/utils/hooks/test/use-cx.js @@ -0,0 +1,64 @@ +/** + * External dependencies + */ +// eslint-disable-next-line no-restricted-imports +import { cx as innerCx } from '@emotion/css'; +import { insertStyles } from '@emotion/utils'; +import { render } from '@testing-library/react'; +import { css, CacheProvider } from '@emotion/react'; +import createCache from '@emotion/cache'; + +/** + * Internal dependencies + */ +import { useCx } from '..'; + +jest.mock( '@emotion/css', () => ( { + cx: jest.fn(), +} ) ); + +jest.mock( '@emotion/utils', () => ( { + insertStyles: jest.fn(), +} ) ); + +function Example( { args } ) { + const cx = useCx(); + + return
; +} + +describe( 'useCx', () => { + it( 'should call cx with the built style name and pass serialized styles to insertStyles', () => { + const serializedStyle = css` + color: red; + `; + const className = 'component-example'; + const object = { + 'component-example-focused': true, + }; + + const key = 'test-cache-key'; + + const container = document.createElement( 'head' ); + + const cache = createCache( { container, key } ); + + render( +