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

@ministerjs/ui

v4.4.0

Published

Vue 3 + Vuetify UI component library for building dashboards and full-stack applications, part of the MinisterJS framework

Readme

@ministerjs/ui

Uma biblioteca de componentes Vue 3 + Vuetify para construção de dashboards e aplicações full-stack, parte do ecossistema MinisterJS.

🚀 Instalação

npm install @ministerjs/ui
# ou
pnpm add @ministerjs/ui
# ou
yarn add @ministerjs/ui

Dependências Peer

Este pacote requer as seguintes dependências peer:

{
  "@ministerjs/composables": "^1.0.2",
  "@ministerjs/model": "^1.1.5",
  "@ministerjs/resource": "^1.3.1",
  "@ministerjs/store": "^1.2.1",
  "@ministerjs/utils": "^2.4.0",
  "@ministerjs/validates": "^1.0.2",
  "vue": "^3.5.12",
  "vue-router": "^4.4.5",
  "vuetify": "^3.7.2"
}

📦 Estrutura do Pacote

Componentes Principais

  • Fields: Campos de formulário especializados
  • Forms: Formulários base para CRUD
  • Views: Visualizações de dados (Lista, Tabela, Item)
  • Widgets: Componentes de UI reutilizáveis
  • Events: Eventos customizados para comunicação
  • Enums: Enumerações para configuração

🎯 Uso Básico

1. Configuração Inicial

// main.ts
import { createApp } from "vue";
import { createVuetify } from "vuetify";
import "@ministerjs/ui/style";
import App from "./App.vue";

const vuetify = createVuetify();
const app = createApp(App);

app.use(vuetify);
app.mount("#app");

2. Importação de Componentes

// Importação individual
import { TextField, SelectField, TableViewList } from "@ministerjs/ui";

// Importação de tipos
import type { FieldScheme, TableViewScheme } from "@ministerjs/ui/types";

// Importação de enums
import { HiddenEnum, TableFeaturesEnum } from "@ministerjs/ui/enums/HiddenEnum";

// Importação de eventos
import { InputFieldEvent } from "@ministerjs/ui/events/InputFieldEvent";

🔧 Componentes de Campo (Fields)

TextField

Campo de texto básico com validação e máscaras:

<template>
  <TextField v-model="value" :scheme="textFieldScheme" @input="handleInput" />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { TextField, TextFieldScheme } from "@ministerjs/ui";

const value = ref("");

const textFieldScheme = new TextFieldScheme({
  title: "Nome",
  key: "name",
  modelValue: value,
  required: true,
  requiredMessage: "Nome é obrigatório",
});

function handleInput(event: InputFieldEvent) {
  console.log("Input event:", event.data);
}
</script>

Campos Especializados

// Campo de CPF com validação automática
import { CPFField, CPFFieldScheme } from "@ministerjs/ui";

const cpfScheme = new CPFFieldScheme({
  title: "CPF",
  key: "cpf",
  required: true,
});

// Campo de Email
import { EmailField, EmailFieldScheme } from "@ministerjs/ui";

const emailScheme = new EmailFieldScheme({
  title: "Email",
  key: "email",
  required: true,
});

// Campo de Preço
import { PriceField, PriceFieldScheme } from "@ministerjs/ui";

const priceScheme = new PriceFieldScheme({
  title: "Valor",
  key: "price",
  defaultValue: 0,
});

Lista Completa de Campos

| Campo | Componente | Scheme | Descrição | | ------------------- | ------------------- | ------------------------- | ----------------------------------- | | CNPJField | CNPJField | CNPJFieldScheme | Campo para CNPJ com validação | | CPFField | CPFField | CPFFieldScheme | Campo para CPF com validação | | CEPField | CEPField | CEPFieldScheme | Campo para CEP com busca automática | | EmailField | EmailField | EmailFieldScheme | Campo de email com validação | | PasswordField | PasswordField | PasswordFieldScheme | Campo de senha com toggle | | PhoneField | PhoneField | PhoneFieldScheme | Campo de telefone com máscara | | PriceField | PriceField | PriceFieldScheme | Campo monetário formatado | | NumberField | NumberField | NumberFieldScheme | Campo numérico | | DateField | DateField | DateFieldScheme | Seletor de data | | TextAreaField | TextAreaField | TextAreaFieldScheme | Área de texto multilinha | | RichTextField | RichTextField | RichTextFieldScheme | Editor de texto rico (CKEditor) | | SelectField | SelectField | SelectFieldScheme | Campo de seleção | | SelectSearchField | SelectSearchField | SelectSearchFieldScheme | Campo de busca com seleção | | FileField | FileField | FileFieldScheme | Upload de arquivos | | ImageField | ImageField | ImageFieldScheme | Upload e preview de imagens |

