Skip to content

Commit

Permalink
Components: Add G2 Flex (#28609)
Browse files Browse the repository at this point in the history
* Components: Add G2 Flex

* Add types to current Flex

* Adapter G2 flex components

* Fix tests

* Components: Move G2 Flex into UI

* Update with latest from g2

* Fix integration of `ui/flex` with `InputControl`

Co-authored-by: Jon Q <hello@jonquach.com>
  • Loading branch information
sarayourfriend and Jon Q authored Feb 3, 2021
1 parent b13f304 commit 0105c9a
Show file tree
Hide file tree
Showing 27 changed files with 1,609 additions and 16 deletions.
15 changes: 12 additions & 3 deletions packages/components/src/flex/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,29 @@
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';

/**
* Internal dependencies
*/
import { Block } from './styles/flex-styles';
import { withNextFlexBlock } from './next';

/**
* WordPress dependencies
* @typedef {import('react').HTMLProps<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>} Props
*/
import { forwardRef } from '@wordpress/element';

/**
* @param {Props} props
* @param {import('react').Ref<HTMLDivElement>} ref
*/
function FlexBlock( { className, ...props }, ref ) {
const classes = classnames( 'components-flex__block', className );

return <Block { ...props } className={ classes } ref={ ref } />;
}

export default forwardRef( FlexBlock );
export default withNextFlexBlock( forwardRef( FlexBlock ) );
19 changes: 18 additions & 1 deletion packages/components/src/flex/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,27 @@ import { forwardRef } from '@wordpress/element';
* Internal dependencies
*/
import { Flex as BaseFlex } from './styles/flex-styles';
import { withNextFlex } from './next';

export { default as FlexBlock } from './block';
export { default as FlexItem } from './item';

/* eslint-disable jsdoc/valid-types */
/**
* @typedef OwnProps
* @property {import('react').CSSProperties['alignItems'] | 'top' | 'bottom'} [align='center'] Sets align-items. Top and bottom are shorthand for flex-start and flex-end respectively.
* @property {number} [gap=2] Determines the spacing in between children components. The `gap` value is a multiplier to the base value of `4`.
* @property {import('react').CSSProperties['justifyContent'] | 'left' | 'right'} [justify='space-between'] * Sets jusifty-content. Left and right are shorthand for flex-start and flex-end respectively, not the actual CSS value.
* @property {boolean} [isReversed=false] Reversed the flex direction.
*/
/* eslint-enable jsdoc/valid-types */

/** @typedef {OwnProps & import('react').HTMLProps<HTMLDivElement> & import('react').RefAttributes<HTMLDivElement>} Props */

/**
* @param {Props} props
* @param {import('react').Ref<HTMLDivElement>} ref
*/
function FlexComponent(
{
align = 'center',
Expand All @@ -42,6 +59,6 @@ function FlexComponent(
);
}

export const Flex = forwardRef( FlexComponent );
export const Flex = withNextFlex( forwardRef( FlexComponent ) );

export default Flex;
15 changes: 12 additions & 3 deletions packages/components/src/flex/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,29 @@
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';

/**
* Internal dependencies
*/
import { Item } from './styles/flex-styles';
import { withNextFlexItem } from './next';

/**
* WordPress dependencies
* @typedef {import('react').RefAttributes<HTMLDivElement> & import('react').HTMLProps<HTMLDivElement>} Props
*/
import { forwardRef } from '@wordpress/element';

/**
* @param {Props} props
* @param {import('react').Ref<HTMLDivElement>} ref
*/
function FlexItem( { className, ...props }, ref ) {
const classes = classnames( 'components-flex__item', className );

return <Item { ...props } className={ classes } ref={ ref } />;
}

export default forwardRef( FlexItem );
export default withNextFlexItem( forwardRef( FlexItem ) );
75 changes: 75 additions & 0 deletions packages/components/src/flex/next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Internal dependencies
*/
import { withNext } from '../ui/context';
import {
Flex as NextFlex,
FlexItem as NextFlexItem,
FlexBlock as NextFlexBlock,
} from '../ui/flex';

const Flex = process.env.COMPONENT_SYSTEM_PHASE === 1 ? NextFlex : undefined;
const FlexBlock =
process.env.COMPONENT_SYSTEM_PHASE === 1 ? NextFlexBlock : undefined;
const FlexItem =
process.env.COMPONENT_SYSTEM_PHASE === 1 ? NextFlexItem : undefined;

/**
* @param {import('./index').Props} props Current props.
* @return {import('../ui/flex/types').FlexProps} Next props.
*/
const flexAdapter = ( { isReversed, ...restProps } ) => ( {
// There's no equivalent for `direction` on the original component so we can just translate `isReversed` to it
direction: isReversed ? 'row-reverse' : 'row',
...restProps,
// There's an HTML attribute named `wrap` that will exist in `restProps` so we need to set it to undefined so the default behavior of the next component takes over
wrap: undefined,
} );

/**
* @param {import('./item').Props} props Current props.
* @return {import('../ui/flex/types').FlexItemProps} Next props.
*/
const flexItemAdapter = ( props ) => ( {
...props,
// ensure these are undefined so the default takes over
isBlock: undefined,
display: undefined,
} );

/**
* @param {import('./block').Props} props Current props.
* @return {import('../ui/flex/types').FlexBlockProps} Next props.
*/
const flexBlockAdapter = ( props ) => ( {
...props,
// ensure this is undefined so the default takes over
display: undefined,
} );

/* eslint-disable jsdoc/valid-types */
/**
* @param {import('react').ForwardRefExoticComponent<import('./index').Props>} Current
*/
/* eslint-enable jsdoc/valid-types */
export function withNextFlex( Current ) {
return withNext( Current, Flex, 'WPComponentsFlex', flexAdapter );
}

/* eslint-disable jsdoc/valid-types */
/**
* @param {import('react').ForwardRefExoticComponent<import('./item').Props>} Current
*/
/* eslint-enable jsdoc/valid-types */
export function withNextFlexItem( Current ) {
return withNext( Current, FlexItem, 'WPComponentsFlex', flexItemAdapter );
}

/* eslint-disable jsdoc/valid-types */
/**
* @param {import('react').ForwardRefExoticComponent<import('./block').Props>} Current
*/
/* eslint-enable jsdoc/valid-types */
export function withNextFlexBlock( Current ) {
return withNext( Current, FlexBlock, 'WPComponentsFlex', flexBlockAdapter );
}
27 changes: 23 additions & 4 deletions packages/components/src/flex/styles/flex-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,39 @@
import { css } from '@emotion/core';
import styled from '@emotion/styled';

/**
* @param {import('..').OwnProps} props
*/
const alignStyle = ( { align } ) => {
if ( align === undefined ) return '';

const aligns = {
top: 'flex-start',
bottom: 'flex-end',
};
const value = aligns[ align ] || align;

const value = aligns[ /** @type {'top' | 'bottom'} */ ( align ) ] || align;

return css( {
alignItems: value,
} );
};

/**
* @param {import('..').OwnProps} props
*/
const justifyStyle = ( { justify, isReversed } ) => {
const justifies = {
left: 'flex-start',
right: 'flex-end',
};
let value = justifies[ justify ] || justify;
let value =
justifies[ /** @type {'left' | 'right'} */ ( justify ) ] || justify;

if ( isReversed && justifies[ justify ] ) {
if (
isReversed &&
justifies[ /** @type {'left' | 'right'} */ ( justify ) ]
) {
value = justify === 'left' ? justifies.right : justifies.left;
}

Expand All @@ -32,6 +45,9 @@ const justifyStyle = ( { justify, isReversed } ) => {
} );
};

/**
* @param {import('..').OwnProps} Props
*/
const gapStyle = ( { gap, isReversed } ) => {
const base = 4;
const value = typeof gap === 'number' ? base * gap : base;
Expand All @@ -49,6 +65,9 @@ const gapStyle = ( { gap, isReversed } ) => {
`;
};

/**
* @param {import('..').OwnProps} props
*/
const reversedStyles = ( { isReversed } ) => {
if ( ! isReversed ) return '';

Expand All @@ -64,8 +83,8 @@ export const Flex = styled.div`
${ alignStyle }
${ justifyStyle }
${ gapStyle }
${ reversedStyles }
${ gapStyle }
`;

export const Item = styled.div`
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/font-size-picker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { isNumber, isString } from 'lodash';
import { __ } from '@wordpress/i18n';
import { useInstanceId } from '@wordpress/compose';
import { textColor } from '@wordpress/icons';
import { useMemo } from '@wordpress/element';
import { useMemo, forwardRef } from '@wordpress/element';

/**
* Internal dependencies
Expand Down Expand Up @@ -177,4 +177,4 @@ function FontSizePicker(
);
}

export default withNextComponent( FontSizePicker );
export default withNextComponent( forwardRef( FontSizePicker ) );
3 changes: 3 additions & 0 deletions packages/components/src/input-control/input-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function InputBase(
ref
) {
const id = useUniqueId( idProp );
const hideLabel = hideLabelFromVision || ! label;

return (
<Root
Expand All @@ -51,6 +52,7 @@ export function InputBase(
isFocused={ isFocused }
labelPosition={ labelPosition }
ref={ ref }
__unstableVersion="next"
>
<LabelWrapper>
<Label
Expand All @@ -67,6 +69,7 @@ export function InputBase(
__unstableInputWidth={ __unstableInputWidth }
className="components-input-control__container"
disabled={ disabled }
hideLabel={ hideLabel }
isFocused={ isFocused }
labelPosition={ labelPosition }
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ const containerDisabledStyles = ( { disabled } ) => {
return css( { backgroundColor } );
};

// Normalizes the margins from the <Flex /> (components/ui/flex/) container.
const containerMarginStyles = ( { hideLabel } ) => {
return hideLabel ? css( { margin: '0 !important' } ) : null;
};

const containerWidthStyles = ( { __unstableInputWidth, labelPosition } ) => {
if ( ! __unstableInputWidth ) return css( { width: '100%' } );

Expand All @@ -82,6 +87,7 @@ export const Container = styled.div`
position: relative;
${ containerDisabledStyles }
${ containerMarginStyles }
${ containerWidthStyles }
`;

Expand Down
1 change: 1 addition & 0 deletions packages/components/src/text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ const Text = styled.p(
text
);

// @ts-ignore Text _is_ forwarded ref but the styled component definition doesn't include $$typeof so we'll just ignore it here
export default withNextComponent( Text );
2 changes: 1 addition & 1 deletion packages/components/src/text/next.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const adapter = ( { as, variant, ...restProps } ) => ( {

/* eslint-disable jsdoc/valid-types */
/**
* @param {import('react').ComponentType<AdaptedTextProps>} Current
* @param {import('react').ForwardRefExoticComponent<AdaptedTextProps>} Current
*/
/* eslint-enable jsdoc/valid-types */
export function withNextComponent( Current ) {
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/ui/context/with-next.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { contextConnect, useContextSystem } from '@wp-g2/context';
/**
* @template {{}} TCurrentProps
* @template {{}} TNextProps
* @param {import('react').ComponentType<TCurrentProps>} CurrentComponent
* @param {import('react').ForwardRefExoticComponent<TCurrentProps>} CurrentComponent
* @param {import('react').ComponentType<TNextProps>} NextComponent
* @param {string} namespace
* @param {(props: TCurrentProps) => TNextProps} adapter
*/
export function withNext(
CurrentComponent = () => null,
CurrentComponent,
NextComponent = () => null,
namespace = 'Component',
adapter = ( p ) => /** @type {any} */ ( p )
Expand Down
Loading

0 comments on commit 0105c9a

Please sign in to comment.