@raclettejs/workbench 0.1.33-canary.2 → 0.1.33
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/.raclette/backend/raclette.config.js +3 -3
- package/.raclette/backend/yarn.lock +4 -11
- package/.raclette/frontend/raclette.config.js +6 -4
- package/.raclette/frontend/yarn.lock +451 -489
- package/.raclette/virtual/backend/raclette.config.js +3 -3
- package/.raclette/virtual/backend/yarn.lock +4 -11
- package/.raclette/virtual/frontend/raclette.config.js +6 -4
- package/.raclette/virtual/frontend/yarn.lock +451 -489
- package/CHANGELOG.md +19 -3
- package/i18n/de-DE.json +15 -0
- package/i18n/en-EU.json +15 -0
- package/i18n/sk-SK.json +15 -0
- package/package.json +5 -4
- package/plugins/pacifico__compositions/frontend/widgets/CompositionListWidget.vue +39 -21
- package/plugins/pacifico__interactionLinks/frontend/widgets/InteractionLinkListWidget.vue +39 -21
- package/plugins/pacifico__plugins/frontend/index.ts +3 -3
- package/plugins/pacifico__plugins/frontend/widgets/PluginListWidget.vue +11 -12
- package/plugins/pacifico__tags/frontend/widgets/TagListWidget.vue +39 -21
- package/plugins/pacifico__users/frontend/widgets/UserListWidget.vue +79 -57
- package/services/frontend/src/app/components/dynamicForm/DynamicForm.vue +139 -51
- package/services/frontend/src/app/components/dynamicForm/DynamicInput.vue +95 -5
- package/services/frontend/src/app/components/dynamicForm/ObjectListInput.vue +78 -41
- package/services/frontend/src/app/components/dynamicForm/TextDivider.vue +46 -6
- package/services/frontend/src/app/components/dynamicForm/typedInputs/ListInput.vue +118 -27
- package/services/frontend/src/app/components/dynamicForm/typedInputs/RecordInput.vue +131 -21
- package/services/frontend/src/app/components/dynamicForm/typedInputs/TagsInput.vue +1 -0
- package/services/frontend/src/app/components/dynamicForm/typedInputs/TriggerInput.vue +4 -4
- package/services/frontend/src/app/composables/useWorkbenchTableActions.ts +29 -0
- package/services/frontend/src/orchestrator/assets/styles/themes/light.ts +4 -3
|
@@ -1,52 +1,70 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
2
|
+
<div class="tw:p-4">
|
|
3
|
+
<BaseDataTable
|
|
4
|
+
:items="parsedUsers"
|
|
5
|
+
:exportable-items="exportableUsers"
|
|
6
|
+
:loading="usersLoading || tagsLoading"
|
|
7
|
+
:headers="headers"
|
|
8
|
+
:row-click-handler="handleRowClick"
|
|
9
|
+
:data-name="$t('workbench.userList.dataName')"
|
|
10
|
+
:show-filters="true"
|
|
11
|
+
:items-deleted="showDeleted"
|
|
12
|
+
>
|
|
13
|
+
<template #toolbar-end>
|
|
14
|
+
<v-btn
|
|
15
|
+
prepend-icon="mdi-plus"
|
|
16
|
+
variant="flat"
|
|
17
|
+
color="success"
|
|
18
|
+
:text="
|
|
19
|
+
$t('core.baseDataTable.createDataButton', {
|
|
20
|
+
dataName: $t('workbench.userList.dataName'),
|
|
21
|
+
})
|
|
22
|
+
"
|
|
23
|
+
@click="goToCreate('userCreateInteractionLink')"
|
|
24
|
+
/>
|
|
25
|
+
</template>
|
|
26
|
+
<template #toolbar-actions-menu>
|
|
27
|
+
<v-list-item
|
|
28
|
+
:title="showDeleted ? $t('core.hideDeleted') : $t('core.showDeleted')"
|
|
29
|
+
prepend-icon="mdi-delete-outline"
|
|
30
|
+
>
|
|
31
|
+
<template #append>
|
|
32
|
+
<v-switch
|
|
33
|
+
v-model="showDeleted"
|
|
34
|
+
color="error"
|
|
35
|
+
density="compact"
|
|
36
|
+
hide-details
|
|
37
|
+
inset
|
|
38
|
+
/>
|
|
39
|
+
</template>
|
|
40
|
+
</v-list-item>
|
|
41
|
+
</template>
|
|
42
|
+
<template #prepend-row-actions="{ item }">
|
|
43
|
+
<v-icon
|
|
44
|
+
v-if="showDeleted"
|
|
45
|
+
color="green"
|
|
46
|
+
class="mr-2"
|
|
47
|
+
@click.stop.prevent="restore(item._id)"
|
|
48
|
+
:title="
|
|
49
|
+
$t('workbench.baseDataTable.restoreDataTitle', {
|
|
50
|
+
dataName: item.title,
|
|
51
|
+
})
|
|
52
|
+
"
|
|
53
|
+
icon="mdi-delete-restore"
|
|
54
|
+
/>
|
|
55
|
+
</template>
|
|
56
|
+
<template #row-actions="{ item }">
|
|
57
|
+
<v-btn
|
|
58
|
+
v-if="item._id !== $user?._id"
|
|
59
|
+
icon="mdi-delete"
|
|
60
|
+
size="small"
|
|
61
|
+
variant="text"
|
|
62
|
+
color="error"
|
|
63
|
+
@click.stop.prevent="deleteUser(item)"
|
|
64
|
+
/>
|
|
65
|
+
</template>
|
|
66
|
+
</BaseDataTable>
|
|
67
|
+
</div>
|
|
50
68
|
</template>
|
|
51
69
|
|
|
52
70
|
<script setup lang="ts">
|
|
@@ -56,6 +74,7 @@ import type { User } from "@raclettejs/core"
|
|
|
56
74
|
import { formatDistance } from "date-fns"
|
|
57
75
|
import { useI18n } from "vue-i18n"
|
|
58
76
|
import BaseDataTable from "@raclettejs/core/orchestrator/components/dataTable/BaseDataTable.vue"
|
|
77
|
+
import { useWorkbenchTableActions } from "@app/composables/useWorkbenchTableActions"
|
|
59
78
|
const showDeleted = ref(false)
|
|
60
79
|
|
|
61
80
|
const props = defineProps<{
|
|
@@ -63,6 +82,7 @@ const props = defineProps<{
|
|
|
63
82
|
}>()
|
|
64
83
|
|
|
65
84
|
const { t } = useI18n()
|
|
85
|
+
const { goToCreate, goToEditById } = useWorkbenchTableActions()
|
|
66
86
|
|
|
67
87
|
const headers = computed<{ title: string; key: keyof User }[]>(() => [
|
|
68
88
|
{
|
|
@@ -108,15 +128,13 @@ const userTableRows = (relativeUpdatedAt: boolean) => {
|
|
|
108
128
|
return []
|
|
109
129
|
}
|
|
110
130
|
|
|
111
|
-
return Object.values(users.value as { [key: string]: User }).map(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}),
|
|
119
|
-
)
|
|
131
|
+
return Object.values(users.value as { [key: string]: User }).map((user) => ({
|
|
132
|
+
...user,
|
|
133
|
+
tags: user.tags.map((tag) => tags.value?.[tag]),
|
|
134
|
+
...(relativeUpdatedAt
|
|
135
|
+
? { updatedAt: formatDistance(new Date(user.updatedAt), new Date()) }
|
|
136
|
+
: {}),
|
|
137
|
+
}))
|
|
120
138
|
}
|
|
121
139
|
|
|
122
140
|
const parsedUsers = computed(() => userTableRows(true))
|
|
@@ -132,6 +150,10 @@ const deleteUser = async (user: User) => {
|
|
|
132
150
|
const restore = async (_id: string) => {
|
|
133
151
|
executeRestore({ _id })
|
|
134
152
|
}
|
|
153
|
+
|
|
154
|
+
const handleRowClick = (item: User) =>
|
|
155
|
+
goToEditById("userEditInteractionLink", item._id)
|
|
156
|
+
|
|
135
157
|
$socket.on("userCreated", () => execute({ isDeleted: showDeleted.value }))
|
|
136
158
|
watch(
|
|
137
159
|
showDeleted,
|
|
@@ -1,69 +1,97 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<h1 v-if="title" class="tw:text-2xl tw:font-bold">
|
|
12
|
-
{{ title }}
|
|
13
|
-
</h1>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<v-form @submit.prevent="onFormSubmit">
|
|
17
|
-
<!-- body -->
|
|
18
|
-
<div class="tw:grid tw:gap-6">
|
|
19
|
-
<template v-for="(value, key) in props.data" :key="key">
|
|
20
|
-
<TextDivider v-if="'divider' in value" :label="value.divider" />
|
|
21
|
-
<DynamicInput
|
|
22
|
-
v-else
|
|
23
|
-
v-model="modelProxy[value.field]"
|
|
24
|
-
:input-type="value.inputType"
|
|
25
|
-
:value="value"
|
|
26
|
-
:disabled="!!disabled"
|
|
27
|
-
:error-message="getValidationError(value)"
|
|
28
|
-
@validate="validateField(value)"
|
|
29
|
-
/>
|
|
30
|
-
</template>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<!-- button area -->
|
|
34
|
-
<slot name="button-area-override">
|
|
35
|
-
<v-btn type="submit" class="tw:hidden!" />
|
|
36
|
-
<div
|
|
37
|
-
class="tw:mt-8 tw:flex tw:gap-4 tw:justify-end"
|
|
38
|
-
v-if="$slots?.['button-area']"
|
|
2
|
+
<div :class="wrapperClasses">
|
|
3
|
+
<v-form
|
|
4
|
+
class="tw:flex tw:min-h-0 tw:w-full tw:flex-col"
|
|
5
|
+
@submit.prevent="onFormSubmit"
|
|
6
|
+
>
|
|
7
|
+
<div class="tw:flex tw:min-h-0 tw:w-full tw:flex-col">
|
|
8
|
+
<header
|
|
9
|
+
v-if="title || routeBackInteractionLinkId"
|
|
10
|
+
class="tw:flex tw:items-center tw:justify-between tw:gap-3 tw:pt-3"
|
|
39
11
|
>
|
|
40
|
-
<
|
|
41
|
-
|
|
12
|
+
<div class="tw:flex tw:min-w-0 tw:items-center tw:gap-2">
|
|
13
|
+
<v-btn
|
|
14
|
+
v-if="routeBackInteractionLinkId"
|
|
15
|
+
@click="navigateBack"
|
|
16
|
+
:density="vuetifyDensity"
|
|
17
|
+
icon="mdi-chevron-left"
|
|
18
|
+
variant="text"
|
|
19
|
+
aria-label="Go back"
|
|
20
|
+
/>
|
|
21
|
+
<h1
|
|
22
|
+
v-if="title"
|
|
23
|
+
class="tw:min-w-0 tw:truncate tw:font-semibold tw:tracking-tight tw:text-[color:rgb(var(--v-theme-on-surface))]"
|
|
24
|
+
:class="titleClasses"
|
|
25
|
+
>
|
|
26
|
+
{{ title }}
|
|
27
|
+
</h1>
|
|
28
|
+
</div>
|
|
29
|
+
</header>
|
|
30
|
+
|
|
31
|
+
<!-- body -->
|
|
32
|
+
<div class="tw:grid" :class="bodyClasses">
|
|
33
|
+
<template v-for="(value, key) in props.data" :key="key">
|
|
34
|
+
<TextDivider
|
|
35
|
+
v-if="'divider' in value"
|
|
36
|
+
:label="value.divider"
|
|
37
|
+
:density="density"
|
|
38
|
+
/>
|
|
39
|
+
<DynamicInput
|
|
40
|
+
v-else
|
|
41
|
+
v-model="modelProxy[value.field]"
|
|
42
|
+
:input-type="value.inputType"
|
|
43
|
+
:value="value"
|
|
44
|
+
:disabled="!!disabled"
|
|
45
|
+
:error-message="getValidationError(value)"
|
|
46
|
+
:density="density"
|
|
47
|
+
@validate="validateField(value)"
|
|
48
|
+
/>
|
|
49
|
+
</template>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- button area -->
|
|
53
|
+
<slot name="button-area-override">
|
|
54
|
+
<v-btn type="submit" class="tw:hidden!" />
|
|
55
|
+
<footer
|
|
56
|
+
v-if="$slots?.['button-area']"
|
|
57
|
+
class="tw:flex tw:flex-wrap tw:items-center tw:justify-end"
|
|
58
|
+
:class="actionClasses"
|
|
59
|
+
>
|
|
60
|
+
<slot name="button-area" v-bind="{ isValid, validateAllFields }" />
|
|
61
|
+
<!-- <v-btn color="primary" variant="outlined"> Validate Form </v-btn>
|
|
42
62
|
<v-btn color="secondary" variant="outlined"> Reset Form </v-btn>
|
|
43
63
|
<v-btn color="info" variant="outlined"> Show Form Data </v-btn> -->
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
</footer>
|
|
65
|
+
</slot>
|
|
66
|
+
</div>
|
|
46
67
|
</v-form>
|
|
47
68
|
</div>
|
|
48
69
|
</template>
|
|
49
70
|
|
|
50
71
|
<script setup lang="ts" generic="T">
|
|
51
|
-
import { computed, ref, watch, watchEffect } from "vue"
|
|
72
|
+
import { computed, ref, watch, watchEffect, withDefaults } from "vue"
|
|
52
73
|
import DynamicInput from "./DynamicInput.vue"
|
|
53
74
|
import TextDivider from "./TextDivider.vue"
|
|
54
75
|
import { DynamicFormItem, DynamicFormField } from "./DynamicFormTypes"
|
|
55
76
|
import { useI18n } from "vue-i18n"
|
|
56
77
|
import { useRouteState } from "@raclettejs/core/orchestrator/composables"
|
|
57
78
|
|
|
58
|
-
const props =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
79
|
+
const props = withDefaults(
|
|
80
|
+
defineProps<{
|
|
81
|
+
title?: string
|
|
82
|
+
data: DynamicFormItem<T>[]
|
|
83
|
+
modelValue: T
|
|
84
|
+
disabled?: Boolean
|
|
85
|
+
validateOnChange?: boolean
|
|
86
|
+
/** When false, constrains width (previous default). Default true fills the layout. */
|
|
87
|
+
fluid?: boolean
|
|
88
|
+
routeBackInteractionLinkId?: string
|
|
89
|
+
density?: "compact" | "comfortable" | "spacious"
|
|
90
|
+
}>(),
|
|
91
|
+
{
|
|
92
|
+
fluid: true,
|
|
93
|
+
},
|
|
94
|
+
)
|
|
67
95
|
|
|
68
96
|
const emit = defineEmits<{
|
|
69
97
|
(e: "update:modelValue", value: T): void
|
|
@@ -75,6 +103,66 @@ const { t } = useI18n()
|
|
|
75
103
|
const { triggerInteractionLinkById } = useRouteState()
|
|
76
104
|
|
|
77
105
|
const validationErrors = ref<Record<string, string>>({})
|
|
106
|
+
const density = computed(() => props.density ?? "comfortable")
|
|
107
|
+
|
|
108
|
+
const vuetifyDensity = computed(() => {
|
|
109
|
+
if (density.value === "spacious") {
|
|
110
|
+
return "default"
|
|
111
|
+
}
|
|
112
|
+
return density.value
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
const horizontalInsetClasses = computed(() => {
|
|
116
|
+
if (density.value === "compact") {
|
|
117
|
+
return "tw:px-3 sm:tw:px-4"
|
|
118
|
+
}
|
|
119
|
+
if (density.value === "spacious") {
|
|
120
|
+
return "tw:px-5 tw:mdpx-6"
|
|
121
|
+
}
|
|
122
|
+
return "tw:px-4 tw:mdpx-5"
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const wrapperClasses = computed(() => [
|
|
126
|
+
"tw:box-border tw:flex tw:min-h-0 tw:w-full tw:flex-col",
|
|
127
|
+
horizontalInsetClasses.value,
|
|
128
|
+
!props.fluid ? "tw:mx-auto tw:max-w-6xl" : "",
|
|
129
|
+
])
|
|
130
|
+
|
|
131
|
+
const titleClasses = computed(() => {
|
|
132
|
+
if (density.value === "compact") {
|
|
133
|
+
return "tw:text-lg"
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (density.value === "spacious") {
|
|
137
|
+
return "tw:text-2xl"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return "tw:text-xl"
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const bodyClasses = computed(() => {
|
|
144
|
+
if (density.value === "compact") {
|
|
145
|
+
return "tw:gap-0"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (density.value === "spacious") {
|
|
149
|
+
return "tw:gap-4"
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return "tw:gap-2"
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
const actionClasses = computed(() => {
|
|
156
|
+
if (density.value === "compact") {
|
|
157
|
+
return "tw:gap-2 tw:py-3"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (density.value === "spacious") {
|
|
161
|
+
return "tw:gap-4 tw:py-5"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return "tw:gap-3 tw:py-4"
|
|
165
|
+
})
|
|
78
166
|
|
|
79
167
|
const isValid = computed(() => Object.keys(validationErrors.value).length === 0)
|
|
80
168
|
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
<div
|
|
3
|
+
class="tw:grid tw:grid-cols-1 tw:rounded-md tw:p-2 tw:grid-cols-12"
|
|
4
|
+
:class="rowGapClasses"
|
|
5
|
+
>
|
|
6
|
+
<label
|
|
7
|
+
class="tw:col-span-5"
|
|
8
|
+
:class="labelSpacingClasses"
|
|
9
|
+
:for="inputId"
|
|
10
|
+
v-if="hasTitleOrDescription"
|
|
11
|
+
>
|
|
12
|
+
<div
|
|
13
|
+
class="tw:font-semibold tw:leading-5 tw:text-[color:rgb(var(--v-theme-on-surface))]"
|
|
14
|
+
:class="labelTextClasses"
|
|
15
|
+
>
|
|
5
16
|
{{ value.title }}
|
|
6
|
-
<span
|
|
17
|
+
<span
|
|
18
|
+
v-if="value.validation?.required"
|
|
19
|
+
class="tw:ml-0.5 tw:text-[color:rgb(var(--v-theme-error))]"
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
>
|
|
22
|
+
*
|
|
23
|
+
</span>
|
|
7
24
|
</div>
|
|
8
|
-
<div
|
|
25
|
+
<div
|
|
26
|
+
v-if="value.description"
|
|
27
|
+
:id="descriptionHtmlId ?? undefined"
|
|
28
|
+
class="tw:mt-1 tw:max-w-prose tw:leading-snug tw:text-[color:rgb(var(--v-theme-on-surface))]"
|
|
29
|
+
:class="descriptionTextClasses"
|
|
30
|
+
>
|
|
9
31
|
{{ value.description }}
|
|
10
32
|
</div>
|
|
11
33
|
</label>
|
|
@@ -66,6 +88,7 @@
|
|
|
66
88
|
<RecordInput
|
|
67
89
|
v-model="recordModel"
|
|
68
90
|
:input-id="inputId"
|
|
91
|
+
v-bind="additionalInputBindings"
|
|
69
92
|
@blur="$emit('validate')"
|
|
70
93
|
/>
|
|
71
94
|
</template>
|
|
@@ -87,6 +110,7 @@
|
|
|
87
110
|
v-model="objectArrayModel"
|
|
88
111
|
:fields="value.fields"
|
|
89
112
|
:disabled="!!disabled"
|
|
113
|
+
:density="density"
|
|
90
114
|
@validate="$emit('validate')"
|
|
91
115
|
/>
|
|
92
116
|
</template>
|
|
@@ -239,6 +263,7 @@ const props = defineProps<{
|
|
|
239
263
|
disabled?: boolean
|
|
240
264
|
errorMessage?: string
|
|
241
265
|
hideDetails?: boolean
|
|
266
|
+
density?: "compact" | "comfortable" | "spacious"
|
|
242
267
|
}>()
|
|
243
268
|
|
|
244
269
|
defineEmits<{
|
|
@@ -262,6 +287,69 @@ const id = useId()
|
|
|
262
287
|
const attrs = useAttrs()
|
|
263
288
|
|
|
264
289
|
const inputId = computed(() => `dynamic-input-${id}`)
|
|
290
|
+
const descriptionHtmlId = computed(() =>
|
|
291
|
+
props.value.description ? `${inputId.value}-description` : undefined,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
const density = computed(() => props.density ?? "comfortable")
|
|
295
|
+
|
|
296
|
+
const vuetifyDensity = computed(() => {
|
|
297
|
+
if (density.value === "spacious") {
|
|
298
|
+
return "default"
|
|
299
|
+
}
|
|
300
|
+
return density.value
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
const rowGapClasses = computed(() => {
|
|
304
|
+
if (density.value === "compact") {
|
|
305
|
+
return "tw:gap-3 tw:md:gap-4"
|
|
306
|
+
}
|
|
307
|
+
if (density.value === "spacious") {
|
|
308
|
+
return "tw:gap-6"
|
|
309
|
+
}
|
|
310
|
+
return "tw:gap-4 tw:md:gap-5"
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
const labelSpacingClasses = computed(() => {
|
|
314
|
+
if (density.value === "spacious") {
|
|
315
|
+
return "tw:pt-1"
|
|
316
|
+
}
|
|
317
|
+
return ""
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
const labelTextClasses = computed(() => {
|
|
321
|
+
if (density.value === "compact") {
|
|
322
|
+
return "tw:text-sm"
|
|
323
|
+
}
|
|
324
|
+
if (density.value === "spacious") {
|
|
325
|
+
return "tw:text-base"
|
|
326
|
+
}
|
|
327
|
+
return "tw:text-sm"
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
const descriptionTextClasses = computed(() => {
|
|
331
|
+
if (density.value === "compact") {
|
|
332
|
+
return "tw:text-xs"
|
|
333
|
+
}
|
|
334
|
+
return "tw:text-sm"
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
const accessibilityFieldBindings = computed(() => {
|
|
338
|
+
const o: Record<string, unknown> = {
|
|
339
|
+
color: "primary",
|
|
340
|
+
}
|
|
341
|
+
const descId = descriptionHtmlId.value
|
|
342
|
+
if (descId) {
|
|
343
|
+
o["aria-describedby"] = descId
|
|
344
|
+
}
|
|
345
|
+
if (props.value.validation?.required) {
|
|
346
|
+
o["aria-required"] = true
|
|
347
|
+
}
|
|
348
|
+
if (props.errorMessage) {
|
|
349
|
+
o["aria-invalid"] = true
|
|
350
|
+
}
|
|
351
|
+
return o
|
|
352
|
+
})
|
|
265
353
|
|
|
266
354
|
const createTypedModel = <T extends DynamicModelType>(
|
|
267
355
|
types: DynamicInputType[],
|
|
@@ -333,8 +421,10 @@ const additionalInputBindings = computed(() => {
|
|
|
333
421
|
} = props.value
|
|
334
422
|
|
|
335
423
|
const result: Record<string, unknown> = {
|
|
424
|
+
...accessibilityFieldBindings.value,
|
|
336
425
|
prefix,
|
|
337
426
|
suffix,
|
|
427
|
+
density: vuetifyDensity.value,
|
|
338
428
|
prependIcon: prependIcon ? `mdi-${prependIcon}` : undefined,
|
|
339
429
|
prependInnerIcon: prependInnerIcon ? `mdi-${prependInnerIcon}` : undefined,
|
|
340
430
|
appendIcon: appendIcon ? `mdi-${appendIcon}` : undefined,
|