@nexdom/uimed-vue 2.0.0-beta.59 → 2.0.0-beta.60

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 (154) hide show
  1. package/AGENTS.md +2 -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/{types-BbWo6RIy.d.ts → components/button/types.d.ts} +4 -8
  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 +91 -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 +92 -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 +102 -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 +145 -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 +22 -1922
  111. package/dist/components.js +22 -3357
  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/{use-dialog-Bn54H-K3.js → composables/dialogs/use-dialog.js} +1 -63
  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-search-shortcut.js +97 -0
  142. package/dist/composables/navigation/use-route-props.js +21 -0
  143. package/dist/composables/navigation/use-unsaved-changes.d.ts +35 -0
  144. package/dist/composables/navigation/use-unsaved-changes.js +88 -0
  145. package/dist/composables/section/section.js +34 -0
  146. package/dist/composables.d.ts +5 -278
  147. package/dist/composables.js +5 -201
  148. package/dist/consts/icons.d.ts +67 -0
  149. package/dist/{icons-H53IqH1s.js → consts/icons.js} +1 -1
  150. package/dist/{locale-CM4o8cD_.js → consts/locale.js} +1 -1
  151. package/dist/consts/types.d.ts +12 -0
  152. package/dist/index.js +2 -2
  153. package/dist/unit-test.js +3 -8
  154. package/package.json +4 -1
package/AGENTS.md CHANGED
@@ -114,7 +114,7 @@ On Windows, prefer VSCode's "Dev Containers: Clone Repository in Container Volum
114
114
  - `vpr test:mutations` — mutation tests (Stryker; thresholds: high 100, low 100, break 100). It starts one test runner per CPU core; on machines with limited memory, run `vpx stryker run --concurrency 4` instead
115
115
  - `vpr test:e2e` — E2E tests (Playwright, runs against the built docs preview site). Outside CI it reuses any server already on port 4173, which is also `vpr docs:dev`'s port: stop the dev server first, or the tests run against it instead of the built site. A running `vitepress preview` keeps serving the build it started with, so restart it after rebuilding the docs
116
116
  - `vpr depcruise` — architecture/dependency rules (dependency-cruiser)
117
- - `vp pack` / `vpr build` — build the library
117
+ - `vp pack` / `vpr build` — build the library. It publishes one module per source file (`unbundle` in `vite.config.ts`), and the entry points import them instead of copying their code, so the apps' bundlers can split the components by the route that uses them
118
118
  - `vpr docs` / `vpr docs:dev` — run docs site (imports the lib from `dist`, not `src` — run `vpr dev` in a second terminal to keep `dist` updated while iterating)
119
119
 
