-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
350 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import {createElement as h} from 'react'; | ||
import {storiesOf} from '@storybook/react'; | ||
const {create} = require('../index'); | ||
const {addon: addonCSSOM} = require('../addon/cssom'); | ||
const {addon: addonVCSSOM} = require('../addon/vcssom'); | ||
|
||
const nano = create(); | ||
addonCSSOM(nano); | ||
addonVCSSOM(nano); | ||
|
||
const sheet = new nano.VSheet(); | ||
sheet.diff({ | ||
'': { | ||
'.test_vcssom': { | ||
color: 'green', | ||
} | ||
} | ||
}); | ||
sheet.diff({ | ||
'': { | ||
'.test_vcssom': { | ||
border: '1px solid tomato', | ||
} | ||
}, | ||
'@media only screen and (max-width: 600px)': { | ||
'.test_vcssom': { | ||
'text-decoration': 'underline', | ||
}, | ||
} | ||
}); | ||
sheet.diff({ | ||
'': { | ||
'.test_vcssom': { | ||
color: 'orange', | ||
'text-transform': 'uppercase', | ||
'font-style': 'italic', | ||
'text-align': 'center', | ||
border: '1px solid black', | ||
}, | ||
'.test_vcssom:hover': { | ||
color: 'red', | ||
} | ||
} | ||
}); | ||
|
||
console.log('sheet', sheet); | ||
|
||
storiesOf('Addons/VCSSOM', module) | ||
.add('rule', () => | ||
h('div', {className: 'test_vcssom'}, 'addonVCSSOM') | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/* eslint-disable */ | ||
'use strict'; | ||
|
||
var cssToTree = require('../vcssom').cssToTree; | ||
|
||
describe('cssToTree', function () { | ||
test('exist', function () { | ||
expect(cssToTree).toBeInstanceOf(Function); | ||
}); | ||
|
||
test('simple object', () => { | ||
var tree = {}; | ||
cssToTree(tree, {color: 'red'}, '&', ''); | ||
|
||
expect(tree).toEqual({ | ||
'': { | ||
'&': { | ||
color: 'red' | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
test('multiple properties', () => { | ||
var tree = {}; | ||
var css = { | ||
color: 'red', | ||
border: '1px solid tomato', | ||
textDecoration: 'underline,' | ||
}; | ||
cssToTree(tree, css, '&', ''); | ||
|
||
expect(tree).toEqual({ '': | ||
{ '&': | ||
{ color: 'red', | ||
border: '1px solid tomato', | ||
textDecoration: 'underline,' } } }); | ||
}); | ||
|
||
test('nested selector', () => { | ||
var tree = {}; | ||
var css = { | ||
color: 'red', | ||
svg: { | ||
fill: 'green', | ||
} | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({ | ||
'': { | ||
'X svg': { | ||
fill: 'green' | ||
}, | ||
X: { | ||
color: 'red' | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
test('nesting with single & pseudo selector', () => { | ||
var tree = {}; | ||
var css = { | ||
svg: { | ||
fill: 'red', | ||
}, | ||
'&:hover': { | ||
fill: 'green', | ||
} | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({"": {"X svg": {"fill": "red"}, "X:hover": {"fill": "green"}}}); | ||
}); | ||
|
||
test('more complicated nesting', () => { | ||
var tree = {}; | ||
var css = { | ||
border: '1px solid red', | ||
fontFamily: 'monospace', | ||
'&:hover': { | ||
color: 'red', | ||
}, | ||
'.global_class &': { | ||
textDecoration: 'underline', | ||
}, | ||
'& svg': { | ||
fill: 'red', | ||
}, | ||
'&:hover svg': { | ||
fill: 'green', | ||
} | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({ '': | ||
{ X: { border: '1px solid red', fontFamily: 'monospace' }, | ||
'X:hover': { color: 'red' }, | ||
'.global_class X': { textDecoration: 'underline' }, | ||
'X svg': { fill: 'red' }, | ||
'X:hover svg': { fill: 'green' } } }); | ||
}); | ||
|
||
test('interpolates multiple ampersands', () => { | ||
var tree = {}; | ||
var css = { | ||
'&:hover,&:active': { | ||
color: 'red', | ||
}, | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({ '': { 'X:hover,X:active': { color: 'red' } } }); | ||
}); | ||
|
||
test('interpolates multiple ampersands wither further nesting', () => { | ||
var tree = {}; | ||
var css = { | ||
'&:hover,&:active': { | ||
svg: { | ||
fill: 'red', | ||
} | ||
}, | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({ '': { 'X:hover svg,X:active svg': { fill: 'red' } } }); | ||
}); | ||
|
||
test('supports media query', () => { | ||
var tree = {}; | ||
var css = { | ||
'@media screen': { | ||
color: 'red', | ||
} | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({ '@media screen': { X: { color: 'red' } } }); | ||
}); | ||
|
||
test('media query with other values', () => { | ||
var tree = {}; | ||
var css = { | ||
color: 'green', | ||
'@media screen': { | ||
color: 'red', | ||
'&:hover': { | ||
color: 'blue', | ||
} | ||
} | ||
}; | ||
cssToTree(tree, css, 'X', ''); | ||
|
||
expect(tree).toEqual({ '': { X: { color: 'green' } }, | ||
'@media screen': { X: { color: 'red' }, 'X:hover': { color: 'blue' } } }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
'use strict'; | ||
|
||
var cssToTree = function (tree, css, selector, prelude) { | ||
var declarations = {}; | ||
var hasDeclarations = false; | ||
var key, value; | ||
|
||
for (key in css) { | ||
value = css[key]; | ||
if (typeof value !== 'object') { | ||
hasDeclarations = true; | ||
declarations[key] = value; | ||
} | ||
} | ||
|
||
if (hasDeclarations) { | ||
if (!tree[prelude]) tree[prelude] = {}; | ||
tree[prelude][selector] = declarations; | ||
} | ||
|
||
for (key in css) { | ||
value = css[key]; | ||
if (typeof value === 'object') { | ||
if (key[0] === '@') { | ||
cssToTree(tree, value, selector, key); | ||
} else { | ||
var hasCurrentSymbol = key.indexOf('&') > -1; | ||
var selectorParts = selector.split(','); | ||
if (hasCurrentSymbol) { | ||
for (var i = 0; i < selectorParts.length; i++) { | ||
selectorParts[i] = key.replace(/&/g, selectorParts[i]); | ||
} | ||
} else { | ||
for (var i = 0; i < selectorParts.length; i++) { | ||
selectorParts[i] = selectorParts[i] + ' ' + key; | ||
} | ||
} | ||
cssToTree(tree, value, selectorParts.join(','), prelude); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
exports.cssToTree = cssToTree; | ||
|
||
exports.addon = function (renderer) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
require('./__dev__/warnOnMissingDependencies')('pipe', renderer, ['createRule']); // cssom | ||
} | ||
|
||
function VRule (rule, decl) { | ||
this.rule = rule; | ||
this.decl = decl; | ||
} | ||
|
||
VRule.prototype.diff = function (newDecl) { | ||
var oldDecl = this.decl; | ||
var style = this.rule.style; | ||
var property; | ||
|
||
for (property in oldDecl) | ||
if (newDecl[property] === undefined) | ||
style.removeProperty(property); | ||
|
||
for (property in newDecl) { | ||
if (newDecl[property] !== oldDecl[property]) { | ||
style.setProperty(property, newDecl[property]); | ||
} | ||
} | ||
|
||
this.decl = newDecl; | ||
}; | ||
|
||
function VSheet () { | ||
/** | ||
* { | ||
* '<at-rule-prelude>': { | ||
* '<selector>': { | ||
* color: 'red | ||
* } | ||
* } | ||
* } | ||
*/ | ||
this.tree = {}; | ||
} | ||
|
||
VSheet.prototype.diff = function (newTree) { | ||
var sh = renderer.sh.sheet; | ||
var msh = renderer.msh.sheet; | ||
var oldTree = this.tree; | ||
|
||
// Remove media queries not present in new tree. | ||
for (var prelude in oldTree) { | ||
if (newTree[prelude] === undefined) { | ||
var rules = oldTree[prelude]; | ||
for (var selector in rules) { | ||
msh.deleteRule(rules[selector].index); | ||
} | ||
} | ||
} | ||
|
||
for (var prelude in newTree) { | ||
if (oldTree[prelude] === undefined) { | ||
// Whole media query is new. | ||
for (var selector in newTree[prelude]) { | ||
var rule = new VRule(renderer.createRule(selector, prelude), {}); | ||
rule.diff(newTree[prelude][selector]); | ||
newTree[prelude][selector] = rule; | ||
} | ||
} else { | ||
// Old tree already has rules with this media query. | ||
var oldRules = oldTree[prelude]; | ||
var newRules = newTree[prelude]; | ||
|
||
// Remove rules not present in new tree. | ||
for (var selector in oldRules) { | ||
if (!newRules[selector]) | ||
sh.deleteRule(oldRules[selector].index) | ||
} | ||
|
||
// Apply new rules. | ||
for (var selector in newRules) { | ||
var rule = oldRules[selector]; | ||
if (rule) { | ||
rule.diff(newRules[selector]); | ||
newRules[selector] = rule; | ||
} else { | ||
rule = new VRule(renderer.createRule(selector, prelude), {}); | ||
rule.diff(newRules[selector]); | ||
newRules[selector] = rule; | ||
} | ||
} | ||
} | ||
} | ||
|
||
this.tree = newTree; | ||
}; | ||
|
||
renderer.VSheet = VSheet | ||
}; |