import {
onBeforeUnmount, onMounted, watch, type Ref, unref, ref,
} from 'vue';
type RefGuard<T> = T | Ref<T>;
interface UseSetPageTitleOptions {
restoreOnUnmount?: boolean;
enabled?: RefGuard<boolean>;
}
/**
* @description 페이지 타이틀 제어 유틸을 제공합니다.
* @param title 설정할 타이틀(문자열 또는 Ref)
* @param options 추가 옵션
* @param options.restoreOnUnmount 언마운트 시 이전 제목 복구 여부(기본값: true)
* @param options.enabled 사용 여부 (기본 값: true);
*/
export default function useSetDocumentTitle(
title: RefGuard<string> = import.meta.env.VITE_TITLE,
options: UseSetPageTitleOptions = {},
) {
const { restoreOnUnmount = true, enabled = true } = options;
const prevTitle = ref('');
/**
* @description enabled 옵션의 현재 활성화 상태를 반환합니다.
* @returns 활성화 여부
*/
const isEnabled = () => Boolean(unref(enabled));
/**
* @description 전달된 값으로 페이지 타이틀을 즉시 설정합니다.
* @param nextTitle 설정할 타이틀
*/
const setTitle = (nextTitle: string) => {
document.title = nextTitle || '';
};
/**
* @description 초기 입력(title)의 현재 값을 기준으로 페이지 타이틀을 적용합니다.
*/
const applyTitle = () => {
setTitle(unref(title) || '');
};
/**
* @description 페이지 진입 이전 타이틀로 복구합니다.
*/
const restoreTitle = () => {
document.title = prevTitle.value || '';
};
/**
* @description 타이틀을 빈 문자열로 초기화합니다.
*/
const clearTitle = () => {
document.title = '';
};
onMounted(() => {
prevTitle.value = document.title;
if (isEnabled()) {
applyTitle();
}
});
watch(() => unref(title), (nextTitle) => {
if (!isEnabled()) return;
setTitle(nextTitle || '');
});
watch(() => isEnabled(), (nextEnabled) => {
if (nextEnabled) {
applyTitle();
return;
}
if (restoreOnUnmount) {
restoreTitle();
}
});
onBeforeUnmount(() => {
if (restoreOnUnmount) {
restoreTitle();
}
});
return {
applyTitle,
setTitle,
restoreTitle,
clearTitle,
prevTitle,
};
}