@visa/charts

Collection of visa charts

Usage no npm install needed!

<script type="module">
  import visaCharts from 'https://cdn.skypack.dev/@visa/charts';
</script>

README

@visa/charts

This packages bundles visa chart components web components into a single build.

Installation Steps

  • Using npm
    $ npm i @visa/charts
    
  • Using yarn
    $ yarn add @visa/charts
    

Components with Ready status in this bundle

Components with Development status


# How to use the @visa/charts web component bundle in different environments

Walk throughs included below:


# Web component in javascript ^

Step 1: Install yarn add @visa/charts

Step 2: Mount components to the window

// in your index.html
<script src="./node_modules/@visa/charts/dist/charts.js"></script>
// or if you take advantage of ES modules, you can use below:
import { defineCustomElements } from '@visa/charts/dist/loader';
defineCustomElements(window);

Step 3 (Optional): Build a function for dynamic prop assignment

// this function is optional, it makes assigning props easier and dynamic
function assignChartProps(chart, props) {
  Object.keys(props).forEach(prop => {
    chart[prop] = props[prop];
  });
}

// example props object
var props = {
  data: [
    { month: 'Apr 17', value: 1407543 },
    { month: 'May 17', value: 6042320 },
    { month: 'Jun 17', value: 3234002 },
    { month: 'Jul 17', value: 2221233 },
    { month: 'Aug 17', value: 4476321 },
    { month: 'Sep 17', value: 3789221 },
    { month: 'Oct 17', value: 6543535 },
    { month: 'Nov 17', value: 7457432 },
    { month: 'Dec 17', value: 2636346 },
    { month: 'Jan 18', value: 2340000 },
    { month: 'Feb 18', value: 3202340 },
    { month: 'Mar 18', value: 8503536 }
  ],
  valueAccessor: 'value',
  ordinalAccessor: 'month'
};

Step 4: Leverage the components using the pattern/method of your choice

// in your JS file

// vanilla method
const barChart = document.getElementById('bar-chart');
assignChartProps(barChart, props); // custom function from Step 3

// templating method
const chartTemplate = document.getElementById('bar-chart-template').content;
const templateBarChart = chartTemplate.firstElementChild;
assignChartProps(templateBarChart, props); // custom function from Step 3
document.body.appendChild(chartTemplate);

// jquery method
const jqueryBarChart = $('#bar-chart')[0];
assignChartProps(jqueryBarChart, props); // custom function from Step 3
<!-- in your HTML file -->

<!-- Vanilla Element -->
<bar-chart id="bar-chart" />

<!-- Vanilla Template -->
<template id="bar-chart-template">
  <bar-chart />
</template>

# Web component in react ^

Step 1: Install yarn add @visa/charts

Step 2: Mount the custom web components to the window

// in your index.js or some other high level component
...
import { defineCustomElements as defineChartLib } from '@visa/charts/dist/loader';
...
ReactDOM.render(<App />, document.getElementById('root'));
defineChartLib(window);
...

Step 3: Add the required util to your project for passing props

// we usually put this in our src/utils folder and export it
export function wc(customEvents = {}, props = {}) {
  let storedEl;

  return function(el) {
    Object.entries(customEvents).forEach(([name, value]) => {
      // If we have an element then add event listeners
      // otherwise remove the event listener
      const action = el ? el.addEventListener : storedEl.removeEventListener;
      if (typeof value === 'function') {
        action(name, value);
        return;
      }
    });
    // If we have an element then set props
    if (el) {
      Object.entries(props).forEach(([name, value]) => {
        el[name] = value;
      });
    }
    storedEl = el;
  };
}

Step 4: Leverage the web components directly in React

// we usually create a local component within our project
// note: you can also apply step 2 directly within the local component if you choose
import React from 'react';
import { wc } from '../utils/wc'; // eslint-disable-line spellcheck/spell-checker
import { defineCustomElements as defineChartLib, applyPolyfills } from '@visa/charts/dist/loader'; // remove this line if you did step 2

/**
 * BarChart
 */
class BarChart extends React.Component {
  /**
   * ensure that the chart components required are available in the window
   */
  // remove this stuff if you did step 2
  componentWillMount() {
    if (!(window.customElements || {}).get('bar-chart')) {
      // if you need stencil's polyfills
      applyPolyfills().then(() => defineChartLib(window));

      // or, if you don't need polyfill
      // defineChartLib(window);
    }
  }

  /**
   * @returns {child} the stencil data visualization component
   */
  render() {
    return <bar-chart ref={wc({}, { ...this.props })} />;
  }
}

BarChart.defaultProps = {};

export default BarChart;

# Web component in angular ^

Step 1: Install yarn add @visa/charts

Step 2: Mount the custom web components to the window

// in main.ts of project or any appropriate .ts file (ideally this only should be called once, during bootstrapping)
import { enableProdMode } from '@angular/core';
// ...
import { defineCustomElements, applyPolyfills } from '@visa/charts/dist/loader';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .catch(err => console.log(err));

// if you need stencil's polyfills
applyPolyfills().then(() => defineCustomElements(window));

// or, if you don't need polyfill
// defineCustomElements(window);

Step 3: Add the required schema to your project for using custom web components

// in a module.ts that includes any components
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
// ...
@NgModule({
    imports: [],
    // ...
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
// ...

Step 4: Leverage the web components directly in Angular

// in component.ts

import { Component, OnInit, ViewChild, ElementRef, OnChanges } from '@angular/core';
// the following import only needs to be called if this was
// not done in the earlier bootstrapping step
import { defineCustomElements } from '@visa/charts/dist/loader';

@Component({
  selector: 'bar-chart',
  templateUrl: './bar-chart.component.html'
})
export class BarChartComponent implements OnInit, OnChanges {
  // we will only pass a single object, with all props as properties
  props = {
    ordinalAccessor: 'month',
    valueAccessor: 'value',
    data: [
      { month: 'Apr 17', value: 1407543 },
      { month: 'May 17', value: 6042320 },
      { month: 'Jun 17', value: 3234002 },
      { month: 'Jul 17', value: 2221233 },
      { month: 'Aug 17', value: 4476321 },
      { month: 'Sep 17', value: 3789221 },
      { month: 'Oct 17', value: 6543535 },
      { month: 'Nov 17', value: 7457432 },
      { month: 'Dec 17', value: 2636346 },
      { month: 'Jan 18', value: 2340000 },
      { month: 'Feb 18', value: 3202340 },
      { month: 'Mar 18', value: 8503536 }
    ]
  };
  @ViewChild('chart') chart: ElementRef;
  constructor() {
    // the following binding to the window only needs to be called
    // if this was not done in the earlier bootstrapping step
    defineCustomElements(window);
  }
  ngOnInit() {
    // our components watch for state change, so this simply binds the properties
    Object.keys(this.props).forEach(key => {
      this.chart.nativeElement[key] = this.props[key];
    });
  }
  ngOnChanges() {
    // if props change, we reassign properties to trigger internal state change
    Object.keys(this.props).forEach(key => {
      this.chart.nativeElement[key] = this.props[key];
    });
  }
}
<!-- in component.html -->

<bar-chart #chart [props]="props"> </bar-chart>