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

alcarritoo-icons-library

v1.0.0

Published

Starter project to build an SVG icon library

Downloads

3

Readme

alcarritoo-icon-library

Consuming your icon library

Once published to npm, your icon library is ready to be consumed. There are various ways to consume the icon library.

Vanilla JS

To consum the icon library in ES6 you can import icons from your library, create an SVG element and add the icon data to it.

// Import the icon from the icon library
import {myIconSmilingFace} from 'my-icon-lib';

// Query the element that you want to append the icon to
const conatiner = document.getElementById('.container');

// Create a new svg element and apply the icon data to it
function buildSVGElement(icon) {
    const div = document.createElement('DIV');
    div.innerHTML = icon.data;
    return (
        div.querySelector('svg') ||
        this.document.createElementNS('http://www.w3.org/2000/svg', 'path')
    );
}

// Append the icon to the container
container.appendChild(buildSVGElement(icon);

Typescript

The TypeScript usage is very similar to the JavaScript usage. The only difference is that you have additional type safety.

// Import the icon from the icon library
import {myIconSmilingFace, MyIcon} from 'my-icon-lib';

// Query the element that you want to append the icon to
const conatiner = document.getElementById('.container');

// Create a new svg element and apply the icon data to it
function buildSVGElement(icon: MyIcon): SVGElement {
    const div = document.createElement('DIV');
    div.innerHTML = icon.data;
    return (
        div.querySelector('svg') ||
        this.document.createElementNS('http://www.w3.org/2000/svg', 'path')
    );
}

// Append the icon to the container
container.appendChild(buildSVGElement(icon));

Framework usage

The usage in frameworks can be a bit more sophisticated than the usage in plain JavaScript or TypeScript. In frameworks we often work with additional concepts like components and more sophisticated builds.

Angular

In Angular we want to provide a reusable component for the icons. A reusable component that accepts a name as an Input property and displays the desired icon. Furthermore, we want to guarantee that tree shaking is supported. If the icon library contains 300 icons but only one of them is used, only one should end up in the resulting bundle. Furthermore it should also support code splitting and lazy loading in a way that the icon only ends up in the chunk it is used.

To achieve these things we implement a IconRegistry.

import {Injectable} from '@angular/core';
import {MyIcon} from './my-icon-lib';

@Injectable({
    providedIn: 'root'
})
export class MyIconsRegistry {

    private registry = new Map<string, string>();

    public registerIcons(icons: MyIcon[]): void {
        icons.forEach((icon: MyIcon) => this.registry.set(icon.name, icon.data));
    }

    public getIcon(iconName: string): string | undefined {
        if (!this.registry.has(iconName)) {
            console.warn(
              `We could not find the Icon with the name ${iconName}, did you add it to the Icon registry?`
            );
        }
        return this.registry.get(iconName);
    }
}

The icon registry holds all the icons in a Map. Next we build the my-icon.component.ts that will use the registry to display an icon.

import {
  ChangeDetectionStrategy, Component, ElementRef, HostBinding, Inject, Input, Optional, ViewEncapsulation
} from '@angular/core';
import {MyIconsRegistry} from './my-icons-registry.service';
import {DOCUMENT} from '@angular/common';

@Component({
    selector: 'my-icon',
    template: `
        <ng-content></ng-content>
    `,
    styles: [':host::ng-deep svg{width: 50px; height: 50px}'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class MyIconComponent {
    private svgIcon: SVGElement;

    @Input()
    set name(iconName: string) {
        if (this.svgIcon) {
            this.element.nativeElement.removeChild(this.svgIcon);
        }
        const svgData = this.myIconsRegistry.getIcon(iconName);
        this.svgIcon = this.svgElementFromString(svgData);
        this.element.nativeElement.appendChild(this.svgIcon);
    }

    constructor(private element: ElementRef, private myIconsRegistry: MyIconsRegistry,
                @Optional() @Inject(DOCUMENT) private document: any) {
    }

    private svgElementFromString(svgContent: string): SVGElement {
        const div = this.document.createElement('DIV');
        div.innerHTML = svgContent;
        return div.querySelector('svg') || this.document.createElementNS('http://www.w3.org/2000/svg', 'path');
    }
}

At this point we are ready to consum the my-icon component. We first register the desired icon in the lazy loaded module and then consume it in a component.

import { NgModule, Component } from '@angular/core';
import {myIconSmilingFace} from 'my-icon-lib';

import {MyIconsRegistry} from './my-icons-registry';
import {MyIconModule} from './my-icon.module.ts';

@Component({
  selector: 'my-feature',
  template: `<my-icon name="smiling_face"></my-icon>`
})
export class MyFeatureComponent {}

@NgModule({
  declarations: [MyFeatureComponent],
  imports: [MyIconModule]
})
export class MyFeatureModule { 

	constructor(private myIconsRegistry: MyIconsRegistry) {
		myIconsRegistry.registerIcons([myIconSmilingFace]);
	}

}

Custom build

For more information check out the svg-to-ts docs.