-
-
Notifications
You must be signed in to change notification settings - Fork 622
Expand file tree
/
Copy pathField.vue
More file actions
126 lines (116 loc) · 4.25 KB
/
Field.vue
File metadata and controls
126 lines (116 loc) · 4.25 KB
1
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
<script setup>
import { cva } from 'cva';
import { computed } from 'vue';
import Description from './Description.vue';
import Label from './Label.vue';
import ErrorMessage from './ErrorMessage.vue';
import markdown from '@/util/markdown.js';
import { twMerge } from 'tailwind-merge';
defineOptions({
inheritAttrs: false,
});
const props = defineProps({
/** When `true`, the field is styled as a configuration field with a two-column grid layout. */
inline: { type: Boolean, default: false },
/** Badge text to display next to the label. */
badge: { type: String, default: '' },
disabled: { type: Boolean, default: false },
/** Error message to display below the field. */
error: { type: String },
/** Object or array of error messages to display below the field. */
errors: { type: Object },
/** When `true`, forces the field to use full width even when `asConfig` is enabled. */
fullWidthSetting: { type: Boolean, default: false },
id: { type: String },
/** Instructions text to display above or below the label. Supports Markdown. */
instructions: { type: String, default: '' },
/** When `true`, displays instructions below the control instead of below the label. */
instructionsBelow: { type: Boolean, default: false },
/** Label text for the field. */
label: { type: String },
readOnly: { type: Boolean, default: false },
required: { type: Boolean, default: false },
});
const labelProps = computed(() => ({
badge: props.badge,
for: props.id,
required: props.required,
text: props.label,
}));
const rootClasses = computed(() =>
twMerge(cva({
base: [
'min-w-0',
],
variants: {
disabled: {
true: 'opacity-50',
},
inline: {
true: 'grid md:grid-cols-2 items-start px-4.5 py-4 gap-y-3 md:gap-y-0 md:gap-x-5!',
},
fullWidthSetting: {
true: 'grid-cols-1',
},
},
})({
...props,
})),
);
const descriptionClasses = computed(() =>
twMerge(cva({
base: ['mb-2 -mt-0.5'],
variants: {
inline: {
true: 'mb-0',
},
fullWidthSetting: {
true: 'mb-3',
},
},
})({
...props,
})),
);
const instructions = computed(() => props.instructions ? markdown(__(props.instructions), { openLinksInNewTabs: true }) : null);
const errors = computed(() => {
if (props.error) {
return [props.error];
}
return props.errors;
});
const hasErrors = computed(() => {
if (!errors.value) return false;
return Array.isArray(errors.value) ? errors.value.length > 0 : Object.keys(errors.value).length > 0;
});
</script>
<template>
<div :class="[rootClasses, $attrs.class]" data-ui-input-group :data-ui-field-has-errors="hasErrors ? '' : null">
<div v-if="label || (instructions && !instructionsBelow) || $slots.label || $slots.actions">
<div
v-if="$slots.actions"
:class="[
'flex items-center gap-x-1 mb-0',
props.label || $slots.label ? 'justify-between' : 'justify-end',
]"
data-ui-field-header
>
<slot name="label">
<Label v-if="label" v-bind="labelProps" class="flex-1" />
</slot>
<slot name="actions" />
</div>
<div v-if="label || (instructions && !instructionsBelow) || ($slots.label && !$slots.actions)" data-ui-field-text :class="inline ? 'mb-0' : 'mb-1.5'">
<slot v-if="!$slots.actions" name="label">
<Label v-if="label" v-bind="labelProps" class="flex-1" />
</slot>
<Description :text="instructions" v-if="instructions && !instructionsBelow" :class="descriptionClasses" />
</div>
</div>
<slot />
<div v-if="(instructions && instructionsBelow) || hasErrors">
<Description :text="instructions" v-if="instructions && instructionsBelow" class="mt-2" />
<ErrorMessage v-if="errors" v-for="(error, i) in errors" :key="i" :text="error" class="mt-2" />
</div>
</div>
</template>