Twind Configuration not working with LitElement - javascript

I can't seem to get theme working with LitElement. I can set the other props of setup no problem, but the theme doesn't get recognized by Twind. It's also worth mentioning that I get no error when compiling. Anyone have a quick solution?
import {LitElement, html} from 'lit';
import {setup, warn, create, cssomSheet} from 'twind';
setup({
mode: warn,
theme: {
colors: {
purple: '#2013',
},
},
});
const sheet = cssomSheet({target: new CSSStyleSheet()});
const {tw} = create({sheet});
export class MyApp extends LitElement {
static styles = [sheet.target];
static get properties() {
return {
name: {type: String},
};
}
constructor() {
super();
this.name = 'World';
}
render() {
return html` <h1 class="${tw`text(3xl purple)`}">${this.name}!</h1> `;
}
}
window.customElements.define('my-app', MyApp);

Probably, the problem is the shadow-dom.
If you can use Twind, you can try to render to light-dom, instead shadow-dom.
To use light-dom add in your web-component class this method:
createRenderRoot() {
return this;
}
In other hand, I don't sure it works without Lit...

Related

Debugiing Lit Element

I wanted to debug lit decorators in chrom inspect. I am using webpack plugin.
I have followed steps https://lit.dev/docs/tools/development/#development-and-production-builds and enabled the dev mode. Still I am getting minimized file version in chrom inspect, source code is not hitting. Please help on this.
`
import {LitElement, html} from 'lit';
import {customElement, property, queryAssignedNodes} from 'lit/decorators.js';
#customElement("my-element")
class MyElement extends LitElement {
#queryAssignedNodes({slot: 'list'})
listItems!: Array<HTMLElement>;
#property({type: String})
name = 'World';
#property({ type: Number })
count = 0;
#property({attribute: false})
article = {
title: 'My Nifty Article',
text: 'Some witty text.',
};
headerTemplate() {
console.log(this.renderRoot);
let shadowRoot = this.renderRoot;
console.log(shadowRoot.querySelector('slot[name="list"]'));
return html`<header>${this.article.title}</header>`;
}
articleTemplate() {
return html`<article>${this.article.text}</article>`;
}
footerTemplate() {
return html`<footer>Your footer here.</footer>`;
}
_onClick() {
this.count++;
const nodes = [...this.listItems];
console.log(nodes);
}
foo() {
return html` <h1>Hello, ${this.name}!</h1>
<button id = "1" onclick="${this._onClick}">
Click Count: ${this.count}
</button>
<slot name="list"></slot>`;
}
render() {
return html`
${this.headerTemplate()}
${this.articleTemplate()}
${this.footerTemplate()}
${this.foo()}
`;
}
}
`
Note: I am trying to debug #queryAssignedNodes decorator.
I am getting minimized file version in chrom inspect, source code is not hitting.

Lit reactive controllers fail to requestUpdate in nested components

I want to create a basic state management using Lit reactive controllers.
The purpose is to share property values accross the application.
The issue occurs when a controller is attached to a view and to a component nested in the view. When value inside controller changes, the value in the view gets updated, but not in the nested component.
Example:
state.js contains the store logic. A view access the store to create a value and show state value. Nested components also show state value.
state.js
export class StateController {
static get properties() {
return {
state: { type: Object },
host: { type: Object }
}
}
constructor(host) {
// Store a reference to the host
this.host = host;
this.state = {};
// Register for lifecycle updates
host.addController(this);
}
_setStoreValue(property, val) {
this.state[property] = val;
this.host.requestUpdate();
}
}
component.js
import { LitElement, html } from 'lit';
import { StateController } from '../state.js';
export class TestComponent extends LitElement {
static get properties() {
return {
stateCtrl: { type: Object },
state: { type: Object },
};
}
constructor() {
super();
this.stateCtrl = new StateController(this);
this.state = this.stateCtrl.state
}
render() {
return html` Value in component: ${this.state?.test} `;
}
}
customElements.define('test-component', TestComponent);
view.js
import { LitElement, html } from 'lit';
import { StateController } from '../state.js';
import './test-component.js';
export class MonTodo extends LitElement {
static get properties() {
return {
stateCtrl: { type: Object },
state: { type: Object },
};
}
constructor() {
super();
this.stateCtrl = new StateController(this);
this.state=this.stateCtrl.state
}
render() {
return html`
<button #click=${() => this.setValueTest()}>Set value to 3</button>
Value in view: ${this.state?.test}
<h3> Component 1</h3>
<test-component></test-component>
<h3> Component 2</h3>
<test-component></test-component>
`;
}
setValueTest() {
this.stateCtrl._setStoreValue("test", 3)
}
}
customElements.define('mon-todo', MonTodo);
A button click in view.js updates this.state.test in view.js but not in component.js
Since you create a new StateController in both MonTodo and TestComponent, they are two different instances of the StateController which only have their specific component as host.
So the StateController in MonTodo only has MonTodo as a host and only updates that and not TestComponent.
You would need to share one controller with both components and call requestUpdate on both.

Can a lit-element track a variable outside its scope

