API Reference

Every function in store.js, html.js, and shell.js.

store.js

createStore(jsonLd, options)

Create a reactive store from a JSON-LD object.

import { createStore } from './losos/store.js'

var store = createStore(data, {
  url: 'https://pod.example/data.jsonld',  // PUT target
  authFetch: window.xlogin.authFetch,       // authenticated fetch
  debounce: 800                             // ms before auto-save
})
MethodDescription
store.get(id)Retrieve a node by @id
store.prop(node, key)Read a property (fuzzy key match)
store.propAll(node, key)Read array property (always returns array)
store.type(node)Get @type
store.set(node, key, value)Write → dirty → auto-save
store.unset(node, key)Delete property → auto-save
store.push(node, key, value)Array append → auto-save
store.remove(node, key, fn)Array filter → auto-save
store.reorder(node, key, from, to)Array move → auto-save
store.save()Force immediate PUT
store.reload()Re-fetch from URL, notify listeners
store.onChange(fn)Subscribe to changes (returns unsubscribe)
store.toJSON()Serialize to JSON-LD string
store.dataThe raw JSON-LD root object
store.dirtyWhether there are unsaved changes

Fuzzy key resolution

store.prop(node, 'title') matches node['title'], node['dct:title'], or any key ending in :title, /title, or #title. This lets panes work with both short context aliases and full URIs.


html.js

html`...`

Tagged template literal that creates a template object. Use ${} for dynamic values:

import { html, render } from './losos/html.js'

render(container, html`
  <h1>${title}</h1>
  <button onclick="${function() { alert('clicked') }}">Click</button>
  ${condition ? html`<p>Shown</p>` : null}
  ${items.map(function(i) { return html`<div>${i.name}</div>` })}
`)

Supported value types in ${}:

render(container, template)

First call builds DOM. Subsequent calls with the same template shape patch only the changed ${} values.

keyed(items, keyFn, templateFn)

Efficient list rendering. Matches items by key, reuses DOM, skips unchanged items:

import { keyed } from './losos/html.js'

html`${keyed(
  items,
  function(i) { return i['@id'] },
  function(i) { return html`<div>${i.name}</div>` }
)}`

Items whose template values haven't changed are not re-rendered — their DOM nodes are reused as-is.

ref()

Grab a DOM element after render:

import { ref } from './losos/html.js'

var inputRef = ref()
render(el, html`<input ref="${inputRef}" />`)
inputRef.el.focus()

onUnmount(container, fn)

Call a function when the container is removed from the DOM (e.g., tab switch):

onUnmount(container, function() {
  unsub()        // unsubscribe from store
  audio.pause()  // clean up resources
})

innerHTML attribute

Set innerHTML directly in templates:

html`<div innerHTML="${htmlString}"></div>`
Warning: XSS risk with untrusted content. See Gotchas.

shell.js

boot(el, options)

Boot the shell. Called automatically if a #losos element exists.

import { boot } from './losos/shell.js'

boot('#app', {
  maxWidth: '100%',       // default: '960px'
  accentColor: '#e63946'  // default: '#7c3aed'
})

Options:

The shell provides built-in tab persistence (namespaced by pathname) and passes parsed JSON-LD as the 4th argument to pane.render().


Pane interface

export default {
  label: 'My Pane',
  icon: '📋',

  canHandle(subject, store) {
    // Return true if this pane should show for the data
    var node = store.get(subject.value)
    return store.type(node)?.includes('MyType')
  },

  render(subject, store, container, rawData) {
    // subject.value = the @id of the primary node
    // store = LION store (read-only, for canHandle)
    // container = DOM element to render into
    // rawData = parsed JSON-LD (use for createStore)
  }
}