npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@klingen/litworks

v1.3.5

Published

The tooling and utils required to make an application using lit-elements

Downloads

20

Readme

Litworks - Lit element toolkit for making applications

The tooling and utils required to make an application using lit-elements powered by RXJS

This small package contains the following

  • Simple but powerfull router
    • Capable of doing routing, sub-routing, even support auxiliary routing like patterns found in angular
  • Directives and Async controller for connecting LIT-element and RXJS
    • A controller simplifying templating
    • A directive perfect for simple values like numbers and strings
  • RXJS extensions for common operations
  • Simple authentication

Litworks router

This is a really simple and based on regex-patterns. It uses groups to extract parameter names. In it's simplest form you can use one global navigationService or you can have multiple routers. If you are building somehting big and complext, it might make sense to pass the navigation service arround using @lit/context.

  • ✅ Supports lazy loading
  • ✅ Multiple routers
  • ✅ Angular style auxiliary routing
  • ✅ URL parameters
  • ✅ Query param based routing
  • ✅ Subrouting

Get Url parameters

  1. First define a route containing a regex group /\/products\/(?<productId>[0-9]+)$/
  2. Read the parameters using the observable found in the NavigationService
navigationService.routeParams$.subscribe(params => console.log(params));
// { "productId": "42" }

Example

The example below shows the most basic usage of the router

const navigationService = new NavigationService();
navigationService.addRoutes([
 { // This will lazy load a component
   name: "Route one",
   route: /\/one$/,
   action: () => {
     return import("./views/test-view/test-view.component");
   },
 },
 { // This will egarly load a component
   name: "Route two - egarly loaded component",
   route: /\/two$/,
   action: () => TestComponent,
 },
{ // This will lazy load a component
   name: "Route three - egarly loaded component with url params",
   route: /\/products\/(?<productId>[0-9]+)$/,
   action: () => TestComponent,
 },
]);
render() {
 return html`<litworks-router-outlet .navigationService=${navigationService}></litworks-router-outlet>`;
}

Litworks RxJs tools

Litworks comes with some basic tools used to integrate better with RxJs

AsyncController

Use the async-controller when you want to bind values more complex than a string or a number. Basically when handling arrays or objects. It can be used in tho ways, with value or using a render-function.

Using the value directly

import { interval } from "rxjs";

@customElement("test-component")
export class TestComponent extends LitElement {
   // Emits every second
   private interval$ = interval(1000); 
   
   private intervalController = createAsyncController(this, interval$, 0);
   
   render() {
     return html`<p>Current count: ${this.intervalController.value}</p>`;
   }
}

Using the render function This is a very tidy way of making good frontend code. Here we are handling the various states with just a few linse of code

import { interval } from "rxjs";

@customElement("test-component")
export class TestComponent extends LitElement {
   // Emits every second
   private interval$ = interval(1000); 
   
   private intervalController = createAsyncController(this, interval$, 0);
   
   render() {
     return intervalController.render({
       onValue: (value) => html`Yay a value: ${value}`,
       onError: (err) => html`Oh s#!%, ${err}`,
       initial: () => html`TODO: Implement loading spinner`,
       pending: () => html`Loading state`,
       // Add onEmpty and an isEmpty function if you want an empty state
       onEmpty: () => html`Got an empty response`,
       // This function evaluates if a response is empty
       isEmpty: (value) => value === null
     });
   }
}

Async directive

When you have an observable emitting a simple value, like a string or a number, the observe-directive is probably the best way of tracking that single value

@customElement("test-component")
export class TestComponent extends LitElement {
   // Emits every second
   private interval$ = interval(1000);

   render() {
     return html`<p>Current count: ${observe(this.interval$)}</p>`;
   }
}

RxJs extensions

fromKeyEvent

Makes it easiser to track keyEvents using RxJs. It's a thin wrapper arround the fromEvent-operator. It uses the keyup-event to track key-events.

// Listens to window
const key$ = fromKeyEvent(['A', 'B', 'C']);
const key2$ = fromKeyEvent(['A', 'B', 'C'], someHTMLElement);

fromDragEvent

Library exposes a method making a drag and drop observable. Use this function whenever you want to make a simple interactive component.

// This observables emits how far the user has dragged on the X and Y axis.
// It is up to you how you apply this awesome data
const newElementPosition$ = fromDragEvent(someElement);

You can also pass some options.

// This observables emits how far the user has dragged on the X and Y axis.
// It is up to you how you apply this awesome data
const newElementPosition$ = fromDragEvent(someElement, {
  
});

namedMerge

For the usecase when you have multiple observables emitting the same values and you want to distiguish the values.

Pass an object and use the keys as names

namedMerge({
    a: interval(1000),
    b: interval(1100),
    c: interval(1200)
}).subscribe(console.log);
// { name: "a", value: 0 }
// { name: "b", value: 0 }
// { name: "c", value: 0 }
// { name: "a", value: 1 }
// { name: "b", value: 1 }
// { name: "c", value: 1 }

Pass an array of objects

namedMerge([
{name: "a", observable: interval(1000)}
{name: "b", observable: interval(1001)}
{name: "c", observable: interval(1002)}
]).subscribe(console.log);
// { name: "a", value: 0 }
// { name: "b", value: 0 }
// { name: "c", value: 0 }
// { name: "a", value: 1 }
// { name: "b", value: 1 }
// { name: "c", value: 1 }

Authentication

In most projects you end up using some sort of OIDC based flow. Having a stable source of user-details and access-token is essential when making a solid frontend application. Library includes a simple Authentication Service.

const authenticationService = new AuthenticationService({
  authority: 'authority',
  client_id: 'client_id',
  redirect_uri: 'something',
  scope: 'some scopes'
});

authenticationService.token$.subscribe(console.log);
authenticationService.user$.subscribe(console.log);
authenticationService.loginFlow();

// Will log out token and user when login is complete

HttpClient

In most projects you want to fetch resources with authentication. The httpClient provided in this library is very basic and is supposed to cover most use-cases. If it does not fit your needs. Copy the source code and hack it or extend it.

Client is just a thin wrapper arround fromFetch. Client just provides a authorization-header and some serialization.

const authenticationService = new AuthenticationService({
  authority: 'authority',
  client_id: 'client_id',
  redirect_uri: 'something',
  scope: 'some scopes'
});

var httpClient = new HttpClient(authenticationService.token$);

httpClient.fetchJson<MyResponse>('https://some-url-to-your-awesome-service.com').subscribe(console.log);

httpClient.fetchBlobImage('https://some-url-to-your-awesome-service.com').subscribe(console.log);

If a token-observable is not provided, the client still works.

Want to simplify boilerplate code?

Check out this project