# About Vuido

<div align="left"><img src="/files/-LDDYq37aDepJbcS6ri1" alt=""></div>

**Create native desktop applications for Windows, OS X and Linux using Vue.js.**


# Introduction

## What is Vuido?

Vuido is a framework for creating native desktop applications based on [Vue.js](https://vuejs.org/). Applications using Vuido can run on Windows, OS X and Linux, using native GUI components, and don't require Electron.

Under the hood, Vuido uses the [libui](https://github.com/andlabs/libui) library which provides native GUI components for each desktop platform, and the [libui-node](https://github.com/parro-it/libui-node) bindings for Node.js.

![](/files/-LDfTEJYjPXU8n0xpILW)

## Why Vuido?

Vuido is a cross-platform JavaScript framework which supports Windows, OS X and Linux. Applications using Vuido have the native look and feel on each platform, without having to write separate code or to use platform specific programming languages.

Vuido is very lightweight compared to other frameworks, such as Electron or NW\.js. The size of a simple Vuido application is about 20 MB, while a typical Electron application takes 90 MB or more. Applications using Vuido also take less memory and have faster startup time.

Vuido is based on Vue.js, a progressive JavaScript framework for building user interfaces. Vuido supports most of the standard Vue.js API. It's also compatible with many Vue.js extensions, for example Vuex. You can design the user interface using the powerful Vue.js template syntax and single-file components.

Applications using Vuido can also use the standard Node.js API, for example the file system and http modules, and any third-party packages compatible with Node.js.

## Development Status

Currently Vuido implements the basic containers and widgets supported by libui. It is ready to be used for creating simple applications. For an example of a real life application created using Vuido, see the [LaunchUI Packager GUI](https://github.com/mimecorg/launchui-packager-gui) project.

Bug reports and feature requests are welcome, however please look for a related issue in the [libui](https://github.com/andlabs/libui) project first, because Vuido can only implement functionality which is already implemented in libui.

## Acknowledgements

Vuido is largely based on Vue.js and shares most of its code, except for the platform specific code related to libui.

Vuido was inspired by [Proton Native](https://github.com/kusti8/proton-native), an environment for creating native desktop applications using React.

## License

Vuido is licensed under the MIT license.

Copyright (C) 2018 Michał Męciński.


# Installation

## Prerequisites

The following prerequisites are needed to compile [libui-node](https://github.com/parro-it/libui-node), which is used by Vuido.

### Windows

* [windows-build-tools](https://www.npmjs.com/package/windows-build-tools)
* [Visual C++ Redistributable Package for Visual Studio 2013](https://www.microsoft.com/en-us/download/details.aspx?id=40784)

```bash
npm install --global --production windows-build-tools
```

### Linux

If they are not provided by default in your distribution:

* [build-essential](https://packages.ubuntu.com/xenial/build-essential)
* [GTK+ 3](https://packages.ubuntu.com/source/xenial/gtk+3.0)

#### Ubuntu / Debian

```bash
sudo apt install build-essential libgtk-3-dev
```

### OS X

* Xcode

```bash
xcode-select --install
```

## Quick Setup

The easiest way to start using Vuido is to use Vue CLI to create a new project.

In order to use the `vue init` command, you can install the vue-cli package globally:

```bash
npm install --global vue-cli
```

If you prefer to use the new [Vue CLI 3](https://cli.vuejs.org/) instead, you have to install both @vue/cli and @vue/cli-init:

```bash
npm install --global @vue/cli @vue/cli-init
```

Run the following command to create the project (replace `my-project` with the name of your project):

```bash
vue init mimecorg/vuido-webpack-template my-project
```

Enter the directory created by vue-cli and install all dependencies:

```bash
cd my-project
npm install
```

Now you can build and run your application:

```bash
npm run build
npm start
```


# Manual Configuration

This information is intended for advanced users who wish to configure a Vuido application manually. In most cases the automatic [quick setup](/installation#quick-setup) should be enough.

You need to install the [vuido](https://www.npmjs.com/package/vuido) package in order to use Vuido in you application:

```bash
npm install --save vuido
```

In order to use single-file components, you will also need [webpack](https://webpack.js.org/) and [vue-loader](https://vue-loader.vuejs.org/). The configuration is similar to a web application using Vue.js, with some important differences:

* The [vuido-template-compiler](https://www.npmjs.com/package/vuido-template-compiler) must be used instead of the standard vue-template-compiler which is used by vue-loader by default. Use the `compiler` option to pass the Vuido compiler to vue-loader. Note that this option requires vue-loader v15 or newer.
* Set the target option to 'node' to ensure that the compiled script can be run correctly by Node.js.
* Use webpack.ExternalsPlugin to exclude libui-node and other native modules from the bundle.

Example of webpack configuration using Vuido:

{% code title="webpack.config.js" %}

```javascript
const path = require( 'path' );
const webpack = require( 'webpack' );
const VueLoaderPlugin = require( 'vue-loader/lib/plugin' );
const VuidoTemplateCompiler = require( 'vuido-template-compiler' );

module.exports = {
  mode: 'development',
  entry: './src/main.js',
  output: {
    path: path.resolve( __dirname, '../dist' ),
    filename: 'main.js'
  }
  target: 'node',
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compiler: VuidoTemplateCompiler
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: [ '.js', '.vue', '.json' ]
  },
  plugins: [
    new webpack.ExternalsPlugin( 'commonjs', [ 'libui-node' ] ),
    new VueLoaderPlugin()
  ]
};
```

{% endcode %}

You also need to install [babel-core](https://www.npmjs.com/package/babel-core), [babel-loader](https://github.com/babel/babel-loader) and [babel-preset-env](https://www.npmjs.com/package/babel-preset-env).

The basic Babel configuration which compiles the scripts for Node.js v8 looks like this:

{% code title=".babelrc" %}

```javascript
{
  "presets": [
    [ "env", {
      "targets": {
        "node": 8
      },
      "modules": false,
      "useBuiltIns": true
    } ]
  ],
  "comments": false
}
```

{% endcode %}


# Production Builds

You can use a single webpack configuration file to create both development and production builds.

The production builds are optimized and minified. They don't contain code which is only used for debugging. You can use the script built in production mode when [packaging your application](/packaging).

Example of webpack configuration for building a Vuido application in both development and production modes:

```javascript
const path = require( 'path' );
const webpack = require( 'webpack' );
const VueLoaderPlugin = require( 'vue-loader/lib/plugin' );
const VuidoTemplateCompiler = require( 'vuido-template-compiler' );

module.exports = function( { production } = {} ) {
  if ( production )
    process.env.NODE_ENV = 'production';

  const config = {
    mode: production ? 'production' : 'development',
    entry: './src/main.js',
    output: {
      path: path.resolve( __dirname, '../dist' ),
      filename: production ? 'main.min.js' : 'main.js'
    },
    target: 'node',
    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader',
          options: {
            compiler: VuidoTemplateCompiler
          }
        },
        {
          test: /\.js$/,
          loader: 'babel-loader',
          exclude: /node_modules/
        }
      ]
    },
    resolve: {
      extensions: [ '.js', '.vue', '.json' ]
    },
    plugins: [
      new webpack.ExternalsPlugin( 'commonjs', [ 'libui-node' ] ),
      new VueLoaderPlugin()
    ]
  };

  return config;
}

```

By default, webpack will create a development bundle, dist/main.js.

In order to enable the production mode, pass the `production` environment flag, for example:

```bash
webpack --config build/webpack.config.js --env.production
```

This will create a dist/main.min.js bundle optimized for production.

Note that you must use webpack 4 to be able to minify a Vuido application. Vuido uses some ES6 features which are not supported by the version of UglifyJS used by webpack 3. Alternatively, you can use a different minifier which is compatible with ES6.


# Usage

When you create a basic Vuido application using vue-cli (see [installation](/installation)), it contains two files in the source directory:

* main.js - the main script executed when the application is started
* MainWindow\.vue - the main window component

## Main Script

The main script of the application looks like this:

{% code title="main.js" %}

```javascript
import Vue from 'vuido'

import MainWindow from './MainWindow'

const window = new Vue( {
  render: h => h( MainWindow )
} );

window.$start();
```

{% endcode %}

In line 2 you can see that the Vuido module is imported as `Vue`. This is because Vuido can be used just like the standard Vue.js API.

The application starts by creating a root Vue instance in lines 5-7. Each root instance represents a single window of the application. The window is defined in a separate component, so the root instance only requires a render function which delegates the rendering to that component.

The window is created and displayed on the screen by calling `$start()`. This method also starts the main loop of the application, so the window remains visible and responds to user input.

## Window Component

The definition of the MainWindow component looks like this:

{% code title="MainWindow\.vue" %}

```markup
<template>
  <Window title="Example" width="400" height="100" margined v-on:close="exit">
    <Box>
      <Text>Welcome to your Vuido application!</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  methods: {
    exit() {
      this.$exit();
    }
  }
}
</script>
```

{% endcode %}

If you are familiar with Vue.js, you will notice that this is a regular single-file component. It consists of a template, which defines the layout of the window and its properties, and a script which defines the behavior of the window.

In this simple example, the window contains only a single static line of text. When the window is closed by the user, the main loop is stopped and the application exits.

If you haven't used Vue.js before, don't worry. The syntax of the window template and the contents of the script section are explained in details in the following chapters of this documentation.

## Running the Application

You must build your application before running it:

```bash
npm run build
```

This command will create a new script in the `dist/` directory of your application. This script can be run directly using Node.js, or packaged for distribution using LaunchUI (see [packaging](/packaging)).

Use the following command to run the application:

```bash
npm start
```


# Window Template

The template section of the window component describes the layout of the window:

```markup
<template>
  <Window title="Example" width="400" height="100" margined v-on:close="exit">
    <Box>
      <Text>Welcome to your Vuido application!</Text>
    </Box>
  </Window>
</template>
```

The template uses a syntax similar to HTML, but using built-in Vuido components and custom components instead of HTML elements.

The root element of the window template is the [Window](/built-in-components/window) component. It contains some attributes, such as the `title` of the window, its `width` and `height`. The `margined` attribute indicates that the window has a margin around its contents. It's a boolean attribute, so it doesn't need to have a value.

The `v-on` directive is described in the [Handling User Input](/usage/handling-user-input) chapter. In this example, when the user attempts to close the window, the `exit()` method of the component is called.

The child element of the Window is a [Box](/built-in-components/containers/box) container. Since a Window can only contain a single child, it's recommended to use a container to make it possible to add multiple widgets.

Box is the simplest container which aligns its children vertically or horizontally. If you add another Text component to the box, you can see that it's displayed below the first line of text. You can add the `padded` attribute to the box container to add a space between its children. If you add the `horizontal` attribute, the box layout will change from vertical to horizontal.

The [Text](/built-in-components/widgets/text) component is the simplest widget which displays static text. Vuido contains many different [built-in widgets](/built-in-components/widgets) for handling user input and displaying information.

Note that you cannot use styles or CSS classes to change the look of components. Vuido uses the native GUI components of the operating system, so unlike HTML elements, they cannot be styled.

You can nest multiple containers to create more complex layouts. For example, let's add two buttons below the the static text:

```markup
<template>
  <Window title="Example" width="400" height="100" margined v-on:close="exit">
    <Box padded>
      <Text>Welcome to your Vuido application!</Text>
      <Box horizontal padded>
        <Button>OK</Button>
        <Button>Cancel</Button>
      </Box>
    </Box>
  </Window>
</template>
```

The outer box aligns it children vertically, so the static text is displayed above the buttons. The inner box has the `horizontal` attribute, so the two buttons are displayed next to each other.

By default, each widget in a Box container is displayed using its minimum size. You can add the `strechy` attribute to a child widget to tell the Box container to increase the width (in a horizontal layout) or height (in a vertical layout) to fill the available space.

If multiple child widgets have the `stretchy` attribute, the available space is divided equally between them. For example, if you add this attribute to both buttons, each of them will expand to half of the window's width. When you resize the window, the buttons will be resized as well.

The [Form](/built-in-components/containers/form) container is useful if you have a form layout with multiple input fields stacked vertically and captions next to them.

The [Group](/built-in-components/containers/group) container adds a border and caption around its content. It can only contain a single child element, so in most cases you should put a box container inside the group.

Finally, the [Tab](/built-in-components/containers/tab) container can be used to group its child elements into separate tabs.


# Script Section

The script section of the window component describes the behavior of the window. The object exported by the script contains options which are passed to the Vue instance when the window is created. For example:

{% code title="" %}

```markup
<script>
export default {
  data() {
    return {
      counter: 0
    };
  },
  methods: {
    increment() {
      this.counter++;
    },
    decrement() {
      this.counter--;
    }
  }
}
</script>
```

{% endcode %}

The `data()` function returns an object which describes the initial state of the window. Its properties become the properties of the Vue instance. All data properties are reactive, which means that the user interface is automatically updated when the values of these properties are changed.

The `methods` option defines functions which become the methods of the Vue instance. These methods can access and change data properties and call other methods of that instance using the `this` keyword. You can use methods to react to user input and implement the logic of the application.

You can also create special functions, called the lifecycle hooks, which are called when the instance is created, destroyed and updated. For example, you can run some code after an instance is created:

```markup
<script>
export default {
  data() {
    return {
      text: ''
    }
  },
  created() {
    this.text = 'Hello';
  }
}
</script>
```

See also [Instance Lifecycle Hooks](https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks) in the Vue.js documentation for more details.

Other options which can be used in the script section are described in the following chapters of this documentation.


# Interpolations

## Text Interpolation

You can use "mustaches" (double curly braces) inside the template for text interpolation. For example:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box>
      <Text>Hello, {{ name }}</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      name: 'John'
    };
  }
}
</script>
```

This will display "Hello, John" in the [Text](/built-in-components/widgets/text) widget. Thanks to reactivity built into Vue.js, the data is bound to the text of the widget, so when the value of the `name` property is changed, the text is automatically updated.

You can use simple JavaScript expressions inside the mustaches, for example `{{ number + 1 }}`.

The interpolation mechanism can also be used in other widgets which have static labels, for example [Button](/built-in-components/widgets/button) and [Checkbox](/built-in-components/widgets/checkbox).

## Binding Attributes

You can use the `v-bind` directive to bind dynamic values to attributes, for example:

```markup
<template>
  <Window v-bind:title="title" width="400" height="100" margined>
    <Box>
      <Text>Welcome to your Vuido application!</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      title: 'Hello!'
    };
  }
}
</script>
```

The `v-bind` directive binds the data property, or the result of an expression, to the attribute specified after the colon. In this example, the title of the window will be "Hello!". When the value of the `title` property is changed, the title of the window is automatically updated.

The `v-bind` directive can be applied to many different attributes. In case of boolean attributes, the `null`, `undefined` and `false` values are interpreted as false and other values are interpreted as true.

{% hint style="info" %}
Currently, some attributes are static and cannot be modified dynamically. For example, it's not possible to change the Box layout between horizontal and vertical using the `v-bind` directive. This might change in the future versions of Vuido.
{% endhint %}

You can use simple JavaScript expressions in bound attributes, for example:

```markup
<Window v-bind:title="'Hello, ' + name">...</Window>
```

You can also use the shorthand syntax by omitting `v-bind` and prefixing the attribute name with a colon, for example:

```markup
<Window :title="title">...</Window>
```

See also [Interpolations](https://vuejs.org/v2/guide/syntax.html#Interpolations) in the Vue.js documentation for more details.


# Computed Properties

You can use computed properties to calculate values based on data properties:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box>
      <Text>Hello, {{ fullName }}</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Smith'
    };
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName;
    }
  }
}
</script>
```

This creates a `fullName` property which will be automatically calculated based on the `firstName` and `lastName` properties. The example will display "Hello, John Smith" in the [Text](/built-in-components/widgets/text) widget.

The above code can be also written like this:

```markup
<Text>Hello, {{ firstName + ' ' + lastName }}</Text>
```

However, when the expression becomes complex, or is repeated within the template, putting it into a computed property results in simpler and more readable code. Also, the computed property is defined using a regular function, so it can contain more complex code, not just a simple expression.

You can use a computed property just like a regular data property, for example:

```javascript
methods: {
  printName() {
    console.log( this.fullName );
  }
}
```

Thanks to Vue.js reactivity, the value of the computed property will only be recalculated when necessary, in this case when the `firstName` or `lastName` is changed. Because of that, computed properties are more efficient than regular methods.

A computed property can also have a setter:

```javascript
computed: {
  fullName: {
    get() {
      return this.firstName + ' ' + this.lastName;
    },
    set( newValue ) {
      const names = newValue.split( ' ' );
      this.firstName = names[ 0 ];
      this.lastName = names[ names.length - 1 ];
    }
  }
}
```

This way, the base properties are automatically modified when the you assign a value directly to the computed property.

In some cases it's necessary to plug directly into the Vue.js reactivity system, for example to initiate an asynchronous operation when a data property changes. You can declare a watcher to do that:

```javascript
watch: {
  page( oldValue, newValue ) {
    // this function is called when the value of the page property is changed
  }
}
```

See also [Computed Properties and Watchers](https://vuejs.org/v2/guide/computed.html) in the Vue.js documentation for more details.


# Conditionals and Loops

## Conditional Rendering

To render a widget or container only under certain conditions, you can use the `v-if` directive:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box padded>
      <Text>Welcome to your Vuido application!</Text>
      <Text v-if="seen">You can see this</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      seen: true
    };
  }
}
</script>
```

In this example, both Text widgets are displayed because the condition evaluates to true. When the value of the `seen` property is changed to false, the second Text widget is removed from the window.

You can use `v-else-if` and `v-else` directives to create conditions with multiple alternatives:

```markup
<Button v-if="mode == 'button'">This is a button</Button>
<Checkbox v-else-if="mode == 'checkbox'">This is a checkbox</Checkbox>
<Text v-else>This is something else</Text>
```

Note that conditional directives destroy and create the widgets whenever the condition changes. To temporarily hide a widget without destroying it, you can use the [visible](/usage/common-attributes#visible) attribute.

See also [Conditional Rendering](https://vuejs.org/v2/guide/conditional.html) in the Vue.js documentation for more details.

## List Rendering

To render multiple instances of the same component, you can use the `v-for` directive:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box padded>
      <Text v-for="item in items">- {{ item }}</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      items: [ 'apples', 'oranges', 'bananas' ]
    };
  }
}
</script>
```

In this example, three Text widgets are rendered, one for each element of the `items` array. When an item is added or removed from this array, corresponding Text widgets are automatically added or removed.

It's recommended to provide a unique `key` attribute for each item. This way, the state of widgets will be preserved when array items are reordered.

See also [List Rendering](https://vuejs.org/v2/guide/list.html) in the Vue.js documentation for more details.


# Handling User Input

## Event Handling

You can use the `v-on` directive to attach event listeners:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box padded>
      <Text>Counter: {{ counter }}</Text>
      <Button v-on:click="increment">Increment</Button>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      counter: 0
    };
  },
  methods: {
    increment() {
      this.counter++;
    }
  }
}
</script>
```

When the user clicks the button, the `increment()` method is called.

The value of the `v-on` directive can be either the name of a method or an expression, so the above example could also be written as:

```markup
<Button v-on:click="counter++">Increment</Button>
```

Events emitted when the value of an input widgets is changed have an argument which specifies the new value. For example:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box>
      <TextInput v-on:input="print"/>
    </Box>
  </Window>
</template>

<script>
export default {
  methods: {
    print( value ) {
      console.log( 'The new value is: ' + value );
    }
  }
}
</script>
```

You can also use the shorthand syntax by omitting `v-on` and prefixing the attribute name with a `@`, for example:

```markup
<Button @click="increment">...</Button>
```

See also [Event Handling](https://vuejs.org/v2/guide/events.html) in the Vue.js documentation for more details.

## Input Binding

You can use the `v-model` directive to create a two-way binding between a data property and an input widget:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Box padded>
      <TextInput v-model="text"/>
      <Text>{{ text }}</Text>
    </Box>
  </Window>
</template>

<script>
export default {
  data() {
    return {
      text: 'Edit me'
    };
  }
}
</script>
```

When the user edits the text in the [TextInput](/built-in-components/widgets/textinput) widget, the value of the `text` property is automatically updated. When the `text` property in changed by code, the input widget is also updated.

The `v-model` directive is actually just a shorthand syntax for an attribute binding and event handling. The example could also be written as:

```markup
<TextInput v-bind:value="text" v-on:input="text = $event"/>
```

The `v-model` directive can be used with many different input widgets, including [TextInput](/built-in-components/widgets/textinput), [TextArea](/built-in-components/widgets/textarea), [Combobox](/built-in-components/widgets/combobox), [ColorButton](/built-in-components/widgets/colorbutton), [Slider](/built-in-components/widgets/slider), [Spinbox](/built-in-components/widgets/spinbox), [Checkbox](/built-in-components/widgets/checkbox), [RadioButtons](/built-in-components/widgets/radiobuttons) and [DropdownList](/built-in-components/widgets/dropdownlist). In case of a Checkbox, the value of the property is either `true` or `false`. In case of RadioButtons and DropdownList, the value is the index of the selected radio button or item.

The `v-model` directive can also be used with [custom components](/usage/custom-components#custom-events).

See also [Form Input Bindings](https://vuejs.org/v2/guide/forms.html) in the Vue.js documentation for more details.


# Managing Windows

## Starting the Application

To start the application, you should create a root Vue component representing a window and call `$start()`. This will display the window and start the main loop of the application:

```javascript
const window = new Vue( {
  render: h => h( MainWindow )
} );

window.$start();
```

## Exiting the Application

To exit the application, call the `$exit()` method. This will stop the main loop of the application. Typically, this is done in response to the close event:

```markup
<template>
  <Window title="Example" width="400" height="100" margined v-on:close="exit">
    ...
  </Window>
</template>

<script>
export default {
  methods: {
    exit() {
      this.$exit();
    }
  }
}
</script>
```

Note that `$exit()` automatically closes all open windows and destroys all root Vue components associated with them.

## Creating Additional Windows

Your application can consist of multiple windows. To create and display another window, create a separate root Vue component and call `$mount()` without any parameters:

{% code title="" %}

```javascript
const logWindow = new Vue( {
  render: h => h( LogWindow )
} );

logWindow.$mount();
```

{% endcode %}

Note that the `$start()` method automatically calls `$mount()` if it hasn't been called. However, if you need to display more than one window, you should use `$mount()` to display them.

## Destroying a Window

To close a window without exiting the application, call `$destroy()` on the root Vue component corresponding to that window:

```markup
<template>
  <Window title="Example" width="400" height="100" margined v-on:close="close">
    ...
  </Window>
</template>

<script>
export default {
  methods: {
    close() {
      this.$root.$destroy();
    }
  }
}
</script>
```

The root component can be accessed using the `$root` property which is part of the Vue.js API.

Note that the application will keep running in the background, even if you destroy all windows. To exit the application, call the `$exit()` method instead.


# Displaying Dialogs

## Message Boxes

You can use the `$dialogs.msgBox()` method to display a simple message box with an OK button. The first parameter is the title of the dialog and the second parameter is the message text. For example:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Button v-on:click="showMessage">Show Message</Button>
  </Window>
</template>

<script>
export default {
  methods: {
    showMessage() {
      this.$dialogs.msgBox( 'Title', 'This is the message.' );
    }
  }
}
</script>
```

You can also use the `$dialogs.msgBoxError()` method to display an error message. It has the same parameters as `msgBox()`.

## File Dialogs

You can use the `$dialogs.openFile()` method to allow the user to select an existing file or `$dialogs.saveFile()` to prompt for a new file to be created or overwritten. Both these methods return the path of the selected file or null if the user cancelled the operation. For example:

```markup
<template>
  <Window title="Example" width="400" height="100" margined>
    <Button v-on:click="openFile">Open File</Button>
  </Window>
</template>

<script>
export default {
  methods: {
    openFile() {
      const filePath = this.$dialogs.openFile();
      if ( filePath != null ) {
        // do something...
      }
    }
  }
}
</script>
```


# Custom Components

## Child Components

In simple applications, the window consists of just one component. However, when the window becomes complex, it may be a good idea to split it into a few separate child components. For example:

```markup
<template>
  <Window title="Example" width="640" height="480" margined>
    <Box padded>
      <WindowHeader/>
      <WindowFooter/>
    </Box>
  </Window>
</template>

<script>
import WindowHeader from './WindowHeader'
import WindowFooter from './WindowFooter'

export default {
  components: {
    WindowHeader,
    WindowFooter
  }
}
</script>
```

This creates a window component which contains two child components, one under another.

The child components must be imported and declared using the `components` option of the parent component. Custom components declared like this can be used just like built-in components.

The root element of a child component can be a container, or even a single widget. For example:

```markup
<template>
  <Box padded>
    <Button>OK</Button>
    <Button>Cancel</Button>
  </Box>
</template>
```

## Component Registration

Some components are used in many different places in the application, for example in different windows. Instead of importing them into every parent component that needs to use them, you can declare a global component.

This can be done by calling `Vue.component()` in the main script of the application:

{% code title="main.js" %}

```javascript
import libui from 'libui-node'
import Vue from 'vuido'

import ButtonGroup from './ButtonGroup'
import MainWindow from './MainWindow'

Vue.component( 'ButtonGroup', ButtonGroup );

const window = new Vue( {
  render: h => h( MainWindow )
} );

window.$mount();

libui.startLoop();
```

{% endcode %}

Now you can place the custom ButtonGroup component inside any other component.

See also [Component Registration](https://vuejs.org/v2/guide/components-registration.html) in the Vue.js documentation for more information.

## Properties

You can use properties to pass data from the parent component to the child component. For example, let's define a custom component like this:

{% code title="ButtonGroup.vue" %}

```markup
<template>
  <Box padded>
    <Button>{{ okText }}</Button>
    <Button>{{ cancelText }}</Button>
  </Box>
</template>

<script>
export default {
  props: {
    okText: String,
    cancelText: String
  }
}
</script>
```

{% endcode %}

The `props` section specifies that this component has two properties, `okText` and `cancelText`, and their values must be strings. You can use other JavaScript types, like `Boolean`, `Numeric`, `Array` or `Object` to validate the property.

Now you can use the ButtonGroup component like this:

```markup
<ButtonGroup ok-text="OK" cancel-text="Cancel"/>
```

Note that the kebab-cased names of attributes are mapped to the corresponding camelCased names of properties.

A property can have a default value:

```javascript
props: {
  okText: { type: String, default: 'OK' },
  cancelText: { type: String, default: 'Cancel' }
}
```

It also can be marked as required:

```javascript
props: {
  items: { type: Array, required: true }
}
```

You can pass a dynamic value to a property using `v-bind`:

```markup
<ButtonGroup v-bind:ok-text="okText" v-bind:cancel-text="cancelText"/>
```

When using a boolean or numeric property, you must use the `v-bind` directive even if you pass a constant value. Otherwise the value would be interpreted as a string. For example:

```markup
<BlogPost v-bind:likes="42" v-bind:is-published="true"/>
```

You can also omit the value to pass `true` to a boolean property:

```markup
<BlogPost is-published/>
```

See also [Props](https://vuejs.org/v2/guide/components-props.html) in the Vue.js documentation for more information.

## Custom Events

Child components can use custom events to notify their parent:

{% code title="ButtonGroup.vue" %}

```markup
<template>
  <Box padded>
    <Button v-on:click="okClick">OK</Button>
    <Button v-on:click="cancelClick">Cancel</Button>
  </Box>
</template>

<script>
export default {
  methods: {
    okClick() {
      this.$emit( 'ok-click' );
    },
    cancelClick() {
      this.$emit( 'cancel-click' );
    }
  }
}
</script>
```

{% endcode %}

The parent component can listen to these events using the `v-on` directive:

```markup
<ButtonGroup v-on:ok-click="accept" v-on:cancel-click="reject"/>
```

You can also use events to pass data to the parent component:

{% code title="NameInput.vue" %}

```markup
<template>
  <Box>
    <Text>Enter your name:</Text>
    <TextInput v-bind:value="value" v-on:input="emitInput"/>
  <Box>
</template>

<script>
export default {
  props: {
    value: String
  },
  methods: {
    emitInput( newValue ) {
      this.$emit( 'input', newValue );
    }
  }
}
</script>
```

{% endcode %}

The parent component can use the following code to update the value of its data property:

```markup
<NameInput v-bind:value="name" v-on:input="name = $event"/>
```

Note that the child component cannot simply modify the `value` property, because that will not automatically update the data in the parent component.

The `v-model` directive can also be used with custom components. By default, it binds the `value` property and the `input` event to the specified property of the parent component, so the above code is equivalent to:

```markup
<NameInput v-model="name"/>
```

When your window contains a complex hierarchy of custom components, passing data around using properties and events may become difficult to manage. In such case consider using a state management library, such as [Vuex](https://vuex.vuejs.org/).

See also [Custom Events](https://vuejs.org/v2/guide/components-custom-events.html) in the Vue.js documentation for more information.

## Slots

You can use slots to pass contents from the parent component to a child component. For example, let's assume that we have this simple child component:

{% code title="NavigationButton.vue" %}

```markup
<template>
  <Button v-on:click="navigate">
    <slot></slot>
  <Button>
<template>
```

{% endcode %}

We can use it like this:

```markup
<NavigationButton>About</NavigationButton>
```

The "About" text is inserted in place of the `<slot>` element. The slot contents can include not just text, but also other elements, including built-in components and custom components.

See also [Slots](https://vuejs.org/v2/guide/components-slots.html) in the Vue.js documentation for more information.

## Dynamic Components

The special `<component>` element can be used to dynamically switch between components. For example, you can replace the entire contents of a window without having to close it and create a new window:

```markup
<template>
  <Window title="Example" width="640" height="480" margined>
    <component v-bind:is="currentComponent"/>
  </Window>
</template>
```

The `currentComponent` property can contain either the name of a registered component, or the options object which defines a component.

See also [Dynamic Components](https://vuejs.org/v2/guide/components.html#Dynamic-Components) in the Vue.js documentation for more information.


# Using libui Classes

In most cases you don't have to use the libui library directly, because Vuido provides its own API and components to interface with that library.

However, there are situations where you have to directly use some classes from the libui library. You can import it in the following way:

```javascript
import libui from 'libui-node'

const path = new libui.UiDrawPath( libui.fillMode.winding );
```

Alternatively, you can use the `$libui` property available in all Vuido components:

```javascript
const path = new this.$libui.UiDrawPath( this.$libui.fillMode.winding );
```

{% hint style="info" %}
For more information, see the [libui-node documentation](https://github.com/parro-it/libui-node/tree/master/docs).
{% endhint %}


# Common Attributes

## Widget Attributes

The following attributes are shared by all widgets and containers.

### enabled

type: Boolean

Whether the widget is enabled or disabled.

### visible

type: Boolean

Whether the widget is visible or hidden.

## Child Attributes

The following attributes can be added to child components to change the way they are handled by the parent container.

### label

type: String

The caption displayed next to the child component in a [Form](/built-in-components/containers/form) container or the caption displayed on the tab in the [Tab](/built-in-components/containers/tab) container.

### stretchy

type: Boolean

Whether the child stretches to fill available space. It applies to the children of the [Box](/built-in-components/containers/box) and [Form](/built-in-components/containers/form) containers.


# Packaging

Although native desktop applications can run in the standard Node.js environment, it is recommended to use [LaunchUI](https://github.com/mimecorg/launchui) to package and distribute them to end users.

Thanks to LaunchUI, users don't need to install any packages using npm or to use the command line. They don't even need to have Node.js installed. They can simply download the package, unzip it and run the application by double-clicking its icon.

LaunchUI wraps Node.js with a small executable which automatically runs the application. No console window is opened and in case of a fatal error, it is reported using a message box.

The easiest way to create a package for your application is to use the [LaunchUI Packager](https://github.com/mimecorg/launchui-packager). It provides an API for creating packages for Windows, Linux and OS X.

You can also use [LaunchUI Packager GUI](https://github.com/mimecorg/launchui-packager-gui), a desktop application which simplifies creating LaunchUI packages without using custom scripts.

To manually package your application, download the binary package for your target platform from [LaunchUI releases](https://github.com/mimecorg/launchui/releases), unpack it and replace the example `app/main.js` script with your application script.


# Built-in Components

The following built-in components are available:

* [Window](/built-in-components/window) - the root component which represents a single window
* [Containers](/built-in-components/containers) - components which can contain other widgets
* [Widgets](/built-in-components/widgets) - components for handling user input and displaying information


# Window

The root of the Vue.js application must be a Window component which represents a single window.

The window must contain exactly one child widget, typically a container.

## Attributes

### title

type: String

The title of the window.

### width

type: Number

The width of the window content.

### height

type: Number

The height of the window content.

### margined

type: Boolean

Whether the window adds a margin around its content.

### menu

type: Boolean

Whether the window has a menu.

### fullscreen

type: Boolean

Whether the window is displayed in full screen mode.

### borderless

type: Boolean

Whether the window is displayed without the border and title bar.

## Events

### close

Called when the close button is clicked. To exit the application, call `this.$exit()`. To close the window without exiting the application, call `this.$root.$destroy()`.

### show

Called when the window is about to be shown. Unlike the `mounted()` life-cycle hook, at this point all widgets are already initialized.

### resize

Called when the size of the window is changed. The current size is passed as an argument. It's an object containing `w` and `h` properties representing the width and height.

## Properties

### window

type: libui.UiWindow

This property of the Window component returns the associated libui.UiWindow object.

## Example

```markup
<Window title="Vuido Example" width="400" height="100" margined v-on:close="exit">
  <Box padded>
    ...
  </Box>
</Window>
```


# Containers

The following built-in container components are available:

* [Box](/built-in-components/containers/box) - arranges all children vertically or horizontally
* [Form](/built-in-components/containers/form) - arranges its children vertically, with captions next to them
* [Group](/built-in-components/containers/group) - provides a border with a caption around its content
* [Tab](/built-in-components/containers/tab) - shows each child widget in a separate tab


# Box

A container which arranges all children vertically or horizontally.

## Attributes

### horizontal

type: Boolean

Whether the box arranges its children vertically or horizontally.

### padded

type: Boolean

Whether the box adds some padding between its children.

## Child Attributes

The following attributes can be added to child components to change the way they are handled by the box container.

### stretchy

type: Boolean

Whether the child stretches to fill available space.

## Example

```markup
<Box horizontal padded>
  <Button v-on:click="ok">OK</Button>
  <Button v-on:click="cancel">Cancel</Button>
</Box>
```


# Form

A container which arranges its children vertically, with captions next to them.

## Attributes

### padded

type: Boolean

Whether the form adds some padding between its children.

## Child Attributes

The following attributes can be added to child components to change the way they are handled by the form container.

### label

type: String

The caption displayed next to the child component.

### stretchy

type: Boolean

Whether the child stretches to fill available space.

## Example

```markup
<Form padded>
  <TextInput label="First name:" v-model="firstName"/>
  <TextInput label="Last name:" v-model="lastName"/>
</Form>
```


# Group

A container which provides a border with a caption around its content.

The group container must contain exactly one child widget, typically another container.

## Attributes

### margined

type: Boolean

Whether the group adds a margin around its content.

### title

type: String

The caption displayed on the group border.

## Example

```markup
<Group title="Group" margined>
  <Box padded>
    ...
  </Box>
</Group>
```


# Tab

A container that shows each child widget in a separate tab.

The tab container can contain one or more children, typically other containers.

## Attributes

### margined

type: Boolean

Whether the tab container adds a margin around the content of each tab.

## Child Attributes

The following attributes can be added to child components to change the way they are handled by the tab container.

### label

type: String

The caption displayed on the tab.

## Example

```markup
<Tab margined>
  <Box label="Tab 1" padded>
    ...
  </Box>
  <Box label="Tab 2" padded>
    ...
  </Box>
  <Box label="Tab 3" padded>
    ...
  </Box>
</Tab>
```


# Widgets

The following built-in widget components are available:

* [Area](/built-in-components/widgets/area) - a custom drawn widget
* [Button](/built-in-components/widgets/button) - a simple button widget
* [Checkbox](/built-in-components/widgets/checkbox) - a checkbox widget
* [ColorButton](/built-in-components/widgets/colorbutton) - a button that opens a color selector dialog
* [DatePicker](/built-in-components/widgets/datepicker) - a widget for selecting a date
* [DateTimePicker](/built-in-components/widgets/datetimepicker) - a widget for selecting a date and time
* [DropdownList](/built-in-components/widgets/dropdownlist) - a widget for selecting a value from a drop-down list
* [FontButton](/built-in-components/widgets/fontbutton) - a button that opens a font selector dialog
* [ProgressBar](/built-in-components/widgets/progressbar) - a progress bar widget
* [RadioButtons](/built-in-components/widgets/radiobuttons) -  a widget that represent a group of radio buttons
* [Separator](/built-in-components/widgets/separator) - a horizontal or vertical line to visually separate widgets
* [Slider](/built-in-components/widgets/slider) - a horizontal slider for editing numeric values
* [Spinbox](/built-in-components/widgets/spinbox) - an input widget for editing numeric values
* [Text](/built-in-components/widgets/text) - static widget which displays simple text
* [TextArea](/built-in-components/widgets/textarea) - an input widget for editing multiple lines of text
* [TextInput](/built-in-components/widgets/textinput) - an input widget for editing a single line of text
* [TimePicker](/built-in-components/widgets/timepicker) - a widget for selecting a time


# Area

A custom drawn widget which provides an API for drawing 2D graphics. It can have scroll bars and it can handle mouse and keyboard input.

The area widget can contain the following child components:

* [AreaGroup](/built-in-components/widgets/area/areagroup) - a group containing other components
* [AreaPath](/built-in-components/widgets/area/areapath) - a stroked and/or filled path
* [AreaText](/built-in-components/widgets/area/areatext) - a paragraph of text with formatting

## Attributes

### scrollable

type: Boolean

Whether the area has a horizontal and vertical scrollbar.

### width

type: Number

The width of the scrollable area.

### height

type: Number

The height of the scrollable area.

## Events

### draw

Emitted when the widget needs to be redrawn. The argument of this event is a [libui.UiAreaDrawParams](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uiareadrawparams) object. You can retrieve the drawing context by calling `params.getContext()`.

### mousedown

Emitted when a mouse button is pressed over the widget. The argument of this event is a [libui.UiAreaMouseEvent](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uiareamouseevent) object.

### mouseup

Emitted when a mouse button is released. The argument of this event is a [libui.UiAreaMouseEvent](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uiareamouseevent) object.

### mousemove

Emitted when the mouse pointer moves over the widget. The argument of this event is a [libui.UiAreaMouseEvent](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uiareamouseevent) object.

### mouseenter

Emitted when the mouse pointer enters the widget.

### mouseleave

Emitted when the mouse pointer leaves the widget.

### dragbroken

Emitted when the window is deactivated during a drag operation. Only implemented on Windows.

### keydown

Emitted when a key was pressed. The argument of this event is a [libui.UiAreaKeyEvent](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uiareakeyevent) object. The event handler should return `true` to indicate that the key event was handled.

### keyup

Emitted when a key was released. The argument of this event is a [libui.UiAreaKeyEvent](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uiareakeyevent) object. The event handler should return `true` to indicate that the key event was handled.

## Example

```markup
<Area v-on:mousedown="mouseDown" v-on:mouseup="mouseUp">
  <AreaPath v-bind:path="circlePath" v-bind:fill="redBrush"/>
</Area>
```


# AreaGroup

A group containing other components, including nested groups, AreaPath and AreaText components. It can define a transformation and a default fill and stroke brush for its children.

## Attributes

### transform

type: [libui.UiDrawMatrix](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uidrawmatrix)

A transformation applied to child components.

### fill

type: [libui.DrawBrush](https://github.com/parro-it/libui-node/blob/master/docs/area.md#drawbrush)

The default fill brush for child components.

### stroke

type: [libui.DrawBrush](https://github.com/parro-it/libui-node/blob/master/docs/area.md#drawbrush)

The default stroke brush for child components.

### line

type: [libui.DrawStrokeParams](https://github.com/parro-it/libui-node/blob/master/docs/area.md#drawstrokeparams)

The default style of line for child components.

## Example

```markup
<Area>
  <AreaGroup v-bind:fill="redBrush"/>
    <AreaPath v-bind:path="circlePath"/>
    <AreaPath v-bind:path="squarePath"/>
  </AreaGroup>    
</Area>
```


# AreaPath

A stroked and/or filled path.

## Attributes

### path

type: [libui.UiDrawPath](https://github.com/parro-it/libui-node/blob/master/docs/area.md#uidrawpath)

The path to be stroked and/or filled.

### fill

type: [libui.DrawBrush](https://github.com/parro-it/libui-node/blob/master/docs/area.md#drawbrush)

The fill brush. By default it is inherited by the parent [AreaGroup](/built-in-components/widgets/area/areagroup). If not specified, the path is not filled.

### stroke

type: [libui.DrawBrush](https://github.com/parro-it/libui-node/blob/master/docs/area.md#drawbrush)

The stroke brush. By default it is inherited by the parent [AreaGroup](/built-in-components/widgets/area/areagroup). If not specified, the path is not stroked.

### line

type: [libui.DrawStrokeParams](https://github.com/parro-it/libui-node/blob/master/docs/area.md#drawstrokeparams)

The style of line for the stroke. By default it is inherited by the parent [AreaGroup](/built-in-components/widgets/area/areagroup). If not specified, a solid one-pixel line is used.

## Example

```markup
<template>
  <Area>
    <AreaPath v-bind:path="circlePath" v-bind:fill="redBrush"/>
  </Area>
</template>

<script>
import libui from 'libui-node'

export default {
  computed: {
    cicrlePath() {
      const path = new libui.UiDrawPath( libui.fillMode.winding );
      path.newFigureWithArc( 100, 100, 50, 0, Math.PI * 2, false );
      path.end();
      return path;
    },
    redBrush() {
      const brush = new libui.DrawBrush();
      brush.color = new libui.Color( 1, 0, 0, 1 );
      brush.type = libui.brushType.solid;
      return brush;
    }
  }
}
</script>
```


# AreaText

A paragraph of text with formatting.

## Attributes

### x

type: Number

The horizontal position of the text.

### y

type: Number

The vertical position of the text.

### layout

type: [libui.DrawTextLayout](https://github.com/parro-it/libui-node/blob/master/docs/attributedstring.md#drawtextlayout)

The content and layout of the text paragraph.

## Example

```markup
<template>
  <Area>
    <AreaText x="100" y="100" v-bind:layout="textLayout"/>
  </Area>
</template>

<script>
import libui from 'libui-node'

export default {
  computed: {
    textLayout() {
      const str = new libui.AttributedString( 'Hello, world!' );
      const font = new libui.FontDescriptor( 'Arial', 10, libui.textWeight.normal,
        libui.textItalic.normal, libui.textStretch.normal );
      return new libui.DrawTextLayout( str, font, 200, libui.textAlign.left );
    }
  }
}
</script>
```


# Button

A simple button widget.

## Events

### click

Called when the button is clicked.

## Example

```markup
<Button v-on:click="ok">OK</Button>
```


# Checkbox

A checkbox widget.

Checkbox supports the `v-model` directive.

## Attributes

### checked

type: Boolean

Whether the checkbox is checked or unchecked.

## Events

### toggle

Emitted when the checkbox checked state is toggled.

## Example

```markup
<Checkbox v-model="checkboxState">Checkbox label</Checkbox>
```


# ColorButton

A button that opens a color selector dialog.

ColorButton supports the `v-model` directive.

## Attributes

### value

type: { r: Number, g: Number, b: Number, a: Number }

The currently selected color. The value is an object containing four numeric properties which represent the red, green, blue and alpha components in the range from 0 to 1.

## Events

### change

Emitted when the selected color is changed. The current color is passed as an argument.

## Example

```markup
<ColorButton v-model="color"/>
```


# Combobox

An input widget for editing text with a drop-down list.

Combobox supports the `v-model` directive.

## Attributes

### items

type: Array

An array of strings representing the available options.

### value

type: String

The current text displayed in the widget.

## Events

### input

Called when the text is changed. The current text is passed as an argument.

## Example

```markup
<Combobox v-bind:items="[ 'Option 1', 'Option 2', 'Option 3' ]" v-model="text"/>
```


# DatePicker

A widget for selecting a date.

{% hint style="warning" %}
Currently DatePicker is not fully implemented.
{% endhint %}

## Example

```markup
<DatePicker/>
```


# DateTimePicker

A widget for selecting a date and time.

{% hint style="warning" %}
Currently DateTimePicker is not fully implemented.
{% endhint %}

## Example

```markup
<DateTimePicker/>
```


# DropdownList

A widget for selecting a value from a drop-down list.

DropdownList supports the `v-model` directive.

## Attributes

### items

type: Array

An array of strings representing the available options.

### selected

type: Number

The index of the currently selected option.

## Events

### change

Emitted when the selected option is changed. The current index is passed as an argument.

## Example

```markup
<DropdownList v-bind:items="[ 'Option 1', 'Option 2', 'Option 3' ]"
              v-model="selected"/>
```


# FontButton

A button that opens a font selector dialog.

{% hint style="warning" %}
Currently it is not possible to select the font programmatically. The default selected font is platform specific.
{% endhint %}

## Properties

### font

type: libui.FontDescriptor

A read-only property of the FontButton element which returns information about the currently selected font. The returned object has the following methods:

* getFamily() - return the font family
* getSize() - return the font size
* getWeight() - return the font weight
* getItalic() - return the italic style
* getStretch() - return the font stretch

{% hint style="info" %}
For more information, see the [libui-node documentation](https://github.com/parro-it/libui-node/blob/master/docs/attributedstring.md#fontdescriptor).
{% endhint %}

## Events

### change

Emitted when the selected font is changed. The current font descriptor is passed as an argument.

## Example

```markup
<FontButton v-on:change="onFontChange"/>
```


# ProgressBar

A progress bar widget.

## Attributes

### value

type: Number

The current position of the progress bar in the range from 0 to 100.

Set the value to -1 to indicate and indeterminate progress. This is useful when the exact progress is unknown but you wish to indicate that progress is being made.

## Example

```markup
<ProgressBar v-bind:value="progress"/>
```


# RadioButtons

&#x20;A widget that represent a group of radio buttons.

The RadioButtons widget supports the `v-model` directive.

## Attributes

### items

type: Array

An array of strings representing the available options. The array must contain at least one element.

### selected

type: Number

The index of the currently selected radio button.

## Events

### change

Emitted when the selected radio button is changed. The current index is passed as an argument.

## Example

```markup
<RadioButtons v-bind:items="[ 'Option 1', 'Option 2', 'Option 3' ]"
              v-model="selected"/>
```


# Separator

A horizontal or vertical line to visually separate widgets.

## Attributes

### horizontal

type: Boolean

Whether the separator is vertical or horizontal.

## Example

```markup
<Separator horizontal/>
```


# Slider

A horizontal slider for editing numeric values.

Slider supports the `v-model` directive.

## Attributes

### min

type: Number

The minimum value of the slider.

### max

type: Number

The maximum value of the slider.

### value

type: Number

The current value of the slider.

## Events

### change

Emitted when the current value is changed. The current value is passed as an argument.

## Example

```markup
<Slider min="0" max="100" v-model="slider"/>
```


# Spinbox

An input widget for editing numeric values.

Spinbox supports the `v-model` directive.

## Attributes

### min

type: Number

The minimum value of the spin box.

### max

type: Number

The maximum value of the spin box.

### value

type: Number

The current value of the spin box.

## Events

### change

Emitted when the current value is changed. The current value is passed as an argument.

## Example

```markup
<Spinbox min="0" max="100" v-model="spinbox"/>
```


# Text

Static widget which displays simple text.

## Example

```markup
<Text>Hello, world!</Text>
```


# TextArea

An input widget for editing multiple lines of text.

TextArea supports the `v-model` directive.

{% hint style="info" %}
TextArea uses the `\n` character as the line separator, regardless of the platform on which the application runs.
{% endhint %}

## Attributes

### readonly

type: Boolean

Whether the widget is read-only or editable.

### value

type: String

The current text displayed in the widget.

## Events

### input

Called when the text is changed. The current text is passed as an argument.

## Example

```markup
<TextArea v-model="text"/>
```


# TextInput

An input widget for editing a single line of text.

TextInput supports the `v-model` directive.

## Attributes

### readonly

type: Boolean

Whether the widget is read-only or editable.

### type

type: String

One of: `text`, `password` or `search`. The default type is `text`.

### value

type: String

The current text displayed in the widget.

## Events

### input

Called when the text is changed. The current text is passed as an argument.

## Example

```markup
<TextInput v-model="text"/>
```


# TimePicker

A widget for selecting a time.

{% hint style="warning" %}
Currently TimePicker is not fully implemented.
{% endhint %}

## Example

```markup
<TimePicker />
```


