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

@sinchlabs/previewer

v1.44.0

Published

<div align="center"> <img src="https://1vxc0v12qhrm1e72gq1mmxkf-wpengine.netdna-ssl.com/wp-content/uploads/2020/04/cropped-Sinch-PR-1000-300x141-1.png" width="320" alt="Sinch Logo" /> </div>

Downloads

22

Readme

Getting Started

  1. Create an .env file and paste the key to decrypt the package. Example below is just that and real keys needs to be provided by Sinch.

.env

DISTCRY = { "previewer": "p455w0rd" }
  1. Install the Previewer package
$ yarn add @sinchlabs/previewer

How To Use

You can use preview in several ways. By using one of the many implemented APIs or application components directly.

Using Previewer by specific API.

It allows to render the entire previewer by passing api-compatible message array. The example below shows a message from api which is passed to the conversation api previewer.

import { PreviewerConversationApi, ConversationChannel, ConversationDirection } from '@sinchlabs/previewer';

const messages = [
  {
    id: '',
    direction: ConversationDirection.UNDEFINED_DIRECTION,
    conversation_id: '',
    contact_id: '',
    metadata: '',
    accept_time: new Date(2020, 9, 17, 8, 59),
    app_message: {
      explicit_channel_message: {},
      text_message: {
        text: 'Hello :)',
      },
    },
  },
];

<PreviewerConversationApi
  channel={ConversationChannel.WHATSAPP}
  messages={messages}
/>;

Previewer also accepts the channel for which to render the message. The types are compatible with conversation api.

Using Previewer app components from modules/app directory.

Previewer allows to import any component from any application that is available. This is useful when you want to preview only a specific message, not the entire previewer. Components are written in typescript so we can easily see what parameters are passable.

import { TextWhatsApp } from '@sinchlabs/previewer/modules/apps/WhatsApp';

<TextWhatsApp
  text="Hello"
  incoming={true}
  date={new Date(2020, 9, 17, 8, 59)}
  RTLLayout={false}
/>;

In this example, we are importing a text message from the WhatsApp application that we want to display. The component allows parameters:

type Props = {
  text: string; // to render specific text
  mediaUrl?: string; // to display media (image/video). The text message allows you to display an image, and this is used, for example, to display the card message from the conversation api
  incoming?: boolean; // incoming / outgoing message
  date?: string | Date; // date
  RTLLayout?: boolean; // ability to display in right to left mode
};

All these parameters can be easily changed in the storybook under the apps/whatsapp/text tab.

Using Previewer with channels restrictions.

Previewer can handle restrictions in two ways (or together).

  • One is just informing that given channel has an error by error indicator in the channel dropdown. To make it work, StandardPhoneFrame component which contains channel dropdown must be wrapped with the RestrictionsProvider
  • Second is RestrictionsCard component which contain information about all channel messages limitations and found errors. To make it work, RestrictionsCard component must be wrapped with the RestrictionsProvider

RestrictionsProvider takes four props:

  • messages [type: ConversationMessage] (required): array of messages
  • onRestrictionError [type: (errors: RestrictionsChannelMessagesStatusType): void] (optional)
  • channelsWithErrorsDetails [type: channels: ConversationChannel[]] (optional): array of channels for which we will display the errors in RestrictionsCard (all by default)
  • enabledChannels [type: channels: ChannelIds] (optional): array of channels for which we should check errors.
import { useEffect, useState } from 'react';

import {
  ConversationChannel,
  RestrictionsProvider,
  RestrictionsCard,
  StandardPhoneFrame,
  PreviewerConversationApi,
} from '@sinchlabs/previewer';

export const ComponentWithRestrictions = (args) => {
  const [channel, setChannel] = useState(args.channel);

  useEffect(() => {
    setChannel(args.channel);
  }, [args.channel]);

  const onChannelSwitched = (newChannel: ConversationChannel) =>
    setChannel(newChannel);

  /* Optional - just in case if somebody would like to handle errors in the custom way  */
  const onRestrictionError = (
    _errors: RestrictionsChannelMessagesStatusType
  ) => {
    /* ... */
  };

  return (
    <RestrictionsProvider
      messages={messages}
      channelsWithErrorsDetails={[channel]}
    >
      {/*
       * `StandardPhoneFrame` wrapped with `RestrictionsProvider` provider will
       * automatically detect errors and show indicators
       */}
      <StandardPhoneFrame
        channel={channel}
        channelSwitcher={args.channelSwitcher}
        onChannelSwitched={onChannelSwitched}
      >
        <PreviewerConversationApi channel={channel} messages={messages} />
      </StandardPhoneFrame>
      {/* `RestrictionsCard` component can be placed anywhere inside `RestrictionsProvider`*/}
      <RestrictionsCard />
    </RestrictionsProvider>
  );
};

WhatsApp Template previewer

PreviewerWhatsAppBusinessAPI component takes four props:

  • messages [type: WhatsAppBusinessAPITemplate] (required): array of messages
  • RTLLayout [type: boolean] (optional): text direction
  • locale [type: boolean] (optional): language code used to format datetime
  • hour12 [type: boolean] (optional): hours format
import { useEffect, useState } from 'react';

import {
  StandardPhoneFrame,
  AppFrameWhatsApp,
  PreviewerWhatsAppBusinessAPI,
} from '@sinchlabs/previewer';

export const WhatsappPreviewer = () => {
  const [messages, setMessages] = useState<WhatsAppBusinessAPITemplate[]>([]);

  return (
    <StandardPhoneFrame>
      <AppFrameWhatsApp>
        <PreviewerWhatsAppBusinessAPI messages={messages} />
      </AppFrameWhatsApp>
    </StandardPhoneFrame>
  );
}; 

KakatoTalk Template previewer

PreviewerKakaoTalkTemplates component takes four props:

  • messages [type: KakaoTalkTemplate] (required): array of messages
  • RTLLayout [type: boolean] (optional): text direction
  • checkErrors [type: boolean] (optional): by default template previewer check for messages errors. If any error is detected, Error board with information is displayed.
  • onError [errors: KakaoTalkTemplateErrors] (optional): callback that returns an errors object
import { useEffect, useState } from 'react';

import {
  StandardPhoneFrame,
  AppFrameKakaoTalk,
  PreviewerKakaoTalkTemplates,
} from '@sinchlabs/previewer';

export const KakaoTalkPreviewer = () => {
  const [messages, setMessages] = useState<KakaoTalkTemplate[]>([]);

  /* Optional - just in case if somebody would like to handle errors in the custom way  */
  const handleError = (_errors: KakaoTalkTemplateErrors) => {
    /* ... */
  };

  return (
    <StandardPhoneFrame>
      <AppFrameKakaoTalk>
        <PreviewerKakaoTalkTemplates
          messages={messages}
          onError={handleError}
        />
      </AppFrameKakaoTalk>
    </StandardPhoneFrame>
  );
}; 

Project Structure

The general form of the project is as shown below:

    +-- assets
    +-- components
    +-- context
    |   +-- ChannelContext.ts
    |   +-- MessageContext.ts
    +-- hooks
    +-- icons
    +-- modules
    |   +-- apis
    |       +-- ConversationApi
    |       +-- RCSApi
    |       +-- SMSApi
    |       +-- WhatsAppApi
    |   +-- apps
    |       +-- AndroidMessages
    |       +-- Messenger
    |       +-- Viber
    |       +-- WhatsApp
    |   +-- deviceFrames
    |       +-- StandardPhoneFrame
    |       +-- TopBar
    +-- style
    |   +-- fonts.ts
    +-- types
    |   +-- client
    |   +-- RCS
    |   +-- SMS
    |   +-- WhatsApp
    +-- utils

The most important directory in the project is modules. There are components responsible for API processing and rendering of application components.

An example of what components the apis/ConversationAPI consists of:

    +-- apis/ConversationApi
    |   +-- AppFrameConversationApi
    |   +-- consts
    |       +-- FieldLimitationsConvesationApi.tsx
    |   +-- messages
    |     +-- CardConversationApi
    |     +-- CarouselConversationApi
    |     +-- ChoiceConversationApi
    |     +-- LocationConversationApi
    |     +-- MediaConversationApi
    |     +-- TextConversationApi
    |   +-- types
    |     +-- events.ts
    |   +-- AppMessage.tsx
    |   +-- ChannelSwitcher.tsx
    |   +-- index.ts
    |   +-- PreviewerConversationApi.tsx

In this case, the root component is PreviewerConversationApi.tsx. This is what you need to use the entire previewer responsible for processing the Conversation API. Among other things, it accepts props with an array of messages compatible with the api schema. Then it maps the message by going to the correct component for example CardConversationApi and depending on the channel uses the components found in apps. For example, for Viber it will choose components responsible for rendering this message.

An example of what components the apps/Viber consists of:

    +-- apps/Viber
    |   +-- AppFrameViber
    |   +-- components
    |   +-- consts
    |   +-- hooks
    |     +-- ButtonMessageViber
    |   +-- messages
    |     +-- ButtonMessageViber
    |     +-- CardBMViber
    |     +-- CardViber
    |     +-- CarouselViber
    |     +-- ChoiceViber
    |     +-- FileViber
    |     +-- ImageViber
    |     +-- LocationViber
    |     +-- TextViber
    |     +-- VideoViber
    |   +-- types
    |   +-- index.ts
    |   +-- MessageViber.tsx
    |   +-- styled.ts