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

@trixwell/ngx-parl

v8.0.0

Published

Highly customizable Angular Material chat component

Readme

NgxParl Component Documentation

Overview

chat_view.png

NgxParl is a backend-agnostic Angular 21 chat UI. It renders the messenger, composer, attachments, scroll, and mobile gestures. The host application owns HTTP, STOMP, sessions, and business rules.

Library class: NgxParlComponent. Selector: ngx-parl.

GitHub Repository: Trixwell/parl

Installation

npm install @trixwell/ngx-parl

Required peer dependencies

npm install @angular/material @angular/cdk @ngneat/transloco ngx-infinite-scroll

@ionic/angular and @ionic/core are optional peers. Ionic is not imported by the library. For a full-page Ionic chat, use [layout]="'fill'", disable ion-content scrolling, and pass [keyboardInset] from the host.

Providers

import {provideNgxParl, NgxParlComponent} from '@trixwell/ngx-parl';

export const appConfig: ApplicationConfig = {
    providers: [provideHttpClient(), provideNgxParl()]
};

provideNgxParl() registers Transloco (en / uk) and locales. provideHttpClient() is required because the library injects HttpClient.

Assets Setup

"assets": [
  {
    "glob": "**/*",
    "input": "node_modules/@trixwell/ngx-parl/src/assets",
    "output": "assets/ngx-parl"
  }
]

Assets are available at assets/ngx-parl/....

Public API

Import from @trixwell/ngx-parl:

  • NgxParlComponent, provideNgxParl
  • ChatMessage, ChatMessageDTO, MessageActionEvent, MessageType
  • FlowTheme, ParlLayout
  • ParlQuickAction, ParlQuickActionsResolver, ParlQuickActionsWhen, defaultParlQuickActionsResolver

There are no @Output() events. Bind model() two-way ([(messageList)], [(messageAction)], [(loadHistory)], …).

Inputs and models

| Name | Type | Default | Description | | --- | --- | --- | --- | | layout | 'dialog' \| 'fill' | 'dialog' | Dialog keeps 800×600. Fill stretches to the host. | | header | boolean | true | Title bar with hide/close. | | theme | FlowTheme | primary | FlowTheme.PRIMARY or FlowTheme.SECONDARY. | | language | 'en' \| 'uk' | 'en' | Transloco language. | | messageList | ChatMessage[] | [] | Canonical list. Two-way. | | messageUpdate | ChatMessage | | Incoming upsert. Scrolls only when the user is at the bottom. | | messageAction | MessageActionEvent | | Pulse: send / edit / delete, then null. | | loadHistory | boolean | false | Pulse when older messages are needed. | | hasMoreHistory | boolean | true | Stop history pulses when the host has no older pages. | | incomingUser | string | '' | Header name. | | transportType | string | '' | Header transport label. | | transportTypeIcon | string | '' | Header transport icon. | | logoChat | string | '' | Outgoing default avatar and (desktop) list header icon. Empty uses the anonymous icon. | | incomingAvatar | string | '' | Incoming default avatar when a message has no avatar. | | mobileMode | boolean | false | Mobile layout, long-press action sheet, native textarea composer, fullscreen image preview. | | keyboardInset | number | 0 | Keyboard overlap in CSS pixels. Host measures; Parl applies padding. | | autoFocus | boolean | true | Focus the composer on init. Set false on mobile so the IME does not open by itself. | | scrollToBottomOnKeyboard | boolean | true | Scroll to latest when keyboardInset becomes greater than 0. | | quickActionsResolver | ParlQuickActionsResolver | | Custom mapping. Default uses message.actions. | | quickActionsWhen | ParlQuickActionsWhen | ParlQuickActionsWhen.ALWAYS | Gate for default and custom resolvers. | | quickActionsAutoSend | boolean | true | Send action.value on click. | | quickActionClick | ParlQuickActionClickEvent | | Click pulse. Two-way. | | hideHandler / closeHandler | () => unknown | | Header actions. |

Host methods

  • scrollToBottom() — jump to the latest message.
  • confirmPending(tempId, dto) — replace an optimistic message after the backend ACK.
  • rejectPending(tempId) — remove an optimistic message on send failure.

Optimistic sends use negative temp ids so they cannot collide with backend ids.

Scrolling

Inner .chat__flow owns scroll. loadHistory is only a request for older pages; it does not scroll.

this.scrollToBottomTrigger.update(value => value + 1);

Ionic fill-page recipe

<ion-content [scrollY]="false">
  <ngx-parl [layout]="'fill'"
            [mobileMode]="true"
            [autoFocus]="false"
            [keyboardInset]="keyboardInset()"
            [incomingAvatar]="peerAvatarUrl()"
            [(messageList)]="messageList"
            [(messageAction)]="messageAction"
            [(loadHistory)]="loadHistory"
            [hasMoreHistory]="hasMoreHistory()">
  </ngx-parl>
</ion-content>

Keep Capacitor / native keyboard measurement in the application. Pass the overlap into [keyboardInset].

Template

<ngx-parl [header]="true"
          [layout]="'dialog'"
          [theme]="theme()"
          [(messageList)]="messageList"
          [(messageUpdate)]="messageUpdate"
          [(messageAction)]="messageAction"
          [(loadHistory)]="loadHistory"
          [hasMoreHistory]="hasMoreHistory()"
          [quickActionsWhen]="quickActionsWhen"
          [quickActionsAutoSend]="true"
          [mobileMode]="mobileMode()"
          [(quickActionClick)]="quickActionClick"
          [transportType]="transportType()"
          [transportTypeIcon]="transportTypeIcon()"
          [logoChat]="logoChat()">
</ngx-parl>

Quick actions

Outgoing message.actions become buttons. Set quickActionsWhen to ParlQuickActionsWhen.MOBILE to hide them on desktop without a custom resolver.

quickActionsAutoSend defaults to true and sends once per click.

Mobile mode

[mobileMode]="true":

  • Hides outgoing avatars and the sender name under the bubble.
  • Uses long-press on the bubble + bottom action sheet (edit / delete). No kebab button.
  • Incoming bubbles are white with a light violet border; outgoing bubbles use violet with timestamps under the bubble.
  • Pill composer with attach on the left and send on the right.
  • Native iOS and Android emoji from the system keyboard (Apple Color Emoji / Noto Color Emoji fallbacks).
  • On-screen send button is always available; Enter still sends, Shift+Enter inserts a newline.