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

@cmmn/ui

v2.2.3

Published

Simple but reach components based on CustomElements, uhtml and @cmmn/cell2.

Downloads

19

Readme

UI library

Simple but reach components based on CustomElements, uhtml and @cmmn/cell2.

component can be generated by comman cmmn gen my-comp ./components

it will generate 3 files: my-comp.component.ts, my-comp.template.ts and my-comp.style.less

Component example:


@Injectable(true) // enabled DI (1)
@component({
    name: 'my-comp', // name of custom element, so use it with <my-comp /> in html 
    template: (html, state, events) => html` 
    <div onclick=${events.onClick()}>${state.Version}</div>
  `, // template is just a template literal (2)
    style, // will be injected in head, no scoping (3)  
})
export class MyComponent extends HtmlComponent<IState, IEvents> {
    // injecting some services  
    constructor(private api: ApiService) {
        super();

        this.useAction(this.someAction, () => [
            this.Version,
        ], ActionSubscribeType.OnFirstRender);
    }

    // properties are mappend from attributes (2)
    @property()
    protected version!: number;

    someAction([version]) {
        // it will be called every time the version changes after first render
    }

    @action(() => version)
    otherAction(version) {
        // it will be called every time the version changes after component will be connected
    }

    @effect()
    someEffect() {
        // it will be called after first render    
    }


    @effect(() => this.version)
    otherEffect() {
        // it will be called after renders, if version have changed    
    }

    connectedCallback() {
        super.connectedCallback(); // important, should be called
        // it will be unsubscribed in disconnectedCallback
        this.onDispose = this.on('render', console.log);
    }

    // render will be after it changed in animationFrame callback
    // frequent renders will be combined in one animationFrame
    // it will not render if:
    // * error have been thrown
    // * State returns undefined
    // * State returns smth comparable to previous result (compare(newValue, oldValue) == true)
    // you can try-catch errors here and return other error state
    get State() {
        try {
            return {
                Version: this.version
            }
        } catch (e) {
            return {Version: 'error'}
        }
    }

    // handle errors in source = effects|aciton|state|template
    onError(error: Error, source) {
        if (source == 'effect' || source == 'action')
            return;
        // by default it will warn in console
        super.onError(error, source);
    }
}

  1. About DI you can read at @cmmn/core
  2. About templates you can read at uhtml, but
    1. html... renders inside current component
    2. html()... will creates new elements every time
    3. html(key) will creates new elements every time key will change
    4. html(obj, key) will creates new elements every time key or obj will change
    5. html has cache which you can see in html.cache
  3. Style should be just a string, your bundler should hanlde it, as @cmmn/tools for example
  4. Properties are mapped from html attributes of your custom element.
    1. Naming will change from camelCase to snake-case in dom. (myProp in js <-> my-prop in dom)
    2. It supports most of js values like objects, functions, numbers, strings...
    3. It compares value equality by Fn.compare from @cmmn/core, so it can call .equals() of value, f.e.
  5. Effects are functions that will be called after render have been, like in React.
    1. You may provide a filtering function: only if result have changed, effect will be called
  6. Actions are functions that will be called if their dependencies will change
    1. It can be subscribed at onConnected: when element attached to dom
    2. Or atFirstRender: when it was rendered first
  7. You can use this.element for direct access to dom-element
  8. You can use this.element.parentElement.component for access to parent component, if parentElement is root of it.
  9. You can access injected content via this.Children. It is stored in connectedCallback.
  10. HtmlComponent is EventEmitter of render | connected | dispose