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

@nodeflair/react-chat

v0.0.11

Published

Presentational chat components for ReactJS

Downloads

2

Readme

React Chat

Build Status

React Chat is presently in alpha and is not meant to be a viable substitute to delicate native chat frameworks.

React Chat currently does not support pagination of messages or rooms, hence might have performance issues when loading huge volume of chat data. Handles for pagination such as scroll pagination will be added soon.

Intro

React Chat is an extensible set of presentational chat components for mobile-first ReactJS web applications. It facilitates simple messaging interactions on-the-go.

React Chat is inspired by the designs at GiftedChat, Slack, WhatsApp and Telegram.

Besides this README, you may find documentation of the design and behaviours of components in Storybook.

Examples and demos will be provided through Storybook and the Examples page in the future. This is a work in progress.

Getting Started

React Chat requires at least React 16.3.0 as a peer dependency.

To install using npm:

npm install @hliejun/react-chat

To install using yarn:

yarn add @hliejun/react-chat

To opt-in to alpha versions, please explicitly state the version. Check on the latest version here.

Usage

React Chat comprises of:

  • ChatList

  • ChatRoom

ChatList

ChatList is a component used for interacting with a list of chat rooms or message groups. As a presentational component, it exposes the handles for various tasks such as displaying chat rooms, refreshing the view, filtering the list and more.

For instance, you can invoke ChatList with the following:

import { ChatList } from '@hliejun/react-chat';

class MyContainer extends React.Component {

  // ...

  render = () => {
    //...
    const { rooms } = this.state;
    //...
    return (
      <ChatList
        onItem={this.segueToChatRoom}
        rooms={this.parseRooms(rooms)}
        title='Chats'
      />
    );
  };

  // ...

  parseRooms = (rooms) => {
    // Fetch and parse data into shape of room objects
  };

  segueToChatRoom = (id) => {
    // Navigate to chat room of id when room is selected
  };

}

The following table indicates the props that ChatList accepts.

Name | Type | Description --- | --- | --- className | string | Style classes passed down from container component hideAvatar | bool | Flag to opt out from showing Avatar in ListItem hideChevron | bool | Flag to opt out from showing chevron indicator as affordance to segueing hideTitleBar | bool | Flag to opt out from showing the TitleBar isLoading | bool | Flag to display loading animations while the ChatList is not readily populated layout | see AppContext | Styling enumeration to match ChatRoom layout liveSearch | bool | Flag to indicate the intended search behaviour menuActions | see Actions | Action handlers and metadata to populate chat ListItem menu onAvatar | func | Handler for interaction with the Avatar in a ListItem onInfo | func | Handler for interaction with the identity Avatar in TitleBar onItem | func | Handler for selecting a ListItem of a specific room onMenu | func | Handler for prompting the ListItem menu of a specific room onRefresh | func | Handler for initiating a fetch or reload to repopulate the ChatList onResult | func | Handler for selecting a search ListItem in the search results pane onSearch | func | Handler for search or filter logic to fetch or reload searchResults Placeholder | React element | Component to fill the body when rooms is empty rooms | see Rooms | Collection of objects specifying the metadata of a room searchHint | string | Placeholder for empty search field searchPlaceholder | React element | Placeholder for empty search results body searchResults | see Search | Collection of objects describing the outcome of onSearch selectedId | string | Unique identifier of the list item that is currently active sizing | see AppContext | Device and sizing enumeration for layout responsiveness subtitle | string | Subtitle to display on TitleBar theme | see AppContext | Theme enumeration for styling constituent components title | string | Title to display on TitleBar user | see Users | Object containing metadata of a user or a user profile

ChatRoom

ChatRoom is a component used for interacting with a chat group, room, conversation, etc. Regardless of the room size, it offers generic handles for various messaging tasks such as typing, sending, searching, deleting, copying and more.

You can use ChatRoom this way:

import { ChatRoom } from '@hliejun/react-chat';

class MyContainer extends React.Component {

  // ...

  render = () => {
    //...
    const { input, messages, room, userId, users } = this.state;
    const { id, name } = room;
    //...
    return (
      <ChatRoom
        inputValue={input}
        messages={this.parseMessages(messages)}
        onInput={this.parseInput}
        onSend={this.sendMessage}
        roomId={id}
        roomName={name}
        userId={userId}
        users={users}
      />
    );
  };

  // ...

  parseMessages = (messages) => {
    // Fetch and parse data into shape of message objects
  };

