Skip to content

Instantly share code, notes, and snippets.

@denilsonsa
Last active April 2, 2025 05:15
Show Gist options
  • Save denilsonsa/4fc1a7bbdf6cfdbd31fe10d22f8e29d1 to your computer and use it in GitHub Desktop.
Save denilsonsa/4fc1a7bbdf6cfdbd31fe10d22f8e29d1 to your computer and use it in GitHub Desktop.
Mixing Lit v1 and Lit v2/v3 html and css templates
// lit-transition.js
// Provides some functions/objects that work on both Lit v1 and Lit v2/v3.
// This code is based on this proof-of-concept: https://codepen.io/denilsonsa/pen/dPyWZbY
// How to use this code? Use this:
// import { multicss as css, multihtml as html, multinothing as nothing } from './lit-transition.js';
// Instead of Lit's own css, html and nothing functions/objects.
////////////////////////////////////////////////////////////
import { css as css2, CSSResult as CSSResult2, html as html2 } from 'ing-web/core.js';
/* eslint-disable prefer-rest-params */
// Old-style (Lit v1 and lit-element v2) CSSResult is checked by `instanceof`.
// New-style (Lit v2/v3 and lit-element v4) CSSResult is checked by the presence of '_$cssResult$'.
// We can build a mixed CSSResult object by making it pass the checks from both versions.
// This mixed object works inside `css` from both and new versions.
// Returns a CSS template that is compatible with both Lit v1 and Lit v3.
export function multicss(strings, ...values) {
for (let i = 0; i < values.length; i++) {
// If this value is a new-style instance `_$cssResult$`,
// but not an old-style instance...
if (values[i]._$cssResult$ && !(values[i] instanceof CSSResult2)) {
// Change its prototype to the old-style prototype,
// while keeping the `_$cssResult$` attribute.
Object.setPrototypeOf(values[i], CSSResult2.prototype);
}
}
// Create a new mixed-style object, and return it.
const ret = css2.apply(this, [strings, ...values]);
ret._$cssResult$ = true;
return ret;
}
// `nothing` is a sentinel object which is checked using `===`.
// Since each version has a different object instance representing `nothing`, they will never be equal.
// The lit-html code checks against that sentinel and calls `.clear()`.
// The same code also calls `.clear()` if the value is an iterable.
// Thus, an empty iterable should behave just like `nothing`.
// (Should have the same behavior only in the context of element contents/children;
// the behavior is certainly different when used in attributes and properties.)
export const multinothing = [];
// Returns an HTML template that is compatible with both Lit v1 and Lit v3.
//
// Works for simple HTML templates.
// More complex ones may or may not work, depending on how deep they are, and
// if they have a mix of plain `html` templates from different versions.
export function multihtml() {
const ret = html2.apply(this, arguments);
ret._$litType$ = 1; // 1 for html, 2 for svg, 3 for MathML
return ret;
}
// A similar approach could be implemented for @lion Validators,
// in case someone needs to support multiple @lion/ui versions.
// https://github.com/ing-bank/lion/tree/master/packages/ui/components/form-core/src/validate
//
// The old ValidateMixin.js was checking `v instanceof Validator`,
// but the new code in their master branch checks for `validatorCtor['_$isValidator$']`.
//
// This new check is not yet available in @lion/form-core 0.18.3, but that version is several years old.
// This new check is available in @lion/ui 0.8.5 or later.
//
// https://github.com/ing-bank/lion/commit/9b92fa216eed801f981c24b0708513f571998103
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment