|
| 1 | +<script setup lang="ts"> |
| 2 | +import { BCol, BFormInput, BFormTextarea, BRow } from "bootstrap-vue"; |
| 3 | +import { computed } from "vue"; |
| 4 | +
|
| 5 | +import type { FormParameterTypeMap } from "../parameterTypes"; |
| 6 | +
|
| 7 | +interface Props { |
| 8 | + value?: FormParameterTypeMap["text"]; |
| 9 | + id?: string; |
| 10 | + type?: "text" | "password"; |
| 11 | + /** <textarea> instead of <input> element */ |
| 12 | + area?: boolean; |
| 13 | + /** Allow multiple entries to be created */ |
| 14 | + multiple?: boolean; |
| 15 | + readonly?: boolean; |
| 16 | + placeholder?: string; |
| 17 | + optional?: boolean; |
| 18 | + showState?: boolean; |
| 19 | + color?: string; |
| 20 | + /** Refers to an optional custom css class name */ |
| 21 | + cls?: string; |
| 22 | + /** Display list of suggestions in autocomplete dialog */ |
| 23 | + datalist?: { label: string; value: string }[]; |
| 24 | +} |
| 25 | +
|
| 26 | +const props = withDefaults(defineProps<Props>(), { |
| 27 | + value: "", |
| 28 | + id: "", |
| 29 | + type: "text", |
| 30 | + area: false, |
| 31 | + multiple: false, |
| 32 | + readonly: false, |
| 33 | + placeholder: "", |
| 34 | + optional: true, |
| 35 | + showState: false, |
| 36 | + color: undefined, |
| 37 | + cls: undefined, |
| 38 | + datalist: undefined, |
| 39 | +}); |
| 40 | +const emit = defineEmits(["input"]); |
| 41 | +
|
| 42 | +const acceptedTypes = computed(() => (["text", "password"].includes(props.type) ? props.type : "text")); |
| 43 | +
|
| 44 | +const currentValue = computed({ |
| 45 | + get() { |
| 46 | + const v = props.value ?? ""; |
| 47 | + if (Array.isArray(v)) { |
| 48 | + if (v.length === 0) { |
| 49 | + return ""; |
| 50 | + } |
| 51 | + return props.multiple ? v.reduce((str_value, v) => str_value + String(v) + "\n", "") : String(v[0]); |
| 52 | + } |
| 53 | + return String(v); |
| 54 | + }, |
| 55 | + set(newVal: string) { |
| 56 | + emit("input", newVal); |
| 57 | + }, |
| 58 | +}); |
| 59 | +
|
| 60 | +const inputArea = computed(() => props.area || props.multiple); |
| 61 | +
|
| 62 | +const style = computed(() => (props.color ? { color: props.color, "border-color": props.color } : null)); |
| 63 | +</script> |
1 | 64 | <template>
|
2 |
| - <b-row align-v="center"> |
3 |
| - <b-col> |
4 |
| - <b-form-textarea |
| 65 | + <BRow align-v="center"> |
| 66 | + <BCol> |
| 67 | + <BFormTextarea |
5 | 68 | v-if="inputArea"
|
6 | 69 | :id="id"
|
7 | 70 | v-model="currentValue"
|
8 | 71 | :class="['ui-text-area', cls]"
|
9 | 72 | :readonly="readonly"
|
10 | 73 | :placeholder="placeholder"
|
11 | 74 | :style="style" />
|
12 |
| - <b-form-input |
| 75 | + <BFormInput |
13 | 76 | v-else
|
14 | 77 | :id="id"
|
15 | 78 | v-model="currentValue"
|
|
23 | 86 | <datalist v-if="datalist && !inputArea" :id="`${id}-datalist`">
|
24 | 87 | <option v-for="data in datalist" :key="data.value" :label="data.label" :value="data.value" />
|
25 | 88 | </datalist>
|
26 |
| - </b-col> |
27 |
| - </b-row> |
| 89 | + </BCol> |
| 90 | + </BRow> |
28 | 91 | </template>
|
29 | 92 |
|
30 |
| -<script> |
31 |
| -export default { |
32 |
| - props: { |
33 |
| - value: { |
34 |
| - // String; Array for multiple |
35 |
| - default: "", |
36 |
| - }, |
37 |
| - id: { |
38 |
| - type: String, |
39 |
| - default: "", |
40 |
| - }, |
41 |
| - type: { |
42 |
| - type: String, |
43 |
| - default: "text", |
44 |
| - }, |
45 |
| - area: { |
46 |
| - // <textarea> instead of <input> element |
47 |
| - type: Boolean, |
48 |
| - default: false, |
49 |
| - }, |
50 |
| - multiple: { |
51 |
| - // Allow multiple entries to be created |
52 |
| - type: Boolean, |
53 |
| - default: false, |
54 |
| - }, |
55 |
| - readonly: { |
56 |
| - type: Boolean, |
57 |
| - default: false, |
58 |
| - }, |
59 |
| - placeholder: { |
60 |
| - type: String, |
61 |
| - default: "", |
62 |
| - }, |
63 |
| - optional: { |
64 |
| - type: Boolean, |
65 |
| - default: true, |
66 |
| - }, |
67 |
| - showState: { |
68 |
| - type: Boolean, |
69 |
| - default: false, |
70 |
| - }, |
71 |
| - color: { |
72 |
| - type: String, |
73 |
| - default: null, |
74 |
| - }, |
75 |
| - cls: { |
76 |
| - // Refers to an optional custom css class name |
77 |
| - type: String, |
78 |
| - default: null, |
79 |
| - }, |
80 |
| - datalist: { |
81 |
| - // Display list of suggestions in autocomplete dialog |
82 |
| - type: Array, |
83 |
| - default: null, |
84 |
| - }, |
85 |
| - }, |
86 |
| - computed: { |
87 |
| - acceptedTypes() { |
88 |
| - return ["text", "password"].includes(this.type) ? this.type : "text"; |
89 |
| - }, |
90 |
| - currentValue: { |
91 |
| - get() { |
92 |
| - const v = this.value ?? ""; |
93 |
| - if (Array.isArray(v)) { |
94 |
| - if (v.length === 0) { |
95 |
| - return ""; |
96 |
| - } |
97 |
| - return this.multiple |
98 |
| - ? this.value.reduce((str_value, v) => str_value + String(v) + "\n", "") |
99 |
| - : String(this.value[0]); |
100 |
| - } |
101 |
| - return String(v); |
102 |
| - }, |
103 |
| - set(newVal, oldVal) { |
104 |
| - if (newVal !== oldVal) { |
105 |
| - this.$emit("input", newVal); |
106 |
| - } |
107 |
| - }, |
108 |
| - }, |
109 |
| - inputArea() { |
110 |
| - return this.area || this.multiple; |
111 |
| - }, |
112 |
| - style() { |
113 |
| - return this.color |
114 |
| - ? { |
115 |
| - color: this.color, |
116 |
| - "border-color": this.color, |
117 |
| - } |
118 |
| - : null; |
119 |
| - }, |
120 |
| - }, |
121 |
| -}; |
122 |
| -</script> |
123 | 93 | <style scoped>
|
124 | 94 | .ui-input-linked {
|
125 | 95 | border-left-width: 0.5rem;
|
|
0 commit comments