📋 Formulários

BaseForm

Formulário base com validação automática:

<template>
  <BaseForm
    :fields="fields"
    @beforesubmit="handleBeforeSubmit"
    @aftersubmit="handleAfterSubmit"
  />
</template>

<script setup lang="ts">
import { BaseForm, FieldSchemeCollection } from "@ministerjs/ui";
import type { AfterSubmitEvent } from "@ministerjs/ui/events";

const fields = new FieldSchemeCollection({
  name: new TextFieldScheme({
    title: "Nome",
    key: "name",
    required: true,
  }),
  email: new EmailFieldScheme({
    title: "Email",
    key: "email",
    required: true,
  }),
});

function handleAfterSubmit(event: AfterSubmitEvent) {
  console.log("Resposta do servidor:", event.data);
}
</script>

📊 Visualizações (Views)

TableViewList

Tabela completa com CRUD, paginação e busca:

<template>
  <TableViewList :scheme="tableScheme" />
</template>

<script setup lang="ts">
import {
  TableViewList,
  TableViewScheme,
  FieldSchemeCollection,
} from "@ministerjs/ui";
import { TableFeaturesEnum } from "@ministerjs/ui/enums/TableFeaturesEnum";
import { useRestResources } from "@ministerjs/resource";
import { TableModel } from "@ministerjs/model";

// Configuração do resource
const { users } = useRestResources(["users"]);

// Configuração dos campos
const fields = new FieldSchemeCollection({
  name: new TextFieldScheme({
    title: "Nome",
    key: "name",
    required: true,
  }),
  email: new EmailFieldScheme({
    title: "Email",
    key: "email",
    required: true,
  }),
  phone: new PhoneFieldScheme({
    title: "Telefone",
    key: "phone",
  }),
});

// Configuração do modelo
const model = new TableModel(users, "id");

// Esquema da tabela
const tableScheme = new TableViewScheme({
  title: "Usuários",
  key: "users",
  fields,
  model,
  headers: {
    name: true,
    email: true,
    phone: false, // Oculta a coluna telefone
  },
  features: TableFeaturesEnum.ALL, // Habilita todas as funcionalidades
  noDataText: "Nenhum usuário encontrado",
});
</script>

Configuração de Funcionalidades

import { TableFeaturesEnum } from "@ministerjs/ui/enums/TableFeaturesEnum";

// Apenas visualização
features: TableFeaturesEnum.GET;

// Apenas criação e visualização
features: TableFeaturesEnum.GET | TableFeaturesEnum.ADD;

// Todas as funcionalidades
features: TableFeaturesEnum.ALL;

// Funcionalidades customizadas
features: TableFeaturesEnum.GET | TableFeaturesEnum.UPD | TableFeaturesEnum.DEL;

Botões de Ação Customizados

const tableScheme = new TableViewScheme({
  // ... outras configurações

  // Botões por item (linha)
  itemActionsButtons: [
    {
      icon: "mdi-eye",
      title: "Visualizar",
      onClick: ({ scheme, item }) => {
        console.log("Visualizar item:", item);
      },
    },
  ],

  // Botões da lista (toolbar)
  listActionsButtons: [
    {
      icon: "mdi-export",
      title: "Exportar",
      onClick: ({ scheme }) => {
        console.log("Exportar dados");
      },
    },
  ],

  // Botões de linha (contexto)
  rowActionsButtons: [
    {
      icon: "mdi-star",
      title: "Favoritar",
      onClick: ({ scheme, item }) => {
        // Toggle favorito
      },
      isActive: ({ scheme, item }) => {
        return item.isFavorite === true;
      },
    },
  ],
});

ItemView

Visualização de item individual:

<template>
  <ItemView :scheme="itemScheme" />
</template>

<script setup lang="ts">
import { ItemView, ItemViewScheme } from "@ministerjs/ui";

const itemScheme = new ItemViewScheme({
  title: "Detalhes do Usuário",
  key: "user",
  fields,
  model,
});
</script>

ListView

Lista simples sem tabela:

<template>
  <ListView :scheme="listScheme" />
</template>

<script setup lang="ts">
import { ListView, ListViewScheme } from "@ministerjs/ui";

const listScheme = new ListViewScheme({
  title: "Lista de Usuários",
  key: "users",
  fields,
  model,
});
</script>

🎨 Widgets

ButtonWidget

<template>
  <ButtonWidget
    icon="mdi-plus"
    text="Adicionar"
    color="primary"
    @click="handleAdd"
  />
</template>

IconButtonWidget

<template>
  <IconButtonWidget
    icon="mdi-edit"
    title="Editar"
    size="small"
    @click="handleEdit"
  />
</template>

ToolbarButtonWidget

