Accounting made easy | Modernbanc
Vault

@modernbanc/js

Modernbanc JS is a plain Javascript library that you can use to embed elements such as inputs and outputs into your UI that will collect or show sensitive data.

Elements are modular, fully customizable so you can easily make them fit your user experience. They’re embedded into your app as securely hosted iFrames that isolate your app from sensitive data. Behind the scenes they use the same /secrets endpoints as in the guide above.

Requirements

  1. A workspace setup with Modernbanc.
  2. A valid API key with a role that has appropriate secret permissions (create/get/update/delete/reveal).

Installation

npm install @modernbanc/js
Local development issue with Nextjs and Create React App

You may have issues where the SDK doesn't make API calls to our server while developing locally on dev server due to browser security around iFrames. As a workaround you can test locally by:

  • Building your app using npm run build
  • Running the built app using:

    • serve -s build for Create React App
    • next start for Nextjs

Initializing

You can initialize your instance with an api key. Make sure that this key has permissions to work with secrets (secret).

const mdb = Modernbanc.init('YOUR_API_KEY')

Once you’ve initialized it you can start creating or accessing elements.

const elem1 = mdb.addElement({ type: 'input', id: 'card_number' })

You can also access them at any time later.

const elem1 = mdb.getElement({ type: 'input', id: 'card_number' })

Mounting elements

You can mount an element using mount function which will add it to the first div that matches specified css selectors

elem1.mount('#card_number')

The above will put an iFrame as a child of the first div that has card_number id. You can also create and mount elements at the same time:

mdb.addElement({ type: 'input', id: 'card_number', selectors: '#card_number' })

Input element

Create element options.

type InputElementOptions = {
  id: 'any_id' // Used for identifying the element.
  type: 'input'
  class?: string // Class to be passed to the element.
  css?: string // Raw css string to be passed to the element.
  google_font_url?: string; // Load a custom font for your element.
  placeholder?: string
  disabled?: string
  'aria-label'?: string
  auto_complete?: string // Enable auto-complete for this input.
  value?: string // Override current or set an initial input value.
  html_type?: TInputHTMLType // Native <input> html type.
  pattern?: string;
  max?: number | string;
  max_length?: number;
  min?: number | string;
  min_length?: number;
  replacers?: Replacer[];
  matchers?: Matcher[];
  deletion_date?: Date; // Date when the secret will be deleted.
  variables?: Record<string, any> | null; // Variables to be passed to the secret.
  /** Deprecated */
  validation?: {
    regex?: RegExp // if specified on('change') will return a `valid` prop.
  }
}
 
// Replacer allows to replace anything that matches the pattern with the replacement.
type Replacer = {
    type: 'regex';
    pattern: string;
    replacement: string;
} | {
    type: 'card_number' | 'expiry_date';
};
 
// Matcher allows to match the value against the pattern.
type Matcher = {
    type: 'regex';
    pattern: string;
    name: string;
} | {
    type: 'valid_card_number';
} | {
    type: 'valid_expiry_date';
} | {
    type: 'card_type';
};

Matchers

Matchers allow you to see if the user's entered final value matches a regex pattern. We offer some prebuilt matchers like valid_card_number or valid_expiry_date.

