# Escrever um componente do Flow: um ficheiro HTML

> Um componente do Flow é um único ficheiro HTML com uma parte Node.js, um formulário de definições e um design. Construa um que altere o texto de uma mensagem, conheça as partes do ficheiro e como o testar.

Framework: flow
Product: Flow (flow@11.1)
Language: pt
Content-SHA256: 53b56a87015dfa5767040691132283b05dbe9e752b869090a08c7a5aa8649f2f
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: 
Review: not-recorded

Um componente é **um ficheiro `.html`**. O Flow lê o ficheiro, executa a sua parte Node.js dentro do fluxo e mostra o seu design no editor. Os componentes oficiais de [o repositório](/en/flow/the-components-repository/) usam todos este formato, por isso pode ler qualquer um como exemplo.

## Um exemplo: `shout.html`

Recebe uma mensagem, converte o texto para maiúsculas, acrescenta um sufixo e envia-a.

```html
<script total>

	exports.id = 'shout';
	exports.name = 'Shout';
	exports.group = 'Common';
	exports.version = '1';
	exports.icon = 'ti ti-speakerphone';
	exports.author = 'Forge';
	exports.config = { suffix: '!' };
	exports.inputs = [{ id: 'input', name: 'Input' }];
	exports.outputs = [{ id: 'output', name: 'Output' }];

	exports.make = function(instance, config) {

		let count = 0;

		instance.message = function($) {
			count++;
			instance.status({ shouted: count });
			$.data = String($.data).toUpperCase() + config.suffix;
			$.send('output');
		};

	};

</script>

<settings>
	<div class="padding">
		<ui-component name="input" path="?.suffix" config="maxlength:10">Suffix</ui-component>
	</div>
</settings>

<readme>
The component converts the text of a message to upper case and adds a suffix.
</readme>

<body>
	<header>
		<i class="ICON"></i>NAME
	</header>
	<footer>
		<div class="padding">Shouted: <b><ui-bind path="STATUS.shouted" config="text:value||0"></ui-bind></b></div>
	</footer>
</body>
```

## As partes do ficheiro

| Parte | Para que serve |
|---|---|
| `<script total>` | o código Node.js do componente, executado no processo do fluxo |
| `<settings>` | o formulário de configuração, com os componentes da interface de utilizador (`ui-component`, os caminhos que começam por `?.` apontam para o `config` do componente) |
| `<readme>` | a ajuda mostrada no editor |
| `<body>` | a caixa no diagrama: um `<header>` com os marcadores `ICON` e `NAME`, e opcionalmente um `<footer>` ou um corpo, onde `<ui-bind path="STATUS.x">` mostra o estado e `CONFIG.x` a configuração |
| `<style>` | o CSS da caixa; `.CLASS` é substituído por uma classe única do componente |
| `<script>` (segundo) | JavaScript opcional do editor, para botões na caixa (pode enviar `{ TYPE: 'trigger', id: ... }` ao fluxo) |

## Os `exports` da parte Node.js

| Export | Significado |
|---|---|
| `id`, `name`, `group`, `version`, `icon`, `author` | a identidade do componente e onde aparece na lista |
| `config` | a configuração predefinida; o formulário de `<settings>` edita-a |
| `inputs`, `outputs` | a lista de conectores `{ id, name }`. Um componente sem `inputs` é uma fonte |
| `kind` | opcional: o papel do componente no catálogo (`trigger`, `action` ou `output`) |
| `make(instance, config)` | chamado uma vez por cada caixa que coloca no diagrama |

## A `instance`

Dentro de `make` define o comportamento atribuindo funções à instância:

| Função | Chamada quando |
|---|---|
| `instance.message = function($) {}` | chega uma mensagem. `$.data` são os dados, `$.send('output')` reencaminha-os para os conectores dessa saída, `$.destroy()` termina-a sem enviar |
| `instance.configure = function() {}` | a configuração muda, e uma vez no início |
| `instance.trigger = function() {}` | o botão do editor ou o código o pede |
| `instance.pause = function(is) {}` | o fluxo é pausado ou retomado |
| `instance.close = function() {}` | a caixa é removida ou o fluxo pára: limpe aqui os seus temporizadores |

E chama `instance.send('output', data)` para criar uma mensagem sua (como faz `timer`), `instance.status(object)` para mostrar um estado na caixa (`delay.html` passa um tempo em milissegundos como segundo argumento para o atualizar) e `instance.throw(error)` para comunicar um erro.

## Experimente

1. Ponha `shout.html` num catálogo e escreva o seu endereço na definição `components2` (veja [o repositório](/en/flow/the-components-repository/)), ou importe um fluxo que o contenha nos seus `components`.
2. Acrescente ao lado um `timer` e um `print` no editor, ligue-os e inicie o fluxo.
3. Abra o estado da caixa: o contador cresce com cada mensagem.

Para testar um componente sem o editor, o repositório tem um pequeno tester, veja [o repositório de componentes](/en/flow/the-components-repository/).
