Skip to main content

Web Components

Use DialStack components in any JavaScript application without React. @dialstack/sdk-js provides native Web Components (Custom Elements) that work in vanilla JavaScript, Vue, Angular, Svelte, or any framework.

Quick Start

Using CDN

HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@dialstack/sdk-js"></script>
</head>
<body>
<dialstack-call-logs></dialstack-call-logs>
<dialstack-voicemails></dialstack-voicemails>

<script>
// Initialize DialStack
const dialstack = DialStack.initialize({
publishableKey: 'pk_live_YOUR_KEY',
// Fetch a client secret from your backend
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
});

// Wire the elements to the initialized instance
document.querySelector('dialstack-call-logs').setInstance(dialstack);
document.querySelector('dialstack-voicemails').setInstance(dialstack);
</script>
</body>
</html>

Using ES Modules

For bundled applications without React, import @dialstack/sdk-js — it registers the custom elements for you, and nothing else is needed.

The /pure subpath is the same SDK with that registration left out, for cases where importing a module must not touch the DOM — server-side rendering, or a test that asserts on registration itself. There you call registerComponents() when you want the elements defined:

TypeScript
import { loadDialstackAndInitialize, registerComponents } from '@dialstack/sdk-js/pure';

async function init() {
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
appearance: {
theme: 'auto',
},
});

// Register the custom elements before creating any of them
await registerComponents();

// Create components programmatically — create() wires the instance for you
const callLogs = dialstack.create('call-logs');
document.getElementById('call-logs-container').appendChild(callLogs);
}

init();
Register the elements before you use one

This applies to the /pure subpath only — importing @dialstack/sdk-js registers the elements on your behalf.

registerComponents() is asynchronous, so await it before calling create() or touching an element in your markup. Until an element is registered it is an unknown element: it ignores every property you set on it and renders nothing, and calling a method like setInstance() on it throws.

Initialization

UMD (Browser Global)

When using the CDN, DialStack is available as a global:

JavaScript
const dialstack = DialStack.initialize({
publishableKey: 'pk_live_YOUR_KEY',
appearance: {
theme: 'light',
variables: {
colorPrimary: '#6772E5',
},
},
});

ES Module (Pure)

For bundled apps, use the pure import:

TypeScript
import { loadDialstackAndInitialize } from '@dialstack/sdk-js/pure';

const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
});

DialStackInstance API

The instance returned from initialize() or loadDialstackAndInitialize() provides these methods:

create(tagName)

Create a component element. If you imported from /pure, await registerComponents() first:

JavaScript
const callLogs = dialstack.create('call-logs');
const voicemails = dialstack.create('voicemails');

// Append to DOM
document.getElementById('container').appendChild(callLogs);

update(options)

Update appearance for all components:

JavaScript
dialstack.update({
appearance: {
theme: 'dark',
variables: {
colorPrimary: '#8B5CF6',
},
},
});

logout()

Clear session and destroy all components:

JavaScript
dialstack.logout();

Component Element Methods

All component elements share these common methods:

MethodDescription
setInstance(instance)Set the DialStack instance
setLocale(locale)Set UI locale
setFormatting(options)Set date/phone formatting
setIcons(icons)Set custom icons
setLayoutVariant(variant)Set layout density
setClasses(classes)Set CSS classes
setOnLoaderStart(callback)Set loading callback
setOnLoadError(callback)Set error callback

Available Components

Tag NameDescription
<dialstack-call-history>Compact call history for a phone number
<dialstack-call-logs>Call history table
<dialstack-voicemails>Voicemail list with playback
<dialstack-phone-numbers>Unified phone number list with search

Event Handling

Set event handlers using setter methods:

JavaScript
const callLogs = document.querySelector('dialstack-call-logs');

callLogs.setOnLoadError((event) => {
console.error('Load failed:', event.error);
});

callLogs.setOnRowClick((event) => {
console.log('Clicked call:', event.callId);
});

Framework Integration

Vue.js

Vue
<template>
<div>
<dialstack-call-logs ref="callLogs"></dialstack-call-logs>
</div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
// The root entry registers the custom elements on import
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';

const callLogs = ref(null);

onMounted(async () => {
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
});

callLogs.value.setInstance(dialstack);
});
</script>

Angular

TypeScript
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
// The root entry registers the custom elements on import
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';

@Component({
selector: 'app-voice-dashboard',
template: ` <dialstack-call-logs #callLogs></dialstack-call-logs> `,
})
export class VoiceDashboardComponent implements OnInit {
@ViewChild('callLogs') callLogsRef!: ElementRef;

async ngOnInit() {
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
});

this.callLogsRef.nativeElement.setInstance(dialstack);
}
}

Svelte

Svelte
<script>
import { onMount } from 'svelte';
// The root entry registers the custom elements on import
import { loadDialstackAndInitialize } from '@dialstack/sdk-js';

let callLogsEl;

onMount(async () => {
const dialstack = await loadDialstackAndInitialize({
publishableKey: 'pk_live_YOUR_KEY',
fetchClientSecret: async () => {
const res = await fetch('/api/dialstack/session', { method: 'POST' });
const { client_secret } = await res.json();
return client_secret;
},
});

callLogsEl.setInstance(dialstack);
});
</script>

<dialstack-call-logs bind:this={callLogsEl}></dialstack-call-logs>

Next Steps