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

crystalline-element

v3.0.1

Published

A collection of Lit enhancements inspired by Stimulus and written in Ruby2JS.

Downloads

44

Readme

❄️ Crystallized

This package has moved to @crystallized/controllers. Please visit https://github.com/whitefusionhq/crystallized for details.


lit npm ruby2js bundlephobia bundlephobia dependency count bundlephobia tree shaking

Lit: Simple. Fast. Web Components.

Crystallized: a collection of Lit 2 enhancements, starting with controllers inspired by Stimulus. Crystallized includes:

  • DeclarativeActionsController - lets you add action attributes to elements in the light DOM as a way of providing declarative event handlers.

  • TargetsController - lets you easily query child nodes in the light DOM using either selectors or explicit attribute-based identifies. Docs coming soon!

Crystallized uses Ruby 3 and Ruby2JS to compile its source code to modern ES6+ JavaScript (example). Crystallized can be used with any modern JS bundler as well as directly in buildless HTML using script type="module".

Lit along with Crystallized works great as a spice on top of server-rendered markup originating from backend frameworks like Rails or static sites generators like Bridgetown—providing features not normally found in web component libraries that assume they're only concerned with client-rendered markup and event handling.

You can build an entire suite of reactive frontend components just with Lit/Crystallized, along with a general strategy to enhance your site with a variety of emerging web components and component libraries (Shoelace for example).

NOTE: this package is currently in the process of transitioning to @crystallized/controllers. All of the below information is deprecated. Please come back shortly for updated instructions!


Installing

yarn add crystalline-element

or

npm i crystalline-element

Using DeclarativeActionsController

Demo on CodePen

It's very simple to add this controller to any Lit 2 component. First let's set up a new test component:

import { LitElement, html } from "lit"
import { DeclarativeActionsController } from "crystalline-element/controllers"

class TestElement extends LitElement {
  actions = new DeclarativeActionsController(this)

  clickMe() {
    this.shadowRoot.querySelector("test-msg").textContent = "clicked!"
  }

  render() {
    return html`
      <slot></slot>
      <test-msg></test-msg>
    `
  }
}
customElements.define("test-element", TestElement)

You'll notice that currently nothing actually calls the clickMe method. Don't worry! We'll declaratively handle that in our regular HTML template:

<test-element>
  <article>
    <button test-element-action="clickMe">Button</button>
  </article>
</test-element>

The tag name of the component (text-element) plus action sets up the event handler via an action attribute, with the method name clickMe being the value of the attribute. This is shorthand for click->clickMe. The controller defaults to click if no event type is specified (with a few exceptions, such as submit for forms and input or change for various form controls).

Because DeclarativeActionsController uses a MutationObserver to keep an eye on HTML in the light DOM, at any time you can update the markup dynamically and actions will work as expected.

In addition, actions don't pass component boundaries. In other words, if you were to add a test-element inside of another test-element, the action within the nested test-element would only call the method for that nested component.

Note: actions are only detected within light DOM and do not traverse shadow trees of child components.

Using CrystallineElement

Demo on CodePen

CrystallineElement is very easy to use. Simply import it, along with helpers from Lit directly, and you can start writing new web components.

More documentation coming soon…

Ruby Example

import [ CrystallineElement, crystallize ], from: "https://cdn.skypack.dev/crystalline-element"
import [ html, css ], from: "https://cdn.skypack.dev/lit"

class MyComponent < CrystallineElement
  property :name, String

  stylesheet css <<~CSS
    p {
      font-weight: bold;
    }
  CSS
 
  define "my-component" # always add below properties, stylesheets, etc.

  def render()
    html "<p>Hello World! Nice to meet you, #{self.name}</p>"
  end
end

class LightDomOnlyComponent < CrystallineElement
  define "light-dom-only", shadow_dom: false

  # ...
end

localVariable = "functional"

crystallize("functional-component", 
  properties: {
    greeting: { type: String }
  }
) do |comp|
  html <<~HTML
    <p>#{comp.greeting}, you can write "#{localVariable}" components with a handy shorthand!</p>
  HTML
end

JavaScript Example

import { CrystallineElement, crystallize } from "https://cdn.skypack.dev/crystalline-element"
import { html, css } from "https://cdn.skypack.dev/lit"

class MyComponent extends CrystallineElement {
  static get properties() {
    return {
      name: { type: String }
    }
  }

  static get styles() {
    return css`
      p {
        font-weight: bold;
      }
    `
  }

  render() {
    return html`<p>Hello World! Nice to meet you, ${this.name}</p>`
  }
}

MyComponent.define("my-component")

class LightDomOnlyComponent extends CrystallineElement {
  // ...
}

LightDomComponent.define("light-dom-only", { shadowDom: false })

const localVariable = "functional"

crystallize("functional-component", {
  properties: {
    greeting: { type: String }
  }
}, comp => html`
  <p>${comp.greeting}, you can write "${localVariable}" components with a handy shorthand!</p>
`)

Building Source with Ruby2JS

Requires Ruby 3.0. A Ruby version manager like rbenv is recommended. Run bundle install to set up the Ruby gems.

Run yarn build (which gets run by the test and release script automatically) to transpile the Ruby src files to the JS dist folder.

Testing

Crystalline uses the Modern Web Test Runner and helpers from Open WC for its test suite.

Run yarn test to run the test suite.

Contributing

  1. Fork it (https://github.com/whitefusionhq/crystallized/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

MIT