
Research
/Security News
Weaponizing Discord for Command and Control Across npm, PyPI, and RubyGems.org
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
@ministerjs/ui
Advanced tools
Vue 3 + Vuetify UI component library for building dashboards and full-stack applications, part of the MinisterJS framework
Uma biblioteca de componentes Vue 3 + Vuetify para construção de dashboards e aplicações full-stack, parte do ecossistema MinisterJS.
npm install @ministerjs/ui
# ou
pnpm add @ministerjs/ui
# ou
yarn add @ministerjs/ui
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"
}
// 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");
// 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";
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>
// 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,
});
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á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>
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>
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;
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;
},
},
],
});
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>
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>
<template>
<ButtonWidget
icon="mdi-plus"
text="Adicionar"
color="primary"
@click="handleAdd"
/>
</template>
<template>
<IconButtonWidget
icon="mdi-edit"
title="Editar"
size="small"
@click="handleEdit"
/>
</template>
<template>
<ToolbarButtonWidget
icon="mdi-delete"
text="Excluir"
color="error"
:loading="deleteLoading"
@click="handleDelete"
/>
</template>
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);
}
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");
}
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
}
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
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
// Importar estilos CSS
import "@ministerjs/ui/style";
// Ou especificamente
import "@ministerjs/ui/dist/styles.css";
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
},
},
},
},
});
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");
import { useModels } from "@ministerjs/model";
const models = useModels({
users: usersModel,
posts: postsModel,
});
import { validateEmail } from "@ministerjs/validates";
const emailField = new EmailFieldScheme({
title: "Email",
key: "email",
rules: [(value) => validateEmail(value) || "Email inválido"],
});
<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>
<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>
# Build de produção
pnpm build
# Build apenas dos tipos
pnpm build:types
# Lint do código
pnpm lint
# Storybook para desenvolvimento
pnpm storybook
// 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";
@ministerjs/ui/style
// 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);
Para contribuir com o pacote, veja o guia de contribuição do monorepo MinisterJS.
Este pacote faz parte do framework MinisterJS e segue a mesma licença do projeto principal.
FAQs
Vue 3 + Vuetify UI component library for building dashboards and full-stack applications, part of the MinisterJS framework
The npm package @ministerjs/ui receives a total of 49 weekly downloads. As such, @ministerjs/ui popularity was classified as not popular.
We found that @ministerjs/ui demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
Security News
Socket now integrates with Bun 1.3’s Security Scanner API to block risky packages at install time and enforce your organization’s policies in local dev and CI.
Research
The Socket Threat Research Team is tracking weekly intrusions into the npm registry that follow a repeatable adversarial playbook used by North Korean state-sponsored actors.