Skip to content

Commit

Permalink
improve injection order (stitchesjs#875)
Browse files Browse the repository at this point in the history
* improve injection order

* add comments
  • Loading branch information
hadihallak authored Nov 17, 2021
1 parent 326ac59 commit 36c7975
Show file tree
Hide file tree
Showing 15 changed files with 212 additions and 178 deletions.
39 changes: 26 additions & 13 deletions packages/core/src/features/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { hasOwn } from '../utility/hasOwn.js'
import { toCssRules } from '../convert/toCssRules.js'
import { toHash } from '../convert/toHash.js'
import { toTailDashed } from '../convert/toTailDashed.js'
import { createRulesInjectionDeferrer } from '../sheet.js'

/** @typedef {import('./css').Internals} Internals */
/** @typedef {import('./css').Composer} Composer */
Expand Down Expand Up @@ -141,6 +142,9 @@ const createRenderer = (
undefinedVariants
] = getPreparedDataFromComposers(internals.composers)

const differedInjector = typeof internals.type === 'function' ? createRulesInjectionDeferrer(sheet) : null
const injectionTarget = differedInjector?.rules || sheet.rules

const selector = `.${baseClassName}${baseClassNames.length > 1 ? `:where(.${baseClassNames.slice(1).join('.')})` : ``}`

/** @type {Render} */
Expand Down Expand Up @@ -194,8 +198,8 @@ const createRenderer = (
if (!sheet.rules.styled.cache.has(composerBaseClass)) {
sheet.rules.styled.cache.add(composerBaseClass)

toCssRules(composerBaseStyle, [`.${composerBaseClass}`], [], config, cssText => {
sheet.rules.styled.apply(cssText)
toCssRules(composerBaseStyle, [`.${composerBaseClass}`], [], config, (cssText) => {
injectionTarget.styled.apply(cssText)
})
}

Expand All @@ -205,16 +209,22 @@ const createRenderer = (
for (const variantToAdd of singularVariantsToAdd) {
if (variantToAdd === undefined) continue

for (const [vClass, vStyle] of variantToAdd) {
for (const [vClass, vStyle, isResponsive] of variantToAdd) {
const variantClassName = `${composerBaseClass}-${toHash(vStyle)}-${vClass}`

classSet.add(variantClassName)

if (!sheet.rules.onevar.cache.has(variantClassName)) {
sheet.rules.onevar.cache.add(variantClassName)

toCssRules(vStyle, [`.${variantClassName}`], [], config, cssText => {
sheet.rules.onevar.apply(cssText)
const groupCache = (isResponsive ? sheet.rules.resonevar : sheet.rules.onevar ).cache
/*
* make sure that normal variants are injected before responsive ones
* @see {@link https://github.com/modulz/stitches/issues/737|github}
*/
const targetInjectionGroup = isResponsive ? injectionTarget.resonevar : injectionTarget.onevar

if (!groupCache.has(variantClassName)) {
groupCache.add(variantClassName)
toCssRules(vStyle, [`.${variantClassName}`], [], config, (cssText) => {
targetInjectionGroup.apply(cssText)
})
}
}
Expand All @@ -231,8 +241,8 @@ const createRenderer = (
if (!sheet.rules.allvar.cache.has(variantClassName)) {
sheet.rules.allvar.cache.add(variantClassName)

toCssRules(vStyle, [`.${variantClassName}`], [], config, cssText => {
sheet.rules.allvar.apply(cssText)
toCssRules(vStyle, [`.${variantClassName}`], [], config, (cssText) => {
injectionTarget.allvar.apply(cssText)
})
}
}
Expand All @@ -249,8 +259,8 @@ const createRenderer = (
if (!sheet.rules.inline.cache.has(iClass)) {
sheet.rules.inline.cache.add(iClass)

toCssRules(css, [`.${iClass}`], [], config, cssText => {
sheet.rules.inline.apply(cssText)
toCssRules(css, [`.${iClass}`], [], config, (cssText) => {
injectionTarget.inline.apply(cssText)
})
}
}
Expand All @@ -269,6 +279,7 @@ const createRenderer = (
selector,
props: forwardProps,
toString: renderedToString,
differedInjector,
}
}

Expand Down Expand Up @@ -347,6 +358,7 @@ const getTargetVariantsToAdd = (
/** @type {string & keyof typeof vMatch} */
let vName

let isResponsive = false
for (vName in vMatch) {
const vPair = vMatch[vName]

Expand All @@ -367,6 +379,7 @@ const getTargetVariantsToAdd = (
vStyle = {
[query in media ? media[query] : query]: vStyle,
}
isResponsive = true
}

vOrder += qOrder
Expand All @@ -384,7 +397,7 @@ const getTargetVariantsToAdd = (
else continue targetVariants
}

(targetVariantsToAdd[vOrder] = targetVariantsToAdd[vOrder] || []).push([isCompoundVariant ? `cv` : `${vName}-${vMatch[vName]}`, vStyle])
(targetVariantsToAdd[vOrder] = targetVariantsToAdd[vOrder] || []).push([isCompoundVariant ? `cv` : `${vName}-${vMatch[vName]}`, vStyle, isResponsive])
}

return targetVariantsToAdd
Expand Down
138 changes: 51 additions & 87 deletions packages/core/src/sheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@
/** @typedef {import('./sheet').RuleGroupNames} RuleGroupNames */
/** @typedef {import('./sheet').SheetGroup} SheetGroup */

/**
* Rules in the sheet appear in this order:
* 1. theme rules (themed)
* 2. global rules (global)
* 3. component rules (styled)
* 4. non-responsive variants rules (onevar)
* 5. responsive variants rules (resonevar)
* 6. compound variants rules (allvar)
* 7. inline rules (inline)
*/
/** @type {RuleGroupNames} */
const names = ['themed', 'global', 'styled', 'onevar', 'allvar', 'inline']
export const names = ['themed', 'global', 'styled', 'onevar', 'resonevar', 'allvar', 'inline']

export const createSheet = (/** @type {DocumentOrShadowRoot} */ root) => {
/** @type {SheetGroup} Object hosting the hydrated stylesheet. */
Expand All @@ -22,10 +32,6 @@ export const createSheet = (/** @type {DocumentOrShadowRoot} */ root) => {
for (const groupName in rules) {
delete rules[groupName]
}

if (sheet.ownerRule) {
sheet.ownerRule.textContent = sheet.ownerRule.textContent
}
}

/** @type {StyleSheetList} */
Expand Down Expand Up @@ -123,90 +129,22 @@ export const createSheet = (/** @type {DocumentOrShadowRoot} */ root) => {
}

const { sheet, rules } = groupSheet

// conditionally generate the inline group
if (!rules.inline) {
const index = sheet.cssRules.length
sheet.insertRule('@media{}', index)
sheet.insertRule('--sxs{--sxs:5}', index)

rules.inline = {
index: index,
group: sheet.cssRules[index + 1],
cache: new Set([5]),
}
}
addApplyToGroup(rules.inline)

// conditionally generate the allvar group
if (!rules.allvar) {
const index = rules.inline.index
sheet.insertRule('@media{}', index)
sheet.insertRule('--sxs{--sxs:4}', index)

rules.allvar = {
index: index,
group: sheet.cssRules[index + 1],
cache: new Set([4]),
}
}
addApplyToGroup(rules.allvar)

// conditionally generate the onevar group
if (!rules.onevar) {
const index = rules.allvar.index
sheet.insertRule('@media{}', index)
sheet.insertRule('--sxs{--sxs:3}', index)

rules.onevar = {
index: index,
group: sheet.cssRules[index + 1],
cache: new Set([3]),
}
}
addApplyToGroup(rules.onevar)

// conditionally generate the styled group
if (!rules.styled) {
const index = rules.onevar.index
sheet.insertRule('@media{}', index)
sheet.insertRule('--sxs{--sxs:2}', index)

rules.styled = {
index: index,
group: sheet.cssRules[index + 1],
cache: new Set([2]),
}
}
addApplyToGroup(rules.styled)

// conditionally generate the global group
if (!rules.global) {
const index = rules.styled.index
sheet.insertRule('@media{}', index)
sheet.insertRule('--sxs{--sxs:1}', index)

rules.global = {
index: index,
group: sheet.cssRules[index + 1],
cache: new Set([1]),
}
}
addApplyToGroup(rules.global)

// conditionally generate the themed group
if (!rules.themed) {
const index = rules.global.index
sheet.insertRule('@media{}', index)
sheet.insertRule('--sxs{--sxs:0}', index)

rules.themed = {
index: index,
group: sheet.cssRules[index + 1],
cache: new Set([0]),
for (let i = names.length - 1; i >= 0; --i) {
// name of group on current index
const name = names[i]
if (!rules[name]) {
// name of prev group
const prevName = names[i + 1]
// get the index of that prev group or else get the length of the whole sheet
const index = rules[prevName] ? rules[prevName].index : sheet.cssRules.length
// insert the grouping & the sxs rule
sheet.insertRule('@media{}', index)
sheet.insertRule(`--sxs{--sxs:${i}}`, index)
// add the group to the group sheet
rules[name] = { group: sheet.cssRules[index + 1], index, cache: new Set([i]) }
}
addApplyToGroup(rules[name])
}
addApplyToGroup(rules.themed)
}

reset()
Expand All @@ -229,3 +167,29 @@ const addApplyToGroup = (/** @type {RuleGroup} */ group) => {
}
}
}
/** Pending rules for injection */
const $pr = Symbol()

/**
* When a stitches component is extending some other random react component,
* it’s gonna create a react component (Injector) using this function and then render it after the children,
* this way, we would force the styles of the wrapper to be injected after the wrapped component
*/
export const createRulesInjectionDeferrer = (globalSheet) => {
// the injection deferrer
function injector() {
for (let i = 0; i < injector[$pr].length; i++) {
const [sheet, cssString] = injector[$pr][i]
globalSheet.rules[sheet].apply(cssString)
}
injector[$pr] = []
return null
}
// private prop to store pending rules
injector[$pr] = []
// mocking the rules.apply api used on the sheet
injector.rules = {}
// creating the apply methods under rules[something]
names.forEach((sheetName) => (injector.rules[sheetName] = { apply: (rule) => injector[$pr].push([sheetName, rule]) }))
return injector
}
2 changes: 1 addition & 1 deletion packages/core/tests/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ describe('Basic', () => {
`--sxs{--sxs:2 c-dataoT}@media{` +
`.c-dataoT{color:DodgerBlue}` +
`}` +
`--sxs{--sxs:5 c-dataoT-icaIZdx-css}@media{` +
`--sxs{--sxs:6 c-dataoT-icaIZdx-css}@media{` +
`.c-dataoT-icaIZdx-css{color:Crimson}` +
`}`
)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/tests/component-css-prop.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('Component with CSS prop', () => {
`--sxs{--sxs:2 c-hhyRYU}@media{` +
`.c-hhyRYU{order:1}` +
`}` +
`--sxs{--sxs:5 c-hhyRYU-ilhKMMn-css}@media{` +
`--sxs{--sxs:6 c-hhyRYU-ilhKMMn-css}@media{` +
`.c-hhyRYU-ilhKMMn-css{order:2}` +
`}`
)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/tests/component-empty-variants.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ describe('Empty Variants', () => {
})

expect(getCssText()).toBe(
`--sxs{--sxs:4 c-PJLV-lhHHWD-cv}@media{` +
`--sxs{--sxs:5 c-PJLV-lhHHWD-cv}@media{` +
`.c-PJLV-lhHHWD-cv{font-size:24px;color:black}` +
`}`
)
Expand Down
Loading

0 comments on commit 36c7975

Please sign in to comment.