When a matcher is matched, we add a class name to the input element with the name of the matcher (e.g likely_visa) (or type if it's our pre-built matcher e.g card_number) so you can style it accordingly.

E.g you can have a custom matcher to detect if card is Visa.

import { useEffect } from 'react';
import Modernbanc, { InputElementOptions } from '@modernbanc/js';
 
const cardNumberOptions: InputElementOptions = {
  type: 'input',
  id: 'card_number',
  placeholder: 'Card Number',
  matchers: [
    {
      type: 'regex',
      pattern: /^4(\d|\s){0,15}$/.source, // Visa
      name: 'likely_visa',
    },
  ],
};
 
const App = () => {
  useEffect(() => {
    const mdb = new Modernbanc('YOUR_API_KEY');
    const element = mdb.addElement(cardNumberOptions);
    element.mount(`#${element.id}_container`);
  }, []);
 
  return <div id={`${cardNumberOptions.id}_container`}></div>;
};
 
export default App;

Helpful for example to know if card is Visa (starts with 4, i.e /^4/ ) or Mastercard (starts with 5 i.e /^5/ )

Validation prop is deprecated

Validation prop in input elements is now deprecated and will be removed in the future. Please use matchers instead.

Replacers

Replacers allow you to replace the value in the input as user enters it. Behind the scenes we just pass through your values to JS's replace() function. We offer some prebuilt replacer types like card_number or expiry_date which will add whitespaces/slashes etc.

Extra states:

  • When relevant we add following classes to html element:

    • .empty
    • .valid
    • .invalid
    • .touched

Methods:

  • setOptions(options: InputElementOptions, push?: boolean) - allows you to update all input options and push the changes to element at any time.

  • createSecret - creates and returns a new secret based on the current text within the input.

    const response = await elem1.createSecret()
    if (response && !response.is_error) {
      console.log(response.secret_id)
    }
  • on(event_type, handler_fn) - subscribe to events:

    • ready - iFrame was loaded
    • change- input value was updated.
    • focus - input was focused.
    • blur - input was unfocused/blurred.
    • key_down - key down event.
    • mount - places the element under a first div that matches css selector. Not needed if you provided selectors in a mdb.addElement method.
    • unmount - removes the element from its parent div.
  • focus - focuses the input element.

    const element = mdb.getElement({ type: 'input', id: 'card_number' })
    element?.focus();
  • blur - blurs the input element.

    const element = mdb.getElement({ type: 'input', id: 'card_number' })
    element?.blur();

Output element:

Options.

type OutputElementOptions = {
    type: 'output'
    id: string; // Used for identifying the element.
    class?: string; // Class to be passed to the element.
    css?: string; // Raw css string to be passed to the element.
    secret_id: string; // Id of a secret to show.
    google_font_url?: string; // Load a custom font for your element.
}

Methods:

  • setOptions(options: OutputElementOptions, push?: boolean) - allows you to update all the output options and push the changes to element at any time.

  • showSecretValue - reveals the value behind the secret_id
  • on(event_type, handler_fn) - subscribe to events:

    • ready - iFrame was loaded.
    • mount - places the element under a first div that matches css selector. Not needed if you provided selectors in a mdb.addElement method.
    • unmount - removes the element from its parent div.

Styling:

Every element has following properties:

  • css - Raw css string that you can pass directly to the component, E.g background: gray; border: 1px solid black. You can also use it to load a custom font for your inputs.

    • We also expose following css variables that you can refer to within your app.
    --font-size-3xs: 0.563rem; /* 9px */
    --font-size-2xs: 0.625rem; /* 10px */
    --font-size-xs: 0.688rem; /* 11px */
    --font-size-sm: 0.75rem; /* 12px */
    --font-size-md: 0.813rem; /* 13px */
    --font-size-lg: 0.875rem; /* 14px */
    --font-size-xl: 0.9375rem; /* 15px */
    --font-size-2xl: 1rem; /* 16px */
    --font-size-3xl: 1.125rem; /* 18px */
    --font-size-4xl: 1.25rem; /* 20px */
    --font-size-5xl: 1.5rem; /* 24px */
    --font-monospace: 'Roboto Mono', monospace;
    --font-regular: 'Inter', sans-serif;
    --speed-transition-very-fast: 70ms;
    --speed-transition-fast: 100ms;
    --speed-transition-normal: 150ms;
  • class - A string containing one or more classes that we pass directly to the html element.

  • google_font_url - Load a custom font for your element by passing a google font url and then using the font-family css property like the example below.

    import { useEffect } from 'react';
    import Modernbanc, { InputElementOptions } from '@modernbanc/js';
     
    const cardNumberOptions: InputElementOptions = {
      type: 'input',
      id: 'card_number',
      placeholder: 'Card Number',
      google_font_url: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap',
      css: 'font-family: "Inter", sans-serif;',
      matchers: [
        {
          type: 'regex',
          pattern: /^4(\d|\s){0,15}$/.source, // Visa
          name: 'likely_visa',
        },
      ],
    };
     
    const App = () => {
      useEffect(() => {
        const mdb = new Modernbanc('YOUR_API_KEY');
        const element = mdb.addElement(cardNumberOptions);
        element.mount(`#${element.id}_container`);
      }, []);
     
      return <div id={`${cardNumberOptions.id}_container`}></div>;
    };
     
    export default App;