<template>
  <ToolbarButtonWidget
    icon="mdi-delete"
    text="Excluir"
    color="error"
    :loading="deleteLoading"
    @click="handleDelete"
  />
</template>

🔄 Eventos

InputFieldEvent

Disparado quando um campo recebe input:

import { InputFieldEvent } from "@ministerjs/ui/events/InputFieldEvent";

function handleInput(event: InputFieldEvent) {
  console.log("Campo:", event.scheme.key);
  console.log("Valor:", event.data);
}

AfterSubmitEvent

Eventos de ciclo de vida do formulário:

import { AfterSubmitEvent } from "@ministerjs/ui/events";

function handleAfterSubmit(event: AfterSubmitEvent) {
  // Ações após o envio bem-sucedido
  console.log("Dados salvos:", event.data);
  router.push("/success");
}

SearchFieldEvent

Evento de busca em campos de seleção:

import { SearchFieldEvent } from "@ministerjs/ui/events/SearchFieldEvent";

function handleSearch(event: SearchFieldEvent) {
  console.log("Termo de busca:", event.data);
  // Implementar lógica de busca customizada
}

⚙️ Enumerações

HiddenEnum

Controla a visibilidade de campos em diferentes contextos:

import { HiddenEnum } from "@ministerjs/ui/enums/HiddenEnum";

const fieldScheme = new TextFieldScheme({
  title: "Campo",
  key: "field",
  hidden: HiddenEnum.TABLE_ADD, // Oculta apenas na criação via tabela
});

// Opções disponíveis:
// HiddenEnum.NEVER - Sempre visível (padrão)
// HiddenEnum.ITEM_UPD - Oculto na edição de item
// HiddenEnum.TABLE_ADD - Oculto na criação via tabela
// HiddenEnum.TABLE_UPD - Oculto na edição via tabela
// HiddenEnum.TABLE_ALWAYS - Oculto sempre na tabela
// HiddenEnum.ALWAYS - Sempre oculto

TableFeaturesEnum

Define funcionalidades habilitadas na tabela:

import { TableFeaturesEnum } from "@ministerjs/ui/enums/TableFeaturesEnum";

// Funcionalidades individuais:
// TableFeaturesEnum.GET - Visualização
// TableFeaturesEnum.ADD - Criação
// TableFeaturesEnum.UPD - Edição
// TableFeaturesEnum.DEL - Exclusão
// TableFeaturesEnum.ALL - Todas as funcionalidades
// TableFeaturesEnum.NONE - Nenhuma funcionalidade

🎨 Estilos

Importação de Estilos

// Importar estilos CSS
import "@ministerjs/ui/style";

// Ou especificamente
import "@ministerjs/ui/dist/styles.css";

Personalização com Vuetify

O pacote é construído sobre Vuetify 3, permitindo personalização completa do tema:

import { createVuetify } from "vuetify";

const vuetify = createVuetify({
  theme: {
    defaultTheme: "light",
    themes: {
      light: {
        colors: {
          primary: "#1976D2",
          secondary: "#424242",
          // ... outras cores
        },
      },
    },
  },
});

🔗 Integração com MinisterJS

Com @ministerjs/resource

import { useRestResources } from "@ministerjs/resource";
import { TableModel } from "@ministerjs/model";

const { users, posts } = useRestResources(["users", "posts"]);

const usersModel = new TableModel(users, "id");
const postsModel = new TableModel(posts, "id");

Com @ministerjs/store

import { useModels } from "@ministerjs/model";

const models = useModels({
  users: usersModel,
  posts: postsModel,
});

Com @ministerjs/validates

import { validateEmail } from "@ministerjs/validates";

const emailField = new EmailFieldScheme({
  title: "Email",
  key: "email",
  rules: [(value) => validateEmail(value) || "Email inválido"],
});

📚 Exemplos Completos

Formulário de Usuário Completo

<template>
  <v-container>
    <v-card>
      <v-card-title>Cadastro de Usuário</v-card-title>
      <v-card-text>
        <BaseForm :fields="userFields" @aftersubmit="handleSuccess" />
      </v-card-text>
    </v-card>
  </v-container>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { useRouter } from "vue-router";
import {
  BaseForm,
  FieldSchemeCollection,
  TextFieldScheme,
  EmailFieldScheme,
  PhoneFieldScheme,
  CPFFieldScheme,
  CEPFieldScheme,
  SelectFieldScheme,
} from "@ministerjs/ui";
import { HiddenEnum } from "@ministerjs/ui/enums/HiddenEnum";

const router = useRouter();

const userFields = new FieldSchemeCollection({
  name: new TextFieldScheme({
    title: "Nome Completo",
    key: "name",
    required: true,
    requiredMessage: "Nome é obrigatório",
  }),

  email: new EmailFieldScheme({
    title: "Email",
    key: "email",
    required: true,
  }),

  phone: new PhoneFieldScheme({
    title: "Telefone",
    key: "phone",
  }),

  cpf: new CPFFieldScheme({
    title: "CPF",
    key: "cpf",
    required: true,
  }),

  cep: new CEPFieldScheme({
    title: "CEP",
    key: "cep",
  }),

  gender: new SelectFieldScheme({
    title: "Gênero",
    key: "gender",
    options: [
      { value: "M", text: "Masculino" },
      { value: "F", text: "Feminino" },
      { value: "O", text: "Outro" },
    ],
  }),

  id: new TextFieldScheme({
    title: "ID",
    key: "id",
    hidden: HiddenEnum.ALWAYS, // Campo oculto
    readonly: true,
  }),
});

function handleSuccess(event: AfterSubmitEvent) {
  console.log("Usuário criado:", event.data);
  router.push("/users");
}
</script>

Dashboard Completo

<template>
  <v-app>
    <v-main>
      <v-container fluid>
        <TableViewList :scheme="usersTableScheme" />
      </v-container>
    </v-main>
  </v-app>
</template>

<script setup lang="ts">
import {
  TableViewList,
  TableViewScheme,
  FieldSchemeCollection,
  TextFieldScheme,
  EmailFieldScheme,
  PhoneFieldScheme,
  DateFieldScheme,
} from "@ministerjs/ui";
import { TableFeaturesEnum } from "@ministerjs/ui/enums/TableFeaturesEnum";
import { HiddenEnum } from "@ministerjs/ui/enums/HiddenEnum";
import { useRestResources } from "@ministerjs/resource";
import { TableModel } from "@ministerjs/model";

// Configuração da API
const { users } = useRestResources(["users"]);
const usersModel = new TableModel(users, "id");

// Campos da tabela
const usersFields = new FieldSchemeCollection({
  id: new TextFieldScheme({
    title: "ID",
    key: "id",
    readonly: true,
    hidden: HiddenEnum.TABLE_ADD,
  }),

  name: new TextFieldScheme({
    title: "Nome",
    key: "name",
    required: true,
  }),

  email: new EmailFieldScheme({
    title: "Email",
    key: "email",
    required: true,
  }),

  phone: new PhoneFieldScheme({
    title: "Telefone",
    key: "phone",
  }),

  createdAt: new DateFieldScheme({
    title: "Criado em",
    key: "createdAt",
    readonly: true,
    hidden: HiddenEnum.TABLE_ALWAYS,
  }),
});

// Esquema da tabela
const usersTableScheme = new TableViewScheme({
  title: "Gerenciamento de Usuários",
  key: "users",
  fields: usersFields,
  model: usersModel,
  headers: {
    id: true,
    name: true,
    email: true,
    phone: true,
    createdAt: false,
  },
  features: TableFeaturesEnum.ALL,
  noDataText: "Nenhum usuário cadastrado",

  // Botões customizados
  listActionsButtons: [
    {
      icon: "mdi-download",
      title: "Exportar CSV",
      onClick: ({ scheme }) => {
        // Lógica de exportação
        console.log("Exportando dados...");
      },
    },
  ],

  itemActionsButtons: [
    {
      icon: "mdi-eye",
      title: "Visualizar Detalhes",
      onClick: ({ scheme, item }) => {
        console.log("Ver detalhes:", item);
      },
    },
  ],
});
</script>

🚀 Deploy e Distribuição

Build do Pacote

# Build de produção
pnpm build

# Build apenas dos tipos
pnpm build:types

# Lint do código
pnpm lint

# Storybook para desenvolvimento
pnpm storybook

Uso em Produção

// Otimização para bundlers
import { TableViewList } from "@ministerjs/ui"; // Tree shaking automático

// Importação de tipos apenas em development
import type { TableViewScheme } from "@ministerjs/ui/types";

🔍 Troubleshooting

Problemas Comuns

  1. Estilos não carregando: Certifique-se de importar @ministerjs/ui/style
  2. Vuetify não configurado: Instale e configure o Vuetify 3
  3. Dependências peer faltando: Instale todas as dependências peer necessárias
  4. Erros de tipo: Verifique se está importando os tipos corretos

Debugging

// Habilitar logs de debug
localStorage.setItem("ministerjs:debug", "true");

// Verificar estado dos campos
console.log(fieldScheme.modelValue.value);
console.log(fieldScheme.isValid.value);
console.log(fieldScheme.errors.value);

📖 Referências

🤝 Contribuição

Para contribuir com o pacote, veja o guia de contribuição do monorepo MinisterJS.

📄 Licença

Este pacote faz parte do framework MinisterJS e segue a mesma licença do projeto principal.