122 lines
3.1 KiB
Vue
122 lines
3.1 KiB
Vue
<template>
|
|
<button
|
|
ref="passwordVisibility"
|
|
@click.prevent="toggleVisibility()"
|
|
@keydown="keydown"
|
|
:class="`btn btn-primary rounded-0 rounded-end password-visibility password-visibility-${id} h-100 border-0 p-0 overflow-hidden`"
|
|
:aria-pressed="visible"
|
|
>
|
|
<span
|
|
:class="{
|
|
'text-bg-primary reveal d-flex justify-content-center align-items-center h-100': true,
|
|
'd-none': visible
|
|
}"
|
|
type="button"
|
|
:title="trans.methods.__('vue.PasswordVisibility.hide')"
|
|
data-bs-toggle="tooltip"
|
|
>
|
|
<FontAwesomeIcon
|
|
icon="fas fa-eye-slash"
|
|
:aria-hidden="true"
|
|
/>
|
|
</span>
|
|
<span
|
|
ref="passwordVisibilitySpan"
|
|
:class="{
|
|
'text-bg-primary reveal d-flex justify-content-center align-items-center h-100': true,
|
|
'd-none': !visible
|
|
}"
|
|
type="button"
|
|
:title="trans.methods.__('vue.PasswordVisibility.show')"
|
|
data-bs-toggle="tooltip"
|
|
>
|
|
<FontAwesomeIcon
|
|
icon="fas fa-eye"
|
|
:aria-hidden="true"
|
|
/>
|
|
</span>
|
|
</button>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
import { onMounted, ref, useAttrs } from "vue";
|
|
import { Tooltips } from "../../modules/bsTooltips";
|
|
import trans from "../../modules/trans";
|
|
|
|
defineOptions({
|
|
name: "PasswordVisibility"
|
|
});
|
|
|
|
// * ATTRIBUTES
|
|
const attrs = useAttrs();
|
|
|
|
// * REFS
|
|
const passwordVisibility = ref<HTMLButtonElement|null>(null);
|
|
|
|
// * DATA
|
|
const id = ref<string>("");
|
|
const input = ref<HTMLInputElement>(document.createElement("input"));
|
|
const visible = ref<boolean>(true);
|
|
const tooltips = ref<Tooltips | null>(null);
|
|
|
|
// * LIFECYCLE
|
|
onMounted(() => {
|
|
const json = String(attrs.json ?? "{}"),
|
|
data = JSON.parse(json);
|
|
id.value = data.id;
|
|
input.value = document.getElementById(id.value) as HTMLInputElement;
|
|
if (!input.value) {
|
|
throw new Error(`Cannot find input id '${id.value}'`);
|
|
}
|
|
if (input.value.tagName !== "INPUT") {
|
|
throw new Error(`id '${id.value}' is not an input`);
|
|
}
|
|
if ((input.value as HTMLInputElement).type !== "password") {
|
|
throw new Error(`id '${id.value}' is not an input password`);
|
|
}
|
|
initTooltips();
|
|
});
|
|
|
|
// * METHODS
|
|
|
|
/** Set event on key down. */
|
|
function keydown(e: KeyboardEvent): void {
|
|
if (
|
|
e.key === " " ||
|
|
e.code === "Space" ||
|
|
e.keyCode === 32 ||
|
|
e.key === "Enter" ||
|
|
e.code === "Enter" ||
|
|
e.keyCode === 13
|
|
) {
|
|
toggleVisibility();
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
/** Update password status (visible, hidden). */
|
|
function toggleVisibility(): void {
|
|
input.value.type = (input.value.type === "password") ? "text" : "password";
|
|
visible.value = (input.value.type === "password") ? true : false;
|
|
}
|
|
|
|
/** Initialise all tooltips in the component. */
|
|
function initTooltips(): void {
|
|
setTimeout(() => {
|
|
tooltips.value = Tooltips.make({
|
|
type: "dom",
|
|
elements: passwordVisibility.value!.querySelectorAll("[data-bs-toggle=\"tooltip\"]")
|
|
});
|
|
}, 500);
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scopped>
|
|
.password-visibility {
|
|
border-top-right-radius: 0 !important;
|
|
}
|
|
.password-visibility .reveal {
|
|
width: 52px;
|
|
}
|
|
</style>
|