Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic support for CSS grid prefixing #174

Merged
merged 5 commits into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions modules/__tests__/createPrefixer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,5 +431,129 @@ describe('Static Prefixer', () => {
expect(prefix(input)).toEqual(output)
})
})

describe('grid', () => {
it('should prefix display values', () => {
const input = { display: 'grid' }
const inlineInput = { display: 'inline-grid' }
const output = { display: ['-ms-grid', 'grid'] }
const inlineOutput = { display: ['-ms-inline-grid', 'inline-grid'] }
expect(prefix(input)).toEqual(output)
expect(prefix(inlineInput)).toEqual(inlineOutput)
})

it('should prefix basic alignment values', () => {
const input = { alignSelf: 'stretch', justifySelf: 'end' }
const output = {
WebkitAlignSelf: 'stretch',
alignSelf: 'stretch',
justifySelf: 'end',
msFlexItemAlign: 'stretch',
msGridColumnAlign: 'end',
msGridRowAlign: 'stretch',
}
expect(prefix(input)).toEqual(output)
})

describe('template', () => {
it('should prefix column templating', () => {
const input = { gridTemplateColumns: '1fr auto' }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some test cases for named grid areas?(e.g. https://vgpena.github.io/using-css-grid-the-right-way/#use-names-not-numbers)

const output = {
gridTemplateColumns: '1fr auto',
msGridColumns: '1fr auto',
msGridTemplateColumns: '1fr auto', // Not a valid property
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by the comment here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list of properties defined here causes this prefix to be automatically generated, even if it isn't valid (to the best of my knowledge). I don't have full context on why this is generated, but I think it could be removed - just waiting to hear back for confirmation.

}
expect(prefix(input)).toEqual(output)
})

it('should prefix row templating', () => {
const input = { gridTemplateRows: '1fr auto' }
const output = {
gridTemplateRows: '1fr auto',
msGridRows: '1fr auto',
msGridTemplateRows: '1fr auto', // Not a valid property
}
expect(prefix(input)).toEqual(output)
})

it('should prefix templating even with named grid lines', () => {
const input = { gridTemplateColumns: '1fr [header content] auto' }
const output = {
gridTemplateColumns: '1fr [header content] auto',
msGridColumns: '1fr [header content] auto',
msGridTemplateColumns: '1fr [header content] auto', // Not a valid property
}
expect(prefix(input)).toEqual(output)
})
})

describe('positions', () => {
it('should prefix a cell with numerical start and end column values', () => {
const input = { gridColumnStart: 2, gridColumnEnd: 5 }
const output = {
gridColumnEnd: 5,
gridColumnStart: 2,
msGridColumn: 2,
msGridColumnEnd: 5, // Not a valid property
msGridColumnSpan: 3,
msGridColumnStart: 2, // Not a valid property
}
expect(prefix(input)).toEqual(output)
})

it('should prefix a cell with numerical start and end row values', () => {
const input = { gridRowStart: 3, gridRowEnd: 7 }
const output = {
gridRowEnd: 7,
gridRowStart: 3,
msGridRow: 3,
msGridRowEnd: 7, // Not a valid property
msGridRowSpan: 4,
msGridRowStart: 3, // Not a valid property
}
expect(prefix(input)).toEqual(output)
})

it('should not prefix a cell with non-numerical position values', () => {
const input = { gridRowStart: 'span 3', gridRowEnd: 5 }
const output = {
gridRowEnd: 5,
gridRowStart: 'span 3',
msGridRowEnd: 5, // Not a valid property
msGridRowStart: 'span 3', // Not a valid property
}
expect(prefix(input)).toEqual(output)
})

it('should expand the shorthand column syntax', () => {
const input = { gridColumn: '3 / 5' }
const output = {
gridColumn: '3 / 5',
msGridColumn: 3,
msGridColumnSpan: 2,
}
expect(prefix(input)).toEqual(output)
})

it('should expand the shorthand row syntax', () => {
const input = { gridRow: '2 / 7' }
const output = {
gridRow: '2 / 7',
msGridRow: 2,
msGridRowSpan: 5,
}
expect(prefix(input)).toEqual(output)
})

it('should not expand non-numerical values', () => {
const input = { gridRow: '2 / span 3' }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lencioni What's the reason why we wouldn't want 2 / span 3 to expand?

const output = {
gridRow: '2 / span 3',
msGridRow: 2,
}
expect(prefix(input)).toEqual(output)
})
})
})
})
})
5 changes: 5 additions & 0 deletions modules/generator/maps/pluginMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ export default {
android: 4.4,
and_uc: maximumVersion,
},
grid: {
edge: 16,
ie: 11,
ie_mob: 11,
},
imageSet: {
chrome: maximumVersion,
safari: maximumVersion,
Expand Down
2 changes: 2 additions & 0 deletions modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import filter from './plugins/filter'
import flex from './plugins/flex'
import flexboxOld from './plugins/flexboxOld'
import gradient from './plugins/gradient'
import grid from './plugins/grid'
import imageSet from './plugins/imageSet'
import logical from './plugins/logical'
import position from './plugins/position'
Expand All @@ -22,6 +23,7 @@ const plugins = [
filter,
flexboxOld,
gradient,
grid,
imageSet,
logical,
position,
Expand Down
95 changes: 95 additions & 0 deletions modules/plugins/grid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* @flow */

function isSimplePositionValue(value: any) {
return typeof value === 'number' && !isNaN(value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? isNaN is available in more places, and the typeof ensures it'll behave identically.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we came full circle on this one

}

const alignmentValues = ['center', 'end', 'start', 'stretch']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it is worth using something that has constant time lookup for this? I don't see Set used anywhere though, but an object should do the trick. n=4 though, so maybe it doesn't really matter.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It definitely shouldn't matter, but an object would be fine too i suppose.


const displayValues = {
'inline-grid': ['-ms-inline-grid', 'inline-grid'],
grid: ['-ms-grid', 'grid'],
}

const propertyConverters = {
alignSelf: (value: any, style: Object) => {
if (alignmentValues.indexOf(value) > -1) {
style.msGridRowAlign = value
}
},

gridColumn: (value: any, style: Object) => {
if (isSimplePositionValue(value)) {
style.msGridColumn = value
} else {
const [start, end] = value.split('/').map(position => +position)
propertyConverters.gridColumnStart(start, style)
propertyConverters.gridColumnEnd(end, style)
}
},

gridColumnEnd: (value: any, style: Object) => {
const { msGridColumn } = style
if (isSimplePositionValue(value) && isSimplePositionValue(msGridColumn)) {
style.msGridColumnSpan = value - msGridColumn
}
},

gridColumnStart: (value: any, style: Object) => {
if (isSimplePositionValue(value)) {
style.msGridColumn = value
}
},

gridRow: (value: any, style: Object) => {
if (isSimplePositionValue(value)) {
style.msGridRow = value
} else {
const [start, end] = value.split('/').map(position => +position)
propertyConverters.gridRowStart(start, style)
propertyConverters.gridRowEnd(end, style)
}
},

gridRowEnd: (value: any, style: Object) => {
const { msGridRow } = style
if (isSimplePositionValue(value) && isSimplePositionValue(msGridRow)) {
style.msGridRowSpan = value - msGridRow
}
},

gridRowStart: (value: any, style: Object) => {
if (isSimplePositionValue(value)) {
style.msGridRow = value
}
},

gridTemplateColumns: (value: any, style: Object) => {
style.msGridColumns = value
},

gridTemplateRows: (value: any, style: Object) => {
style.msGridRows = value
},

justifySelf: (value: any, style: Object) => {
if (alignmentValues.indexOf(value) > -1) {
style.msGridColumnAlign = value
}
},
}

export default function grid(
property: string,
value: any,
style: Object
): ?Array<string> {
if (property === 'display' && value in displayValues) {
return displayValues[value]
}

if (property in propertyConverters) {
const propertyConverter = propertyConverters[property]
propertyConverter(value, style)
}
}
2 changes: 2 additions & 0 deletions modules/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import flex from './flex'
import flexboxIE from './flexboxIE'
import flexboxOld from './flexboxOld'
import gradient from './gradient'
import grid from './grid'
import imageSet from './imageSet'
import logical from './logical'
import position from './position'
Expand All @@ -23,6 +24,7 @@ export default [
flexboxIE,
flexboxOld,
gradient,
grid,
imageSet,
logical,
position,
Expand Down