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 🙏

© 2025 – Pkg Stats / Ryan Hefner

crie

v0.1.12

Published

Generate React JSX intrinsic element typings from Angular Elements libraries — supports both legacy @Input/@Output and new signal APIs.

Downloads

34

Readme

crie

Generate strongly typed React JSX intrinsic element definitions from Angular Elements libraries. crie scans your Angular component sources, collects the available inputs and outputs (including the new input(), output(), and model() signal helpers), and emits .d.ts typings that let TypeScript-aware React tooling understand your custom elements. That means authoring JSX with the same confidence you have when consuming first-party React components.

Why "crie"? It stands for Convert React Intrinsic Elements. Bring the ergonomics of JSX authoring to Angular Elements projects without manually writing declaration files or duplicating prop contracts in two frameworks.

Table of contents

Highlights

  • Supports modern Angular signals – understands input(), output(), and model() usage alongside classic @Input()/@Output() decorators.
  • 🧭 Smart type resolution – re-exports referenced types into generated namespaces so JSX property types stay accurate.
  • ⚙️ Configurable discoverability – point crie at any Angular workspace layout with glob include/exclude patterns.
  • 💡 React-friendly output – generates JSX.IntrinsicElements definitions plus optional HTML attribute mixing for easy consumption in React.
  • 🧱 CLI-first workflow – ship typings from CI/CD, package scripts, or local dev with a single command.

Requirements

  • Node.js 18.18 or newer (matches the engine requirement declared in package.json).
  • TypeScript project for your Angular Elements library. The CLI reads your tsconfig.json to understand source files and module resolution.

Installation

crie can be installed globally or used through npx. For most projects, adding it as a dev dependency keeps everything versioned with your workspace.

# Local (recommended)
npm install --save-dev crie
# or
pnpm add -D crie
# or
yarn add --dev crie

# Global install (optional)
npm install --global crie

Quick start

  1. Install the package (see above).

  2. Create a crie config (optional – defaults cover many setups). See Configuration for details.

  3. Build your Angular components so TypeScript metadata is up to date. If you are using Angular's standalone components or a multi-project workspace, make sure the referenced tsconfig matches the compiled output you ship.

  4. Generate typings:

    npx crie react-types

    Use --config <path> if your config lives outside the current directory.

  5. Verify the output – open the emitted .d.ts file and spot-check a few components to ensure their inputs/outputs look correct.

  6. Ship the generated file – usually under dist/elements/alo-kit/global.d.ts by default. Commit it or publish it with your package.

How it works

crie walks your TypeScript project using ts-morph, reading Angular @Component metadata to find selectors that look like custom elements (kebab-case). For every component:

  • Input sources:
    • Classic @Input() decorators on fields/getters/setters.
    • Signal-based input()/model() factory calls.
  • Output sources:
    • Classic @Output() decorators.
    • Signal-based output() factories.
    • model() helpers create both an input and a corresponding on<Name>Change event.

crie resolves the TypeScript types for these members. When a type comes from another module, it records the declaration and re-exports it in a generated namespace (AloTypes$<hash>). Finally, it writes a .d.ts file that augments React.JSX.IntrinsicElements with your custom tags, merging:

  • Optional React HTML attributes (configurable).
  • Strongly typed props for inputs.
  • Typed CustomEvent handlers for outputs (onFoo by convention).
  • The standard children prop.

Configuration

Configuration is fully optional. Without any file crie assumes:

  • root: the current working directory
  • tsconfig: tsconfig.json
  • include: ['src/**/*.ts']
  • exclude: unit test files, declaration files, and build output
  • outDir: dist/elements/alo-kit
  • outFile: global.d.ts
  • react.addReactHtmlAttributes: true
  • react.emitWrappers: false (reserved for future use)
  • react.wrapperDir: dist/react-wrappers

If a value sounds unfamiliar, jump to the options table or the annotated example config for a deeper explanation.

Config file locations

crie uses cosmiconfig under the hood. It searches upward from the provided --config directory (default .) for:

  • crie.config.json
  • crie.config.ts
  • crie.config.mjs
  • crie.config.cjs
  • package.json (crie key)

Options

| Option | Type | Default | Description | | ------ | ---- | ------- | ----------- | | root | string | process.cwd() | Base directory for resolving paths. Useful when your config lives in a monorepo root but you need to target a package subdirectory. | | tsconfig | string | "tsconfig.json" | Path (relative to root) to the TypeScript configuration that describes your Angular project. | | include | string[] | ["src/**/*.ts"] | Glob patterns (relative to root) to scan for Angular components. Use this to limit analysis to specific libraries. | | exclude | string[] | See defaults above | Glob patterns to skip files (tests, generated output, etc.). | | tagPrefix | string \| undefined | undefined | If provided, only selectors starting with this prefix are considered. Helpful when a library exports both elements and components. | | outDir | string | "dist/elements/alo-kit" | Directory where the generated declaration file is written. | | outFile | string | "global.d.ts" | File name for the generated declaration file. | | widenPrimitivesToString | boolean | false | When true, primitive inputs are widened to string (handy if your elements are used declaratively in HTML where attributes are string-valued). | | react.addReactHtmlAttributes | boolean | true | When true, each intrinsic element merges with React.HTMLAttributes<HTMLElement> so common props like className and style are available. Set to false if you want strictly custom inputs/outputs. | | react.emitWrappers | boolean | false | Reserved for future wrapper generation. Currently unused by the CLI but accepted to avoid breaking config when the feature lands. | | react.wrapperDir | string | "dist/react-wrappers" | Destination for future wrapper files. |

