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

alexa-react

v1.0.6

Published

JSX for APL is a React-based APL templating framework that allows developers to define APL document within the code.

Downloads

8

Readme

JSX for APL is a React-based APL templating framework that allows developers to define APL document within the code. By using the React-style JSX/TSX file format, developers can include JSX-based APL components as XML-style definition for the APL and shorten the APL definition code length, making the development more manageable.

Installation

Install ask-sdk-jsx-for-apl, react and react-dom as dependencies

npm install -S ask-sdk-jsx-for-apl react react-dom

Getting Started

To learn how to set up your workspace and get started, please reference the Getting Started section.

Basic Usage

To create an APL component using JSX, create an APL document using APL component and MainTemplate component.

Component Code

// apl/LaunchAplDocument.js

import * as React from 'react';
import { APL, MainTemplate, Container, Text } from 'ask-sdk-jsx-for-apl';

export class LaunchAplDocument extends React.Component {
    constructor(props) {
        super(props);
        this.launchMessage = 'Welcome to my first JSX for APL skill!';
    }
    render() {
        return (
            <APL theme="dark">
                <MainTemplate>
                    <Container
                        alignItems="center"
                        justifyContent="spaceAround">
                        <Text
                            text={this.launchMessage}
                            fontSize="50px"
                            color="rgb(251,184,41)" />
                    </Container>
                </MainTemplate>
            </APL>
        );
    }
}

After creating your component, include it in your skill response as an APL directive.

Skill Response

import { SkillBuilders } from 'ask-sdk';
import * as Alexa from 'ask-sdk-core';
import { AplDocument } from "ask-sdk-jsx-for-apl";

import { LaunchAplDocument } from './apl/LaunchAplDocument';

class LaunchIntentHandler {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    }

  handle(handlerInput) {
    const responseBuilder = handlerInput.responseBuilder;
    return responseBuilder
        .addDirective(new AplDocument(<LaunchAplDocument />).getDirective())
        .speak("Welcome to my first JSX for APL skill")
        .getResponse();
  }
}

const builder = SkillBuilders.custom();

export const handler = builder.addRequestHandlers(
    new LaunchIntentHandler()
).lambda();

To see more example, check out the Common Usage section in our Wiki.

Why use JSX for APL?

Code First Approach

JSX for APL uses React-based components to define each APL document. By using JSX files to include XML-based APL document declaration and defining the document in an encapsulated React component, we can simply import and include the component into the response as a natural Javascript/Typescript code. Following code shows how a JSX for APL document can naturally fit into the LaunchIntent handler.

APL Document

import * as React from 'react';
import { APL, MainTemplate, Frame, Container, Text } from 'ask-sdk-jsx-for-apl';

export class LaunchAplDocument extends React.Component {
    constructor(props) {
        super(props);
        this.launchMessage = 'Welcome to my first JSX for APL skill!';
    }
    render() {
        return (
            <APL theme="dark">
                <MainTemplate parameters={["payload"]}>
                    <Frame
                    width="100vw"
                    height="100vh"
                    backgroundColor="rgb(22,147,165)"
                    >
                        <Container
                        alignItems="center"
                        justifyContent="spaceAround"
                        >
                            <Text
                                text={this.launchMessage}
                                fontSize="50px"
                                color="rgb(251,184,41)"
                            />
                        </Container>
                    </Frame>
                </MainTemplate>
            </APL>
        );
    }
}

Intent Handler

import { HandlerInput, RequestHandler } from 'ask-sdk';
import * as Alexa from 'ask-sdk-core';
import { Response } from 'ask-sdk-model';

import { LaunchAplDocument } from './apl/LaunchAplDocument';

export class LaunchIntentHandler {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    }

    handle(handlerInput) {
        const responseBuilder = handlerInput.responseBuilder;
        return responseBuilder
            .addDirective(new AplDocument(<LaunchAplDocument />).getDirective())
            .speak("Welcome to my first JSX for APL skill!")
            .getResponse();
    }
};

Main Skill

import { SkillBuilders } from 'ask-sdk';

import { LaunchIntentHandler } from './handlers/LaunchIntentHandler';

const builder = SkillBuilders.custom();

export const handler = builder.addRequestHandlers(
    new LaunchIntentHandler()
).lambda();

Dynamic APL Response

By leveraging React's component render lifecycle, JSX for APL can dynamically change the custom component's behaviour and minimize the returned APL document size.