120
120
  CI (`.github/workflows/ci.yml`) runs, in order: commitlint on PR commits, `vp pack`, `vpr check`, `vpr depcruise`, `vp test --coverage`, `vpr test:mutations`, `vpr test:e2e`, and then the SonarQube analysis (`vpr sonar`), whose quality gate fails the PR on any issue or unreviewed security hotspot in `src/` (see [Static analysis](#static-analysis-sonarqube)). Match this locally before opening a PR.
@@ -212,6 +212,7 @@ Use an existing composable (e.g. `use-toast`) as the reference, and deliver in t
212
212
  - Components use the map for their own icons too (`icons.help`, `icons.close`), never `$` aliases nor `mdi-*` strings.
213
213
  - The map is also Vuetify's alias set (`createUimed()` and `vueTestUtilsPluginUimed()` pass it as `aliases`), since Vuetify's components draw some icons by alias on their own (e.g. `$clear` in clearable fields, `$prev`/`$next` in the pagination). It only has the aliases the library's components render, so a component that renders a new one (a new Vuetify component or prop) needs it added to the map, named exactly as the alias; without it, the icon is drawn empty, without a warning. Add each state that renders an alias to `src/consts/__tests__/icon-aliases.test.ts`, which fails on icons drawn without a path of `@mdi/js`.
214
214
  - Pure helpers that don't use Vue live in `src/utils/<name>.ts`, with tests in `src/utils/__tests__/`. Generic helpers that any TypeScript project could use (e.g. `isDeepEqual`) belong in `@nexdom/shared` instead.
215
+ - No module in `src` has side effects at its top level (code that must run just because the module is imported, such as registering something globally), except the CSS imports of `src/index.ts`: `package.json` declares `"sideEffects": ["*.css"]`, so the apps' bundlers drop or move to another chunk any other module whose exports aren't used. A new side effect means adding its built file (e.g. `./dist/...`) to `sideEffects`.
215
216
  - Public components/composables are re-exported from `src/components/index.ts` and `src/composables/index.ts`. Prop types stay internal (`types.ts` is not re-exported); consumers derive them with `ComponentProps` (see [Usage](#usage)).
216
217
  - Every publicly exported component must use the `U` prefix on its export identifier (e.g., `UButton`, `UMain`), while internal file names and component names remain unprefixed.
217
218
  - Use [JSDoc](https://jsdoc.app/about-getting-started) on every method/prop/type intended to be part of the public API — it's the primary documentation surface and supports markdown/code examples.
@@ -0,0 +1,7 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
3
+ if (typeof require !== "undefined") return require.apply(this, arguments);
4
+ throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
5
+ });
6
+ //#endregion
7
+ export { __require };
@@ -0,0 +1,5 @@
1
+ import app_bar_vue_vue_type_script_setup_true_lang_default from "./app-bar.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/app-bar/app-bar.vue
3
+ var app_bar_default = app_bar_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { app_bar_default as default };
@@ -0,0 +1,286 @@
1
+ import { icons } from "../../consts/icons.js";
2
+ import useRouteProps, { routeToListItemProps } from "../../composables/navigation/use-route-props.js";
3
+ import { useNavigationShortcutKeys } from "../../composables/navigation/use-navigation-search-shortcut.js";
4
+ import skeleton_loader_default from "../skeleton-loader/skeleton-loader.js";
5
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, openBlock, renderList, renderSlot, toDisplayString, unref, useModel, useSlots, watch, withCtx } from "vue";
6
+ import { VAppBar, VAppBarNavIcon, VAppBarTitle, VAvatar, VBadge, VBtn, VCard, VCardItem, VCardText, VDivider, VIcon, VImg, VList, VListGroup, VListItem, VListItemAction, VListSubheader, VMenu } from "vuetify/components";
7
+ import { toInitials } from "@nexdom/shared/utils";
8
+ //#region src/components/app-bar/app-bar.vue?vue&type=script&setup=true&lang.ts
9
+ const _hoisted_1 = { class: "text-high-emphasis" };
10
+ const _hoisted_2 = { class: "text-medium-emphasis" };
11
+ var app_bar_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
12
+ inheritAttrs: false,
13
+ __name: "app-bar",
14
+ props: /*@__PURE__*/ mergeModels({
15
+ dataTestid: {
16
+ type: String,
17
+ required: false
18
+ },
19
+ title: {
20
+ type: String,
21
+ required: false
22
+ },
23
+ help: {
24
+ type: null,
25
+ required: false
26
+ },
27
+ user: {
28
+ type: Object,
29
+ required: false
30
+ },
31
+ notifications: {
32
+ type: Array,
33
+ required: false
34
+ },
35
+ navigation: {
36
+ type: Boolean,
37
+ required: false
38
+ },
39
+ logo: {
40
+ type: String,
41
+ required: false
42
+ },
43
+ loading: {
44
+ type: Boolean,
45
+ required: false
46
+ }
47
+ }, {
48
+ "notificationsOpen": {
49
+ type: Boolean,
50
+ default: false
51
+ },
52
+ "notificationsOpenModifiers": {},
53
+ "navigationOpen": { type: Boolean },
54
+ "navigationOpenModifiers": {}
55
+ }),
56
+ emits: ["update:notificationsOpen", "update:navigationOpen"],
57
+ setup(__props) {
58
+ const props = __props;
59
+ const slots = useSlots();
60
+ const notificationsOpen = useModel(__props, "notificationsOpen");
61
+ const navigationOpen = useModel(__props, "navigationOpen");
62
+ const { ariaKeyshortcuts: navigationKeyshortcuts } = useNavigationShortcutKeys();
63
+ const helpBtnDataTestid = computed(() => `${props.dataTestid}-help`);
64
+ const notificationsBtnDataTestid = computed(() => `${props.dataTestid}-notifications`);
65
+ const navigationBtnDataTestid = computed(() => `${props.dataTestid}-navigation`);
66
+ const notificationsMenuDataTestid = computed(() => `${props.dataTestid}-notifications-menu`);
67
+ const userBtnDataTestid = computed(() => `${props.dataTestid}-user`);
68
+ const userMenuDataTestid = computed(() => `${props.dataTestid}-user-menu`);
69
+ const showHelp = computed(() => !!props.help);
70
+ const routeProps = useRouteProps(() => props.help);
71
+ const showNotifications = computed(() => !!props.notifications);
72
+ const unreadCount = computed(() => props.notifications.filter((notification) => !notification.read).length);
73
+ const hasUnreadNotifications = computed(() => unreadCount.value > 0);
74
+ const unreadLabel = computed(() => unreadCount.value === 1 ? "1 não lida" : `${unreadCount.value} não lidas`);
75
+ const notificationsLabel = computed(() => hasUnreadNotifications.value ? `Notificações (${unreadLabel.value})` : "Notificações");
76
+ watch(() => props.loading, (loading) => {
77
+ if (loading) notificationsOpen.value = false;
78
+ });
79
+ const showUser = computed(() => !!props.user);
80
+ const userInitials = computed(() => toInitials(props.user.title ?? ""));
81
+ const userAvatarProps = computed(() => {
82
+ if (props.user.img) return { image: props.user.img };
83
+ if (userInitials.value) return { text: userInitials.value };
84
+ return { icon: icons.accountAlternative };
85
+ });
86
+ const hasUserInfo = computed(() => !!props.user.title || !!props.user.subtitle);
87
+ function isParentOption(option) {
88
+ return "items" in option;
89
+ }
90
+ return (_ctx, _cache) => {
91
+ return openBlock(), createBlock(unref(VAppBar), {
92
+ "data-testid": props.dataTestid,
93
+ "aria-busy": props.loading || void 0
94
+ }, {
95
+ append: withCtx(() => [createVNode(skeleton_loader_default, {
96
+ loading: props.loading,
97
+ type: "avatar"
98
+ }, {
99
+ default: withCtx(() => [
100
+ showHelp.value ? (openBlock(), createBlock(unref(VBtn), mergeProps({ key: 0 }, unref(routeProps), {
101
+ "data-testid": helpBtnDataTestid.value,
102
+ "aria-label": "Ajuda",
103
+ icon: unref(icons).help
104
+ }), null, 16, ["data-testid", "icon"])) : createCommentVNode("v-if", true),
105
+ showNotifications.value ? (openBlock(), createBlock(unref(VMenu), {
106
+ key: 1,
107
+ modelValue: notificationsOpen.value,
108
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => notificationsOpen.value = $event),
109
+ "close-on-content-click": false
110
+ }, {
111
+ activator: withCtx(({ props }) => [createVNode(unref(VBtn), mergeProps(props, {
112
+ "data-testid": notificationsBtnDataTestid.value,
113
+ "aria-label": notificationsLabel.value,
114
+ icon: ""
115
+ }), {
116
+ default: withCtx(() => [createVNode(unref(VBadge), {
117
+ "model-value": hasUnreadNotifications.value,
118
+ content: unreadCount.value,
119
+ label: unreadLabel.value,
120
+ color: "error"
121
+ }, {
122
+ default: withCtx(() => [createVNode(unref(VIcon), { icon: unref(icons).notifications }, null, 8, ["icon"])]),
123
+ _: 1
124
+ }, 8, [
125
+ "model-value",
126
+ "content",
127
+ "label"
128
+ ])]),
129
+ _: 1
130
+ }, 16, ["data-testid", "aria-label"])]),
131
+ default: withCtx(() => [createVNode(unref(VCard), { "data-testid": notificationsMenuDataTestid.value }, {
132
+ default: withCtx(() => [props.notifications?.length ? (openBlock(), createBlock(unref(VList), { key: 0 }, {
133
+ default: withCtx(() => [createVNode(unref(VListSubheader), null, {
134
+ default: withCtx(() => [..._cache[2] || (_cache[2] = [createTextVNode("Notificações", -1)])]),
135
+ _: 1
136
+ }), (openBlock(true), createElementBlock(Fragment, null, renderList(props.notifications, (notification, index) => {
137
+ return openBlock(), createBlock(unref(VListItem), {
138
+ key: index,
139
+ active: !notification.read,
140
+ title: notification.title,
141
+ subtitle: notification.subtitle,
142
+ "active-class": "text-primary-text"
143
+ }, createSlots({
144
+ subtitle: withCtx(({ subtitle }) => [createElementVNode("span", _hoisted_1, toDisplayString(subtitle), 1)]),
145
+ _: 2
146
+ }, [notification.when ? {
147
+ name: "append",
148
+ fn: withCtx(() => [createVNode(unref(VListItemAction), { end: "" }, {
149
+ default: withCtx(() => [createCommentVNode(" No prop sets the secondary text color, which follows the theme's contrast "), createElementVNode("small", _hoisted_2, toDisplayString(notification.when), 1)]),
150
+ _: 2
151
+ }, 1024)]),
152
+ key: "0"
153
+ } : void 0]), 1032, [
154
+ "active",
155
+ "title",
156
+ "subtitle"
157
+ ]);
158
+ }), 128))]),
159
+ _: 1
160
+ })) : (openBlock(), createBlock(unref(VCardText), { key: 1 }, {
161
+ default: withCtx(() => [..._cache[3] || (_cache[3] = [createTextVNode("Nenhuma notificação", -1)])]),
162
+ _: 1
163
+ }))]),
164
+ _: 1
165
+ }, 8, ["data-testid"])]),
166
+ _: 1
167
+ }, 8, ["modelValue"])) : createCommentVNode("v-if", true),
168
+ showUser.value ? (openBlock(), createBlock(unref(VMenu), {
169
+ key: 2,
170
+ "close-on-content-click": false
171
+ }, {
172
+ activator: withCtx(({ props }) => [createVNode(unref(VBtn), mergeProps(props, {
173
+ "data-testid": userBtnDataTestid.value,
174
+ "aria-label": "Menu do usuário",
175
+ icon: ""
176
+ }), {
177
+ default: withCtx(() => [createCommentVNode(" Decorative: the button already has an accessible name "), createVNode(unref(VAvatar), mergeProps(userAvatarProps.value, {
178
+ color: "primary",
179
+ "aria-hidden": "true"
180
+ }), null, 16)]),
181
+ _: 1
182
+ }, 16, ["data-testid"])]),
183
+ default: withCtx(() => [createVNode(unref(VCard), { "data-testid": userMenuDataTestid.value }, {
184
+ default: withCtx(() => [
185
+ createCommentVNode(" The card's header puts the avatar beside the title, and no prop stacks or centers\n them: the avatar and the user's info get an item each, centered by a class, as USection\n and UFooter center their text. The options below stay aligned to the start "),
186
+ createVNode(unref(VCardItem), { class: "text-center" }, {
187
+ default: withCtx(() => [createCommentVNode(" Decorative: the user's name, when given, is already the title below "), createVNode(unref(VAvatar), mergeProps(userAvatarProps.value, {
188
+ size: "x-large",
189
+ color: "primary",
190
+ "aria-hidden": "true"
191
+ }), null, 16)]),
192
+ _: 1
193
+ }),
194
+ hasUserInfo.value ? (openBlock(), createBlock(unref(VCardItem), {
195
+ key: 0,
196
+ title: __props.user?.title,
197
+ subtitle: __props.user?.subtitle,
198
+ class: "text-center"
199
+ }, null, 8, ["title", "subtitle"])) : createCommentVNode("v-if", true),
200
+ createCommentVNode(" The app's details of the user continue the header, so their text is centered too "),
201
+ slots["user-section-details"] ? (openBlock(), createBlock(unref(VCardText), {
202
+ key: 1,
203
+ class: "text-center"
204
+ }, {
205
+ default: withCtx(() => [renderSlot(_ctx.$slots, "user-section-details")]),
206
+ _: 3
207
+ })) : createCommentVNode("v-if", true),
208
+ createVNode(unref(VDivider)),
209
+ createCommentVNode(" Vuetify's `list` role only allows list items, but the options are links and\n separators "),
210
+ createVNode(unref(VList), {
211
+ nav: "",
212
+ role: "group"
213
+ }, {
214
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(props.user?.options, (option, index) => {
215
+ return openBlock(), createElementBlock(Fragment, { key: index }, [index > 0 ? (openBlock(), createBlock(unref(VDivider), {
216
+ key: 0,
217
+ class: "mt-1"
218
+ })) : createCommentVNode("v-if", true), isParentOption(option) ? (openBlock(), createBlock(unref(VListGroup), { key: 1 }, {
219
+ activator: withCtx(({ props, isOpen }) => [createVNode(unref(VListItem), mergeProps({ ref_for: true }, props, {
220
+ title: option.description,
221
+ "aria-expanded": isOpen,
222
+ role: void 0,
223
+ tag: "button",
224
+ type: "button",
225
+ class: "w-100 text-start"
226
+ }), null, 16, ["title", "aria-expanded"])]),
227
+ default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(option.items, (childOption, index) => {
228
+ return openBlock(), createBlock(unref(VListItem), mergeProps({ key: index }, { ref_for: true }, unref(routeToListItemProps)(childOption.route), {
229
+ title: childOption.description,
230
+ onClick: childOption.action
231
+ }), null, 16, ["title", "onClick"]);
232
+ }), 128))]),
233
+ _: 2
234
+ }, 1024)) : (openBlock(), createBlock(unref(VListItem), mergeProps({
235
+ key: 2,
236
+ title: option.description
237
+ }, { ref_for: true }, unref(routeToListItemProps)(option.route), { onClick: option.action }), null, 16, ["title", "onClick"]))], 64);
238
+ }), 128))]),
239
+ _: 1
240
+ })
241
+ ]),
242
+ _: 3
243
+ }, 8, ["data-testid"])]),
244
+ _: 3
245
+ })) : createCommentVNode("v-if", true)
246
+ ]),
247
+ _: 3
248
+ }, 8, ["loading"])]),
249
+ default: withCtx(() => [
250
+ __props.navigation ? (openBlock(), createBlock(unref(VAppBarNavIcon), {
251
+ key: 0,
252
+ "data-testid": navigationBtnDataTestid.value,
253
+ "aria-expanded": navigationOpen.value,
254
+ "aria-label": "Menu de navegação",
255
+ "aria-keyshortcuts": unref(navigationKeyshortcuts),
256
+ onClick: _cache[0] || (_cache[0] = ($event) => navigationOpen.value = !navigationOpen.value)
257
+ }, null, 8, [
258
+ "data-testid",
259
+ "aria-expanded",
260
+ "aria-keyshortcuts"
261
+ ])) : createCommentVNode("v-if", true),
262
+ __props.logo ? (openBlock(), createBlock(unref(VImg), {
263
+ key: 1,
264
+ src: props.logo,
265
+ alt: "",
266
+ height: "100%",
267
+ width: "fit-content",
268
+ class: "py-2 ml-5 mr-n3",
269
+ cover: ""
270
+ }, null, 8, ["src"])) : createCommentVNode("v-if", true),
271
+ props.title ? (openBlock(), createBlock(unref(VAppBarTitle), {
272
+ key: 2,
273
+ role: "heading",
274
+ "aria-level": "1"
275
+ }, {
276
+ default: withCtx(() => [createTextVNode(toDisplayString(props.title), 1)]),
277
+ _: 1
278
+ })) : createCommentVNode("v-if", true)
279
+ ]),
280
+ _: 3
281
+ }, 8, ["data-testid", "aria-busy"]);
282
+ };
283
+ }
284
+ });
285
+ //#endregion
286
+ export { app_bar_vue_vue_type_script_setup_true_lang_default as default };
@@ -0,0 +1,96 @@
1
+ import { RouteLocationRaw } from "vue-router";
2
+ //#region src/components/app-bar/types.d.ts
3
+ /**
4
+ * Props exposed by the {@link AppBar} component.
5
+ */
6
+ export type AppBarProps = {
7
+ /**
8
+ * Component id to use on automated tests.
9
+ */
10
+ dataTestid?: string;
11
+ /**
12
+ * Main title to be presented.
13
+ */
14
+ title?: string;
15
+ /**
16
+ * Help page route.
17
+ */
18
+ help?: RouteLocationRaw;
19
+ /**
20
+ * Resources available to the user in the app-bar
21
+ */
22
+ user?: AppBarUserProps;
23
+ /**
24
+ * List of notifications to show in the {@link AppBar}.
25
+ */
26
+ notifications?: Array<AppBarNotification>;
27
+ };
28
+ /**
29
+ * A single notification entry shown in the {@link AppBar}.
30
+ */
31
+ interface AppBarNotification {
32
+ /**
33
+ * Main text describing the notification.
34
+ */
35
+ title: string;
36
+ /**
37
+ * Complementary text with additional details.
38
+ */
39
+ subtitle?: string;
40
+ /**
41
+ * Whether the notification has already been read.
42
+ */
43
+ read?: boolean;
44
+ /**
45
+ * Free text telling when the notification was generated, shown as is (e.g.
46
+ * `"10:30"`, `"Ontem"` or `"28/09/2026"`). Hidden when omitted or empty.
47
+ */
48
+ when?: string;
49
+ }
50
+ export interface AppBarUserProps {
51
+ /**
52
+ * Major identifier, like the user full name. Without an `img`, the
53
+ * avatar shows its initials (e.g. `"RP"` for `"Rafael Perini"`).
54
+ */
55
+ title?: string;
56
+ /**
57
+ * Complement to user identifier, like it's e-mail or username.
58
+ */
59
+ subtitle?: string;
60
+ /**
61
+ * URL leading to a user picture. When omitted, the avatar shows the initials
62
+ * of the `title`, or a generic icon when there's no title either.
63
+ */
64
+ img?: string;
65
+ /**
66
+ * Options to show the user when its menu is opened.
67
+ * Can be plain options, grouped or both.
68
+ */
69
+ options?: Array<ParentOptionOrOption>;
70
+ }
71
+ export type ParentOptionOrOption = ParentOption | Option;
72
+ export type ParentOption = {
73
+ /**
74
+ * Text to present for the group.
75
+ */
76
+ description: string;
77
+ /**
78
+ * Child {@link Option} list.
79
+ */
80
+ items: Array<Option>;
81
+ };
82
+ export interface Option {
83
+ /**
84
+ * Text to present for the action.
85
+ */
86
+ description: string;
87
+ /**
88
+ * Route to navigate when item is clicked.
89
+ */
90
+ route?: RouteLocationRaw;
91
+ /**
92
+ * Callback to be triggered when the item is clicked.
93
+ */
94
+ action?: () => void;
95
+ }
96
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import button_vue_vue_type_script_setup_true_lang_default from "./button.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/button/button.vue
3
+ var button_default = button_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { button_default as default };
@@ -0,0 +1,31 @@
1
+ import { ButtonProps } from "./types.js";
2
+ //#region src/components/button/button.vue.d.ts
3
+ /**
4
+ * Button component to be used throughout the application.
5
+ *
6
+ * @example
7
+ * ```vue
8
+ * <template>
9
+ * <u-button color="danger" @click="onClick">
10
+ * Confirmar
11
+ * </u-button>
12
+ * </template>
13
+ * ```
14
+ *
15
+ * @see {@link https://nexdom-healthtech.github.io/uimed-vue/guide/components/button | Button Guide}
16
+ */
17
+ declare const _default: typeof __VLS_export;
18
+ declare const __VLS_export: __VLS_WithSlots<import("vue", { with: { "resolution-mode": "import" } }).DefineComponent<ButtonProps, {}, {}, {}, {}, import("vue", { with: { "resolution-mode": "import" } }).ComponentOptionsMixin, import("vue", { with: { "resolution-mode": "import" } }).ComponentOptionsMixin, {} & {
19
+ click: (event: MouseEvent) => any;
20
+ }, string, import("vue", { with: { "resolution-mode": "import" } }).PublicProps, Readonly<ButtonProps> & Readonly<{
21
+ onClick?: ((event: MouseEvent) => any) | undefined;
22
+ }>, {}, {}, {}, {}, string, import("vue", { with: { "resolution-mode": "import" } }).ComponentProvideOptions, false, {}, any>, {
23
+ default?: (props: {}) => any;
24
+ }>;
25
+ type __VLS_WithSlots<T, S> = T & {
26
+ new (): {
27
+ $slots: S;
28
+ };
29
+ };
30
+ //#endregion
31
+ export { _default as default };
@@ -0,0 +1,97 @@
1
+ import useRouteProps from "../../composables/navigation/use-route-props.js";
2
+ import { useFullWidth } from "../../composables/dimensions/dimensions.js";
3
+ import { useButtonColor, useButtonForm, useButtonRoute, useButtonType, useButtonVariant } from "../../composables/button/button.js";
4
+ import { computed, createBlock, createVNode, defineComponent, mergeProps, openBlock, renderSlot, unref, withCtx } from "vue";
5
+ import { VBtn, VProgressCircular } from "vuetify/components";
6
+ var button_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
+ inheritAttrs: false,
8
+ __name: "button",
9
+ props: {
10
+ variant: {
11
+ type: String,
12
+ required: false
13
+ },
14
+ type: {
15
+ type: String,
16
+ required: false
17
+ },
18
+ color: {
19
+ type: String,
20
+ required: false
21
+ },
22
+ disabled: {
23
+ type: Boolean,
24
+ required: false
25
+ },
26
+ loading: {
27
+ type: Boolean,
28
+ required: false
29
+ },
30
+ fullWidth: {
31
+ type: Boolean,
32
+ required: false
33
+ },
34
+ form: {
35
+ type: String,
36
+ required: false
37
+ },
38
+ route: {
39
+ type: null,
40
+ required: false
41
+ },
42
+ dataTestid: {
43
+ type: String,
44
+ required: false
45
+ }
46
+ },
47
+ emits: ["click"],
48
+ setup(__props, { emit: __emit }) {
49
+ const props = __props;
50
+ const emit = __emit;
51
+ const variant = useButtonVariant(() => props.variant);
52
+ const color = useButtonColor(() => props.color, () => props.variant);
53
+ const widthClass = useFullWidth(() => props.fullWidth);
54
+ const isDisabled = computed(() => props.disabled || props.loading);
55
+ const route = useButtonRoute(() => props.route, isDisabled);
56
+ const routeProps = useRouteProps(route);
57
+ const type = useButtonType(() => props.type, () => props.route, isDisabled);
58
+ const form = useButtonForm(() => props.form, () => props.route);
59
+ function onClick(event) {
60
+ emit("click", event);
61
+ }
62
+ return (_ctx, _cache) => {
63
+ return openBlock(), createBlock(unref(VBtn), mergeProps({
64
+ disabled: isDisabled.value,
65
+ loading: props.loading,
66
+ "data-testid": props.dataTestid,
67
+ variant: unref(variant),
68
+ color: unref(color),
69
+ type: unref(type),
70
+ form: unref(form),
71
+ class: unref(widthClass)
72
+ }, unref(routeProps), {
73
+ active: false,
74
+ onClick
75
+ }), {
76
+ loader: withCtx(() => [createVNode(unref(VProgressCircular), {
77
+ indeterminate: "",
78
+ width: "2",
79
+ "aria-hidden": "true"
80
+ })]),
81
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
82
+ _: 3
83
+ }, 16, [
84
+ "disabled",
85
+ "loading",
86
+ "data-testid",
87
+ "variant",
88
+ "color",
89
+ "type",
90
+ "form",
91
+ "class"
92
+ ]);
93
+ };
94
+ }
95
+ });
96
+ //#endregion
97
+ export { button_vue_vue_type_script_setup_true_lang_default as default };
@@ -1,14 +1,11 @@
1
+ import { ColorVariant } from "../../composables/colors/types.js";
1
2
  import { RouteLocationRaw } from "vue-router";
