Search selfstore
v1.8.21

Widget events

Every widget reports through DOM events rather than callbacks, so a host reacts without polling and without holding a reference to each element.

All of them bubble and are composed, which means they cross the shadow boundary. One listener high up sees everything:

document.addEventListener('selfstore-connected', (e) => {
  console.log(e.detail.outcome);
});

Connecting

Event Element Detail
selfstore-connected connect, gate { outcome }
selfstore-error connect { error }
selfstore-cancelled connect, join none
selfstore-gate-deferred gate none

The gate does not re-emit the connect events - the connect element it builds lives inside it, and the events bubble through on their own.

Status

Event Element Detail
selfstore-status-action status { action }

action is choose-destination, download, reconnect, unlock or null. The widget reports which remedy the user asked for; performing it is your app’s job.

Backups

Event Element Detail
selfstore-backups-opened backups { fileId }
selfstore-backups-created backups { label }
selfstore-backups-renamed backups { fileId, label }
selfstore-backups-deleted backups { fileId }
selfstore-backups-forgotten backups { fileId }
selfstore-backups-wrong-password backups { fileId }
selfstore-backups-error backups { code }
selfstore-backups-leave backups { fileId }
selfstore-backups-encrypt backups { fileId, label, active }
selfstore-backups-share backups { fileId, label, active }

The last three are requests, not reports. The panel surfaces an intent it cannot carry out on its own - leaving a share, encrypting a backup, opening a share panel - and your app owns what happens next. Everything above them describes something that already happened.

Sharing

Event Element Detail
selfstore-link-created share { link }
selfstore-link-copied share { url }
selfstore-share-stopped share none

Joining

Event Element Detail
selfstore-joined join { outcome: 'joined' }
selfstore-join-refused join { outcome }

selfstore-join-refused is not a failure channel. It names the two outcomes the journey expects - a spent invitation, or a device already following another share - so your app offers the right next step instead of a retry that will fail the same way.

Listening in a framework

React before 19 does not map custom events to on* props, so use a ref and addEventListener. Vue’s @selfstore-connected and Svelte’s on:selfstore-connected work directly. See using the widgets in a framework.

Errors have codes too

These events report what the user did or saw. The store’s own failures are a separate, typed surface - see error codes.