@be-enlighten/enspace-sdk-ui

Vue 3 component library and Nuxt 4 module for the Enspace SDK — dumb base components + entity components wired to the /query data layer.
2,371
Install
npm install @be-enlighten/enspace-sdk-ui
Latest Version:0.17.0
Vue:3
License:MIT
Last Updated:Sep 25, 2026
Links: npm
Maintainer: hardeath950

@be-enlighten/enspace-sdk-ui

Biblioteca de componentes Vue 3 do Enspace, sobre Nuxt UI 4 e Tailwind 4.

Dois tipos de componente:

  • Base (dumb): só props, slots e emits. Zero data fetching, zero router.
  • Entidade (wired): consomem a data layer /query do @be-enlighten/enspace-sdk-vue internamente, com override por props. As regras de domínio do Enspace (owner, membro pendente, self-exclusion) vivem no componente, não na sua app.

Navegação sempre sai por emits: a app decide a rota.

Instalação

pnpm add @be-enlighten/enspace-sdk-ui

Peers:

Peer Obrigatória? Para quê
vue@^3.5 sim runtime dos componentes
@nuxt/ui@^4 sim stack de estilo (Nuxt UI 4 + Tailwind 4)
@be-enlighten/enspace-sdk-vue sim composables /query dos componentes de entidade
@be-enlighten/enspace-sdk-core sim tipos de domínio na API pública
@tanstack/vue-table@^8 sim motor do EnTable
pinia, @pinia/colada opcional só para componentes wired
streamdown-vue, @be-enlighten/beni-avatar opcional componentes de AI
ai, @ai-sdk/vue opcional chat de AI com streaming
nuxt, @nuxt/kit opcional módulo /nuxt

A app consumidora precisa do plugin @nuxt/ui/vite (Vite) ou do módulo Nuxt UI.

Setup

1. EnApp na raiz

Os componentes En* precisam do UApp do Nuxt UI na raiz (modal, tooltip, toast). O EnApp abraça o UApp por dentro e provê locale e mensagens globais, então é o único wrapper obrigatório:

<script setup lang="ts">
import { EnApp } from '@be-enlighten/enspace-sdk-ui'
</script>

<template>
  <EnApp locale="pt-BR">
    <RouterView />
  </EnApp>
</template>

locale?: MaybeRefOrGetter<EnUiLocale> (default 'pt-BR') aceita valor direto, ref ou getter. Com vue-i18n na app, a ponte é direta e não exige peer de vue-i18n no pacote:

<script setup lang="ts">
import { useI18n } from 'vue-i18n'

const { locale } = useI18n()
</script>

<template>
  <EnApp :locale="locale">
    <RouterView />
  </EnApp>
</template>

O locale também é mapeado para o @nuxt/ui/locale (pt-BR → pt_br, en → en, es → es) e repassado ao UApp interno: um knob controla os textos do pacote e os do Nuxt UI.

messages?: EnUiMessagesOverrides sobrescreve textos por locale (Partial<Record<EnUiLocale, DeepPartial<EnUiMessages>>>), aplicados por deep-merge sobre o dicionário interno:

<EnApp
  :locale="locale"
  :messages="{ 'pt-BR': { members: { table: { invite: 'Convidar colegas' } } } }"
>

Resolução do locale em cada componente: prop locale → inject do EnApp → 'pt-BR'. Sem EnApp, tudo continua funcionando com o fallback. O contexto injetado é exportado (EnUiContextKey, tipo EnUiContext) para casos avançados.

toaster?: ToasterProps | null e tooltip?: TooltipProviderProps repassam a config do UApp interno (posição dos toasts, delay dos tooltips, etc). Tipagem espelha AppProps do @nuxt/ui — sem perder nada do que o UApp aceita:

<EnApp :locale="locale" :toaster="{ position: 'top-right' }" :tooltip="{ delayDuration: 200 }">
  <RouterView />
</EnApp>

2. CSS

O build extrai o CSS dos componentes (handle de resize do EnTable, regras contain de performance) para um arquivo separado, que precisa ser importado uma vez:

import '@be-enlighten/enspace-sdk-ui/style.css'

Sem esse import, a feature resizable do EnTable fica sem o handle visual e as otimizações de contain não se aplicam.

3. Registro global (opcional)

O padrão é importar por nome (import { EnMembersViewManyTable } from '@be-enlighten/enspace-sdk-ui'). Para registro global:

import { EnspaceUi } from '@be-enlighten/enspace-sdk-ui'
import '@be-enlighten/enspace-sdk-ui/style.css'

app.use(EnspaceUi, { locale: 'pt-BR' }) // opções: `locale` e `messages`, mesma semântica das props do EnApp

O plugin registra todos os componentes públicos, provê o contexto de i18n no nível da app e chama o shim de NuxtLink. Ele não abraça o UApp: o <EnApp> na raiz continua necessário.

installNuxtLinkShim(app) — componentes do Nuxt UI com to (ULink, UButton) renderizam <NuxtLink custom>, que só o Nuxt registra. Em apps Vite + vue-router, o shim registra um NuxtLink que delega ao RouterLink com o mesmo contrato de slot (href, navigate, isActive). É no-op sem vue-router ou quando NuxtLink já existe. O plugin EnspaceUi chama o shim automaticamente; com imports nomeados, chame manualmente.

4. Nuxt 4

export default defineNuxtConfig({
  modules: [
    '@be-enlighten/enspace-sdk-vue/nuxt', // data layer, necessário para os componentes de entidade
    '@be-enlighten/enspace-sdk-ui/nuxt',
  ],
})

O módulo auto-importa todos os componentes e injeta o CSS. Opções na chave enspaceUi:

Opção Default Descrição
prefix '' Prefixo dos nomes registrados ('Ui' → <UiEnTable />).
global false Registra tudo globalmente em vez de auto-import sob demanda. Necessário fora de templates Vue (ex.: MDC do @nuxt/content); custo: tudo entra no bundle.
dataModuleCheck true Avisa no build quando o módulo de dados não está registrado. Desligue em apps que usam só componentes base.

O <EnApp> na raiz continua necessário no Nuxt.

5. Base-only (sem o grafo de AI)

O barrel raiz re-exporta estaticamente todos os componentes — inclusive os de AI, cujo grafo de deps toca as peers opcionais CJS (ai, streamdown-vue). Em apps que usam só os componentes base, isso pode quebrar o dev do Vite (os CJS profundos são servidos sem interop CJS→ESM).

Para esses apps existe o entry @be-enlighten/enspace-sdk-ui/base com os quatro componentes base (EnApp, EnLayout, EnTable, EnKanbanBoard) e seus tipos — o grafo de AI nunca é importado e as peers opcionais de AI não são necessárias:

import { EnApp, EnTable, type EnTableColumn } from '@be-enlighten/enspace-sdk-ui/base'
import '@be-enlighten/enspace-sdk-ui/style.css'

Apps Nuxt que usam só os componentes base não precisam fazer nada: o módulo /nuxt já registra os quatro base pelo entry ./base (os demais continuam vindo do barrel).

Componentes

Componente Grupo Tipo Descrição Props principais Emits Slots
EnApp base infra Provider raiz: abraça o UApp e provê locale/messages globais (ver Setup) locale?, messages? — default
EnLayout layout dumb Shell de layout configurável (7 variants) com sidebar primária, sidebar secundária, inspector e navbar. Controla estrutura e visual em uma prop variant variant, title?, side?, collapsible?, rail?, mode?, defaultOpen?, showNavbarToggle?, navbarHeight? — sidebar-header, sidebar-default, sidebar-footer, sidebar-secondary-header, sidebar-secondary-default, sidebar-secondary-footer, inspector-header, inspector-default, inspector-footer, navbar-leading, navbar-title, navbar-trailing, default
EnTable base dumb Listagem padrão Enspace, genérica em R (ver detalhes abaixo) columns, rows, loading?, selectable?, selected?, sort?, pagination?, emptyState?, resizable?, columnSizing?, columnVisibility?, columnOrder?, virtualize?, locale? update:selected, page-change, sort-change, row-click, update:columnSizing, update:columnVisibility, update:columnOrder #cell-{key}, #actions, #empty, #pagination
EnKanbanBoard base dumb Board kanban genérico em R: agrupa por campo (groupBy, dot-path), DnD HTML5 entre colunas com drop zone destacada, colunas ocultáveis/ordenáveis (localStorage ou modo controlado), virtualização por coluna, skeleton, context menu por cartão (abrir/editar/mover/arquivar/lixeira/copiar link), badges de tag, meta de usuários (dumb) e rodapé de datas data, cardMap, groupBy, columns?, storageKey?, primaryKey?, defaultColumnSortField?, defaultColumnSortDesc?, doneStatus?, permissions?, managedColumns?, columnVisibility?, columnOrder?, showHeaderColumnControls?, showSkeleton?, cardsLoading?, staggerColumnMs?, callbacks (onOpenPage?, onEdit?, onMoveTo?, onArchiveCard?, onTrashCard?, handleCopyExternalLink?), locale? drop, done-drop, card-click, archive, create, context-mouse, ready —
EnAccountSharedMenu Shared wired Menu de conta (perfil + logout, itens custom) profile?, items?, collapsed?, logoutRedirectUri?, locale? logout, navigate encaminha slots ao dropdown interno
EnAiAgentsViewManyGrid ViewMany wired Grid de agentes com tabs todos/sistema/workspace, busca por nome/slug e CTA de criar locale? select ({ action, agent }), create —
EnAiAgentsViewOneCard ViewOne dumb Card de agente com avatar BENI temático, badges de source/tipo e menu edit/delete (desabilitado para agentes de sistema) agent, locale? select ({ action, agent }) —
EnAiChatsSharedFloat Shared dumb Widget flutuante de IA: botão BENI draggable (posição persistida) + painel redimensionável com sessão, nova conversa e histórico open?, onBeforeSend?, onNotify?, types?, walletState?, locale? update:open, openFullscreen ({ chatId, agent }) —
EnAiChatsFormsCreate Forms wired Tela de nova conversa: hero do agente, alertas de wallet, quick chats, composer com upload e seletores de modelo/mode/reasoning. Cria o chat e emite o resultado compact?, showWalletAlerts?, showQuickChats?, showFileUpload?, showFooter?, showAgentSelector?, initialPrompt?, agentSlug?, walletState?, types?, locale? chatCreated, update:agentSlug, goToBilling header (+ header-left/header-center/header-right)
EnAiChatsFormsPrompt Forms dumb Composer sobre UChatPrompt: v-model de texto, preview de arquivos no header, upload à esquerda e footers do caller modelValue, placeholder, status?, error?, disabled?, variant?, showFileUpload?, files?, isUploading?, maxrows?, rows?, compact?, locale? update:modelValue, submit, filesSelected, fileRemove, stop, reload files-preview, footer-left, footer-right (scoped)
EnAiChatsSharedDockHeader Shared dumb Ações do header do dock: histórico, nova conversa, tela cheia e fechar creating?, sidebarOpen?, locale? toggleSidebar, newChat, fullscreen, close —
EnAiChatsSharedHeader Shared dumb Barra de header do chat: avatar BENI à esquerda, seletor de agente ao centro, ações à direita beniState, beniBodyColor, beniBodyColorTo, beniEyesColor, beniHeadItem?, agentsLoading?, agentOptions, agentDescriptions?, selectedAgentSlug?, showAgentSelector?, locale? selectAgent header-left, header-center, header-right
EnAiChatsSharedLoader Shared dumb Indicador de carregamento do chat (três pontos + rótulo), inline ou overlay com blur label?, message?, overlay? — —
EnAiChatsViewManyList ViewMany wired Sidebar de histórico de chats: nav "Nova conversa"/"Buscar" + command palette (⌘K), grupos por recência, rename inline e delete com confirmação selected?, collapsed?, searchShortcut?, locale? update:selected, newChat, delete —
EnAiChatsViewOneSession ViewOne wired Conversa ao vivo: mensagens com streaming (reasoning/tool/texto/arquivo), composer com upload, seletores de modelo/mode/reasoning, regenerar/copiar e estado do avatar BENI chatId, showFooter?, compact?, agentSlug?, initialMode?, initialModel?, initialReasoning?, onBeforeSend?, onNotify?, locale? update:agentSlug, error, newChat header (+ header-left/header-center/header-right)
EnAiChatsControlsModelBadge Controls dumb Badge transitório quando o backend roteia o request para outro modelo from, to, visionRouted, locale? — —
EnAiChatsControlsModelSelect Controls wired Pill de seleção de modelo: entrada "modelo padrão" + modelos agrupados por provider, com ícones de capability e busca v-model (string | null), compact?, locale? update:modelValue —
EnAiChatsControlsModePill Controls dumb Pill de alternância do modo do agente (Write/Plan). Clique cicla o modo modelValue (AgentMode), locale? update:modelValue —
EnAiChatsControlsReasoningPill Controls dumb Seletor do nível de reasoning (off/low/medium/high) em dropdown com checkbox modelValue (AiReasoningSetting), options, locale? update:modelValue —
EnAiChatsFilesAvatar Files dumb Tile de arquivo: thumbnail ou ícone por mime, overlay de status e botão remover no hover name, type, previewUrl, status?, error?, removable?, locale? remove —
EnAiChatsFilesDragDropOverlay Files dumb Overlay fullscreen "solte os arquivos aqui" durante o drag show, locale? — —
EnAiChatsFilesPreview Files dumb Linha de avatares dos arquivos pendentes de envio v-model (AiChatFileWithStatus[]), locale? remove (+ update:modelValue) —
EnAiChatsFilesUploadButton Files dumb Botão clipe + input file oculto (multiple; imagens/PDF/CSV/TXT/DOC/XLS) disabled?, locale? filesSelected —
EnBillingFormsCreditRequest Forms wired Formulário de solicitação de créditos (amount + reason), como modal ou inline open?, workspace?, modal?, locale? update:open, success —
EnBillingSharedWalletCard Shared wired Card de saldo da carteira do workspace: nome, badge de status, moeda, saldo formatado e CTA de créditos workspace?, locale? topup —
EnBillingViewManyCreditRequests ViewMany wired Lista de pedidos de crédito: valor, status, motivo, data e cancelamento (só pending) workspace?, locale? cancelled —
EnBillingViewManyTransactions ViewMany wired Histórico paginado de transações da wallet em tabela workspace?, pageSize?, locale? — —
EnCommunicationsFormsComposer Forms dumb Composer de mensagem/comentário: v-model:text, Enter envia (Shift+Enter quebra linha), envio em loading, dica de atalho e slots de extensão v-model:text, placeholder?, ariaLabel?, sendLabel?, cancelLabel?, cancelable?, disabled?, sending?, autofocus?, rows?, maxrows?, showHint?, color?, locale? submit, typing, cancel header, actions
EnCommunicationsSharedMessageBubble Shared dumb Bolha de mensagem/comentário: avatar + autor, timestamp formatado, own (direita), grouped (consecutiva), system (linha central), estado de envio, marcas de editado/removido e ações no hover content, author, avatarText?, timestamp?, own?, grouped?, system?, status?, edited?, deleted?, locale? — actions
EnCommunicationsSharedStatusBadge Shared dumb Badge de status de thread (open/closed/archived) com cor semântica e ícone status, size?, variant?, iconless?, locale? — —
EnCommunicationsViewManyComments ViewMany wired Comentários de um registro: threading de dois níveis client-side (respostas expansíveis), criar/responder, editar e excluir só os próprios (modal de confirmação); canal realtime opt-in entity, entityReference, workspace?, comments?, loading?, members?, realtime?, disabled?, presence?, locale? event, error —
EnCommunicationsViewManyThreads ViewMany wired Lista de conversas do workspace: busca server-side (_q com debounce) e filtros de tipo/status, seleção de linha e CTA "nova conversa" delegados ao consumer workspace?, threads?, loading?, filters?, selectable?, selected?, disabled?, entity?, entityReference?, presence?, locale? select, update:selected, create —
EnCommunicationsViewOneThread ViewOne wired Conversa ao vivo: transcrição com separadores de dia e agrupamento de autor, auto-scroll, modo campo (ensure obter-ou-criar no mount), status no kebab (reopen/close/archive), canal realtime + "está digitando…" reference?, thread?, entity?, entityReference?, fieldId?, title?, type?, workspace?, presence?, realtime?, showHeader?, limit?, locale? resolved, message-sent, status-change, event, error —
EnMembersViewManyTable ViewMany wired Tabela de membros com busca e ações protegidas (troca de role, remoção); coluna de presença online/offline opt-in workspace?, members?, loading?, searchable?, presence?, resizable?, columnVisibility?, locale? invite, update-role, remove —
EnMembersFormsCreate Forms wired Modal de convite (email + role inicial; owner nunca é oferecido) v-model:open, workspace?, locale? created, cancel —
EnMembersSharedPresenceFacepile Shared wired Facepile de quem está online no workspace: avatar group (max + +N, "eu" primeiro) + popover com nome/email; ponto cinza com tooltip quando vazio workspace?, max?, enabled?, locale? — —
EnMembersSharedPresenceIndicator Shared dumb Ponto de status de presença (online/offline) com aria-label localizado e cores semânticas online, size?, locale? — —
EnNotificationsActionsCommentReply Actions wired Card de ação para menção em comentário: cita o trecho e responde com comentário filho notification, locale? — —
EnNotificationsActionsOpenLink Actions dumb Card de ação genérico para notificações com link. Não renderiza nada sem link notification, locale? open —
EnNotificationsActionsTaskCard Actions dumb Card de ação para notificações de tarefa: nome, transição de status e botão de abrir notification, locale? open —
EnNotificationsActionsThreadReply Actions wired Card de ação para menção em thread: cita o trecho e responde na thread de origem notification, locale? — —
EnNotificationsSharedBell Shared wired Sino com badge de não lidas. Não abre painel: o estado é da app count?, max?, shortcuts?, locale? click —
EnNotificationsSharedSlideover Shared wired Painel lateral com as últimas limit notificações (marcar lida, dispensar, todas) v-model:open, limit?, locale? navigate, dismiss, mark-all-read, view-all #item
EnNotificationsViewInbox ViewInbox wired Inbox completo: lista com busca server-side, abas e teclado + painel de leitura com cards de ação + slideover mobile. Deep-link por prop, navegação por emits v-model:selected, limit?, title?, openReference?, locale? open-task, open-link, open-reference-resolved navbar-leading
EnNotificationsViewManyList ViewMany dumb Lista estilo inbox: ator, chip de não lida, título/corpo, data compacta, seleção por clique e navegação por ArrowUp/ArrowDown notifications, v-model (NotificationExpanded | null), locale? update:modelValue item (scoped)
EnNotificationsViewOneDetail ViewOne wired Painel de leitura: navbar com ações (marcar lida, dispensar, copiar referência), cabeçalho, corpo e card de ação por type.key notification, locale? close, open-task, open-link —
EnPlansFormsUpgrade Forms wired Modal de upgrade/downgrade com preview de proration. Upgrade imediato, downgrade agendado para o fim do período planCode?, workspace?, v-model:open, locale? success, cancel —
EnPlansSharedQuotaBars Shared wired Barras de progresso read-only das cotas do workspace: ícone do produto, badge de modo e used/limit formatados workspace?, locale? — —
EnPlansViewCompare View wired Tabela comparativa de planos sobre UPricingTable, com seções de cotas inclusas e features workspace?, locale? select —
EnPlansViewManyGrid ViewMany wired Grade responsiva de cards de plano com banner de downgrade agendado e modo current/upgrade/downgrade por card workspace?, locale? select, cancel-pending —
EnPlansViewOneCard ViewOne dumb Card de plano sobre UPricingPlan: preço, features concedidas, quotas no footer e CTA por mode plan, mode?, highlight?, locale? select —
EnWorkspacesSharedSelector Shared wired Seletor de workspace ativo (lista cacheada, setActive persistido) workspace?, creatable?, collapsed?, locale? change, create —

Todo componente com texto embutido aceita a prop locale ('pt-BR' | 'en' | 'es') como override pontual. Na prática o locale vem do <EnApp>; a prop só é necessária para um componente divergir do resto da app.

EnTable

Motor: UTable + @tanstack/vue-table. A API pública não expõe tipos da lib de tabela.

  • Colunas declarativas (EnTableColumn): { key, label, sortable?, align?, hidden? }.
  • Seleção em massa: selectable + v-model:selected (array de linhas, por referência de objeto). Checkbox no header com estado indeterminado; a seleção é podada quando rows muda.
  • Ordenação controlada: coluna sortable renderiza botão no header, o estado vem pela prop sort e as mudanças saem por sort-change. Quem ordena é o consumer ou o backend.
  • Paginação server-side: prop pagination: { page, pageCount, total? } + page-change, ou override completo pelo slot #pagination.
  • Resize, visibilidade, ordem e virtualização, todos opt-in: resizable (handle visual + update:columnSizing), columnSizing (larguras controladas, fecha o round-trip de persistência), columnVisibility + update:columnVisibility, columnOrder + update:columnOrder (as colunas estruturais select/actions não se movem), virtualize (padrão 44/10 quando ligado).
  • Estados: loading (spinner + aria-busy) e vazio via UEmpty interno (emptyState ou slot #empty).
  • A11y: tabela semântica, aria-sort, aria-label nos checkboxes, linhas com foco e teclado (Enter/Espaço) quando há listener de row-click.

Componentes de entidade

  • Regras de domínio implementadas: owner nunca é oferecido como opção de role (convite e troca) e não pode ser modificado nem removido (o menu vira botão desabilitado com tooltip); membro pending não muda de status nem de role; self-exclusion é detectada (remover o próprio usuário fica desabilitado); remoção sempre atrás de modal de confirmação.
  • Erro não é vazio: componentes wired renderizam estado de erro próprio (ícone, título, descrição e botão de retry). Falha de API nunca cai no empty state.
  • Override controlado: passar a prop de dados (ex.: members) desabilita a query interna, sem fetch desnecessário.
  • Família inbox (EnNotificationsView* + EnNotificationsActions*): o EnNotificationsViewInbox monta lista, leitura e slideover mobile, e delega aos cards de ação pelo type.key da notificação. A busca é server-side com debounce de 300ms. Deep-link é da app: a prop open-reference seleciona a notificação e open-reference-resolved avisa para limpar a URL.
  • Família communications (EnCommunications*): EnCommunicationsViewOneThread liga /query (useThread/useThreadMessages/mutations) e /realtime (useLiveThread + useTypingIndicator no mesmo canal) — mensagens recebidas chegam por invalidação de cache e "está digitando…" via relay efêmero; chat de campo (entity + entityReference + fieldId) dispara useEnsureThread (obter-ou-criar) automático no mount. Thread closed/archived não aceita mensagem (o composer vira aviso e o kebab oferece reabrir). EnCommunicationsViewManyThreads não assina canal próprio (não existe canal de lista no gateway): a frescura vem da invalidação do Pinia Colada feita pelo detalhe e pelas mutations. EnCommunicationsViewManyComments resolve o threading de dois níveis client-side (a lista da API é plana) e restringe editar/excluir ao próprio comentário (join pelo user do profile); sem canal de lista de threads, exclusão sempre atrás de modal de confirmação.
  • SSR-safe: nenhum acesso a window/document fora de guards.

i18n

Dicionário interno pt-BR/en/es com fallback (match exato → prefixo de língua → pt-BR), sem peer de vue-i18n. O locale global vem do <EnApp>; componentes também aceitam a prop locale como override pontual. Todo texto pode ser sobrescrito globalmente pela prop messages do EnApp (deep-merge por locale) ou pontualmente por props e slots (ex.: emptyState.title).

import { resolveMessages } from '@be-enlighten/enspace-sdk-ui'

resolveMessages('es').table.emptyTitle // 'Sin resultados'

Nomes dos componentes

En{Entidade}{Grupo}{Cardinalidade?}{Variante}

  • Entidade: domínio do recurso (Members, Workspaces, Account, Notifications, ...).
  • Grupo: View, Forms ou Shared.
  • Cardinalidade: Many ou One, obrigatória em View e ausente fora dele.
  • Variante (opcional): Table, Selector, Bell, Slideover, ...
  • Bases: En{Nome} simples (EnTable, EnApp, EnLayout), sempre dumb.

Exemplos: EnMembersViewManyTable, EnWorkspacesSharedSelector, EnAccountSharedMenu, EnNotificationsSharedBell.

Licença

MIT.

Related Packages

@be-enlighten/enspace-sdk-vue

Vue 3 composables/plugin and Nuxt 4 module for the Enspace SDK.

3,348
runedu-js-sdk

Javascript SDK of runedu project

6,628
nuxt-ui-colors-no-inline

Nuxt module that ensures nuxt-ui-colors CSS generated by Nuxt UI respects the Nu...

1,609 2
dingcloud-sdk

Ding-cloud数据埋点sdk

633
@bloomreach/vue-sdk

Bloomreach SPA SDK for Vue

75,260 19

Version History

Version Released License
0.17.0 MIT
0.16.0 MIT
0.15.0 MIT
0.14.0 MIT
0.13.0 MIT