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

laxar-react-adapter

v2.0.1

Published

Write LaxarJS widgets and controls using React

Downloads

16

Readme

LaxarJS React Adapter Build Status

Create LaxarJS widgets and controls using React

Installation

npm install --save laxar-react-adapter babel-plugin-transform-react-jsx babel-plugin-transform-class-properties

This will automatically add React if not already installed. These instructions assume that Babel is already configured with ES2015 support, e.g. by using the LaxarJS Yeoman generator.

Load the React adapter module (laxar-react-adapter) into your project and pass it to LaxarJS create:

import { create } from 'laxar';
import * as reactAdapter from 'laxar-react-adapter';
import artifacts from 'laxar-loader/artifacts?flow=main&theme=cube';
const configuration = { /* ... */ };
create( [ reactAdapter /* , ... */ ], artifacts, configuration )
   .flow( /* ... name, element ... */ )
   .bootstrap();

webpack Configuration

If you did not use the Yeoman generator to pre-configure webpack for React, your loader configuration will probably need to be adjusted. For webpack to resolve JSX files and to process them using Babel, the configuration (usually webpack.config.js) needs to be adjusted:

   resolve: { extensions: [ '.js', '.jsx' ] },
   module: {
      rules: [
         // ...,
         {
            test: /\.jsx?$/,
            exclude: path.resolve( __dirname, './node_modules' );
            use: 'babel-loader'
         }
      ]
   }

Finally include support for JSX in your .babelrc:

{
   // ...
   "plugins": [
      // ...,
      "transform-class-properties",
      "transform-react-jsx"
   ]
}

For ESLint support, check out the eslint-plugin-react module. That's it.

Usage

With the adapter in place, you can now write widgets and controls using React. The LaxarJS Yeoman generator can create implementation stubs for you, if you specify the integration technology "react". When creating widgets manually, make sure to set the "integration.technology" to "react" in the widget.json.

Creating a React Widget

Widgets can be created from a JSX file containing a basic widget component.

For example my-new-widget.jsx:

import React from 'react';
import { injections } from 'laxar-react-adapter';

export default class MyNewWidget extends React.Component {
   static [ injections ] = [ 'axFeatures' ];
   render() {
      const [ features ] = this.props.injections;
      return <div>Hello, world! { features.some.config }</div>;
   }
}

The component in this example is injected the axFeatures object. This object can be used to access the widget instance configuration. If a widget does not require any injections, the static property may be omitted.

Another injection called axReactRender is provided only when using "react" as the integration technology, and it can be used to update the widget DOM after a data change. When using component classes, this is not necessary, as this.forceUpdate() can be used instead. The following example uses the axReactRender injection in a functional component:

import React from 'react';
import { injections } from 'laxar-react-adapter';

MyNewWidget[ injections ] = [ 'axReactRender' ];
export default function MyNewWidget( props ) {
   const [ reactRender ] = props.injections;

   let count = 0;
   return <div onClick={ increment }>Clicks: { count }</div>;

   function increment() {
      ++count;
      reactRender();
   }
}

The render function is a no-op as long as the widget has not been attached to the DOM (e.g. while in a background-tab, or within a closed popup). As soon as the widget has been attached to the page DOM, axReactRender calls the forceUpdate() method of the component.

Read the LaxarJS documentation for more about creating widgets and activities and the available injections.

Providing a Widget Area to embed other Widgets

LaxarJS widgets can provide widget areas in their own HTML template. These areas can then be referenced from within page definitions in order to add widgets to them. To create such a widget with React, the component AxWidgetArea is provided by the adapter.

An AxWidgetArea instance accepts the following React props:

  • name (String): the local name of the widget area (required). This is the part after the . in the page definition. Must be constant

  • axAreaHelper (Object): the widget injection axAreaHelper (required)

  • axVisibility (Object): the widget injection axVisibility. This is required for the area visibility to ever be false

  • className (String, Object): forwarded to the className of the generated container DIV

  • visible (Boolean): false if the widget area should be hidden (default: true). The area will be hidden using CSS display: none, and will be kept in the DOM

