Skip to content

Commit

Permalink
feat(Grid): allow multiple values for reversed prop (#2235)
Browse files Browse the repository at this point in the history
  • Loading branch information
layershifter authored and levithomason committed Oct 22, 2017
1 parent 4f29636 commit 0adef6a
Show file tree
Hide file tree
Showing 13 changed files with 61 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react'
import { Grid } from 'semantic-ui-react'

const GridExampleReversedMultiple = () => (
<Grid reversed='computer tablet' columns='equal'>
<Grid.Row>
<Grid.Column>Computer and Tablet Fourth</Grid.Column>
<Grid.Column>Computer and Tablet Third</Grid.Column>
<Grid.Column>Computer and Tablet Second</Grid.Column>
</Grid.Row>
</Grid>
)

export default GridExampleReversedMultiple
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ const GridResponsiveVariationsExamples = () => (
<ComponentExample examplePath='collections/Grid/ResponsiveVariations/GridExampleReversedComputerVertically' />
<ComponentExample examplePath='collections/Grid/ResponsiveVariations/GridExampleReversedTabletVertically' />
<ComponentExample examplePath='collections/Grid/ResponsiveVariations/GridExampleReversedMobileVertically' />
<ComponentExample
description='A grid or row can specify that its columns should reverse order on multiple device sizes.'
examplePath='collections/Grid/ResponsiveVariations/GridExampleReversedMultiple'
/>

<ComponentExample
title='Device Visibility'
Expand Down
2 changes: 1 addition & 1 deletion src/collections/Grid/Grid.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { default as GridColumn } from './GridColumn';
import { default as GridRow } from './GridRow';

export type GridReversedProp = 'computer' | 'computer vertically' | 'mobile' | 'mobile vertically' | 'tablet' | 'tablet vertically';
export type GridReversedProp = string | 'computer' | 'computer vertically' | 'mobile' | 'mobile vertically' | 'tablet' | 'tablet vertically';

export interface GridProps {
[key: string]: any;
Expand Down
6 changes: 3 additions & 3 deletions src/collections/Grid/Grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
SUI,
useKeyOnly,
useKeyOrValueAndKey,
useMultipleProp,
useTextAlignProp,
useValueAndKey,
useVerticalAlignProp,
useWidthProp,
} from '../../lib'
Expand Down Expand Up @@ -53,8 +53,8 @@ function Grid(props) {
useKeyOrValueAndKey(divided, 'divided'),
useKeyOrValueAndKey(padded, 'padded'),
useKeyOrValueAndKey(relaxed, 'relaxed'),
useMultipleProp(reversed, 'reversed'),
useTextAlignProp(textAlign),
useValueAndKey(reversed, 'reversed'),
useVerticalAlignProp(verticalAlign),
useWidthProp(columns, 'column', true),
'grid',
Expand Down Expand Up @@ -124,7 +124,7 @@ Grid.propTypes = {
]),

/** A grid can specify that its columns should reverse order at different device sizes. */
reversed: PropTypes.oneOf([
reversed: customPropTypes.multipleProp([
'computer', 'computer vertically', 'mobile', 'mobile vertically', 'tablet', 'tablet vertically',
]),

Expand Down
6 changes: 3 additions & 3 deletions src/collections/Grid/GridColumn.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
META,
SUI,
useKeyOnly,
useOnlyProp,
useMultipleProp,
useTextAlignProp,
useValueAndKey,
useVerticalAlignProp,
Expand Down Expand Up @@ -41,7 +41,7 @@ function GridColumn(props) {
const classes = cx(
color,
useKeyOnly(stretched, 'stretched'),
useOnlyProp(only, 'only'),
useMultipleProp(only, 'only'),
useTextAlignProp(textAlign),
useValueAndKey(floated, 'floated'),
useVerticalAlignProp(verticalAlign),
Expand Down Expand Up @@ -92,7 +92,7 @@ GridColumn.propTypes = {
mobile: PropTypes.oneOf(SUI.WIDTHS),

/** A row can appear only for a specific device, or screen sizes. */
only: customPropTypes.onlyProp(SUI.VISIBILITY),
only: customPropTypes.multipleProp(SUI.VISIBILITY),

/** A column can stretch its contents to take up the entire grid or row height. */
stretched: PropTypes.bool,
Expand Down
11 changes: 5 additions & 6 deletions src/collections/Grid/GridRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import {
META,
SUI,
useKeyOnly,
useOnlyProp,
useMultipleProp,
useTextAlignProp,
useValueAndKey,
useVerticalAlignProp,
useWidthProp,
} from '../../lib'
Expand Down Expand Up @@ -39,9 +38,9 @@ function GridRow(props) {
useKeyOnly(centered, 'centered'),
useKeyOnly(divided, 'divided'),
useKeyOnly(stretched, 'stretched'),
useOnlyProp(only),
useMultipleProp(only, 'only'),
useMultipleProp(reversed, 'reversed'),
useTextAlignProp(textAlign),
useValueAndKey(reversed, 'reversed'),
useVerticalAlignProp(verticalAlign),
useWidthProp(columns, 'column', true),
'row',
Expand Down Expand Up @@ -82,10 +81,10 @@ GridRow.propTypes = {
divided: PropTypes.bool,

/** A row can appear only for a specific device, or screen sizes. */
only: customPropTypes.onlyProp(SUI.VISIBILITY),
only: customPropTypes.multipleProp(SUI.VISIBILITY),

/** A row can specify that its columns should reverse order at different device sizes. */
reversed: PropTypes.oneOf([
reversed: customPropTypes.multipleProp([
'computer', 'computer vertically', 'mobile', 'mobile vertically', 'tablet', 'tablet vertically',
]),

Expand Down
13 changes: 8 additions & 5 deletions src/lib/classNameBuilders.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,25 @@ export const useKeyOrValueAndKey = (val, key) => val && (val === true ? key : `$
//

/**
* The "only" prop implements control of visibility classes for Grid subcomponents.
* The "multiple" prop implements control of visibility and reserved classes for Grid subcomponents.
*
* @param {*} val The value of the "only" prop
* @param {*} val The value of the "multiple" prop
* @param {*} key A props key
*
* @example
* <Grid.Row only='mobile' />
* <Grid.Row only='mobile tablet' />
* <div class="mobile only row"></div>
* <div class="mobile only tablet only row"></div>
*/
export const useOnlyProp = (val) => {
export const useMultipleProp = (val, key) => {
if (!val || val === true) return null

return val.replace('large screen', 'large-screen')
return val
.replace('large screen', 'large-screen')
.replace(/ vertically/g, '-vertically')
.split(' ')
.map(prop => `${prop.replace('-', ' ')} only`)
.map(prop => `${prop.replace('-', ' ')} ${key}`)
.join(' ')
}

Expand Down
5 changes: 3 additions & 2 deletions src/lib/customPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,10 @@ export const demand = requiredProps => (props, propName, componentName) => {
}

/**
* Ensure an only prop contains a string with only possible values.
* Ensure an multiple prop contains a string with only possible values.
* @param {string[]} possible An array of possible values to prop.
*/
export const onlyProp = possible => (props, propName, componentName) => {
export const multipleProp = possible => (props, propName, componentName) => {
if (!Array.isArray(possible)) {
throw new Error([
'Invalid argument supplied to some, expected an instance of array.',
Expand All @@ -244,6 +244,7 @@ export const onlyProp = possible => (props, propName, componentName) => {

const values = propValue
.replace('large screen', 'large-screen')
.replace(/ vertically/g, '-vertically')
.split(' ')
.map(val => _.trim(val).replace('-', ' '))
const invalid = _.difference(values, possible)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export {
useKeyOrValueAndKey,
useValueAndKey,

useOnlyProp,
useMultipleProp,
useTextAlignProp,
useVerticalAlignProp,
useWidthProp,
Expand Down
7 changes: 3 additions & 4 deletions test/specs/collections/Grid/Grid-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,16 @@ describe('Grid', () => {
rendersContent: false,
})

common.implementsMultipleProp(GridRow, 'reversed', [
'computer', 'computer vertically', 'mobile', 'mobile vertically', 'tablet', 'tablet vertically',
])
common.implementsTextAlignProp(Grid)
common.implementsVerticalAlignProp(Grid)
common.implementsWidthProp(Grid, SUI.WIDTHS, {
propKey: 'columns',
widthClass: 'column',
})

common.propKeyAndValueToClassName(Grid, 'reversed', [
'computer', 'computer vertically', 'mobile', 'mobile vertically', 'tablet', 'tablet vertically',
])

common.propKeyOnlyToClassName(Grid, 'centered')
common.propKeyOnlyToClassName(Grid, 'container')
common.propKeyOnlyToClassName(Grid, 'doubling')
Expand Down
2 changes: 1 addition & 1 deletion test/specs/collections/Grid/GridColumn-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('GridColumn', () => {
rendersContent: false,
})

common.implementsOnlyProp(GridColumn)
common.implementsMultipleProp(GridColumn, 'only', SUI.VISIBILITY)
common.implementsTextAlignProp(GridColumn)
common.implementsVerticalAlignProp(GridColumn)

Expand Down
9 changes: 4 additions & 5 deletions test/specs/collections/Grid/GridRow-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ describe('GridRow', () => {
rendersContent: false,
})

common.implementsOnlyProp(GridRow)
common.implementsMultipleProp(GridRow, 'only', SUI.VISIBILITY)
common.implementsMultipleProp(GridRow, 'reversed', [
'computer', 'computer vertically', 'mobile', 'mobile vertically', 'tablet', 'tablet vertically',
])
common.implementsTextAlignProp(GridRow)
common.implementsVerticalAlignProp(GridRow)
common.implementsWidthProp(GridRow, SUI.WIDTHS, {
propKey: 'columns',
widthClass: 'column',
})

common.propKeyAndValueToClassName(GridRow, 'reversed', [
['computer', 'computer vertically', 'mobile', 'mobile vertically', 'tablet', 'tablet vertically'],
])

common.propKeyOnlyToClassName(GridRow, 'centered')
common.propKeyOnlyToClassName(GridRow, 'divided')
common.propKeyOnlyToClassName(GridRow, 'stretched')
Expand Down
20 changes: 11 additions & 9 deletions test/specs/commonTests/implementsCommonProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,28 +159,30 @@ export const implementsLabelProp = (Component, options = {}) => {
/**
* Assert that a Component correctly implements the "only" prop.
* @param {React.Component|Function} Component The component to test.
* @param {String} propKey A props key.
*/
export const implementsOnlyProp = (Component) => {
export const implementsMultipleProp = (Component, propKey, propValues) => {
const { assertRequired } = helpers('propKeyAndValueToClassName', Component)
const propValues = SUI.VISIBILITY

describe('only (common)', () => {
describe(`${propKey} (common)`, () => {
assertRequired(Component, 'a `Component`')

noDefaultClassNameFromProp(Component, 'only', propValues)
noClassNameFromBoolProps(Component, 'only', propValues)
noDefaultClassNameFromProp(Component, propKey, propValues)
noClassNameFromBoolProps(Component, propKey, propValues)

propValues.forEach((propVal) => {
it(`adds "${propVal} only" to className`, () => {
shallow(createElement(Component, { only: propVal })).should.have.className(`${propVal} only`)
it(`adds "${propVal} ${propKey}" to className`, () => {
shallow(createElement(Component, { [propKey]: propVal }))
.should.have.className(`${propVal} ${propKey}`)
})
})

it('adds all possible values to className', () => {
const className = propValues.map(prop => `${prop} only`).join(' ')
const className = propValues.map(prop => `${prop} ${propKey}`).join(' ')
const propValue = propValues.join(' ')

shallow(createElement(Component, { only: propValue })).should.have.className(className)
shallow(createElement(Component, { [propKey]: propValue }))
.should.have.className(className)
})
})
}
Expand Down

0 comments on commit 0adef6a

Please sign in to comment.