In my lit-element I'm rendering something based on an outside variable. How can I know to update when that variable changes?
import { LitElement, html } from 'lit-element';
import './element01.js';
class Layout extends LitElement {
createRenderRoot(){ return this; }
static get properties() {
return {
settings: { Object }
};
}
constructor() {
super();
}
render() {
return html`
${(settings.foo === 'bar')? html`<my-element01 />` : null}
`;
}
}
customElements.define('my-layout', Layout);
The settings object is being modified outside, how can this element know to update? I'm not using any other framework.
The index.html file should always have a
<my-app></my-app>
Within the my-app element, you will be able to use all the features of litElement such as
class MyApp extends LitElement {
static get properties() {
return {
prop: {type: Object},
};
}
render() {
return html`
<my-element .prop="${this.prop}"</my-element>
<my-server .prop="${this.prop}"</my-server>
<button #onClick='${(e) => this.prop += 1}' >change the settings value</button>
`;
}
}
Here one example I tried to illustrate. settings property changed outside of litElement and effected in litElement.
demo
index.html
...
<my-layout></my-layout>
<br>
<button onClick="_buttonClicked()" >change the settings value</button>
<script>
document.querySelector('my-layout').settings={foo:"bar"};
function _buttonClicked (e) {
document.querySelector('my-layout').settings = {foo:"baz"};
}
</script>
my-layout :
import { LitElement, html } from 'lit-element';
//import './element01.js';
class Layout extends LitElement {
createRenderRoot(){ return this; }
static get properties() {
return {
settings: { Object }
};
}
constructor() {
super();
}
render() {
return html`
${this.settings.foo === 'bar'? html`<span> element01 will be rendered</span>` : null}
`;
}
}
customElements.define('my-layout', Layout)
I made some syntax corrections

Using javascript class based style as Vue Component

I'm pretty much new to the Vue Eco-System, buh I'd like to achieve something as below:
**VisitListTemplateFile.vue**
<template>...</template>
<script>
import VisitListView from '../../views/VisitListView'
import '../../assets/vendor/datatables/app.datatables';
import Body from '../partials/Body';
export default new VisitListView("VisitListView", Body);
</script>
<style scoped>
#import "../../assets/vendor/datatables/datatables.min.css";
</style>
**VisitListViewFile.js**
import {BaseView} from '../../core/BaseView';
export default class VisitListView extends BaseView {
constructor(name, ...components) {
super(name, ...components);
}
mounted() {
console.log("TEST");
}
}
It works kind of, but I realize that the callback functions e.g mounted isn't called, although there is a workaround to make it work. I was wondering if there is a cleaner way to do it.
----UPDATE----
I did this and it works, so my question is, does this pose any problem?
BaseView.js
export class BaseView {
constructor(name, ...components) {
this.name = name;
this.components = {};
components.forEach(comp => {
this.components[comp.name] = comp;
});
return {
components: this.components,
mounted: this.mounted
}
}
mounted(){
super.mounted();
}
}

Override/extend static properties on ES7 classes in React.js

ES7 introduces the concept of static property and method definitions. Along with an ES7-capable transpiler, these can be used in React to specify validators and defaults for props, like so:
export default class ComponentOne extends React.Component {
static propTypes = {
foo: React.PropTypes.string
}
static defaultProps = {
foo: 'bar'
}
// ...
}
This is super handy, but gets tricky when subclasses come into play. For example, say the following module is added to the same codebase as ComponentOne above:
export default class ComponentTwo extends ComponentOne {
static propTypes = {
baz: React.PropTypes.number
}
static defaultProps = {
baz: 42
}
// ...
}
I'd like ComponentTwo to "inherit" the property validators and defaults of its superclass, ComponentOne. Instead, propTypes and defaultProps on ComponentTwo shadow those on ComponentOne, and React tosses out those defined on ComponentOne.
Since super is a reference to the current class's prototype, and static is supposed to reference values hung directly off the prototype, I thought this might work:
import _ from 'lodash';
export default class ComponentTwo extends ComponentOne {
static propTypes = _.merge(super.propTypes, {
baz: React.PropTypes.number
});
}
However, this generates an error, presumably from Babel: Parsing error: 'super' outside of function or class.
This works, but is not very portable:
export default class ComponentTwo extends ComponentOne {
static propTypes = Object.assign({
baz: React.PropTypes.number
}, ComponentOne.propTypes);
}
Are there any other ways to do this more cleanly/reusably?
I stumbled upon this question, and it's been almost 3 years, but who know, someone might need it. (And it's still relevant)
Given that when you extend a class it automatically inherits of its parent class, you would not need to overwrite the static propTypes property.
Given a parent class:
class Parent {
static propTypes = {
parentProp: PropTypes.string
}
}
If you don't want to add other propTypes/defaultProps, you can simply:
class Children extends Parent {
// Do not declare the propTypes, it will extends by itself.
}
console.log(Children.propTypes); // Will output an object with parentProp in it
If you want to explicitly tell that you extends Parent propTypes, or add new propTypes:
class Children extends Parent {
static propTypes = {
...Parent.propTypes, // Yes, you can spread static properties like everything else
childProp: Proptypes.number,
}
}
Small note, for this to work properly with Babel, you might need to include the transform-es2015-classes babel plugin in your plugins or preset. My .babelrc:
"presets": [
["env", {
"include": ["transform-es2015-classes"]
}],
"stage-0",
"react"
],
Hope this helps!
Curiously enough, using super works for static methods. I'd think it should work for static properties too. To me, then, it feels more natural to use the super class name directly:
export default class ComponentTwo extends ComponentOne {
static propTypes = _.merge({}, ComponentOne.propTypes, {
baz: React.PropTypes.number
});
}
But, to use super, one workaround I can think of is using a static method to initialize the property, which unfortunately would have to be called manually:
class ComponentTwo extends ComponentOne {
static _init() {
this.propTypes = _.merge({}, super.propTypes, {
baz: React.PropTypes.number
});
}
}
ComponentTwo._init();

Categories