  parseInput = (nextInput) => {
    // Input control to parse HTML string into desirable values
    // ...
    // When done parsing, reload ChatRoom with new input state
    // Pure components will not reload if unaffected by input
    this.setState({
      input: parsedInput
    });
  };

  sendMessage = (input) => {
    // Call API to submit message
  };

}

The following table indicates the props that ChatRoom accepts.

Name | Type | Description --- | --- | --- attachOptions | see Media | Action handlers for media attachments className | string | Style classes passed down from container component hideAvatar | bool | Flag to opt out from showing Avatar in Message item inputData | see Media | Object describing attached media due for posting inputHint | string | Placeholder for input field inputValue | string | HTML-formatted string for rendering into input field layout | see AppContext | Styling enumeration describing layout of messages liveSearch | bool | Flag to indicate the intended search behaviour menuActions | see Actions | Action handlers and metadata to populate chat Message menu messages | see Messages | Collection of objects representing Message content onAttach | func | Handler for attaching media to input onAvatar | func | Handler for interaction with the Avatar in a Message onContent | func | Handler for selecting a message Content onInfo | func | Handler for interaction with the identity Avatar in TitleBar onInput | func | Handler for intercepting and updating input field value onMenu | func | Handler for prompting the content Menu of a specific message onRefresh | func | Handler for initiating a fetch or reload to repopulate the Message list onResult | func | Handler for selecting a search ListItem in the search results pane onReturn | func | Handler for interacting with the return button to perform a segue onSearch | func | Handler for search or filter logic to fetch or reload searchResults onSend | func | Handler for submitting input value roomAvatar | string | Link to room avatar image roomId | string | Unique identifier of the room for actions contextual to the room roomName | string | Name or title of the chat room searchHint | string | Placeholder for empty search field searchPlaceholder | React element | Placeholder for empty search results body searchResults | see Search | Collection of objects describing the outcome of onSearch sizing | see AppContext | Device and sizing enumeration for layout responsiveness subtitle | string | Subtitle to display on TitleBar theme | see AppContext | Theme enumeration for styling constituent components userId | string | Unique identifier of the current user users | see Users | Indexed collection of objects containing metadata of all users involved in the chat room

Actions

(WIP) Here are the PropTypes declaration for menu actions for the respective components.


{/* ListItem Menu Actions */}

menuActions: PropTypes.arrayOf(PropTypes.shape({
  action: PropTypes.func.isRequired,
  icon: PropTypes.string,
  label: PropTypes.string.isRequired,
  type: PropTypes.oneOf([
    'archive',
    'delete',
    'info',
    'pin',
    'star',
    'unread'
  ]).isRequired
}))

{/* Message Menu Actions */}

menuActions: PropTypes.arrayOf(PropTypes.shape({
  action: PropTypes.func.isRequired,
  icon: PropTypes.string,
  label: PropTypes.string.isRequired,
  type: PropTypes.oneOf([
    'copy',
    'delete',
    'forward',
    'info',
    'pin',
    'reply'
  ]).isRequired
})),

AppContext

(WIP) Here are the PropTypes declaration for app context options.


{/* Layout */}

layout: PropTypes.oneOf([
  'aligned',
  'staggered'
])

{/* Sizing */}

sizing: PropTypes.oneOf([
  'desktop',
  'mobile',
  'tablet'
])

{/* Theme */}

theme: PropTypes.oneOf([
  'dark',
  'light'
])

Messages

(WIP) Here are the PropTypes declaration for messages.


{/* Messages */}

messages: PropTypes.arrayOf(PropTypes.shape({
  data: PropTypes.shape({
    coordinates: PropTypes.shape({
      lat: PropTypes.string,
      lng: PropTypes.string
    }),
    galleryId: PropTypes.string,
    markdown: PropTypes.string,
    metadata: PropTypes.object,
    source: PropTypes.string.isRequired,
    type: PropTypes.oneOf([
      'audio',
      'file',
      'gif',
      'image',
      'link',
      'location',
      'markdown',
      'pdf',
      'video'
    ]).isRequired
  }),
  eventContent: PropTypes.element,
  eventName: PropTypes.string,
  isDelivered: PropTypes.bool,
  isLoading: PropTypes.bool,
  isRead: PropTypes.bool,
  messageId: PropTypes.string.isRequired,
  senderId: PropTypes.string,
  text: PropTypes.string,
  timeStamp: PropTypes.string.isRequired,
  type: PropTypes.oneOf([
    'event',
    'media',
    'system',
    'text'
  ]).isRequired
})).isRequired

