CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lit-element

A simple base class for creating fast, lightweight web components

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

property-system.mddocs/

Property System

The property system provides reactive property management with decorators, type conversion, and change detection for building reactive custom elements. Properties automatically trigger re-renders when changed and can be synchronized with attributes.

Capabilities

Property Decorator

Declares a reactive property that triggers updates when changed.

/**
 * Declares a reactive property that triggers updates when changed
 * @param options Configuration options for the property
 * @returns Property decorator function
 */
function property(options?: PropertyDeclaration): PropertyDecorator;

interface PropertyDeclaration {
  /**
   * Type hint for attribute conversion (String, Number, Boolean, Array, Object)
   */
  type?: TypeHint;

  /**
   * Attribute name to observe, or false to disable attribute observation
   */
  attribute?: boolean | string;

  /**
   * Whether to reflect property value back to attribute
   */
  reflect?: boolean;

  /**
   * Custom converter for attribute/property conversion
   */
  converter?: AttributeConverter;

  /**
   * Whether to skip creating a property accessor
   */
  noAccessor?: boolean;

  /**
   * Function to determine if property has changed
   */
  hasChanged?: HasChanged;
}

Usage Examples:

import { LitElement, html, property } from "lit-element";

class MyElement extends LitElement {
  @property({ type: String })
  name = "World";

  @property({ type: Number, reflect: true })
  count = 0;

  @property({ type: Boolean, attribute: "is-active" })
  isActive = false;

  @property({ type: Array })
  items: string[] = [];

  @property({ 
    type: String,
    hasChanged: (newVal, oldVal) => newVal?.toLowerCase() !== oldVal?.toLowerCase()
  })
  caseSensitive = "";

  render() {
    return html`
      <div>
        <p>Name: ${this.name}</p>
        <p>Count: ${this.count}</p>
        <p>Active: ${this.isActive}</p>
        <p>Items: ${this.items.join(", ")}</p>
      </div>
    `;
  }
}

State Decorator

Declares internal reactive state that doesn't reflect to attributes.

/**
 * Declares internal reactive state that doesn't reflect to attributes
 * @param options Configuration options for the state property
 * @returns Property decorator function
 */
function state(options?: StateDeclaration): PropertyDecorator;

interface StateDeclaration {
  /**
   * Function to determine if state has changed
   */
  hasChanged?: HasChanged;
}

Usage Examples:

import { LitElement, html, property, state } from "lit-element";

class MyElement extends LitElement {
  @property({ type: String })
  title = "";

  @state()
  private _expanded = false;

  @state()
  private _loading = false;

  private _toggle() {
    this._expanded = !this._expanded;
  }

  render() {
    return html`
      <div>
        <h2 @click=${this._toggle}>${this.title}</h2>
        ${this._expanded ? html`
          <div class="content">
            ${this._loading ? html`<p>Loading...</p>` : html`<p>Content here</p>`}
          </div>
        ` : ''}
      </div>
    `;
  }
}

Static Properties

Alternative to decorators for JavaScript or when decorators aren't preferred.

/**
 * Static property declarations for reactive properties
 */
static properties: PropertyDeclarations;

interface PropertyDeclarations {
  [key: string]: PropertyDeclaration;
}

Usage Examples:

import { LitElement, html } from "lit-element";

class MyElement extends LitElement {
  static properties = {
    name: { type: String },
    count: { type: Number, reflect: true },
    items: { type: Array },
    _internal: { state: true }
  };

  constructor() {
    super();
    this.name = "World";
    this.count = 0;
    this.items = [];
    this._internal = false;
  }

  render() {
    return html`<p>Hello, ${this.name}!</p>`;
  }
}

Type Hints

Type hints for automatic attribute conversion.

/**
 * Type hint for property conversion
 */
