@nexdom/uimed-vue 2.0.0-beta.8 → 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.
Files changed (222) hide show
  1. package/README.md +1 -1
  2. package/dist/_virtual/_rolldown/runtime.js +7 -0
  3. package/dist/components/app-bar/app-bar.js +5 -0
  4. package/dist/components/app-bar/app-bar.vue_vue_type_script_setup_true_lang.js +286 -0
  5. package/dist/components/app-bar/types.d.ts +96 -0
  6. package/dist/components/button/button.js +5 -0
  7. package/dist/components/button/button.vue.d.ts +31 -0
  8. package/dist/components/button/button.vue_vue_type_script_setup_true_lang.js +97 -0
  9. package/dist/components/button/types.d.ts +65 -0
  10. package/dist/components/data-sets/data-set/data-set.js +5 -0
  11. package/dist/components/data-sets/data-set/data-set.vue.d.ts +47 -0
  12. package/dist/components/data-sets/data-set/data-set.vue_vue_type_script_setup_true_lang.js +157 -0
  13. package/dist/components/data-sets/data-set/types.d.ts +93 -0
  14. package/dist/components/data-sets/data-set-bar.js +5 -0
  15. package/dist/components/data-sets/data-set-bar.vue_vue_type_script_setup_true_lang.js +99 -0
  16. package/dist/components/data-sets/data-set-item/data-set-item.js +5 -0
  17. package/dist/components/data-sets/data-set-item/data-set-item.vue.d.ts +35 -0
  18. package/dist/components/data-sets/data-set-item/data-set-item.vue_vue_type_script_setup_true_lang.js +57 -0
  19. package/dist/components/data-sets/data-set-item/types.d.ts +42 -0
  20. package/dist/components/details/details.js +5 -0
  21. package/dist/components/details/details.vue.d.ts +28 -0
  22. package/dist/components/details/details.vue_vue_type_script_setup_true_lang.js +56 -0
  23. package/dist/components/details/types.d.ts +29 -0
  24. package/dist/components/dialogs/dialog/dialog-host-key.js +10 -0
  25. package/dist/components/dialogs/dialog/dialog.js +5 -0
  26. package/dist/components/dialogs/dialog/dialog.vue.d.ts +36 -0
  27. package/dist/components/dialogs/dialog/dialog.vue_vue_type_script_setup_true_lang.js +112 -0
  28. package/dist/components/dialogs/dialog/types.d.ts +47 -0
  29. package/dist/components/dialogs/dialog-host.js +5 -0
  30. package/dist/components/dialogs/dialog-host.vue_vue_type_script_setup_true_lang.js +81 -0
  31. package/dist/components/dialogs/toast.js +5 -0
  32. package/dist/components/dialogs/toast.vue_vue_type_script_setup_true_lang.js +35 -0
  33. package/dist/components/footer/footer.js +5 -0
  34. package/dist/components/footer/footer.vue_vue_type_script_setup_true_lang.js +31 -0
  35. package/dist/components/footer/types.d.ts +16 -0
  36. package/dist/components/form/form.js +5 -0
  37. package/dist/components/form/form.vue.d.ts +32 -0
  38. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +37 -0
  39. package/dist/components/form/types.d.ts +15 -0
  40. package/dist/components/grid/column/column.js +5 -0
  41. package/dist/components/grid/column/column.vue.d.ts +33 -0
  42. package/dist/components/grid/column/column.vue_vue_type_script_setup_true_lang.js +45 -0
  43. package/dist/components/grid/column/types.d.ts +27 -0
  44. package/dist/components/grid/container/container.js +5 -0
  45. package/dist/components/grid/container/container.vue.d.ts +27 -0
  46. package/dist/components/grid/container/container.vue_vue_type_script_setup_true_lang.js +33 -0
  47. package/dist/components/grid/container/types.d.ts +17 -0
  48. package/dist/components/grid/row/row.js +5 -0
  49. package/dist/components/grid/row/row.vue.d.ts +29 -0
  50. package/dist/components/grid/row/row.vue_vue_type_script_setup_true_lang.js +61 -0
  51. package/dist/components/grid/row/types.d.ts +63 -0
  52. package/dist/components/icon-button/icon-button.js +5 -0
  53. package/dist/components/icon-button/icon-button.vue.d.ts +23 -0
  54. package/dist/components/icon-button/icon-button.vue_vue_type_script_setup_true_lang.js +51 -0
  55. package/dist/components/icon-button/types.d.ts +32 -0
  56. package/dist/components/img/img.js +5 -0
  57. package/dist/components/img/img.vue.d.ts +23 -0
  58. package/dist/components/img/img.vue_vue_type_script_setup_true_lang.js +61 -0
  59. package/dist/components/img/types.d.ts +43 -0
  60. package/dist/components/inputs/autocomplete-field/autocomplete-field.js +5 -0
  61. package/dist/components/inputs/autocomplete-field/autocomplete-field.vue.d.ts +33 -0
  62. package/dist/components/inputs/autocomplete-field/autocomplete-field.vue_vue_type_script_setup_true_lang.js +161 -0
  63. package/dist/components/inputs/autocomplete-field/types.d.ts +84 -0
  64. package/dist/components/inputs/checkbox/checkbox.js +5 -0
  65. package/dist/components/inputs/checkbox/checkbox.vue.d.ts +33 -0
  66. package/dist/components/inputs/checkbox/checkbox.vue_vue_type_script_setup_true_lang.js +71 -0
  67. package/dist/components/inputs/checkbox/types.d.ts +35 -0
  68. package/dist/components/inputs/date-time-field/date-time-field.js +5 -0
  69. package/dist/components/inputs/date-time-field/date-time-field.vue.d.ts +32 -0
  70. package/dist/components/inputs/date-time-field/date-time-field.vue_vue_type_script_setup_true_lang.js +205 -0
  71. package/dist/components/inputs/date-time-field/types.d.ts +84 -0
  72. package/dist/components/inputs/field-loader.js +5 -0
  73. package/dist/components/inputs/field-loader.vue_vue_type_script_setup_true_lang.js +30 -0
  74. package/dist/components/inputs/mask-field/mask-field.js +5 -0
  75. package/dist/components/inputs/mask-field/mask-field.vue.d.ts +32 -0
  76. package/dist/components/inputs/mask-field/mask-field.vue_vue_type_script_setup_true_lang.js +120 -0
  77. package/dist/components/inputs/mask-field/types.d.ts +118 -0
  78. package/dist/components/inputs/text-field/text-field.js +5 -0
  79. package/dist/components/inputs/text-field/text-field.vue.d.ts +30 -0
  80. package/dist/components/inputs/text-field/text-field.vue_vue_type_script_setup_true_lang.js +119 -0
  81. package/dist/components/inputs/text-field/types.d.ts +70 -0
  82. package/dist/components/link/link.js +5 -0
  83. package/dist/components/link/link.vue.d.ts +27 -0
  84. package/dist/components/link/link.vue_vue_type_script_setup_true_lang.js +32 -0
  85. package/dist/components/link/types.d.ts +18 -0
  86. package/dist/components/main/main.js +5 -0
  87. package/dist/components/main/main.vue.d.ts +33 -0
  88. package/dist/components/main/main.vue_vue_type_script_setup_true_lang.js +104 -0
  89. package/dist/components/main/types.d.ts +75 -0
  90. package/dist/components/navigation-menu/navigation-menu.js +5 -0
  91. package/dist/components/navigation-menu/navigation-menu.vue_vue_type_script_setup_true_lang.js +207 -0
  92. package/dist/components/navigation-menu/types.d.ts +62 -0
  93. package/dist/components/page-transition/page-transition.js +5 -0
  94. package/dist/components/page-transition/page-transition.vue.d.ts +40 -0
  95. package/dist/components/page-transition/page-transition.vue_vue_type_script_setup_true_lang.js +27 -0
  96. package/dist/components/page-transition/types.d.ts +18 -0
  97. package/dist/components/sections/section/section.js +5 -0
  98. package/dist/components/sections/section/section.vue.d.ts +28 -0
  99. package/dist/components/sections/section/section.vue_vue_type_script_setup_true_lang.js +108 -0
  100. package/dist/components/sections/section/types.d.ts +80 -0
  101. package/dist/components/sections/section-content/section-content.js +5 -0
  102. package/dist/components/sections/section-content/section-content.vue.d.ts +27 -0
  103. package/dist/components/sections/section-content/section-content.vue_vue_type_script_setup_true_lang.js +16 -0
  104. package/dist/components/skeleton-loader/skeleton-loader.js +5 -0
  105. package/dist/components/skeleton-loader/skeleton-loader.vue_vue_type_script_setup_true_lang.js +65 -0
  106. package/dist/components/table/table.js +5 -0
  107. package/dist/components/table/table.vue.d.ts +19 -0
  108. package/dist/components/table/table.vue_vue_type_script_setup_true_lang.js +84 -0
  109. package/dist/components/table/types.d.ts +51 -0
  110. package/dist/components.d.ts +23 -940
  111. package/dist/components.js +23 -1254
  112. package/dist/composables/alignment/alignment.js +41 -0
  113. package/dist/composables/alignment/types.d.ts +12 -0
  114. package/dist/composables/button/button.js +54 -0
  115. package/dist/composables/colors/constants.js +27 -0
  116. package/dist/composables/colors/types.d.ts +4 -0
  117. package/dist/composables/colors/use-vuetify-background-color.js +16 -0
  118. package/dist/composables/colors/use-vuetify-color.js +11 -0
  119. package/dist/composables/colors/use-vuetify-text-color.js +12 -0
  120. package/dist/composables/data-set/data-set.js +128 -0
  121. package/dist/composables/dialogs/types.d.ts +88 -0
  122. package/dist/composables/dialogs/use-confirm.d.ts +21 -0
  123. package/dist/composables/dialogs/use-confirm.js +55 -0
  124. package/dist/composables/dialogs/use-decorative-timer.js +25 -0
  125. package/dist/composables/dialogs/use-dialog-focus.js +64 -0
  126. package/dist/composables/dialogs/use-dialog-loading.js +13 -0
  127. package/dist/composables/dialogs/use-dialog.d.ts +36 -0
  128. package/dist/composables/dialogs/use-dialog.js +73 -0
  129. package/dist/composables/dialogs/use-run-or-toast.d.ts +27 -0
  130. package/dist/composables/dialogs/use-run-or-toast.js +65 -0
  131. package/dist/composables/dialogs/use-toast.d.ts +25 -0
  132. package/dist/composables/dialogs/use-toast.js +39 -0
  133. package/dist/composables/dimensions/dimensions.js +18 -0
  134. package/dist/composables/inputs/autocomplete-field.js +39 -0
  135. package/dist/composables/inputs/date-time-field.js +109 -0
  136. package/dist/composables/inputs/fields.js +28 -0
  137. package/dist/composables/inputs/mask-field.js +133 -0
  138. package/dist/composables/inputs/rules.js +16 -0
  139. package/dist/composables/inputs/text-field.js +81 -0
  140. package/dist/composables/navigation/types.d.ts +54 -0
  141. package/dist/composables/navigation/use-navigation-rail.js +163 -0
  142. package/dist/composables/navigation/use-navigation-search-shortcut.js +96 -0
  143. package/dist/composables/navigation/use-route-props.js +21 -0
  144. package/dist/composables/navigation/use-unsaved-changes.d.ts +35 -0
  145. package/dist/composables/navigation/use-unsaved-changes.js +88 -0
  146. package/dist/composables/section/section.js +34 -0
  147. package/dist/composables.d.ts +6 -67
  148. package/dist/composables.js +6 -65
  149. package/dist/consts/icons.d.ts +67 -0
  150. package/dist/consts/icons.js +69 -0
  151. package/dist/consts/locale.js +12 -0
  152. package/dist/consts/types.d.ts +12 -0
  153. package/dist/index.d.ts +1 -13
  154. package/dist/index.js +39 -14
  155. package/dist/plugins.d.ts +15 -4
  156. package/dist/plugins.js +54 -3
  157. package/dist/styles/fonts/UnimedSlab-Regular.woff2 +0 -0
  158. package/dist/styles/fonts/fonts.css +5 -0
  159. package/dist/styles/settings.scss +155 -0
  160. package/dist/unit-test.js +11 -7
  161. package/package.json +11 -11
  162. package/skills/uimed-vue/SKILL.md +113 -0
  163. package/skills/uimed-vue/references/api/components/autocomplete-field.md +45 -0
  164. package/skills/uimed-vue/references/api/components/button.md +48 -0
  165. package/skills/uimed-vue/references/api/components/checkbox.md +36 -0
  166. package/skills/uimed-vue/references/api/components/data-sets/data-set-item.md +61 -0
  167. package/skills/uimed-vue/references/api/components/data-sets/data-set.md +67 -0
  168. package/skills/uimed-vue/references/api/components/date-time-field.md +44 -0
  169. package/skills/uimed-vue/references/api/components/details.md +33 -0
  170. package/skills/uimed-vue/references/api/components/dialog.md +70 -0
  171. package/skills/uimed-vue/references/api/components/form.md +43 -0
  172. package/skills/uimed-vue/references/api/components/grid/column.md +41 -0
  173. package/skills/uimed-vue/references/api/components/grid/container.md +32 -0
  174. package/skills/uimed-vue/references/api/components/grid/row.md +37 -0
  175. package/skills/uimed-vue/references/api/components/icon-button.md +37 -0
  176. package/skills/uimed-vue/references/api/components/img.md +34 -0
  177. package/skills/uimed-vue/references/api/components/link.md +31 -0
  178. package/skills/uimed-vue/references/api/components/main.md +174 -0
  179. package/skills/uimed-vue/references/api/components/mask-field.md +60 -0
  180. package/skills/uimed-vue/references/api/components/page-transition.md +37 -0
  181. package/skills/uimed-vue/references/api/components/sections/section-content.md +23 -0
  182. package/skills/uimed-vue/references/api/components/sections/section.md +61 -0
  183. package/skills/uimed-vue/references/api/components/table.md +35 -0
  184. package/skills/uimed-vue/references/api/components/text-field.md +42 -0
  185. package/skills/uimed-vue/references/api/composables/use-confirm.md +96 -0
  186. package/skills/uimed-vue/references/api/composables/use-dialog.md +95 -0
  187. package/skills/uimed-vue/references/api/composables/use-run-or-toast.md +58 -0
  188. package/skills/uimed-vue/references/api/composables/use-toast.md +48 -0
  189. package/skills/uimed-vue/references/api/composables/use-unsaved-changes.md +106 -0
  190. package/skills/uimed-vue/references/api/index.md +1 -0
  191. package/skills/uimed-vue/references/guide/components/autocomplete-field.md +256 -0
  192. package/skills/uimed-vue/references/guide/components/button.md +155 -0
  193. package/skills/uimed-vue/references/guide/components/checkbox.md +113 -0
  194. package/skills/uimed-vue/references/guide/components/data-set.md +370 -0
  195. package/skills/uimed-vue/references/guide/components/date-time-field.md +202 -0
  196. package/skills/uimed-vue/references/guide/components/details.md +76 -0
  197. package/skills/uimed-vue/references/guide/components/dialog.md +269 -0
  198. package/skills/uimed-vue/references/guide/components/form.md +96 -0
  199. package/skills/uimed-vue/references/guide/components/icon-button.md +76 -0
  200. package/skills/uimed-vue/references/guide/components/img.md +128 -0
  201. package/skills/uimed-vue/references/guide/components/layout.md +323 -0
  202. package/skills/uimed-vue/references/guide/components/link.md +47 -0
  203. package/skills/uimed-vue/references/guide/components/main.md +435 -0
  204. package/skills/uimed-vue/references/guide/components/mask-field.md +256 -0
  205. package/skills/uimed-vue/references/guide/components/page-transition.md +111 -0
  206. package/skills/uimed-vue/references/guide/components/section.md +232 -0
  207. package/skills/uimed-vue/references/guide/components/table.md +102 -0
  208. package/skills/uimed-vue/references/guide/components/text-field.md +172 -0
  209. package/skills/uimed-vue/references/guide/composables/use-confirm.md +123 -0
  210. package/skills/uimed-vue/references/guide/composables/use-dialog.md +102 -0
  211. package/skills/uimed-vue/references/guide/composables/use-run-or-toast.md +55 -0
  212. package/skills/uimed-vue/references/guide/composables/use-toast.md +57 -0
  213. package/skills/uimed-vue/references/guide/composables/use-unsaved-changes.md +129 -0
  214. package/skills/uimed-vue/references/guide/getting-started.md +135 -0
  215. package/skills/uimed-vue/references/guide/icons.md +71 -0
  216. package/skills/uimed-vue/references/guide/index.md +51 -0
  217. package/skills/uimed-vue/references/guide/migration-v1-to-v2.md +191 -0
  218. package/skills/uimed-vue/references/guide/unit-testing.md +85 -0
  219. package/AGENTS.md +0 -160
  220. package/CLAUDE.md +0 -1
  221. package/dist/types-BPXXtbmW.d.ts +0 -5
  222. package/dist/use-toast-CACuYhK_.js +0 -53