The following example shows a usage of dynamic APL Response to check for the viewport shape on runtime and service different width and height values for the APL documents.

APL Document

import * as React from 'react';
import { APL, MainTemplate, Frame, Container, Text } from 'ask-sdk-jsx-for-apl';

export class LaunchAplDocument extends React.Component {
    constructor(props) {
        super(props);
        this.launchMessage = 'Welcome to my first JSX for APL skill!';
    }
    render() {
      return (
        <APL theme="dark">
          <MainTemplate parameters={["payload"]}>
            <Frame
              width={this.props.aplParameters.width}
              height={this.props.aplParameters.height}
              backgroundColor="rgb(22,147,165)"
            >
              <Container
                alignItems="center"
                justifyContent="spaceAround"
              >
                <Text
                  text={this.launchMessage}
                  fontSize="50px"
                  color="rgb(251,184,41)"
                />
              </Container>
            </Frame>
          </MainTemplate>
        </APL>
      );
    }
}

Intent Handler

import { HandlerInput, RequestHandler } from 'ask-sdk';
import * as Alexa from 'ask-sdk-core';
import { Response } from 'ask-sdk-model';

import { LaunchAplDocument } from './apl/LaunchAplDocument';

export class LaunchIntentHandler {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    }

    handle(handlerInput) {
        const responseBuilder = handlerInput.responseBuilder;
        const viewportShape = handlerInput.requestEnvelope.context.Viewport.shape;
        const aplParameters = {
          width: '100vw',
          height: '100vh'
        };
        if (viewportShape === 'ROUND') {
          aplParameters.width = '80vh';
          aplParameters.height = '80vh';
        }

        return responseBuilder
            .addDirective(
                new AplDocument(<LaunchAplDocument aplParameters={aplParameters} />)
                    .getDirective()
            )
            .speak("Welcome to my first JSX for APL skill")
            .getResponse();
    }
};

Readability, Reusability and Reliability

In the traditional JSON-based APL, a reuse of components can get complicated. Without use of layouts, multiple copies of same structure can exist and code change management can get very difficult. With JSX for APL, however, the reusability issue is resolved by simply creating new instances of a defined component class, making changes very fast and reliable.

The following example shows the reuse of Container component to serve different content.

Sub-component Code

import * as React from 'react';
import { Container } from 'ask-sdk-jsx-for-apl';

class WorkoutColumn extends React.Component {
    render() {
        return (
            <Container width="30%" height="100%"
                paddingBottom="16dp"
                paddingLeft="16dp"
                paddingRight="16dp"
                paddingTop="16dp"
                spacing="16dp">
                {this.props.children}
            </Container>
        );
    }
}

export default WorkoutColumn;

APL Document

import * as React from 'react';
import { APL, Container, Image, Text } from 'ask-sdk-jsx-for-apl';
import WorkoutColumn from './workout-column-apl';

class WorkoutApl extends React.Component {
    private renderWorkoutPartsImage() { ... }
    private renderWorkoutStepsImages() { ... }
    private renderWorkoutStepsTexts() { ... }

    render() {
        return (
            <APL theme="dark">
                <MainTemplate>
                    <Container width="100%" height="80vh" direction="row">
                        <WorkoutColumn>
                            {
                                this.renderWorkoutPartsImage();
                            }
                        </WorkoutColumn>
                        <WorkoutColumn>
                            {
                                this.renderWorkoutStepsImages();
                            }
                        </WorkoutColumn>
                        <WorkoutColumn>
                            {
                                this.renderWorkoutStepsTexts();
                            }
                        </WorkoutColumn>
                    </Container>
                </MainTemplate>
            </APL>
        );
    }
}

export default WorkoutApl;

Intent Handler

import * as Alexa from 'ask-sdk';

import WorkOutApl from './apl/workout-apl';

class WorkoutTypeIntentHandler {
    canHandle(handlerInput) {
        return Alexa.getIntentName(handlerInput.requestEnvelope) === 'WorkoutTypeIntent';
    }

    async handle(handlerInput) {
        const responseBuilder = handlerInput.responseBuilder;
        ... other code logic ...
        return responseBuilder
            .addDirective(new AplDocument(<WorkOutApl ... />).getDirective())
            .speak('Here\'s a workout!')
            .getResponse();
    }
}

Check out the Core Concepts page in our Wiki to see more details!

Security

See CONTRIBUTING for more information.

License

This project is licensed under the Apache-2.0 License.