Media

(WIP) Here are the PropTypes declaration for media-related objects.


{/* Attach Options */}

attachOptions: PropTypes.arrayOf(PropTypes.shape({
  action: PropTypes.func.isRequired,
  icon: PropTypes.string,
  label: PropTypes.string.isRequired,
  type: PropTypes.oneOf([
    'audio',
    'file',
    'gif',
    'image',
    'link',
    'location',
    'markdown',
    'pdf',
    'video'
  ]).isRequired
}))

{/* Input Data */}

inputData: PropTypes.shape({
  coordinates: PropTypes.shape({
    lat: PropTypes.string,
    lng: PropTypes.string
  }),
  galleryId: PropTypes.string,
  markdown: PropTypes.string,
  metadata: PropTypes.object,
  source: PropTypes.string.isRequired,
  type: PropTypes.oneOf([
    'audio',
    'file',
    'gif',
    'image',
    'link',
    'location',
    'markdown',
    'pdf',
    'video'
  ]).isRequired
})

Rooms

(WIP) Here are the PropTypes declaration for rooms.


{/* Rooms */}

rooms: PropTypes.arrayOf(PropTypes.shape({
  avatar: PropTypes.string,
  description: PropTypes.string,
  id: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  status: PropTypes.oneOf([
    'archive',
    'pin',
    'star',
    'new'
  ]),
  subtitle: PropTypes.string,
  timeStamp: PropTypes.string
})).isRequired

Search

(WIP) Here are the PropTypes declaration for search results.


{/* Search Results */}

PropTypes.arrayOf(PropTypes.shape({
  avatar: PropTypes.string,
  description: PropTypes.string,
  id: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  timeStamp: PropTypes.string
}))

Users

(WIP) Here are the PropTypes declaration for user(s).


{/* User */}

user: PropTypes.shape({
  avatar: PropTypes.string,
  description: PropTypes.string,
  email: PropTypes.string,
  id: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  phone: PropTypes.string,
  website: PropTypes.string
})

{/* Users */}

users: PropTypes.objectOf(PropTypes.shape({
  avatar: PropTypes.string,
  description: PropTypes.string,
  email: PropTypes.string,
  id: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  phone: PropTypes.string,
  website: PropTypes.string
})).isRequired

Style Classes

(WIP) Formats and variants off CSS classes.

Development

(WIP) Code Design, Linters, Storybook, RollUp, AppContext, Classnames. DOMPurify.

TODOs

Summary of upcoming TODOs:

Features

  • [ ] Animations
  • [ ] Children buttons in TitleBar
  • [ ] Dividers
  • [ ] Expose child components for use
  • [ ] Media preview
  • [ ] Message markdown
  • [ ] Message replies
  • [ ] Refresh
  • [ ] Scroll pagination
  • [ ] Themes and abstract colors usage

Performance

  • [ ] Recycle views
  • [ ] Reduce bundle size with UglifyJS
  • [ ] Split bundles for selective import
  • [ ] Switch to PureComponent(s)
  • [ ] Trim style classes

Code Quality

  • [ ] Add Jest tests
  • [ ] Refactor all stories
  • [ ] Switch to SCSS for stories

Documentation

  • [ ] Add example screenshots
  • [ ] Complete README
  • [ ] Complete Storybook
  • [ ] Examples with ChatKit

Maintenance

  • [ ] Setup issues

Credits and Licenses

This project is licensed under the MIT License. See LICENSE for copyright credits to the respective sources. The following people and resources have helped this project greatly in one way or another:

Throttling without Lodash Author: Jhey Tompkins Web: Throttling and Debouncing in Javascript

Default to Polymer SVG Icons Author: PolymerElements and David Francisco Repo (polymerelements): https://github.com/PolymerElements/iron-icons Repo (dmfrancisco): https://github.com/dmfrancisco/react-icons

Web URL Regex Author: Diego Perini Gist: https://gist.github.com/dperini/729294

SASS Mixins Authors: Richard Torres and Engage Interactive Repo (engageinteractive): https://github.com/engageinteractive/core Gist (richardtorres314): https://gist.github.com/richardtorres314/26b18e12958ba418bb37993fdcbfc1bd

SASS Material Colors Author: minusfive Repo: https://github.com/minusfive/sass-material-colors

Support

(WIP) Issues and contact.