Skip to content

Instantly share code, notes, and snippets.

@barneycarroll
Last active June 29, 2022 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save barneycarroll/9436eb23c937e8d1433170b2da7c8174 to your computer and use it in GitHub Desktop.
Save barneycarroll/9436eb23c937e8d1433170b2da7c8174 to your computer and use it in GitHub Desktop.
Simple CSS-in-JS via speculative 'MFX' idiom. MFX inverts the typical convenience component interface for Mithril: 1) no opportunity to return virtual DOM; 2) completely flexible input signature; 3) executes on every render; 4) returns a lifecycle dictionary. The mechanism is a very simple wrapper for a lifecycled fragment which always produces …
import css from './css.js'
let color = 'red'
let fontFamily = 'sans-serif'
m.mount(document.body, {
view: () => [
m('p',
css`
color: ${ color };
`,
css`
font: 2em/1.5 ${ fontFamily };
`,
'Hi',
),
m('input', {
value: color,
oninput: e => {
color = e.target.value
},
}),
m('select', {
onchange: e => {
fontFamily = e.target.selectedOptions[0].value
},
},
['serif', 'sans-serif', 'monospace'].map(value =>
m('option', {
selected: value === fontFamily
}, value),
),
),
],
})
import mfx from './mfx.js'
import xet from 'xet'
const style = document.head.appendChild(
document.createElement('style')
)
const classes = new WeakMap
let count = 0
export default mfx((template, ...variables) => ({
oninit(){
this.name = xet(classes, template, () => {
const name = `class${ count++ }`
style.textContent += (
`.${ name } {${ variables.reduce(
(string, _, index) => `${ string }`var(--${ name }'-var${ index })${ template:at(index + 1) }`,
template[0],
) }}\n`
)
return name
})
},
oncreate({dom, attrs}){
dom.parentNode.classList.add(this.name)
attrs.onupdate.apply(this, arguments)
},
onupdate({dom}){
variables.forEach((value, index) => {
dom.parentNode.style.setProperty(`--${ this.name }-var{ index }`, value)
})
}
}))
export default function mfx(factory){
return function transform(){
return m.fragment(factory.apply(this, arguments), '')
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment