npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@be-enlighten/enspace-sdk-ui

v0.11.1

Published

Vue 3 component library and Nuxt 4 module for the Enspace SDK — dumb base components + entity components wired to the /query data layer.

Readme

@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-BRpt_br, enen, eses) 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.

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.

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? | — | — | | EnMembersViewManyTable | ViewMany | wired | Tabela de membros com busca e ações protegidas (troca de role, remoção) | workspace?, members?, loading?, searchable?, 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 | — | | 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.
  • 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.