Here is an example of a "react" widget providing a widget area "myContent" (accessible in the page as <widget-id>.myContent):

import React from 'react';
import { AxWidgetArea, injections } from 'laxar-react-adapter';

export default class MyNewWidget extends React.Component {
   static [ injections ] = [ 'axAreaHelper' ];

   render() {
      const [ areaHelper ] = this.props.injections;
      return <AxWidgetArea name='myContent' axAreaHelper={ areaHelper } />;
   }
}

In this example the widget area is always visible. For the visibility to change at runtime, the additional injection axVisibility is required. We're using React's setState to trigger change detection and automatic re-rending of the component.

import React from 'react';
import { AxWidgetArea, injections } from 'laxar-react-adapter';


export default class MyNewWidget extends React.Component {
   static [ injections ] = [ 'axAreaHelper', 'axVisibility' ];
   constructor( props ) {
      super( props );
      this.state = {
         showing: true
      }
   }
   render() {
      const [ areaHelper, visibility ] = this.props.injections;
      const toggleShowing = () => {
         this.setState(prev => ({ showing: !prev.showing }));
      };
      return (
         <div onClick={ toggleShowing }>
            <AxWidgetArea
               name='myContent'
               visible={ this.state.showing }
               axAreaHelper={ areaHelper }
               axVisibility={ visibility } />
         </div>
      );
   }
}

Creating a React Control

A LaxarJS control allows you to encapsulates one or more React components with associated CSS styles that can be overwritten by LaxarJS themes.

React controls are implemented as regular JavaScript modules, just like plain LaxarJS controls:

// my-new-control.jsx
import React from 'react';

export default class MyNewControl extends React.Component {
   render() {
      return <div className='my-new-control'></div>;
   }
}

Select "react" as the integration technology when you generate the control with the LaxarJS Yeoman generator, or set it as the "integration.technology" of the control.json descriptor when creating a control manually:

// control.json
{
   "name": "my-new-control",
   "integration": {
      "technology": "react"
   }
}

Widgets can access the control by loading its module, or by requesting it through the axControls injection. The latter is recommended as it does not depend as much on the project-specific loader configuration:

// my-new-widget.jsx
import React from 'react';
import { injections } from 'laxar-react-adapter';

export class MyNewWidget extends React.Component {
   static [ injections ] = [ 'axControls' ];
   render() {
      const [ controls ] = this.props.injections;
      const { MyReactControl } = controls.provide( 'my-new-control' );
      return <div>Hello, world! <MyReactControl /></div>;
   }
}

For this to work the widget needs to list their controls in the "controls" section of the descriptor, which also ensures that CSS theming works:

// widget.json
{
   "name": "my-new-widget",
   "integration": {
      "technology": "react",
      "type": "widget"
   },
   "controls": [ "my-new-control" ],
   "features": { /* ... */ }
}

Read the LaxarJS documentation for general information on providing controls.

Testing with LaxarJS Mocks

Starting with laxar-mocks v2.0.0, you can easily create tests with the setupForWidget function. Simply write your specs like this:

import * as axMocks from 'laxar-mocks';

describe( 'The my-counter-widget', () => {

   beforeEach( axMocks.setupForWidget() );
   beforeEach( () => {
      axMocks.widget.configure( { someFeature: 'someConfigValue' } );
   } );

   beforeEach( axMocks.widget.load );

   let widgetDom;
   beforeEach( () => { widgetDom = axMocks.widget.render(); } );

   // ... tests ...

   afterEach( axMocks.tearDown );
} );

Building the Adapter from Source

Instead of using a pre-compiled library within a project, you can also clone this repository:

git clone https://github.com/LaxarJS/laxar-react-adapter.git
cd laxar-react-adapter
npm install

To see changes in your application, either configure your project to work with the sources (e.g. by using webpack), or rebuild the webpack bundles by running npm run dist.

To run the automated karma tests:

npm test

To generate HTML spec runners for opening in your web browser, so that you can e.g. use the browser's developer tools:

npm  start

Now you can select a spec-runner by browsing to http://localhost:8080/dist/spec/.