Skip to content

Instantly share code, notes, and snippets.

@nexpr
Last active October 28, 2023 17:18
Show Gist options
  • Save nexpr/bf2c22055484df1be3983c41e91128ef to your computer and use it in GitHub Desktop.
Save nexpr/bf2c22055484df1be3983c41e91128ef to your computer and use it in GitHub Desktop.
import { html } from "lit"
import { StylitElement } from "./StylitElement.js"
class ExampleElement extends StylitElement {
static properties = {
n: {}
}
constructor() {
super()
this.n = 0
}
render() {
const $ = this.styleDirective
return html`
<div class=${$`border: 1px solid #aaa; :is(div) { padding: 10px }`}>
<button @click=${() => this.n++}>${this.n}</button>
<div class=${$`background: #ddd`}>text</div>
${this.n % 2 == 0
? html`<div class=${$`color:red`}>text</div>`
: html`<div class=${$`color:blue`}>text</div>`
}
<div class=${this.n % 2 === 0 ? $`color:red` : $`color:blue`}>
text
</div>
<div class=${$`color:${this.n % 2 === 0 ? "red" : "blue"}`}>
text
</div>
</div>
`
}
}
customElements.define("example-element", ExampleElement)
<!doctype html>
<script type="importmap">
{
"imports": {
"lit": "https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js",
"lit/directive.js": "https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js"
}
}
</script>
<script type="module" src="./ExampleElement.js"></script>
<example-element></example-element>
import { html, LitElement } from "lit"
import { directive, Directive } from "lit/directive.js"
const makeStyleDirective = (element, Directive) => {
const cssss = new CSSStyleSheet()
return {
directive: directive(
class extends Directive {
host = element
cssss = cssss
}
),
cssss,
}
}
const map = new Map()
let map_key = 0
const registry = new FinalizationRegistry((key) => {
const rule = map.get(key)
removeCSSRule(rule)
map.delete(key)
})
const removeCSSRule = (rule) => {
if (!rule) return
const stylesheet = rule.parentStyleSheet
if (!stylesheet) return
const index = [...stylesheet.cssRules].indexOf(rule)
if (index < 0) return
stylesheet.deleteRule(index)
}
class StyleDirective extends Directive {
host = null
cssss = null
rule = null
key = ""
cache = null
render(template, ...values) {
if (!this.key) {
this.key = "k" + map_key++
registry.register(this, this.key)
}
const css = `.${this.key} {${String.raw(template, ...values)}}`
if (this.cache !== css) {
removeCSSRule(this.rule)
const rule_index = this.cssss.insertRule(css)
this.rule = this.cssss.cssRules[rule_index]
map.set(this.key, this.rule)
this.cache = css
}
return this.key
}
}
export class StylitElement extends LitElement {
constructor() {
super()
const { directive, cssss } = makeStyleDirective(this, StyleDirective)
this.styleDirective = directive
this._cssss = cssss
}
createRenderRoot() {
const root = super.createRenderRoot()
root.adoptedStyleSheets.push(this._cssss)
return root
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment