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

@stackchat/proactive-messaging

v1.0.9

Published

Message popups for the stackchat web-messenger

Downloads

132

Readme

@stackchat/proactive-messaging

A utility library for @stackchat/web-messenger to display proactive messages to a user above the Stackchat Web Messenger button or tab.

Table of Contents

Introduction

This library allows you to handle the creation, display and manipulation of messages that are proactively displayed to the user. A user can also interact with these messages eliminating the need of guesswork from the user.

Proactive messages can be triggered automatically during an ongoing conversation in the Stackchat Web Messenger or can be manually triggered as the need arises.

Each proactive message looks like this(when default styles are used)

or like this with actions:

Note: Proactive messages are only displayed if and only if the messenger widget is not open. If it is open, then all the proactive messages are silently ignored.

Usage

Note: This library works in conjuction with and requires @stackchat/web-messenger so as to be able to display proactive messages.

Script

If your project does not use a bundler or package manager, you can use our cdn hosted assets:

<!--
Copy and paste the following script right below
the 'script' tag for Stackchat Web Messenger
-->
<script async type="text/javascript" src="https://assets.au.stackchat.com/sdk/proactive-messaging/1.0.4/index.js"></script>

Optionally, if you would to include our default styles, also add the following:

<link type="text/css" src="https://assets.au.stackchat.com/sdk/proactive-messaging/1.0.4/main.css">

Now you have access to Stackchat Web Messenger(exposed as window.stackchat) and ProactiveMessaging(exposed as window.ProactiveMessaging)

<script>
	let messageStack;

	// add an event listener to initialise Proactive
	// Messaging once Stackchat Web Messenger has
	// finished initialising
	window.stackchat.on('ready', initialiseProactiveMessaging)

	window.stackchat.init({
		appId: "YOUR_APP_ID_HERE"
	})

	function initialiseProactiveMessaging() {
		// This step is required before calling
		// messageStack.start()
		messageStack = new window.ProactiveMessaging({
			messenger: window.stackchat,
			ttl: 4000 // default
			author: "Test Bot"
		})

		// start 
		messageStack.start();
	}
</script>

Package Manager

Install the dependencies via npm or yarn:

# NPM
npm install --save @stackchat/web-messenger@latest @stackchat/proactive-messaging@latest

# Yarn
yarn add @stackchat/web-messenger@latest @stackchat/proactive-messaging@latest

To include our default styles, also include the following:

import "@stackchat/proactive-messaging/dist/main.css"

Now in your JavaScript code:

import Stackchat from "@stackchat/web-messenger";
import { ProactiveMessaging } from "@stackchat/proactive-messaging";

let messageStack

// Add an event listener to know when Web Messenger 
// is ready to go
Stackchat.on('ready', initialiseProactiveMessaging)

//
const initialiseProactiveMessaging() => {
	// This step is required before calling
	// messageStack.start()
	messageStack = new ProactiveMessaging({
		messenger: Stackchat,
		ttl: 4000 // default
		author: "Test Bot"
	})

	// start 
	messageStack.start();
}

// Initialise Web Messenger
Stackchat.init({
	appId: "YOUR_APP_ID_HERE"
})

API

This library exposes a single class - ProactiveMessaging - which is used to handle proactives messages and to manipulate them.

const messageStack = new ProactiveMessaging(options) //see below

Initialisation Options

  • options

    | Property | Optional | Default Value | Description | |-----------|----------|--- |-------------| |messenger|No |- |An initialised instance of the StackChat Web Messenger. This is required to be able to display the proactive messages above the message bubble/tab | |ttl |Yes |2000 |The amount of time each message should live on the screen in milliseconds. By default, its 2s i.e. 2000ms| |author |No |- |The name displayed at the top of each message. This is what will be used as author name for each proactive message| |maxMessages |No |- |The maximum number of messages that are displayed on the screen at any given time. By default, it is 3| |singularCloseButton |No |- |Determines whether to show one close button for all messages or one for each message|

Methods

  • start()

    Triggers the ProactiveMessaging instance to start listening for incoming messages in a conversation. As long as the messenger widget is not open, ProactiveMessaging will ensure that any message which contains the following in its metadata property will be displayed proactively.

    {
    	proactive: true
    }
    
    // Therefore the message object should look like this
    message = {
    	metadata: {
    		proactive: true,
    		...otherMetaProps
    	},
    	...otherMessageProps
    }
  • addMessage(text, actions?)

    Allows the developer to simulate or display a proactive message to the user without it becoming a part of the ongoing conversation.

    For e.g.

    // Without actions
    messageStack.addMessage("Hello, world!")
      
    // With actions
    messageStack.addMessage(
    	"Hello, world!",
    	[
    		{
    			text: "Hello there!",
    			openMessengerOnReply: false
    		},
    		{
    			text: "Hi! What are you up to?",
    			openMessengerOnReply: true
    		}
    	]
    )
  • stop()

    Triggers the ProactiveMessaging instance to stop listening to incoming messages and removes all associated DOM elements from the page.

Event Binding

ProactiveMessaging offers two special methods to allow developers to react to events as they occur.

Note: You can add and remove event binding at any time.

  • on(event, handler)

    Allows you to specify a callback for a event which is called when that aforesaid event occurs.

  • off(event?, handler?)

    Allows you to remove a callback tied to an event. If no handler is specfied, it removes all the callbacks associated with the event. If no event has been specified, all callbacks for all events are cleared.

Events

This is the list of events that you can use with on and off methods as described above.

  • ready

    This event is fired when your ProactiveMessaging instance is ready. From this point on, it can start displaying proactive messages.

    messageStack.on("ready", () => {
      console.log("Proactive Messaging is ready!");
    });
  • proactive-message:clicked

    This event is fired when a user clicks on a proactive message. This event is not fired when a user dismisses a message or clicks on a quick reply.

    messageStack.on("proactive-message:clicked", (event) => {
      console.log("Proactive Message clicked > message", event.message);
    });
  • proactive-message:dismissed

    This event is fired when a user dismisses a proactive message. It is not fired if the message auto dismisses after the ttl.

    messageStack.on("proactive-message:dismissed", (event) => {
      console.log("Proactive Message dismissed > message", event.message);
    });
  • quick-reply:clicked

    This event is fired when a user clicks on one of the quick replies in a proactive message.

    messageStack.on("quick-reply:clicked", (event) => {
      console.log("Quick reply clicked");
      console.log("Message", event.message);
      console.log("Quick reply", event.quickReply);
    });
  • messenger:opened

    This event is fired whenever the Stackchat Web Messenger is opened by your ProactiveMessaging instance. Stackchat Web Messenger is opened when a user clicks on a message or clicks on one of the quick replies. Refer to the first part of the API section above.

    messageStack.on("messenger:opened", () => {
      console.log("Stackchat Web Messenger opened");
    });
  • clear

    This event is fired when all the proactive messages have been cleared - by user interaction or otherwise. Consider this as a blank slate similar to right after the ready event has occured.

    messageStack.on("clear", () => {
      console.log("All proactive messages cleared!");
    });

Styling

Default Styles

This library includes some base styles that display proactive messages in the nice UI as shown above here and here.

Consuming default styles depends on the way you integrate this library:

  • Script

    You can use our CDN hosted stylesheet via a script tag

    <link type="text/css" src="https://assets.au.stackchat.com/sdk/proactive-messaging/1.0.4/main.css">
  • Package Manager

    When using a package manager like npm or yarn, the default styles are automatically imported when you import ProactiveMessaging.

    In this case, you need only provide additional styles to suit your organisation's branding requirements. Please look at the custom styles section below.

Custom Styles

The module mostly uses classes to apply styles to the individual components and they are named logically so to enable easy overrides.

Important

Some base styles are required to display proactive messages properly. These styles are added to the elements inline and therefore, can not be overridden.

Animations

If you plan on overriding the default animation behaviour, please ensure you provide styles for two selectors i.e. @keyframes and @webkit-keyframes to account for compatibility with different browsers.

The default stylesheet is provided below for your reference. Use it as a reference point for classes you would like to add custom styles to.

/** The base container for all proactive messages **/
.proactive-container {
  overflow-y: hidden;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  flex-direction: column;
  z-index: 9998;
}

.proactive-container * {
	outline: none;
}

/** Singular close button to dismiss all messages **/
.proactive-container .external-close-button {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background-color: #d8d8d8;
  cursor: pointer;
}

/** The container for individual proactive message **/
.proactive-container .proactive-message {
	margin-bottom: 8px;
	padding: 4px;
}

/** The message inside each proactive message **/
.proactive-container .proactive-message .message {
  background-color: white;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.2);
  width: 232px;
}

.proactive-container .proactive-message .message .header {
	position: relative;
	width: 100%;
	height: 40px;
	display: flex;
	align-items: center;
	justify-content: flex-start;
}

/** The author of the proactive message **/
.proactive-container .proactive-message .message .header .name {
	margin: 0;
	margin-left: 16px;
	margin-right: 8px;
	font-weight: 600;
	font-size: 14px;
	color: #8c1aff;
}

/** The close button inside each proactive message **/
.proactive-container .proactive-message .message .header .close-button {
	position: absolute;
	right: 0;
	top: 0;
	width: 40px;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: transparent;
	border: none;
	cursor: pointer;
}

/** The content of the proactive message **/
.proactive-container .proactive-message .message .content {
	padding: 8px 16px 16px 16px;
}

.proactive-container .proactive-message .message .content .text {
	margin: 0;
	font-size: 14px;
}

/** The container for quick actions(if any) for each individual message **/
.proactive-container .proactive-message .actions {
	margin-top: 4px;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
}

/** Each indidivual action of a proactive message **/
.proactive-container .proactive-message .actions .action {
	background: linear-gradient(
			0,
			rgba(140, 26, 255, 0.45) 60%,
			rgba(140, 26, 255, 0.45) 60%
		), linear-gradient(0, #fff 100%, #fff 0);
	box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.25);
	border: 1px solid #8c1aff;
	border-radius: 4px;
	margin-left: 4px;
	font-size: 14px;
	padding: 11px;
	min-width: 64px;
	font-weight: 600;
	cursor: pointer;
	line-height: 16px;
	color: #000;
}

/**
 * Classes to handle animating in and out
 * of individual proactive messages
 */
.show-message,
.hide-message {
	-webkit-animation-name: animGenie;
	animation-name: animGenie;
	-webkit-animation-duration: 0.4s;
	animation-duration: 0.4s;
}

.hide-message {
	animation-direction: reverse;
	-webkit-animation-name: animGenieReverse;
	animation-name: animGenieReverse;
}

/**
 * The animation for messaging coming in
 * and being displayed on screen
 */
@-webkit-keyframes animGenie {
	0% {
		opacity: 0;
		-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		-webkit-animation-timing-function: ease-in;
		animation-timing-function: ease-in;
	}
	40% {
		opacity: 0.5;
		-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		-webkit-animation-timing-function: ease-out;
		animation-timing-function: ease-out;
	}
	70% {
		opacity: 0.6;
		-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
		transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
		transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
	}
}

@keyframes animGenie {
	0% {
		opacity: 0;
		-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		-webkit-animation-timing-function: ease-in;
		animation-timing-function: ease-in;
	}
	40% {
		opacity: 0.5;
		-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		-webkit-animation-timing-function: ease-out;
		animation-timing-function: ease-out;
	}
	70% {
		opacity: 0.6;
		-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
		transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
		transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
	}
}

/**
 * The animation for messaging going out
 * and being removed off screen
 */
@-webkit-keyframes animGenieReverse {
	0% {
		opacity: 0;
		-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		-webkit-animation-timing-function: ease-in;
		animation-timing-function: ease-in;
	}
	40% {
		opacity: 0.5;
		-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		-webkit-animation-timing-function: ease-out;
		animation-timing-function: ease-out;
	}
	70% {
		opacity: 0.6;
		-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
		transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
		transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
	}
}

@keyframes animGenieReverse {
	0% {
		opacity: 0;
		-webkit-transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		transform: translate3d(45%, calc(144%), 0) scale3d(0, 1, 1);
		-webkit-animation-timing-function: ease-in;
		animation-timing-function: ease-in;
	}
	40% {
		opacity: 0.5;
		-webkit-transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		transform: translate3d(27%, 0, 0) scale3d(0.02, 1.1, 1);
		-webkit-animation-timing-function: ease-out;
		animation-timing-function: ease-out;
	}
	70% {
		opacity: 0.6;
		-webkit-transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
		transform: translate3d(9%, -40px, 0) scale3d(0.8, 1.1, 1);
	}
	100% {
		opacity: 1;
		-webkit-transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
		transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
	}
}