Annotated example config

The snippet below demonstrates every commonly used option inside crie.config.ts. Feel free to convert it to JSON/JS depending on your tooling — cosmiconfig accepts them all.

import { defineConfig } from "crie/config"; // If you prefer, export a plain object instead.

export default defineConfig({
  // All paths below are resolved from this directory.
  root: __dirname,

  // Point at the TypeScript program that contains your Angular Elements.
  tsconfig: "tsconfig.lib.json",

  // Only scan the Angular library that actually exposes custom elements.
  include: ["projects/storefront/src/**/*.ts"],

  // Skip spec files, Storybook stories, or any generated output directories.
  exclude: ["**/*.spec.ts", "**/*.stories.tsx", "dist/**"],

  // Only emit React typings for selectors that start with "my-app-".
  tagPrefix: "my-app-",

  // Control where the generated declaration file ends up.
  outDir: "dist/elements",
  outFile: "global.d.ts",

  // Shape how props and events surface inside React.
  widenPrimitivesToString: false,
  react: {
    addReactHtmlAttributes: true,
    emitWrappers: false,
    wrapperDir: "dist/react-wrappers"
  }
});

Key takeaways:

  • root gives you monorepo flexibility — point the config at the package folder even if the CLI runs from the repo root.
  • include/exclude are powerful filters. Because crie uses fast-glob under the hood, patterns like projects/**/src/**/*.ts are supported.
  • React-specific options are grouped under react to keep the surface area small and future-proof. Set addReactHtmlAttributes to false if you want to avoid mixing className, style, etc. into your custom elements.
  • widenPrimitivesToString comes in handy when your consumers mostly use HTML (where attributes are string-valued) instead of JSX.

Example configurations

{
  "root": "packages/my-elements",
  "tsconfig": "tsconfig.lib.json",
  "include": ["src/**/*.ts"],
  "outDir": "dist/typings",
  "outFile": "elements.d.ts"
}
import { defineConfig } from "crie/config"; // hypothetical helper, use plain object if not available

export default {
  root: __dirname,
  tsconfig: "tsconfig.lib.json",
  include: ["projects/storefront/src/**/*.ts"],
  tagPrefix: "my-app-",
  react: {
    addReactHtmlAttributes: true
  }
};
{
  "name": "my-elements",
  "version": "1.0.0",
  "crie": {
    "outDir": "dist/elements",
    "widenPrimitivesToString": true
  }
}

CLI reference

crie react-types

Scan your Angular project and emit React JSX intrinsic element typings.

Usage: crie react-types [options]

Options:
  --config <path>  path to crie.config.* directory (default: .)
  -h, --help       display help for command

The command prints the resolved config, processes your components, and writes the declaration file. If no qualifying components are found, it exits with status code 1.

Exit codes

  • 0 – Success.
  • 1 – No components matched or an error occurred.

Generated output

The resulting declaration file (default dist/elements/alo-kit/global.d.ts) looks similar to:

/* Auto-generated by crie. Do not edit manually. */

declare namespace AloTypes$1a2b3c4d {
  interface ProductCardInput {
    /* ... */
  }
}

export {};
declare global {
  namespace React {
    namespace JSX {
      interface IntrinsicElements {
        'my-product-card':
          React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>
          & {
              sku?: string;
              quantity?: number;
          }
          & {
              onAddToCart?: (e: CustomEvent<ProductPayload>) => void;
          }
          & { children?: React.ReactNode };
      }
    }
  }
}

Each component tag maps to an intersection type composed of:

  1. Optional React HTML attributes (configurable).
  2. A type literal for inputs (@Input, input(), etc.).
  3. A type literal for outputs exposed as on<EventName> handlers returning CustomEvent.
  4. children?: React.ReactNode.

Recipes

Publishing typings with your package

  1. Add a build step before publishing:

    {
      "scripts": {
        "prepublishOnly": "npm run build && crie react-types"
      }
    }
  2. Ensure dist (or your configured directory) is included in the files array or .npmignore.

  3. Publish as usual – the generated global.d.ts will appear on npm thanks to the entry in package.json#files.

Using the declarations in a React app

  1. Install your Angular Elements package.

  2. Import the generated declaration file once in your app (or reference it via types in package.json). For global augmentations you can simply rely on TypeScript's automatic inclusion if the file lives inside node_modules/<pkg>/dist/....

  3. Start writing JSX with IntelliSense:

    export const Example = () => (
      <my-product-card
        sku="SKU-42"
        quantity={2}
        onAddToCart={(e) => console.log(e.detail)}
      />
    );

TypeScript and editors now know the valid props and event payloads for your custom elements.

FAQ

Development

To work on crie itself:

npm install
npm run build         # or npm run dev for watch mode
npm test              # powered by Vitest

Before publishing, npm run release bumps the patch version and publishes to npm.

License

MIT © Mahdi Zarei (skyBlueDev)