@nexdom/uimed-vue 2.0.0-beta.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/components/app-bar/app-bar.js +5 -0
- package/dist/components/app-bar/app-bar.vue_vue_type_script_setup_true_lang.js +286 -0
- package/dist/components/app-bar/types.d.ts +96 -0
- package/dist/components/button/button.js +5 -0
- package/dist/components/button/button.vue.d.ts +31 -0
- package/dist/components/button/button.vue_vue_type_script_setup_true_lang.js +97 -0
- package/dist/components/button/types.d.ts +65 -0
- package/dist/components/data-sets/data-set/data-set.js +5 -0
- package/dist/components/data-sets/data-set/data-set.vue.d.ts +47 -0
- package/dist/components/data-sets/data-set/data-set.vue_vue_type_script_setup_true_lang.js +157 -0
- package/dist/components/data-sets/data-set/types.d.ts +93 -0
- package/dist/components/data-sets/data-set-bar.js +5 -0
- package/dist/components/data-sets/data-set-bar.vue_vue_type_script_setup_true_lang.js +99 -0
- package/dist/components/data-sets/data-set-item/data-set-item.js +5 -0
- package/dist/components/data-sets/data-set-item/data-set-item.vue.d.ts +35 -0
- package/dist/components/data-sets/data-set-item/data-set-item.vue_vue_type_script_setup_true_lang.js +57 -0
- package/dist/components/data-sets/data-set-item/types.d.ts +42 -0
- package/dist/components/details/details.js +5 -0
- package/dist/components/details/details.vue.d.ts +28 -0
- package/dist/components/details/details.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/components/details/types.d.ts +29 -0
- package/dist/components/dialogs/dialog/dialog-host-key.js +10 -0
- package/dist/components/dialogs/dialog/dialog.js +5 -0
- package/dist/components/dialogs/dialog/dialog.vue.d.ts +36 -0
- package/dist/components/dialogs/dialog/dialog.vue_vue_type_script_setup_true_lang.js +112 -0
- package/dist/components/dialogs/dialog/types.d.ts +47 -0
- package/dist/components/dialogs/dialog-host.js +5 -0
- package/dist/components/dialogs/dialog-host.vue_vue_type_script_setup_true_lang.js +81 -0
- package/dist/components/dialogs/toast.js +5 -0
- package/dist/components/dialogs/toast.vue_vue_type_script_setup_true_lang.js +35 -0
- package/dist/components/footer/footer.js +5 -0
- package/dist/components/footer/footer.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/footer/types.d.ts +16 -0
- package/dist/components/form/form.js +5 -0
- package/dist/components/form/form.vue.d.ts +32 -0
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +37 -0
- package/dist/components/form/types.d.ts +15 -0
- package/dist/components/grid/column/column.js +5 -0
- package/dist/components/grid/column/column.vue.d.ts +33 -0
- package/dist/components/grid/column/column.vue_vue_type_script_setup_true_lang.js +45 -0
- package/dist/components/grid/column/types.d.ts +27 -0
- package/dist/components/grid/container/container.js +5 -0
- package/dist/components/grid/container/container.vue.d.ts +27 -0
- package/dist/components/grid/container/container.vue_vue_type_script_setup_true_lang.js +33 -0
- package/dist/components/grid/container/types.d.ts +17 -0
- package/dist/components/grid/row/row.js +5 -0
- package/dist/components/grid/row/row.vue.d.ts +29 -0
- package/dist/components/grid/row/row.vue_vue_type_script_setup_true_lang.js +61 -0
- package/dist/components/grid/row/types.d.ts +63 -0
- package/dist/components/icon-button/icon-button.js +5 -0
- package/dist/components/icon-button/icon-button.vue.d.ts +23 -0
- package/dist/components/icon-button/icon-button.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/components/icon-button/types.d.ts +32 -0
- package/dist/components/img/img.js +5 -0
- package/dist/components/img/img.vue.d.ts +23 -0
- package/dist/components/img/img.vue_vue_type_script_setup_true_lang.js +61 -0
- package/dist/components/img/types.d.ts +43 -0
- package/dist/components/inputs/autocomplete-field/autocomplete-field.js +5 -0
- package/dist/components/inputs/autocomplete-field/autocomplete-field.vue.d.ts +33 -0
- package/dist/components/inputs/autocomplete-field/autocomplete-field.vue_vue_type_script_setup_true_lang.js +161 -0
- package/dist/components/inputs/autocomplete-field/types.d.ts +84 -0
- package/dist/components/inputs/checkbox/checkbox.js +5 -0
- package/dist/components/inputs/checkbox/checkbox.vue.d.ts +33 -0
- package/dist/components/inputs/checkbox/checkbox.vue_vue_type_script_setup_true_lang.js +71 -0
- package/dist/components/inputs/checkbox/types.d.ts +35 -0
- package/dist/components/inputs/date-time-field/date-time-field.js +5 -0
- package/dist/components/inputs/date-time-field/date-time-field.vue.d.ts +32 -0
- package/dist/components/inputs/date-time-field/date-time-field.vue_vue_type_script_setup_true_lang.js +205 -0
- package/dist/components/inputs/date-time-field/types.d.ts +84 -0
- package/dist/components/inputs/field-loader.js +5 -0
- package/dist/components/inputs/field-loader.vue_vue_type_script_setup_true_lang.js +30 -0
- package/dist/components/inputs/mask-field/mask-field.js +5 -0
- package/dist/components/inputs/mask-field/mask-field.vue.d.ts +32 -0
- package/dist/components/inputs/mask-field/mask-field.vue_vue_type_script_setup_true_lang.js +120 -0
- package/dist/components/inputs/mask-field/types.d.ts +118 -0
- package/dist/components/inputs/text-field/text-field.js +5 -0
- package/dist/components/inputs/text-field/text-field.vue.d.ts +30 -0
- package/dist/components/inputs/text-field/text-field.vue_vue_type_script_setup_true_lang.js +119 -0
- package/dist/components/inputs/text-field/types.d.ts +70 -0
- package/dist/components/link/link.js +5 -0
- package/dist/components/link/link.vue.d.ts +27 -0
- package/dist/components/link/link.vue_vue_type_script_setup_true_lang.js +32 -0
- package/dist/components/link/types.d.ts +18 -0
- package/dist/components/main/main.js +5 -0
- package/dist/components/main/main.vue.d.ts +33 -0
- package/dist/components/main/main.vue_vue_type_script_setup_true_lang.js +104 -0
- package/dist/components/main/types.d.ts +75 -0
- package/dist/components/navigation-menu/navigation-menu.js +5 -0
- package/dist/components/navigation-menu/navigation-menu.vue_vue_type_script_setup_true_lang.js +207 -0
- package/dist/components/navigation-menu/types.d.ts +62 -0
- package/dist/components/page-transition/page-transition.js +5 -0
- package/dist/components/page-transition/page-transition.vue.d.ts +40 -0
- package/dist/components/page-transition/page-transition.vue_vue_type_script_setup_true_lang.js +27 -0
- package/dist/components/page-transition/types.d.ts +18 -0
- package/dist/components/sections/section/section.js +5 -0
- package/dist/components/sections/section/section.vue.d.ts +28 -0
- package/dist/components/sections/section/section.vue_vue_type_script_setup_true_lang.js +108 -0
- package/dist/components/sections/section/types.d.ts +80 -0
- package/dist/components/sections/section-content/section-content.js +5 -0
- package/dist/components/sections/section-content/section-content.vue.d.ts +27 -0
- package/dist/components/sections/section-content/section-content.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/components/skeleton-loader/skeleton-loader.js +5 -0
- package/dist/components/skeleton-loader/skeleton-loader.vue_vue_type_script_setup_true_lang.js +65 -0
- package/dist/components/table/table.js +5 -0
- package/dist/components/table/table.vue.d.ts +19 -0
- package/dist/components/table/table.vue_vue_type_script_setup_true_lang.js +84 -0
- package/dist/components/table/types.d.ts +51 -0
- package/dist/components.d.ts +23 -896
- package/dist/components.js +23 -1381
- package/dist/composables/alignment/alignment.js +41 -0
- package/dist/composables/alignment/types.d.ts +12 -0
- package/dist/composables/button/button.js +54 -0
- package/dist/composables/colors/constants.js +27 -0
- package/dist/composables/colors/types.d.ts +4 -0
- package/dist/composables/colors/use-vuetify-background-color.js +16 -0
- package/dist/composables/colors/use-vuetify-color.js +11 -0
- package/dist/composables/colors/use-vuetify-text-color.js +12 -0
- package/dist/composables/data-set/data-set.js +128 -0
- package/dist/composables/dialogs/types.d.ts +88 -0
- package/dist/composables/dialogs/use-confirm.d.ts +21 -0
- package/dist/composables/dialogs/use-confirm.js +55 -0
- package/dist/composables/dialogs/use-decorative-timer.js +25 -0
- package/dist/composables/dialogs/use-dialog-focus.js +64 -0
- package/dist/composables/dialogs/use-dialog-loading.js +13 -0
- package/dist/composables/dialogs/use-dialog.d.ts +36 -0
- package/dist/{use-dialog-Ck2_ZW7T.js → composables/dialogs/use-dialog.js} +2 -53
- package/dist/composables/dialogs/use-run-or-toast.d.ts +27 -0
- package/dist/composables/dialogs/use-run-or-toast.js +65 -0
- package/dist/composables/dialogs/use-toast.d.ts +25 -0
- package/dist/composables/dialogs/use-toast.js +39 -0
- package/dist/composables/dimensions/dimensions.js +18 -0
- package/dist/composables/inputs/autocomplete-field.js +39 -0
- package/dist/composables/inputs/date-time-field.js +109 -0
- package/dist/composables/inputs/fields.js +28 -0
- package/dist/composables/inputs/mask-field.js +133 -0
- package/dist/composables/inputs/rules.js +16 -0
- package/dist/composables/inputs/text-field.js +81 -0
- package/dist/composables/navigation/types.d.ts +54 -0
- package/dist/composables/navigation/use-navigation-rail.js +163 -0
- package/dist/composables/navigation/use-navigation-search-shortcut.js +96 -0
- package/dist/composables/navigation/use-route-props.js +21 -0
- package/dist/composables/navigation/use-unsaved-changes.d.ts +35 -0
- package/dist/composables/navigation/use-unsaved-changes.js +88 -0
- package/dist/composables/section/section.js +34 -0
- package/dist/composables.d.ts +6 -193
- package/dist/composables.js +6 -117
- package/dist/consts/icons.d.ts +67 -0
- package/dist/consts/icons.js +69 -0
- package/dist/consts/locale.js +12 -0
- package/dist/consts/types.d.ts +12 -0
- package/dist/index.d.ts +1 -13
- package/dist/index.js +39 -14
- package/dist/plugins.d.ts +15 -4
- package/dist/plugins.js +54 -3
- package/dist/styles/fonts/UnimedSlab-Regular.woff2 +0 -0
- package/dist/styles/fonts/fonts.css +5 -0
- package/dist/styles/settings.scss +155 -0
- package/dist/unit-test.js +11 -7
- package/package.json +11 -11
- package/skills/uimed-vue/SKILL.md +113 -0
- package/skills/uimed-vue/references/api/components/autocomplete-field.md +45 -0
- package/skills/uimed-vue/references/api/components/button.md +48 -0
- package/skills/uimed-vue/references/api/components/checkbox.md +36 -0
- package/skills/uimed-vue/references/api/components/data-sets/data-set-item.md +61 -0
- package/skills/uimed-vue/references/api/components/data-sets/data-set.md +67 -0
- package/skills/uimed-vue/references/api/components/date-time-field.md +44 -0
- package/skills/uimed-vue/references/api/components/details.md +33 -0
- package/skills/uimed-vue/references/api/components/dialog.md +70 -0
- package/skills/uimed-vue/references/api/components/form.md +43 -0
- package/skills/uimed-vue/references/api/components/grid/column.md +41 -0
- package/skills/uimed-vue/references/api/components/grid/container.md +32 -0
- package/skills/uimed-vue/references/api/components/grid/row.md +37 -0
- package/skills/uimed-vue/references/api/components/icon-button.md +37 -0
- package/skills/uimed-vue/references/api/components/img.md +34 -0
- package/skills/uimed-vue/references/api/components/link.md +31 -0
- package/skills/uimed-vue/references/api/components/main.md +174 -0
- package/skills/uimed-vue/references/api/components/mask-field.md +60 -0
- package/skills/uimed-vue/references/api/components/page-transition.md +37 -0
- package/skills/uimed-vue/references/api/components/sections/section-content.md +23 -0
- package/skills/uimed-vue/references/api/components/sections/section.md +61 -0
- package/skills/uimed-vue/references/api/components/table.md +35 -0
- package/skills/uimed-vue/references/api/components/text-field.md +42 -0
- package/skills/uimed-vue/references/api/composables/use-confirm.md +96 -0
- package/skills/uimed-vue/references/api/composables/use-dialog.md +95 -0
- package/skills/uimed-vue/references/api/composables/use-run-or-toast.md +58 -0
- package/skills/uimed-vue/references/api/composables/use-toast.md +48 -0
- package/skills/uimed-vue/references/api/composables/use-unsaved-changes.md +106 -0
- package/skills/uimed-vue/references/api/index.md +1 -0
- package/skills/uimed-vue/references/guide/components/autocomplete-field.md +256 -0
- package/skills/uimed-vue/references/guide/components/button.md +155 -0
- package/skills/uimed-vue/references/guide/components/checkbox.md +113 -0
- package/skills/uimed-vue/references/guide/components/data-set.md +370 -0
- package/skills/uimed-vue/references/guide/components/date-time-field.md +202 -0
- package/skills/uimed-vue/references/guide/components/details.md +76 -0
- package/skills/uimed-vue/references/guide/components/dialog.md +269 -0
- package/skills/uimed-vue/references/guide/components/form.md +96 -0
- package/skills/uimed-vue/references/guide/components/icon-button.md +76 -0
- package/skills/uimed-vue/references/guide/components/img.md +128 -0
- package/skills/uimed-vue/references/guide/components/layout.md +323 -0
- package/skills/uimed-vue/references/guide/components/link.md +47 -0
- package/skills/uimed-vue/references/guide/components/main.md +435 -0
- package/skills/uimed-vue/references/guide/components/mask-field.md +256 -0
- package/skills/uimed-vue/references/guide/components/page-transition.md +111 -0
- package/skills/uimed-vue/references/guide/components/section.md +232 -0
- package/skills/uimed-vue/references/guide/components/table.md +102 -0
- package/skills/uimed-vue/references/guide/components/text-field.md +172 -0
- package/skills/uimed-vue/references/guide/composables/use-confirm.md +123 -0
- package/skills/uimed-vue/references/guide/composables/use-dialog.md +102 -0
- package/skills/uimed-vue/references/guide/composables/use-run-or-toast.md +55 -0
- package/skills/uimed-vue/references/guide/composables/use-toast.md +57 -0
- package/skills/uimed-vue/references/guide/composables/use-unsaved-changes.md +129 -0
- package/skills/uimed-vue/references/guide/getting-started.md +135 -0
- package/skills/uimed-vue/references/guide/icons.md +71 -0
- package/skills/uimed-vue/references/guide/index.md +51 -0
- package/skills/uimed-vue/references/guide/migration-v1-to-v2.md +191 -0
- package/skills/uimed-vue/references/guide/unit-testing.md +85 -0
- package/AGENTS.md +0 -233
- package/CLAUDE.md +0 -1
- package/dist/types-HPMP8IrV.d.ts +0 -49
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
# Componente base
|
|
2
|
+
|
|
3
|
+
O componente destinado a raiz do projeto se chama `Main`.
|
|
4
|
+
|
|
5
|
+
É responsável por carregar o menu superior, o menu de navegação lateral, o rodapé, os componentes utilizados pelos composables de [Toasts](../composables/use-toast.md), [Diálogos](../composables/use-dialog.md), [Confirmações](../composables/use-confirm.md) e [Alterações não salvas](../composables/use-unsaved-changes.md) e os estilos necessários para os demais componentes.
|
|
6
|
+
|
|
7
|
+
## Propriedades
|
|
8
|
+
|
|
9
|
+
### Logo
|
|
10
|
+
|
|
11
|
+
A `logo` nos permite provisionar a URL que será utilizada pelo `Main` para orquestrar a apresentação de uma imagem de logo na aplicação.
|
|
12
|
+
|
|
13
|
+
A logo é decorativa e não é anunciada por leitores de tela, que identificam a aplicação pelo título do menu superior (`title` da prop `app-bar`); por isso, informe o título junto com a `logo`.
|
|
14
|
+
|
|
15
|
+
```vue
|
|
16
|
+
<template>
|
|
17
|
+
<u-main :appBar :logo>
|
|
18
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
19
|
+
</u-main>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script lang="ts" setup>
|
|
23
|
+
import { reactive, ref, watch } from "vue";
|
|
24
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
25
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
26
|
+
|
|
27
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
28
|
+
|
|
29
|
+
const logo = "/uimed-vue/favicon.svg";
|
|
30
|
+
|
|
31
|
+
const appBar = reactive<NonNullable<MainProps["appBar"]>>({
|
|
32
|
+
title: "Menu superior",
|
|
33
|
+
});
|
|
34
|
+
</script>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Menu superior
|
|
38
|
+
|
|
39
|
+
A prop `app-bar` define as configurações para apresentação do menu superior.
|
|
40
|
+
|
|
41
|
+
Para ocultar o menu superior, basta omitir essa prop.
|
|
42
|
+
|
|
43
|
+
As ações do menu superior têm nomes fixos para leitores de tela: "Menu de navegação" (exibido apenas em telas pequenas, que também informa se o menu de navegação está aberto ou fechado), "Ajuda", "Notificações" e "Menu do usuário". Quando há notificações não lidas, o botão de notificações inclui a quantidade no nome, por exemplo "Notificações (2 não lidas)" ou "Notificações (1 não lida)".
|
|
44
|
+
|
|
45
|
+
No menu do usuário aberto, o avatar aparece maior e centralizado, com o nome (`title`) e o `subtitle` do usuário abaixo dele.
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<template>
|
|
49
|
+
<u-main :appBar @update:notifications-open="toggleNotifications">
|
|
50
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
51
|
+
</u-main>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script lang="ts" setup>
|
|
55
|
+
import { reactive, ref, watch } from "vue";
|
|
56
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
57
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
58
|
+
|
|
59
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
60
|
+
|
|
61
|
+
const appBar = reactive<NonNullable<MainProps["appBar"]>>({
|
|
62
|
+
title: "Menu superior",
|
|
63
|
+
help: "https://www.google.com",
|
|
64
|
+
notifications: [
|
|
65
|
+
{
|
|
66
|
+
title: "v1.1",
|
|
67
|
+
subtitle: "Nova versão disponível para instalação.",
|
|
68
|
+
when: "10:30",
|
|
69
|
+
read: false,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
title: "v1",
|
|
73
|
+
subtitle: "Nova versão disponível para testes.",
|
|
74
|
+
when: "Ontem",
|
|
75
|
+
read: false,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: "vBeta",
|
|
79
|
+
subtitle: "Nova versão disponível para testes.",
|
|
80
|
+
when: "29/09/2026",
|
|
81
|
+
read: true,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: "vAlpha",
|
|
85
|
+
subtitle: "Nova versão disponível para testes.",
|
|
86
|
+
when: "28/09/2026",
|
|
87
|
+
read: true,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
user: {
|
|
91
|
+
title: "Rafael Perini",
|
|
92
|
+
subtitle: "UIMed-Vue Co-Creator",
|
|
93
|
+
img: "/uimed-vue/avatar.jpg",
|
|
94
|
+
options: [
|
|
95
|
+
{
|
|
96
|
+
description: "Bibliotecas",
|
|
97
|
+
items: [
|
|
98
|
+
{
|
|
99
|
+
description: "Pkg-template",
|
|
100
|
+
route: "https://nexdom-healthtech.github.io/pkg-template/",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
description: "Shared",
|
|
104
|
+
route: "https://nexdom-healthtech.github.io/shared/",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
description: "UIMed-Vue",
|
|
108
|
+
route: "https://nexdom-healthtech.github.io/uimed-vue/",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
description: "GitHub NEXDOM",
|
|
114
|
+
route: "https://github.com/nexdom-healthtech",
|
|
115
|
+
},
|
|
116
|
+
{ description: "Sair", action: () => window.alert("Saindo...") },
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
function toggleNotifications(open: boolean) {
|
|
122
|
+
if (!open) {
|
|
123
|
+
appBar.notifications = appBar.notifications?.map((notification) => ({
|
|
124
|
+
...notification,
|
|
125
|
+
read: true,
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
</script>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Usuário sem imagem
|
|
133
|
+
|
|
134
|
+
O avatar do usuário mostra a imagem informada em `img`. Sem `img`, ele mostra as iniciais do `title`: a primeira letra do primeiro e do último nome, como "RP" para "Rafael Perini". Sem `img` nem `title`, ele mostra um ícone genérico. A regra vale tanto para o botão do menu superior quanto para o menu do usuário aberto.
|
|
135
|
+
|
|
136
|
+
O avatar é decorativo: leitores de tela não leem as iniciais e continuam anunciando o botão como "Menu do usuário".
|
|
137
|
+
|
|
138
|
+
```vue
|
|
139
|
+
<template>
|
|
140
|
+
<u-main :appBar>
|
|
141
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
142
|
+
</u-main>
|
|
143
|
+
</template>
|
|
144
|
+
|
|
145
|
+
<script lang="ts" setup>
|
|
146
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
147
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
148
|
+
|
|
149
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
150
|
+
|
|
151
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
152
|
+
title: "Menu superior",
|
|
153
|
+
user: {
|
|
154
|
+
title: "Rafael Perini",
|
|
155
|
+
subtitle: "UIMed-Vue Co-Creator",
|
|
156
|
+
options: [{ description: "Sair", action: () => window.alert("Saindo...") }],
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
</script>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Detalhes do usuário
|
|
163
|
+
|
|
164
|
+
Para mostrar mais informações do usuário no menu, como a empresa e o perfil de acesso, use o slot `user-section-details`. O conteúdo aparece abaixo do nome e do subtítulo e acima das opções, com o texto centralizado como eles. O slot aceita qualquer conteúdo, inclusive ações, como um botão para gerenciar o perfil.
|
|
165
|
+
|
|
166
|
+
O slot só é exibido quando há um menu do usuário, ou seja, quando `appBar.user` é informado.
|
|
167
|
+
|
|
168
|
+
```vue
|
|
169
|
+
<template>
|
|
170
|
+
<u-main :appBar>
|
|
171
|
+
<template #user-section-details>
|
|
172
|
+
<u-row>
|
|
173
|
+
<u-column cols="12">
|
|
174
|
+
<strong>Unimed do Estado de Santa Catarina</strong>
|
|
175
|
+
<div>Perfil Administrador</div>
|
|
176
|
+
</u-column>
|
|
177
|
+
</u-row>
|
|
178
|
+
<u-row>
|
|
179
|
+
<u-column cols="12">
|
|
180
|
+
<u-button variant="secondary" full-width @click="manageProfile">
|
|
181
|
+
Gerenciar perfil
|
|
182
|
+
</u-button>
|
|
183
|
+
</u-column>
|
|
184
|
+
</u-row>
|
|
185
|
+
</template>
|
|
186
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
187
|
+
</u-main>
|
|
188
|
+
</template>
|
|
189
|
+
|
|
190
|
+
<script lang="ts" setup>
|
|
191
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
192
|
+
import { UButton, UColumn, UMain, URow } from "@nexdom/uimed-vue/components";
|
|
193
|
+
|
|
194
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
195
|
+
|
|
196
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
197
|
+
title: "Menu superior",
|
|
198
|
+
user: {
|
|
199
|
+
title: "Julyana Costa",
|
|
200
|
+
subtitle: "julyana.costa@example.com",
|
|
201
|
+
options: [{ description: "Sair", action: () => window.alert("Saindo...") }],
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
function manageProfile() {
|
|
206
|
+
window.alert("Abrindo o perfil...");
|
|
207
|
+
}
|
|
208
|
+
</script>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Menu de navegação
|
|
212
|
+
|
|
213
|
+
A prop `navigation-menu` define as configurações para apresentação do menu lateral de navegação.
|
|
214
|
+
|
|
215
|
+
Para ocultar o menu de navegação, basta omitir essa prop.
|
|
216
|
+
|
|
217
|
+
Em telas largas (a partir de 1145px), o menu fica sempre visível à esquerda do conteúdo, recolhido, mostrando apenas os ícones dos itens e grupos do primeiro nível e um item "Buscar". Ele se expande sobre o conteúdo, sem deslocá-lo, enquanto o mouse está sobre ele, enquanto o foco do teclado está nele ou pelo atalho de busca, e volta a se recolher quando o mouse e o foco saem dele. Recolhido, ele destaca o grupo que contém a página atual; expandido, abre esse grupo e destaca apenas o item da página. Ao se recolher, ele fecha os grupos e limpa o texto da busca.
|
|
218
|
+
|
|
219
|
+
Em telas pequenas, o menu fica oculto e é aberto sobre o conteúdo pelo botão "Menu de navegação" do menu superior.
|
|
220
|
+
|
|
221
|
+
Os itens e grupos do primeiro nível do menu exibem um ícone antes da sua descrição, informado pelo nome na propriedade obrigatória `icon`. Os nomes disponíveis estão em [Ícones](../icons.md). Os itens dentro de um grupo não aceitam ícones, para que o menu siga o mesmo padrão visual em todas as aplicações.
|
|
222
|
+
|
|
223
|
+
O menu também conta com um campo de busca que filtra itens e grupos em tempo real, no formato _case-insensitive_.
|
|
224
|
+
|
|
225
|
+
O atalho `Ctrl + K` (`⌘ + K` no macOS), indicado no próprio campo de busca, expande o menu (ou o abre, em telas pequenas) e coloca o foco na busca, com o texto já digitado selecionado. Com o menu expandido ou aberto, o atalho apenas leva o foco de volta à busca. Levar o foco ao item "Buscar" do menu recolhido tem o mesmo efeito. Ele funciona mesmo com o foco em um campo de formulário, mas é ignorado com o foco dentro de diálogos, confirmações, menus suspensos e editores de texto rico, ou no botão de um menu suspenso aberto.
|
|
226
|
+
|
|
227
|
+
A tecla `Esc` recolhe (ou fecha) o menu enquanto o foco está nele ou, se ele foi expandido pelo atalho, mesmo com o foco fora dele (como durante o carregamento, em que a busca desabilitada não recebe o foco). Se o menu foi expandido pelo atalho ou pelo item "Buscar", o foco volta ao elemento que o tinha antes. Recolhido pelo `Esc`, o menu só volta a se expandir quando o mouse entra nele, quando o foco sai e volta a ele, ou pelo atalho.
|
|
228
|
+
|
|
229
|
+
Quando a página tem mais de um `UMain` com menu de navegação, apenas o primeiro responde ao atalho. Por isso, nesta página, `Ctrl + K` abre o menu da demonstração abaixo em vez da busca da documentação, que continua disponível pela tecla `/`.
|
|
230
|
+
|
|
231
|
+
```vue
|
|
232
|
+
<template>
|
|
233
|
+
<u-main :appBar :navigationMenu>
|
|
234
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
235
|
+
</u-main>
|
|
236
|
+
</template>
|
|
237
|
+
|
|
238
|
+
<script lang="ts" setup>
|
|
239
|
+
import { ref, reactive } from "vue";
|
|
240
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
241
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
242
|
+
|
|
243
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
244
|
+
|
|
245
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
246
|
+
title: "Menu superior",
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const navigationMenu: NonNullable<MainProps["navigationMenu"]> = {
|
|
250
|
+
items: [
|
|
251
|
+
{
|
|
252
|
+
description: "Início",
|
|
253
|
+
route: "/",
|
|
254
|
+
icon: "home",
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
description: "Documentação",
|
|
258
|
+
icon: "folder",
|
|
259
|
+
items: [
|
|
260
|
+
{
|
|
261
|
+
description: "Componentes",
|
|
262
|
+
route: "/components",
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
description: "Composables",
|
|
266
|
+
route: "/composables",
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
description: "Configurações",
|
|
272
|
+
icon: "cog",
|
|
273
|
+
action: () => window.alert("Abrindo configurações..."),
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
};
|
|
277
|
+
</script>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Carregamento
|
|
281
|
+
|
|
282
|
+
A prop `loading` exibe skeletons no lugar das ações do menu superior (ajuda, notificações e usuário) e dos itens do menu de navegação, enquanto os dados do usuário e as opções de menu são carregados.
|
|
283
|
+
|
|
284
|
+
A logo e o título continuam visíveis, assim como o botão do menu de navegação, em telas pequenas. O menu de navegação continua se expandindo (ou abrindo, em telas pequenas) normalmente, com a busca e o item "Buscar" desabilitados, e ao final do carregamento os itens aparecem já filtrados pelo texto buscado. Se o menu de notificações estiver aberto quando o carregamento começar, ele é fechado.
|
|
285
|
+
|
|
286
|
+
O conteúdo da página não é afetado: nele, utilize a prop `loading` dos próprios componentes, como o [Section](./section.md).
|
|
287
|
+
|
|
288
|
+
```vue
|
|
289
|
+
<template>
|
|
290
|
+
<u-main :appBar :navigationMenu :loading>
|
|
291
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
292
|
+
</u-main>
|
|
293
|
+
</template>
|
|
294
|
+
|
|
295
|
+
<script lang="ts" setup>
|
|
296
|
+
import { ref } from "vue";
|
|
297
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
298
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
299
|
+
|
|
300
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
301
|
+
|
|
302
|
+
// Altere para `false` quando os dados do usuário e do menu forem carregados
|
|
303
|
+
const loading = ref(true);
|
|
304
|
+
|
|
305
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
306
|
+
title: "Menu superior",
|
|
307
|
+
help: "https://www.google.com",
|
|
308
|
+
notifications: [],
|
|
309
|
+
user: {
|
|
310
|
+
title: "Rafael Perini",
|
|
311
|
+
subtitle: "UIMed-Vue Co-Creator",
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const navigationMenu: NonNullable<MainProps["navigationMenu"]> = {
|
|
316
|
+
items: [
|
|
317
|
+
{
|
|
318
|
+
description: "Início",
|
|
319
|
+
route: "/",
|
|
320
|
+
icon: "home",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
description: "Configurações",
|
|
324
|
+
icon: "cog",
|
|
325
|
+
action: () => window.alert("Abrindo configurações..."),
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
</script>
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Rodapé
|
|
333
|
+
|
|
334
|
+
A prop `footer` exibe um texto fixo na parte inferior da tela, como a versão da aplicação, para que o usuário consiga informá-la ao suporte ao relatar um problema. O texto fica centralizado e o conteúdo da página termina acima do rodapé, sem ficar coberto por ele.
|
|
335
|
+
|
|
336
|
+
Para ocultar o rodapé, basta omitir essa prop ou deixar o seu `description` vazio, por exemplo enquanto o usuário não estiver autenticado. O carregamento (prop `loading`) não afeta o rodapé.
|
|
337
|
+
|
|
338
|
+
```vue
|
|
339
|
+
<template>
|
|
340
|
+
<u-main :appBar :footer="isAuthenticated ? footer : undefined">
|
|
341
|
+
<h2>O conteúdo da página vai aqui...</h2>
|
|
342
|
+
</u-main>
|
|
343
|
+
</template>
|
|
344
|
+
|
|
345
|
+
<script lang="ts" setup>
|
|
346
|
+
import { ref } from "vue";
|
|
347
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
348
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
349
|
+
|
|
350
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
351
|
+
|
|
352
|
+
const isAuthenticated = ref(true);
|
|
353
|
+
|
|
354
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
355
|
+
title: "Menu superior",
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const footer: NonNullable<MainProps["footer"]> = {
|
|
359
|
+
description: "Versão 1.4.2",
|
|
360
|
+
};
|
|
361
|
+
</script>
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Cor de fundo
|
|
365
|
+
|
|
366
|
+
A prop `background` aplica uma cor ao fundo de toda a aplicação, como em landing pages, com as mesmas opções de cor do [Botão](./button.md): `primary`, `secondary`, `positive`, `informative`, `caution` e `danger`. Quando omitida, a aplicação usa o fundo padrão do tema.
|
|
367
|
+
|
|
368
|
+
O texto colocado diretamente sobre o fundo passa a usar a cor associada a ele (branco ou preto). O menu superior, o rodapé, as [Sections](./section.md) e os diálogos mantêm os próprios fundos.
|
|
369
|
+
|
|
370
|
+
Cuide do contraste ao escolher a cor:
|
|
371
|
+
|
|
372
|
+
- `secondary` é a mesma cor do fundo das [Sections](./section.md) e do menu superior, que perdem a separação do restante da página.
|
|
373
|
+
- Evite combinações em que o componente some no fundo, como um botão `primary` ou links sobre o fundo `primary`, ou links e campos de formulário sobre o fundo `danger`.
|
|
374
|
+
|
|
375
|
+
```vue
|
|
376
|
+
<template>
|
|
377
|
+
<u-main background="primary" :appBar>
|
|
378
|
+
<h2>Boas-vindas ao portal</h2>
|
|
379
|
+
</u-main>
|
|
380
|
+
</template>
|
|
381
|
+
|
|
382
|
+
<script lang="ts" setup>
|
|
383
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
384
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
385
|
+
|
|
386
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
387
|
+
|
|
388
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
389
|
+
title: "Menu superior",
|
|
390
|
+
};
|
|
391
|
+
</script>
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Eventos
|
|
395
|
+
|
|
396
|
+
### Notificações
|
|
397
|
+
|
|
398
|
+
O evento `update:notificationsOpen` é emitido sempre que o menu de notificações é aberto ou fechado.
|
|
399
|
+
|
|
400
|
+
```vue
|
|
401
|
+
<template>
|
|
402
|
+
<u-main :app-bar="appBar" @update:notifications-open="onNotificationsOpen">
|
|
403
|
+
<h2>{{ notificationsOpenCount }} interação(ões)</h2>
|
|
404
|
+
</u-main>
|
|
405
|
+
</template>
|
|
406
|
+
|
|
407
|
+
<script lang="ts" setup>
|
|
408
|
+
import { ref } from "vue";
|
|
409
|
+
import type { ComponentProps } from "vue-component-type-helpers";
|
|
410
|
+
import { UMain } from "@nexdom/uimed-vue/components";
|
|
411
|
+
|
|
412
|
+
type MainProps = ComponentProps<typeof UMain>;
|
|
413
|
+
|
|
414
|
+
const notificationsOpenCount = ref(0);
|
|
415
|
+
|
|
416
|
+
const appBar: NonNullable<MainProps["appBar"]> = {
|
|
417
|
+
title: "Menu superior",
|
|
418
|
+
notifications: [],
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
function onNotificationsOpen() {
|
|
422
|
+
notificationsOpenCount.value++;
|
|
423
|
+
}
|
|
424
|
+
</script>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Playground
|
|
428
|
+
|
|
429
|
+
Experimente as combinações de props do componente.
|
|
430
|
+
|
|
431
|
+
## Ver também
|
|
432
|
+
|
|
433
|
+
Consulte a referência de [API do UMain](../../api/components/main.md) para a lista completa de props, slots e eventos.
|
|
434
|
+
|
|
435
|
+
O conteúdo da página ocupa toda a altura visível abaixo do menu superior (e acima do rodapé, quando exibido): para centralizar o formulário de uma tela de login nela, por exemplo, veja [Altura total](./layout.md#altura-total) nos componentes de layout.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Campos com máscara
|
|
2
|
+
|
|
3
|
+
O componente para campos com máscara se chama `MaskField`.
|
|
4
|
+
|
|
5
|
+
Ele funciona como um [campo de texto](./text-field.md), mas formata o valor enquanto o usuário digita, inserindo automaticamente os separadores da máscara (`.`, `-`, `/`, `(`, `)`, espaço). O `v-model` recebe **somente os caracteres digitados**, sem os separadores e com as letras em maiúsculas (por exemplo, `12345678909` para o CPF `123.456.789-09` e `12ABC34501DE35` para o CNPJ `12.ABC.345/01DE-35`), que é o formato normalmente enviado ao backend.
|
|
6
|
+
|
|
7
|
+
> [!Warning]
|
|
8
|
+
> Deve ser utilizado no lugar do `<input>` nativo e do `UTextField` sempre que o valor tiver uma máscara.
|
|
9
|
+
|
|
10
|
+
## Propriedades
|
|
11
|
+
|
|
12
|
+
### Máscaras predefinidas
|
|
13
|
+
|
|
14
|
+
A prop `mask` é obrigatória e define a máscara aplicada ao campo. A biblioteca oferece as seguintes máscaras predefinidas:
|
|
15
|
+
|
|
16
|
+
| `mask` | Máscara | Exemplo exibido | `v-model` |
|
|
17
|
+
| ------- | -------------------- | -------------------------------------------- | ------------------------------------ |
|
|
18
|
+
| `cpf` | `###.###.###-##` | `123.456.789-09` | `12345678909` |
|
|
19
|
+
| `cnpj` | `##.###.###/####-##` | `12.345.678/0001-95`<br>`12.ABC.345/01DE-35` | `12345678000195`<br>`12ABC34501DE35` |
|
|
20
|
+
| `cep` | `#####-###` | `01310-100` | `01310100` |
|
|
21
|
+
| `phone` | `(##) #####-####` | `(11) 91234-5678` | `11912345678` |
|
|
22
|
+
| `date` | `##/##/####` | `31/12/2026` | `31122026` |
|
|
23
|
+
|
|
24
|
+
A máscara `cnpj` aceita tanto o CNPJ numérico quanto o alfanumérico (IN RFB nº 2.229/2024): as 12 primeiras posições aceitam letras de A a Z, sem acento, ou dígitos, e as 2 últimas (os dígitos verificadores), somente dígitos. As letras podem ser digitadas ou coladas em minúsculas: o campo as exibe e as envia ao `v-model` em maiúsculas. O CNPJ alfanumérico só é aceito com `mask="cnpj"`: a máscara `##.###.###/####-##`, informada como máscara personalizada, aceita somente dígitos.
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<template>
|
|
28
|
+
<u-mask-field v-model="cpf" label="CPF" mask="cpf" />
|
|
29
|
+
<u-mask-field v-model="cnpj" label="CNPJ" mask="cnpj" />
|
|
30
|
+
<u-mask-field v-model="cep" label="CEP" mask="cep" />
|
|
31
|
+
<u-mask-field v-model="phone" label="Celular" mask="phone" />
|
|
32
|
+
<u-mask-field v-model="date" label="Data" mask="date" />
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script lang="ts" setup>
|
|
36
|
+
import { ref } from "vue";
|
|
37
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
38
|
+
|
|
39
|
+
const cpf = ref("");
|
|
40
|
+
const cnpj = ref("");
|
|
41
|
+
const cep = ref("");
|
|
42
|
+
const phone = ref("");
|
|
43
|
+
const date = ref("");
|
|
44
|
+
</script>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> [!Tip]
|
|
48
|
+
> A máscara `phone` tem 11 dígitos (DDD e celular). Um telefone fixo, com 10 dígitos, é considerado incompleto e exibe a mensagem "Valor incompleto".
|
|
49
|
+
|
|
50
|
+
> [!Warning]
|
|
51
|
+
> O campo não valida os dígitos verificadores do CPF e do CNPJ nem a existência do documento: ele só confere o formato. Valide o documento no backend da aplicação.
|
|
52
|
+
|
|
53
|
+
> [!Tip]
|
|
54
|
+
> A máscara `date` apenas formata o valor: ela não valida se a data existe (`31/02/2026` é aceito) e o `v-model` fica no formato `DDMMAAAA` (por exemplo, `31122026`). Para datas, prefira os [campos de data e hora](./date-time-field.md), que oferecem seletor, limites e o formato padrão `YYYY-MM-DD`.
|
|
55
|
+
|
|
56
|
+
### Máscaras personalizadas
|
|
57
|
+
|
|
58
|
+
A prop `mask` também aceita a própria máscara, em que `#` representa um dígito (0–9) e qualquer outro caractere é um separador fixo, inserido automaticamente e fora do `v-model`. Os separadores podem ser símbolos, espaços ou letras: em `####-##/####`, o valor `1234561234` é exibido como `1234-56/1234`, e em `Nº ####`, o valor `1234` é exibido como `Nº 1234`. Uma máscara personalizada precisa ter pelo menos um `#`: o tipo da prop `mask` rejeita uma máscara sem ele, assim como o nome de uma máscara predefinida escrito errado (como `cpff`).
|
|
59
|
+
|
|
60
|
+
```vue
|
|
61
|
+
<template>
|
|
62
|
+
<u-mask-field v-model="protocol" label="Protocolo" mask="####-##/####" />
|
|
63
|
+
<u-mask-field v-model="number" label="Número" mask="Nº ####" />
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<script lang="ts" setup>
|
|
67
|
+
import { ref } from "vue";
|
|
68
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
69
|
+
|
|
70
|
+
const protocol = ref("");
|
|
71
|
+
const number = ref("");
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> [!Warning]
|
|
76
|
+
> Evite separadores fixos que o usuário também poderia digitar, como os dígitos de `0800 ###-####` ou o `55` de `+55 (##) #####-####`: quando o campo espera um desses separadores, o caractere igual a ele é lido como o separador, e não como valor. Por exemplo, digitar `0` no campo vazio de `0800 ###-####` não tem efeito, e o `v-model` `0800123` é exibido como `0800 123-`. Nesses casos, deixe o trecho fixo fora da máscara (por exemplo, no `label` ou no `hint`).
|
|
77
|
+
|
|
78
|
+
### Comportamento ao digitar
|
|
79
|
+
|
|
80
|
+
- Somente dígitos são aceitos, exceto nas 12 primeiras posições da máscara `cnpj`, que também aceitam letras de A a Z, sem acento, convertidas para maiúsculas. Os demais caracteres (símbolos, letras acentuadas, `ç` e letras nos dígitos verificadores do CNPJ) são descartados, sem atualizar o `v-model`. O número de caracteres é limitado pela quantidade de posições da máscara (por exemplo, 14 no CNPJ).
|
|
81
|
+
- Um separador aparece assim que a posição anterior a ele é preenchida (`123` vira `123.`). Se o usuário digitar o próprio separador na posição dele, ele não é duplicado.
|
|
82
|
+
- Com a máscara completa, um caractere digitado no final é ignorado. Digitado no meio, ele é inserido, e o último caractere do valor é descartado.
|
|
83
|
+
- Inserir ou apagar um caractere no meio do valor desloca os caracteres seguintes, e um caractere que não cabe na nova posição é descartado. Por exemplo, no CNPJ `12.345.678/90AB-12`, digitar `9` no início desloca a letra `B` para os dígitos verificadores, onde ela é descartada, e o valor passa a ser `91.234.567/890A-12`.
|
|
84
|
+
- `Backspace` logo após um separador apenas move o cursor para antes dele, e o próximo `Backspace` apaga o caractere anterior. Da mesma forma, `Delete` logo antes de um separador move o cursor para depois dele. Ao apagar uma seleção, somente os caracteres selecionados são removidos (uma seleção só com separadores não apaga nada), e o valor é formatado novamente.
|
|
85
|
+
- Ao colar um valor, com ou sem formatação, em maiúsculas ou minúsculas, o resultado é o mesmo: os caracteres que a máscara não aceita são descartados e o excesso é cortado no final.
|
|
86
|
+
- O cursor permanece após o mesmo caractere ao digitar, apagar ou colar no meio do valor, inclusive com teclados com composição de texto (IME).
|
|
87
|
+
- Em dispositivos móveis, o teclado numérico é exibido nas máscaras que aceitam somente dígitos. Na máscara `cnpj`, que aceita letras, é exibido o teclado de texto, já em maiúsculas.
|
|
88
|
+
|
|
89
|
+
> [!Warning]
|
|
90
|
+
> Como o valor é reescrito a cada alteração, o histórico de desfazer do navegador (`Ctrl+Z`) não fica disponível no campo.
|
|
91
|
+
|
|
92
|
+
### Valor inicial
|
|
93
|
+
|
|
94
|
+
Quando o `v-model` chega fora do formato (com a máscara, por exemplo), o campo exibe o valor normalizado, sem alterar o `v-model`. Um `v-model` com letras minúsculas na máscara `cnpj` (como `12abc34501de35`) é exibido em maiúsculas e é válido, e só é enviado em maiúsculas quando o usuário altera o valor. Quando ele não cabe na máscara, por ter mais caracteres do que ela comporta ou caracteres fora do formato dela (como letras no CPF ou nos dígitos verificadores do CNPJ), o campo exibe somente a parte que cabe, e a validação falha com a mensagem "Valor inválido", exibida assim que o campo é validado (ao sair dele ou ao enviar o [formulário](./form.md)). Em todos os casos, o `v-model` só é alterado quando o usuário altera o valor exibido: colar o mesmo valor que já está exibido não o altera.
|
|
95
|
+
|
|
96
|
+
```vue
|
|
97
|
+
<template>
|
|
98
|
+
<u-mask-field v-model="maskedCpf" label="CPF com máscara" mask="cpf" />
|
|
99
|
+
<u-mask-field v-model="longCpf" label="CPF com dígitos a mais" mask="cpf" />
|
|
100
|
+
</template>
|
|
101
|
+
|
|
102
|
+
<script lang="ts" setup>
|
|
103
|
+
import { ref } from "vue";
|
|
104
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
105
|
+
|
|
106
|
+
const maskedCpf = ref("123.456.789-09");
|
|
107
|
+
const longCpf = ref("123456789099");
|
|
108
|
+
</script>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
> [!Important]
|
|
112
|
+
> Trocar a prop `mask` com o campo preenchido (por exemplo, de `cnpj` para `cpf`) não altera o `v-model`: um valor que não cabe na nova máscara é exibido cortado e falha na validação com a mensagem "Valor inválido". Ao trocar a máscara, ajuste ou limpe o valor na aplicação.
|
|
113
|
+
|
|
114
|
+
### Variantes
|
|
115
|
+
|
|
116
|
+
A prop `variant` define a variação de estilo aplicada ao campo. O padrão é `primary`.
|
|
117
|
+
|
|
118
|
+
```vue
|
|
119
|
+
<template>
|
|
120
|
+
<u-mask-field label="Primary" mask="cpf" variant="primary" />
|
|
121
|
+
<u-mask-field label="Secondary" mask="cpf" variant="secondary" />
|
|
122
|
+
</template>
|
|
123
|
+
|
|
124
|
+
<script lang="ts" setup>
|
|
125
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
126
|
+
</script>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Labels, placeholders e mensagens
|
|
130
|
+
|
|
131
|
+
As props `label`, `placeholder` e `hint` funcionam da mesma forma que nos [campos de texto](./text-field.md).
|
|
132
|
+
|
|
133
|
+
Sem a prop `placeholder`, o campo exibe a própria máscara como placeholder, com `0` no lugar de cada `#` e os separadores fixos como na máscara: `000.000.000-00` para `cpf`, `00.000.000/0000-00` para `cnpj`, `00000-000` para `cep` e `Nº 0000` para `Nº ####`. Um `placeholder` informado substitui o padrão, e `placeholder=""` remove o placeholder. Como nos campos de texto, com um `label`, o placeholder só aparece quando o campo está em foco.
|
|
134
|
+
|
|
135
|
+
```vue
|
|
136
|
+
<template>
|
|
137
|
+
<u-mask-field label="CEP" mask="cep" hint="Somente os dígitos são salvos" />
|
|
138
|
+
<u-mask-field label="CPF" mask="cpf" placeholder="Somente números" />
|
|
139
|
+
</template>
|
|
140
|
+
|
|
141
|
+
<script lang="ts" setup>
|
|
142
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
143
|
+
</script>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Validação
|
|
147
|
+
|
|
148
|
+
Enquanto houver um valor sem que a máscara esteja completa (por exemplo, um CNPJ com menos de 14 caracteres), o campo exibe a mensagem "Valor incompleto", e um valor que não cabe na máscara (veja [Valor inicial](#valor-inicial)) exibe a mensagem "Valor inválido". A validação confere somente o formato, e não se o documento é válido. Com a prop `required`, o campo também impede o envio do [formulário](./form.md) enquanto estiver vazio, exibindo a mensagem "Campo obrigatório".
|
|
149
|
+
|
|
150
|
+
```vue
|
|
151
|
+
<template>
|
|
152
|
+
<u-form>
|
|
153
|
+
<u-mask-field label="CPF" mask="cpf" required />
|
|
154
|
+
<u-button type="submit">Enviar</u-button>
|
|
155
|
+
</u-form>
|
|
156
|
+
</template>
|
|
157
|
+
|
|
158
|
+
<script lang="ts" setup>
|
|
159
|
+
import { UButton, UForm, UMaskField } from "@nexdom/uimed-vue/components";
|
|
160
|
+
</script>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Estados
|
|
164
|
+
|
|
165
|
+
#### Desabilitado
|
|
166
|
+
|
|
167
|
+
Utilize a prop `disabled` para indicar ao usuário que não há possibilidade de interação com o campo.
|
|
168
|
+
|
|
169
|
+
```vue
|
|
170
|
+
<template>
|
|
171
|
+
<u-mask-field model-value="12345678909" label="Desabilitado" mask="cpf" disabled />
|
|
172
|
+
</template>
|
|
173
|
+
|
|
174
|
+
<script lang="ts" setup>
|
|
175
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
176
|
+
</script>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Somente leitura
|
|
180
|
+
|
|
181
|
+
Utilize a prop `readonly` para evitar que o valor presente em um campo seja alterado.
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<template>
|
|
185
|
+
<u-mask-field model-value="12345678909" label="Somente leitura" mask="cpf" readonly />
|
|
186
|
+
</template>
|
|
187
|
+
|
|
188
|
+
<script lang="ts" setup>
|
|
189
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
190
|
+
</script>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### Carregamento
|
|
194
|
+
|
|
195
|
+
A prop `loading` exibe um indicador de carregamento no campo enquanto ativa. Nesse estado, o campo mantém o rótulo como nome acessível e fica marcado como ocupado, e leitores de tela ignoram o indicador.
|
|
196
|
+
|
|
197
|
+
```vue
|
|
198
|
+
<template>
|
|
199
|
+
<u-mask-field label="Carregando" mask="cpf" loading />
|
|
200
|
+
</template>
|
|
201
|
+
|
|
202
|
+
<script lang="ts" setup>
|
|
203
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
204
|
+
</script>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Limpável
|
|
208
|
+
|
|
209
|
+
A prop `clearable` exibe um recurso para limpar o campo, que altera o `v-model` para uma `string` vazia.
|
|
210
|
+
|
|
211
|
+
```vue
|
|
212
|
+
<template>
|
|
213
|
+
<u-mask-field v-model="cep" label="Limpável" mask="cep" clearable />
|
|
214
|
+
</template>
|
|
215
|
+
|
|
216
|
+
<script lang="ts" setup>
|
|
217
|
+
import { ref } from "vue";
|
|
218
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
219
|
+
|
|
220
|
+
const cep = ref("01310100");
|
|
221
|
+
</script>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Eventos
|
|
225
|
+
|
|
226
|
+
### Atualização
|
|
227
|
+
|
|
228
|
+
O evento `update:modelValue` será emitido toda vez que o valor do campo for alterado pelo usuário, repassando somente os caracteres do valor, sem os separadores e com as letras em maiúsculas, como uma `string`. Caracteres descartados e separadores digitados não emitem o evento.
|
|
229
|
+
|
|
230
|
+
```vue
|
|
231
|
+
<template>
|
|
232
|
+
<u-mask-field label="Celular" mask="phone" :model-value @update:model-value="onUpdateValue" />
|
|
233
|
+
<p>{{ changes }} alteração(ões): "{{ modelValue }}"</p>
|
|
234
|
+
</template>
|
|
235
|
+
|
|
236
|
+
<script lang="ts" setup>
|
|
237
|
+
import { ref } from "vue";
|
|
238
|
+
import { UMaskField } from "@nexdom/uimed-vue/components";
|
|
239
|
+
|
|
240
|
+
const modelValue = ref("1191234567");
|
|
241
|
+
const changes = ref(0);
|
|
242
|
+
|
|
243
|
+
function onUpdateValue(newValue: string) {
|
|
244
|
+
modelValue.value = newValue;
|
|
245
|
+
changes.value++;
|
|
246
|
+
}
|
|
247
|
+
</script>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Playground
|
|
251
|
+
|
|
252
|
+
Experimente as combinações de props do componente.
|
|
253
|
+
|
|
254
|
+
## Ver também
|
|
255
|
+
|
|
256
|
+
Consulte a referência de [API do UMaskField](../../api/components/mask-field.md) para a lista completa de props e eventos.
|