Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
28 changes: 14 additions & 14 deletions packages/jss/.size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
{
"jss.js": {
"bundled": 64943,
"minified": 23190,
"gzipped": 7213
"bundled": 67593,
"minified": 24213,
"gzipped": 7280
},
"jss.min.js": {
"bundled": 63547,
"minified": 22421,
"gzipped": 6867
"bundled": 66197,
"minified": 23445,
"gzipped": 6945
},
"jss.cjs.js": {
"bundled": 60631,
"minified": 26218,
"gzipped": 7331
"bundled": 63129,
"minified": 27446,
"gzipped": 7413
},
"jss.esm.js": {
"bundled": 59003,
"minified": 24912,
"gzipped": 7165,
"bundled": 61481,
"minified": 26123,
"gzipped": 7251,
"treeshaked": {
"rollup": {
"code": 20176,
"code": 21197,
"import_statements": 345
},
"webpack": {
"code": 21666
"code": 22685
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions packages/jss/src/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import pluginStyleRule, {StyleRule} from './styleRule'
import pluginConditionalRule, {ConditionalRule} from './conditionalRule'
import pluginKeyframesRule, {KeyframesRule} from './keyframesRule'
import pluginKeyframeRule, {KeyframeRule} from './keyframeRule'
import pluginLayerRule, {LayerRule} from './layerRule'
import pluginFontFaceRule, {FontFaceRule} from './fontFaceRule'
import pluginViewportRule, {ViewportRule} from './viewportRule'
import pluginSimpleRule, {SimpleRule} from './simpleRule'
Expand All @@ -11,6 +12,7 @@ export const plugins = [
pluginConditionalRule,
pluginKeyframesRule,
pluginKeyframeRule,
pluginLayerRule,
pluginFontFaceRule,
pluginViewportRule,
pluginSimpleRule
Expand All @@ -21,6 +23,7 @@ export {
ConditionalRule,
KeyframesRule,
KeyframeRule,
LayerRule,
FontFaceRule,
ViewportRule,
SimpleRule
Expand Down
3 changes: 3 additions & 0 deletions packages/jss/src/plugins/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import PluginStyleRule, {StyleRule} from './styleRule'
import PluginConditionalRule, {ConditionalRule} from './conditionalRule'
import PluginKeyframesRule, {KeyframesRule} from './keyframesRule'
import PluginKeyframeRule, {KeyframeRule} from './keyframeRule'
import PluginLayerRule, {LayerRule} from './layerRule'
import PluginFontFaceRule, {FontFaceRule} from './fontFaceRule'
import PluginViewportRule, {ViewportRule} from './viewportRule'
import PluginSimpleRule, {SimpleRule} from './simpleRule'
Expand All @@ -12,6 +13,7 @@ export type plugins = [
typeof PluginConditionalRule,
typeof PluginKeyframesRule,
typeof PluginKeyframeRule,
typeof PluginLayerRule,
typeof PluginFontFaceRule,
typeof PluginViewportRule,
typeof PluginSimpleRule
Expand All @@ -22,6 +24,7 @@ declare export {
ConditionalRule,
KeyframesRule,
KeyframeRule,
LayerRule,
FontFaceRule,
ViewportRule,
SimpleRule
Expand Down
89 changes: 89 additions & 0 deletions packages/jss/src/plugins/layerRule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import RuleList from '../RuleList'
import getWhitespaceSymbols from '../utils/getWhitespaceSymbols'

const defaultToStringOptions = {
indent: 1,
children: true
}

const atRegExp = /@([\w-]+)/

/**
* Rule for @layer
*/
export class LayerRule {
type = 'layer'

isProcessed = false

constructor(key, styles, options) {
this.key = key
const atMatch = key.match(atRegExp)
this.at = atMatch ? atMatch[1] : 'unknown'
// Key might contain a unique suffix in case the `name` passed by user was duplicate.
this.query = options.name || `@${this.at}`
this.options = options
this.rules = new RuleList({...options, parent: this})

for (const name in styles) {
this.rules.add(name, styles[name])
}

this.rules.process()
}

/**
* Get a rule.
*/
getRule(name) {
return this.rules.get(name)
}

/**
* Get index of a rule.
*/
indexOf(rule) {
return this.rules.indexOf(rule)
}

/**
* Create and register rule, run plugins.
*/
addRule(name, style, options) {
const rule = this.rules.add(name, style, options)
if (!rule) return null
this.options.jss.plugins.onProcessRule(rule)
return rule
}

/**
* Replace rule, run plugins.
*/
replaceRule(name, style, options) {
const newRule = this.rules.replace(name, style, options)
if (newRule) this.options.jss.plugins.onProcessRule(newRule)
return newRule
}

/**
* Generates a CSS string.
*/
toString(options = defaultToStringOptions) {
const {linebreak} = getWhitespaceSymbols(options)
if (options.indent == null) options.indent = defaultToStringOptions.indent
if (options.children == null) options.children = defaultToStringOptions.children
if (options.children === false) {
return `${this.query} {}`
}
const children = this.rules.toString(options)
return children ? `${this.query} {${linebreak}${children}${linebreak}}` : ''
}
}

const keyRegExp = /@layer\s+/

export default {
onCreateRule(key, styles, options) {
return keyRegExp.test(key) ? new LayerRule(key, styles, options) : null
}
}
33 changes: 33 additions & 0 deletions packages/jss/src/plugins/layerRule.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// @flow
import RuleList from '../RuleList'
import type {
CSSMediaRule,
Rule,
RuleOptions,
ToCssOptions,
JssStyle,
// eslint doesn't understand usage with types
// eslint-disable-next-line no-unused-vars
ContainerRule
} from '../flow-types'

declare export class LayerRule implements ContainerRule {
type: string;
at: string;
key: string;
query: string;
rules: RuleList;
options: RuleOptions;
isProcessed: boolean;
renderable: ?CSSMediaRule;
constructor(key: string, styles: Object, options: RuleOptions): this;
getRule(name: string): Rule;
indexOf(rule: Rule): number;
addRule(name: string, style: JssStyle, options?: RuleOptions): Rule | null;
replaceRule(name: string, style: JssStyle, options?: RuleOptions): Rule | null;
toString(options?: ToCssOptions): string;
}

declare export default {
onCreateRule(key: string, styles: JssStyle, options: RuleOptions): LayerRule | null
}
28 changes: 28 additions & 0 deletions packages/jss/tests/integration/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,34 @@ describe('Integration: rules', () => {
`)
})

describe('@layer rule', () => {
it('should return CSS', () => {
const rule = jss.createRule('@layer test', {
button: {
color: 'red'
}
})
expect(rule.type).to.be('layer')
expect(rule.key).to.be('@layer test')
expect(rule.toString()).to.be(stripIndent`
@layer test {
.button-id {
color: red;
}
}
`)
})

it('should return CSS without empty rule', () => {
const rule = jss.createRule('@layer test', {
button: {}
})
expect(rule.type).to.be('layer')
expect(rule.key).to.be('@layer test')
expect(rule.toString()).to.be('')
})
})

describe('@media rule', () => {
it('should return CSS', () => {
const rule = jss.createRule('@media print', {a: {display: 'none'}})
Expand Down