1<template>
2 <div class="relative gap-2 flex items-center w-full">
3 <component
4 :is="isPhone ? PhoneControl : FormControl"
5 ref="control"
6 class="flex-1"
7 :class="isPhone ? undefined : '[&_p]:text-p-xs'"
8 :type="isPhone ? undefined : type"
9 :placeholder="placeholder"
10 v-model="model"
11 @keydown.enter.prevent="blurInput"
12 >
13 <!-- <template #suffix>
14
15 </template> -->
16 </component>
17 <div class="flex items-center gap-0">
18 <Tooltip
19 v-if="isPrimary"
20 :text="canTogglePrimary ? __('Remove primary') : __('Primary')"
21 >
22 <Button
23 variant="ghost"
24 :aria-label="__('Remove primary')"
25 @click="$emit('setPrimary')"
26 >
27 <template #icon>
28 <LucideStar class="size-4 fill-ink-amber-5 stroke-ink-amber-5" />
29 </template>
30 </Button>
31 </Tooltip>
32 <Tooltip v-else :text="__('Set as primary')">
33 <Button
34 variant="ghost"
35 type="button"
36 :aria-label="__('Set as primary')"
37 @mousedown.prevent
38 @click="$emit('setPrimary')"
39 >
40 <template #icon>
41 <LucideStar class="size-4" />
42 </template>
43 </Button>
44 </Tooltip>
45 <Tooltip :text="__('Remove')">
46 <Button
47 :disabled="!canRemove"
48 variant="ghost"
49 type="button"
50 :aria-label="__('Remove')"
51 @mousedown.prevent
52 @click="$emit('remove')"
53 >
54 <template #icon>
55 <LucideX class="size-3.5" />
56 </template>
57 </Button>
58 </Tooltip>
59 </div>
60 </div>
61</template>
62
63<script setup lang="ts">
64import { __ } from "@/translation";
65import { Button, FormControl, Tooltip } from "frappe-ui";
66import { computed, nextTick, onMounted, ref } from "vue";
67import LucideStar from "~icons/lucide/star";
68import LucideX from "~icons/lucide/x";
69import PhoneControl from "../frappe-ui/PhoneControl/PhoneControl.vue";
70
71const props = withDefaults(
72 defineProps<{
73 isPrimary: boolean;
74 canRemove: boolean;
75 canTogglePrimary?: boolean;
76 type?: "email" | "tel" | "text";
77 placeholder?: string;
78 autofocus?: boolean;
79 }>(),
80 {
81 canTogglePrimary: false,
82 type: "text",
83 placeholder: "",
84 autofocus: false,
85 }
86);
87
88const model = defineModel<string>({ required: true });
89
90defineEmits<{
91 setPrimary: [];
92 remove: [];
93}>();
94
95const control = ref<any>(null);
96const isPhone = computed(() => props.type === "tel");
97
98function getInputEl(): HTMLInputElement | null {
99 return control.value?.$el?.querySelector?.("input") ?? null;
100}
101
102function blurInput() {
103 getInputEl()?.blur();
104}
105
106onMounted(() => {
107 if (props.autofocus) {
108 nextTick(() => getInputEl()?.focus());
109 }
110});
111</script>
112