2
- //#region src/composables/colors/types.d.ts
3
- type ColorVariant = "primary" | "secondary" | FeedbackColorVariant;
4
- type FeedbackColorVariant = "positive" | "informative" | "caution" | "danger";
5
- //#endregion
6
3
  //#region src/components/button/types.d.ts
7
- type ButtonVariant = "primary" | "secondary" | "ghost";
4
+ export type ButtonVariant = "primary" | "secondary" | "ghost";
8
5
  /**
9
6
  * Props exposed by the {@link Button} component.
10
7
  */
11
- type ButtonProps = {
8
+ export type ButtonProps = {
12
9
  /**
13
10
  * Applies a distinct style variation to the button.
14
11
  * One of `primary`, `secondary`, or `ghost`.
@@ -65,5 +62,4 @@ type ButtonProps = {
65
62
  */
66
63
  dataTestid?: string;
67
64
  };
68
- //#endregion
69
- export { FeedbackColorVariant as i, ButtonVariant as n, ColorVariant as r, ButtonProps as t };
65
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import data_set_vue_vue_type_script_setup_true_lang_default from "./data-set.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/data-sets/data-set/data-set.vue
3
+ var data_set_default = data_set_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { data_set_default as default };
@@ -0,0 +1,47 @@
1
+ import { DataSetProps, DataSetSlots } from "./types.js";
2
+ //#region src/components/data-sets/data-set/data-set.vue.d.ts
3
+ /**
4
+ * Data set component to list records as a responsive grid of cards, with
5
+ * client-side pagination, and an optional bar above the records with actions
6
+ * about the list and a search field. Each record of the current page is
7
+ * rendered by the default slot, usually with `UDataSetItem`.
8
+ *
9
+ * @example
10
+ * ```vue
11
+ * <template>
12
+ * <u-data-set
13
+ * :items="patients"
14
+ * :columns="4"
15
+ * :actions="[{ label: 'Novo paciente', onClick: create }]"
16
+ * searchable
17
+ * >
18
+ * <template #default="{ item }">
19
+ * <u-data-set-item :title="item.name" :subtitle="item.plan" />
20
+ * </template>
21
+ * </u-data-set>
22
+ * </template>
23
+ * ```
24
+ *
25
+ * @see {@link https://nexdom-healthtech.github.io/uimed-vue/guide/components/data-set | DataSet Guide}
26
+ */
27
+ declare const _default: typeof __VLS_export;
28
+ declare const __VLS_export: <T extends object>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
29
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<(DataSetProps<T> & {
30
+ page?: number;
31
+ search?: string;
32
+ }) & {
33
+ "onUpdate:page"?: ((value: number) => any) | undefined;
34
+ "onUpdate:search"?: ((value: string) => any) | undefined;
35
+ }> & (typeof globalThis extends {
36
+ __VLS_PROPS_FALLBACK: infer P;
37
+ } ? P : {});
38
+ expose: (exposed: {}) => void;
39
+ attrs: any;
40
+ slots: DataSetSlots<T>;
41
+ emit: ((event: "update:page", value: number) => void) & ((event: "update:search", value: string) => void);
42
+ }>) => import("vue").VNode & {
43
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
44
+ };
45
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {};
46
+ //#endregion
47
+ export { _default as default };