Skip to content

serikshaikamalov/lit-components

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reusable lit components

WYSIWYG HTML Editor

Demo: WYSIWYG Editor

HTML editor is a tool that allows users to create and edit web content in a way that shows how the final product will appear. image

Key Features of WYSIWYG:

  • Text Formatting: Bold, italic, underline, font size
  • Links: Ability to add and edit hyperlinks.
  • Lists: Ordered (numbered) and unordered (bullet) lists.

Table component

Demo: Reusable table component

This reusable table component is simple and can be expanded with additional features like sorting, filtering, and pagination. The component is designed to be flexible, allowing it to be used in various parts of an application with different data sets and columns.

  • Desktop view image

  • Mobile/Tablet view

The component requires two properties:

  • columnConfig. This is representaion of your entity.
  • data. List of data that should be displayed in table

Usage:

import { LitElement, html, css } from "lit";

export class MovieList extends LitElement {
  static get properties() {
    return {
      tableConfig: { type: Object },
      data: { type: Array },
    };
  }

  constructor() {
    super();

    this.tableConfig = [
      {
        key: "name",
        label: "Name",
        formatter: (v) => v && v.slice(0, 10),
      },
      {
        key: "publishedYear",
        label: "published",
      },
      {
        key: "image",
        label: "Image",
        render: (item) => html`
          <div style="width: 50px; height: 50px; display: flex;">
            <img src=${item?.image}></media-component>
          </div>
        `,
      },
    ];

    this.data = [
      {
        name: "Rush hour 3",
        publishedYear: 2007,
        image:
          "https://e7.pngegg.com/pngimages/544/802/png-clipart-rush-hour-film-television-rush-tshirt-television-thumbnail.png",
      },
      {
        name: "Vanguard",
        publishedYear: 2021,
        image: "https://m.media-amazon.com/images/I/91415BMkZEL._AC_SY679_.jpg",
      },
    ];
  }

  connectedCallback() {
    super.connectedCallback();
  }

  render() {
    return html` <app-table .columnConfig=${this.tableConfig} .data=${this.data}></app-table> `;
  }
}
customElements.define("movie-list", MovieList);

In this example:

  • tableConfig defines the columns with optional formatter and render functions.

  • data contains the rows of the table.

Dropdown

Simple form builder

Pagination

Utils

Snippets

How to deal with dark/light mode

EventTarget

Demo: BasketStorage

When to use it?

  • A way of communication between components
  • Source of the truth / Singleton
  • As a global storage

Usage

/**
 * This singleton EventEmitter can be used throughout your application to handle custom events.
 */
export class BasketStorage extends EventTarget {
  items = [];
  static instance;

  static getInstance() {
    if (!BasketStorage.instance) {
      BasketStorage.instance = new BasketStorage();
    }
    return BasketStorage.instance;
  }

  addItem(item) {
    this.items = [...this.items, item];
    this.dispatchEvent(new CustomEvent("updated", { detail: { item } }));
  }
  getItems() {
    return this.items;
  }
}

const basketStorage = BasketStorage.getInstance();
export default basketStorage;

with lit component

import { html, css, LitElement } from "https://cdn.jsdelivr.net/npm/lit@2/+esm";
import basketStorage from "./basketStorage.js";

export class Basket extends LitElement {
  static get properties() {
    return {
      items: { type: Array },
    };
  }

  constructor() {
    super();
  }

  connectedCallback() {
    super.connectedCallback();
    basketStorage.addEventListener("updated", (i) => {
      this.items = basketStorage.getItems();
    });
  }

  submit(e) {
    e.preventDefault();

    const searchNode = this.renderRoot.querySelector("#search");
    if (searchNode) {
      const v = searchNode.value;
      basketStorage.addItem(v);
    }
    searchNode.value = "";
  }

  render() {
    return html`
      <form @submit=${this.submit}>
        <div>
          <input type="text" id="search" />
          <button type="submit">Submit</button>
        </div>
        <div>
          ${this.items
            ? html`${this.items.map((i) => {
                return html`<div>${i}</div>`;
              })}`
            : html`<h2>No items</h2>`}
        </div>
      </form>
    `;
  }
}
customElements.define("app-basket", Basket);

Get form values in one shot

submit(e){
    e.preventDefault()
    const formData = new FormData(e.target)
    const formProps = Object.fromEntries(formData)
    // {a: 1, b: 2}
}