@@ -0,0 +1,269 @@
1
+ # Janelas modais
2
+
3
+ O componente para apresentar conteúdo em uma janela modal, sobre a página, se chama `Dialog`. Enquanto a janela está aberta, o restante da página fica inacessível.
4
+
5
+ > [!Warning]
6
+ > Deve ser utilizado no lugar do `<dialog>` nativo.
7
+
8
+ A janela abre e fecha pelo `v-model`. Para apresentar apenas uma mensagem ou pedir uma confirmação, prefira as composables [useDialog](../composables/use-dialog.md) e [useConfirm](../composables/use-confirm.md).
9
+
10
+ ## Uso
11
+
12
+ A prop `title` define o título da janela, em texto simples e em uma única linha (títulos longos são cortados com reticências), e o conteúdo vai no slot padrão. A prop `actions` define os botões exibidos no rodapé, alinhados à direita, nesta ordem. Coloque a ação principal por último.
13
+
14
+ Clicar em uma ação **não fecha** a janela: feche-a no `onClick`, alterando o `v-model` para `false`.
15
+
16
+ ```vue
17
+ <template>
18
+ <u-button @click="open = true">Ver detalhes</u-button>
19
+ <u-dialog v-model="open" title="Consulta agendada" :actions>
20
+ A consulta de Maria da Silva foi agendada para 12/10, às 14h, com a Dra. Ana Souza.
21
+ </u-dialog>
22
+ </template>
23
+
24
+ <script lang="ts" setup>
25
+ import { ref } from "vue";
26
+ import type { ComponentProps } from "vue-component-type-helpers";
27
+ import { UButton, UDialog } from "@nexdom/uimed-vue/components";
28
+
29
+ type DialogAction = NonNullable<ComponentProps<typeof UDialog>["actions"]>[number];
30
+
31
+ const open = ref(false);
32
+
33
+ const actions: DialogAction[] = [{ label: "Fechar", onClick: () => (open.value = false) }];
34
+ </script>
35
+ ```
36
+
37
+ ### Fechando a janela
38
+
39
+ Além das ações, o usuário pode fechar a janela pela tecla `Esc` ou clicando fora dela.
40
+
41
+ O botão "voltar" do navegador também fecha a janela, sem sair da página, em aplicações que usam o [Vue Router](https://router.vuejs.org/). A exceção é quando o "voltar" leva a uma página aberta com `router.replace`, como a página pela qual o usuário entrou na aplicação: nesse caso, a navegação acontece e a janela continua aberta.
42
+
43
+ Quando o usuário fecha a janela por um desses meios, ela começa a sumir na hora, mas o `v-model` só passa a ser `false` ao fim da animação de fechamento. Por isso:
44
+
45
+ - atribuir `true` ao `v-model` durante essa animação não tem efeito, porque ele ainda é `true`: a janela termina de fechar e o `v-model` passa a ser `false` em seguida;
46
+ - se o `@update:model-value` recusar a atualização, mantendo o valor `true`, a janela continua fechada com o `v-model` em `true`;
47
+ - se a janela for removida da página antes do fim da animação (por um `v-if`, por exemplo), o `v-model` continua `true`.
48
+
49
+ Enquanto alguma ação apresenta um indicador de carregamento (`loading`), o usuário não consegue fechar a janela por nenhum desses meios: ela faz uma breve animação, continua aberta e o `v-model` não muda. Exceto no caso do `router.replace` acima, o "voltar" também não sai da página nesse meio tempo. Ações apenas desabilitadas (`disabled`) não impedem o fechamento. A aplicação ainda pode fechar a janela a qualquer momento, atribuindo `false` ao `v-model`.
50
+
51
+ Em uma página que usa [useUnsavedChanges](../composables/use-unsaved-changes.md) e tem alterações não salvas, o "voltar" é verificado pela página antes da janela, inclusive durante o carregamento: o diálogo "Alterações não salvas" aparece sobre a janela. "Continuar editando" mantém o usuário na página, com a janela aberta, e "Sair sem salvar" sai da página, mesmo que a ação ainda esteja em carregamento.
52
+
53
+ ```vue
54
+ <template>
55
+ <u-button @click="open = true">Abrir janela</u-button>
56
+ <p>v-model: {{ open }}</p>
57
+ <u-dialog v-model="open" title="Fechando a janela">
58
+ Feche esta janela pela tecla <code>Esc</code> ou clicando fora dela.
59
+ </u-dialog>
60
+ </template>
61
+
62
+ <script lang="ts" setup>
63
+ import { ref } from "vue";
64
+ import { UButton, UDialog } from "@nexdom/uimed-vue/components";
65
+
66
+ const open = ref(false);
67
+ </script>
68
+ ```
69
+
70
+ ### Foco
71
+
72
+ Ao abrir, a janela coloca o foco no primeiro elemento focável do conteúdo, como um campo de formulário, ou, se não houver, na primeira ação. Enquanto a janela está aberta, a tecla `Tab` circula apenas entre os elementos dela. Ao fechar, o foco volta ao elemento que estava focado antes de a janela abrir, como o botão que a abriu.
73
+
74
+ O título é o nome acessível da janela, anunciado por leitores de tela ao abri-la. Sem título, o conteúdo é anunciado no lugar.
75
+
76
+ ## Propriedades
77
+
78
+ ### Formulários
79
+
80
+ Para enviar um formulário pelas ações, use uma ação do tipo `submit` com a prop `form` apontando para o `id` do [formulário](./form.md). O evento `submit` do formulário só é disparado quando não há pendências de validação.
81
+
82
+ Enquanto os dados são salvos, a ação principal pode apresentar um indicador de carregamento (`loading`) e as demais podem ficar desabilitadas (`disabled`). Nesse meio tempo, a janela não fecha pela tecla `Esc`, por um clique fora dela nem pelo botão "voltar": o usuário acompanha o salvamento até o fim, e o exemplo fecha a janela depois de salvar.
83
+
84
+ O exemplo copia o nome para o rascunho ao abrir a janela, e não ao fechá-la: ao cancelar, a ação passa o `v-model` para `false` enquanto a janela ainda está sumindo, e trocar o texto nesse momento seria visível.
85
+
86
+ ```vue
87
+ <template>
88
+ <u-button @click="openForm">Editar paciente</u-button>
89
+ <p>Nome: {{ name }}</p>
90
+ <u-dialog v-model="open" title="Editar paciente" :actions>
91
+ <u-form :id="formId" @submit="save">
92
+ <u-text-field v-model="draft" label="Nome" required />
93
+ </u-form>
94
+ </u-dialog>
95
+ </template>
96
+
97
+ <script lang="ts" setup>
98
+ import { computed, ref, useId } from "vue";
99
+ import type { ComponentProps } from "vue-component-type-helpers";
100
+ import { UButton, UDialog, UForm, UTextField } from "@nexdom/uimed-vue/components";
101
+
102
+ type DialogAction = NonNullable<ComponentProps<typeof UDialog>["actions"]>[number];
103
+
104
+ const formId = useId();
105
+ const open = ref(false);
106
+ const isSaving = ref(false);
107
+ const name = ref("Maria da Silva");
108
+ const draft = ref("");
109
+
110
+ const actions = computed<DialogAction[]>(() => [
111
+ {
112
+ label: "Cancelar",
113
+ variant: "ghost",
114
+ disabled: isSaving.value,
115
+ onClick: () => (open.value = false),
116
+ },
117
+ { label: "Salvar", type: "submit", form: formId, loading: isSaving.value },
118
+ ]);
119
+
120
+ function openForm() {
121
+ draft.value = name.value;
122
+ open.value = true;
123
+ }
124
+
125
+ function savePatient(): Promise<void> {
126
+ return new Promise((resolve) => setTimeout(resolve, 1500));
127
+ }
128
+
129
+ async function save() {
130
+ isSaving.value = true;
131
+ await savePatient();
132
+ name.value = draft.value;
133
+ isSaving.value = false;
134
+ open.value = false;
135
+ }
136
+ </script>
137
+ ```
138
+
139
+ ### Tamanhos
140
+
141
+ A prop `size` define a largura máxima da janela: `small` (400px), `medium` (560px) ou `large` (800px). O padrão é `medium`.
142
+
143
+ ```vue
144
+ <template>
145
+ <u-button variant="secondary" @click="openSize('small')">Pequena</u-button>
146
+ <u-button variant="secondary" @click="openSize('medium')">Média</u-button>
147
+ <u-button variant="secondary" @click="openSize('large')">Grande</u-button>
148
+ <u-dialog v-model="open" :title="`Tamanho ${size}`" :size :actions>
149
+ Esta janela usa o tamanho <code>{{ size }}</code
150
+ >.
151
+ </u-dialog>
152
+ </template>
153
+
154
+ <script lang="ts" setup>
155
+ import { ref } from "vue";
156
+ import type { ComponentProps } from "vue-component-type-helpers";
157
+ import { UButton, UDialog } from "@nexdom/uimed-vue/components";
158
+
159
+ type DialogProps = ComponentProps<typeof UDialog>;
160
+ type DialogSize = NonNullable<DialogProps["size"]>;
161
+ type DialogAction = NonNullable<DialogProps["actions"]>[number];
162
+
163
+ const open = ref(false);
164
+ const size = ref<DialogSize>("medium");
165
+
166
+ const actions: DialogAction[] = [{ label: "Fechar", onClick: () => (open.value = false) }];
167
+
168
+ function openSize(value: DialogSize) {
169
+ size.value = value;
170
+ open.value = true;
171
+ }
172
+ </script>
173
+ ```
174
+
175
+ ### Conteúdo longo
176
+
177
+ Quando o conteúdo não cabe na tela, apenas ele rola: o título e as ações continuam visíveis.
178
+
179
+ ```vue
180
+ <template>
181
+ <u-button @click="open = true">Ler termos</u-button>
182
+ <u-dialog v-model="open" title="Termos de uso" :actions>
183
+ <p v-for="index in 20" :key="index">
184
+ {{ index }}. O paciente autoriza o uso dos seus dados de saúde exclusivamente para fins de
185
+ atendimento, conforme a legislação vigente.
186
+ </p>
187
+ </u-dialog>
188
+ </template>
189
+
190
+ <script lang="ts" setup>
191
+ import { ref } from "vue";
192
+ import type { ComponentProps } from "vue-component-type-helpers";
193
+ import { UButton, UDialog } from "@nexdom/uimed-vue/components";
194
+
195
+ type DialogAction = NonNullable<ComponentProps<typeof UDialog>["actions"]>[number];
196
+
197
+ const open = ref(false);
198
+
199
+ const actions: DialogAction[] = [
200
+ { label: "Recusar", variant: "ghost", onClick: () => (open.value = false) },
201
+ { label: "Aceitar", onClick: () => (open.value = false) },
202
+ ];
203
+ </script>
204
+ ```
205
+
206
+ ### Confirmações a partir da janela
207
+
208
+ Diálogos das composables [useDialog](../composables/use-dialog.md) e [useConfirm](../composables/use-confirm.md) abertos por uma ação aparecem sobre a janela. Ao fechá-los, o foco volta para a janela ou, se ela também tiver sido fechada, para o elemento que a abriu.
209
+
210
+ ```vue
211
+ <template>
212
+ <u-main>
213
+ <u-button @click="open = true">Ver prontuário</u-button>
214
+ <p>Prontuário: {{ status }}</p>
215
+ <u-dialog v-model="open" title="Prontuário" :actions>
216
+ Maria da Silva, 42 anos. Última consulta em 12/09.
217
+ </u-dialog>
218
+ </u-main>
219
+ </template>
220
+
221
+ <script lang="ts" setup>
222
+ import { computed, ref } from "vue";
223
+ import type { ComponentProps } from "vue-component-type-helpers";
224
+ import { UButton, UDialog, UMain } from "@nexdom/uimed-vue/components";
225
+ import { useConfirm } from "@nexdom/uimed-vue/composables";
226
+
227
+ type DialogAction = NonNullable<ComponentProps<typeof UDialog>["actions"]>[number];
228
+
229
+ const { confirm, isRunning } = useConfirm();
230
+ const open = ref(false);
231
+ const status = ref("ativo");
232
+
233
+ const actions = computed<DialogAction[]>(() => [
234
+ { label: "Fechar", variant: "ghost", onClick: () => (open.value = false) },
235
+ { label: "Excluir", color: "danger", loading: isRunning.value, onClick: remove },
236
+ ]);
237
+
238
+ function removeRecord(): Promise<boolean> {
239
+ return new Promise((resolve) => setTimeout(() => resolve(true), 1500));
240
+ }
241
+
242
+ async function remove() {
243
+ const removed = await confirm(
244
+ {
245
+ title: "Excluir prontuário",
246
+ message: "Esta ação não pode ser desfeita.",
247
+ confirmText: "Excluir",
248
+ color: "danger",
249
+ },
250
+ removeRecord,
251
+ );
252
+
253
+ if (removed) {
254
+ status.value = "excluído";
255
+ open.value = false;
256
+ }
257
+ }
258
+ </script>
259
+ ```
260
+
261
+ ## Playground
262
+
263
+ Experimente as combinações de props do componente.
264
+
265
+ ## Ver também
266
+
267
+ - Consulte a referência de [API do UDialog](../../api/components/dialog.md) para a lista completa de props, eventos e slots.
268
+ - Para apresentar mensagens ou perguntas simples, use a composable [useDialog](../composables/use-dialog.md).
269
+ - Para confirmar uma ação antes de executá-la, use a composable [useConfirm](../composables/use-confirm.md).
@@ -0,0 +1,96 @@
1
+ # Formulários
2
+
3
+ O componente que engloba os formulários se chama `Form` dentro do uimed-vue.
4
+
5
+ > [!Warning]
6
+ > Deve ser utilizado no lugar do `<form>` nativo.
7
+
8
+ ## Eventos
9
+
10
+ ### Envio
11
+
12
+ O evento `submit` é emitido quando o formulário é enviado, repassando o `SubmitEvent` nativo. Ele não é disparado quando restam campos com pendências de validação.
13
+
14
+ ```vue
15
+ <template>
16
+ <u-section title="Cadastro" :subtitle :actions>
17
+ <u-section-content>
18
+ <u-form :id="formId" @submit="onSubmit">
19
+ <u-text-field label="Nome" required />
20
+ <u-text-field label="Sobrenome" required />
21
+ </u-form>
22
+ </u-section-content>
23
+ </u-section>
24
+ </template>
25
+
26
+ <script lang="ts" setup>
27
+ import type { ComponentProps } from "vue-component-type-helpers";
28
+ import { UForm, UTextField, USection, USectionContent } from "@nexdom/uimed-vue/components";
29
+ import { ref, useId, computed } from "vue";
30
+
31
+ type SectionAction = NonNullable<ComponentProps<typeof USection>["actions"]>[number];
32
+
33
+ const submits = ref(0);
34
+ const formId = useId();
35
+
36
+ const subtitle = computed(() => `Pessoa - ${submits.value} envio(s)`);
37
+
38
+ const actions: SectionAction[] = [{ type: "submit", label: "Enviar", form: formId }];
39
+
40
+ function onSubmit() {
41
+ submits.value++;
42
+ alert("Enviado com sucesso!");
43
+ }
44
+ </script>
45
+ ```
46
+
47
+ ### Envio com carregamento
48
+
49
+ Um botão de envio com `loading` fica desabilitado e não envia o formulário. Quando ele é o primeiro botão de envio do formulário, pressionar `Enter` em um dos campos também não envia o formulário. Isso vale também para os botões de fora do formulário relacionados a ele pela prop `form`, como as ações de uma seção. Assim, basta manter o botão de envio com `loading` enquanto o envio é executado para evitar envios repetidos. Com mais de um botão de envio, mantenha todos com `loading` ou `disabled` durante o envio.
50
+
51
+ > [!Tip]
52
+ > O `isRunning` do [`useRunOrToast`](../composables/use-run-or-toast.md) pode controlar o `loading` do botão enquanto o envio é executado.
53
+
54
+ Preencha os campos e pressione `Enter` em um deles, ou clique em "Enviar", para simular um envio de 1,5 segundo.
55
+
56
+ ```vue
57
+ <template>
58
+ <u-section title="Cadastro" :subtitle :actions>
59
+ <u-section-content>
60
+ <u-form :id="formId" @submit="onSubmit">
61
+ <u-text-field label="Nome" required />
62
+ <u-text-field label="Sobrenome" required />
63
+ </u-form>
64
+ </u-section-content>
65
+ </u-section>
66
+ </template>
67
+
68
+ <script lang="ts" setup>
69
+ import type { ComponentProps } from "vue-component-type-helpers";
70
+ import { UForm, UTextField, USection, USectionContent } from "@nexdom/uimed-vue/components";
71
+ import { ref, useId, computed } from "vue";
72
+
73
+ type SectionAction = NonNullable<ComponentProps<typeof USection>["actions"]>[number];
74
+
75
+ const submits = ref(0);
76
+ const isSubmitting = ref(false);
77
+ const formId = useId();
78
+
79
+ const subtitle = computed(() => `Pessoa - ${submits.value} envio(s)`);
80
+
81
+ const actions = computed<SectionAction[]>(() => [
82
+ { type: "submit", label: "Enviar", form: formId, loading: isSubmitting.value },
83
+ ]);
84
+
85
+ async function onSubmit() {
86
+ submits.value++;
87
+ isSubmitting.value = true;
88
+ await new Promise((resolve) => setTimeout(resolve, 1500));
89
+ isSubmitting.value = false;
90
+ }
91
+ </script>
92
+ ```
93
+
94
+ ## Ver também
95
+
96
+ Consulte a referência de [API do UForm](../../api/components/form.md) para a lista completa de props, slots e eventos.
@@ -0,0 +1,76 @@
1
+ # Botões de ícone
2
+
3
+ O componente para botões que exibem apenas um ícone se chama `IconButton`.
4
+
5
+ Use-o para ações que o ícone basta para identificar, como editar um registro de uma listagem. Quando a ação precisa de um texto para ser entendida, use o [Button](./button.md).
6
+
7
+ O ícone é ignorado pelos leitores de tela, que anunciam no lugar dele o texto da prop `label`, obrigatória. Por isso, esse texto deve descrever a ação do botão (por exemplo, "Editar paciente"), e não o desenho do ícone (por exemplo, "Lápis").
8
+
9
+ ## Propriedades
10
+
11
+ ### Ícone
12
+
13
+ A prop `icon`, obrigatória, recebe o nome de um dos ícones listados em [Ícones](../icons.md).
14
+
15
+ ```vue
16
+ <template>
17
+ <u-icon-button icon="home" label="Início" />
18
+ <u-icon-button icon="calendar" label="Agenda" />
19
+ <u-icon-button icon="cogAlternative" label="Configurações" />
20
+ </template>
21
+
22
+ <script lang="ts" setup>
23
+ import { UIconButton } from "@nexdom/uimed-vue/components";
24
+ </script>
25
+ ```
26
+
27
+ ### Cores
28
+
29
+ A prop `color` aceita um dos valores da paleta do componente: `primary`, `secondary`, `positive`, `informative`, `caution` ou `danger`. O padrão é `primary`.
30
+
31
+ ```vue
32
+ <template>
33
+ <u-icon-button icon="account" label="Perfil" color="primary" />
34
+ <u-icon-button icon="cog" label="Configurações" color="secondary" />
35
+ <u-icon-button icon="calendar" label="Agenda" color="positive" />
36
+ <u-icon-button icon="fileDocument" label="Documentos" color="informative" />
37
+ <u-icon-button icon="folder" label="Cadastros" color="caution" />
38
+ <u-icon-button icon="wallet" label="Financeiro" color="danger" />
39
+ </template>
40
+
41
+ <script lang="ts" setup>
42
+ import { UIconButton } from "@nexdom/uimed-vue/components";
43
+ </script>
44
+ ```
45
+
46
+ ## Eventos
47
+
48
+ ### Clique
49
+
50
+ O evento `click` é emitido ao clicar no botão, repassando o `MouseEvent` nativo.
51
+
52
+ ```vue
53
+ <template>
54
+ <u-icon-button icon="accountGroup" label="Adicionar paciente" @click="onClick" />
55
+ <span>{{ clicks }} paciente(s)</span>
56
+ </template>
57
+
58
+ <script lang="ts" setup>
59
+ import { ref } from "vue";
60
+ import { UIconButton } from "@nexdom/uimed-vue/components";
61
+
62
+ const clicks = ref(0);
63
+
64
+ function onClick() {
65
+ clicks.value++;
66
+ }
67
+ </script>
68
+ ```
69
+
70
+ ## Playground
71
+
72
+ Experimente as combinações de props do componente.
73
+
74
+ ## Ver também
75
+
76
+ Consulte a referência de [API do UIconButton](../../api/components/icon-button.md) para a lista completa de props e eventos, e [Ícones](../icons.md) para todos os ícones disponíveis.
@@ -0,0 +1,128 @@
1
+ # Imagens
2
+
3
+ O componente padrão para exibir imagens se chama `Img`.
4
+
5
+ > [!Warning]
6
+ > Deve ser utilizado no lugar do `<img>` nativo.
7
+
8
+ As imagens são decorativas: leitores de tela as ignoram. Quando a imagem transmite informação, apresente essa informação também em texto na página.
9
+
10
+ Por padrão, a imagem só é carregada quando está prestes a aparecer na tela. Até lá, e enquanto ela carrega, o espaço reservado para ela fica vazio. Informe as dimensões da imagem (`width` e `height`, ou `aspectRatio`) para reservar esse espaço e evitar que o conteúdo da página se desloque quando ela aparecer.
11
+
12
+ > [!Warning]
13
+ > Coloque a imagem dentro de uma `UColumn`. Diretamente dentro de uma `URow`, sem coluna, a imagem ignora a `width` e ocupa toda a largura da linha.
14
+
15
+ ## Propriedades
16
+
17
+ ### Dimensões
18
+
19
+ As props `width` e `height` definem a largura e a altura da imagem e reservam esse espaço antes de ela carregar. Números são medidas em pixels, e textos aceitam qualquer unidade CSS, como `"50%"`, relativa à largura da coluna.
20
+
21
+ Dentro de uma `UColumn`, a largura nunca ultrapassa a da coluna: quando é maior, a imagem encolhe até a largura da coluna, mantendo a altura informada.
22
+
23
+ ```vue
24
+ <template>
25
+ <u-row>
26
+ <u-column>
27
+ <u-img src="/logo.svg" :width="187" :height="239" />
28
+ </u-column>
29
+ </u-row>
30
+ </template>
31
+
32
+ <script lang="ts" setup>
33
+ import { UColumn, UImg, URow } from "@nexdom/uimed-vue/components";
34
+ </script>
35
+ ```
36
+
37
+ Com uma porcentagem em `width` e uma `aspectRatio`, a imagem acompanha a largura da coluna e mantém a proporção.
38
+
39
+ ```vue
40
+ <template>
41
+ <u-row>
42
+ <u-column>
43
+ <u-img src="/foto.jpg" width="50%" :aspect-ratio="3 / 4" />
44
+ </u-column>
45
+ </u-row>
46
+ </template>
47
+
48
+ <script lang="ts" setup>
49
+ import { UColumn, UImg, URow } from "@nexdom/uimed-vue/components";
50
+ </script>
51
+ ```
52
+
53
+ ### Proporção
54
+
55
+ A prop `aspectRatio` define a proporção entre a largura e a altura da imagem (por exemplo, `16 / 9`). A altura é calculada a partir da largura, então o espaço é reservado mesmo quando a largura depende da coluna.
56
+
57
+ Sem `width`, a imagem ocupa toda a largura da coluna. Quando `height` também é informada, ela prevalece sobre a `aspectRatio`.
58
+
59
+ ```vue
60
+ <template>
61
+ <u-row>
62
+ <u-column cols="4">
63
+ <u-img src="/foto.jpg" :aspect-ratio="3 / 4" />
64
+ </u-column>
65
+ <u-column cols="8">
66
+ <u-img src="/foto.jpg" :width="120" :aspect-ratio="3 / 4" />
67
+ </u-column>
68
+ </u-row>
69
+ </template>
70
+
71
+ <script lang="ts" setup>
72
+ import { UColumn, UImg, URow } from "@nexdom/uimed-vue/components";
73
+ </script>
74
+ ```
75
+
76
+ ### Preenchimento
77
+
78
+ Por padrão, a imagem é exibida por inteiro dentro do espaço reservado, que pode ficar com sobras quando a proporção da imagem é diferente da do espaço.
79
+
80
+ A prop `cover` faz a imagem preencher todo o espaço, recortando o que exceder. Ela só faz diferença quando a proporção do espaço é definida, com `width` e `height` ou com `aspectRatio`.
81
+
82
+ ```vue
83
+ <template>
84
+ <u-row>
85
+ <u-column cols="6">
86
+ <u-img src="/foto.jpg" :width="240" :height="160" />
87
+ </u-column>
88
+ <u-column cols="6">
89
+ <u-img src="/foto.jpg" :width="240" :height="160" cover />
90
+ </u-column>
91
+ </u-row>
92
+ </template>
93
+
94
+ <script lang="ts" setup>
95
+ import { UColumn, UImg, URow } from "@nexdom/uimed-vue/components";
96
+ </script>
97
+ ```
98
+
99
+ ### Carregamento imediato
100
+
101
+ Por padrão, a imagem só é carregada quando está prestes a aparecer na tela, o que economiza dados em páginas com muitas imagens.
102
+
103
+ A prop `eager` carrega a imagem assim que a página é aberta. Use-a em imagens visíveis desde a abertura da página, como a logo de uma tela de login.
104
+
105
+ ```vue
106
+ <template>
107
+ <u-row>
108
+ <u-column cols="6">
109
+ <u-img src="/foto.jpg" :width="120" :height="160" />
110
+ </u-column>
111
+ <u-column cols="6">
112
+ <u-img src="/foto.jpg" :width="120" :height="160" eager />
113
+ </u-column>
114
+ </u-row>
115
+ </template>
116
+
117
+ <script lang="ts" setup>
118
+ import { UColumn, UImg, URow } from "@nexdom/uimed-vue/components";
119
+ </script>
120
+ ```
121
+
122
+ ## Playground
123
+
124
+ Experimente as combinações de props do componente.
125
+
126
+ ## Ver também
127
+
128
+ Consulte a referência de [API do UImg](../../api/components/img.md) para a lista completa de props.