@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.
- package/README.md +1 -1
- 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 -940
- package/dist/components.js +23 -1254
- 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/composables/dialogs/use-dialog.js +73 -0
- 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 -67
- package/dist/composables.js +6 -65
- 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 -160
- package/CLAUDE.md +0 -1
- package/dist/types-BPXXtbmW.d.ts +0 -5
- package/dist/use-toast-CACuYhK_.js +0 -53
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { computed, toValue } from "vue";
|
|
2
|
+
//#region src/composables/alignment/alignment.ts
|
|
3
|
+
const alignXToClass = {
|
|
4
|
+
start: "justify-start",
|
|
5
|
+
center: "justify-center",
|
|
6
|
+
end: "justify-end"
|
|
7
|
+
};
|
|
8
|
+
const alignYToClasses = {
|
|
9
|
+
start: {
|
|
10
|
+
items: "align-start",
|
|
11
|
+
content: "align-content-start"
|
|
12
|
+
},
|
|
13
|
+
center: {
|
|
14
|
+
items: "align-center",
|
|
15
|
+
content: "align-content-center"
|
|
16
|
+
},
|
|
17
|
+
end: {
|
|
18
|
+
items: "align-end",
|
|
19
|
+
content: "align-content-end"
|
|
20
|
+
},
|
|
21
|
+
stretch: {
|
|
22
|
+
items: "align-stretch",
|
|
23
|
+
content: "align-content-stretch"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Vuetify's `justify-*` utility class for components with an `alignX` prop, laid out with flexbox.
|
|
28
|
+
* Falls back to `"start"`.
|
|
29
|
+
*/
|
|
30
|
+
function useAlignX(alignX) {
|
|
31
|
+
return computed(() => alignXToClass[toValue(alignX) ?? "start"]);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Vuetify's `align-*` and `align-content-*` utility classes for components with an `alignY` prop,
|
|
35
|
+
* laid out with flexbox. Falls back to `"start"`.
|
|
36
|
+
*/
|
|
37
|
+
function useAlignY(alignY) {
|
|
38
|
+
return computed(() => alignYToClasses[toValue(alignY) ?? "start"]);
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { useAlignX, useAlignY };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/composables/alignment/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Horizontal alignment of a component's items: to the start, to the center or to the end,
|
|
4
|
+
* following the text direction.
|
|
5
|
+
*/
|
|
6
|
+
export type AlignX = "start" | "center" | "end";
|
|
7
|
+
/**
|
|
8
|
+
* Vertical alignment of a component's items: to the top, to the center, to the bottom, or
|
|
9
|
+
* stretched to the whole height available.
|
|
10
|
+
*/
|
|
11
|
+
export type AlignY = "start" | "center" | "end" | "stretch";
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import useVuetifyColor from "../colors/use-vuetify-color.js";
|
|
2
|
+
import useVuetifyTextColor from "../colors/use-vuetify-text-color.js";
|
|
3
|
+
import { computed, toValue } from "vue";
|
|
4
|
+
//#region src/composables/button/button.ts
|
|
5
|
+
const buttonVariantToVuetifyVariant = {
|
|
6
|
+
primary: "elevated",
|
|
7
|
+
secondary: "outlined",
|
|
8
|
+
ghost: "text"
|
|
9
|
+
};
|
|
10
|
+
function useButtonVariant(variant) {
|
|
11
|
+
return computed(() => {
|
|
12
|
+
const variantValue = toValue(variant);
|
|
13
|
+
return variantValue ? buttonVariantToVuetifyVariant[variantValue] : buttonVariantToVuetifyVariant.primary;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The route the button navigates to, or `undefined` while it's blocked, so a `disabled` or
|
|
18
|
+
* `loading` button is rendered as a disabled `<button>` instead of a link that the keyboard,
|
|
19
|
+
* assistive technologies or `element.click()` could still follow.
|
|
20
|
+
*/
|
|
21
|
+
function useButtonRoute(route, blocked) {
|
|
22
|
+
return computed(() => toValue(blocked) ? void 0 : toValue(route));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The button's `type`. It doesn't apply to a button with a `route`, which is `undefined` while
|
|
26
|
+
* rendered as a link, and `"button"` while blocked, so the disabled `<button>` it's rendered as
|
|
27
|
+
* isn't a submit button.
|
|
28
|
+
*/
|
|
29
|
+
function useButtonType(type, route, blocked) {
|
|
30
|
+
return computed(() => {
|
|
31
|
+
if (!toValue(route)) return toValue(type) ?? "button";
|
|
32
|
+
return toValue(blocked) ? "button" : void 0;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Maps the button's color to Vuetify's. Secondary (outlined) and ghost buttons have no fill, so
|
|
37
|
+
* their color is the text's, which takes the color's text shade to keep WCAG AA's contrast.
|
|
38
|
+
*/
|
|
39
|
+
function useButtonColor(color, variant) {
|
|
40
|
+
const fillColor = useVuetifyColor(color);
|
|
41
|
+
const textColor = useVuetifyTextColor(color);
|
|
42
|
+
return computed(() => {
|
|
43
|
+
return toValue(variant) === "secondary" || toValue(variant) === "ghost" ? textColor.value : fillColor.value;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The button's `form`, or `undefined` when it has a `route`, even while blocked, since `form`
|
|
48
|
+
* doesn't apply to it.
|
|
49
|
+
*/
|
|
50
|
+
function useButtonForm(form, route) {
|
|
51
|
+
return computed(() => toValue(route) ? void 0 : toValue(form));
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { useButtonColor, useButtonForm, useButtonRoute, useButtonType, useButtonVariant };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/composables/colors/constants.ts
|
|
2
|
+
const feedbackColorToVuetifyColor = {
|
|
3
|
+
positive: "success",
|
|
4
|
+
informative: "info",
|
|
5
|
+
caution: "warning",
|
|
6
|
+
danger: "error"
|
|
7
|
+
};
|
|
8
|
+
const colorToVuetifyColor = {
|
|
9
|
+
primary: "primary",
|
|
10
|
+
secondary: "secondary",
|
|
11
|
+
...feedbackColorToVuetifyColor
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The theme colors to use when a color is the text color, on the surface or background, instead
|
|
15
|
+
* of a fill. The fills are too light to reach WCAG AA's contrast as text, so each one has a darker
|
|
16
|
+
* shade, except `secondary`, which is almost white and gives way to the theme's text color.
|
|
17
|
+
*/
|
|
18
|
+
const colorToVuetifyTextColor = {
|
|
19
|
+
primary: "primary-text",
|
|
20
|
+
secondary: "on-surface",
|
|
21
|
+
positive: "success-text",
|
|
22
|
+
informative: "info-text",
|
|
23
|
+
caution: "warning-text",
|
|
24
|
+
danger: "error-text"
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { colorToVuetifyColor, colorToVuetifyTextColor, feedbackColorToVuetifyColor };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { colorToVuetifyColor } from "./constants.js";
|
|
2
|
+
import { computed, toValue } from "vue";
|
|
3
|
+
//#region src/composables/colors/use-vuetify-background-color.ts
|
|
4
|
+
/**
|
|
5
|
+
* Vuetify's utility class that applies a color to the background of an element, and the color the
|
|
6
|
+
* theme pairs with it to its text, for props that color a background. No class when the color is
|
|
7
|
+
* omitted, so the element keeps its default background.
|
|
8
|
+
*/
|
|
9
|
+
function useVuetifyBackgroundColor(color) {
|
|
10
|
+
return computed(() => {
|
|
11
|
+
const colorValue = toValue(color);
|
|
12
|
+
return colorValue ? `bg-${colorToVuetifyColor[colorValue]}` : void 0;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { useVuetifyBackgroundColor as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { colorToVuetifyColor } from "./constants.js";
|
|
2
|
+
import { computed, toValue } from "vue";
|
|
3
|
+
//#region src/composables/colors/use-vuetify-color.ts
|
|
4
|
+
function useVuetifyColor(color) {
|
|
5
|
+
return computed(() => {
|
|
6
|
+
const colorValue = toValue(color);
|
|
7
|
+
return colorValue ? colorToVuetifyColor[colorValue] : colorToVuetifyColor.primary;
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { useVuetifyColor as default };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { colorToVuetifyTextColor } from "./constants.js";
|
|
2
|
+
import { computed, toValue } from "vue";
|
|
3
|
+
//#region src/composables/colors/use-vuetify-text-color.ts
|
|
4
|
+
/**
|
|
5
|
+
* Maps a color to the theme color to use when it's the text color, e.g. in a ghost button, so it
|
|
6
|
+
* keeps WCAG AA's contrast on the surface and background.
|
|
7
|
+
*/
|
|
8
|
+
function useVuetifyTextColor(color) {
|
|
9
|
+
return computed(() => colorToVuetifyTextColor[toValue(color) ?? "primary"]);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { useVuetifyTextColor as default };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { computed, onScopeDispose, ref, toValue, watch } from "vue";
|
|
2
|
+
//#region src/composables/data-set/data-set.ts
|
|
3
|
+
/**
|
|
4
|
+
* Width, out of the grid's 12 columns, taken by each record so that
|
|
5
|
+
* `columns` records fit side by side on a row.
|
|
6
|
+
*/
|
|
7
|
+
const dataSetColumnsToColumnCols = {
|
|
8
|
+
1: "12",
|
|
9
|
+
2: "6",
|
|
10
|
+
3: "4",
|
|
11
|
+
4: "3",
|
|
12
|
+
6: "2"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Space, in pixels, between two cards of the same row: the default gutter of
|
|
16
|
+
* `URow`/`UColumn` (Vuetify's `v-row` with its default density puts a 24px
|
|
17
|
+
* gap between its columns). `n` cards side by side take `n` card widths plus
|
|
18
|
+
* `n - 1` gaps, so they fit in `width` pixels when
|
|
19
|
+
* `n * (minDataSetItemWidth + gap) <= width + gap`.
|
|
20
|
+
*/
|
|
21
|
+
const dataSetItemGap = 24;
|
|
22
|
+
/**
|
|
23
|
+
* Supported numbers of records per row, from the largest to the smallest.
|
|
24
|
+
*/
|
|
25
|
+
const dataSetColumnsOptions = [
|
|
26
|
+
6,
|
|
27
|
+
4,
|
|
28
|
+
3,
|
|
29
|
+
2,
|
|
30
|
+
1
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Number of records to place side by side: the largest supported amount, up
|
|
34
|
+
* to `columns`, that keeps each card at least {@link minDataSetItemWidth}
|
|
35
|
+
* pixels wide, besides the {@link dataSetItemGap} between cards, in a data set
|
|
36
|
+
* `width` pixels wide, but never less than one.
|
|
37
|
+
* While the width is unknown (`0`, e.g. before the first measure or during
|
|
38
|
+
* server-side rendering), `columns` is used as is.
|
|
39
|
+
*/
|
|
40
|
+
function getDataSetFittingColumns(columns, width) {
|
|
41
|
+
if (!width) return columns;
|
|
42
|
+
const fittingColumns = Math.min(columns, Math.floor((width + dataSetItemGap) / 264));
|
|
43
|
+
return dataSetColumnsOptions.find((option) => option <= fittingColumns) ?? 1;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reactive version of {@link getDataSetFittingColumns}.
|
|
47
|
+
*/
|
|
48
|
+
function useDataSetFittingColumns(columns, width) {
|
|
49
|
+
return computed(() => getDataSetFittingColumns(toValue(columns), toValue(width)));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Width, in pixels, of the given element, kept up to date with a
|
|
53
|
+
* `ResizeObserver`. It's `0` while there's no element, e.g. before it's
|
|
54
|
+
* mounted, and the observer is disconnected when the element changes or the
|
|
55
|
+
* calling scope is disposed.
|
|
56
|
+
*/
|
|
57
|
+
function useDataSetWidth(element) {
|
|
58
|
+
const width = ref(0);
|
|
59
|
+
let observer;
|
|
60
|
+
function disconnect() {
|
|
61
|
+
observer?.disconnect();
|
|
62
|
+
observer = void 0;
|
|
63
|
+
}
|
|
64
|
+
watch(() => toValue(element), (currentElement) => {
|
|
65
|
+
disconnect();
|
|
66
|
+
width.value = 0;
|
|
67
|
+
if (!currentElement) return;
|
|
68
|
+
observer = new ResizeObserver(([entry]) => {
|
|
69
|
+
width.value = entry.contentRect.width;
|
|
70
|
+
});
|
|
71
|
+
observer.observe(currentElement);
|
|
72
|
+
}, { immediate: true });
|
|
73
|
+
onScopeDispose(disconnect);
|
|
74
|
+
return width;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Maps the number of records per row to the width of each record's grid
|
|
78
|
+
* column.
|
|
79
|
+
*/
|
|
80
|
+
function useDataSetColumnCols(columns) {
|
|
81
|
+
return computed(() => dataSetColumnsToColumnCols[toValue(columns)]);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Width, out of the bar's 12 columns, of the actions and of the search field
|
|
85
|
+
* above the records of a data set `width` pixels wide: they share the bar in
|
|
86
|
+
* halves (`"6"`) where two cards fit side by side, so the search field, as wide
|
|
87
|
+
* as a card, fits in its half, and take a line each (`"12"`) otherwise.
|
|
88
|
+
*/
|
|
89
|
+
function useDataSetBarCols(width) {
|
|
90
|
+
return computed(() => getDataSetFittingColumns(2, toValue(width)) === 2 ? "6" : "12");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Maps the record properties considered by the search to Vuetify's filter
|
|
94
|
+
* keys. An empty list means every property, just like an undefined one.
|
|
95
|
+
*/
|
|
96
|
+
function useDataSetFilterKeys(searchKeys) {
|
|
97
|
+
return computed(() => {
|
|
98
|
+
const keys = toValue(searchKeys);
|
|
99
|
+
return keys?.length ? keys : void 0;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Up to this many pages, every page button is shown. Vuetify's automatic
|
|
104
|
+
* sizing collapses 3 pages into `1 … 2 … 3` in containers narrower than
|
|
105
|
+
* ~336px, although showing every page never takes more room than its
|
|
106
|
+
* collapsed form (`1 … x … 5`, 5 buttons) up to this amount.
|
|
107
|
+
*/
|
|
108
|
+
const maxAlwaysVisiblePages = 5;
|
|
109
|
+
/**
|
|
110
|
+
* Number of page buttons to show for `pageCount` pages: every page up to
|
|
111
|
+
* {@link maxAlwaysVisiblePages}, otherwise `undefined` to let Vuetify fit them
|
|
112
|
+
* to the available width.
|
|
113
|
+
*/
|
|
114
|
+
function getDataSetTotalVisible(pageCount) {
|
|
115
|
+
return pageCount <= maxAlwaysVisiblePages ? pageCount : void 0;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Goes back to the first page whenever the search changes. It must run before
|
|
119
|
+
* the new search reaches Vuetify's iterator, which would otherwise clamp the
|
|
120
|
+
* outdated page to the last one of the filtered records.
|
|
121
|
+
*/
|
|
122
|
+
function useDataSetSearchPageReset(search, page) {
|
|
123
|
+
watch(() => toValue(search), () => {
|
|
124
|
+
page.value = 1;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
export { getDataSetFittingColumns, getDataSetTotalVisible, useDataSetBarCols, useDataSetColumnCols, useDataSetFilterKeys, useDataSetFittingColumns, useDataSetSearchPageReset, useDataSetWidth };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { ColorVariant, FeedbackColorVariant } from "../colors/types.js";
|
|
2
|
+
import { ButtonVariant } from "../../components/button/types.js";
|
|
3
|
+
//#region src/composables/dialogs/types.d.ts
|
|
4
|
+
export interface ToastOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Text to be presented in the toast.
|
|
7
|
+
*/
|
|
8
|
+
message: string;
|
|
9
|
+
/**
|
|
10
|
+
* Applies a color to the toast.
|
|
11
|
+
* One of `positive`, `informative`, `caution`, or `danger`.
|
|
12
|
+
* @default "informative"
|
|
13
|
+
*/
|
|
14
|
+
color?: FeedbackColorVariant;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A button displayed at the bottom of a dialog opened by `useDialog`'s `dialog`.
|
|
18
|
+
*/
|
|
19
|
+
export interface DialogAction<T extends string = string> {
|
|
20
|
+
/**
|
|
21
|
+
* Text displayed on the button.
|
|
22
|
+
*/
|
|
23
|
+
text: string;
|
|
24
|
+
/**
|
|
25
|
+
* Value the dialog resolves with when the button is clicked.
|
|
26
|
+
*/
|
|
27
|
+
value: T;
|
|
28
|
+
/**
|
|
29
|
+
* Applies a distinct style variation to the button.
|
|
30
|
+
* One of `primary`, `secondary`, or `ghost`.
|
|
31
|
+
* @default "ghost", or "primary" for the last action
|
|
32
|
+
*/
|
|
33
|
+
variant?: ButtonVariant;
|
|
34
|
+
/**
|
|
35
|
+
* Applies a color to the button.
|
|
36
|
+
* One of `primary`, `secondary`, `positive`, `informative`, `caution`, or `danger`.
|
|
37
|
+
* @default "primary"
|
|
38
|
+
*/
|
|
39
|
+
color?: ColorVariant;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Options of a dialog opened by `useDialog`'s `dialog`.
|
|
43
|
+
*/
|
|
44
|
+
export interface DialogOptions<T extends string = string> {
|
|
45
|
+
/**
|
|
46
|
+
* Plain text displayed as the dialog's title. HTML isn't interpreted.
|
|
47
|
+
*/
|
|
48
|
+
title?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Plain text displayed as the dialog's message. HTML isn't interpreted.
|
|
51
|
+
*/
|
|
52
|
+
message: string;
|
|
53
|
+
/**
|
|
54
|
+
* Buttons displayed at the bottom of the dialog, right-aligned, in the given order.
|
|
55
|
+
* @default [{ text: "Fechar" }], which resolves `undefined`
|
|
56
|
+
*/
|
|
57
|
+
actions?: DialogAction<T>[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Options of a dialog opened by `useConfirm`'s `confirm`.
|
|
61
|
+
*/
|
|
62
|
+
export interface ConfirmOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Plain text displayed as the dialog's title. HTML isn't interpreted.
|
|
65
|
+
*/
|
|
66
|
+
title?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Plain text displayed as the dialog's message. HTML isn't interpreted.
|
|
69
|
+
*/
|
|
70
|
+
message: string;
|
|
71
|
+
/**
|
|
72
|
+
* Text displayed on the confirm button.
|
|
73
|
+
* @default "Confirmar"
|
|
74
|
+
*/
|
|
75
|
+
confirmText?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Text displayed on the cancel button.
|
|
78
|
+
* @default "Cancelar"
|
|
79
|
+
*/
|
|
80
|
+
cancelText?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Applies a color to the confirm button.
|
|
83
|
+
* One of `primary`, `secondary`, `positive`, `informative`, `caution`, or `danger`.
|
|
84
|
+
* @default "primary"
|
|
85
|
+
*/
|
|
86
|
+
color?: ColorVariant;
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConfirmOptions } from "./types.js";
|
|
2
|
+
//#region src/composables/dialogs/use-confirm.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Composable which returns a function to run actions only after the user confirms them in a
|
|
5
|
+
* dialog, and a computed property `isRunning`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const { confirm, isRunning } = useConfirm();
|
|
10
|
+
*
|
|
11
|
+
* const removed = await confirm(
|
|
12
|
+
* { title: "Excluir paciente", message: "Esta ação não pode ser desfeita.", confirmText: "Excluir", color: "danger" },
|
|
13
|
+
* () => api.deletePatient(id),
|
|
14
|
+
* );
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export default function useConfirm(): {
|
|
18
|
+
confirm: <F extends (...args: Parameters<F>) => PromiseLike<Awaited<ReturnType<F>>>>(options: ConfirmOptions, action: F, ...params: Parameters<F>) => Promise<Awaited<ReturnType<F>> | false>;
|
|
19
|
+
isRunning: import("vue").ComputedRef<boolean>;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { openDialog } from "./use-dialog.js";
|
|
2
|
+
import useRunOrToast from "./use-run-or-toast.js";
|
|
3
|
+
//#region src/composables/dialogs/use-confirm.ts
|
|
4
|
+
/**
|
|
5
|
+
* Composable which returns a function to run actions only after the user confirms them in a
|
|
6
|
+
* dialog, and a computed property `isRunning`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const { confirm, isRunning } = useConfirm();
|
|
11
|
+
*
|
|
12
|
+
* const removed = await confirm(
|
|
13
|
+
* { title: "Excluir paciente", message: "Esta ação não pode ser desfeita.", confirmText: "Excluir", color: "danger" },
|
|
14
|
+
* () => api.deletePatient(id),
|
|
15
|
+
* );
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function useConfirm() {
|
|
19
|
+
const { run, isRunning } = useRunOrToast();
|
|
20
|
+
/**
|
|
21
|
+
* Displays a confirmation dialog and, if the user confirms, runs the given function while the
|
|
22
|
+
* dialog shows the confirm button loading. If the function throws an error, the dialog closes
|
|
23
|
+
* and a toast shows the error message.
|
|
24
|
+
* @returns the function returned value, or `false` if the user cancels or the function fails
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const { confirm } = useConfirm();
|
|
29
|
+
*
|
|
30
|
+
* // Call like this:
|
|
31
|
+
* const result1 = await confirm({ message: "Salvar alterações?" }, () => save(form));
|
|
32
|
+
*
|
|
33
|
+
* // Or this:
|
|
34
|
+
* const result2 = await confirm({ message: "Salvar alterações?" }, save, form);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function confirm(options, action, ...params) {
|
|
38
|
+
return openDialog({
|
|
39
|
+
title: options.title,
|
|
40
|
+
message: options.message,
|
|
41
|
+
role: "alertdialog",
|
|
42
|
+
actions: [{ text: options.cancelText ?? "Cancelar" }, {
|
|
43
|
+
text: options.confirmText ?? "Confirmar",
|
|
44
|
+
value: "confirm",
|
|
45
|
+
color: options.color
|
|
46
|
+
}]
|
|
47
|
+
}, (value) => value === "confirm" ? run(action, ...params) : false);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
confirm,
|
|
51
|
+
isRunning
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { useConfirm as default };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/composables/dialogs/use-decorative-timer.ts
|
|
2
|
+
/**
|
|
3
|
+
* Content props that hide a snackbar's timer bar from assistive technologies,
|
|
4
|
+
* keeping it only as a visual countdown, since the message itself is already
|
|
5
|
+
* announced by the snackbar's live region.
|
|
6
|
+
*
|
|
7
|
+
* Workaround until Vuetify offers an option for it: the timer bar is a
|
|
8
|
+
* `VProgressLinear` that always renders `role="progressbar"` with
|
|
9
|
+
* `aria-hidden="false"` and no accessible name, and neither `VSnackbar` nor
|
|
10
|
+
* Vuetify's defaults can set attributes on it. So these vnode hooks mark the
|
|
11
|
+
* bar after every render of the snackbar content, which also covers the bar
|
|
12
|
+
* recreated when the pointer leaves the snackbar. Vue doesn't patch the
|
|
13
|
+
* attribute back, since Vuetify keeps rendering the same `"false"` value.
|
|
14
|
+
*/
|
|
15
|
+
function useDecorativeTimer() {
|
|
16
|
+
return {
|
|
17
|
+
onVnodeMounted: hideTimer,
|
|
18
|
+
onVnodeUpdated: hideTimer
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function hideTimer({ el }) {
|
|
22
|
+
el?.querySelector(".v-snackbar__timer [role='progressbar']")?.setAttribute("aria-hidden", "true");
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { useDecorativeTimer as default };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { onMounted, toValue, watch } from "vue";
|
|
2
|
+
//#region src/composables/dialogs/use-dialog-focus.ts
|
|
3
|
+
/** Focus state of the closed dialogs, by their card, for the dialogs opened from them. */
|
|
4
|
+
const closedDialogs = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
/** Elements that can get the focus when the dialog opens. The first one in the dialog gets it. */
|
|
6
|
+
const focusable = [
|
|
7
|
+
"button:not([disabled])",
|
|
8
|
+
"[href]",
|
|
9
|
+
"input:not([disabled]):not([type=\"hidden\"])",
|
|
10
|
+
"select:not([disabled])",
|
|
11
|
+
"textarea:not([disabled])",
|
|
12
|
+
"[tabindex]:not([tabindex=\"-1\"])"
|
|
13
|
+
].join(", ");
|
|
14
|
+
/**
|
|
15
|
+
* Moves the focus into a dialog once it opens and back to where it was when it closes, including
|
|
16
|
+
* when dialogs are opened from others. Internal to the dialog components.
|
|
17
|
+
* @param isActive - Whether the dialog is displayed. It turns `false` as soon as the dialog starts
|
|
18
|
+
* leaving, so the focus returns right away.
|
|
19
|
+
* @param card - The dialog's card, marked with `data-u-dialog`, or nothing while it isn't rendered.
|
|
20
|
+
* @returns `focusFirstElement`, to call once the dialog finishes entering.
|
|
21
|
+
*/
|
|
22
|
+
function useDialogFocus(isActive, card) {
|
|
23
|
+
/** Focus state of this dialog, shared with the dialogs opened from it. */
|
|
24
|
+
const focusState = {
|
|
25
|
+
isOpen: () => toValue(isActive),
|
|
26
|
+
origin: null
|
|
27
|
+
};
|
|
28
|
+
onMounted(() => onActiveChange(toValue(isActive)));
|
|
29
|
+
watch(() => toValue(isActive), onActiveChange);
|
|
30
|
+
function onActiveChange(active) {
|
|
31
|
+
if (active) {
|
|
32
|
+
focusState.origin = document.activeElement;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const element = toValue(card);
|
|
36
|
+
if (element) closedDialogs.set(element, focusState);
|
|
37
|
+
const target = findFocusTarget(focusState.origin);
|
|
38
|
+
if (hasFocus(element) && (target instanceof HTMLElement || target instanceof SVGElement)) target.focus();
|
|
39
|
+
}
|
|
40
|
+
function focusFirstElement() {
|
|
41
|
+
toValue(card)?.querySelector(focusable)?.focus();
|
|
42
|
+
}
|
|
43
|
+
return { focusFirstElement };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Element that gets the focus back when a dialog closes: its origin or, when the origin is inside
|
|
47
|
+
* another dialog that closed meanwhile (and can't get the focus anymore), that dialog's.
|
|
48
|
+
*/
|
|
49
|
+
function findFocusTarget(origin) {
|
|
50
|
+
const card = origin?.closest("[data-u-dialog]");
|
|
51
|
+
const owner = card && closedDialogs.get(card);
|
|
52
|
+
return owner && !owner.isOpen() ? findFocusTarget(owner.origin) : origin;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether the focus is on the dialog or lost (on nothing or on the page's body), so it can move.
|
|
56
|
+
* Otherwise it moved elsewhere, e.g. to another dialog opened over this one.
|
|
57
|
+
*/
|
|
58
|
+
function hasFocus(card) {
|
|
59
|
+
const active = document.activeElement;
|
|
60
|
+
if (!active) return true;
|
|
61
|
+
return !!card && (card.contains(active) || active.contains(card));
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { useDialogFocus };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { computed, toValue } from "vue";
|
|
2
|
+
//#region src/composables/dialogs/use-dialog-loading.ts
|
|
3
|
+
/**
|
|
4
|
+
* Tells whether any action of a dialog is loading, during which the user can't close it with
|
|
5
|
+
* `Esc`, a click outside or the browser's back button. Internal to the dialog components.
|
|
6
|
+
* @param actions - The dialog's actions, if any.
|
|
7
|
+
* @returns `isLoading`, which is `true` while at least one action is `loading`.
|
|
8
|
+
*/
|
|
9
|
+
function useDialogLoading(actions) {
|
|
10
|
+
return { isLoading: computed(() => toValue(actions)?.some((action) => action.loading) ?? false) };
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { useDialogLoading };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import "../../components/button/types.js";
|
|
2
|
+
import { DialogOptions } from "./types.js";
|
|
3
|
+
//#region src/composables/dialogs/use-dialog.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Composable which returns a function to display dialogs.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const { dialog } = useDialog();
|
|
10
|
+
*
|
|
11
|
+
* const answer = await dialog({
|
|
12
|
+
* title: "Sessão expirando",
|
|
13
|
+
* message: "Deseja continuar conectado?",
|
|
14
|
+
* actions: [
|
|
15
|
+
* { text: "Sair", value: "leave" },
|
|
16
|
+
* { text: "Continuar", value: "stay" },
|
|
17
|
+
* ],
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export default function useDialog(): {
|
|
22
|
+
dialog: typeof dialog;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Displays a dialog. Dialogs are displayed one at a time, in the order they were requested.
|
|
26
|
+
* @param {DialogOptions} options - Options for the dialog.
|
|
27
|
+
* @returns the `value` of the clicked action, or `undefined` when the dialog is closed by the
|
|
28
|
+
* default action, the `Esc` key, a click outside it or the browser's back button.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* await dialog({ title: "Aviso", message: "Seu cadastro foi enviado para análise." });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
declare function dialog<T extends string = never>(options: DialogOptions<T>): Promise<T | undefined>;
|
|
36
|
+
//#endregion
|