> ## Documentation Index
> Fetch the complete documentation index at: https://documentacao.legitimuz.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vue

> Monte o widget num app Vue 3 com um composable que monta no onMounted e limpa no onUnmounted.

Ao final deste guia o fluxo de verificação abre num app Vue 3, com o ciclo de vida do widget preso
ao do componente.

## Pré-requisitos

* Node.js 20 ou superior.
* Uma `sdkUrl` emitida pelo seu backend, como no [passo 6](/setup/integrate).

## Monte o fluxo

<Steps>
  <Step title="Carregue o SDK">
    ```html title="index.html" theme={null}
    <script src="https://sdk.legitimuz.com/v1/websdk.js"></script>
    ```

    Antes do bundle. O script registra `window.Legitimuz`.
  </Step>

  <Step title="Declare o global">
    O build de CDN não traz tipos. Reaproveite a declaração do
    [guia de React](/frameworks/react) — ela é a mesma, e espelha
    `packages/websdk/src/types.ts`.
  </Step>

  <Step title="Escreva o composable">
    ```ts title="src/useLegitimuz.ts" theme={null}
    import { onMounted, onUnmounted, ref } from "vue";
    import type { LegitimuzWidgetHandle, MountOptions } from "./legitimuz";

    export type UseLegitimuzOptions = Omit<MountOptions, "target">;

    export function useLegitimuz(options: UseLegitimuzOptions) {
      const containerRef = ref<HTMLDivElement | null>(null);
      let handle: LegitimuzWidgetHandle | null = null;

      onMounted(() => {
        if (!containerRef.value) return;
        handle = window.Legitimuz.mount({ ...options, target: containerRef.value });
      });

      onUnmounted(() => handle?.destroy());

      return containerRef;
    }
    ```

    Mesma disciplina do hook React: uma montagem por `sdkUrl`, e `destroy()` no desmonte para
    encerrar a stream de câmera.
  </Step>

  <Step title="Use no componente">
    ```vue title="src/VerificationWidget.vue" theme={null}
    <script setup lang="ts">
    import { ref } from "vue";
    import { useLegitimuz } from "./useLegitimuz";
    import type { WebSdkCompleteResult, WebSdkError, WebSdkEvent } from "./legitimuz";

    const props = defineProps<{ sdkUrl: string }>();

    const log = ref<string[]>([]);
    const push = (text: string) => log.value.push(text);

    const containerRef = useLegitimuz({
      sdkUrl: props.sdkUrl,
      onReady: () => push("ready"),
      onEvent: (event: WebSdkEvent) => push(`event: ${event.type}`),
      // "o fluxo terminou", não "deu certo": status é "submitted" ou "abandoned"
      onComplete: (result: WebSdkCompleteResult) => push(`complete: ${result.status}`),
      onCancel: () => push("cancelled"),
      onError: (error: WebSdkError) => push(`error ${error.code}: ${error.user_message}`),
    });
    </script>

    <template>
      <div ref="containerRef" style="height: 640px"></div>
      <pre>{{ log.join("\n") }}</pre>
    </template>
    ```
  </Step>

  <Step title="Configure a sdkUrl">
    ```bash title=".env" theme={null}
    VITE_LEGITIMUZ_SDK_URL=<SUA_SDK_URL>
    ```

    Gitignorado pelo padrão do Vite. Nunca comite um valor real.
  </Step>
</Steps>

## Confira que funcionou

A primeira tela aparece dentro do container e o `<pre>` recebe `ready`.

## Se você renderizar o custom element

Os exemplos acima usam `mount()`, que monta num `<div>` comum e não precisa de configuração de
compilador. O SDK também expõe o custom element `<legitimuz-websdk>`. **Só nesse caso** o Vue
precisa ser avisado de que a tag não é um componente que ele deveria resolver:

```ts title="vite.config.ts" theme={null}
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag === "legitimuz-websdk",
        },
      },
    }),
  ],
});
```

Sem isso, renderizar a tag declarativamente gera aviso de componente não resolvido.

## Próximo passo

<Columns cols={2}>
  <Card title="Opções do mount()" icon="settings-2" href="/web-sdk/options">
    Aparência, idioma, timeout e todos os callbacks.
  </Card>

  <Card title="7. Testar" icon="play" href="/setup/test">
    Rode a jornada ponta a ponta e veja a decisão chegar.
  </Card>
</Columns>
