@groupteknology/vuno 0.4.0 → 0.6.1
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/LICENSE +21 -21
- package/README.md +198 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +6 -0
- package/dist/runtime/app/assets/css/main.css +1 -1
- package/dist/runtime/app/components/App/App.d.vue.ts +33 -0
- package/dist/runtime/app/components/App/App.vue +127 -0
- package/dist/runtime/app/components/App/App.vue.d.ts +33 -0
- package/dist/runtime/app/components/App/AppContext.d.vue.ts +3 -0
- package/dist/runtime/app/components/App/AppContext.vue +7 -0
- package/dist/runtime/app/components/App/AppContext.vue.d.ts +3 -0
- package/dist/runtime/app/components/App/AppModal.d.vue.ts +38 -0
- package/dist/runtime/app/components/App/AppModal.vue +103 -0
- package/dist/runtime/app/components/App/AppModal.vue.d.ts +38 -0
- package/dist/runtime/app/components/App/AppOverlay.d.vue.ts +7 -0
- package/dist/runtime/app/components/App/AppOverlay.vue +33 -0
- package/dist/runtime/app/components/App/AppOverlay.vue.d.ts +7 -0
- package/dist/runtime/app/components/App/AppToast.d.vue.ts +11 -0
- package/dist/runtime/app/components/App/AppToast.vue +53 -0
- package/dist/runtime/app/components/App/AppToast.vue.d.ts +11 -0
- package/dist/runtime/app/components/App/AppToaster.d.vue.ts +11 -0
- package/dist/runtime/app/components/App/AppToaster.vue +49 -0
- package/dist/runtime/app/components/App/AppToaster.vue.d.ts +11 -0
- package/dist/runtime/app/components/Cell/CellBadge.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellBadge.vue +24 -0
- package/dist/runtime/app/components/Cell/CellBadge.vue.d.ts +5 -0
- package/dist/runtime/app/components/Cell/CellBoolean.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellBoolean.vue +21 -0
- package/dist/runtime/app/components/Cell/CellBoolean.vue.d.ts +5 -0
- package/dist/runtime/app/components/Cell/CellCurrency.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellCurrency.vue +14 -0
- package/dist/runtime/app/components/Cell/CellCurrency.vue.d.ts +5 -0
- package/dist/runtime/app/components/Cell/CellDate.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellDate.vue +19 -0
- package/dist/runtime/app/components/Cell/CellDate.vue.d.ts +5 -0
- package/dist/runtime/app/components/Cell/CellImage.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellImage.vue +22 -0
- package/dist/runtime/app/components/Cell/CellImage.vue.d.ts +5 -0
- package/dist/runtime/app/components/Cell/CellNumber.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellNumber.vue +15 -0
- package/dist/runtime/app/components/Cell/CellNumber.vue.d.ts +5 -0
- package/dist/runtime/app/components/Cell/CellText.d.vue.ts +5 -0
- package/dist/runtime/app/components/Cell/CellText.vue +13 -0
- package/dist/runtime/app/components/Cell/CellText.vue.d.ts +5 -0
- package/dist/runtime/app/components/Confirm/Confirm.vue +20 -13
- package/dist/runtime/app/components/Field/FieldArray.vue +68 -68
- package/dist/runtime/app/components/Field/FieldColor.vue +36 -36
- package/dist/runtime/app/components/Form/Form.vue +61 -49
- package/dist/runtime/app/components/Form/FormModal.vue +23 -15
- package/dist/runtime/app/components/Form/FormSection.vue +27 -27
- package/dist/runtime/app/components/Page/Page.vue +46 -46
- package/dist/runtime/app/components/State/EmptyState.vue +20 -20
- package/dist/runtime/app/components/State/FailureState.vue +21 -21
- package/dist/runtime/app/components/Table/Table.vue +286 -373
- package/dist/runtime/app/components/Table/TableCell.vue +24 -73
- package/dist/runtime/app/composables/useVunoConfirm.d.ts +15 -0
- package/dist/runtime/app/composables/useVunoConfirm.js +5 -0
- package/dist/runtime/app/composables/useVunoContext.d.ts +13 -0
- package/dist/runtime/app/composables/useVunoContext.js +9 -0
- package/dist/runtime/app/composables/useVunoModal.d.ts +21 -0
- package/dist/runtime/app/composables/useVunoModal.js +26 -0
- package/dist/runtime/app/composables/useVunoOverlay.d.ts +22 -0
- package/dist/runtime/app/composables/useVunoOverlay.js +10 -0
- package/dist/runtime/app/composables/useVunoTableQuery.js +3 -3
- package/dist/runtime/app/composables/useVunoTheme.js +2 -1
- package/dist/runtime/app/composables/useVunoToast.d.ts +28 -0
- package/dist/runtime/app/composables/useVunoToast.js +13 -0
- package/dist/runtime/app/internal/useVunoTable.d.ts +65 -0
- package/dist/runtime/app/internal/useVunoTable.js +161 -0
- package/dist/runtime/app/theme/index.js +69 -2
- package/dist/runtime/app/types/app.d.ts +83 -0
- package/dist/runtime/app/types/app.js +0 -0
- package/dist/runtime/app/types/confirm.d.ts +8 -0
- package/dist/runtime/app/types/index.d.ts +1 -0
- package/dist/runtime/app/types/table.d.ts +80 -13
- package/dist/runtime/app/types/theme.d.ts +12 -0
- package/dist/runtime/app/utils/column.d.ts +9 -0
- package/dist/runtime/app/utils/column.js +5 -0
- package/dist/runtime/app/utils/pagination.d.ts +12 -0
- package/dist/runtime/app/utils/pagination.js +6 -0
- package/package.json +6 -3
|
@@ -57,72 +57,72 @@ function move(index, offset) {
|
|
|
57
57
|
</script>
|
|
58
58
|
|
|
59
59
|
<template>
|
|
60
|
-
<div :class="ui.root">
|
|
61
|
-
<div
|
|
62
|
-
v-for="(item, index) in items"
|
|
63
|
-
:key="index"
|
|
64
|
-
:class="ui.item"
|
|
65
|
-
>
|
|
66
|
-
<div :class="ui.itemHeader">
|
|
67
|
-
<span :class="ui.itemLabel">{{ index + 1 }}</span>
|
|
68
|
-
|
|
69
|
-
<div :class="ui.itemActions">
|
|
70
|
-
<UButton
|
|
71
|
-
v-if="props.sortable && index > 0"
|
|
72
|
-
:aria-label="messages.fileMoveUp"
|
|
73
|
-
color="neutral"
|
|
74
|
-
:icon="icons.fileMoveUp"
|
|
75
|
-
size="xs"
|
|
76
|
-
variant="ghost"
|
|
77
|
-
@click="move(index, -1)"
|
|
78
|
-
/>
|
|
79
|
-
<UButton
|
|
80
|
-
v-if="props.sortable && index < items.length - 1"
|
|
81
|
-
:aria-label="messages.fileMoveDown"
|
|
82
|
-
color="neutral"
|
|
83
|
-
:icon="icons.fileMoveDown"
|
|
84
|
-
size="xs"
|
|
85
|
-
variant="ghost"
|
|
86
|
-
@click="move(index, 1)"
|
|
87
|
-
/>
|
|
88
|
-
<UButton
|
|
89
|
-
:aria-label="messages.removeItem"
|
|
90
|
-
color="error"
|
|
91
|
-
:disabled="!canRemove"
|
|
92
|
-
:icon="icons.removeItem"
|
|
93
|
-
size="xs"
|
|
94
|
-
variant="ghost"
|
|
95
|
-
@click="remove(index)"
|
|
96
|
-
/>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<div :class="ui.itemFields">
|
|
101
|
-
<div
|
|
102
|
-
v-for="field in props.fields"
|
|
103
|
-
:key="`${index}-${field.name}`"
|
|
104
|
-
:class="getColumnSpanClass(field.columns)"
|
|
105
|
-
>
|
|
106
|
-
<FormField :field="fieldAt(field, index)" />
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
|
|
111
|
-
<div
|
|
112
|
-
v-if="items.length === 0"
|
|
113
|
-
:class="ui.empty"
|
|
114
|
-
>
|
|
115
|
-
{{ messages.emptyArray }}
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
<UButton
|
|
119
|
-
class="self-start"
|
|
120
|
-
color="neutral"
|
|
121
|
-
:disabled="!canAdd"
|
|
122
|
-
:icon="icons.addItem"
|
|
123
|
-
:label="props.addLabel ?? messages.addItem"
|
|
124
|
-
variant="outline"
|
|
125
|
-
@click="add"
|
|
126
|
-
/>
|
|
127
|
-
</div>
|
|
60
|
+
<div :class="ui.root">
|
|
61
|
+
<div
|
|
62
|
+
v-for="(item, index) in items"
|
|
63
|
+
:key="index"
|
|
64
|
+
:class="ui.item"
|
|
65
|
+
>
|
|
66
|
+
<div :class="ui.itemHeader">
|
|
67
|
+
<span :class="ui.itemLabel">{{ index + 1 }}</span>
|
|
68
|
+
|
|
69
|
+
<div :class="ui.itemActions">
|
|
70
|
+
<UButton
|
|
71
|
+
v-if="props.sortable && index > 0"
|
|
72
|
+
:aria-label="messages.fileMoveUp"
|
|
73
|
+
color="neutral"
|
|
74
|
+
:icon="icons.fileMoveUp"
|
|
75
|
+
size="xs"
|
|
76
|
+
variant="ghost"
|
|
77
|
+
@click="move(index, -1)"
|
|
78
|
+
/>
|
|
79
|
+
<UButton
|
|
80
|
+
v-if="props.sortable && index < items.length - 1"
|
|
81
|
+
:aria-label="messages.fileMoveDown"
|
|
82
|
+
color="neutral"
|
|
83
|
+
:icon="icons.fileMoveDown"
|
|
84
|
+
size="xs"
|
|
85
|
+
variant="ghost"
|
|
86
|
+
@click="move(index, 1)"
|
|
87
|
+
/>
|
|
88
|
+
<UButton
|
|
89
|
+
:aria-label="messages.removeItem"
|
|
90
|
+
color="error"
|
|
91
|
+
:disabled="!canRemove"
|
|
92
|
+
:icon="icons.removeItem"
|
|
93
|
+
size="xs"
|
|
94
|
+
variant="ghost"
|
|
95
|
+
@click="remove(index)"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div :class="ui.itemFields">
|
|
101
|
+
<div
|
|
102
|
+
v-for="field in props.fields"
|
|
103
|
+
:key="`${index}-${field.name}`"
|
|
104
|
+
:class="getColumnSpanClass(field.columns)"
|
|
105
|
+
>
|
|
106
|
+
<FormField :field="fieldAt(field, index)" />
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div
|
|
112
|
+
v-if="items.length === 0"
|
|
113
|
+
:class="ui.empty"
|
|
114
|
+
>
|
|
115
|
+
{{ messages.emptyArray }}
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<UButton
|
|
119
|
+
class="self-start"
|
|
120
|
+
color="neutral"
|
|
121
|
+
:disabled="!canAdd"
|
|
122
|
+
:icon="icons.addItem"
|
|
123
|
+
:label="props.addLabel ?? messages.addItem"
|
|
124
|
+
variant="outline"
|
|
125
|
+
@click="add"
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
128
|
</template>
|
|
@@ -18,40 +18,40 @@ const ui = useVunoTheme("fieldColor", () => props.ui);
|
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<template>
|
|
21
|
-
<div :class="ui.root">
|
|
22
|
-
<!-- El selector nativo y el texto comparten valor: se puede pegar un
|
|
23
|
-
código de la guía de marca sin pelearse con la rueda de color. -->
|
|
24
|
-
<UPopover>
|
|
25
|
-
<UButton
|
|
26
|
-
:aria-label="props.label"
|
|
27
|
-
color="neutral"
|
|
28
|
-
:disabled="props.disabled"
|
|
29
|
-
:size="props.size"
|
|
30
|
-
:ui="{ leadingIcon: 'rounded-full' }"
|
|
31
|
-
variant="outline"
|
|
32
|
-
>
|
|
33
|
-
<span
|
|
34
|
-
:class="ui.swatch"
|
|
35
|
-
:style="{ backgroundColor: value || 'transparent' }"
|
|
36
|
-
/>
|
|
37
|
-
</UButton>
|
|
38
|
-
|
|
39
|
-
<template #content>
|
|
40
|
-
<UColorPicker
|
|
41
|
-
v-model="value"
|
|
42
|
-
class="p-2"
|
|
43
|
-
/>
|
|
44
|
-
</template>
|
|
45
|
-
</UPopover>
|
|
46
|
-
|
|
47
|
-
<UInput
|
|
48
|
-
v-model="value"
|
|
49
|
-
class="font-mono"
|
|
50
|
-
:disabled="props.disabled"
|
|
51
|
-
:name="props.name"
|
|
52
|
-
:placeholder="props.placeholder ?? '#000000'"
|
|
53
|
-
:size="props.size"
|
|
54
|
-
:ui="{ root: 'w-full' }"
|
|
55
|
-
/>
|
|
56
|
-
</div>
|
|
21
|
+
<div :class="ui.root">
|
|
22
|
+
<!-- El selector nativo y el texto comparten valor: se puede pegar un
|
|
23
|
+
código de la guía de marca sin pelearse con la rueda de color. -->
|
|
24
|
+
<UPopover>
|
|
25
|
+
<UButton
|
|
26
|
+
:aria-label="props.label"
|
|
27
|
+
color="neutral"
|
|
28
|
+
:disabled="props.disabled"
|
|
29
|
+
:size="props.size"
|
|
30
|
+
:ui="{ leadingIcon: 'rounded-full' }"
|
|
31
|
+
variant="outline"
|
|
32
|
+
>
|
|
33
|
+
<span
|
|
34
|
+
:class="ui.swatch"
|
|
35
|
+
:style="{ backgroundColor: value || 'transparent' }"
|
|
36
|
+
/>
|
|
37
|
+
</UButton>
|
|
38
|
+
|
|
39
|
+
<template #content>
|
|
40
|
+
<UColorPicker
|
|
41
|
+
v-model="value"
|
|
42
|
+
class="p-2"
|
|
43
|
+
/>
|
|
44
|
+
</template>
|
|
45
|
+
</UPopover>
|
|
46
|
+
|
|
47
|
+
<UInput
|
|
48
|
+
v-model="value"
|
|
49
|
+
class="font-mono"
|
|
50
|
+
:disabled="props.disabled"
|
|
51
|
+
:name="props.name"
|
|
52
|
+
:placeholder="props.placeholder ?? '#000000'"
|
|
53
|
+
:size="props.size"
|
|
54
|
+
:ui="{ root: 'w-full' }"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
57
|
</template>
|
|
@@ -86,53 +86,65 @@ defineExpose({ dirty, errors: errorNames, isDirty, reset, resetField, submit: ()
|
|
|
86
86
|
</script>
|
|
87
87
|
|
|
88
88
|
<template>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
>
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
89
|
+
<!--
|
|
90
|
+
`novalidate` apaga la validación nativa del navegador, no el `required`.
|
|
91
|
+
Sin él conviven dos validaciones: la del navegador corta el envío antes
|
|
92
|
+
de que el esquema llegue a ejecutarse, y avisa con un globo suyo, en el
|
|
93
|
+
idioma del navegador y sin pasar por el tema. Los mensajes del esquema
|
|
94
|
+
no llegaban a verse en los campos obligatorios.
|
|
95
|
+
|
|
96
|
+
El atributo `required` se queda en los inputs, que es lo que anuncia el
|
|
97
|
+
campo como obligatorio a un lector de pantalla y lo que permite
|
|
98
|
+
estilarlo; lo único que se apaga es la interfaz nativa.
|
|
99
|
+
-->
|
|
100
|
+
<UForm
|
|
101
|
+
:id="formId"
|
|
102
|
+
ref="form"
|
|
103
|
+
novalidate
|
|
104
|
+
:schema="props.schema"
|
|
105
|
+
:state="state"
|
|
106
|
+
:ui="{ base: ui.base }"
|
|
107
|
+
@submit="onSubmit"
|
|
108
|
+
>
|
|
109
|
+
<UTabs
|
|
110
|
+
v-if="isTabs"
|
|
111
|
+
:defaultValue="tabItems[0]?.value"
|
|
112
|
+
:items="tabItems"
|
|
113
|
+
:size="size"
|
|
114
|
+
:ui="{ root: ui.tabs, content: ui.tabsContent }"
|
|
115
|
+
:unmountOnHide="false"
|
|
116
|
+
variant="link"
|
|
117
|
+
>
|
|
118
|
+
<template #content="{ item }">
|
|
119
|
+
<FormSection
|
|
120
|
+
plain
|
|
121
|
+
:section="item.section"
|
|
122
|
+
/>
|
|
123
|
+
</template>
|
|
124
|
+
</UTabs>
|
|
125
|
+
|
|
126
|
+
<div
|
|
127
|
+
v-else
|
|
128
|
+
:class="ui.sections"
|
|
129
|
+
>
|
|
130
|
+
<div
|
|
131
|
+
v-for="(section, index) in props.definition.sections"
|
|
132
|
+
:key="`${section.id}-${index}`"
|
|
133
|
+
:class="getColumnSpanClass(section.columns)"
|
|
134
|
+
>
|
|
135
|
+
<FormSection :section="section" />
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<div
|
|
140
|
+
v-if="slots.footer"
|
|
141
|
+
:class="ui.footer"
|
|
142
|
+
>
|
|
143
|
+
<slot
|
|
144
|
+
:dirty="dirty"
|
|
145
|
+
name="footer"
|
|
146
|
+
:reset="reset"
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
</UForm>
|
|
138
150
|
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed, useId, useTemplateRef } from "vue";
|
|
3
3
|
import { useVunoMessages, useVunoTheme } from "#vuno/composables/useVunoTheme";
|
|
4
|
+
import AppModal from "#vuno/components/App/AppModal.vue";
|
|
4
5
|
import Form from "./Form.vue";
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
closeOnSubmit: { type: Boolean, required: false },
|
|
@@ -18,7 +19,7 @@ const state = defineModel("state", { type: null, ...{ required: true } });
|
|
|
18
19
|
defineSlots();
|
|
19
20
|
const messages = useVunoMessages();
|
|
20
21
|
const ui = useVunoTheme("formModal", () => props.ui);
|
|
21
|
-
const modalUi = computed(() => ({ body: ui.value.body, content: ui.value.content, footer: ui.value.footer }));
|
|
22
|
+
const modalUi = computed(() => ({ body: ui.value.body, content: ui.value.content, footer: ui.value.footer, root: ui.value.root }));
|
|
22
23
|
const formId = useId();
|
|
23
24
|
const form = useTemplateRef("form");
|
|
24
25
|
function close() {
|
|
@@ -33,27 +34,34 @@ function onSubmit(event) {
|
|
|
33
34
|
</script>
|
|
34
35
|
|
|
35
36
|
<template>
|
|
36
|
-
|
|
37
|
+
<!--
|
|
38
|
+
Sobre `AppModal`: un `<dialog>` nativo, no el de Nuxt UI. El navegador lo
|
|
39
|
+
pone en su capa superior, que atrapa el foco, lo devuelve al cerrar y
|
|
40
|
+
apila los diálogos por orden de apertura.
|
|
41
|
+
|
|
42
|
+
Importa que sean todos del mismo sistema: la capa superior queda por
|
|
43
|
+
encima de cualquier z-index, así que un formulario posicionado con
|
|
44
|
+
z-index abierto sobre un diálogo nativo se pintaría detrás de él, en el
|
|
45
|
+
DOM y sin verse.
|
|
46
|
+
-->
|
|
47
|
+
<AppModal
|
|
37
48
|
v-model:open="open"
|
|
38
49
|
:description="props.description"
|
|
39
50
|
:dismissible="!props.loading"
|
|
40
|
-
scrollable
|
|
41
51
|
:title="props.title"
|
|
42
52
|
:ui="modalUi"
|
|
43
53
|
>
|
|
44
54
|
<slot name="trigger" />
|
|
45
55
|
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
/>
|
|
56
|
-
</template>
|
|
56
|
+
<Form
|
|
57
|
+
:id="formId"
|
|
58
|
+
ref="form"
|
|
59
|
+
v-model:state="state"
|
|
60
|
+
:definition="props.definition"
|
|
61
|
+
:schema="props.schema"
|
|
62
|
+
:ui="props.formUi"
|
|
63
|
+
@submit="onSubmit"
|
|
64
|
+
/>
|
|
57
65
|
|
|
58
66
|
<template #footer>
|
|
59
67
|
<slot
|
|
@@ -79,5 +87,5 @@ function onSubmit(event) {
|
|
|
79
87
|
/>
|
|
80
88
|
</slot>
|
|
81
89
|
</template>
|
|
82
|
-
</
|
|
90
|
+
</AppModal>
|
|
83
91
|
</template>
|
|
@@ -13,31 +13,31 @@ const showHeader = computed(() => props.plain ? Boolean(props.section.descriptio
|
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<template>
|
|
16
|
-
<div :class="root">
|
|
17
|
-
<div
|
|
18
|
-
v-if="showHeader"
|
|
19
|
-
:class="ui.header"
|
|
20
|
-
>
|
|
21
|
-
<p
|
|
22
|
-
v-if="props.section.title && !props.plain"
|
|
23
|
-
:class="ui.title"
|
|
24
|
-
>
|
|
25
|
-
{{ props.section.title }}
|
|
26
|
-
</p>
|
|
27
|
-
<p
|
|
28
|
-
v-if="props.section.description"
|
|
29
|
-
:class="ui.description"
|
|
30
|
-
>
|
|
31
|
-
{{ props.section.description }}
|
|
32
|
-
</p>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<div
|
|
36
|
-
v-for="(field, index) in props.section.fields"
|
|
37
|
-
:key="`${field.name}-${index}`"
|
|
38
|
-
:class="getColumnSpanClass(field.columns)"
|
|
39
|
-
>
|
|
40
|
-
<FormField :field="field" />
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
16
|
+
<div :class="root">
|
|
17
|
+
<div
|
|
18
|
+
v-if="showHeader"
|
|
19
|
+
:class="ui.header"
|
|
20
|
+
>
|
|
21
|
+
<p
|
|
22
|
+
v-if="props.section.title && !props.plain"
|
|
23
|
+
:class="ui.title"
|
|
24
|
+
>
|
|
25
|
+
{{ props.section.title }}
|
|
26
|
+
</p>
|
|
27
|
+
<p
|
|
28
|
+
v-if="props.section.description"
|
|
29
|
+
:class="ui.description"
|
|
30
|
+
>
|
|
31
|
+
{{ props.section.description }}
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div
|
|
36
|
+
v-for="(field, index) in props.section.fields"
|
|
37
|
+
:key="`${field.name}-${index}`"
|
|
38
|
+
:class="getColumnSpanClass(field.columns)"
|
|
39
|
+
>
|
|
40
|
+
<FormField :field="field" />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
43
|
</template>
|
|
@@ -14,50 +14,50 @@ const navbarUi = computed(() => ({ left: ui.value.navbarLeft, root: ui.value.nav
|
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<template>
|
|
17
|
-
<UDashboardPanel :ui="panelUi">
|
|
18
|
-
<template #header>
|
|
19
|
-
<UDashboardNavbar :ui="navbarUi">
|
|
20
|
-
<!--
|
|
21
|
-
Se ocupa `#left` entero en vez de `#title`: el `#title` de la
|
|
22
|
-
barra vive dentro de un `<h1>`, y una miga de pan ahí sería un
|
|
23
|
-
`<nav>` dentro de un encabezado.
|
|
24
|
-
-->
|
|
25
|
-
<template #left>
|
|
26
|
-
<slot name="leading" />
|
|
27
|
-
|
|
28
|
-
<!-- En `neutral`: en color de marca, el último segmento se lee
|
|
29
|
-
como un enlace a otro sitio. -->
|
|
30
|
-
<UBreadcrumb
|
|
31
|
-
v-if="props.breadcrumb?.length"
|
|
32
|
-
:class="ui.breadcrumb"
|
|
33
|
-
color="neutral"
|
|
34
|
-
:items="props.breadcrumb"
|
|
35
|
-
/>
|
|
36
|
-
</template>
|
|
37
|
-
|
|
38
|
-
<template #right>
|
|
39
|
-
<slot name="actions" />
|
|
40
|
-
</template>
|
|
41
|
-
</UDashboardNavbar>
|
|
42
|
-
</template>
|
|
43
|
-
|
|
44
|
-
<template #body>
|
|
45
|
-
<div :class="ui.body">
|
|
46
|
-
<!-- Un `<div>` y no un `<header>`: un `<header>` suelto es un
|
|
47
|
-
landmark `banner`, y solo puede haber uno por página. -->
|
|
48
|
-
<div :class="ui.heading">
|
|
49
|
-
<h1 :class="ui.title">{{ props.title }}</h1>
|
|
50
|
-
|
|
51
|
-
<p
|
|
52
|
-
v-if="props.description"
|
|
53
|
-
:class="ui.description"
|
|
54
|
-
>
|
|
55
|
-
{{ props.description }}
|
|
56
|
-
</p>
|
|
57
|
-
</div>
|
|
58
|
-
|
|
59
|
-
<slot />
|
|
60
|
-
</div>
|
|
61
|
-
</template>
|
|
62
|
-
</UDashboardPanel>
|
|
17
|
+
<UDashboardPanel :ui="panelUi">
|
|
18
|
+
<template #header>
|
|
19
|
+
<UDashboardNavbar :ui="navbarUi">
|
|
20
|
+
<!--
|
|
21
|
+
Se ocupa `#left` entero en vez de `#title`: el `#title` de la
|
|
22
|
+
barra vive dentro de un `<h1>`, y una miga de pan ahí sería un
|
|
23
|
+
`<nav>` dentro de un encabezado.
|
|
24
|
+
-->
|
|
25
|
+
<template #left>
|
|
26
|
+
<slot name="leading" />
|
|
27
|
+
|
|
28
|
+
<!-- En `neutral`: en color de marca, el último segmento se lee
|
|
29
|
+
como un enlace a otro sitio. -->
|
|
30
|
+
<UBreadcrumb
|
|
31
|
+
v-if="props.breadcrumb?.length"
|
|
32
|
+
:class="ui.breadcrumb"
|
|
33
|
+
color="neutral"
|
|
34
|
+
:items="props.breadcrumb"
|
|
35
|
+
/>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<template #right>
|
|
39
|
+
<slot name="actions" />
|
|
40
|
+
</template>
|
|
41
|
+
</UDashboardNavbar>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<template #body>
|
|
45
|
+
<div :class="ui.body">
|
|
46
|
+
<!-- Un `<div>` y no un `<header>`: un `<header>` suelto es un
|
|
47
|
+
landmark `banner`, y solo puede haber uno por página. -->
|
|
48
|
+
<div :class="ui.heading">
|
|
49
|
+
<h1 :class="ui.title">{{ props.title }}</h1>
|
|
50
|
+
|
|
51
|
+
<p
|
|
52
|
+
v-if="props.description"
|
|
53
|
+
:class="ui.description"
|
|
54
|
+
>
|
|
55
|
+
{{ props.description }}
|
|
56
|
+
</p>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<slot />
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
</UDashboardPanel>
|
|
63
63
|
</template>
|
|
@@ -13,24 +13,24 @@ const ui = useVunoTheme("state", () => props.ui);
|
|
|
13
13
|
</script>
|
|
14
14
|
|
|
15
15
|
<template>
|
|
16
|
-
<div :class="ui.root">
|
|
17
|
-
<UIcon
|
|
18
|
-
class="text-dimmed"
|
|
19
|
-
:class="ui.icon"
|
|
20
|
-
:name="props.icon ?? icons.empty"
|
|
21
|
-
/>
|
|
22
|
-
|
|
23
|
-
<p :class="ui.title">{{ props.title ?? messages.emptyTable }}</p>
|
|
24
|
-
|
|
25
|
-
<p
|
|
26
|
-
v-if="props.hint"
|
|
27
|
-
:class="ui.hint"
|
|
28
|
-
>
|
|
29
|
-
{{ props.hint }}
|
|
30
|
-
</p>
|
|
31
|
-
|
|
32
|
-
<div :class="ui.actions">
|
|
33
|
-
<slot name="actions" />
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
16
|
+
<div :class="ui.root">
|
|
17
|
+
<UIcon
|
|
18
|
+
class="text-dimmed"
|
|
19
|
+
:class="ui.icon"
|
|
20
|
+
:name="props.icon ?? icons.empty"
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<p :class="ui.title">{{ props.title ?? messages.emptyTable }}</p>
|
|
24
|
+
|
|
25
|
+
<p
|
|
26
|
+
v-if="props.hint"
|
|
27
|
+
:class="ui.hint"
|
|
28
|
+
>
|
|
29
|
+
{{ props.hint }}
|
|
30
|
+
</p>
|
|
31
|
+
|
|
32
|
+
<div :class="ui.actions">
|
|
33
|
+
<slot name="actions" />
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
36
|
</template>
|
|
@@ -10,25 +10,25 @@ const ui = useVunoTheme("state", () => props.ui);
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<template>
|
|
13
|
-
<div :class="ui.root">
|
|
14
|
-
<UIcon
|
|
15
|
-
class="text-error"
|
|
16
|
-
:class="ui.icon"
|
|
17
|
-
:name="icons.failure"
|
|
18
|
-
/>
|
|
19
|
-
|
|
20
|
-
<p :class="ui.title">{{ props.failure.title ?? messages.failureTitle }}</p>
|
|
21
|
-
|
|
22
|
-
<p :class="ui.hint">{{ props.failure.hint ?? messages.failureHint }}</p>
|
|
23
|
-
|
|
24
|
-
<div :class="ui.actions">
|
|
25
|
-
<UButton
|
|
26
|
-
color="neutral"
|
|
27
|
-
:icon="icons.retry"
|
|
28
|
-
:label="messages.retry"
|
|
29
|
-
variant="outline"
|
|
30
|
-
@click="props.failure.retry()"
|
|
31
|
-
/>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
13
|
+
<div :class="ui.root">
|
|
14
|
+
<UIcon
|
|
15
|
+
class="text-error"
|
|
16
|
+
:class="ui.icon"
|
|
17
|
+
:name="icons.failure"
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
<p :class="ui.title">{{ props.failure.title ?? messages.failureTitle }}</p>
|
|
21
|
+
|
|
22
|
+
<p :class="ui.hint">{{ props.failure.hint ?? messages.failureHint }}</p>
|
|
23
|
+
|
|
24
|
+
<div :class="ui.actions">
|
|
25
|
+
<UButton
|
|
26
|
+
color="neutral"
|
|
27
|
+
:icon="icons.retry"
|
|
28
|
+
:label="messages.retry"
|
|
29
|
+
variant="outline"
|
|
30
|
+
@click="props.failure.retry()"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
34
|
</template>
|