type TypeHint = 
  | typeof String    // Converts to/from string attributes
  | typeof Number    // Converts to/from numeric attributes  
  | typeof Boolean   // Converts to/from boolean attributes (presence-based)
  | typeof Array     // JSON serialization for complex types
  | typeof Object;   // JSON serialization for complex types

Attribute Converter

Custom conversion between attributes and properties.

/**
 * Interface for custom attribute/property conversion
 */
interface AttributeConverter<Type = unknown, TypeHint = unknown> {
  /**
   * Convert attribute value to property value
   * @param value Attribute value (string or null)
   * @param type Type hint for conversion
   * @returns Converted property value
   */
  fromAttribute?(value: string | null, type?: TypeHint): Type;

  /**
   * Convert property value to attribute value
   * @param value Property value
   * @param type Type hint for conversion  
   * @returns Converted attribute value (string, number, boolean, or null)
   */
  toAttribute?(value: Type, type?: TypeHint): unknown;
}

Usage Examples:

import { LitElement, html, property } from "lit-element";

const dateConverter = {
  fromAttribute: (value: string | null) => {
    return value ? new Date(value) : null;
  },
  toAttribute: (value: Date | null) => {
    return value ? value.toISOString() : null;
  }
};

class MyElement extends LitElement {
  @property({ converter: dateConverter })
  createdAt: Date | null = null;

  render() {
    return html`
      <p>Created: ${this.createdAt?.toLocaleDateString() || 'Not set'}</p>
    `;
  }
}

Has Changed Function

Function to determine if a property value has changed.

/**
 * Function to determine if property has changed
 * @param value New property value
 * @param oldValue Previous property value
 * @returns True if property has changed
 */
interface HasChanged {
  (value: unknown, oldValue: unknown): boolean;
}

/**
 * Default hasChanged implementation using strict inequality
 */
function notEqual(value: unknown, oldValue: unknown): boolean;

Default Converter

Default converter used for standard type conversion.

/**
 * Default attribute converter with support for standard types
 */
const defaultConverter: AttributeConverter;

Usage Examples:

import { LitElement, html, property, notEqual } from "lit-element";

class MyElement extends LitElement {
  @property({ 
    type: String,
    hasChanged: (newVal, oldVal) => {
      // Case-insensitive comparison
      return newVal?.toLowerCase() !== oldVal?.toLowerCase();
    }
  })
  name = "";

  @property({
    type: Number,
    hasChanged: (newVal, oldVal) => {
      // Only update if difference is significant
      return Math.abs(Number(newVal) - Number(oldVal)) > 0.1;
    }
  })
  value = 0;

  render() {
    return html`
      <div>
        <p>Name: ${this.name}</p>
        <p>Value: ${this.value}</p>
      </div>
    `;
  }
}

Property Change Detection

Understanding how property changes are detected and handled.

/**
 * Request an update which will trigger the update lifecycle
 * @param name Property name that changed
 * @param oldValue Previous value of the property
 * @param options Additional options for the update request
 */
requestUpdate(name?: PropertyKey, oldValue?: unknown, options?: RequestUpdateOptions): void;

interface RequestUpdateOptions {
  /**
   * Whether to trigger an update even if hasChanged returns false
   */
  force?: boolean;
}

Usage Examples:

import { LitElement, html } from "lit-element";

class MyElement extends LitElement {
  private _data: any[] = [];

  get data() {
    return this._data;
  }

  set data(value: any[]) {
    const oldValue = this._data;
    this._data = value;
    // Manually request update for array property
    this.requestUpdate('data', oldValue);
  }

  addItem(item: any) {
    this._data.push(item);
    // Request update after mutating array
    this.requestUpdate('data', this._data);
  }

  render() {
    return html`
      <ul>
        ${this.data.map(item => html`<li>${item}</li>`)}
      </ul>
    `;
  }
}

docs

core-element.md

css-styling.md

decorators.md

directives.md

index.md

polyfill-support.md

property-system.md

template-system.md

tile.json