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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@grimoire-intel/yetzirah-angular

v1.0.0

Published

Angular wrappers for Yetzirah Web Components

Readme

@grimoire-intel/yetzirah-angular

Angular wrappers for Yetzirah Web Components - bringing Material Design behavior patterns to Angular 16+.

Installation

npm install @grimoire-intel/yetzirah-angular @grimoire-intel/yetzirah
# or
pnpm add @grimoire-intel/yetzirah-angular @grimoire-intel/yetzirah
# or
yarn add @grimoire-intel/yetzirah-angular @grimoire-intel/yetzirah

Usage

Option 1: Standalone Components (Angular 16+, Recommended)

For apps using Angular's standalone component API:

import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@grimoire-intel/yetzirah'; // Import Web Components

@Component({
  selector: 'app-root',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <ytz-button>Click me</ytz-button>
    <ytz-dialog>
      <h2>Dialog Title</h2>
      <p>Dialog content goes here</p>
    </ytz-dialog>
  `
})
export class AppComponent {}

Alternatively, use the provided helper:

import { Component } from '@angular/core';
import { provideYetzirah } from '@grimoire-intel/yetzirah-angular';
import '@grimoire-intel/yetzirah';

@Component({
  selector: 'app-root',
  standalone: true,
  schemas: [provideYetzirah()],
  template: `<ytz-button>Click me</ytz-button>`
})
export class AppComponent {}

Option 2: Traditional NgModule

For apps still using NgModule:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { YetzirahModule } from '@grimoire-intel/yetzirah-angular';
import '@grimoire-intel/yetzirah'; // Import Web Components

@NgModule({
  imports: [
    BrowserModule,
    YetzirahModule
  ],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})
export class AppModule {}

Loading Web Components

You must ensure @grimoire-intel/yetzirah is loaded before using the components. There are several ways to do this:

Method 1: Import in main.ts (Recommended)

// main.ts
import '@grimoire-intel/yetzirah';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent);

Method 2: CDN in index.html

<!-- index.html -->
<script type="module" src="https://unpkg.com/@grimoire-intel/yetzirah/dist/yetzirah.js"></script>

Method 3: Selective imports

// Import only the components you need for smaller bundle size
import '@grimoire-intel/yetzirah/button';
import '@grimoire-intel/yetzirah/dialog';
import '@grimoire-intel/yetzirah/tabs';

Available Components

All Yetzirah Web Components are available in Angular templates with dedicated standalone components.

Tier 1 Standalone Components

| Component | Selector | Import | |-----------|----------|--------| | Button | ytz-button | ButtonComponent | | Dialog | ytz-dialog | DialogComponent | | Drawer | ytz-drawer | DrawerComponent | | Tabs | ytz-tabs, ytz-tab-list, ytz-tab, ytz-tab-panel | TabsComponent, TabListComponent, TabComponent, TabPanelComponent | | Menu | ytz-menu, ytz-menu-item, ytz-menu-trigger | MenuComponent, MenuItemComponent, MenuTriggerComponent | | Accordion | ytz-accordion, ytz-accordion-item | AccordionComponent, AccordionItemComponent | | Disclosure | ytz-disclosure | DisclosureComponent | | Tooltip | ytz-tooltip | TooltipComponent | | Popover | ytz-popover | PopoverComponent | | Autocomplete | ytz-autocomplete, ytz-autocomplete-option | AutocompleteComponent, AutocompleteOptionComponent | | Listbox | ytz-listbox, ytz-listbox-option | ListboxComponent, ListboxOptionComponent | | Select | ytz-select, ytz-select-option | SelectComponent, SelectOptionComponent |

Tier 2 Standalone Components

| Component | Selector | Forms Support | |-----------|----------|---------------| | Toggle | ytz-toggle | ControlValueAccessor, [(ngModel)], formControlName | | Chip | ytz-chip | - | | IconButton | ytz-icon-button | - | | Slider | ytz-slider | ControlValueAccessor, [(ngModel)], formControlName | | DataGrid | ytz-datagrid, ytz-datagrid-column | - | | ThemeToggle | ytz-theme-toggle | - |

Tier 1 Component API

Dialog

import { Component } from '@angular/core';
import { DialogComponent, ButtonComponent } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [DialogComponent, ButtonComponent],
  template: `
    <ytz-button (click)="isOpen = true">Open Dialog</ytz-button>

    <ytz-dialog [open]="isOpen" (close)="isOpen = false">
      <div class="pa4 bg-white br3">
        <h2>Dialog Title</h2>
        <p>Dialog content goes here.</p>
        <ytz-button (click)="isOpen = false">Close</ytz-button>
      </div>
    </ytz-dialog>
  `
})
export class MyComponent {
  isOpen = false;
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | open | boolean | false | Controls dialog visibility | | static | boolean | false | Prevent backdrop dismiss |

| Output | Type | Description | |--------|------|-------------| | close | EventEmitter<void> | Emitted when dialog closes |

Select

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { SelectComponent, SelectOptionComponent } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [FormsModule, SelectComponent, SelectOptionComponent],
  template: `
    <ytz-select [(ngModel)]="selected" placeholder="Choose an option...">
      <ytz-select-option value="1">Option 1</ytz-select-option>
      <ytz-select-option value="2">Option 2</ytz-select-option>
      <ytz-select-option value="3">Option 3</ytz-select-option>
    </ytz-select>
  `
})
export class MyComponent {
  selected = '';
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | ngModel | string \| string[] | '' | Two-way bound value | | multiple | boolean | false | Enable multi-select | | disabled | boolean | false | Disable the select | | placeholder | string | - | Placeholder text |

Tabs

import { Component } from '@angular/core';
import {
  TabsComponent,
  TabListComponent,
  TabComponent,
  TabPanelComponent
} from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [TabsComponent, TabListComponent, TabComponent, TabPanelComponent],
  template: `
    <ytz-tabs>
      <ytz-tab-list>
        <ytz-tab>Tab 1</ytz-tab>
        <ytz-tab>Tab 2</ytz-tab>
        <ytz-tab>Tab 3</ytz-tab>
      </ytz-tab-list>
      <ytz-tab-panel>Content for Tab 1</ytz-tab-panel>
      <ytz-tab-panel>Content for Tab 2</ytz-tab-panel>
      <ytz-tab-panel>Content for Tab 3</ytz-tab-panel>
    </ytz-tabs>
  `
})
export class MyComponent {}

Menu

import { Component } from '@angular/core';
import {
  MenuComponent,
  MenuTriggerComponent,
  MenuItemComponent,
  ButtonComponent
} from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [MenuComponent, MenuTriggerComponent, MenuItemComponent, ButtonComponent],
  template: `
    <ytz-menu>
      <ytz-menu-trigger>
        <ytz-button>Open Menu</ytz-button>
      </ytz-menu-trigger>
      <ytz-menu-item (click)="handleEdit()">Edit</ytz-menu-item>
      <ytz-menu-item (click)="handleDelete()">Delete</ytz-menu-item>
    </ytz-menu>
  `
})
export class MyComponent {
  handleEdit() { console.log('Edit'); }
  handleDelete() { console.log('Delete'); }
}

Autocomplete

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AutocompleteComponent, AutocompleteOptionComponent } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [FormsModule, AutocompleteComponent, AutocompleteOptionComponent],
  template: `
    <ytz-autocomplete [(ngModel)]="value" placeholder="Search fruits...">
      @for (option of options; track option) {
        <ytz-autocomplete-option [value]="option">{{ option }}</ytz-autocomplete-option>
      }
    </ytz-autocomplete>
  `
})
export class MyComponent {
  value = '';
  options = ['Apple', 'Banana', 'Cherry', 'Date'];
}

Tier 2 Component API

Toggle

Implements ControlValueAccessor for Angular forms integration.

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Toggle } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [FormsModule, Toggle],
  template: `
    <ytz-toggle [(ngModel)]="enabled" [disabled]="false" (change)="onChange($event)"></ytz-toggle>
  `
})
export class MyComponent {
  enabled = false;
  onChange(event: Event) { console.log(event); }
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | ngModel | boolean | false | Two-way bound checked state | | disabled | boolean | false | Disables the toggle |

| Output | Type | Description | |--------|------|-------------| | ngModelChange | boolean | Emits when checked state changes | | change | Event | Native change event |

Chip

import { Component } from '@angular/core';
import { Chip } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [Chip],
  template: `
    <ytz-chip [deletable]="true" (delete)="onDelete()">Tag Name</ytz-chip>
  `
})
export class MyComponent {
  onDelete() { console.log('deleted'); }
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | deletable | boolean | false | Shows delete button | | disabled | boolean | false | Disables the chip |

| Output | Type | Description | |--------|------|-------------| | delete | EventEmitter<void> | Emits when delete button clicked |

IconButton

import { Component } from '@angular/core';
import { IconButton } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [IconButton],
  template: `
    <ytz-icon-button ariaLabel="Close" tooltip="Close dialog" (click)="onClick()">
      <svg><!-- icon --></svg>
    </ytz-icon-button>
  `
})
export class MyComponent {
  onClick() { console.log('clicked'); }
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | ariaLabel | string | required | Accessible label (maps to aria-label) | | tooltip | string | - | Tooltip text | | disabled | boolean | false | Disables the button |

Slider

Implements ControlValueAccessor for Angular forms integration.

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Slider } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [FormsModule, Slider],
  template: `
    <ytz-slider [(ngModel)]="volume" [min]="0" [max]="100" [step]="1"></ytz-slider>
  `
})
export class MyComponent {
  volume = 50;
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | ngModel | number | 0 | Two-way bound value | | min | number | 0 | Minimum value | | max | number | 100 | Maximum value | | step | number | 1 | Step increment | | disabled | boolean | false | Disables the slider |

| Output | Type | Description | |--------|------|-------------| | ngModelChange | number | Emits on value change | | input | Event | Live value change during drag | | change | Event | Committed value change on release |

DataGrid

import { Component } from '@angular/core';
import { DataGrid, DataGridColumn } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [DataGrid, DataGridColumn],
  template: `
    <ytz-datagrid [data]="data" [rowHeight]="40" (sort)="onSort($event)" (rowSelect)="onSelect($event)">
      <ytz-datagrid-column field="id" header="ID" [width]="80"></ytz-datagrid-column>
      <ytz-datagrid-column field="name" header="Name" [sortable]="true"></ytz-datagrid-column>
      <ytz-datagrid-column field="email" header="Email"></ytz-datagrid-column>
    </ytz-datagrid>
  `
})
export class MyComponent {
  data = [
    { id: 1, name: 'Alice', email: '[email protected]' },
    { id: 2, name: 'Bob', email: '[email protected]' }
  ];
  onSort(event: any) { console.log(event); }
  onSelect(event: any) { console.log(event); }
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | data | any[] | [] | Row data array | | columns | Column[] | [] | Column definitions (alternative to children) | | rowHeight | number | 40 | Row height in pixels |

| Output | Type | Description | |--------|------|-------------| | sort | { column, direction } | Sort requested | | rowSelect | { row, index } | Row selected | | rowActivate | { row, index } | Row double-clicked |

ThemeToggle

import { Component } from '@angular/core';
import { ThemeToggle } from '@grimoire-intel/yetzirah-angular';

@Component({
  standalone: true,
  imports: [ThemeToggle],
  template: `
    <ytz-theme-toggle [storageKey]="'my-app-theme'" (themeChange)="onThemeChange($event)"></ytz-theme-toggle>
  `
})
export class MyComponent {
  onThemeChange(event: CustomEvent) { console.log(event.detail); }
}

| Input | Type | Default | Description | |-------|------|---------|-------------| | storageKey | string | 'theme' | localStorage key | | noPersist | boolean | false | Disable persistence |

| Output | Type | Description | |--------|------|-------------| | themeChange | { theme, isDark } | Theme changed |

TypeScript Support

This package includes TypeScript definitions for all components. However, since these are Web Components, you may need to add custom element type declarations for strict type checking:

// src/custom-elements.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    'ytz-button': any;
    'ytz-dialog': any;
    // ... add other components as needed
  }
}

Two-Way Binding

Angular's two-way binding works with Web Component properties and events:

@Component({
  template: `
    <ytz-toggle
      [checked]="isEnabled"
      (change)="onToggleChange($event)">
    </ytz-toggle>
  `
})
export class MyComponent {
  isEnabled = false;

  onToggleChange(event: Event) {
    this.isEnabled = (event.target as any).checked;
  }
}

Styling

Yetzirah components are unstyled by default. Import the optional CSS if desired:

// main.ts or styles.css
import '@grimoire-intel/yetzirah/button.css';
import '@grimoire-intel/yetzirah/dialog.css';
import '@grimoire-intel/yetzirah/disclosure.css';

Or use the dark theme:

import '@grimoire-intel/yetzirah/dark.css';

Testing

# Run all tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run with coverage
pnpm test:coverage

Tests use Jest with jest-preset-angular for Angular-specific testing utilities.

Requirements

  • Angular 16 or higher
  • Modern browsers with Web Components support (all evergreen browsers)

How It Works

These wrappers integrate Yetzirah web components with Angular's patterns:

  • ControlValueAccessor: Form controls work with ngModel and reactive forms
  • CUSTOM_ELEMENTS_SCHEMA: Allows ytz-* elements in templates
  • Event binding: Component events emit as Angular EventEmitters

See @grimoire-intel/yetzirah for full component documentation.

License

MIT

Repository

https://github.com/grimoire-intelligence/yetzirah