Important

This project is very much in its infancy. These specs will provide information about features which are yet to be implemented.
Broadly speaking, they target at least v0.5.x from the milestone page

Quick overview#

vs is a lightweight runtime to design and run custom user interfaces based on fltk.
It aims to be fast, to fit on systems with limited resources available, and to run on virtually any platform.
The vs runtime ships with several built-in features, tools and libraries:

  • A self-hosted workspace/explorer to quickly access local and remote apps, to update vs, and to visually customize user settings.
  • A self-hosted UI builder/IDE to visually inspect, debug or write custom components and applications.
  • C bindings to expose most features and allow custom native components from third parties.
  • A language server & extension to directly handle .vs and .tvs files in vscode and compatible editors.

Structure of an application#

  • An entry-point file referred as app, whose root element is app.
  • Components, whose root element is component, either used from the entry-point file or other components.
  • Data sources, usually files with a specific format or endpoints with a well-defined interface.
  • Assets like images.
  • An optional external application usually as a dynamic library linked with the app, or indirectly used via a Unix socket domain.

Furthermore, there are additional elements which are not controlled by those writing the app, but on the user side:

  • A storage where secrets and persistent data can be saved.
  • A profile with clear permissions and safety policies. An application can provide one as asset suggesting the user to adopt it, but it has no control over what the user decides.

Both apps and components can be either specified as final vs xml files, or they can be the result of some static data and a template compiled down into “final” xml files.

Basic VS elements#

basic attributes for frame-able components#

Except for some special entity or those which cannot have a vs frame, there are some attributes shared by everyone

attribute type default description
name string?
mixins
frame.mode
frame.access
frame.type

basic attributes for fl:xxx#

TODO: Add link to automatically generated docs

app#

attributes#

attribute type default description
key blob(256)? null If set, this is the class key used by the component. It requires fat components
tag string? null If set, this is the page-tag information to distinguish different pages within the same class keys
link-with path? null If set, the dynamic library to expose to each embedded script

component#

attributes#

attribute type default description
thin boolean true If true, this component will not allow storing app class keys, policies and path information
auto-prune boolean false If true, remove this component from the tree, directly expanding its children. Incompatible with thin: false
key blob(256)? null If set, this is the class key used by the component. It requires fat components
tag string? null If set, this is the page-tag information to distinguish different pages within the same class keys

namespace#

metadata#

metadata are is a pseudo-element which must be placed as direct children of an app or component entity.
Entries inside it will be parsed for documentation, attribution or to provide versioning information.

import#

import are directives which must be placed as direct children of an app or component entity.

use#

data#

attributes#

  • src
  • filter
  • sort
  • order

debug#

attributes#

  • key
  • value

viewport#

attributes#

  • src

elements with a frame#

attributes#

  • name
  • mixins
  • frame.mode
  • frame.acces
  • frame.type

script#

scripts are pseudo-entities which must be placed as direct children of a frame-able entity. Only one for each frame-able entity can be defined.

attributes#

attribute type default description
lang string? null If unset, the language will be automatically inferred from contextual information
src path? null If set, its content will only be used as fall-back and the src content will be preferred.
type single, module single Used to specify if it should be handled as a single user script or a shared one (TODO:link)
compact boolean false If set, all code is assumed to be inside the body of the default callback.

mixin#

mixins are pseudo-entities which must be placed as direct children of a frame-able entity. Only one for each frame-able entity can be defined.

attributes#

semantics#

Using components#

There are two ways to use other components inside others or within your app:

  • Via vs:use, suggested for cases where it is only needed once.
  • Adding a vs:import directive in the app/component, and using it as an element under the specified name.

There is also vs:viewport which does something similar, but in this case a new root is rendered within your document, with no event or symbol being passed top/down or bottom/up.

Examples#

<vs:component tag.suggested="component-a">
    <vs:import src="this://component-b.vs" tag="component-b"/>

    <component-b prop-1="value-1"/>
</vs:component>
<vs:component tag.suggested="component-a">
    <vs:use vs:src="this://component-b.vs" prop-1="value-1"/>
</vs:component>

Names#

Names are unique identifiers within a namespace for components.
Adding a name to a component instance also implies that a vs frame is created for it. The converse is also true, and if no explicit name is assigned, one will be automatically generated.
Related to names there are two undefined behaviours:

  • Giving the same name to two or more elements within the same namespace.
  • Accessing elements for which the name has not been manually defined.

Restrictions on names#

At this time, no restriction on names has been defined nor implemented.

Scope of visibility#

The scope within names are visible is called namespace. A namespace is not strictly speaking equivalent to the UI tree structure, and all elements within a namespace, regardless of their child/parent ordering, are mutually visible.

Transparent nodes#

Some elements will have their associated frame and name, but their mode is set to transparent.
In this case any child will be part of the same namespace as their parent, ignoring their tree dependency.

Limitations on visibility#

Elements for which their mode is set to container or slot-container will prevent name resolution upwards from children.
Elements for which their mode is set to slot or slot-container will prevent name resolution downwards to its children from nodes above it.
A node, will always be able to access up and down, regardless of the mode set. Limitations are only for others going through it.

Props#

Computed values#

Symbols#

Callbacks#

Unknowns#

Fields (Setter/Getters)#

Dispatcher#

Draw#

Event propagation#

Scripts#

Embedded scripts are

Single user scripts#

Module scripts#

Mixins#

Special mixins#

  • *
  • +tagName

Embedded interfaces#

Native#

QuickJS#

LUA#

WASM#

External#

RISCV#

Custom components#

Templating#

Templating is based on a vs.templ, a custom XML preprocessor loosely inspired by xslt.
Its documentation can be found on its separate repository here.
Within the context of vs.fltk, using templates involves two files:

  • the static dataset which contains any structured needed by the final generation. For vs, its root must be <vs:static-data> and provide a template attribute pointing to the actual component template. The suggested extension is .vs, the same as normal components.
  • the template itself, containing a vs tree structure and templating commands as well.
    Its conventional extension is .tvs. These files should never be used as components on their own.

When importing or using a component which requires processing, it is compiled and replaces the original dataset before the building process in the UI continues.
You can find an example for a dataset & its associated template.

Data#

Data elements are one of the mechanism in vs to include state in your applications.

General structure#

Attributes#

  • readonly as boolean. Defaults to false. If true, no mutation is allowed from within this application.
  • volatile as boolean. Defaults to true. If true it must be expected that events outside the scope of this app can change data.
  • src as string. The source path of data. It must be specified.
  • schema as string. The source path to a schema file. Used as metadata for static checks when the associated datasource is used.

Subtypes#

CSV#

Additional attributes#

  • header as boolean. Defaults to false. If true the first row is used as schema information or skipped if schema is already provided.
  • separator.field as string. Defaults to \t. The character to split columns.
  • separator.record as string. Defaults to \n. The character to split records.

FS#

JSON#

SQLITE#

XML#