Skip to content

<portable-inventory> Web Component

A custom element that wraps the PortableInventory SDK class. Uses Shadow DOM for style encapsulation. No JavaScript setup required — just set attributes.

Basic Usage

<script src="https://unpkg.com/@portable-inventory/widget-sdk@0.1.0/dist/portable-inventory-sdk.umd.js"></script>

<portable-inventory
  api-key="your-api-key"
  base-url="https://your-instance.example.com"
></portable-inventory>

The element auto-mounts when connected to the DOM and auto-destroys when removed.

Attributes

Attribute Type Required Description
api-key string Yes API key for authentication. Element does not mount without this.
base-url string No Base URL of the Varasto instance
product-id string No Navigate widget to this product on mount
location-id string No Set active location context on mount
theme-primary string No Primary accent color (e.g. #3b82f6)
theme-bg string No Background color
theme-text string No Text color
theme-radius string No Border radius (e.g. 8px)
theme-font string No Font family
compact boolean No Presence attribute — add to enable compact mode (no value needed)

All 10 attributes are observed. Changing any attribute dynamically triggers a widget reconnect.

Themed Example

<portable-inventory
  api-key="your-api-key"
  base-url="https://your-instance.example.com"
  product-id="42"
  theme-primary="#10b981"
  theme-bg="#f0fdf4"
  theme-text="#065f46"
  theme-radius="12px"
  compact
></portable-inventory>

Dynamic Attribute Updates

Changing product-id or location-id sends a command to the widget without full reconnect. Changing config or theme attributes triggers a destroy-and-remount cycle.

const el = document.querySelector('portable-inventory');

// Navigates widget to product 99 (no reconnect)
el.setAttribute('product-id', '99');

// Changes theme — triggers full reconnect
el.setAttribute('theme-primary', '#ef4444');

Framework Integration

React

function InventoryWidget({ apiKey, productId }: { apiKey: string; productId: string }) {
  return (
    <portable-inventory
      api-key={apiKey}
      base-url="https://your-instance.example.com"
      product-id={productId}
      theme-primary="#3b82f6"
    />
  );
}

For TypeScript, add a type declaration to avoid JSX errors:

// src/types/web-components.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    'portable-inventory': React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement> & {
        'api-key'?: string;
        'base-url'?: string;
        'product-id'?: string;
        'location-id'?: string;
        'theme-primary'?: string;
        'theme-bg'?: string;
        'theme-text'?: string;
        'theme-radius'?: string;
        'theme-font'?: string;
        compact?: boolean;
      },
      HTMLElement
    >;
  }
}

Vue

<template>
  <portable-inventory
    :api-key="apiKey"
    base-url="https://your-instance.example.com"
    :product-id="selectedProduct"
    theme-primary="#8b5cf6"
  />
</template>

<script setup lang="ts">
import '@portable-inventory/widget-sdk';
import { ref } from 'vue';

const apiKey = 'your-api-key';
const selectedProduct = ref('42');
</script>

Tell Vue to skip resolution of the custom element:

// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === 'portable-inventory',
        },
      },
    }),
  ],
});

Angular

Register the CUSTOM_ELEMENTS_SCHEMA in your module:

// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import '@portable-inventory/widget-sdk';

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  // ...
})
export class AppModule {}

Use in templates:

<portable-inventory
  [attr.api-key]="apiKey"
  base-url="https://your-instance.example.com"
  [attr.product-id]="selectedProduct"
  theme-primary="#f59e0b"
></portable-inventory>

Shadow DOM

The web component uses Shadow DOM (mode: 'open') to encapsulate the widget iframe. Parent page styles do not leak into the widget, and widget styles do not affect the host page.

To inspect the shadow root programmatically:

const el = document.querySelector('portable-inventory');
console.log(el.shadowRoot); // ShadowRoot { mode: 'open', ... }

Listening to Events

The web component does not directly expose the on()/off() event API. To listen to widget events, use the JavaScript API instead:

import { PortableInventory } from '@portable-inventory/widget-sdk';

const widget = new PortableInventory({
  apiKey: 'your-api-key',
  container: '#my-container',
});

widget.on('transaction_complete', (data) => {
  console.log(data);
});

widget.mount();

See API Reference for the full event system documentation.