Skip to content

Commit

Permalink
Merge pull request chromaui#114 from m-akinc/better-support-pseudo-st…
Browse files Browse the repository at this point in the history
…ates-with-host-selector

Better support pseudo-states in selectors with `:host()`
  • Loading branch information
ghengeveld authored Apr 15, 2024
2 parents e3202ee + e7dc467 commit 6a645d0
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 10 deletions.
17 changes: 13 additions & 4 deletions src/preview/rewriteStyleSheet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,12 @@ describe("rewriteStyleSheet", () => {
})

it('supports ":host" with classes', () => {
const sheet = new Sheet(":host(.a:hover, .b) .c { color: red }")
const sheet = new Sheet(":host(.a:hover) .c { color: red }")
rewriteStyleSheet(sheet as any)
const selectors = sheet.cssRules[0].getSelectors()
expect(selectors).toContain(":host(.a:hover, .b) .c")
expect(selectors).toContain(":host(.a.pseudo-hover, .b) .c")
expect(selectors).toContain(":host(.a.pseudo-hover-all, .b) .c")
expect(selectors).toContain(":host(.a:hover) .c")
expect(selectors).toContain(":host(.a.pseudo-hover) .c")
expect(selectors).toContain(":host(.a.pseudo-hover-all) .c")
})

it('supports ":host" with state selectors in descendant selector', () => {
Expand All @@ -232,6 +232,15 @@ describe("rewriteStyleSheet", () => {
expect(selectors).toContain(":host(.a.pseudo-hover-all) .b")
})

it('supports ":host" with state selectors in :host and descendant selector', () => {
const sheet = new Sheet(":host(.a:focus) .b:hover { color: red }")
rewriteStyleSheet(sheet as any)
const selectors = sheet.cssRules[0].getSelectors()
expect(selectors).toContain(":host(.a:focus) .b:hover")
expect(selectors).toContain(":host(.a.pseudo-focus) .b.pseudo-hover")
expect(selectors).toContain(":host(.a.pseudo-focus-all.pseudo-hover-all) .b")
})

it('supports "::slotted"', () => {
const sheet = new Sheet("::slotted(:hover) { color: red }")
rewriteStyleSheet(sheet as any)
Expand Down
11 changes: 5 additions & 6 deletions src/preview/rewriteStyleSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,14 @@ const rewriteRule = ({ cssText, selectorText }: CSSStyleRule, shadowRoot?: Shado
const statesAllClassSelectors = states.map((s) => `.pseudo-${s}-all`).join("")

if (selector.startsWith(":host(")) {
const matches = selector.match(/^:host\((\S+)\) /)
if (matches && !matchOne.test(matches[1])) {
// If :host() did not contain states, then simple replacement won't work.
const matches = selector.match(/^:host\((\S+)\)\s+(.+)$/)
if (matches && matchOne.test(matches[2])) {
// If there are pseudo-state selectors outside of :host(), then simple replacement won't work.
// E.g. :host(.foo#bar) .baz:hover:active -> :host(.foo#bar.pseudo-hover-all.pseudo-active-all) .baz
ancestorSelector = `:host(${matches[1]}${statesAllClassSelectors}) ${plainSelector.replace(matches[0], "")}`
// E.g. :host(.foo:focus) .bar:hover -> :host(.foo.pseudo-focus-all.pseudo-hover-all) .bar
ancestorSelector = `:host(${matches[1].replace(matchAll, "")}${statesAllClassSelectors}) ${matches[2].replace(matchAll, "")}`
} else {
ancestorSelector = states.reduce((acc, state) => acc.replace(replacementRegExp(state), `.pseudo-${state}-all`), selector)
// NOTE: Selectors with pseudo states on both :host and a descendant are not properly supported.
// E.g. :host(.foo:focus) .bar:hover -> :host(.foo.pseudo-focus-all.pseudo-hover-all) .bar
}
} else if (selector.startsWith("::slotted(") || shadowRoot) {
// If removing pseudo-state selectors from inside ::slotted left it empty (thus invalid), must fix it by adding '*'.
Expand Down

0 comments on commit 6a645d0

Please sign in to comment.